FHEM Forum

Verschiedenes => Bastelecke => MySensors => Thema gestartet von: Ranseyer am 11 Februar 2018, 18:28:31

Titel: NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 11 Februar 2018, 18:28:31
Hi,

der folgende Sketch läuft gerade auf einem Arduino Nano. Der hängt am RS485 Bus und verfügt über einen NFS-Reader. PDF-Doku (https://dangerousthings.com/wp-content/uploads/PN532_Manual_V3-1.pdf).

...
// Enable debug prints to serial monitor
#define MY_DEBUG

#define MY_NODE_ID 22
// Enable and select radio type attached
//#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
// Enable RS485 transport layer
#define MY_RS485
#define MY_TRANSPORT_WAIT_READY_MS 1000

// Define this to enables DE-pin management on defined pin
#define MY_RS485_DE_PIN 2

// Set RS485 baud rate to use
#define MY_RS485_BAUD_RATE 38400

// Enable this if RS485 is connected to a hardware serial port
// Not possible with Arduino Nano !!
//#define MY_RS485_HWSERIAL Serial


#include <SPI.h>
#include <MySensors.h> 
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>


// Add your valid rfid keys here. To find you your key just run sketch; hold your new RFID tag in fron ot the reader;
// and copy the key from serial output of this sketch.
const uint8_t maxKeyLength = 7;
uint8_t validKeys[][maxKeyLength] = {
                    { 0xB3, 0xC6, 0xD9, 0x80, 0x00, 0x00, 0x00 },
                    { 0, 0, 0, 0, 0, 0, 0 },    // ADD YOUR KEYS HERE!
                    { 0, 0, 0, 0, 0, 0, 0 }};
int keyCount = sizeof validKeys / maxKeyLength;


#define CHILD_ID 99   // Id of the sensor child

// Pin definition
const int lockPin = 4;         // (Digital 4) The pin that activates the relay/solenoid lock.
bool lockStatus;
MyMessage lockMsg(CHILD_ID, V_LOCK_STATUS);
PN532_I2C pn532i2c(Wire);
PN532 nfc(pn532i2c);

void setup() {
 
  pinMode(lockPin, OUTPUT);

  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Couldn't find PN53x board");
    while (1); // halt
  }
  Serial.print("Found NFC chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  Serial.print('.'); Serial.println((versiondata>> & 0xFF, DEC);
  // Set the max number of retry attempts to read from a card
  // This prevents us from waiting forever for a card, which is
  // the default behaviour of the PN532.
  nfc.setPassiveActivationRetries(0x3);
 
  // configure board to read RFID tags
  nfc.SAMConfig();

  lockStatus = loadState(0);    // Read last lock status from eeprom
  setLockState(lockStatus, true); // Now set the last known state and send it to controller
}

void presentation()  {
  sendSketchInfo("RFID Lock", "1.0");
  present(CHILD_ID, S_LOCK);
}

void loop() {
  bool success;
  uint8_t key[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  uint8_t currentKeyLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)

 
  // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
  // 'uid' will be populated with the UID, and uidLength will indicate
  // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &key[0], &currentKeyLength);
 
  if (success) {
    Serial.print("Found tag id: ");
    for (uint8_t i=0; i < currentKeyLength; i++)
    {
      if (i>0) Serial.print(",");
      Serial.print("0x");Serial.print(key[i], HEX);
    }
    for (uint8_t i=currentKeyLength; i < maxKeyLength; i++)
    {
      Serial.print(",0x00");
    }


    Serial.println("");

    bool valid = false;
    // Compare this key to the valid once registered here in sketch
    for (int i=0;i<keyCount && !valid;i++) {
      for (int j=0;j<currentKeyLength && !valid;j++) {
        if (key[j] != validKeys[i][j]) {
          break;
        }
        if (j==currentKeyLength-1) {
          valid = true;
        }
      }
    }
    if (valid) {
      // Switch lock status
      setLockState(!lockStatus, true);       
    }
   
    // Wait for card/tag to leave reader   
    while(nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &key[0], &currentKeyLength));
  }
}



// Unlocks the door.
void setLockState(bool state, bool doSend){
  if (state)
     Serial.println("open lock");
  else
     Serial.println("close lock");
  if (doSend)
    send(lockMsg.set(state));
  digitalWrite(lockPin, state);
  saveState(0,state);
  lockStatus = state;
}

void receive(const MyMessage &message) {
  // We only expect one type of message from controller. But we better check anyway.
  if (message.type==V_LOCK_STATUS) {
     // Change relay state
     setLockState(message.getBool(), false);
 
     // Write some debug info
     Serial.print("Incoming lock status:");
     Serial.println(message.getBool());
   }
}


Auf der Debug-Konsole bekomme ich dann solche Meldungen:
(leicht verfremdet)
ZitatFound tag id: 0x4,0x15,0x99,0x49,0xDD,0xDD,0x81
Found tag id: 0x65,0xDD,0xDD,0x6B,0x00,0x00,0x00



Ziel ist
A) Der Sketch sollte einen Pin ansteuern können. Das zu Nutzen mach aber bestenfalls Sinn wenn der Arduino gut geschützt ist...
B) Ich möchte einen Event im FHEM erhalten und die ID des Tags sehen. Daraufhin will ich dann FHEM entscheiden lassen was zu tun ist.


