20 class ConfigPeerAddMsg;
21 class ConfigPeerRemoveMsg;
22 class ConfigPeerListReqMsg;
23 class ConfigParamReqMsg;
26 class ConfigWriteIndexMsg;
33 class AesChallengeMsg;
37 class InfoActuatorStatusMsg;
38 class InfoParamResponsePairsMsg;
39 class InfoPeerListMsg;
47 class ActionCommandMsg;
73 uint8_t pload[MaxDataLen];
76 Message () : len(0), cnt(0), flag(0), typ(0), comm(0), subcom(0) {}
86 const uint8_t* buffer ()
const {
90 uint8_t buffersize () {
98 const uint8_t* data ()
const {
102 uint8_t datasize ()
const {
103 return len >= 11 ? len - 11 : 0;
106 void append (uint8_t data) {
107 *(buffer() + len) = data;
111 void append (uint16_t data) {
112 uint8_t* ptr = buffer() + len;
113 *ptr = (uint8_t)(data >> 8);
114 *(ptr+1) = (uint8_t)(data & 0xff);
118 void append (uint32_t data) {
119 append((uint16_t)(data >> 16));
120 append((uint16_t)(data & 0xffff));
123 void append (
void* data,uint8_t l) {
124 memcpy(buffer()+len,data,l);
128 void append (uint8_t d1, uint8_t d2, uint8_t d3) {
129 uint8_t* ptr = buffer() + len;
136 void append (uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4) {
137 uint8_t* ptr = buffer() + len;
145 void initWithCount(uint8_t length, uint8_t typ, uint8_t flags, uint8_t comm) {
152 void init(uint8_t length, uint8_t cnt, uint8_t typ, uint8_t flags, uint8_t comm, uint8_t sub) {
153 initWithCount(length,typ,flags,comm);
158 void length (uint8_t l) {
162 uint8_t length ()
const {
166 void count (uint8_t c) {
170 uint8_t count ()
const {
174 void from(
const HMID& hmid) {
178 const HMID& from ()
const {
186 void to(
const HMID& hmid) {
188 if( hmid == HMID::broadcast ) {
194 const HMID& to ()
const {
202 void type (uint8_t t) {
206 uint8_t type ()
const {
210 void flags (uint8_t f) {
214 uint8_t flags ()
const {
218 void command (uint8_t c) {
222 uint8_t command ()
const {
226 void subcommand (uint8_t c) {
230 uint8_t subcommand ()
const {
235 decode(buffer(),length());
238 void decode(uint8_t *buf, uint8_t len) {
239 uint8_t prev = buf[0];
240 buf[0] = (~buf[0]) ^ 0x89;
242 for (i=1; i<len-1; i++) {
244 buf[i] = (prev + 0xdc) ^ buf[i];
251 encode(buffer(),length());
254 void encode(uint8_t *buf,uint8_t len) {
255 buf[0] = (~buf[0]) ^ 0x89;
256 uint8_t buf2 = buf[1];
257 uint8_t prev = buf[0];
259 for (i=1; i<len-1; i++) {
260 prev = (prev + 0xdc) ^ buf[i];
279 DHEX(buffer()+9,length()-9);
281 DDECLN((uint32_t)millis());
284 void setRepeated () {
300 bool isKeepAwake ()
const {
301 return (flag & WKUP) == WKUP;
304 bool isWakeMeUp ()
const {
305 return (flag & WKMEUP) == WKMEUP;
308 void setWakeMeUp () {
312 void setBroadcast () {
316 bool isBroadcast ()
const {
317 return (flag & BCAST) == BCAST;
320 bool isRepeated ()
const {
321 return (flag & RPTED) == RPTED;
324 bool ackRequired ()
const {
325 return (flag & BIDI) == BIDI;
328 bool burstRequired ()
const {
329 return (flag & BURST) == BURST;
332 void burstRequired (
bool value) {
333 if( value ==
true ) {
341 bool isPairSerial ()
const {
342 return typ==AS_MESSAGE_CONFIG && subcom==AS_CONFIG_PAIR_SERIAL;
345 bool isAck ()
const {
346 return typ==AS_MESSAGE_RESPONSE && (comm & AS_RESPONSE_NACK) == AS_RESPONSE_ACK;
349 bool isNack ()
const {
350 return typ==AS_MESSAGE_RESPONSE && (comm & AS_RESPONSE_NACK) == AS_RESPONSE_NACK;
353 bool isResponseAes ()
const {
354 return typ==AS_MESSAGE_RESPONSE_AES;
357 bool isChallengeAes ()
const {
358 return typ==AS_MESSAGE_RESPONSE && (comm & AS_RESPONSE_AES_CHALLANGE) == AS_RESPONSE_AES_CHALLANGE;
361 bool isRemoteEvent ()
const {
362 return typ==AS_MESSAGE_REMOTE_EVENT;
365 bool isSensorEvent ()
const {
366 return typ==AS_MESSAGE_SENSOR_EVENT;
369 bool isInfoActuatorStatusMsg ()
const {
370 return typ==AS_MESSAGE_INFO && comm==AS_INFO_ACTUATOR_STATUS;
413 uint8_t channel ()
const {
return command(); }
420 const Peer& peer1 ()
const {
return *((
const Peer*)data()); }
421 Peer peer2 ()
const {
return Peer(peer1(),*(data()+
sizeof(
Peer))); }
424 uint8_t peers ()
const {
426 return (p2.channel() == 0) || (p2 == peer1()) ? 1 : 2;
444 const Peer& peer ()
const {
return *((
const Peer*)data()); }
445 uint8_t list ()
const {
return *(data()+
sizeof(
Peer)); }
467 void init(uint8_t msgcnt,uint8_t ch,uint8_t counter,
bool lg,
bool lowbat) {
468 uint8_t flags = lg ? 0x40 : 0x00;
469 if( lowbat ==
true ) {
472 Message::init(0xb,msgcnt,AS_MESSAGE_REMOTE_EVENT,BIDI|WKMEUP,(ch & 0x3f) | flags,counter);
475 Peer peer ()
const {
return Peer(from(),command() & 0x3f); }
476 uint8_t counter ()
const {
return subcommand(); }
477 bool isLong ()
const {
return (command() & 0x40) == 0x40; }
484 void init(uint8_t msgcnt,uint8_t ch,uint8_t counter,uint8_t value,
bool lowbat) {
485 init(msgcnt,ch,counter,value,
false,lowbat);
487 void init(uint8_t msgcnt,uint8_t ch,uint8_t counter,uint8_t value,
bool lg,
bool lowbat) {
488 uint8_t flags = lg ? 0x40 : 0x00;
489 if( lowbat ==
true ) {
492 Message::init(0xc,msgcnt,AS_MESSAGE_SENSOR_EVENT,BIDI|WKMEUP,(ch & 0x3f) | flags,counter);
495 uint8_t value ()
const {
return *data(); }
502 uint8_t channel ()
const {
return subcommand(); }
509 uint8_t channel ()
const {
return subcommand(); }
510 uint8_t value ()
const {
return *data(); }
511 uint16_t ramp ()
const {
513 if( datasize() >= 3) {
514 value = (*(data()+1) << 8) + *(data()+2);
518 uint16_t delay ()
const {
519 uint16_t dly = 0xffff;
520 if( datasize() >= 5) {
521 dly = (*(data()+3) << 8) + *(data()+4);
523 if( dly == 0 ) dly = 0xffff;
532 uint8_t channel ()
const {
return subcommand(); }
533 uint8_t len ()
const {
return (datasize()); }
534 uint8_t value (uint8_t idx)
const {
return *(data()+idx); }
535 bool eot (uint8_t eot_char=AS_ACTION_COMMAND_EOT)
const {
return (length() >= 12) ? (*(data()+length()-12) == eot_char) :
false; }
540 void init(uint8_t flags=0x00) {
541 initWithCount(0x0a,AS_MESSAGE_RESPONSE,flags,AS_RESPONSE_ACK);
547 void init(uint8_t flags=0x00) {
548 initWithCount(0x0a,AS_MESSAGE_RESPONSE,flags,AS_RESPONSE_ACK2);
554 template <
class ChannelType>
555 void init(ChannelType& ch,uint8_t rssi) {
556 initWithCount(0x0e,AS_MESSAGE_RESPONSE,0x00,AS_RESPONSE_ACK_STATUS);
557 subcom = ch.number();
558 pload[0] = ch.status();
559 pload[1] = ch.flags();
567 initWithCount(0x0a,AS_MESSAGE_RESPONSE,0x00,AS_RESPONSE_NACK);
573 void init(
const uint8_t* data) {
574 initWithCount(0x12,AS_MESSAGE_RESPONSE,0x00,AS_RESPONSE_ACK);
584 void init(
const Message& msg,uint8_t keyidx) {
585 initWithCount(0x11,AS_MESSAGE_RESPONSE,RPTEN|BIDI,AS_RESPONSE_AES_CHALLANGE);
589 uint8_t* tmp = data()-1;
590 for( uint8_t i=0; i<6; i++ ) {
591 *tmp = (uint8_t)rand();
596 const uint8_t* challenge ()
const {
599 uint8_t keyindex ()
const {
600 return *(challenge()+6);
606 void init(
const Message& msg) {
607 initWithCount(0x19,AS_MESSAGE_RESPONSE_AES,BIDI,0x00);
611 return Message::data()-2;
618 return Message::data()-2;
624 template <
class ChannelType>
625 void init (uint8_t count,ChannelType& ch,uint8_t rssi) {
626 Message::init(0x0e,count,AS_MESSAGE_INFO,BIDI|WKMEUP,AS_INFO_ACTUATOR_STATUS,ch.number());
627 pload[0] = ch.status();
628 pload[1] = ch.flags();
635 void init (uint8_t count) {
636 initWithCount(0x0b-1+(8*2),AS_MESSAGE_INFO,BIDI,AS_INFO_PARAM_RESPONSE_PAIRS);
639 uint8_t* data() {
return Message::data()-1; }
640 void entries (uint8_t num) { length(0x0b-1+(num*2)); };
645 void init (uint8_t count) {
646 initWithCount(0x0b-1+(4*
sizeof(
Peer)),AS_MESSAGE_INFO,Message::BIDI,AS_INFO_PEER_LIST);
649 uint8_t* data() {
return Message::data()-1; }
650 void entries (uint8_t num) { length(0x0b-1+(num*
sizeof(
Peer))); };
655 void init (__attribute__((unused))
const HMID& to,uint8_t count) {
656 Message::init(0x1a,count,AS_MESSAGE_DEVINFO,0x00,AS_INFO_SERIAL,0x00);
658 uint8_t* data() {
return Message::data()-2; }
659 void fill(uint8_t firmversion,uint8_t modelid[2],
const char* serial,uint8_t subtype,uint8_t devinfo[3]) {
660 uint8_t* buf = data();
662 memcpy(buf+1,modelid,2);
663 memcpy(buf+3,serial,10);
665 memcpy(buf+14,devinfo,3);
667 void fill(uint8_t firmversion,uint8_t subtype) {
668 uint8_t* buf = data();
672 uint8_t* serial () {
return data() + 3; }
673 uint8_t* model () {
return data() + 1; }
674 uint8_t* info () {
return data() + 14; }
679 void init (__attribute__((unused))
const HMID& to,uint8_t count) {
680 Message::init(0x14,count,AS_MESSAGE_INFO,0x00,AS_INFO_SERIAL,0x00);
682 uint8_t* data() {
return Message::data()-4; }
683 void fill(
const char* serial) {
684 uint8_t* buf = data();
685 memcpy(buf+3,serial,10);
687 uint8_t* serial () {
return data() + 3; }
692 void init(uint8_t msgcnt,uint8_t ch) {
693 Message::init(0x0b,msgcnt,AS_MESSAGE_SENSOR_DATA,BIDI|WKMEUP,ch,0);
695 template <
typename T>
697 uint8_t* values = buffer() + len +
sizeof(T) - 1;
698 uint8_t num =
sizeof(T);
700 *values = value & 0xff;
708 subcommand(subcommand()+1);