AskSin++
RFID.h
1 //- -----------------------------------------------------------------------------------------------------------------------
2 // AskSin++
3 // 2018-05-03 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
4 // 2019-01-14 jp112sdl Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
5 //- -----------------------------------------------------------------------------------------------------------------------
6 
7 #ifndef __RFID_H__
8 #define __RFID_H__
9 
10 #include "MultiChannelDevice.h"
11 #include "Register.h"
12 
13 #ifdef USE_MFRC522_I2C
14 #include <Wire.h>
15 #include <MFRC522_I2C.h>
16 #endif
17 
18 #ifdef USE_WIEGAND
19 #include <Wiegand.h> // https://github.com/monkeyboard/Wiegand-Protocol-Library-for-Arduino
20 #endif
21 
22 #ifdef USE_MFRC522_SPI
23 #include <MFRC522.h>
24 #endif
25 
26 #ifdef USE_RDM6300
27 #include <SoftwareSerial.h>
28 #endif
29 
30 #define ID_ADDR_SIZE 8
31 
32 namespace as {
33 
34 DEFREGISTER(RFIDReg1,CREG_AES_ACTIVE,0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7)
35 class RFIDList1 : public RegList1<RFIDReg1> {
36 public:
37  RFIDList1 (uint16_t addr) : RegList1<RFIDReg1>(addr) {}
38  void defaults () {
39  clear();
40  }
41 };
42 
43 class ChipIdMsg : public Message {
44  public:
45 
46  bool free(uint8_t*addr) {
47  bool f = true;
48  for (uint8_t n = 0; n < ID_ADDR_SIZE; n++) {
49  if (addr[n] != 0x00) {
50  f = false;
51  break;
52  }
53  }
54  return f;
55  }
56 
57  void init(uint8_t msgcnt, uint8_t ch, uint8_t*addr) {
58  char hexstr[ID_ADDR_SIZE * 2];
59  if (free(addr)) {
60  for (uint8_t n = 0; n < (ID_ADDR_SIZE * 2); n++)
61  hexstr[n] = 0x20;
62  } else {
63  //convert address to hex-string - from https://stackoverflow.com/questions/6357031/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-in-c
64  unsigned char * pin = addr;
65  const char * hex = "0123456789ABCDEF";
66  char * pout = hexstr;
67  uint8_t i = 0;
68  for(; i < ID_ADDR_SIZE-1; ++i){
69  *pout++ = hex[(*pin>>4)&0xF];
70  *pout++ = hex[(*pin++)&0xF];
71  }
72  *pout++ = hex[(*pin>>4)&0xF];
73  *pout++ = hex[(*pin)&0xF];
74  *pout = 0;
75 
76  }
77  //DPRINT("hexstr=");DPRINTLN(hexstr);
78  Message::init(0x1a, msgcnt, AS_MESSAGE_SENSOR_DATA, BIDI , ch , hexstr[0]);
79  for (uint8_t i = 1; i < (ID_ADDR_SIZE * 2); i++) {
80  pload[i-1] = hexstr[i];
81  }
82  }
83 };
84 
85 template<class HALTYPE,int PEERCOUNT,class List0Type=List0>
86 class RFIDChannel : public Channel<HALTYPE,RFIDList1,EmptyList,DefList4,PEERCOUNT,List0Type>, Alarm {
87 // ChipIdMsg chipIdMsg;
88 
89  enum { none=0, released, longpressed, longreleased };
90 
91  uint8_t state, matches, repeatcnt;
92 
93 public:
95 
96  RFIDChannel () : BaseChannel(), Alarm(0), state(0), matches(0),repeatcnt(0) {}
97  virtual ~RFIDChannel () {}
98 
99  virtual void trigger (__attribute__((unused)) AlarmClock& clock) {
100  state = 0;
101  this->changed(true);
102  }
103 
104  uint8_t status () const {
105  return state;
106  }
107 
108  uint8_t flags () const {
109  return 0;
110  }
111 
112  void start () {
113  matches <<= 1;
114  }
115 
116  bool check (uint8_t* addr) {
117  if( free() == false && isID(addr) == true ) {
118  matches |= 0b00000001;
119  return true;
120  }
121  return false;
122  }
123 
124  void sendChipID() {
125  uint8_t buf[ID_ADDR_SIZE];
126  RFIDList1 l = this->getList1();
127  for( uint8_t n=0; n< ID_ADDR_SIZE; ++n ) {
128  buf[n] = l.readRegister(0xe0+n);
129  }
130  ChipIdMsg& chipIdMsg = (ChipIdMsg&)this->device().message();
131  chipIdMsg.init(this->device().nextcount(), this->number(), buf);
132  _delay_ms(400); //need some small delay for ccu for appropriate message processing
133  this->device().sendPeerEvent(chipIdMsg, *this);
134  }
135 
136  void finish () {
137  uint8_t s = none;
138  // 3 or 6 matches are longpress and longlongpress
139  if( (matches & 0b00111111) == 0b00000111 || (matches & 0b00111111) == 0b00111111 ) {
140  s = longpressed;
141  DPRINTLN(F("longpressed"));
142  this->device().buzzer().on();
143  // clear longlong
144  matches &= 0b11000111;
145  }
146  // check for long release
147  else if( (matches & 0b00001111) == 0b00001110 ) {
148  s = longreleased;
149  DPRINTLN(F("longreleased"));
150  this->device().buzzer().off();
151  }
152  // check for release
153  else if( (matches & 0b00000011) == 0b00000010 ) {
154  s = released;
155  DPRINTLN(F("released"));
156  this->device().buzzer().on(millis2ticks(100));
157  }
158  if( s != none ) {
159  RemoteEventMsg& msg = (RemoteEventMsg&)this->device().message();
160  msg.init(this->device().nextcount(),this->number(),repeatcnt,(s==longreleased || s==longpressed),this->device().battery().low());
161  if( s == released || s == longreleased) {
162  // send the message to every peer
163  this->device().sendPeerEvent(msg,*this);
164  repeatcnt++;
165  }
166  else if (s == longpressed) {
167  // broadcast the message
168  this->device().broadcastPeerEvent(msg,*this);
169  }
170  }
171  }
172 
173  bool match (uint8_t* addr) {
174  start();
175  bool res = check(addr);
176  finish();
177  return res;
178  }
179 
180  bool isID (uint8_t* buf) {
181  RFIDList1 l = this->getList1();
182  for( uint8_t n=0; n< ID_ADDR_SIZE; ++n ) {
183  if( l.readRegister(0xe0+n) != buf[n] ) {
184  return false;
185  }
186  }
187  return true;
188  }
189 
190  void storeID (uint8_t* buf) {
191  if( learn() == true ) {
192  for( uint8_t n=0; n < ID_ADDR_SIZE; ++n ) {
193  this->getList1().writeRegister(0xe0+n,buf[n]);
194  }
195  state = 0;
196  sendChipID();
197  this->changed(true);
198  sysclock.cancel(*this);
199  }
200  }
201 
202  bool free () {
203  return {
204  this->getList1().readRegister(0xe0) == 0x00 &&
205  this->getList1().readRegister(0xe1) == 0x00 &&
206  this->getList1().readRegister(0xe2) == 0x00 &&
207  this->getList1().readRegister(0xe3) == 0x00 &&
208  this->getList1().readRegister(0xe4) == 0x00 &&
209  this->getList1().readRegister(0xe5) == 0x00 &&
210  this->getList1().readRegister(0xe6) == 0x00 &&
211  this->getList1().readRegister(0xe7) == 0x00
212  };
213  }
214 
215  bool learn () const {
216  return state == 200;
217  }
218 
219  bool process (const ActionSetMsg& msg) {
220  state = msg.value();
221  this->changed(true);
222  if( state != 0 ) {
223  sysclock.cancel(*this);
224  set(seconds2ticks(60));
225  sysclock.add(*this);
226  }
227  return true;
228  }
229 
230  bool process (const ActionCommandMsg& msg) {
231  if ( (msg.len() == ID_ADDR_SIZE) || (msg.len() == 1 && msg.value(0) == 0xcc) ) {
232  for( uint8_t n=0; n < ID_ADDR_SIZE; ++n ) {
233  uint8_t val = msg.len() == 1 ? 0x00:msg.value(n);
234  this->getList1().writeRegister(0xe0+n,val);
235  }
236  state = 0;
237  this->device().getHal().buzzer.on(millis2ticks(300), millis2ticks(200),2);
238  sendChipID();
239  this->changed(true);
240  }
241 
242  if (msg.value(0) == 0xba) {
243  if (msg.len() == 3)
244  this->device().getHal().buzzer.on(decis2ticks(msg.value(1)),decis2ticks(msg.value(2)), -1);
245 
246  if (msg.len() == 4)
247  this->device().getHal().buzzer.on(decis2ticks(msg.value(1)),decis2ticks(msg.value(2)),msg.value(3));
248  }
249 
250  if (msg.len() == 1 && msg.value(0) == 0xb1) {
251  this->device().getHal().buzzer.on();
252  }
253 
254  if (msg.len() == 1 && msg.value(0) == 0xb0) {
255  this->device().getHal().buzzer.off(true);
256  }
257 
258  if (msg.len() == 1 && msg.value(0) == 0xfe) {
259  sendChipID();
260  }
261 
262  if (msg.len() == 2 && msg.value(0) == 0xff) {
263  this->device().getHal().standbyLedInvert(msg.value(1) == 0x01);
264  }
265 
266  return true;
267  }
268 
269  bool process (__attribute__((unused)) const RemoteEventMsg& msg) {return false; }
270  bool process (__attribute__((unused)) const SensorEventMsg& msg) {return false; }
271 };
272 
273 #ifdef USE_WIEGAND
274 template <class RFIDDev,class RFIDChannel,WIEGAND& rdrDev,int LED_GREEN,int LED_RED>
275 #endif
276 #if (defined(USE_MFRC522_I2C) || defined(USE_MFRC522_SPI))
277 template <class RFIDDev,class RFIDChannel,MFRC522& rdrDev,int LED_GREEN,int LED_RED>
278 #endif
279 #ifdef USE_RDM6300
280 template <class RFIDDev,class RFIDChannel,SoftwareSerial& rdrDev,int LED_GREEN,int LED_RED>
281 #endif
282 
283 
284 class RFIDScanner : public Alarm {
285  RFIDDev& dev;
287  uint8_t cnt;
288 public:
289  RFIDScanner (RFIDDev& d) : Alarm(millis2ticks(500)), dev(d), cnt(0) {
290  led.init();
291  }
292  virtual ~RFIDScanner () {}
293 
294  RFIDChannel* learning () {
295  for( uint8_t i=0; i<dev.rfidCount(); ++i ) {
296  RFIDChannel& rc = dev.rfidChannel(i);
297  if( rc.learn() == true ) {
298  return &rc;
299  }
300  }
301  return 0;
302  }
303 
304  RFIDChannel* matches (uint8_t* addr) {
305  for( uint8_t i=0; i<dev.rfidCount(); ++i ) {
306  RFIDChannel& rc = dev.rfidChannel(i);
307  if( rc.match(addr) == true ) {
308  return &rc;
309  }
310  }
311  return 0;
312  }
313 
314  RFIDChannel* find (uint8_t* addr) {
315  for( uint8_t i=0; i<dev.rfidCount(); ++i ) {
316  RFIDChannel& rc = dev.rfidChannel(i);
317  if( rc.isID(addr) == true ) {
318  return &rc;
319  }
320  }
321  return 0;
322  }
323 
324  void DADDR(uint8_t * addr) {
325  for (uint8_t i = 0; i < ID_ADDR_SIZE; i++)
326  DHEX(addr[i]);
327  DPRINTLN(F(""));
328  }
329 
330  void start () {
331  for( uint8_t i=0; i<dev.rfidCount(); ++i ) {
332  RFIDChannel& rc = dev.rfidChannel(i);
333  rc.start();
334  }
335  }
336 
337  void finish () {
338  for( uint8_t i=0; i<dev.rfidCount(); ++i ) {
339  RFIDChannel& rc = dev.rfidChannel(i);
340  rc.finish();
341  }
342  }
343 
344  bool check (uint8_t* addr) {
345  bool res = false;
346  for( uint8_t i=0; i<dev.rfidCount(); ++i ) {
347  RFIDChannel& rc = dev.rfidChannel(i);
348  res |= rc.check(addr);
349  }
350  return res;
351  }
352 
353  bool getRfidAddress(uint8_t *addr) {
354 #ifdef USE_WIEGAND
355  if (rdrDev.available()) {
356  memset(addr,0x00, ID_ADDR_SIZE);
357  unsigned long wgAddr = rdrDev.getCode();
358  byte addrArr[8];
359  for (uint8_t i = 0; i < ID_ADDR_SIZE; i++)
360  addrArr[i] = wgAddr >> (i*8) & 0xff;
361  memcpy(addr, addrArr, ID_ADDR_SIZE);
362 
363  //DADDR(addr);
364  return true;
365  }
366  return false;
367 #endif
368 
369 #if (defined(USE_MFRC522_I2C) || defined(USE_MFRC522_SPI))
370  if (!rdrDev.PICC_IsNewCardPresent())
371  if (!rdrDev.PICC_IsNewCardPresent())
372  return false;
373  if (!rdrDev.PICC_ReadCardSerial()) return false;
374  memset(addr,0x00,ID_ADDR_SIZE);
375  memcpy(addr,rdrDev.uid.uidByte,rdrDev.uid.size);
376 
377  //DADDR(addr);
378  return true;
379 #endif
380 
381 #ifdef USE_RDM6300
382  while (rdrDev.available() > 0) {
383  char d = rdrDev.read();
384  static uint8_t bytecount = 0;
385  static uint8_t addrval = 0;
386  static bool decode = false;
387  switch (d) {
388  case 0x02:
389  bytecount = 0;
390  memset(addr,0x00,ID_ADDR_SIZE);
391  decode = true;
392  break;
393  case 0x03:
394  decode = false;
395  while (rdrDev.available()) rdrDev.read(); //empty rx buffer
396  return true;
397  break;
398  default:
399  if (decode == true) {
400  uint8_t val = (d > 57) ? d -= 55 : d -= 48;
401  if (bytecount % 2 == 0) {
402  addrval = val << 4;
403  } else {
404  addrval |= val;
405  addr[bytecount/2] = addrval;
406  //DPRINT("[");DDEC(bytecount/2);DPRINT("]=");DHEXLN(addrval);
407  addrval = 0;
408  }
409  bytecount++;
410  }
411  break;
412  }
413  }
414  return false;
415 #endif
416  }
417 
418  bool readRfid(uint8_t *addr) {
419  uint8_t iD[ID_ADDR_SIZE];
420  static uint8_t last_addr[ID_ADDR_SIZE];
421 
422  bool success = false;
423 
424  memset(addr,0,ID_ADDR_SIZE);
425  if (getRfidAddress(iD)) {
426  memcpy(addr,iD,ID_ADDR_SIZE);
427  if (memcmp(addr, last_addr, ID_ADDR_SIZE) != 0) {
428  dev.buzzer().on(millis2ticks(100));
429  }
430  success = true;
431  }
432  memcpy(last_addr,addr,ID_ADDR_SIZE);
433 
434  return success;
435  }
436 
437  void scan () {
438  uint8_t addr[ID_ADDR_SIZE];
439 
440  start();
441  bool readID = readRfid(addr);
442 
443  if( check(addr) == true ) {
444  led.ledOn(millis2ticks(500),0);
445  } else {
446  if (readID == true )
447  dev.buzzer().on(millis2ticks(40),millis2ticks(40),3);
448  }
449  finish();
450  }
451 
452  bool learn (RFIDChannel* lc) {
453  uint8_t addr[ID_ADDR_SIZE];
454  while( readRfid(addr) == true ) {
455  if( find(addr) == 0 ) {
456  lc->storeID(addr);
457  dev.buzzer().on(millis2ticks(40), millis2ticks(50),10);
458  return true;
459  }
460  }
461  return false;
462  }
463 
464  void trigger (AlarmClock& clock) {
465  // reactivate
466  set(millis2ticks(500));
467  clock.add(*this);
468  ++cnt;
469  // check if we have a learning channel
470  RFIDChannel* lc = learning();
471  if( lc != 0 ) {
472  uint8_t cycle = cnt & 0x01;
473  led.ledOn(cycle == 0 ? tick : 0, cycle == 0 ? 0 : tick);
474  dev.buzzer().on(millis2ticks(40));
475  // if we have learned a new ID
476  if( learn(lc) == true ) {
477  clock.cancel(*this);
478  set(seconds2ticks(5));
479  led.ledOff();
480  led.ledOn(tick);
481  clock.add(*this);
482  }
483  }
484  else {
485  // scan the bus now
486  scan();
487  }
488  }
489 };
490 
491 }
492 
493 #endif
as::Alarm
Definition: Alarm.h:15
as::RFIDScanner
Definition: RFID.h:284
as::Channel
Definition: Channel.h:21
as::ActionSetMsg
Definition: Message.h:505
as::Message
Definition: Message.h:51
as::AlarmClock
Definition: AlarmClock.h:32
as::ChipIdMsg
Definition: RFID.h:43
as::RemoteEventMsg
Definition: Message.h:463
as::SensorEventMsg
Definition: Message.h:480
as::ActionCommandMsg
Definition: Message.h:528
as::DualStatusLed< LED_GREEN, LED_RED >
as::RFIDChannel
Definition: RFID.h:86