Hintergrund: Die Steuersignale für Garagentore ((Türöffner) usw. will ich keinesfalls außen an Gebäuden erreichbar haben.


Was mir helfen würde wäre eine Idee wie man das am besten coded. Noch besser ein Codeschnipsel, gerne auch ungetestet!
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: localhosthack0r am 14 Februar 2018, 15:45:41
Hi,
nicht getestet, aber als Gedankenanstoß:

Vielleicht kann man die ID als String, per V_TEXT S_INFO an FHEM schicken, siehe:

MySensors API
https://www.mysensors.org/download/serial_api_20
und
https://forum.fhem.de/index.php/topic,75374.0.html
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 16 Februar 2018, 20:09:53
Danke, ich fürchte das ist die falsche Richtung. V_Text denke ist um ein Display anzusteuern. (Oder geht das dann in beide Richtungen?)

Ich wäre eher gewesen bei:
ZitatV_IR_RECEIVE   33   This message contains a received IR-command   S_IR

Im Moment brauche ich erst noch einen String mit der ID des RFID Tags. Denke das bekomme ich hier vor Ort hin. Würde mich dann nochmals melden wegen einem Tipp um das zu übertragen und einen Event im FHEM zu erzeugen...

Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 17 Februar 2018, 15:17:21
Der Sketch zeigt schon mal die ID in der Debug-Konsole:

/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*******************************
*
* REVISION HISTORY
* Version 1.0 - Henrik Ekblad
*
* DESCRIPTION
* RFID Lock sensor/actuator
*
* Use RFID tag to lock/unlock a door or trigger a scene on your controller.
* This example sketch allows you to add an optional relay or solenoid
* which can be activated/opened by RFID or controller. 
*
* Use the I2C wiring option for your RFID module and connect to the following Arduino pins.
*
* RFID       Arduino
* -----      -------
* GND   ->   GND
* VCC   ->   +5V
* SCL   ->   A5
* SDA   ->   A4
*
* Use normal wiring for NRF24L01 radio
*
* Attach a optional relay or solonoid lock to pin 4
* http://www.mysensors.org/build/rfid
*/

// Enable debug prints to serial monitor
#define MY_DEBUG
#define MY_TRANSPORT_WAIT_READY_MS 1000

#define MY_NODE_ID 22
// Enable and select radio type attached
//#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
// Enable RS485 transport layer
#define MY_RS485


// Define this to enables DE-pin management on defined pin
#define MY_RS485_DE_PIN 2

// Set RS485 baud rate to use
#define MY_RS485_BAUD_RATE 38400

// Enable this if RS485 is connected to a hardware serial port
// Not possible with Arduino Nano !!
//#define MY_RS485_HWSERIAL Serial

#define RF_INIT_DELAY   125



#include <SPI.h>
#include <MySensors.h> 
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>





// Add your valid rfid keys here. To find you your key just run sketch; hold your new RFID tag in fron ot the reader;
// and copy the key from serial output of this sketch.
const uint8_t maxKeyLength = 7;
uint8_t validKeys[][maxKeyLength] = {
                    { 0xB3, 0xC6, 0xD9, 0x80, 0x00, 0x00, 0x00 },
                    { 0, 0, 0, 0, 0, 0, 0 },    // ADD YOUR KEYS HERE!
                    { 0, 0, 0, 0, 0, 0, 0 }};
int keyCount = sizeof validKeys / maxKeyLength;
String tagid = String();


#define CHILD_ID_LOCK  1   // Id of the sensor child
#define CHILD_ID_WRONG 2   // Id of the sensor child
#define CHILD_ID_ALARM 3   // Id of the sensor child
#define CHILD_ID_TAGID 4   // Id of the sensor child
//#define CHILD_ID 99   // Id of the sensor child

// Pin definition
const int lockPin = 4;         // (Digital 4) The pin that activates the relay/solenoid lock.
bool lockStatus;
MyMessage  lockMsg(CHILD_ID_LOCK, V_LOCK_STATUS);
MyMessage  armMsg(CHILD_ID_WRONG, V_ARMED);
MyMessage  wrongMsg(CHILD_ID_ALARM, V_TRIPPED);
MyMessage  tagMsg(CHILD_ID_TAGID,  V_IR_RECEIVE);
//xxx


PN532_I2C pn532i2c(Wire);
PN532 nfc(pn532i2c);

void setup() {

  pinMode(lockPin, OUTPUT);

  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Couldn't find PN53x board");
    while (1); // halt
  }
  Serial.print("Found NFC chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  // Set the max number of retry attempts to read from a card
  // This prevents us from waiting forever for a card, which is
  // the default behaviour of the PN532.
  nfc.setPassiveActivationRetries(0x3);

  // configure board to read RFID tags
  nfc.SAMConfig();

  lockStatus = loadState(0);    // Read last lock status from eeprom
  setLockState(lockStatus, true); // Now set the last known state and send it to controller
}

void presentation()  {
  sendSketchInfo("RFID Lock", "0.0.2");
  present(CHILD_ID_LOCK, S_LOCK);      delay(RF_INIT_DELAY);
  present(CHILD_ID_WRONG, S_DOOR);   delay(RF_INIT_DELAY);
  present(CHILD_ID_ALARM, S_MOTION);   delay(RF_INIT_DELAY);
  present(CHILD_ID_TAGID, S_IR);     delay(RF_INIT_DELAY);
}




void loop() {
  bool success;
  uint8_t key[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  uint8_t currentKeyLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)

  // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
  // 'uid' will be populated with the UID, and uidLength will indicate
  // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &key[0], &currentKeyLength);
//  Serial.print(key, BYTE);
//    Serial.println(uid);


 
  if (success) {
    tagid+=("Found tag id: ");
    for (uint8_t i=0; i < currentKeyLength; i++)
    {
      if (i>0) tagid+=(",");
      tagid+=("0x");tagid+=(key[i]);
    }
    for (uint8_t i=currentKeyLength; i < maxKeyLength; i++)
    {
      tagid+=(",0x00");
    }

//    Serial.println("Start");
    Serial.println(tagid);
//    Serial.println("Ende");
      bool tripped = 1;
      Serial.println(tripped);
      send(wrongMsg.set(tripped?"1":"0"));  // Send tripped value to gw
      send(tagMsg.set(tagid));  // Send id of the rfid-tag  to gw
      //V_IR_RECEIVE  33  This message contains a received IR-command S_IR
//MyMessage  lockMsg(CHILD_ID_LOCK, V_LOCK_STATUS);
//MyMessage  armMsg(CHILD_ID_WRONG, V_ARMED);
//MyMessage  wrongMsg(CHILD_ID_ALARM, V_TRIPPED);
//MyMessage  tagMsg(CHILD_TAGID, V_TRIPPED);




    Serial.println("");

    bool valid = false;
    // Compare this key to the valid once registered here in sketch
    for (int i=0;i<keyCount && !valid;i++) {
      for (int j=0;j<currentKeyLength && !valid;j++) {
        if (key[j] != validKeys[i][j]) {
          break;
        }
        if (j==currentKeyLength-1) {
          valid = true;
        }
      }
    }
    if (valid) {
      // Switch lock status
      setLockState(!lockStatus, true);       
    }

    // Wait for card/tag to leave reader   
    while(nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &key[0], &currentKeyLength));
  }
}



// Unlocks the door.
void setLockState(bool state, bool doSend){
  if (state)
     Serial.println("open lock");
  else
     Serial.println("close lock");
  if (doSend)
    send(lockMsg.set(state));
  digitalWrite(lockPin, state);
  saveState(0,state);
  lockStatus = state;
}

void receive(const MyMessage &message) {
  // We only expect one type of message from controller. But we better check anyway.
  if (message.type==V_LOCK_STATUS) {
     // Change relay state
     setLockState(message.getBool(), false);

     // Write some debug info
     Serial.print("Incoming lock status:");
     Serial.println(message.getBool());
   }
}


