AskSin++
Device.h
1 //- -----------------------------------------------------------------------------------------------------------------------
2 // AskSin++
3 // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
4 //- -----------------------------------------------------------------------------------------------------------------------
5 
6 #ifndef __DEVICE_H__
7 #define __DEVICE_H__
8 
9 #include "AskSinPP.h"
10 #include "Sign.h"
11 #include "HMID.h"
12 #include "Channel.h"
13 #include "ChannelList.h"
14 #include "Message.h"
15 #include "Radio.h"
16 #include "Led.h"
17 #include "Buzzer.h"
18 #include "Activity.h"
19 
20 #ifdef USE_HW_SERIAL
21  #if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega328PB__)
22  #include <avr/boot.h>
23  #elif defined (ARDUINO_ARCH_STM32F1)
24  #else
25  #error Using Hardware serial is not supported on MCU type currently used
26  #endif
27 #endif
28 
29 #if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
30 #define OTA_CONFIG_START 0xffe0 // start address of 16 byte config data in bootloader
31 #define OTA_MODEL_START 0xfff0 // start address of 2 byte model id in bootloader
32 #define OTA_SERIAL_START 0xfff2 // start address of 10 byte serial number in bootloader
33 #define OTA_HMID_START 0xfffc // start address of 3 byte device id in bootloader
34 #else
35 #define OTA_CONFIG_START 0x7fe0 // start address of 16 byte config data in bootloader
36 #define OTA_MODEL_START 0x7ff0 // start address of 2 byte model id in bootloader
37 #define OTA_SERIAL_START 0x7ff2 // start address of 10 byte serial number in bootloader
38 #define OTA_HMID_START 0x7ffc // start address of 3 byte device id in bootloader
39 #endif
40 
41 namespace as {
42 
43 class DeviceType {
44 public:
45 enum Types {
46  AlarmControl = 0x01,
47  Switch = 0x10,
48  OutputUnit = 0x12,
49  Dimmer = 0x20,
50  BlindActuator = 0x30,
51  ClimateControl = 0x39,
52  Remote = 0x40,
53  Sensor = 0x41,
54  Swi = 0x42,
55  PushButton = 0x43,
56  SingleButton = 0x44,
57  PowerMeter = 0x51,
58  Thermostat = 0x58,
59  KFM100 = 0x60,
60  THSensor = 0x70,
61  ThreeStateSensor = 0x80,
62  MotionDetector = 0x81,
63  KeyMatic = 0xC0,
64  WinMatic = 0xC1,
65  TipTronic = 0xC3,
66  SmokeDetector = 0xCD,
67 };
68 };
69 
70 struct DeviceInfo {
71  uint8_t DeviceID[3];
72  char Serial[11];
73  uint8_t DeviceModel[2];
74  uint8_t Firmware;
75  uint8_t DeviceType;
76  uint8_t DeviceInfo[2];
77 };
78 
79 template <class HalType,class List0Type=List0>
80 class Device {
81 
82 public:
83  typedef typename HalType::LedType LedType;
84  typedef typename HalType::BatteryType BatteryType;
85  typedef typename HalType::RadioType RadioType;
86  typedef typename HalType::BuzzerType BuzzerType;
87  typedef List0Type List0;
88 
89 private:
90  HalType* hal;
91  List0Type& list0;
92  uint8_t msgcount;
93 
94  HMID lastdev;
95  uint8_t lastmsg;
96 
97 #ifdef USE_HW_SERIAL
98  uint8_t device_id[3];
99 #endif
100 
101 protected:
102  Message msg;
103  KeyStore kstore;
104 
105  const DeviceInfo& info;
106  uint8_t numChannels;
107 
108 public:
109  Device (const DeviceInfo& i,uint16_t addr,List0Type& l,uint8_t ch) : hal(0), list0(l), msgcount(0), lastmsg(0), kstore(addr), info(i), numChannels(ch) {
110 #ifdef USE_HW_SERIAL
111  device_id[0]=0x00;
112 #endif
113  }
114  virtual ~Device () {}
115 
116  LedType& led () { return hal->led; }
117  BatteryType& battery () { return hal->battery; }
118  const BatteryType& battery () const { return hal->battery; }
119  RadioType& radio () { return hal->radio; }
120  BuzzerType& buzzer () { return hal->buzzer; }
121  KeyStore& keystore () { return this->kstore; }
122  Activity& activity () { return hal->activity; }
123 
124  Message& message () { return msg; }
125 
126  void channels (uint8_t num) {
127  numChannels = num;
128  }
129 
130  uint8_t channels () const {
131  return numChannels;
132  }
133 
134  bool hasChannel (uint8_t number) const {
135  return number != 0 && number <= channels();
136  }
137 
138 
139  bool isRepeat(const Message& m) {
140  if( m.isRepeated() && lastdev == m.from() && lastmsg == m.count() ) {
141  return true;
142  }
143  // store last message data
144  lastdev = m.from();
145  lastmsg = m.count();
146  return false;
147  }
148 
149  void setHal (HalType& h) {
150  hal = &h;
151  }
152 
153  HalType& getHal () {
154  return *hal;
155  }
156 
157  StorageConfig getConfigArea () {
158  return StorageConfig(kstore.address()-STORAGE_CFG_START);
159  }
160 
161  uint8_t getConfigByte (uint8_t offset) {
162  uint8_t data=0;
163 #ifdef USE_OTA_BOOTLOADER
164  if( offset < 16 ) {
165  HalType::pgm_read(&data,OTA_CONFIG_START+offset,1);
166  }
167 #elif defined(DEVICE_CONFIG)
168  uint8_t tmp[] = {DEVICE_CONFIG};
169  if( offset < sizeof(tmp) ) {
170  data = tmp[offset];
171  }
172 #endif
173  return data;
174  }
175 
176  void getDeviceID (HMID& id) {
177 #ifdef USE_OTA_BOOTLOADER
178  HalType::pgm_read((uint8_t*)&id,OTA_HMID_START,sizeof(id));
179 #elif defined(USE_HW_SERIAL)
180  if (device_id[0] == 0x00) {
181  #ifdef ARDUINO_ARCH_STM32F1
182  uint32_t crc = AskSinBase::crc24((uint8_t*)0x1FFFF7E8,12);
183  device_id[0] = (uint8_t)(crc & 0x000000ff);
184  device_id[1] = (uint8_t)(crc >> 8 & 0x000000ff);
185  device_id[2] = (uint8_t)(crc >> 16 & 0x000000ff);
186  #else
187  device_id[0] = boot_signature_byte_get(21);
188  device_id[1] = boot_signature_byte_get(22);
189  device_id[2] = boot_signature_byte_get(23);
190  #endif
191  }
192  id = HMID(device_id);
193 #else
194  uint8_t ids[3];
195  memcpy_P(ids,info.DeviceID,3);
196  id = HMID(ids);
197 #endif
198  }
199 
200  void getDeviceSerial (uint8_t* serial) {
201 #ifdef USE_OTA_BOOTLOADER
202  HalType::pgm_read((uint8_t*)serial,OTA_SERIAL_START,10);
203 #elif defined(USE_HW_SERIAL)
204  #ifdef ARDUINO_ARCH_STM32F1
205  memcpy_P(serial,info.Serial,4);
206  uint8_t* s = serial+4;
207  for( int i=0; i<3; ++i ) {
208  uint8_t d = device_id[i];
209  *s++ = AskSinBase::toChar(d >> 4);
210  *s++ = AskSinBase::toChar(d & 0x0f);
211  }
212  #else
213  for (uint8_t i = 0; i < 3; i++) {
214  serial[i] = (boot_signature_byte_get(i + 14) % 26) + 65; // Char A-Z
215  }
216  for (uint8_t i = 3; i < 10; i++) {
217  serial[i] = (boot_signature_byte_get(i + 14) % 10) + 48; // Char 0-9
218  }
219  #endif
220 #else
221  memcpy_P(serial,info.Serial,10);
222 #endif
223  }
224 
225  bool isDeviceSerial (const uint8_t* serial) {
226  uint8_t tmp[10];
227  getDeviceSerial(tmp);
228  return memcmp(serial,tmp,10) == 0;
229  }
230 
231  bool isDeviceID(const HMID& id) {
232  HMID me;
233  getDeviceID(me);
234  return id == me;
235  }
236 
237  void getDeviceModel (uint8_t* model) {
238 #ifdef USE_OTA_BOOTLOADER
239  HalType::pgm_read(model,OTA_MODEL_START,2);
240 #else
241  memcpy_P(model,info.DeviceModel,sizeof(info.DeviceModel));
242 #endif
243  }
244 
245  void getDeviceInfo (uint8_t* di) {
246  // first byte is number of channels
247 #ifdef DEVICE_CHANNEL_COUNT
248  *di = DEVICE_CHANNEL_COUNT;
249 #else
250  *di = this->channels();
251 #endif
252  memcpy_P(di+1,info.DeviceInfo,sizeof(info.DeviceInfo));
253  }
254 
255  HMID getMasterID () {
256  return list0.masterid();
257  }
258 
259  const List0Type& getList0 () {
260  return list0;
261  }
262 
263  bool pollRadio () {
264  uint8_t num = radio().read(msg);
265  // minimal msg is 10 byte
266  // ignore own messages from radio
267  if( num >= 10 && isDeviceID(msg.from()) == false ) {
268  return process(msg);
269  }
270  return false;
271  }
272 
273  uint8_t nextcount () {
274  return ++msgcount;
275  }
276 
277  virtual void configChanged () {}
278 
279  virtual bool process(__attribute__((unused)) Message& msg) { return false; }
280 
281  bool isBroadcastMsg(Message msg) {
282  return (msg.to() == HMID::broadcast && msg.isPairSerial()) || ( msg.isBroadcast() && (msg.isRemoteEvent() || msg.isSensorEvent()) );
283  }
284 
285  bool send(Message& msg,const HMID& to) {
286  msg.to(to);
287  getDeviceID(msg.from());
288  msg.setRpten(); // has to be set always
289  return send(msg);
290  }
291 
292  bool send(Message& msg) {
293  hal->prepareSend(msg);
294  bool result = false;
295  uint8_t maxsend = list0.transmitDevTryMax();
296  bool ledmode = list0.ledMode();
297  if( ledmode == 1 ) {
298  led().set(LedStates::send);
299  }
300  while( result == false && maxsend > 0 ) {
301  result = radio().write(msg,msg.burstRequired());
302  DPRINT(F("<- "));
303  msg.dump();
304  maxsend--;
305  if( result == true && msg.ackRequired() == true && msg.to().valid() == true ) {
306  Message response;
307  if( (result=waitResponse(msg,response,60)) ) { // 600ms
308  #ifdef USE_AES
309  if( response.isChallengeAes() == true ) {
310  AesChallengeMsg& cm = response.aesChallenge();
311  result = processChallenge(msg,cm.challenge(),cm.keyindex());
312  }
313  else
314  #endif
315  {
316  result = response.isAck();
317  // if we got a Nack - we stop trying to send again
318  if( response.isNack() ) {
319  maxsend = 0;
320  }
321  // we request wakeup
322  // we got the flag to stay awake
323  if( msg.isWakeMeUp() || response.isKeepAwake() ) {
324  activity().stayAwake(millis2ticks(500));
325  }
326  }
327  }
328  DPRINT(F("waitAck: ")); DHEX((uint8_t)result); DPRINTLN(F(""));
329  }
330  }
331  if( ledmode == 1 ) {
332  led().set( result == true ? LedStates::ack : LedStates::nack);
333  }
334  return result;
335  }
336 
337 
338  void sendAck (Message& msg,uint8_t flag=0x00) {
339  msg.ack().init(flag);
340  kstore.addAuth(msg);
341  send(msg,msg.from());
342  }
343 
344  void sendAck2 (Message& msg,uint8_t flag=0x00) {
345  msg.ack2().init(flag);
346  kstore.addAuth(msg);
347  send(msg,msg.from());
348  }
349 
350  void sendNack (Message& msg) {
351  msg.nack().init();
352  send(msg,msg.from());
353  }
354 
355  template <class ChannelType>
356  void sendAck (Message& msg,ChannelType& ch) {
357  msg.ackStatus().init(ch,radio().rssi());
358  ch.patchStatus(msg);
359  kstore.addAuth(msg);
360  send(msg,msg.from());
361  ch.changed(false);
362  }
363 
364  void sendDeviceInfo () {
365  sendDeviceInfo(getMasterID(),nextcount());
366  }
367 
368  void sendDeviceInfo (const HMID& to,uint8_t count) {
369  DeviceInfoMsg& pm = msg.deviceInfo();
370  pm.init(to,count);
371  pm.fill(pgm_read_byte(&info.Firmware),pgm_read_byte(&info.DeviceType));
372  getDeviceModel(pm.model());
373  getDeviceSerial(pm.serial());
374  getDeviceInfo(pm.info());
375  send(msg,to);
376  }
377 
378  void sendSerialInfo (const HMID& to,uint8_t count) {
379  SerialInfoMsg& pm = msg.serialInfo();
380  pm.init(to,count);
381  getDeviceSerial(pm.serial());
382  send(msg,to);
383  }
384 
385  template <class ChannelType>
386  void sendInfoActuatorStatus (const HMID& to,uint8_t count,ChannelType& ch,bool ack=true) {
387  InfoActuatorStatusMsg& pm = msg.infoActuatorStatus();
388  pm.init(count,ch,radio().rssi());
389  if( ack == false ) {
390  pm.clearAck();
391  }
392  ch.patchStatus(msg);
393  send(msg,to);
394  ch.changed(false);
395  }
396 
397  void sendInfoParamResponsePairs(HMID to,uint8_t count,const GenericList& list) {
398  InfoParamResponsePairsMsg& pm = msg.infoParamResponsePairs();
399  // setup message for maximal size
400  pm.init(count);
401  uint8_t current=0;
402  uint8_t* buf=pm.data();
403  for( int i=0; i<list.getSize(); ++i ) {
404  *buf++ = list.getRegister(i);
405  *buf++ = list.getByte(i);
406  current++;
407  if( current == 8 ) {
408  // reset to zero
409  current=0;
410  buf=pm.data();
411  if( send(msg,to) == false ) {
412  // exit loop in case of error
413  break;
414  }
415  }
416  }
417  *buf++ = 0;
418  *buf++ = 0;
419  current++;
420  pm.entries(current);
421  pm.clearAck();
422  send(msg,to);
423  }
424 
425  template <class ChannelType>
426  void sendInfoPeerList (HMID to,uint8_t count,const ChannelType& channel) {
427  InfoPeerListMsg& pm = msg.infoPeerList();
428  // setup message for maximal size
429  pm.init(count);
430  uint8_t current=0;
431  uint8_t* buf=pm.data();
432  for( uint8_t i=0; i<channel.peers(); ++i ) {
433  Peer p = channel.peer(i);
434  if( p.valid() == true ) {
435  memcpy(buf,&p,sizeof(Peer));
436  buf+=sizeof(Peer);
437  current++;
438  if( current == 4 ) {
439  // reset to zero
440  current=0;
441  buf=pm.data();
442  if( send(msg,to) == false ) {
443  // exit loop in case of error
444  break;
445  }
446  }
447  }
448  }
449  memset(buf,0,sizeof(Peer));
450  current++;
451  pm.entries(current);
452  pm.clearAck();
453  send(msg,to);
454  }
455 
456  void sendMasterEvent (Message& msg) {
457  send(msg,getMasterID());
458  hal->sendPeer();
459  }
460 
461  template <class ChannelType>
462  void sendPeerEvent (Message& msg,const ChannelType& ch) {
463  bool sendtopeer=false;
464  for( int i=0; i<ch.peers(); ++i ){
465  Peer p = ch.peer(i);
466  if( p.valid() == true ) {
467  // skip if this is not the first peer of that device
468  if( ch.peerfor(p) < i ) {
469  continue;
470  }
471  if( isDeviceID(p) == true ) {
472  // we send to ourself - no ack needed
473  getDeviceID(msg.from());
474  msg.to(msg.from());
475  if( msg.ackRequired() == true ) {
476  msg.clearAck();
477  this->process(msg);
478  msg.setAck();
479  }
480  else {
481  this->process(msg);
482  }
483  }
484  else {
485  // check if burst needed for peer
486  typename ChannelType::List4 l4 = ch.getList4(p);
487  msg.burstRequired( l4.burst() );
488  send(msg,p);
489  sendtopeer = true;
490  }
491  }
492  }
493  // if we have no peer - send to master/broadcast
494  if( sendtopeer == false ) {
495  send(msg,getMasterID());
496  }
497  // signal that we have send to peer
498  hal->sendPeer();
499  }
500 
501  template <class ChannelType>
502  void broadcastPeerEvent (Message& msg,const ChannelType& ch) {
503  getDeviceID(msg.from());
504  msg.clearAck();
505  // check if we are peered to ourself
506  if( ch.peerfor(msg.from()) < ch.peers() ) {
507  msg.to(msg.from());
508  // simply process
509  this->process(msg);
510  }
511  HMID todev;
512  bool burst=false;
513  // go over all peers, get first external device
514  // check if one of the peers needs a burst to wakeup
515  for( uint8_t i=0; i<ch.peers(); ++i ) {
516  Peer p = ch.peer(i);
517  if( p.valid() == true ) {
518  if( msg.from() != p ) {
519  if( todev.valid() == false ) {
520  todev = p;
521  }
522  typename ChannelType::List4 l4 = ch.getList4(p);
523  burst |= l4.burst();
524  }
525  }
526  }
527  // if we have no external device - send to master/broadcast
528  if( todev.valid() == false ) {
529  todev = getMasterID();
530  }
531  // DPRINT("BCAST to: ");todev.dump(); DPRINTLN("\n");
532  msg.burstRequired(burst);
533  msg.setBroadcast();
534  send(msg,todev);
535  // signal that we have send to peer
536  hal->sendPeer();
537  }
538 
539  template <class ChannelType>
540  void broadcastEvent (Message& msg,const ChannelType& ch) {
541  broadcastEvent(msg);
542  }
543 
544  void broadcastEvent (Message& msg) {
545  msg.clearAck();
546  msg.burstRequired(false);
547  msg.setBroadcast();
548  send(msg,HMID::broadcast);
549  hal->sendPeer();
550  }
551 
552  void writeList (const GenericList& list,const uint8_t* data,uint8_t length) {
553  for( uint8_t i=0; i<length; i+=2, data+=2 ) {
554  list.writeRegister(*data,*(data+1));
555  }
556  }
557 /*
558  bool waitForAck(Message& msg,uint8_t timeout) {
559  do {
560  if( radio().readAck(msg) == true ) {
561  return true;
562  }
563  _delay_ms(10); // wait 10ms
564  timeout--;
565  }
566  while( timeout > 0 );
567  return false;
568  }
569 */
570  bool waitResponse(const Message& msg,Message& response,uint8_t timeout) {
571  do {
572  uint8_t num = radio().read(response);
573  if( num > 0 ) {
574  DPRINT(F("-> ")); response.dump();
575  if( msg.count() == response.count() &&
576  msg.to() == response.from() ) {
577  return true;
578  }
579  }
580  _delay_ms(10); // wait 10ms
581  timeout--;
582  }
583  while( timeout > 0 );
584  return false;
585  }
586 
587 #ifdef USE_AES
588  void sendAckAes (Message& msg,const uint8_t* data) {
589  msg.ackAes().init(data);
590  send(msg,msg.from());
591  }
592 
593  bool requestSignature(const Message& msg) {
594  // no signature for internal message processing needed
595  if( isDeviceID(msg.from()) == true ) {
596  return true;
597  }
598  // signing only possible if sender requests ACK
599  if( msg.ackRequired() == true ) {
600  AesChallengeMsg signmsg;
601  signmsg.init(msg,kstore.getIndex());
602  kstore.challengeKey(signmsg.challenge(),kstore.getIndex());
603  // TODO re-send message handling
604  DPRINT(F("<- ")); signmsg.dump();
605  radio().write(signmsg,signmsg.burstRequired());
606  // read answer
607  if( waitForAesResponse(msg.from(),signmsg,60) == true ) {
608  AesResponseMsg& response = signmsg.aesResponse();
609  // DPRINT("AES ");DHEX(response.data(),16);
610  // fill initial vector with message to sign
611  kstore.fillInitVector(msg);
612  // DPRINT("IV ");DHEX(iv,16);
613  // decrypt response
614  uint8_t* data = response.data();
615  aes128_dec(data,&kstore.ctx);
616  // xor encrypted data with initial vector
617  kstore.applyVector(data);
618  // store data for sending ack
619  kstore.storeAuth(response.count(),data);
620  // decrypt response
621  aes128_dec(data,&kstore.ctx);
622  // DPRINT("r "); DHEX(response.data()+6,10);
623  // DPRINT("s "); DHEX(msg.buffer(),10);
624  // compare decrypted message with original message
625  if( memcmp(data+6,msg.buffer(),10) == 0 ) {
626  DPRINTLN(F("Signature OK"));
627  return true;
628  }
629  else {
630  DPRINTLN(F("Signature FAILED"));
631  }
632  }
633  else {
634  DPRINTLN(F("waitForAesResponse failed"));
635  }
636  }
637  return false;
638  }
639 
640  bool processChallenge(const Message& msg,const uint8_t* challenge,uint8_t keyidx) {
641  if( kstore.challengeKey(challenge,keyidx) == true ) {
642  DPRINT(F("Process Challenge - Key: "));DHEXLN(keyidx);
643  AesResponseMsg answer;
644  answer.init(msg);
645  // fill initial vector with message to sign
646  kstore.fillInitVector(msg);
647  uint8_t* data = answer.data();
648  for( uint8_t i=0; i<6; ++i ) {
649  data[i] = (uint8_t)rand();
650  }
651  memcpy(data+6,msg.buffer(),10); // TODO - check message to short possible
652  aes128_enc(data,&kstore.ctx);
653  kstore.applyVector(data);
654  aes128_enc(data,&kstore.ctx);
655  return send(answer,msg.to());
656  }
657  return false;
658  }
659 
660  bool waitForAesResponse(const HMID& from,Message& answer,uint8_t timeout) {
661  do {
662  uint8_t num = radio().read(answer);
663  if( num > 0 ) {
664  DPRINT(F("-> ")); answer.dump();
665  if( answer.isResponseAes() && from == answer.from() ) {
666  return true;
667  }
668  }
669  _delay_ms(10); // wait 10ms
670  timeout--;
671  }
672  while( timeout > 0 );
673  return false;
674  }
675 
676 #endif
677 };
678 
679 }
680 
681 #endif
as::Activity
Definition: Activity.h:148
as::InfoActuatorStatusMsg
Definition: Message.h:622
as::Message
Definition: Message.h:51
as::AskSinBase::toChar
static uint8_t toChar(uint8_t c)
Definition: AskSinPP.h:90
as::Peer
Definition: Peer.h:14
as::PushButton
Definition: PushButton.h:14
as::StorageConfig
Definition: Storage.h:464
as::SerialInfoMsg
Definition: Message.h:677
as::Device
Definition: Device.h:80
as::DeviceInfo
Definition: Device.h:70
as::InfoPeerListMsg
Definition: Message.h:643
as::DeviceType
Definition: Device.h:43
as::KeyStore
Definition: Sign.h:31
as::AesChallengeMsg
Definition: Message.h:582
as::GenericList
Definition: ChannelList.h:72
as::DeviceInfoMsg
Definition: Message.h:653
as::AskSinBase::crc24
static uint32_t crc24(const uint8_t *data, int len)
Definition: AskSinPP.h:113
as::AesResponseMsg
Definition: Message.h:604
as::Sensor
Definition: Sensors.h:11
as::InfoParamResponsePairsMsg
Definition: Message.h:633
as::HMID
Definition: HMID.h:14