13 #include "ChannelList.h"
21 #if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega328PB__)
23 #elif defined (ARDUINO_ARCH_STM32F1)
25 #error Using Hardware serial is not supported on MCU type currently used
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
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
51 ClimateControl = 0x39,
61 ThreeStateSensor = 0x80,
62 MotionDetector = 0x81,
73 uint8_t DeviceModel[2];
79 template <
class HalType,
class List0Type=List0>
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;
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) {
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; }
124 Message& message () {
return msg; }
126 void channels (uint8_t num) {
130 uint8_t channels ()
const {
134 bool hasChannel (uint8_t number)
const {
135 return number != 0 && number <= channels();
139 bool isRepeat(
const Message& m) {
140 if( m.isRepeated() && lastdev == m.from() && lastmsg == m.count() ) {
149 void setHal (HalType& h) {
161 uint8_t getConfigByte (uint8_t offset) {
163 #ifdef USE_OTA_BOOTLOADER
165 HalType::pgm_read(&data,OTA_CONFIG_START+offset,1);
167 #elif defined(DEVICE_CONFIG)
168 uint8_t tmp[] = {DEVICE_CONFIG};
169 if( offset <
sizeof(tmp) ) {
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
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);
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);
192 id =
HMID(device_id);
195 memcpy_P(ids,info.DeviceID,3);
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];
213 for (uint8_t i = 0; i < 3; i++) {
214 serial[i] = (boot_signature_byte_get(i + 14) % 26) + 65;
216 for (uint8_t i = 3; i < 10; i++) {
217 serial[i] = (boot_signature_byte_get(i + 14) % 10) + 48;
221 memcpy_P(serial,info.Serial,10);
225 bool isDeviceSerial (
const uint8_t* serial) {
227 getDeviceSerial(tmp);
228 return memcmp(serial,tmp,10) == 0;
231 bool isDeviceID(
const HMID&
id) {
237 void getDeviceModel (uint8_t* model) {
238 #ifdef USE_OTA_BOOTLOADER
239 HalType::pgm_read(model,OTA_MODEL_START,2);
241 memcpy_P(model,info.DeviceModel,
sizeof(info.DeviceModel));
245 void getDeviceInfo (uint8_t* di) {
247 #ifdef DEVICE_CHANNEL_COUNT
248 *di = DEVICE_CHANNEL_COUNT;
250 *di = this->channels();
252 memcpy_P(di+1,info.DeviceInfo,
sizeof(info.DeviceInfo));
255 HMID getMasterID () {
256 return list0.masterid();
259 const List0Type& getList0 () {
264 uint8_t num = radio().read(msg);
267 if( num >= 10 && isDeviceID(msg.from()) ==
false ) {
273 uint8_t nextcount () {
277 virtual void configChanged () {}
279 virtual bool process(__attribute__((unused))
Message& msg) {
return false; }
281 bool isBroadcastMsg(
Message msg) {
282 return (msg.to() == HMID::broadcast && msg.isPairSerial()) || ( msg.isBroadcast() && (msg.isRemoteEvent() || msg.isSensorEvent()) );
287 getDeviceID(msg.from());
293 hal->prepareSend(msg);
295 uint8_t maxsend = list0.transmitDevTryMax();
296 bool ledmode = list0.ledMode();
298 led().set(LedStates::send);
300 while( result ==
false && maxsend > 0 ) {
301 result = radio().write(msg,msg.burstRequired());
305 if( result ==
true && msg.ackRequired() ==
true && msg.to().valid() ==
true ) {
307 if( (result=waitResponse(msg,response,60)) ) {
309 if( response.isChallengeAes() ==
true ) {
311 result = processChallenge(msg,cm.challenge(),cm.keyindex());
316 result = response.isAck();
318 if( response.isNack() ) {
323 if( msg.isWakeMeUp() || response.isKeepAwake() ) {
324 activity().stayAwake(millis2ticks(500));
328 DPRINT(F(
"waitAck: ")); DHEX((uint8_t)result); DPRINTLN(F(
""));
332 led().set( result ==
true ? LedStates::ack : LedStates::nack);
338 void sendAck (
Message& msg,uint8_t flag=0x00) {
339 msg.ack().init(flag);
341 send(msg,msg.from());
344 void sendAck2 (
Message& msg,uint8_t flag=0x00) {
345 msg.ack2().init(flag);
347 send(msg,msg.from());
352 send(msg,msg.from());
355 template <
class ChannelType>
356 void sendAck (
Message& msg,ChannelType& ch) {
357 msg.ackStatus().init(ch,radio().rssi());
360 send(msg,msg.from());
364 void sendDeviceInfo () {
365 sendDeviceInfo(getMasterID(),nextcount());
368 void sendDeviceInfo (
const HMID& to,uint8_t 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());
378 void sendSerialInfo (
const HMID& to,uint8_t count) {
381 getDeviceSerial(pm.serial());
385 template <
class ChannelType>
386 void sendInfoActuatorStatus (
const HMID& to,uint8_t count,ChannelType& ch,
bool ack=
true) {
388 pm.init(count,ch,radio().rssi());
397 void sendInfoParamResponsePairs(
HMID to,uint8_t count,
const GenericList& list) {
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);
411 if( send(msg,to) ==
false ) {
425 template <
class ChannelType>
426 void sendInfoPeerList (
HMID to,uint8_t count,
const ChannelType& channel) {
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));
442 if( send(msg,to) == false ) {
449 memset(buf,0,
sizeof(
Peer));
456 void sendMasterEvent (
Message& msg) {
457 send(msg,getMasterID());
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 ){
466 if( p.valid() ==
true ) {
468 if( ch.peerfor(p) < i ) {
471 if( isDeviceID(p) ==
true ) {
473 getDeviceID(msg.from());
475 if( msg.ackRequired() ==
true ) {
486 typename ChannelType::List4 l4 = ch.getList4(p);
487 msg.burstRequired( l4.burst() );
494 if( sendtopeer ==
false ) {
495 send(msg,getMasterID());
501 template <
class ChannelType>
502 void broadcastPeerEvent (
Message& msg,
const ChannelType& ch) {
503 getDeviceID(msg.from());
506 if( ch.peerfor(msg.from()) < ch.peers() ) {
515 for( uint8_t i=0; i<ch.peers(); ++i ) {
517 if( p.valid() ==
true ) {
518 if( msg.from() != p ) {
519 if( todev.valid() ==
false ) {
522 typename ChannelType::List4 l4 = ch.getList4(p);
528 if( todev.valid() ==
false ) {
529 todev = getMasterID();
532 msg.burstRequired(burst);
539 template <
class ChannelType>
540 void broadcastEvent (
Message& msg,
const ChannelType& ch) {
544 void broadcastEvent (
Message& msg) {
546 msg.burstRequired(
false);
548 send(msg,HMID::broadcast);
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));
570 bool waitResponse(
const Message& msg,
Message& response,uint8_t timeout) {
572 uint8_t num = radio().read(response);
574 DPRINT(F(
"-> ")); response.dump();
575 if( msg.count() == response.count() &&
576 msg.to() == response.from() ) {
583 while( timeout > 0 );
588 void sendAckAes (
Message& msg,
const uint8_t* data) {
589 msg.ackAes().init(data);
590 send(msg,msg.from());
593 bool requestSignature(
const Message& msg) {
595 if( isDeviceID(msg.from()) ==
true ) {
599 if( msg.ackRequired() ==
true ) {
601 signmsg.init(msg,kstore.getIndex());
602 kstore.challengeKey(signmsg.challenge(),kstore.getIndex());
604 DPRINT(F(
"<- ")); signmsg.dump();
605 radio().write(signmsg,signmsg.burstRequired());
607 if( waitForAesResponse(msg.from(),signmsg,60) ==
true ) {
611 kstore.fillInitVector(msg);
614 uint8_t* data = response.data();
615 aes128_dec(data,&kstore.ctx);
617 kstore.applyVector(data);
619 kstore.storeAuth(response.count(),data);
621 aes128_dec(data,&kstore.ctx);
625 if( memcmp(data+6,msg.buffer(),10) == 0 ) {
626 DPRINTLN(F(
"Signature OK"));
630 DPRINTLN(F(
"Signature FAILED"));
634 DPRINTLN(F(
"waitForAesResponse failed"));
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);
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();
651 memcpy(data+6,msg.buffer(),10);
652 aes128_enc(data,&kstore.ctx);
653 kstore.applyVector(data);
654 aes128_enc(data,&kstore.ctx);
655 return send(answer,msg.to());
660 bool waitForAesResponse(
const HMID& from,
Message& answer,uint8_t timeout) {
662 uint8_t num = radio().read(answer);
664 DPRINT(F(
"-> ")); answer.dump();
665 if( answer.isResponseAes() && from == answer.from() ) {
672 while( timeout > 0 );