18608 TSF:MSG:SEND,22-22-0-0,s=4,c=1,t=33,pt=1,l=1,sg=0,ft=0,st=OK:1

Found tag id: 0x222,0x2222,0x37,0x59,0x00,0x00,0x00Found tag id: 0x2222,0x22,0x37,0x59,0x00,0x00,0x00
1
20432 TSF:MSG:SEND,22-22-0-0,s=3,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=OK:1
20444 TSF:MSG:SEND,22-22-0-0,s=4,c=1,t=33,pt=1,l=1,sg=0,ft=0,st=OK:1



Nun muss ich noch die Übertragung zu FHEM hinbekommen...
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: tiwo85 am 18 Februar 2018, 09:23:49
Ich habe mal bei einem Sensor mit V_var1 Etc. rumexperementiert. Das ist bei jedem Device verfügbar und du kannst das auch in FHEM als Reading registrieren.

Gesendet von meinem Huawei P10 Plus mit Tapatalk

Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: KarlHeinz2000 am 20 Februar 2018, 22:36:04
An der Stelle, wo die debug Ausgabe rauskommt, die ID nicht (nur) seriell ausgeben, sondern parallel in ein char[] kopieren.
Das char[] kannst du dann ganz normal als payload senden, egal mit welcher Variable (V_TEXT, V_VAR, V_ID,...). Ich würde wohl V_ID nehmen. Payloadgrenze von max 26(?) Bytes am Stück beachten (mit NRF24).
Wenn du eine andere Variable nutzt als von MYSENSORS vorgeschlagen, geht halt das autocreate nicht und du musst das in FHEM entsprechen per Hand anlegen (mapreading...).
Vermutlich brauchst du vor dem Senden auch noch eine Konvertierung nach HEX, sonst ist die ID dezimal.
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 02 März 2018, 09:53:22
Das mit den IR-typischen Variablen sollte schon klappen. V_ID würde ich (im Moment noch nicht) nehmen, das erfordert die Prästentation eines Temp-Sensors, dass das mit autocreate klappt.

Habe mal etwas an dem Sketch rumgebastelt, habe aber keinen solchen Leser (irgendwo liegt noch ein mrf522 rum, der auf seinen Einsatz wartet...) und kann daher nicht selbst testen:

/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*******************************
*
* REVISION HISTORY
* Version 1.0 - Henrik Ekblad
*
* DESCRIPTION
* RFID Lock sensor/actuator
*
* Use RFID tag to lock/unlock a door or trigger a scene on your controller.
* This example sketch allows you to add an optional relay or solenoid
* which can be activated/opened by RFID or controller.
*
* Use the I2C wiring option for your RFID module and connect to the following Arduino pins.
*
* RFID       Arduino
* -----      -------
* GND   ->   GND
* VCC   ->   +5V
* SCL   ->   A5
* SDA   ->   A4
*
* Use normal wiring for NRF24L01 radio
*
* Attach a optional relay or solonoid lock to pin 4
* http://www.mysensors.org/build/rfid
*/

// Enable debug prints to serial monitor
#define MY_DEBUG
#define MY_DEBUG_LOCAL
#define MY_TRANSPORT_WAIT_READY_MS 1000

#define MY_NODE_ID 22
// Enable and select radio type attached
//#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
// Enable RS485 transport layer
#define MY_RS485


// Define this to enables DE-pin management on defined pin
#define MY_RS485_DE_PIN 2

// Set RS485 baud rate to use
#define MY_RS485_BAUD_RATE 38400

// Enable this if RS485 is connected to a hardware serial port
// Not possible with Arduino Nano !!
//#define MY_RS485_HWSERIAL Serial

#define RF_INIT_DELAY   125



#include <SPI.h>
#include <MySensors.h>
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>





// Add your valid rfid keys here. To find you your key just run sketch; hold your new RFID tag in fron ot the reader;
// and copy the key from serial output of this sketch.
const uint8_t maxKeyLength = 7;
uint8_t validKeys[][maxKeyLength] = {
                    { 0xB3, 0xC6, 0xD9, 0x80, 0x00, 0x00, 0x00 },
                    { 0, 0, 0, 0, 0, 0, 0 },    // ADD YOUR KEYS HERE!
                    { 0, 0, 0, 0, 0, 0, 0 }};
int keyCount = sizeof validKeys / maxKeyLength;
String tagid = String();


#define CHILD_ID_LOCK  1   // Id of the sensor child
#define CHILD_ID_WRONG 2   // Id of the sensor child
#define CHILD_ID_ALARM 3   // Id of the sensor child
#define CHILD_ID_TAGID 4   // Id of the sensor child
//#define CHILD_ID 99   // Id of the sensor child

// Pin definition
const int lockPin = 4;         // (Digital 4) The pin that activates the relay/solenoid lock.
bool lockStatus;
MyMessage  lockMsg(CHILD_ID_LOCK, V_LOCK_STATUS);
MyMessage  armMsg(CHILD_ID_WRONG, V_ARMED);
MyMessage  wrongMsg(CHILD_ID_ALARM, V_TRIPPED);
MyMessage  tagMsg(CHILD_ID_TAGID,  V_IR_RECEIVE);
//xxx


PN532_I2C pn532i2c(Wire);
PN532 nfc(pn532i2c);

void setup() {

  pinMode(lockPin, OUTPUT);

  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Couldn't find PN53x board");
    while (1); // halt
  }
  Serial.print(F("Found NFC chip PN5")); Serial.println((versiondata>>24) & 0xFF, HEX);
  Serial.print(F("Firmware ver. ")); Serial.print((versiondata>>16) & 0xFF, DEC);
  Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  // Set the max number of retry attempts to read from a card
  // This prevents us from waiting forever for a card, which is
  // the default behaviour of the PN532.
  nfc.setPassiveActivationRetries(0x3);

  // configure board to read RFID tags
  nfc.SAMConfig();

  lockStatus = loadState(0);    // Read last lock status from eeprom
  setLockState(lockStatus, true); // Now set the last known state and send it to controller
}

void presentation()  {
  sendSketchInfo("RFID Lock", "0.0.2");
  present(CHILD_ID_LOCK, S_LOCK);      delay(RF_INIT_DELAY);
  present(CHILD_ID_WRONG, S_DOOR);   delay(RF_INIT_DELAY);
  present(CHILD_ID_ALARM, S_MOTION);   delay(RF_INIT_DELAY);
  present(CHILD_ID_TAGID, S_IR);     delay(RF_INIT_DELAY);
}

