RSeries astromech firmware
ReelTwoSMQ32.h
Go to the documentation of this file.
1 #ifndef REELTWOSMQ32_H
2 #define REELTWOSMQ32_H
3 #define USE_SMQ
4 #define USE_SMQ32
5 
6 #ifndef SMQ_HOSTNAME
7 #define SMQ_HOSTNAME "Generic"
8 #endif
9 
10 #ifdef ReelTwo_h
11 #error ReelTwoSMQ32.h must be included before ReelTwo.h
12 #endif
13 
14 #include "ReelTwo.h"
15 #include <esp_now.h>
16 #include <WiFi.h>
17 
18 #ifdef USE_SMQDEBUG
19 #define SMQ_DEBUG_PRINTLN(s) DEBUG_PRINTLN(s)
20 #define SMQ_DEBUG_PRINT(s) DEBUG_PRINT(s)
21 #define SMQ_DEBUG_PRINTF(...) DEBUG_PRINTF(__VA_ARGS__)
22 #define SMQ_DEBUG_PRINTLN_HEX(s) DEBUG_PRINTLN_HEX(s)
23 #define SMQ_DEBUG_PRINT_HEX(s) DEBUG_PRINT_HEX(s)
24 #define SMQ_DEBUG_FLUSH(s) DEBUG_FLUSH()
25 #else
26 #define SMQ_DEBUG_PRINTLN(s)
27 #define SMQ_DEBUG_PRINT(s)
28 #define SMQ_DEBUG_PRINTF(...)
29 #define SMQ_DEBUG_PRINTLN_HEX(s)
30 #define SMQ_DEBUG_PRINT_HEX(s)
31 #define SMQ_DEBUG_FLUSH(s)
32 #endif
33 
34 #define SMQ_ADDR_HEX_STR "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"
35 #define SMQ_ADDR_HEX_ARR(addr) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
36 #define SMQ_ADDR_HEX_PTR(addr) &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]
37 
38 #define SMQ_MAX_KEYLEN ESP_NOW_KEY_LEN
39 
40 #define SMQ_BEACON_BROADCAST_INTERVAL 1000
41 #define SMQ_HOST_LOST_TIMEOUT 10000
42 
43 #define SMQ_MAX_PAIRED_HOSTS 20
44 #define SMQ_MINIMUM_KEY_LEN 8
45 
46 // Pairing times out after 2 minutes
47 #define SMQ_PAIRING_TIMEOUT 2*60*1000
48 
49 // static const char* PMK_KEY_STR = "PLEASE_CHANGE_ME";
50 
51 typedef uint16_t msg_id;
52 typedef uint32_t smq_id;
53 
54 #define WIFI_CHANNEL 1
55 #define QUEUE_SIZE 10
56 #define MAX_MSG_SIZE 250
57 #define SMQ_MAX_HOST_NAME 13
58 
59 struct SMQAddress
60 {
61  uint8_t fData[6];
62 
63  bool equals(uint8_t addr[6])
64  {
65  return (memcmp(addr, fData, sizeof(fData)) == 0);
66  }
67 
68  bool equals(SMQAddress& addr)
69  {
70  return equals(addr.fData);
71  }
72 
73  String toString()
74  {
75  char macaddr[6*3+1];
76  snprintf(macaddr, sizeof(macaddr), "%02X:%02X:%02X:%02X:%02X:%02X",
77  fData[0], fData[1], fData[2], fData[3], fData[4], fData[5]);
78  return macaddr;
79  }
80 };
81 
82 struct SMQLMK
83 {
84  uint8_t fData[16];
85 
86  bool equals(uint8_t addr[16])
87  {
88  return (memcmp(addr, fData, sizeof(fData)) == 0);
89  }
90 
91  bool equals(SMQLMK& addr)
92  {
93  return equals(addr.fData);
94  }
95 
96  String toString()
97  {
98  char str[16*3+1];
99  uint8_t* p = fData;
100  snprintf(str, sizeof(str), "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
101  p[0], p[1], p[2], p[3], p[4], p[5],
102  p[6], p[7], p[8], p[9], p[10], p[11],
103  p[12], p[13], p[14], p[15]);
104  return str;
105  }
106 };
107 
109 {
112 };
113 
114 struct SMQHost
115 {
117  uint8_t fCount;
120  uint32_t fLastSeen;
121  bool fPaired;
125 
126  String getHostName()
127  {
128  return fName;
129  }
130 
131  String getHostAddress()
132  {
133  char macaddr[6*3+1];
134  uint8_t* p = fAddr.fData;
135  snprintf(macaddr, sizeof(macaddr), "%02X:%02X:%02X:%02X:%02X:%02X",
136  p[0], p[1], p[2], p[3], p[4], p[5]);
137  return macaddr;
138  }
139 
140  String getHostKey()
141  {
142  return fLMK.toString();
143  }
144 
146  {
147  memcpy(addr, &fAddr, sizeof(*addr));
148  return addr;
149  }
150 
151  bool hasTopic(smq_id topicID)
152  {
153  for (unsigned i = 0; i < fCount; i++)
154  {
155  if (fTopics[i] == topicID)
156  return true;
157  }
158  return false;
159  }
160 
161  bool hasTopic(const char* topic)
162  {
163  return hasTopic(WSID32(topic));
164  }
165 };
166 
168 {
169  uint8_t fAddr[6];
170  uint8_t fSize;
171  uint8_t fData[MAX_MSG_SIZE];
172 };
173 static bool sSMQInited = false;
174 static SMQAddress sSMQFromAddr;
175 static unsigned sSMQPairedHostsCount;
176 static SMQAddressKey sSMQPairedHosts[SMQ_MAX_PAIRED_HOSTS];
177 static char sSMQPairingMode = false;
178 static uint32_t sSMQPairingTimeOut = 0;
179 static bool sClearToSend = false;
180 static uint8_t sSendBuffer[MAX_MSG_SIZE];
181 static uint8_t* sSendPtr = sSendBuffer;
182 static SMQLMK sSMQLMK;
183 static uint8_t sBroadcastMAC[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
184 static QueueHandle_t sRecvQueue;
185 static uint8_t* sReadPtr = nullptr;
186 static int sReadLen = 0;
187 static char sHostName[SMQ_MAX_HOST_NAME];
188 static SMQHost* sHostHead;
189 static SMQHost* sHostTail;
190 static uint32_t sKeyHash;
191 static uint8_t* sSendAddr = nullptr;
192 static void (*sPairingEvent)(SMQHost* host);
193 static void (*sDiscoverEvent)(SMQHost* host);
194 static void (*sLostEvent)(SMQHost* host);
195 static smq_id sSMQBEACON_ID = STRID("BEACON");
196 static smq_id sSMQPAIRING_ID = STRID("PAIRING");
197 
198 #define REELTWO_READY() _REELTWO_READY_
199 
210 class SMQ
211 {
212 public:
213  static void startPairing()
214  {
215  if (addBroadcastPeer())
216  {
217  sSMQPairingMode = true;
218  sSMQPairingTimeOut = millis() + SMQ_PAIRING_TIMEOUT;
219  }
220  }
221 
222  static bool isPairing()
223  {
224  return (sSMQPairingMode == true);
225  }
226 
227  static void stopPairing()
228  {
229  if (sSMQPairingMode)
230  {
231  sSMQPairingMode++;
232  sSMQPairingTimeOut = millis() + 2000;
233  }
234  }
235 
236  static int masterKeyExchange(SMQLMK* remoteKey)
237  {
238  static SMQLMK zeroAddress;
239  SMQLMK lmk;
240  getLocalMasterKey(&lmk);
241  if (lmk.equals(zeroAddress) == remoteKey->equals(zeroAddress))
242  {
243  if (lmk.equals(zeroAddress))
244  {
245  // Error condition neither device has a master key
246  printf("No master key. One device must have a master key to pair.\n");
247  return -1;
248  }
249  else if (!lmk.equals(*remoteKey))
250  {
251  // Error condition two different master keys cannot pair
252  printf("Two different master keys. Reset one device to factory defaults and try again.\n");
253  return -1;
254  }
255  else
256  {
257  // One of the devices has a master key continue
258  }
259  }
260  if (!lmk.equals(zeroAddress))
261  {
262  printf("WE HAVE A MASTER KEY\n");
263  // We have a master key
264  *remoteKey = lmk;
265  return 0;
266  }
267  // Remote device has master key
268  printf("REMOTE HAS MASTER KEY\n");
269  lmk = *remoteKey;
270  setLocalMasterKey(&lmk);
271  return 1;
272  }
273 
274  static void addPairedHosts(unsigned numHosts, SMQAddressKey* hosts)
275  {
276  numHosts = min(numHosts, unsigned(SMQ_MAX_PAIRED_HOSTS));
277  sSMQPairedHostsCount = numHosts;
278  memcpy(sSMQPairedHosts, hosts, numHosts * sizeof(sSMQPairedHosts[0]));
279  if (!addPairedPeers())
280  {
281  SMQ_DEBUG_PRINTLN("Failed to add paired peers");
282  }
283  SMQ_DEBUG_PRINTLN("Paired Hosts:");
284  for (int i = 0; i < sSMQPairedHostsCount; i++)
285  {
286  SMQ_DEBUG_PRINT(sSMQPairedHosts[i].fAddr.toString());
287  SMQ_DEBUG_PRINT(" - ");
288  SMQ_DEBUG_PRINTLN(sSMQPairedHosts[i].fLMK.toString());
289  }
290  }
291 
292  static bool addPairedHost(SMQAddress* addr, SMQLMK* lmk = nullptr)
293  {
294  // Make sure host doesn't exist already
295  for (unsigned i = 0; i < sSMQPairedHostsCount; i++)
296  {
297  if (memcmp(&sSMQPairedHosts[i].fAddr, addr, sizeof(*addr)) == 0)
298  return false;
299  }
300  if (sSMQPairedHostsCount+1 < SMQ_MAX_PAIRED_HOSTS)
301  {
302  SMQAddressKey host;
303  host.fAddr = *addr;
304  host.fLMK = *lmk;
305  sSMQPairedHosts[sSMQPairedHostsCount++] = host;
306  return true;
307  }
308  return false;
309  }
310 
311  static unsigned getPairedHostCount()
312  {
313  return sSMQPairedHostsCount;
314  }
315 
316  static unsigned getPairedHosts(SMQAddressKey* hosts, unsigned maxCount)
317  {
318  maxCount = min(maxCount, sSMQPairedHostsCount);
319  memcpy(hosts, sSMQPairedHosts, maxCount * sizeof(sSMQPairedHosts[0]));
320  return maxCount;
321  }
322 
323  static void setHostPairingCallback(void (*callback)(SMQHost* host))
324  {
325  sPairingEvent = callback;
326  }
327 
328  static void setHostDiscoveryCallback(void (*callback)(SMQHost* host))
329  {
330  sDiscoverEvent = callback;
331  }
332 
333  static void setHostLostCallback(void (*callback)(SMQHost* host))
334  {
335  sLostEvent = callback;
336  }
337 
338  static bool clearToSend()
339  {
340  return sClearToSend;
341  }
342 
343  static String getAddress()
344  {
345  return WiFi.macAddress();
346  }
347 
348  static bool init(String hostName, String key)
349  {
350  return init(hostName.c_str(), key.c_str());
351  }
352 
353  static bool init(const char* hostName = nullptr, const char* key = nullptr)
354  {
355  // Ensure minimum key length
356  if (key != nullptr && strlen(key) < SMQ_MINIMUM_KEY_LEN)
357  {
358  SMQ_DEBUG_PRINTLN("Key too short");
359  return false;
360  }
361  if (WiFi.getMode() != WIFI_STA)
362  {
363  printf("CHANGING TO WIFI_STA MODE\n");
364  // Puts ESP in STATION MODE
365  WiFi.mode(WIFI_STA);
366  }
367  if (WiFi.getMode() != WIFI_STA)
368  {
369  SMQ_DEBUG_PRINTLN("WiFi must be in station mode");
370  return false;
371  }
372  if (esp_now_init() != ESP_OK)
373  {
374  SMQ_DEBUG_PRINTLN("Failed to initalize SMQ32");
375  return false;
376  }
377  memset(sHostName, '\0', sizeof(sHostName));
378  snprintf(sHostName, sizeof(sHostName)-1, "%s", (hostName != nullptr) ? hostName : SMQ_HOSTNAME);
379  sKeyHash = (key != nullptr && *key != '\0') ? WSID32(key) : 0;
380  sRecvQueue = xQueueCreate(QUEUE_SIZE, sizeof(SMQRecvMsg));
381  union
382  {
383  SMQLMK key;
384  uint32_t crc[4];
385  } master;
386  master.crc[0] = WSID32(key);
387  master.crc[1] = WSID32(key+1);
388  master.crc[2] = WSID32(key+2);
389  master.crc[3] = WSID32(key+3);
390  printf("MASTER: %s\n", master.key.toString().c_str());
391  esp_now_set_pmk(master.key.fData);
392 
393  // Set up callback
394  esp_err_t status = esp_now_register_recv_cb(msg_recv_cb);
395  if (ESP_OK != status)
396  {
397  SMQ_DEBUG_PRINTLN("Could not register callback");
398  // handle_error(status);
399  return false;
400  }
401 
402  status = esp_now_register_send_cb(msg_send_cb);
403  if (ESP_OK != status)
404  {
405  SMQ_DEBUG_PRINTLN("Could not register send callback");
406  // handle_error(status);
407  return false;
408  }
409  sClearToSend = true;
410  sSMQInited = true;
411  return true;
412  }
413 
414  static bool addBroadcastPeer()
415  {
416  // add broadcast peer if not already added
417  if (!esp_now_is_peer_exist(sBroadcastMAC))
418  {
419  esp_now_peer_info_t peer_info;
420  peer_info.channel = WIFI_CHANNEL;
421  memcpy(peer_info.peer_addr, sBroadcastMAC, sizeof(sBroadcastMAC));
422  peer_info.ifidx = WIFI_IF_STA;
423  peer_info.encrypt = false;
424  esp_err_t status = esp_now_add_peer(&peer_info);
425  if (ESP_OK != status)
426  {
427  SMQ_DEBUG_PRINTLN("Could not add peer");
428  // handle_error(status);
429  return false;
430  }
431  }
432  return true;
433  }
434 
435  static void createLocalMasterKey(SMQLMK* key)
436  {
437  esp_fill_random(key->fData, sizeof(key->fData));
438  }
439 
440  static void setLocalMasterKey(SMQLMK* key)
441  {
442  sSMQLMK = *key;
443  }
444 
445  static void getLocalMasterKey(SMQLMK* key)
446  {
447  *key = sSMQLMK;
448  }
449 
450  static void removeBroadcastPeer()
451  {
452  // Delete broadcast peer if it exists ignore if not
453  esp_now_del_peer(sBroadcastMAC);
454  }
455 
456  static void process()
457  {
458  static uint32_t sLastBeacon;
459  SMQRecvMsg msg;
460  if (!sSMQInited)
461  return;
462  while (xQueueReceive(sRecvQueue, &msg, 0))
463  {
464  sReadPtr = msg.fData;
465  sReadLen = msg.fSize;
466  // printf("sReadLen: %d *sReadPtr=0x%02X\n", sReadLen, *sReadPtr);
467  if (sReadLen > 1 && *sReadPtr++ == 0x0E)
468  {
469  sReadLen--;
470  // printf("FROM : %02X:%02X:%02X:%02X:%02X:%02X\n",
471  // msg.fAddr[0], msg.fAddr[1], msg.fAddr[2],
472  // msg.fAddr[3], msg.fAddr[4], msg.fAddr[5]);
473  Message::process(&msg);
474  }
475  }
476  if (sLastBeacon + SMQ_BEACON_BROADCAST_INTERVAL < millis())
477  {
478  if (sSMQPairingMode && sSMQPairingTimeOut < millis())
479  {
481  sSMQPairingMode = false;
482  // sSMQPairingMode will be 2 if successful
483  if (sSMQPairingMode == true && sPairingEvent)
484  {
485  sPairingEvent(nullptr);
486  }
487  }
488  if (SMQ::clearToSend())
489  {
490  if (sSMQPairingMode)
491  {
492  Message::sendPair();
493  }
494  else if (sSMQPairedHostsCount != 0)
495  {
496  Message::sendBeacon();
497  }
498  sLastBeacon = millis();
499  }
500  pruneHostList();
501  }
502  }
503 
504  static void sendString(String str)
505  {
506  send_string(str.c_str());
507  }
508 
509  static void send_string(const char* str)
510  {
511  uint8_t delim = 0x00;
512  send_raw_bytes(&delim, sizeof(delim));
513 
514  uint16_t len = strlen(str);
515  send_data(&len, sizeof(len));
516  send_data(str, len);
517  }
518 
519  static void send_string(PROGMEMString str)
520  {
521  uint8_t delim = 0x00;
522  send_raw_bytes(&delim, sizeof(delim));
523 
524  size_t len = strlen_P((const char*)str);
525  send_data(&len, sizeof(len));
526  send_data(str, len);
527  }
528 
529  static void send_string_id(const msg_id id)
530  {
531  uint8_t delim = 0x01;
532  send_raw_bytes(&delim, sizeof(delim));
533  send_raw_bytes(&id, sizeof(id));
534  }
535 
536  static void send_topic_id(const smq_id id)
537  {
538  uint8_t delim = 0x0E;
539  send_raw_bytes(&delim, sizeof(delim));
540  send_raw_bytes(&id, sizeof(id));
541  }
542 
543  static void send_topic_hash(const char* str)
544  {
545  send_topic_id(WSID32(str));
546  }
547 
548  static void send_string_hash(const char* str)
549  {
550  uint8_t delim = 0x01;
551  send_raw_bytes(&delim, sizeof(delim));
552 
553  uint16_t crc = 0xFFFF;
554  uint16_t len = strlen(str);
555  const uint8_t* b = (uint8_t*)str;
556  const uint8_t* buf_end = (uint8_t*)str + len;
557  while (b < buf_end)
558  {
559  crc = update_crc(crc, *b++);
560  }
561  crc = ~crc;
562  send_raw_bytes(&crc, sizeof(crc));
563  }
564 
566  {
567  uint8_t delim = 0x01;
568  send_raw_bytes(&delim, sizeof(delim));
569 
570  uint16_t crc = 0xFFFF;
571  uint16_t len = strlen_P((const char*)str);
572  const uint8_t* b = (uint8_t*)str;
573  const uint8_t* buf_end = (uint8_t*)str + len;
574  while (b < buf_end)
575  {
576  crc = update_crc(crc, pgm_read_byte(b++));
577  }
578  send_raw_bytes(&crc, sizeof(crc));
579  }
580 
581  static void send_start(const smq_id id)
582  {
583  send_topic_id(id);
584  send_raw_bytes(&sKeyHash, sizeof(sKeyHash));
585  }
586 
587  static void send_start(const char* str)
588  {
589  send_topic_hash(str);
590  send_raw_bytes(&sKeyHash, sizeof(sKeyHash));
591  }
592 
593  static void send_start(PROGMEMString str)
594  {
595  send_topic_hash(String(str).c_str());
596  send_raw_bytes(&sKeyHash, sizeof(sKeyHash));
597  }
598 
599  static void send_string(const msg_id id, const char* val)
600  {
601  send_string_id(id);
602  send_string(val);
603  }
604 
605  static void send_string(const char* key, const char* val)
606  {
607  send_string_hash(key);
608  send_string(val);
609  }
610 
611  static void send_string(PROGMEMString key, const char* val)
612  {
613  send_string(key);
614  send_string(val);
615  }
616 
618  {
619  send_string(key);
620  send_string(val);
621  }
622 
623  static void sendString(const char* key, const char* val)
624  {
625  send_string(key, val);
626  }
627 
628  static void sendString(String key, String val)
629  {
630  send_string(key.c_str(), val.c_str());
631  }
632 
633  static void sendString(const char* key, String val)
634  {
635  send_string(key, val.c_str());
636  }
637 
638  static void sendString(String key, const char* val)
639  {
640  send_string(key.c_str(), val);
641  }
642 
643  static void send_int8(const msg_id id, int8_t val)
644  {
645  uint8_t delim = 0x02;
646  send_string_id(id);
647  send_raw_bytes(&delim, sizeof(delim));
648  send_data(&val, sizeof(val));
649  }
650 
651  static void send_int8(const char* key, int8_t val)
652  {
653  uint8_t delim = 0x02;
654  send_string_hash(key);
655  send_raw_bytes(&delim, sizeof(delim));
656  send_data(&val, sizeof(val));
657  }
658 
659  static void send_int8(PROGMEMString key, int8_t val)
660  {
661  uint8_t delim = 0x02;
662  send_string_hash(key);
663  send_raw_bytes(&delim, sizeof(delim));
664  send_data(&val, sizeof(val));
665  }
666 
667  static void send_int16(const msg_id id, int16_t val)
668  {
669  uint8_t delim = 0x03;
670  send_string_id(id);
671  send_raw_bytes(&delim, sizeof(delim));
672  send_data(&val, sizeof(val));
673  }
674 
675  static void send_int16(const char* key, int16_t val)
676  {
677  uint8_t delim = 0x03;
678  send_string_hash(key);
679  send_raw_bytes(&delim, sizeof(delim));
680  send_data(&val, sizeof(val));
681  }
682 
683  static void send_int16(PROGMEMString key, int16_t val)
684  {
685  uint8_t delim = 0x03;
686  send_string_hash(key);
687  send_raw_bytes(&delim, sizeof(delim));
688  send_data(&val, sizeof(val));
689  }
690 
691  static void send_int32(const msg_id id, int32_t val)
692  {
693  uint8_t delim = 0x04;
694  send_string_id(id);
695  send_raw_bytes(&delim, sizeof(delim));
696  send_data(&val, sizeof(val));
697  }
698 
699  static void send_int32(const char* key, int32_t val)
700  {
701  uint8_t delim = 0x04;
702  send_string_hash(key);
703  send_raw_bytes(&delim, sizeof(delim));
704  send_data(&val, sizeof(val));
705  }
706 
707  static void send_int32(PROGMEMString key, int32_t val)
708  {
709  uint8_t delim = 0x04;
710  send_string_hash(key);
711  send_raw_bytes(&delim, sizeof(delim));
712  send_data(&val, sizeof(val));
713  }
714 
715  static void send_long(const msg_id id, long val)
716  {
717  send_int32(id, val);
718  }
719 
720  static void send_long(const char* key, long val)
721  {
722  send_int32(key, val);
723  }
724 
725  static void send_uint8(const msg_id id, uint8_t val)
726  {
727  uint8_t delim = 0x05;
728  send_string_id(id);
729  send_raw_bytes(&delim, sizeof(delim));
730  send_data(&val, sizeof(val));
731  }
732 
733  static void send_uint8(const char* key, uint8_t val)
734  {
735  uint8_t delim = 0x05;
736  send_string_hash(key);
737  send_raw_bytes(&delim, sizeof(delim));
738  send_data(&val, sizeof(val));
739  }
740 
741  static void send_uint8(PROGMEMString key, uint8_t val)
742  {
743  uint8_t delim = 0x05;
744  send_string_hash(key);
745  send_raw_bytes(&delim, sizeof(delim));
746  send_data(&val, sizeof(val));
747  }
748 
749  static void send_uint16(const msg_id id, uint16_t val)
750  {
751  uint8_t delim = 0x06;
752  send_string_id(id);
753  send_raw_bytes(&delim, sizeof(delim));
754  send_data(&val, sizeof(val));
755  }
756 
757  static void send_uint16(const char* key, uint16_t val)
758  {
759  uint8_t delim = 0x06;
760  send_string_hash(key);
761  send_raw_bytes(&delim, sizeof(delim));
762  send_data(&val, sizeof(val));
763  }
764 
765  static void send_uint16(PROGMEMString key, uint16_t val)
766  {
767  uint8_t delim = 0x06;
768  send_string_hash(key);
769  send_raw_bytes(&delim, sizeof(delim));
770  send_data(&val, sizeof(val));
771  }
772 
773  static void send_uint32(const msg_id id, uint32_t val)
774  {
775  uint8_t delim = 0x07;
776  send_string_id(id);
777  send_raw_bytes(&delim, sizeof(delim));
778  send_data(&val, sizeof(val));
779  }
780 
781  static void send_uint32(const char* key, uint32_t val)
782  {
783  uint8_t delim = 0x07;
784  send_string(key);
785  send_raw_bytes(&delim, sizeof(delim));
786  send_data(&val, sizeof(val));
787  }
788 
789  static void send_uint32(PROGMEMString key, uint32_t val)
790  {
791  uint8_t delim = 0x07;
792  send_string_hash(key);
793  send_raw_bytes(&delim, sizeof(delim));
794  send_data(&val, sizeof(val));
795  }
796 
797  static void send_float(const msg_id id, float val)
798  {
799  uint8_t delim = 0x08;
800  send_string_id(id);
801  send_raw_bytes(&delim, sizeof(delim));
802  send_data(&val, sizeof(val));
803  }
804 
805  static void send_float(const char* key, float val)
806  {
807  uint8_t delim = 0x08;
808  send_string_hash(key);
809  send_raw_bytes(&delim, sizeof(delim));
810  send_data(&val, sizeof(val));
811  }
812 
813  static void send_float(PROGMEMString key, float val)
814  {
815  uint8_t delim = 0x08;
816  send_string_hash(key);
817  send_raw_bytes(&delim, sizeof(delim));
818  send_data(&val, sizeof(val));
819  }
820 
821  static void send_double(const msg_id id, double val)
822  {
823  uint8_t delim = 0x09;
824  send_string_id(id);
825  send_raw_bytes(&delim, sizeof(delim));
826  send_data(&val, sizeof(val));
827  }
828 
829  static void send_double(const char* key, double val)
830  {
831  uint8_t delim = 0x09;
832  send_string_hash(key);
833  send_raw_bytes(&delim, sizeof(delim));
834  send_data(&val, sizeof(val));
835  }
836 
837  static void send_double(PROGMEMString key, double val)
838  {
839  uint8_t delim = 0x09;
840  send_string_hash(key);
841  send_raw_bytes(&delim, sizeof(delim));
842  send_data(&val, sizeof(val));
843  }
844 
845  static void send_boolean(const msg_id id, bool val)
846  {
847  uint8_t delim = (val) ? 0x0A : 0x0B;
848  send_string_id(id);
849  send_raw_bytes(&delim, sizeof(delim));
850  }
851 
852  static void send_boolean(const char* key, bool val)
853  {
854  uint8_t delim = (val) ? 0x0A : 0x0B;
855  send_string_hash(key);
856  send_raw_bytes(&delim, sizeof(delim));
857  }
858 
859  static void send_boolean(PROGMEMString key, bool val)
860  {
861  uint8_t delim = (val) ? 0x0A : 0x0B;
862  send_string_hash(key);
863  send_raw_bytes(&delim, sizeof(delim));
864  }
865 
866  static void send_null(const msg_id id)
867  {
868  uint8_t delim = 0x0C;
869  send_string_id(id);
870  send_raw_bytes(&delim, sizeof(delim));
871  }
872 
873  static void send_null(const char* key)
874  {
875  uint8_t delim = 0x0C;
876  send_string_hash(key);
877  send_raw_bytes(&delim, sizeof(delim));
878  }
879 
880  static void send_null(PROGMEMString key)
881  {
882  uint8_t delim = 0x0C;
883  send_string_hash(key);
884  send_raw_bytes(&delim, sizeof(delim));
885  }
886 
887  // static void send_buffer(const void* buf, uint16_t len)
888  // {
889  // uint8_t delim = 0x0D;
890  // send_string(key);
891  // send_raw_bytes(&delim, sizeof(delim));
892  // send_data(&len, sizeof(len));
893  // send_data(buf, len);
894  // }
895 
896  static void clearAllPeers()
897  {
898  esp_now_peer_info_t peer;
899  esp_err_t e = esp_now_fetch_peer(true, &peer);
900  while (e == ESP_OK)
901  {
902  uint8_t addr[8];
903  memcpy(addr, peer.peer_addr, sizeof(addr));
904  e = esp_now_fetch_peer(false, &peer);
905  esp_now_del_peer(addr);
906  }
908  }
909 
910  static bool sendTopic(String topic, String host)
911  {
912  return sendTopic(topic.c_str(), (host.length() != 0) ? host.c_str() : nullptr);
913  }
914 
915  static bool sendTopic(PROGMEMString topic)
916  {
917  return sendTopic(String(topic).c_str());
918  }
919 
920  // host can either be host name or host mac address
921  static bool sendTopic(const char* topic, const char* hostNameAddr = nullptr)
922  {
923  // printf("sendTopic %s\n", topic);
924  sSendAddr = nullptr;
925  if (!sSMQInited || !clearToSend())
926  {
927  SMQ_DEBUG_PRINT("FAILED TO SEND TOPIC: "); SMQ_DEBUG_PRINTLN(topic);
928  return false;
929  }
930  clearAllPeers();
931 
932  bool searchHostMac = false;
933  uint8_t addr[6];
934  if (hostNameAddr != nullptr)
935  {
936  if (sscanf(hostNameAddr, SMQ_ADDR_HEX_STR, SMQ_ADDR_HEX_PTR(addr)) == sizeof(addr))
937  {
938  searchHostMac = true;
939  }
940  }
941 
942  bool found = false;
943  smq_id topicID = WSID32(topic);
944  for (SMQHost* host = sHostHead; host != nullptr; host = host->fNext)
945  {
946  // If host name is specified and does not match advance to next host
947  if (hostNameAddr != nullptr)
948  {
949  if (!searchHostMac)
950  {
951  if (strcmp(hostNameAddr, host->fName) != 0)
952  continue;
953  }
954  else if (memcmp(addr, &host->fAddr, sizeof(addr)) != 0)
955  {
956  continue;
957  }
958  }
959  for (unsigned i = 0; i < host->fCount; i++)
960  {
961  if (host->fTopics[i] == topicID)
962  {
963  esp_now_peer_info_t peer_info;
964  memset(&peer_info, '\0', sizeof(peer_info));
965  peer_info.channel = WIFI_CHANNEL;
966  memcpy(peer_info.peer_addr, &host->fAddr, sizeof(host->fAddr));
967  peer_info.ifidx = WIFI_IF_STA;
968  peer_info.encrypt = true;
969  memcpy(peer_info.lmk, host->fLMK.fData, sizeof(host->fLMK.fData));
970  SMQ_DEBUG_PRINTF("ADD %s PEER: %s [LMK:%s]\n", host->getHostName().c_str(), host->getHostAddress().c_str(), host->getHostKey().c_str());
971  if (esp_now_add_peer(&peer_info) == ESP_OK)
972  {
973  if (!found)
974  {
975  sSendAddr = host->fAddr.fData;
976  found = true;
977  }
978  else
979  {
980  sSendAddr = nullptr;
981  }
982  }
983  else
984  {
985  SMQ_DEBUG_PRINTF("Failed to register peer\n");
986  }
987  }
988  }
989  }
990  if (found)
991  {
992  SMQ::send_start(topic);
993  return true;
994  }
995  return false;
996  }
997 
999  {
1000  return sSMQFromAddr;
1001  }
1002 
1003  static bool broadcastTopic(smq_id topic)
1004  {
1005  sSendAddr = sBroadcastMAC;
1006  if (clearToSend())
1007  {
1008  clearAllPeers();
1009  if (addBroadcastPeer())
1010  {
1011  SMQ::send_start(topic);
1012  return true;
1013  }
1014  }
1015  return false;
1016  }
1017 
1018  static bool broadcastPairedTopic(smq_id topic)
1019  {
1020  sSendAddr = nullptr;
1021  if (clearToSend())
1022  {
1023  clearAllPeers();
1024  if (addPairedPeers())
1025  {
1026  SMQ::send_start(topic);
1027  return true;
1028  }
1029  }
1030  return false;
1031  }
1032 
1033  static bool addPairedPeers()
1034  {
1035  clearAllPeers();
1036  for (unsigned i = 0; i < sSMQPairedHostsCount; i++)
1037  {
1038  // printf("Listening to [%d] %s\n", i, sSMQPairedHosts[i].toString().c_str());
1039  esp_now_peer_info_t peer_info;
1040  memset(&peer_info, '\0', sizeof(peer_info));
1041  peer_info.channel = WIFI_CHANNEL;
1042  SMQAddressKey* host = &sSMQPairedHosts[i];
1043  // uint8_t* fAddr = sSMQPairedHosts[i].fAddr;
1044  // printf("PAIR %02X:%02X:%02X:%02X:%02X:%02X sizeof=%d\n",
1045  // fAddr[0], fAddr[1], fAddr[2], fAddr[3], fAddr[4], fAddr[5],
1046  // sizeof(sSMQPairedHosts[i]));
1047  memcpy(peer_info.peer_addr, &host->fAddr, sizeof(host->fAddr));
1048  peer_info.ifidx = WIFI_IF_STA;
1049  peer_info.encrypt = true;
1050  memcpy(peer_info.lmk, host->fLMK.fData, sizeof(host->fLMK.fData));
1051  SMQ_DEBUG_PRINTF("ADD PEER: %s [LMK:%s]\n", host->fAddr.toString().c_str(), host->fLMK.toString().c_str());
1052  esp_err_t status = esp_now_add_peer(&peer_info);
1053  if (ESP_OK != status)
1054  {
1055  SMQ_DEBUG_PRINTF("esp_now_add_peer status=%d\n", status);
1056  SMQ_DEBUG_PRINTLN("Could not add peer");
1057  // handle_error(status);
1058  return false;
1059  }
1060  }
1061  return true;
1062  }
1063 
1064  static void send_end()
1065  {
1066  uint8_t delim = 0xFF;
1067  send_raw_bytes(&delim, sizeof(delim));
1068 
1069  // printf(" - len=%d\n", sSendPtr - sSendBuffer);
1070  sClearToSend = false;
1071  esp_err_t status = esp_now_send(sSendAddr, sSendBuffer, sSendPtr - sSendBuffer);
1072  switch (status)
1073  {
1074  case ESP_ERR_ESPNOW_NOT_INIT:
1075  SMQ_DEBUG_PRINTLN("Not init");
1076  break;
1077  case ESP_ERR_ESPNOW_ARG:
1078  SMQ_DEBUG_PRINTLN("Invalid arg");
1079  break;
1080  case ESP_ERR_ESPNOW_INTERNAL:
1081  SMQ_DEBUG_PRINTLN("Internal error");
1082  break;
1083  case ESP_ERR_ESPNOW_NO_MEM:
1084  SMQ_DEBUG_PRINTLN("No mem");
1085  break;
1086  case ESP_ERR_ESPNOW_NOT_FOUND:
1087  SMQ_DEBUG_PRINTLN("Not found");
1088  break;
1089  case ESP_ERR_ESPNOW_IF:
1090  SMQ_DEBUG_PRINTLN("Interface mismatch");
1091  break;
1092  case ESP_OK:
1093  break;
1094  }
1095  if (status != ESP_OK)
1096  {
1097  SMQ_DEBUG_PRINTF("esp_now_send: %d\n", status);
1098  sClearToSend = true;
1099  }
1100  sSendPtr = sSendBuffer;
1101  }
1102 
1103  static void sendEnd()
1104  {
1105  send_end();
1106  }
1107 
1108  class Message;
1109  typedef void (*MessageHandler)(Message& msg);
1110 
1197  class Message
1199  {
1200  public:
1201  Message(smq_id topic, MessageHandler handler) :
1202  fTopic(topic),
1203  fHandler(handler)
1204  {
1205  fNext = *tail();
1206  *tail() = this;
1207  }
1208 
1209  long get_integer(const msg_id keyID)
1210  {
1211  if (find_key(keyID))
1212  {
1213  return get_integer_worker();
1214  }
1215  fMType = -1;
1216  return 0;
1217  }
1218 
1219  long get_integer(const char* key)
1220  {
1221  if (key == NULL || find_key(WSID16(key)))
1222  {
1223  return get_integer_worker();
1224  }
1225  fMType = -1;
1226  return 0;
1227  }
1228 
1229  long get_integer(PROGMEMString key)
1230  {
1231  if (key == NULL || find_key(key))
1232  {
1233  return get_integer_worker();
1234  }
1235  fMType = -1;
1236  return 0;
1237  }
1238 
1239  double get_double(const msg_id keyID)
1240  {
1241  if (find_key(keyID))
1242  {
1243  return get_double_worker();
1244  }
1245  fMType = -1;
1246  return 0;
1247  }
1248 
1249  double get_double(const char* key)
1250  {
1251  if (key == NULL || find_key(key))
1252  {
1253  return get_double_worker();
1254  }
1255  fMType = -1;
1256  return 0;
1257  }
1258 
1259  double get_double(PROGMEMString key)
1260  {
1261  if (key == NULL || find_key(key))
1262  {
1263  return get_double_worker();
1264  }
1265  fMType = -1;
1266  return 0;
1267  }
1268 
1269  String getString(const msg_id keyID)
1270  {
1271  char buf[250];
1272  return get_string(keyID, buf, sizeof(buf));
1273  }
1274 
1275 
1276  String getString(const char* key)
1277  {
1278  char buf[250];
1279  return get_string(key, buf, sizeof(buf));
1280  }
1281 
1282  String getString(String key)
1283  {
1284  return getString(key.c_str());
1285  }
1286 
1287  const char* get_string(const msg_id keyID, char* buffer, size_t maxlen)
1288  {
1289  if (find_key(keyID))
1290  {
1291  return get_string_worker(buffer, maxlen);
1292  }
1293 
1294  buffer[0] = '\0';
1295  fMType = -1;
1296  return NULL;
1297  }
1298 
1299  const char* get_string(const char* key, char* buffer, size_t maxlen)
1300  {
1301  if (find_key(WSID16(key)))
1302  {
1303  return get_string_worker(buffer, maxlen);
1304  }
1305  buffer[0] = '\0';
1306  fMType = -1;
1307  return NULL;
1308  }
1309 
1310  const char* get_string(PROGMEMString key, char* buffer, size_t maxlen)
1311  {
1312  if (key == NULL || find_key(key))
1313  {
1314  return get_string_worker(buffer, maxlen);
1315  }
1316  buffer[0] = '\0';
1317  fMType = -1;
1318  return NULL;
1319  }
1320 
1321  bool get_boolean(const msg_id key)
1322  {
1323  return (bool)get_integer(key);
1324  }
1325  bool get_boolean(const char* key)
1326  {
1327  return (bool)get_integer(key);
1328  }
1329  bool get_boolean(PROGMEMString key)
1330  {
1331  return (bool)get_integer(key);
1332  }
1333  int8_t get_int8(const msg_id key)
1334  {
1335  return (int8_t)get_integer(key);
1336  }
1337  int8_t get_int8(const char* key)
1338  {
1339  return (int8_t)get_integer(key);
1340  }
1341  int8_t get_int8(PROGMEMString key)
1342  {
1343  return (int8_t)get_integer(key);
1344  }
1345  int16_t get_int16(const msg_id key)
1346  {
1347  return (int16_t)get_integer(key);
1348  }
1349  int16_t get_int16(const char* key)
1350  {
1351  return (int16_t)get_integer(key);
1352  }
1353  int16_t get_int16(PROGMEMString key)
1354  {
1355  return (int16_t)get_integer(key);
1356  }
1357  int32_t get_int32(const msg_id key)
1358  {
1359  return (int16_t)get_integer(key);
1360  }
1361  int32_t get_int32(const char* key)
1362  {
1363  return (int16_t)get_integer(key);
1364  }
1365  int32_t get_int32(PROGMEMString key)
1366  {
1367  return (int16_t)get_integer(key);
1368  }
1369  uint8_t get_uint8(const msg_id key)
1370  {
1371  return (uint8_t)get_integer(key);
1372  }
1373  uint8_t get_uint8(const char* key)
1374  {
1375  return (uint8_t)get_integer(key);
1376  }
1377  uint8_t get_uint8(PROGMEMString key)
1378  {
1379  return (uint8_t)get_integer(key);
1380  }
1381  uint16_t get_uint16(const uint16_t key)
1382  {
1383  return (uint16_t)get_integer(key);
1384  }
1385  uint16_t get_uint16(const char* key)
1386  {
1387  return (uint16_t)get_integer(key);
1388  }
1389  uint16_t get_uint16(PROGMEMString key)
1390  {
1391  return (uint16_t)get_integer(key);
1392  }
1393  uint32_t get_uint32(const msg_id key)
1394  {
1395  return (uint32_t)get_integer(key);
1396  }
1397  uint32_t get_uint32(const char* key)
1398  {
1399  return (uint32_t)get_integer(key);
1400  }
1401  uint32_t get_uint32(PROGMEMString key)
1402  {
1403  return (uint32_t)get_integer(key);
1404  }
1405  float get_float(const msg_id key)
1406  {
1407  return (float)get_double(key);
1408  }
1409  float get_float(const char* key)
1410  {
1411  return (float)get_double(key);
1412  }
1413  float get_float(PROGMEMString key)
1414  {
1415  return (float)get_double(key);
1416  }
1417 
1418  void end()
1419  {
1420  while (!fEOM)
1421  {
1422  find_key(static_cast<const char*>(NULL));
1423  }
1424  }
1425 
1426  private:
1427  bool find_key(const msg_id keyID)
1428  {
1429  while (!fEOM)
1430  {
1431  bool match = false;
1432  uint8_t t = read_uint8();
1433  switch (t)
1434  {
1435  case 0x00:
1436  {
1437  // String
1438  // DEBUG_PRINTLN("[KEYSTRING]");
1439  uint16_t lencrc = read_uint16();
1440  uint16_t len = read_uint16();
1441  // TODO verify lencrc
1442  UNUSED_ARG(lencrc);
1443 
1444  uint16_t crc = read_uint16();
1445  uint16_t recrc = 0;
1446  while (len-- > 0)
1447  {
1448  int8_t ch = read_int8();
1449  recrc = update_crc(recrc, ch);
1450  }
1451  if (recrc == crc)
1452  {
1453  match = (crc == keyID);
1454  }
1455  // else
1456  // {
1457  // DEBUG_PRINT("crc=");
1458  // DEBUG_PRINT_HEX(crc);
1459  // DEBUG_PRINT(" expected=");
1460  // DEBUG_PRINT_HEX(recrc);
1461  // DEBUG_PRINTLN("CRC BAD4");
1462  // DEBUG_FLUSH();
1463  // }
1464  break;
1465  }
1466  case 0x01:
1467  {
1468  // Hash
1469  // DEBUG_PRINTLN("[KEYCRC]");
1470  uint16_t crc = read_uint16();
1471  match = (keyID == crc);
1472  break;
1473  }
1474  case 0xFF:
1475  // EOM
1476  fEOM = true;
1477  return false;
1478  default:
1479  DEBUG_PRINTLN("BAD MSG");
1480  return false;
1481  }
1482  fMType = read_uint8();
1483  if (match)
1484  return true;
1485 
1486  // skip value
1487  get_integer_worker();
1488  }
1489  return false;
1490  }
1491 
1492  bool find_key(const char* key)
1493  {
1494  unsigned keylen = (key != NULL) ? strlen(key) : 0;
1495  while (!fEOM)
1496  {
1497  bool match = false;
1498  uint8_t t = read_uint8();
1499  switch (t)
1500  {
1501  case 0x00:
1502  {
1503  // String
1504  DEBUG_PRINTLN("[KEYSTRING]");
1505  uint16_t lencrc = read_uint16();
1506  uint16_t len = read_uint16();
1507  // TODO verify lencrc
1508  UNUSED_ARG(lencrc);
1509 
1510  uint16_t crc = read_uint16();
1511  uint16_t recrc = 0;
1512  const char* k = key;
1513  match = (keylen == len);
1514  while (len-- > 0)
1515  {
1516  int8_t ch = read_int8();
1517  DEBUG_PRINT((char)ch);
1518  DEBUG_PRINT(" - ");
1519  if (k != NULL)
1520  {
1521  DEBUG_PRINTLN((char)*k);
1522  }
1523  recrc = update_crc(recrc, ch);
1524  if (match && *k++ != ch)
1525  match = false;
1526  }
1527  DEBUG_PRINT("pmatch=");
1528  DEBUG_PRINTLN(match);
1529  if (recrc != crc)
1530  {
1531  DEBUG_PRINT("crc=");
1532  DEBUG_PRINT_HEX(crc);
1533  DEBUG_PRINT(" expected=");
1534  DEBUG_PRINT_HEX(recrc);
1535  DEBUG_PRINTLN("CRC BAD4");
1536  DEBUG_FLUSH();
1537  }
1538  break;
1539  }
1540  case 0x01:
1541  {
1542  // Hash
1543  DEBUG_PRINTLN("[KEYCRC]");
1544  uint16_t crc = read_uint16();
1545  uint16_t keycrc = 0xFFFF;
1546  const uint8_t* b = (uint8_t*)key;
1547  const uint8_t* buf_end = (uint8_t*)key + keylen;
1548  while (b < buf_end)
1549  {
1550  keycrc = update_crc(keycrc, *b++);
1551  }
1552  match = (keylen != 0 && keycrc == crc);
1553  break;
1554  }
1555  case 0xFF:
1556  // EOM
1557  fEOM = true;
1558  return false;
1559  default:
1560  DEBUG_PRINTLN("BAD MSG");
1561  return false;
1562  }
1563  fMType = read_uint8();
1564  if (match)
1565  return true;
1566 
1567  // skip value
1568  get_integer_worker();
1569  }
1570  return false;
1571  }
1572 
1573  bool find_key(PROGMEMString keyP)
1574  {
1575  const char* key = (const char*)keyP;
1576  unsigned keylen = (key != NULL) ? strlen_P(key) : 0;
1577  while (!fEOM)
1578  {
1579  bool match = false;
1580  uint8_t t = read_uint8();
1581  switch (t)
1582  {
1583  case 0x00:
1584  {
1585  // String
1586  DEBUG_PRINTLN("[KEYSTRING]");
1587  uint16_t lencrc = read_uint16();
1588  uint16_t len = read_uint16();
1589  // TODO verify lencrc
1590  UNUSED_ARG(lencrc);
1591 
1592  uint16_t crc = read_uint16();
1593  uint16_t recrc = 0;
1594  const char* k = key;
1595  match = (keylen == len);
1596  while (len-- > 0)
1597  {
1598  int8_t ch = read_int8();
1599  DEBUG_PRINT((char)ch);
1600  DEBUG_PRINT(" - ");
1601  if (k != NULL)
1602  {
1603  DEBUG_PRINTLN((char)*k);
1604  }
1605  recrc = update_crc(recrc, ch);
1606  if (match && pgm_read_byte(k++) != ch)
1607  match = false;
1608  }
1609  DEBUG_PRINT("[match=");
1610  DEBUG_PRINTLN(match);
1611  if (recrc != crc)
1612  {
1613  DEBUG_PRINT("crc=");
1614  DEBUG_PRINT_HEX(crc);
1615  DEBUG_PRINT(" expected=");
1616  DEBUG_PRINT_HEX(recrc);
1617  DEBUG_PRINTLN("CRC BAD4");
1618  DEBUG_FLUSH();
1619  }
1620  break;
1621  }
1622  case 0x01:
1623  {
1624  // Hash
1625  DEBUG_PRINTLN("[KEYCRC]");
1626  uint16_t crc = read_uint16();
1627  uint16_t keycrc = 0xFFFF;
1628  const uint8_t* b = (uint8_t*)key;
1629  const uint8_t* buf_end = (uint8_t*)key + keylen;
1630  while (b < buf_end)
1631  {
1632  keycrc = update_crc(keycrc, pgm_read_byte(b++));
1633  }
1634  match = (keylen != 0 && keycrc == crc);
1635  break;
1636  }
1637  case 0xFF:
1638  // EOM
1639  fEOM = true;
1640  return false;
1641  default:
1642  DEBUG_PRINTLN("BAD MSG");
1643  return false;
1644  }
1645  fMType = read_uint8();
1646  if (match)
1647  return true;
1648 
1649  // skip value
1650  get_integer_worker();
1651  }
1652  return false;
1653  }
1654 
1655  long get_integer_worker()
1656  {
1657  long ret = 0;
1658  switch (fMType)
1659  {
1660  case 0x00:
1661  {
1662  // Skip String
1663  uint16_t lencrc = read_uint16();
1664  uint16_t len = read_uint16();
1665  // TODO verify lencrc
1666  UNUSED_ARG(lencrc);
1667 
1668  uint16_t crc = read_uint16();
1669  uint16_t recrc = 0;
1670  while (len-- > 0)
1671  {
1672  uint8_t ch = read_uint8();
1673  recrc = update_crc(recrc, ch);
1674  }
1675  if (recrc != crc)
1676  {
1677  DEBUG_PRINTLN("CRC BAD1");
1678  }
1679  break;
1680  }
1681  case 0x01:
1682  {
1683  // Skip Hash
1684  uint16_t crc = read_uint16();
1685  UNUSED_ARG(crc);
1686  break;
1687  }
1688  case 0x02:
1689  {
1690  // int8
1691  uint16_t crc = read_uint16();
1692  int8_t val = read_int8();
1693  uint16_t recrc = 0;
1694  for (unsigned i = 0; i < sizeof(val); i++)
1695  {
1696  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1697  }
1698  if (recrc == crc)
1699  ret = val;
1700  break;
1701  }
1702  case 0x03:
1703  {
1704  // int16
1705  uint16_t crc = read_uint16();
1706  int16_t val = read_int16();
1707  uint16_t recrc = 0;
1708  for (unsigned i = 0; i < sizeof(val); i++)
1709  {
1710  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1711  }
1712  if (recrc == crc)
1713  ret = val;
1714  break;
1715  }
1716  case 0x04:
1717  {
1718  // int32
1719  uint16_t crc = read_uint16();
1720  int32_t val = read_int32();
1721  uint16_t recrc = 0;
1722  for (unsigned i = 0; i < sizeof(val); i++)
1723  {
1724  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1725  }
1726  if (recrc == crc)
1727  ret = val;
1728  break;
1729  }
1730  case 0x05:
1731  {
1732  // uint8
1733  uint16_t crc = read_uint16();
1734  uint8_t val = read_uint8();
1735  uint16_t recrc = 0;
1736  for (unsigned i = 0; i < sizeof(val); i++)
1737  {
1738  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1739  }
1740  if (recrc == crc)
1741  ret = val;
1742  break;
1743  }
1744  case 0x06:
1745  {
1746  // uint16
1747  uint16_t crc = read_uint16();
1748  uint16_t val = read_uint16();
1749  uint16_t recrc = 0;
1750  for (unsigned i = 0; i < sizeof(val); i++)
1751  {
1752  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1753  }
1754  if (recrc == crc)
1755  ret = val;
1756  break;
1757  }
1758  case 0x07:
1759  {
1760  // uint32
1761  uint16_t crc = read_uint16();
1762  uint32_t val = read_uint32();
1763  uint16_t recrc = 0;
1764  for (unsigned i = 0; i < sizeof(val); i++)
1765  {
1766  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1767  }
1768  if (recrc == crc)
1769  ret = val;
1770  break;
1771  }
1772  case 0x08:
1773  {
1774  // uint32
1775  uint16_t crc = read_uint16();
1776  float val = read_float();
1777  uint16_t recrc = 0;
1778  for (unsigned i = 0; i < sizeof(val); i++)
1779  {
1780  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1781  }
1782  if (recrc == crc)
1783  ret = (long)val;
1784  break;
1785  }
1786  case 0x09:
1787  {
1788  // double
1789  uint16_t crc = read_uint16();
1790  double val = read_double();
1791  uint16_t recrc = 0;
1792  for (unsigned i = 0; i < sizeof(val); i++)
1793  {
1794  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1795  }
1796  if (recrc == crc)
1797  ret = (long)val;
1798  break;
1799  }
1800  case 0x0A:
1801  // true
1802  ret = true;
1803  break;
1804  case 0x0B:
1805  // false
1806  ret = false;
1807  break;
1808  case 0x0C:
1809  // null
1810  ret = 0;
1811  break;
1812  case 0x0D:
1813  // buffer
1814  break;
1815  case 0xFF:
1816  // EOM
1817  fEOM = true;
1818  break;
1819  }
1820  return ret;
1821  }
1822 
1823  double get_double_worker()
1824  {
1825  double ret = 0;
1826  switch (fMType)
1827  {
1828  case 0x00:
1829  {
1830  // Skip String
1831  uint16_t lencrc = read_uint16();
1832  uint16_t len = read_uint16();
1833  // TODO verify lencrc
1834  UNUSED_ARG(lencrc);
1835 
1836  uint16_t crc = read_uint16();
1837  uint16_t recrc = 0;
1838  while (len-- > 0)
1839  {
1840  uint8_t ch = read_uint8();
1841  recrc = update_crc(recrc, ch);
1842  }
1843  if (recrc != crc)
1844  {
1845  DEBUG_PRINTLN("CRC BAD2");
1846  }
1847  break;
1848  }
1849  case 0x01:
1850  {
1851  // Skip Hash
1852  uint16_t crc = read_uint16();
1853  UNUSED_ARG(crc)
1854  break;
1855  }
1856  case 0x02:
1857  {
1858  // int8
1859  uint16_t crc = read_uint16();
1860  int8_t val = read_int8();
1861  uint16_t recrc = 0;
1862  for (unsigned i = 0; i < sizeof(val); i++)
1863  {
1864  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1865  }
1866  if (recrc == crc)
1867  ret = val;
1868  break;
1869  }
1870  case 0x03:
1871  {
1872  // int16
1873  uint16_t crc = read_uint16();
1874  int16_t val = read_int16();
1875  uint16_t recrc = 0;
1876  for (unsigned i = 0; i < sizeof(val); i++)
1877  {
1878  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1879  }
1880  if (recrc == crc)
1881  ret = val;
1882  break;
1883  }
1884  case 0x04:
1885  {
1886  // int32
1887  uint16_t crc = read_uint16();
1888  int32_t val = read_int32();
1889  uint16_t recrc = 0;
1890  for (unsigned i = 0; i < sizeof(val); i++)
1891  {
1892  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1893  }
1894  if (recrc == crc)
1895  ret = val;
1896  break;
1897  }
1898  case 0x05:
1899  {
1900  // uint8
1901  uint16_t crc = read_uint16();
1902  uint8_t val = read_uint8();
1903  uint16_t recrc = 0;
1904  for (unsigned i = 0; i < sizeof(val); i++)
1905  {
1906  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1907  }
1908  if (recrc == crc)
1909  ret = val;
1910  break;
1911  }
1912  case 0x06:
1913  {
1914  // uint16
1915  uint16_t crc = read_uint16();
1916  uint16_t val = read_uint16();
1917  uint16_t recrc = 0;
1918  for (unsigned i = 0; i < sizeof(val); i++)
1919  {
1920  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1921  }
1922  if (recrc == crc)
1923  ret = val;
1924  break;
1925  }
1926  case 0x07:
1927  {
1928  // uint32
1929  uint16_t crc = read_uint16();
1930  uint32_t val = read_uint32();
1931  uint16_t recrc = 0;
1932  for (unsigned i = 0; i < sizeof(val); i++)
1933  {
1934  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1935  }
1936  if (recrc == crc)
1937  ret = val;
1938  break;
1939  }
1940  case 0x08:
1941  {
1942  // uint32
1943  uint16_t crc = read_uint16();
1944  float val = read_float();
1945  uint16_t recrc = 0;
1946  for (unsigned i = 0; i < sizeof(val); i++)
1947  {
1948  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1949  }
1950  if (recrc == crc)
1951  ret = val;
1952  break;
1953  }
1954  case 0x09:
1955  {
1956  // double
1957  uint16_t crc = read_uint16();
1958  double val = read_double();
1959  uint16_t recrc = 0;
1960  for (unsigned i = 0; i < sizeof(val); i++)
1961  {
1962  recrc = update_crc(recrc, ((uint8_t*)&val)[i]);
1963  }
1964  if (recrc == crc)
1965  ret = val;
1966  break;
1967  }
1968  case 0x0A:
1969  // true
1970  ret = true;
1971  break;
1972  case 0x0B:
1973  // false
1974  ret = false;
1975  break;
1976  case 0x0C:
1977  // null
1978  ret = 0;
1979  break;
1980  case 0x0D:
1981  // buffer
1982  break;
1983  case 0xFF:
1984  // EOM
1985  fEOM = true;
1986  break;
1987  }
1988  return ret;
1989  }
1990 
1991  const char* get_string_worker(char* buffer, size_t maxlen)
1992  {
1993  const char* ret = NULL;
1994  switch (fMType)
1995  {
1996  case 0x00:
1997  {
1998  // Skip String
1999  uint16_t lencrc = read_uint16();
2000  uint16_t len = read_uint16();
2001  // TODO verify lencrc
2002  UNUSED_ARG(lencrc);
2003 
2004  uint16_t crc = read_uint16();
2005  uint16_t recrc = 0;
2006  char* b = buffer;
2007 
2008  // DEBUG_PRINT("crc : "); DEBUG_PRINTLN_HEX(crc);
2009  // DEBUG_PRINT("len : "); DEBUG_PRINTLN(len);
2010  while (len-- > 0)
2011  {
2012  uint8_t ch = read_uint8();
2013  if (maxlen > 0)
2014  {
2015  *b = ch;
2016  if (maxlen - 1 > 0)
2017  b++;
2018  *b = '\0';
2019  // DEBUG_PRINT("str : "); DEBUG_PRINTLN(buffer);
2020  maxlen--;
2021  }
2022  recrc = update_crc(recrc, ch);
2023  }
2024  // DEBUG_PRINT("recrc : "); DEBUG_PRINTLN_HEX(recrc);
2025  if (recrc == crc)
2026  {
2027  ret = buffer;
2028  }
2029  else
2030  {
2031  buffer[0] = '\0';
2032  // DEBUG_PRINTLN("CRC BAD3");
2033  }
2034  break;
2035  }
2036  default:
2037  {
2038  // skip value
2039  get_integer_worker();
2040  break;
2041  }
2042  }
2043  return ret;
2044  }
2045 
2046  static void process(SMQRecvMsg* smsg)
2047  {
2048  smq_id recvTopicID = read_uint32();
2049  // printf("recvTopicID: 0x%08X\n", recvTopicID);
2050  uint32_t keyHash = read_uint32();
2051  if (keyHash == sKeyHash)
2052  {
2053  // PAIR is like BEACON just unencrypted
2054  if (recvTopicID == sSMQPAIRING_ID && !sSMQPairingMode)
2055  {
2056  SMQ_DEBUG_PRINTLN("Received PAIRING but not in PAIRING mode. Ignored.");
2057  }
2058  else if (recvTopicID == sSMQBEACON_ID || recvTopicID == sSMQPAIRING_ID)
2059  {
2060  char name[SMQ_MAX_HOST_NAME];
2061  read_buffer((uint8_t*)name, sizeof(name), sizeof(name));
2062  name[sizeof(name)-1] = '\0';
2063 
2064  SMQLMK key;
2065  uint8_t count = read_uint8();
2066  SMQHost* host = getHost(smsg->fAddr, count);
2067  if (recvTopicID == sSMQPAIRING_ID)
2068  {
2069  read_buffer(key.fData, sizeof(key.fData), sizeof(key.fData));
2070  SMQ_DEBUG_PRINTF("RECEIVED KEY: %s\n", key.toString().c_str());
2071  if (host != nullptr)
2072  {
2073  memcpy(host->fLMK.fData, &key, sizeof(key));
2074  }
2075  }
2076  // if (recvTopicID == sSMQBEACON_ID)
2077  // {
2078  // printf("BEACON [0x%08X]\n", recvTopicID);
2079  // }
2080  // else if (recvTopicID == sSMQPAIRING_ID)
2081  // {
2082  // printf("PAIRING [0x%08X]\n", recvTopicID);
2083  // }
2084  if (host != nullptr)
2085  {
2086  // Check if host name has been set and if not initialize
2087  // printf("FOUND HOST \"%s\" paired=%d\n", host->fName, host->fPaired);
2088  if (strcmp(host->fName, name) != 0 ||
2089  (recvTopicID == sSMQBEACON_ID && host->fPaired) ||
2090  (recvTopicID == sSMQPAIRING_ID && !host->fPaired))
2091  {
2092  // Need to initialize host entry
2093  strcpy(host->fName, name);
2094  host->fCount = count;
2095  host->fPaired = false;
2096  // printf("TOPIC COUNT=%d\n", count);
2097  for (unsigned i = 0; i < count; i++)
2098  {
2099  smq_id topic;
2100  read_buffer((uint8_t*)&topic, sizeof(topic), sizeof(topic));
2101  // printf("READING [0x%08X]\n", topic);
2102  host->fTopics[i] = topic;
2103  }
2104  if (recvTopicID == sSMQPAIRING_ID && sPairingEvent != nullptr)
2105  {
2106  if (sSMQPairingMode)
2107  {
2108  // Ensure we send at least one PAIR event
2109  Message::sendPair();
2110  sPairingEvent(host);
2111  host->fPaired = true;
2112  // pruneHost(host, false);
2113  }
2114  }
2115  else if (recvTopicID == sSMQBEACON_ID && sDiscoverEvent != nullptr)
2116  {
2117  sDiscoverEvent(host);
2118  }
2119  }
2120  host->fLastSeen = millis();
2121  }
2122  else
2123  {
2124  printf("HOST NOT FOUND: %s\n", name);
2125  }
2126  }
2127  else
2128  {
2129  // printf("recvTopicID: 0x%08X\n", recvTopicID);
2130  memcpy(sSMQFromAddr.fData, smsg->fAddr, sizeof(smsg->fAddr));
2131  for (Message* msg = *tail(); msg != NULL; msg = msg->fNext)
2132  {
2133  // smq_id topicID = (sizeof(smq_id) == sizeof(uint32_t)) ?
2134  // pgm_read_dword(&msg->fTopic) : pgm_read_word(&msg->fTopic);
2135  smq_id topicID = msg->fTopic;
2136  if (recvTopicID == topicID)
2137  {
2138  // SMQ_DEBUG_PRINT("PROCESS: "); SMQ_DEBUG_PRINTLN_HEX(recvTopicID);
2139  msg->fMType = -1;
2140  msg->fEOM = false;
2141  // DEBUG_PRINTLN("CALLING MSG");
2142  // DEBUG_PRINT("fHandler=");
2143  // DEBUG_PRINTLN_HEX((size_t)msg->fHandler);
2144  msg->fHandler(*msg);
2145  msg->end();
2146  break;
2147  }
2148  }
2149  }
2150  }
2151  }
2152 
2153  static void sendPair()
2154  {
2155  uint8_t count = 0;
2156  for (Message* msg = *tail(); msg != NULL; msg = msg->fNext)
2157  count++;
2158  if (broadcastTopic(sSMQPAIRING_ID))
2159  {
2160  send_raw_bytes(&sHostName, sizeof(sHostName));
2161  send_raw_bytes(&count, sizeof(count));
2162  send_raw_bytes(&sSMQLMK, sizeof(sSMQLMK));
2163  for (Message* msg = *tail(); msg != NULL; msg = msg->fNext)
2164  {
2165  smq_id topicID = msg->fTopic;
2166  send_raw_bytes(&topicID, sizeof(topicID));
2167  }
2168  send_end();
2169  }
2170  else
2171  {
2172  SMQ_DEBUG_PRINTLN("FAILED TO SEND PAIRING");
2173  }
2174  }
2175 
2176  static void sendBeacon()
2177  {
2178  uint8_t count = 0;
2179  for (Message* msg = *tail(); msg != NULL; msg = msg->fNext)
2180  count++;
2181  if (broadcastPairedTopic(sSMQBEACON_ID))
2182  {
2183  send_raw_bytes(&sHostName, sizeof(sHostName));
2184  send_raw_bytes(&count, sizeof(count));
2185  for (Message* msg = *tail(); msg != NULL; msg = msg->fNext)
2186  {
2187  smq_id topicID = msg->fTopic;
2188  send_raw_bytes(&topicID, sizeof(topicID));
2189  }
2190  send_end();
2191  }
2192  }
2193 
2194  smq_id fTopic;
2195  MessageHandler fHandler;
2196  Message* fNext;
2197  bool fEOM = true;
2198  int fMType = -1;
2199 
2200  static Message** tail()
2201  {
2202  static Message* sTail;
2203  return &sTail;
2204  }
2205  friend class SMQ;
2206  };
2207 
2208 private:
2209  static SMQHost* getHost(const uint8_t* mac_addr, uint8_t topicCount = 0)
2210  {
2211  SMQHost* host;
2212  for (host = sHostHead; host != nullptr; host = host->fNext)
2213  {
2214  if (memcmp(mac_addr, &host->fAddr, sizeof(host->fAddr)) == 0)
2215  {
2216  // Return found host
2217  return host;
2218  }
2219  }
2220  // Need to create a new host entry
2221  size_t siz = sizeof(SMQHost)+sizeof(host->fTopics[0])*topicCount;
2222  host = (SMQHost*)malloc(siz);
2223  if (host != nullptr)
2224  {
2225  memset(host, '\0', siz);
2226  memcpy(&host->fAddr, mac_addr, sizeof(host->fAddr));
2227  if (sHostHead == nullptr)
2228  {
2229  sHostHead = host;
2230  }
2231  else
2232  {
2233  sHostTail->fNext = host;
2234  }
2235  host->fPrev = sHostTail;
2236  sHostTail = host;
2237  }
2238  // Lookup the LMK for this host
2239  for (unsigned i = 0; i < sSMQPairedHostsCount; i++)
2240  {
2241  SMQAddressKey* hostKey = &sSMQPairedHosts[i];
2242  if (hostKey->fAddr.equals(host->fAddr))
2243  {
2244  host->fLMK = hostKey->fLMK;
2245  }
2246  }
2247  return host;
2248  }
2249 
2250  static void pruneHost(SMQHost* host, bool notify = true)
2251  {
2252  if (notify)
2253  sLostEvent(host);
2254 
2255  if (host->fPrev != nullptr)
2256  {
2257  host->fPrev->fNext = host->fNext;
2258  }
2259  else if (sHostHead == host)
2260  {
2261  sHostHead = host->fNext;
2262  }
2263  if (host->fNext != nullptr)
2264  {
2265  host->fNext->fPrev = host->fPrev;
2266  }
2267  else if (host == sHostTail)
2268  {
2269  sHostTail = host->fPrev;
2270  }
2271  if (host != nullptr)
2272  {
2273  host->fPrev = host->fNext = nullptr;
2274  }
2275  free(host);
2276  }
2277 
2278  static void pruneHostList()
2279  {
2280  uint32_t now = millis();
2281  SMQHost* host = sHostHead;
2282  while (host != nullptr)
2283  {
2284  SMQHost* next = host->fNext;
2285  if (host->fLastSeen + SMQ_HOST_LOST_TIMEOUT < now)
2286  {
2287  SMQHost* lostHost = host;
2288  pruneHost(lostHost);
2289  }
2290  host = next;
2291  }
2292  }
2293 
2294  static void msg_recv_cb(const uint8_t *mac_addr, const uint8_t *data, int len)
2295  {
2296  SMQRecvMsg msg;
2297  if (len < sizeof(msg.fData))
2298  {
2299  memcpy(msg.fAddr, mac_addr, sizeof(msg.fAddr));
2300  memcpy(msg.fData, data, len);
2301  msg.fSize = len;
2302  // Dont wait if queue is full. Message will be lost
2303  if (xQueueSend(sRecvQueue, &msg, 0) != pdPASS)
2304  {
2305  SMQ_DEBUG_PRINTLN("[SMQ] xQueueSend FAILED");
2306  }
2307  }
2308  }
2309 
2310  static void msg_send_cb(const uint8_t* mac, esp_now_send_status_t sendStatus)
2311  {
2312  switch (sendStatus)
2313  {
2314  case ESP_NOW_SEND_SUCCESS:
2315  // Serial.println("Send success");
2316  break;
2317 
2318  case ESP_NOW_SEND_FAIL:
2319  SMQ_DEBUG_PRINTLN("[SMQ] esp_now_send FAILED");
2320  break;
2321 
2322  default:
2323  break;
2324  }
2325  sClearToSend = true;
2326  addPairedPeers();
2327  }
2328 
2329  static inline uint16_t update_crc(uint16_t crc, const uint8_t data)
2330  {
2331  // crc-16 poly 0x8005 (x^16 + x^15 + x^2 + 1)
2332  static const PROGMEM uint16_t crc16_table[256] =
2333  {
2334  0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
2335  0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
2336  0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
2337  0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
2338  0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
2339  0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
2340  0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
2341  0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
2342  0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
2343  0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
2344  0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
2345  0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
2346  0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
2347  0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
2348  0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
2349  0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
2350  };
2351  return (crc >> 8) ^ pgm_read_word_near(&crc16_table[(crc ^ data) & 0xFF]);
2352  }
2353 
2354  static uint16_t calc_crc(const void* buf, size_t len, uint16_t crc)
2355  {
2356  const uint8_t* b = (uint8_t*)buf;
2357  const uint8_t* buf_end = (uint8_t*)buf + len;
2358  while (b < buf_end)
2359  {
2360  crc = update_crc(crc, *b++);
2361  }
2362  return crc;
2363  }
2364 
2365  static void send_raw_bytes(const void* buf, size_t len)
2366  {
2367  // Truncate on overflow
2368  if (sSendPtr + len >= &sSendBuffer[sizeof(sSendBuffer)])
2369  {
2370  printf("SMQ TRUNCATE\n");
2371  len = 0;
2372  }
2373  // for (int i = 0; i < len; i++)
2374  // {
2375  // printf("%02X ", ((uint8_t*)buf)[i]);
2376  // }
2377  memcpy(sSendPtr, buf, len);
2378  sSendPtr += len;
2379  }
2380 
2381  static void send_data(const void* buf, uint16_t len)
2382  {
2383  uint16_t crc = 0;
2384  const uint8_t* b = (uint8_t*)buf;
2385  const uint8_t* buf_end = (uint8_t*)buf + len;
2386  while (b < buf_end)
2387  {
2388  crc = update_crc(crc, *b++);
2389  }
2390  send_raw_bytes(&crc, sizeof(crc));
2391  send_raw_bytes(buf, len);
2392  }
2393 
2394  static void send_data(PROGMEMString pbuf, uint16_t len)
2395  {
2396  uint16_t crc = 0;
2397  const uint8_t* pb = (uint8_t*)pbuf;
2398  const uint8_t* pbuf_end = (uint8_t*)pbuf + len;
2399  while (pb < pbuf_end)
2400  {
2401  crc = update_crc(crc, pgm_read_byte(pb++));
2402  }
2403  send_raw_bytes(&crc, sizeof(crc));
2404  pb = (uint8_t*)pbuf;
2405  pbuf_end = (uint8_t*)pbuf + len;
2406  while (pb < pbuf_end)
2407  {
2408  byte b = pgm_read_byte(pb++);
2409  send_raw_bytes(&b, sizeof(b));
2410  }
2411  }
2412 
2413  static int read(void* buf, size_t len)
2414  {
2415  char* b = (char*)buf;
2416  char* b_end = b + len;
2417  while (b < b_end)
2418  {
2419  if (sReadLen <= 0)
2420  break;
2421  *b++ = *sReadPtr++;
2422  sReadLen--;
2423  }
2424  int cnt = b - (char*)buf;
2425  // if (cnt > 0)
2426  // {
2427  // DEBUG_PRINT(cnt); DEBUG_PRINT("<== [0x");
2428  // for (int i = 0; i < cnt; i++)
2429  // {
2430  // DEBUG_PRINT_HEX(((uint8_t*)buf)[i]);
2431  // DEBUG_PRINT(" ");
2432  // }
2433  // DEBUG_PRINTLN("]");
2434  // DEBUG_FLUSH();
2435  // }
2436  return cnt;
2437  }
2438 
2439  static int8_t read_int8()
2440  {
2441  int8_t val = 0;
2442  read(&val, sizeof(val));
2443  return val;
2444  }
2445 
2446  static int16_t read_int16()
2447  {
2448  int16_t val = 0;
2449  read(&val, sizeof(val));
2450  return val;
2451  }
2452 
2453  static int32_t read_int32()
2454  {
2455  int32_t val = 0;
2456  read(&val, sizeof(val));
2457  return val;
2458  }
2459 
2460  static uint8_t read_uint8()
2461  {
2462  uint8_t val = 0;
2463  read(&val, sizeof(val));
2464  return val;
2465  }
2466 
2467  static uint16_t read_uint16()
2468  {
2469  uint16_t val = 0;
2470  read(&val, sizeof(val));
2471  return val;
2472  }
2473 
2474  static uint32_t read_uint32()
2475  {
2476  uint32_t val = 0;
2477  read(&val, sizeof(val));
2478  return val;
2479  }
2480 
2481  static float read_float()
2482  {
2483  float val = 0;
2484  read(&val, sizeof(val));
2485  return val;
2486  }
2487 
2488  static double read_double()
2489  {
2490  double val = 0;
2491  read(&val, sizeof(val));
2492  return val;
2493  }
2494 
2495  static uint8_t* read_buffer(uint8_t* buf, uint16_t len, uint16_t bufsize)
2496  {
2497  uint8_t* p = buf;
2498  uint8_t* pend = p + min(len, bufsize);
2499  while (p < pend)
2500  {
2501  if (sReadLen <= 0)
2502  break;
2503  *p++ = *sReadPtr++;
2504  }
2505  if (len > bufsize)
2506  {
2507  /* Skip data that is bigger than our buffer */
2508  len = len - bufsize;
2509  while (len--)
2510  read_uint8();
2511  /* message was truncated and is probably not valid */
2512  return NULL;
2513  }
2514  return buf;
2515  }
2516 };
2518 
2519 typedef void (*SMQMessageHandler)(class SMQ::Message& msg);
2520 
2521 #define SMQMSG_FUNC_DECL(topic) \
2522  static void SMQHandler_##topic(SMQ::Message& msg)
2523 #define SMQMESSAGE(topic, handler) \
2524  SMQMSG_FUNC_DECL(topic); \
2525  SMQ::Message SMQMSG_##topic(STRID(#topic), SMQHandler_##topic); \
2526  SMQMSG_FUNC_DECL(topic) { UNUSED_ARG(msg) handler }
2527 
2528 #endif
SMQAddress::toString
String toString()
Definition: ReelTwoSMQ32.h:73
SMQRecvMsg
Definition: ReelTwoSMQ32.h:167
SMQ::send_string_hash
static void send_string_hash(PROGMEMString str)
Definition: ReelTwoSMQ32.h:565
SMQ_DEBUG_PRINT
#define SMQ_DEBUG_PRINT(s)
Definition: ReelTwoSMQ32.h:27
SMQHost::getHostKey
String getHostKey()
Definition: ReelTwoSMQ32.h:140
SMQ::init
static bool init(const char *hostName=nullptr, const char *key=nullptr)
Definition: ReelTwoSMQ32.h:353
SMQ::clearToSend
static bool clearToSend()
Definition: ReelTwoSMQ32.h:338
SMQRecvMsg::fData
uint8_t fData[MAX_MSG_SIZE]
Definition: ReelTwoSMQ32.h:171
SMQ::process
static void process()
Definition: ReelTwoSMQ32.h:456
SMQ::send_topic_hash
static void send_topic_hash(const char *str)
Definition: ReelTwoSMQ32.h:543
QUEUE_SIZE
#define QUEUE_SIZE
Definition: ReelTwoSMQ32.h:55
SMQLMK::equals
bool equals(uint8_t addr[16])
Definition: ReelTwoSMQ32.h:86
SMQ::send_null
static void send_null(const msg_id id)
Definition: ReelTwoSMQ32.h:866
SMQ::send_string
static void send_string(const char *key, const char *val)
Definition: ReelTwoSMQ32.h:605
SMQRecvMsg::fSize
uint8_t fSize
Definition: ReelTwoSMQ32.h:170
SMQ_MAX_HOST_NAME
#define SMQ_MAX_HOST_NAME
Definition: ReelTwoSMQ32.h:57
SMQMessageHandler
void(* SMQMessageHandler)(class SMQ::Message &msg)
Definition: ReelTwoSMQ32.h:2519
SMQAddressKey::fAddr
SMQAddress fAddr
Definition: ReelTwoSMQ32.h:110
DEBUG_PRINT
#define DEBUG_PRINT(s)
Definition: ReelTwo.h:189
SMQ::addPairedHost
static bool addPairedHost(SMQAddress *addr, SMQLMK *lmk=nullptr)
Definition: ReelTwoSMQ32.h:292
ReelTwo.h
sSMQ
SMQ sSMQ
Definition: ReelTwoSMQ32.h:2517
SMQ::send_uint8
static void send_uint8(const char *key, uint8_t val)
Definition: ReelTwoSMQ32.h:733
smq_id
uint32_t smq_id
Definition: ReelTwoSMQ32.h:52
SMQ::send_end
static void send_end()
Definition: ReelTwoSMQ32.h:1064
SMQLMK::equals
bool equals(SMQLMK &addr)
Definition: ReelTwoSMQ32.h:91
SMQ::sendTopic
static bool sendTopic(const smq_id id)
Definition: ReelTwoSMQ.h:155
SMQ::isPairing
static bool isPairing()
Definition: ReelTwoSMQ32.h:222
SMQ::send_uint32
static void send_uint32(const msg_id id, uint32_t val)
Definition: ReelTwoSMQ32.h:773
SMQ::send_double
static void send_double(const msg_id id, double val)
Definition: ReelTwoSMQ32.h:821
SMQ::sendString
static void sendString(const char *key, String val)
Definition: ReelTwoSMQ32.h:633
SMQ::send_double
static void send_double(PROGMEMString key, double val)
Definition: ReelTwoSMQ32.h:837
SMQAddressKey
Definition: ReelTwoSMQ32.h:108
SMQ::send_double
static void send_double(const char *key, double val)
Definition: ReelTwoSMQ32.h:829
smq_id
uint16_t smq_id
Definition: ReelTwoSMQ.h:42
SMQ_HOST_LOST_TIMEOUT
#define SMQ_HOST_LOST_TIMEOUT
Definition: ReelTwoSMQ32.h:41
SMQAddress
Definition: ReelTwoSMQ32.h:59
SMQ::send_uint16
static void send_uint16(const char *key, uint16_t val)
Definition: ReelTwoSMQ32.h:757
SMQ::setHostLostCallback
static void setHostLostCallback(void(*callback)(SMQHost *host))
Definition: ReelTwoSMQ32.h:333
SMQ::send_topic_id
static void send_topic_id(const smq_id id)
Definition: ReelTwoSMQ32.h:536
SMQHost::getAddress
SMQAddress * getAddress(SMQAddress *addr)
Definition: ReelTwoSMQ32.h:145
SMQ::setHostPairingCallback
static void setHostPairingCallback(void(*callback)(SMQHost *host))
Definition: ReelTwoSMQ32.h:323
SMQAddress::fData
uint8_t fData[6]
Definition: ReelTwoSMQ32.h:61
DEBUG_PRINTLN
#define DEBUG_PRINTLN(s)
Definition: ReelTwo.h:188
SMQ::send_start
static void send_start(PROGMEMString str)
Definition: ReelTwoSMQ32.h:593
SMQ::send_string_id
static void send_string_id(const msg_id id)
Definition: ReelTwoSMQ32.h:529
SMQHost::fPrev
SMQHost * fPrev
Definition: ReelTwoSMQ32.h:123
SMQ::send_long
static void send_long(const msg_id id, long val)
Definition: ReelTwoSMQ32.h:715
SMQHost::fPaired
bool fPaired
Definition: ReelTwoSMQ32.h:121
SMQ::setLocalMasterKey
static void setLocalMasterKey(SMQLMK *key)
Definition: ReelTwoSMQ32.h:440
SMQ::send_boolean
static void send_boolean(const char *key, bool val)
Definition: ReelTwoSMQ32.h:852
SMQ::MessageHandler
void(* MessageHandler)(Message &msg)
Definition: ReelTwoSMQ.h:470
SMQ::sendString
static void sendString(String key, String val)
Definition: ReelTwoSMQ32.h:628
SMQHost::fName
char fName[SMQ_MAX_HOST_NAME]
Definition: ReelTwoSMQ32.h:116
SMQ_PAIRING_TIMEOUT
#define SMQ_PAIRING_TIMEOUT
Definition: ReelTwoSMQ32.h:47
SMQ::getPairedHosts
static unsigned getPairedHosts(SMQAddressKey *hosts, unsigned maxCount)
Definition: ReelTwoSMQ32.h:316
MAX_MSG_SIZE
#define MAX_MSG_SIZE
Definition: ReelTwoSMQ32.h:56
SMQ::setHostDiscoveryCallback
static void setHostDiscoveryCallback(void(*callback)(SMQHost *host))
Definition: ReelTwoSMQ32.h:328
SMQ_BEACON_BROADCAST_INTERVAL
#define SMQ_BEACON_BROADCAST_INTERVAL
Definition: ReelTwoSMQ32.h:40
SMQ::send_int32
static void send_int32(PROGMEMString key, int32_t val)
Definition: ReelTwoSMQ32.h:707
SMQ::send_int16
static void send_int16(PROGMEMString key, int16_t val)
Definition: ReelTwoSMQ32.h:683
SMQ::sendTopic
static bool sendTopic(PROGMEMString topic)
Definition: ReelTwoSMQ32.h:915
SMQHost::fTopics
smq_id fTopics[]
Definition: ReelTwoSMQ32.h:124
SMQ_HOSTNAME
#define SMQ_HOSTNAME
Definition: ReelTwoSMQ32.h:7
SMQ::send_uint32
static void send_uint32(PROGMEMString key, uint32_t val)
Definition: ReelTwoSMQ32.h:789
SMQ::send_int16
static void send_int16(const msg_id id, int16_t val)
Definition: ReelTwoSMQ32.h:667
SMQ::addPairedPeers
static bool addPairedPeers()
Definition: ReelTwoSMQ32.h:1033
DEBUG_FLUSH
#define DEBUG_FLUSH()
Definition: ReelTwo.h:193
SMQAddress::equals
bool equals(SMQAddress &addr)
Definition: ReelTwoSMQ32.h:68
SMQHost
Definition: ReelTwoSMQ32.h:114
SMQ::broadcastTopic
static bool broadcastTopic(smq_id topic)
Definition: ReelTwoSMQ32.h:1003
SMQ::send_long
static void send_long(const char *key, long val)
Definition: ReelTwoSMQ32.h:720
SMQ::send_start
static void send_start(const char *str)
Definition: ReelTwoSMQ32.h:587
SMQ::send_int16
static void send_int16(const char *key, int16_t val)
Definition: ReelTwoSMQ32.h:675
SMQ::send_start
static void send_start(const smq_id id)
Definition: ReelTwoSMQ32.h:581
SMQ::send_float
static void send_float(PROGMEMString key, float val)
Definition: ReelTwoSMQ32.h:813
SMQ::send_uint8
static void send_uint8(PROGMEMString key, uint8_t val)
Definition: ReelTwoSMQ32.h:741
SMQ::messageSender
static SMQAddress messageSender()
Definition: ReelTwoSMQ32.h:998
SMQ::stopPairing
static void stopPairing()
Definition: ReelTwoSMQ32.h:227
SMQ::sendString
static void sendString(const char *key, const char *val)
Definition: ReelTwoSMQ32.h:623
SMQ::getLocalMasterKey
static void getLocalMasterKey(SMQLMK *key)
Definition: ReelTwoSMQ32.h:445
WSID16
constexpr uint16_t WSID16(const char *str)
Definition: ReelTwo.h:343
SMQHost::hasTopic
bool hasTopic(smq_id topicID)
Definition: ReelTwoSMQ32.h:151
WSID32
constexpr uint32_t WSID32(const char *str)
Definition: ReelTwo.h:348
STRID
#define STRID(str)
Definition: ReelTwo.h:361
SMQ::send_string
static void send_string(PROGMEMString str)
Definition: ReelTwoSMQ32.h:519
WIFI_CHANNEL
#define WIFI_CHANNEL
Definition: ReelTwoSMQ32.h:54
SMQ::send_string
static void send_string(const msg_id id, const char *val)
Definition: ReelTwoSMQ32.h:599
SMQHost::fAddr
SMQAddress fAddr
Definition: ReelTwoSMQ32.h:118
SMQ
Serial Message Queue.
Definition: ReelTwoSMQ.h:54
SMQ::send_uint16
static void send_uint16(const msg_id id, uint16_t val)
Definition: ReelTwoSMQ32.h:749
SMQ::send_boolean
static void send_boolean(PROGMEMString key, bool val)
Definition: ReelTwoSMQ32.h:859
SMQHost::fNext
SMQHost * fNext
Definition: ReelTwoSMQ32.h:122
SMQ::removeBroadcastPeer
static void removeBroadcastPeer()
Definition: ReelTwoSMQ32.h:450
SMQHost::fCount
uint8_t fCount
Definition: ReelTwoSMQ32.h:117
SMQ::addPairedHosts
static void addPairedHosts(unsigned numHosts, SMQAddressKey *hosts)
Definition: ReelTwoSMQ32.h:274
SMQ_ADDR_HEX_PTR
#define SMQ_ADDR_HEX_PTR(addr)
Definition: ReelTwoSMQ32.h:36
SMQ_DEBUG_PRINTLN
#define SMQ_DEBUG_PRINTLN(s)
Definition: ReelTwoSMQ32.h:26
SMQ::clearAllPeers
static void clearAllPeers()
Definition: ReelTwoSMQ32.h:896
SMQ::send_int8
static void send_int8(const msg_id id, int8_t val)
Definition: ReelTwoSMQ32.h:643
SMQ::sendString
static void sendString(String key, const char *val)
Definition: ReelTwoSMQ32.h:638
SMQ::send_float
static void send_float(const msg_id id, float val)
Definition: ReelTwoSMQ32.h:797
SMQ::addBroadcastPeer
static bool addBroadcastPeer()
Definition: ReelTwoSMQ32.h:414
SMQ_DEBUG_PRINTF
#define SMQ_DEBUG_PRINTF(...)
Definition: ReelTwoSMQ32.h:28
SMQ_ADDR_HEX_STR
#define SMQ_ADDR_HEX_STR
Definition: ReelTwoSMQ32.h:34
SMQ::getAddress
static String getAddress()
Definition: ReelTwoSMQ32.h:343
SMQ::getPairedHostCount
static unsigned getPairedHostCount()
Definition: ReelTwoSMQ32.h:311
SMQ::send_int8
static void send_int8(const char *key, int8_t val)
Definition: ReelTwoSMQ32.h:651
SMQ_MINIMUM_KEY_LEN
#define SMQ_MINIMUM_KEY_LEN
Definition: ReelTwoSMQ32.h:44
SMQHost::fLMK
SMQLMK fLMK
Definition: ReelTwoSMQ32.h:119
SMQ::send_int32
static void send_int32(const char *key, int32_t val)
Definition: ReelTwoSMQ32.h:699
SMQ_MAX_PAIRED_HOSTS
#define SMQ_MAX_PAIRED_HOSTS
Definition: ReelTwoSMQ32.h:43
SMQAddressKey::fLMK
SMQLMK fLMK
Definition: ReelTwoSMQ32.h:111
SMQ::send_uint32
static void send_uint32(const char *key, uint32_t val)
Definition: ReelTwoSMQ32.h:781
DEBUG_PRINT_HEX
#define DEBUG_PRINT_HEX(s)
Definition: ReelTwo.h:192
SMQHost::hasTopic
bool hasTopic(const char *topic)
Definition: ReelTwoSMQ32.h:161
SMQHost::getHostName
String getHostName()
Definition: ReelTwoSMQ32.h:126
SMQ::masterKeyExchange
static int masterKeyExchange(SMQLMK *remoteKey)
Definition: ReelTwoSMQ32.h:236
SMQ::send_uint8
static void send_uint8(const msg_id id, uint8_t val)
Definition: ReelTwoSMQ32.h:725
SMQ::send_uint16
static void send_uint16(PROGMEMString key, uint16_t val)
Definition: ReelTwoSMQ32.h:765
SMQ::send_null
static void send_null(const char *key)
Definition: ReelTwoSMQ32.h:873
SMQ::send_string
static void send_string(PROGMEMString key, const char *val)
Definition: ReelTwoSMQ32.h:611
SMQ::sendTopic
static bool sendTopic(String topic, String host)
Definition: ReelTwoSMQ32.h:910
SMQ::send_string_hash
static void send_string_hash(const char *str)
Definition: ReelTwoSMQ32.h:548
SMQ::sendTopic
static bool sendTopic(const char *topic, const char *hostNameAddr=nullptr)
Definition: ReelTwoSMQ32.h:921
SMQ::send_int8
static void send_int8(PROGMEMString key, int8_t val)
Definition: ReelTwoSMQ32.h:659
SMQ::send_float
static void send_float(const char *key, float val)
Definition: ReelTwoSMQ32.h:805
PROGMEMString
const typedef __FlashStringHelper * PROGMEMString
Definition: ReelTwo.h:235
SMQHost::fLastSeen
uint32_t fLastSeen
Definition: ReelTwoSMQ32.h:120
msg_id
uint16_t msg_id
Definition: ReelTwoSMQ.h:40
SMQ::send_int32
static void send_int32(const msg_id id, int32_t val)
Definition: ReelTwoSMQ32.h:691
UNUSED_ARG
#define UNUSED_ARG(arg)
Definition: ReelTwo.h:25
SMQLMK::toString
String toString()
Definition: ReelTwoSMQ32.h:96
SMQRecvMsg::fAddr
uint8_t fAddr[6]
Definition: ReelTwoSMQ32.h:169
SMQHost::getHostAddress
String getHostAddress()
Definition: ReelTwoSMQ32.h:131
SMQ::send_boolean
static void send_boolean(const msg_id id, bool val)
Definition: ReelTwoSMQ32.h:845
SMQLMK::fData
uint8_t fData[16]
Definition: ReelTwoSMQ32.h:84
SMQ::send_null
static void send_null(PROGMEMString key)
Definition: ReelTwoSMQ32.h:880
SMQAddress::equals
bool equals(uint8_t addr[6])
Definition: ReelTwoSMQ32.h:63
SMQ::init
static bool init(String hostName, String key)
Definition: ReelTwoSMQ32.h:348
SMQ::send_string
static void send_string(const char *str)
Definition: ReelTwoSMQ.h:106
SMQ::startPairing
static void startPairing()
Definition: ReelTwoSMQ32.h:213
SMQLMK
Definition: ReelTwoSMQ32.h:82
msg_id
uint16_t msg_id
Definition: ReelTwoSMQ32.h:51
SMQ::send_string
static void send_string(PROGMEMString key, PROGMEMString val)
Definition: ReelTwoSMQ32.h:617
SMQ::createLocalMasterKey
static void createLocalMasterKey(SMQLMK *key)
Definition: ReelTwoSMQ32.h:435
SMQ::sendString
static void sendString(String str)
Definition: ReelTwoSMQ32.h:504
SMQ::broadcastPairedTopic
static bool broadcastPairedTopic(smq_id topic)
Definition: ReelTwoSMQ32.h:1018
SMQ::sendEnd
static void sendEnd()
Definition: ReelTwoSMQ32.h:1103