void loop() {
  bool success;
  uint8_t key[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  uint8_t currentKeyLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)

  /* Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
    'uid' will be populated with the UID, and uidLength will indicate
    if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)*/
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &key[0], &currentKeyLength);

  if (success) {
#ifdef MY_DEBUG_LOCAL
    Serial.println(key, BYTE);
    Serial.println(uid);
#endif
    char buffer[24];
    sprintf(buffer, "0x%07lX", key);
    send(tagMsg.set(buffer));
/*tagid=(""); //Start with an empty string!
    for (uint8_t i=0; i < currentKeyLength; i++)
    {
      if (i>0) tagid+=(",");
      tagid+=("0x");tagid+=(key[i]);
    }
    for (uint8_t i=currentKeyLength; i < maxKeyLength; i++)
    {
      tagid+=(",0x00");
    }

//    Serial.println("Start");
    Serial.println(tagid);
//    Serial.println("Ende");*/

    bool tripped = 1;
#ifdef MY_DEBUG_LOCAL
    Serial.println(tripped);
#endif
    send(wrongMsg.set(tripped?"1":"0"));  // Send tripped value to gw
    //send(tagMsg.set(tagid));  // Send id of the rfid-tag  to gw
    //V_IR_RECEIVE  33  This message contains a received IR-command S_IR
    //MyMessage  lockMsg(CHILD_ID_LOCK, V_LOCK_STATUS);
    //MyMessage  armMsg(CHILD_ID_WRONG, V_ARMED);
    //MyMessage  wrongMsg(CHILD_ID_ALARM, V_TRIPPED);
    //MyMessage  tagMsg(CHILD_TAGID, V_TRIPPED);

#ifdef MY_DEBUG_LOCAL
    Serial.println("");
#endif

    bool valid = false;
    // Compare this key to the valid once registered here in sketch
    for (int i=0;i<keyCount && !valid;i++) {
      for (int j=0;j<currentKeyLength && !valid;j++) {
        if (key[j] != validKeys[i][j]) {
          break;
        }
        if (j==currentKeyLength-1) {
          valid = true;
        }
      }
    }
    if (valid) {
      // Switch lock status
      setLockState(!lockStatus, true);       
    }

    // Wait for card/tag to leave reader   
    while(nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &key[0], &currentKeyLength));
  }
}

// Unlocks the door.
void setLockState(bool state, bool doSend){
#ifdef MY_DEBUG_LOCAL 
  if (state)
    Serial.println("open lock");
  else
    Serial.println("close lock");
#endif
  if (doSend)
    send(lockMsg.set(state));
    digitalWrite(lockPin, state);
    saveState(0,state);
    lockStatus = state;
}

void receive(const MyMessage &message) {
  // We only expect one type of message from controller. But we better check anyway.
  if (message.type==V_LOCK_STATUS) {
     // Change relay state
     setLockState(message.getBool(), false);

     // Write some debug info
     Serial.print("Incoming lock status:");
     Serial.println(message.getBool());
   }
}


Da jedenfalls ich den Leser mittelfristig mit RS485@HW-serial betreiben wollte, habe ich mal angefangen, sämtliche seriellen Ausgaben abschaltbar zu machen ;) . Übrigens schlucken so lange Texte viel Speicher, ergo ist das Motto: solange aussagefähig, ist kürzer besser, und am besten aus dem EEPROM geladen (F("))...

Als Merkposten noch:
- https://forum.mysensors.org/topic/2439/rfid-garage-door-opener (Schön strukturiert, leider noch V1.5, mit der Option, zulässige IDs zu programmieren)
- https://forum.mysensors.org/topic/2223/rfid-2-person-readout (auch V1.5, interessant: die dump_byte_array-Funktion)

Gruß, Beta-User
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 03 März 2018, 10:09:22
Danke an alle für den Input.

Ich hab nochmals ganz von vorne angefangen beim Original Muster von MySensors.
Und schrittweise die Sachen übernommen.

Der Stand Ausgabe auf der Debug-Konsole:
ZitatFound tag id: 0x65,0x61,0xA9,0x6B,0x00,0x00,0x00
Start
0x101,0x97,0x169,0x107,0x00,0x00,0x00
Ende
19716 TSF:MSG:SEND,22-22-0-0,s=4,c=1,t=33,pt=0,l=10,sg=0,ft=0,st=OK:0x783008EA
1
19728 TSF:MSG:SEND,22-22-0-0,s=3,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=OK:1


Der EventMonitor:
Zitat2018-03-03 10:00:31 MYSENSORS_DEVICE MYSENSOR_22 ir_receive4: 0x783008EA
2018-03-03 10:00:31 MYSENSORS_DEVICE MYSENSOR_22 tripped3: on


Der Code: https://github.com/ranseyer/home-automatics/blob/master/MySens-RS485-Lock-201802/MySens-RS485-Lock-201802.ino

Was mir unklar ist:

Was genau tut das (ja das ist bestimmte eine dumme Frage!)
    char buffer[24];
    sprintf(buffer, "0x%07lX", key);
    send(tagMsg.set(buffer));

Problem dabei: "key enthält nicht den ganzen Key.


Dieser wäre dezimal in tagid enthalten (wobei mir dezimal auch nicht gefällt):
tagid=(""); //Start with an empty string!
    for (uint8_t i=0; i < currentKeyLength; i++)
    {
      if (i>0) tagid+=(",");
      tagid+=("0x");tagid+=(key[i]);
    }
    for (uint8_t i=currentKeyLength; i < maxKeyLength; i++)
    {
      tagid+=(",0x00");
    }

    Serial.println("Start");
    Serial.println(tagid);
    Serial.println("Ende");

    char buffer[24];
    sprintf(buffer, "0x%07lX", key);
    send(tagMsg.set(buffer));
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 03 März 2018, 13:16:07
Zu was tut das:
Es wird erst eine Variable des Typs char definiert mit max. 24 Zeichen Länge. In diese werden dann aus der Variable "key" die ersten 7 Bytes als großgeschriebener HEX-Wert geschoben, wobei der String mit "0x" anfängt.

Eigentlich sollte in key aber wirklich der ganze Key enthalten sein, auch die Ausgangsfunktion aus dem MySensors-Sketch bedient sich ja daraus.

Wirf da mal das 0x raus und verlängere das, einfach die 7 ersetzen durch irgendwas, was weniger wie 24 ist...
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 03 März 2018, 13:39:58
Cool, viel besser (Test mit zwei Tags...):

    char buffer[24];
    sprintf(buffer, "%23lX", key);
    send(tagMsg.set(buffer));



246=F6 das verstehe ich.

Events:
2018-03-03 13:28:54 MYSENSORS_DEVICE MYSENSOR_22 ir_receive4:                303108EA
2018-03-03 13:28:54 MYSENSORS_DEVICE MYSENSOR_22 tripped3: on
2018-03-03 13:28:57 MYSENSORS_DEVICE MYSENSOR_22 ir_receive4:                393508EA
2018-03-03 13:28:57 MYSENSORS_DEVICE MYSENSOR_22 tripped3: on


Debug:

Found tag id: 0x65,0x61,0xA9,0x6B,0x00,0x00,0x00
Start
0x101,0x97,0x169,0x107,0x00,0x00,0x00
Ende
24931 TSF:MSG:SEND,22-22-0-0,s=4,c=1,t=33,pt=0,l=23,sg=0,ft=0,st=OK:               303108EA
1
24944 TSF:MSG:SEND,22-22-0-0,s=3,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=OK:1

Found tag id: 0xF6,0xEA,0x25,0x3B,0x00,0x00,0x00
Start
0x246,0x234,0x37,0x59,0x00,0x00,0x00
Ende
27575 TSF:MSG:SEND,22-22-0-0,s=4,c=1,t=33,pt=0,l=23,sg=0,ft=0,st=OK:               393508EA
1




(Ich werde die Zahlen später mal etwas editieren...)
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 03 März 2018, 18:21:58
Cool!

Irritierend ist nur, dass die beiden Ausgaben nicht im wesentlichen identisch ist, aber vermutlich habe ich da eine falsche Vorstellung von der HEX-Umrechnerei.

Jetzt müßte man also entscheiden, ob man lieber bei der "alten" Methode bleibt (in Hex-Schreibweise, damit es immer 2 Stellen sind), oder ob wir das buffer-char-array verwenden wollen. Ich würde doch eher zu letzterem tendieren, zumal ich nicht weiß, ob das Ergebnis der "neuen" Methode ebenso eindeutig ist wie das alte, sonst könnte man das komplett umstellen.

Aber wenn wir in der alten Vorgehensweise die Kommas und 0x-e drin lassen, wird das zu lang zum Versenden, dafür kann man den Vergleichscode lassen, wie er ist. Ich würde also jetzt das rausnehmen (aus den "=+"-Anweisungen).

Andere Meinungen?
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 03 März 2018, 18:34:01
Denke die HEX Schreibweise macht am meisten Sinn. (Aber im Prinzip geht es ja nur darum einen eindeutigen Wert zu haben. Egal welchen.)
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 03 März 2018, 18:45:53
Schon, die Frage ist nur, welche:
Found tag id: 0x65,0x61,0xA9,0x6B,0x00,0x00,0x00
oder
303108EA
Tendiere eingentlich dazu, dass 6561A96B000000 die beste Variante wäre... Sind 14 Zeichen, was im Rahmen des übertagbaren liegt und man kann den Vergleich lassen, wie er ist ;) .
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 03 März 2018, 18:56:06
Denke das ist auch die TagID: 0x65,0x61,0xA9,0x6B,0x00,0x00,0x00.

Denke ich würde es so machen:
  if (success) {
    Serial.print("Found tag id: ");
    for (uint8_t i=0; i < currentKeyLength; i++)
    {
      if (i>0) Serial.print(key[i], HEX);
    }
    for (uint8_t i=currentKeyLength; i < maxKeyLength; i++)
    {
      Serial.print("00");
    }
    Serial.println("");


das ergibt dann
ZitatFound tag id: EA253B000000
Start
0x246,0x234,0x37,0x59,0x00,0x00,0x00
Ende
4940 TSF:MSG:SEND,22-22-0-0,s=4,c=1,t=33,pt=0,l=23,sg=0,ft=0,st=OK:               393508EA
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 03 März 2018, 19:14:13
Bei Serial.print darf gerne eine "korrekte" Darstellung rauskommen, das sollte dann ja auch in die Liste der gültigen ID's so aufgenommen werden.

Aber der Sende-String/char* muß kürzer sein.

Hmmm. Kannst du mal etwas mit dem spritf rumspielen und das Ergebnis auch an Serial ausgeben? Insbesondere: Was ergibt:
sprintf(buffer, "%X", key);?

Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 03 März 2018, 19:48:17
Das ergibt:
ZitatFound tag id: EA253B000000
Start
0x246,0x234,0x37,0x59,0x00,0x00,0x00
Ende


Das sind 4 Hexzahlen + das Auffüllen mit dreimal Hex "00" ...

Aber was mir gerade so auffällt: Eine Hex-Zahl wird verschluckt.
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 03 März 2018, 19:58:11
Hmmm, vielleicht so? Aber dann ist die Länge nicht mehr dynamisch...

sprintf(buffer, "%X%X%X%X%X%X%X", key[0],key[1],key[2],key[3],key[4],key[5],key[6]);
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 03 März 2018, 20:42:22
Evtl. wäre das eine Variante:

char buffer[currentKeyLength*2];
sprintf(buffer, "%hhX", key);
Serial.print(buffer);
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 03 März 2018, 21:00:35
Bei mir kann es leider erst morgen weitergehen. Im Moment bin ich bei:

Zitat2855 MCO:PIM:NODE REG=1
Found tag id: EA253B000000
Start
0x246,0x234,0x37,0x59,0x00,0x00,0x00
Ende
Buffer
8E21
5041 TSF:MSG:SEND,22-22-0-0,s=3,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=OK:1

ZitatSerial.println("Buffer");
char buffer[currentKeyLength*2];
sprintf(buffer, "%hhX", key);
Serial.print(buffer);
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 03 März 2018, 22:39:24
Hmm, warum fehlt da immer der erste Wert?

Mag er key[0] nur, wenn man es ausdrücklich sagt?

Dann wäre
sprintf(buffer, "%X%X", key[0], key);vielleicht eine Option?

Vorsichtshalber auch mit etwas längerem Array?

char buffer[currentKeyLength*2+3];

Interessante Sache jedenfalls. Vielleicht sollte ich doch mal einen Minimal-Aufbau machen...

Schönen Sonntag jedenfalls
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 04 März 2018, 08:07:11
Ist der Grund, warum das erste Element des key-Arrays nicht ausgegeben wird vielleicht der, dass dieser länger ist als die anderen?
Dann könnte vielleicht das funktionieren:

sprintf(buffer, "%llX%X", key[0], key);

Insgesamt wäre es aber wohl besser, wieder zu der zusammensetzenden Form zurückzukehren. Sonst ist irgendwie zu unklar, wie lange das geht bzw. wo das Grenzen hat. Eigentlich sollte folgendes klappen, allerdings wohl in Kleinschreibung, aber was soll's:
tagid=(""); //Start with an empty string!
    for (uint8_t i=0; i < currentKeyLength; i++)
    {
      tagid+=(String(key[i], HEX));
    }
    for (uint8_t i=currentKeyLength; i < maxKeyLength; i++)
    {
      tagid+=("00");
    }

Das mit der String-Funktion ist aus dem https://forum.mysensors.org/topic/2223/rfid-2-person-readout geklaut, da ist auch eine Vergleichsfunktion drin. Wenn du sowas brauchst, solltest du die allerdings noch in eine Array-Form umbauen.

Müßte eigentlich so gehen:
Im Header:
String ok_rfid[]={  "abcdefg",
                    "hijklmn"};

In der Prüfung eine for (i bis int n = sizeof(ok_rfid) / sizeof(ok_rfid[0]), in der dann geprüft wird, ob tagid==ok_rfid;

Wenn wir das fertig und funktional haben, sollten wir den Sketch dann (mit nRF24) bei MySensors einchecken...

Gruß, Beta-User
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 04 März 2018, 10:39:39
Die Funktion ist fast perfekt. Nutzen würde ich das ganze "Betamäßig".
Veröffentlichen sollten wir das so noch nicht:
-Die ID wird ja doppelt ermittelt. Ohne "key" bekomme ich das derzeit nicht hin
-Denke die originale ermittlung des Keys war falsch, unsere ist richtig (die billigen Mifare-Karten haben 4 Bytes und nicht drei)
-Denke meinen Code kann man niemandem zeigen...


PS: Ich würde für mich selbst noch erweitern (Ob sowas  in ein Muster gehört ist dann die zweite Frage)
-Wenn beliebiger Tag erkannt, oder ein IO angesteuert wird einen Output-Pin defaultmäßig 3 Minuten aktivieren (für Licht, Camera, ...)
-Klingeltaste (Wenn ein IO angesteuert wird  "tripped ausspucken)
Denke das bekomm ich hin...
PPS: Meine HW ist instabil. (Denke der Spannungsregler vom Arduino Nano ist zu schwach, Teilweise wird der FTDI-Chip nicht am Rechner erkannt, oder der Reader vom Arduino)



    Serial.print("Original tag id: ");
    for (uint8_t i=0; i < currentKeyLength; i++)
    {
      if (i>0) Serial.print(key[i], HEX);
    }
    for (uint8_t i=currentKeyLength; i < maxKeyLength; i++)
    {
      Serial.print("00");
    }
    Serial.println("");


    tagid=(""); //Start with an empty string!
    for (uint8_t i=0; i < currentKeyLength; i++)
    {
      tagid+=(String(key[i], HEX));
    }
    for (uint8_t i=currentKeyLength; i < maxKeyLength; i++)
    {
      tagid+=("00");
    }
   
    bool tripped = 1;
    #ifdef MY_DEBUG_LOCAL
     Serial.println(tripped);
    #endif

    send(wrongMsg.set(tripped?"1":"0"));  // Send tripped value to gw

    char buffer[24];
    sprintf(buffer, "%23lX", key);
    send(tagMsg.set(buffer));  // Send id of the rfid-tag  to gw
   
    Serial.print("New tag id: "); Serial.print(tagid); Serial.println("");


Debug:
ZitatOriginal tag id: 61A96B000000
1
66662 TSF:MSG:SEND,22-22-0-0,s=3,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=OK:1
66678 TSF:MSG:SEND,22-22-0-0,s=4,c=1,t=33,pt=0,l=23,sg=0,ft=0,st=OK:               623608E3
New tag id: 6561a96b000000

Zitat2018-03-04 10:22:08 MYSENSORS_DEVICE MYSENSOR_22 tripped3: on
2018-03-04 10:22:08 MYSENSORS_DEVICE MYSENSOR_22 ir_receive4:                623608E3
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 04 März 2018, 11:22:17
Du kannst m.E. einfach die ersten 10 Zeilen weglassen (das ist der Teil, der die erste Ausgabe veranlasst). Einfach mit /* beginnen und dann */ ans Ende...

Ist der Sketch auf github?
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Ranseyer am 04 März 2018, 11:28:37
Nee, das was in FHEM ankommt, ist der inhalt von "key". Der wird von der originalen Routine angezeigt. Ich habe jetzt spontan auch nicht geschafft die "tagid" genauso umzuwandeln...

sprintf(buffer, "%23lX", key);
    send(tagMsg.set(buffer));  //

ZitatDenke die originale ermittlung des Keys war falsch
Das  ist Quatsch. Nur die Anzeige war verkürzt...

Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 04 März 2018, 11:32:24
Versende einfach die tagid ;) . Nicht mehr das mit sprintf...
Titel: Antw:NFC: Event erzeugen und Tag-ID übertragen wenn ein Tag erkannt wird...
Beitrag von: Beta-User am 17 Juni 2018, 16:40:43
So, jetzt habe ich den RC522 auch mal testweise in Betrieb genommen. Mit dem folgenden Code bekomme ich die ID's verschickt, Rest ist nicht getestet:

EDIT: Ist eine MCP2551-AltSoftSerial-Version; bitte bei Bedarf den DE-Pin zuschalten ;)
/*   --------------------------------------------------------------------------------------------------------------------
   Example sketch/program showing An Arduino Door Access Control featuring RFID, EEPROM, Relay
   --------------------------------------------------------------------------------------------------------------------
   This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid

   This example showing a complete Door Access Control System

  Simple Work Flow (not limited to) :
                                     +---------+
  +----------------------------------->READ TAGS+^------------------------------------------+
  |                              +--------------------+                                     |
  |                              |                    |                                     |
  |                              |                    |                                     |
  |                         +----v-----+        +-----v----+                                |
  |                         |MASTER TAG|        |OTHER TAGS|                                |
  |                         +--+-------+        ++-------------+                            |
  |                            |                 |             |                            |
  |                            |                 |             |                            |
  |                      +-----v---+        +----v----+   +----v------+                     |
  |         +------------+READ TAGS+---+    |KNOWN TAG|   |UNKNOWN TAG|                     |
  |         |            +-+-------+   |    +-----------+ +------------------+              |
  |         |              |           |                |                    |              |
  |    +----v-----+   +----v----+   +--v--------+     +-v----------+  +------v----+         |
  |    |MASTER TAG|   |KNOWN TAG|   |UNKNOWN TAG|     |GRANT ACCESS|  |DENY ACCESS|         |
  |    +----------+   +---+-----+   +-----+-----+     +-----+------+  +-----+-----+         |
  |                       |               |                 |               |               |
  |       +----+     +----v------+     +--v---+             |               +--------------->
  +-------+EXIT|     |DELETE FROM|     |ADD TO|             |                               |
        +----+     |  EEPROM   |     |EEPROM|             |                               |
                   +-----------+     +------+             +-------------------------------+


   Use a Master Card which is act as Programmer then you can able to choose card holders who will granted access or not

* **Easy User Interface**

   Just one RFID tag needed whether Delete or Add Tags. You can choose to use Leds for output or Serial LCD module to inform users.

* **Stores Information on EEPROM**

   Information stored on non volatile Arduino's EEPROM memory to preserve Users' tag and Master Card. No Information lost
   if power lost. EEPROM has unlimited Read cycle but roughly 100,000 limited Write cycle.

* **Security**
   To keep it simple we are going to use Tag's Unique IDs. It's simple and not hacker proof.

   @license Released into the public domain.

   Typical pin layout used:
   -----------------------------------------------------------------------------------------
               MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
               Reader/PCD   Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro
   Signal      Pin          Pin           Pin       Pin        Pin              Pin
   -----------------------------------------------------------------------------------------
   RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
   SPI SS      SDA(SS)      10            53        D10        10               10
   SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
   SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
   SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
*/

#define SN "RFID Reader"
#define SV "0.1"

#include <EEPROM.h>     // We are going to read and write PICC's UIDs from/to EEPROM
#include <SPI.h>        // RC522 Module uses SPI protocol
#include <MFRC522.h>  // Library for Mifare RC522 Devices
#include <Bounce2.h>

#define MY_DEBUG
//#define MY_DEBUG_LOCAL
// Enable RS485 transport layer
#define MY_RS485
//#define MY_RS485_HWSERIAL Serial
//#define MY_SPLASH_SCREEN_DISABLED

// Define this to enables DE-pin management on defined pin
//#define MY_RS485_DE_PIN 2
// Set RS485 baud rate to use
#define MY_RS485_BAUD_RATE 19200 //57600 //38400 //9600
//#define MY_RS485_SOH_COUNT 3

#define MY_NODE_ID 94
#define MY_TRANSPORT_WAIT_READY_MS 20000
#include <Arduino.h>

#include <MySensors.h>

//für die millis()-Berechnung, wann wieder gesendet werden soll
unsigned long SEND_FREQUENCY = 180000; // Sleep time between reads (in milliseconds)
unsigned long lastSend = 0;

#define RF_INIT_DELAY   125
#define ONE_SEC         1000
#define MAX_CARDS       18
#define PROG_WAIT       10
#define HEARTBEAT       10

/*Pin definitions*/
#define LED_PIN         A3
#define GARAGEPIN       4
#define SWITCH_PIN      5
#define RST_PIN    7   //  MFRC
#define SS_PIN    10   //  MFRC

MFRC522      mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
MFRC522::Uid olduid;
MFRC522::Uid masterkey = { 10, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  0 };

byte       countValidCards  = 0;
MFRC522::Uid validCards[MAX_CARDS];

void       ShowCardData(MFRC522::Uid* uid);
bool       sameUid(MFRC522::Uid* old, MFRC522::Uid* check);
void       copyUid(MFRC522::Uid* src, MFRC522::Uid* dest);
bool       isValidCard(MFRC522::Uid* uid);
int        releasecnt = 0;

#define    CHILD_ID_ALARM    1
#define    CHILD_ID_LOCK     2
#define CHILD_ID_TAGID 4 // Id of the sensor child

//volatile String tagid = String();

Bounce     debouncer = Bounce();

int        oldSwitchValue = -1;
int        switchValue = 0;
long       timer = -1;
bool       programmode = false;
bool       ledon;
int        programTimer = 0;
bool       armed = true;
unsigned long lastTime = 0;

MyMessage  lockMsg(CHILD_ID_LOCK,          V_LOCK_STATUS);
MyMessage  lockArmMsg(CHILD_ID_ALARM,      V_ARMED);
MyMessage  wrongMsg(CHILD_ID_ALARM,        V_TRIPPED);
MyMessage tagMsg(CHILD_ID_TAGID, V_IR_RECEIVE);

void before()
{
  pinMode(GARAGEPIN, OUTPUT);     // Initialise in/output ports

  // Make sure MFRC will be disabled on the SPI bus
  pinMode(RST_PIN, OUTPUT);
  digitalWrite(RST_PIN, LOW);
  pinMode(SS_PIN, OUTPUT);
  digitalWrite(SS_PIN, LOW);

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  // Setup the button
  pinMode(SWITCH_PIN, INPUT);
  // Activate internal pull-up
  digitalWrite(SWITCH_PIN, HIGH);

  // After setting up the button, setup debouncer
  debouncer.attach(SWITCH_PIN);
  debouncer.interval(5);
}

void presentation() {

  sendSketchInfo(SN, SV);
  present(CHILD_ID_LOCK, S_LOCK);      delay(RF_INIT_DELAY);
  present(CHILD_ID_ALARM, S_MOTION);   delay(RF_INIT_DELAY);
  present(CHILD_ID_TAGID, S_IR);
  recallEeprom();

  // Init MFRC RFID sensor
  SPI.begin();      // Init SPI bus
  mfrc522.PCD_Init();   // Init MFRC522
  ShowReaderDetails();          // Show details of PCD - MFRC522 Card Reader details

  send(lockArmMsg.set(armed));
  Serial.println(F("Init done..."));

}

void setup() {

}

void loop()
{
  timer++;
  debouncer.update();

  // Get the update value
  int switchValue = debouncer.read();
  if (switchValue != oldSwitchValue) {
    // Send in the new value
    Serial.print (F("Switch "));
    Serial.println (switchValue);

    if (switchValue && programmode) {
      lastTime     = millis() / 1000;
    }

    if (!switchValue && programmode && lastTime > 0) {
      if ( (millis() / 1000) - lastTime > 3) {
        Serial.println(F("Reset all cards"));
        countValidCards  = 0;
        blinkFast(50);
      } else {
        Serial.println(F("Program off"));
        digitalWrite(LED_PIN, LOW);
        programmode = false;

        storeEeprom();
      }
    }

    if (!switchValue)   {
      programTimer = 0;
    }
    oldSwitchValue = switchValue;
  }

  if (programmode && ((timer % (ONE_SEC / HEARTBEAT)) == 0 ))  {
    ledon = !ledon;
    digitalWrite(LED_PIN, ledon);
    programTimer++;

    // Stop program mode after 20 sec inactivity
    if (programTimer > PROG_WAIT)  {
      programmode = false;
      digitalWrite(LED_PIN, false);
      Serial.println(F("Program expired"));
    }
  }

  if ((timer % (200 / HEARTBEAT)) == 0 )   {
    // Look for new cards
    if ( ! mfrc522.PICC_IsNewCardPresent()) {
      if (releasecnt > 0)   {
        releasecnt--;
        if (!releasecnt)  {
          olduid.size = 0;
          Serial.println(F("release"));
        }
      }
      return;
    }
    releasecnt = 5;

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial()) {
      return;
    }

    // Dump debug info about the card; PICC_HaltA() is automatically called
    //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));

    getTagId(&(mfrc522.uid));
       
    if (!olduid.size || !sameUid(&(mfrc522.uid), &olduid))  {
      ShowCardData(&(mfrc522.uid));
      copyUid(&(mfrc522.uid), &olduid);
      if ( isValidCard(&olduid) )   {
        OpenDoor(programmode);
      } else  {

        if (sameUid(&(mfrc522.uid), &masterkey)) {
          // Only switch in program mode when mastercard is found AND the program button is pressed
          if (switchValue)  {
            Serial.println(F("Program mode"));
            programmode = true;
            programTimer = 0;
            lastTime     = 0;
          }
        } else {
          if (programmode) {
            Serial.println(F("new card"));
            programTimer = 0;

            if (countValidCards < MAX_CARDS)
            {
              // Add card to list...
              copyUid(&(mfrc522.uid), &validCards[countValidCards]);
              countValidCards++;
              blinkFast(15);
            }
          } else {
            Serial.println(F("Invalid card"));
            if (armed) {
              send(wrongMsg.set(1));
              delay(2000);
              send(wrongMsg.set(0));
              //send(tagMsg.set(tagid)); // Send id of the rfid-tag  to gw
            }
          }
        }
      }
    }
  }
}

void ShowCardData(MFRC522::Uid* uid) {
  Serial.print(F("Card UID:"));
  for (byte i = 0; i < uid->size; i++) {
    if (uid->uidByte[i] < 0x10) {
      Serial.print(F(" 0"));
    } else {
      Serial.print(F(" "));
    }
    Serial.print(uid->uidByte[i], HEX);
  }
  Serial.println();
}

void getTagId(MFRC522::Uid* uid) {
   String tagid=("");
   for (byte i = 0; i < uid->size; i++) {
    if (uid->uidByte[i] < 0x10) {
      if (i>0) tagid+=(",");
    } else {
      tagid+=(" ");
    }
    tagid+=("0x");
    tagid+=(String(uid->uidByte[i], HEX));
  }
  Serial.print("tagid: ");
  Serial.println(tagid);
  char TAGID[tagid.length() + 1];
  tagid.toCharArray(TAGID, tagid.length() + 1);
 
  send(tagMsg.set(TAGID)); // Send id of the rfid-tag  to gw
}

void copyUid(MFRC522::Uid* src, MFRC522::Uid* dest)
{
  dest->size = src->size;
  dest->sak  = src->sak;

  for (byte i = 0; i < src->size; i++) {
    dest->uidByte[i] = src->uidByte[i];
  }
}

bool sameUid(MFRC522::Uid* old, MFRC522::Uid* check)
{
  if (old->size != check->size) {
    return false;
  }
  for (byte i = 0; i < old->size; i++) {
    if (old->uidByte[i] != check->uidByte[i]) {
      return false;
    }
  }
  return true;
}

bool isValidCard(MFRC522::Uid* uid)
{
  for (byte i = 0; i < countValidCards; i++)  {
    if (validCards[i].size != uid->size)  {
      break;
    }
    for (int j = 0; j < uid->size; j++) {
      if (validCards[i].uidByte[j] != uid->uidByte[j])  {
        break;
      }
      if (j == (uid->size - 1)) {
        return true;
      }
    }
  }
  return false;
}


void storeEeprom()
{
  byte address = 0;
  saveState(address++, countValidCards);

  for (byte i = 0; i < countValidCards; i++) {
    saveState(address++, validCards[i].size);
    for (byte j = 0; j < 10; j++) {
      saveState(address++, validCards[i].uidByte[j]);
    }
  }
}

void recallEeprom()
{
  byte address = 0;

  countValidCards = loadState(address++);
  if (countValidCards > MAX_CARDS) {
    Serial.println(F("Not a valid EEPROM reading set to default"));
    countValidCards = 0;
    storeEeprom();
    return;
  }

  for (byte i = 0; i < countValidCards; i++)  {
    validCards[i].size = loadState(address++);
    for (byte j = 0; j < 10; j++)  {
      validCards[i].uidByte[j] = loadState(address++);
    }
  }

}

void blinkFast(int times)
{
  for (int i = 0; i < times; i++) {
    ledon = !ledon;
    digitalWrite(LED_PIN, ledon);
    delay(100);
  }
}

void OpenDoor(bool fakeOpen)
{
  Serial.println(F("Open door!"));
  send(lockMsg.set(false));

  if (!fakeOpen) {
    digitalWrite(LED_PIN, HIGH);
    digitalWrite(GARAGEPIN, HIGH);
  }
  delay(1000);

  if (!fakeOpen) {
    digitalWrite(GARAGEPIN, LOW);
    digitalWrite(LED_PIN, LOW);
  }

  send(lockMsg.set(true));
}

void ShowReaderDetails() {
  // Get the MFRC522 software version
  byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
  Serial.print(F("MFRC522 Software Version: 0x"));
  Serial.print(v, HEX);
  if (v == 0x91) {
    Serial.print(F(" = v1.0"));
  } else if (v == 0x92) {
    Serial.print(F(" = v2.0"));
  } else {
    Serial.print(F(" (unknown)"));
  }
  Serial.println("");

  // When 0x00 or 0xFF is returned, communication probably failed
  if ((v == 0x00) || (v == 0xFF)) {
    Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?"));
  }
}


void incomingMessage(const MyMessage &message)
{
  if (message.type == V_LOCK_STATUS) {
    // Change relay state
    if (!message.getBool())  {
      OpenDoor(false);
    }

    // Write some debug info
    Serial.print(F("Lock status: "));
    Serial.println(message.getBool());
  }
  else
  {
    if (message.type == V_ARMED)  {
      // Change relay state
      armed = message.getBool();

      // Write some debug info
      Serial.print(F("Arm status: "));
      Serial.println(message.getBool());
    }
    else
    {
      // Write some debug info
      Serial.print(F("Incoming msg type: "));
      Serial.print(message.type);
      Serial.print(F(" id: "));
      Serial.print(message.sensor);
      Serial.print(F(" content: "));
      Serial.println(message.getInt());
    }
  }
}