EnigmaIOT  0.9.8
Secure sensor and gateway platform based on ESP8266 and ESP32
EnigmaIOTNode.cpp
Go to the documentation of this file.
1 
9 //#define ESP8266
10 
11 //#ifdef ESP8266
12 #include <Arduino.h>
13 #include "EnigmaIOTNode.h"
14 #include "timeManager.h"
15 #include <FS.h>
16 #include <MD5Builder.h>
17 #ifdef ESP8266
18 #include <Updater.h>
19 #elif defined ESP32
20 #include <Update.h>
21 #include "esp_wifi.h"
22 #endif
23 #include <StreamString.h>
24 #include <ArduinoJson.h>
25 #include <regex>
26 
27 const char CONFIG_FILE[] = "/config.json";
28 
29 int localLed = -1;
30 
31 #ifdef ESP32
32 TimerHandle_t ledTimer;
33 #elif defined(ESP8266)
34 ETSTimer ledTimer;
35 #endif // ESP32
36 
38 
39 #ifdef ESP32
40 RTC_DATA_ATTR rtcmem_data_t rtcmem_data_storage;
41 #endif
42 
43 
46  sendRestart ();
47  FILESYSTEM.begin ();
48  FILESYSTEM.remove (CONFIG_FILE);
49  FILESYSTEM.end ();
50  DEBUG_WARN ("Config file %s deleted. Restarting");
51 
52  clearRTC ();
53  ESP.restart ();
54 }
55 
57  const size_t len = 2;
58  uint8_t buffer[len];
59 
60  buffer[0] = RESTART_CONFIRM;
61  buffer[1] = restartReason;
62 
63  DEBUG_WARN ("Message Len %d\n", len);
64  DEBUG_WARN ("Trying to send: %s\n", printHexBuffer (buffer, len));
65  if (!EnigmaIOTNode.sendData (buffer, len, CONTROL_TYPE)) {
66  DEBUG_WARN ("Error sending restart");
67  } else {
68  DEBUG_WARN ("Restart sent");
69  }
70  //time_t restartRequested = millis ();
71  //while (millis () - restartRequested > 200) {
72  // yield ();
73  //}
74 
75 }
76 
78  if (!node.getSleepy ()) {
79  return 0;
80  } else {
81  return rtcmem_data.sleepTime;
82  }
83 }
84 
86  return rtcmem_data.rssi;
87 }
88 
89 void EnigmaIOTNodeClass::setLed (uint8_t led, time_t onTime) {
90  this->led = led;
91  ledOnTime = onTime;
92 }
93 
95  resetPin = pin;
96 }
97 
99  memset (data->nodeKey, 0, KEY_LENGTH);
100  data->lastMessageCounter = 0;
101  data->nodeId = 0;
102  data->channel = 3;
103  memset (data->gateway, 0, 6);
104  memset (data->networkKey, 0, KEY_LENGTH);
105  data->nodeRegisterStatus = UNREGISTERED;
106  data->sleepy = false;
107  data->nodeKeyValid = false;
108  data->broadcastKeyRequested = false;
109  data->broadcastKeyValid = false;
110  DEBUG_DBG ("RTC Cleared");
111 }
112 
113 void dumpRtcData (rtcmem_data_t* data, uint8_t* gateway = NULL) {
114  Serial.println ("RTC MEM DATA:");
115  if (data) {
116  Serial.printf (" -- CRC: %s\n", printHexBuffer ((uint8_t*)&(data->crc32), sizeof (uint32_t)));
117  Serial.printf (" -- Node Key: %s\n", printHexBuffer (data->nodeKey, KEY_LENGTH));
118  Serial.printf (" -- Node key is %svalid\n", data->nodeKeyValid ? "" : "NOT ");
119  Serial.printf (" -- Node status is %d: %s\n", data->nodeRegisterStatus, data->nodeRegisterStatus == REGISTERED ? "REGISTERED" : "NOT REGISTERED");
120  Serial.printf (" -- Node name: %s\n", data->nodeName);
121  Serial.printf (" -- Last message counter: %d\n", data->lastMessageCounter);
122  Serial.printf (" -- Last control counter: %d\n", data->lastControlCounter);
123  Serial.printf (" -- Last downlink counter: %d\n", data->lastDownlinkMsgCounter);
124  Serial.printf (" -- NodeID: %d\n", data->nodeId);
125  Serial.printf (" -- Channel: %d\n", data->channel);
126  Serial.printf (" -- RSSI: %d\n", data->rssi);
127  Serial.printf (" -- Network name: %s\n", data->networkName);
128  char gwAddress[ENIGMAIOT_ADDR_LEN * 3];
129  Serial.printf (" -- Gateway: %s\n", mac2str (data->gateway, gwAddress));
130  Serial.printf (" -- Comm errors: %d\n", data->commErrors);
131  if (gateway)
132  Serial.printf (" -- Gateway address: %s\n", mac2str (gateway, gwAddress));
133  Serial.printf (" -- Network Key: %s\n", printHexBuffer (data->networkKey, KEY_LENGTH));
134  Serial.printf (" -- Mode: %s\n", data->sleepy ? "sleepy" : "non sleepy");
135  Serial.printf (" -- Broadcast key: %s\n", printHexBuffer (data->broadcastKey, KEY_LENGTH));
136  Serial.printf (" -- Broadcast key is %s and %s requested\n",
137  data->broadcastKeyValid ? "valid" : "not valid",
138  data->broadcastKeyRequested ? "is" : "is not");
139  } else {
140  Serial.println ("rtcmem_data pointer is NULL");
141  }
142 }
143 
144 #if USE_FLASH_INSTEAD_RTC
145 const char* RTC_DATA_FILE = "/context.bin";
147  //FILESYSTEM.remove (RTC_DATA_FILE); // Only for testing
148  //bool file_correct = false;
149  clock_t start_load = millis ();
150  FILESYSTEM.begin ();
151 
152  rtcmem_data_t context;
153 
154  if (FILESYSTEM.exists (RTC_DATA_FILE)) {
155  DEBUG_DBG ("Opening %s file", RTC_DATA_FILE);
156  File contextFile = FILESYSTEM.open (RTC_DATA_FILE, "r");
157  if (contextFile) {
158  DEBUG_DBG ("%s opened", RTC_DATA_FILE);
159  size_t size = contextFile.size ();
160  if (size != sizeof (rtcmem_data_t)) {
161  DEBUG_WARN ("File size error. Expected %d bytes. Got %d", sizeof (rtcmem_data_t), size);
162  contextFile.close ();
163  FILESYSTEM.remove (RTC_DATA_FILE);
164  return false;
165  }
166  size = contextFile.readBytes ((char*)&context, sizeof (rtcmem_data_t));
167  contextFile.close ();
168  if (size != sizeof (rtcmem_data_t)) {
169  DEBUG_WARN ("File read error. Expected %d bytes. Got %d", sizeof (rtcmem_data_t), size);
170  //contextFile.close ();
171  FILESYSTEM.remove (RTC_DATA_FILE);
172  return false;
173  }
174  if (!checkCRC ((uint8_t*)context.nodeKey, sizeof (rtcmem_data_t) - sizeof (uint32_t), &context.crc32)) {
175  DEBUG_WARN ("RTC Data is not valid. Wrong CRC");
176  //contextFile.close ();
177  FILESYSTEM.remove (RTC_DATA_FILE);
178  return false;
179  } else {
180  memcpy (&rtcmem_data, &context, sizeof (rtcmem_data_t));
184  node.setKeyValidFrom (millis ());
190  // setChannel (rtcmem_data.channel);
191  //channel = rtcmem_data.channel;
192  //memcpy (gateway, rtcmem_data.gateway, comm->getAddressLength ()); // setGateway
193  //memcpy (networkKey, rtcmem_data.networkKey, KEY_LENGTH);
196  // set default sleep time if it was not set
197  if (rtcmem_data.sleepy && rtcmem_data.sleepTime == 0) {
199  }
201  DEBUG_DBG ("Set %s mode", node.getSleepy () ? "sleepy" : "non sleepy");
202 #if DEBUG_LEVEL >= VERBOSE
204 #endif
205  }
206  } else {
207  DEBUG_WARN ("Error opening file %s", RTC_DATA_FILE);
208  FILESYSTEM.remove (RTC_DATA_FILE);
209  return false;
210  }
211  } else {
212  DEBUG_WARN ("%s do not exist", RTC_DATA_FILE);
213  return false;
214  }
215 
216  DEBUG_DBG ("Load process finished in %lu ms", millis () - start_load);
217 
218  return true;
219 }
220 #else
222 #ifdef ESP8266
223  if (ESP.rtcUserMemoryRead (RTC_ADDRESS, (uint32_t*)&rtcmem_data, sizeof (rtcmem_data))) {
224  DEBUG_VERBOSE ("Read RTCData: %s", printHexBuffer ((uint8_t*)&rtcmem_data, sizeof (rtcmem_data)));
225  } else {
226  DEBUG_ERROR ("Error reading RTC memory");
228  return false;
229  }
230 #elif defined ESP32
231  memcpy ((uint8_t*)&rtcmem_data, (uint8_t*)&rtcmem_data_storage, sizeof (rtcmem_data));
232  DEBUG_VERBOSE ("----- Read RTCData: %s", printHexBuffer ((uint8_t*)&rtcmem_data, sizeof (rtcmem_data)));
233 #endif
234  if (!checkCRC ((uint8_t*)rtcmem_data.nodeKey, sizeof (rtcmem_data) - sizeof (uint32_t), &rtcmem_data.crc32)) {
235  DEBUG_DBG ("RTC Data is not valid");
237  return false;
238  } else {
242  node.setKeyValidFrom (millis ());
248  // setChannel (rtcmem_data.channel);
249  //channel = rtcmem_data.channel;
250  //memcpy (gateway, rtcmem_data.gateway, comm->getAddressLength ()); // setGateway
251  //memcpy (networkKey, rtcmem_data.networkKey, KEY_LENGTH);
254  // set default sleep time if it was not set
255  if (rtcmem_data.sleepy && rtcmem_data.sleepTime == 0) {
257  }
259  DEBUG_DBG ("Set %s mode", node.getSleepy () ? "sleepy" : "non sleepy");
260 #if DEBUG_LEVEL >= VERBOSE
262 #endif
263 
264  }
265  return true;
266 
267 }
268 #endif
269 
271  //FILESYSTEM.remove (CONFIG_FILE); // Only for testing
272  bool json_correct = false;
273 
274  if (FILESYSTEM.exists (CONFIG_FILE)) {
275  DEBUG_DBG ("Opening %s file", CONFIG_FILE);
276  File configFile = FILESYSTEM.open (CONFIG_FILE, "r");
277  if (configFile) {
278  DEBUG_DBG ("%s opened", CONFIG_FILE);
279  //size_t size = configFile.size ();
280 
281  const size_t capacity = JSON_ARRAY_SIZE (32) + JSON_OBJECT_SIZE (7) + 110;
282  DynamicJsonDocument doc (capacity);
283  DeserializationError error = deserializeJson (doc, configFile);
284  if (error) {
285  DEBUG_ERROR ("Failed to parse file");
286  } else {
287  DEBUG_DBG ("JSON file parsed");
288  }
289  configFile.close ();
290 
291  if (doc.containsKey("type")){
292  if (!strcmp("node",doc["type"])) {
293  if (doc.containsKey ("networkName") && doc.containsKey ("networkKey")
294  && doc.containsKey ("sleepTime")) {
295  json_correct = true;
296  }
297  } else {
298  FILESYSTEM.remove (CONFIG_FILE);
299  DEBUG_ERROR ("Wrong configuration. Removing file %s", CONFIG_FILE);
300  return false;
301  }
302  }
303 
304  strlcpy (rtcmem_data.networkName, doc["networkName"] | "", sizeof (rtcmem_data.networkName));
305  rtcmem_data.sleepTime = doc["sleepTime"].as<int> ();
307 
308  memset (rtcmem_data.networkKey, 0, KEY_LENGTH);
309  JsonArray netKeyJson = doc["networkKey"];
310  if (netKeyJson.size () != KEY_LENGTH) {
311  DEBUG_WARN ("Error in stored network key. Expected length: %d, actual length %d", KEY_LENGTH, netKeyJson.size ());
312  return false;
313  }
314  for (int i = 0; i < KEY_LENGTH; i++) {
315  rtcmem_data.networkKey[i] = netKeyJson[i].as<int> ();
316  }
317  DEBUG_DBG ("Network Key dump: %s", printHexBuffer (rtcmem_data.networkKey, KEY_LENGTH));
318  strncpy ((char*)rtcmem_data.nodeName, doc["nodeName"] | "", NODE_NAME_LENGTH);
320 
321  uint8_t gwAddr[ENIGMAIOT_ADDR_LEN];
322  char gwAddrStr[ENIGMAIOT_ADDR_LEN * 3];
323  if (doc.containsKey ("gateway")) {
324  strncpy (gwAddrStr, doc["gateway"], sizeof (gwAddrStr));
325  str2mac (gwAddrStr, gwAddr);
326  memcpy (rtcmem_data.gateway, gwAddr, 6);
327  }
328 
329  if (json_correct) {
330  DEBUG_VERBOSE ("Configuration successfuly read");
331  }
332 
333  DEBUG_DBG ("==== EnigmaIOT Node Configuration ====");
334  DEBUG_DBG ("Network name: %s", rtcmem_data.networkName);
335  DEBUG_DBG ("Sleep time: %u", rtcmem_data.sleepTime);
336  DEBUG_DBG ("Node name: %s", rtcmem_data.nodeName);
337  DEBUG_DBG ("Gateway: %s", gwAddrStr);
338  DEBUG_VERBOSE ("Network key: %s", printHexBuffer (rtcmem_data.networkKey, KEY_LENGTH));
339 
340  String output;
341  serializeJsonPretty (doc, output);
342 
343  DEBUG_DBG ("JSON file %s", output.c_str ());
344  }
345  } else {
346  DEBUG_WARN ("%s do not exist", CONFIG_FILE);
347  }
348 
349  return json_correct;
350 }
351 
353  if (configCleared)
354  return false;
355 
356  if (!fsOpen)
357  FILESYSTEM.begin ();
358 
359  File configFile = FILESYSTEM.open (CONFIG_FILE, "w");
360  if (!configFile) {
361  DEBUG_WARN ("failed to open config file %s for writing", CONFIG_FILE);
362  return false;
363  }
364 
365  const size_t capacity = JSON_ARRAY_SIZE (32) + JSON_OBJECT_SIZE (7) + 110;
366  DynamicJsonDocument doc (capacity);
367 
368  char gwAddrStr[ENIGMAIOT_ADDR_LEN * 3];
369  mac2str (rtcmem_data.gateway, gwAddrStr);
370 
371  doc["type"] = "node";
372  doc["networkName"] = rtcmem_data.networkName;
373  JsonArray netKeyJson = doc.createNestedArray ("networkKey");
374  for (int i = 0; i < KEY_LENGTH; i++) {
375  netKeyJson.add (rtcmem_data.networkKey[i]);
376  }
377  doc["sleepTime"] = rtcmem_data.sleepTime;
378  doc["gateway"] = gwAddrStr;
379  doc["nodeName"] = rtcmem_data.nodeName;
380 
381  if (serializeJson (doc, configFile) == 0) {
382  DEBUG_ERROR ("Failed to write to file");
383  configFile.close ();
384  //FILESYSTEM.remove (CONFIG_FILE); // Testing
385  return false;
386  }
387 
388  String output;
389  serializeJsonPretty (doc, output);
390 
391  DEBUG_DBG ("%s", output.c_str ());
392 
393  configFile.flush ();
394  //size_t size = configFile.size ();
395 
396  configFile.close ();
397  DEBUG_DBG ("Configuration saved to flash. %u bytes", configFile.size ());
398 #if DEBUG_LEVEL >= DBG
400 #endif
401  if (!fsOpen)
402  FILESYSTEM.end ();
403  return true;
404 }
405 
406 #if USE_FLASH_INSTEAD_RTC
408  clock_t start_save = millis ();
409  if (configCleared)
410  return false;
411  rtcmem_data.crc32 = calculateCRC32 ((uint8_t*)rtcmem_data.nodeKey, sizeof (rtcmem_data) - sizeof (uint32_t));
412  File contextFile = FILESYSTEM.open (RTC_DATA_FILE, "w");
413  if (!contextFile) {
414  DEBUG_WARN ("failed to open config file %s for writing", RTC_DATA_FILE);
415  return false;
416  }
417  contextFile.write ((uint8_t*)&rtcmem_data, sizeof (rtcmem_data));
418  contextFile.flush ();
419  size_t size = contextFile.size ();
420  contextFile.close ();
421  DEBUG_DBG ("Write configuration data to file %s in flash. %u bytes", RTC_DATA_FILE, size);
422  DEBUG_VERBOSE ("Write RTCData: %s", printHexBuffer ((uint8_t*)&rtcmem_data, sizeof (rtcmem_data)));
423 #if DEBUG_LEVEL >= VERBOSE
425 #endif
426  DEBUG_DBG ("Save process finished in %lu ms", millis () - start_save);
427 
428  return true;
429 }
430 
431 #else
432 
434  if (configCleared)
435  return false;
436  if (protectOTA || otaRunning) {
437  DEBUG_WARN ("Cannot write to RTC memory");
438  return true;
439  }
440 #ifdef ESP8266
441  rtcmem_data.crc32 = calculateCRC32 ((uint8_t*)rtcmem_data.nodeKey, sizeof (rtcmem_data) - sizeof (uint32_t));
442  if (ESP.rtcUserMemoryWrite (RTC_ADDRESS, (uint32_t*)&rtcmem_data, sizeof (rtcmem_data))) {
443  DEBUG_DBG ("Write configuration data to RTC memory");
444 #if DEBUG_LEVEL >= VERBOSE
445  DEBUG_VERBOSE ("Write RTCData: %s", printHexBuffer ((uint8_t*)&rtcmem_data, sizeof (rtcmem_data)));
447 #endif
448  return true;
449  }
450 #elif defined ESP32
451  rtcmem_data.crc32 = calculateCRC32 ((uint8_t*)rtcmem_data.nodeKey, sizeof (rtcmem_data) - sizeof (uint32_t));
452  memcpy ((uint8_t*)&rtcmem_data_storage, (uint8_t*)&rtcmem_data, sizeof (rtcmem_data));
453  rtcmem_data_storage.crc32 = calculateCRC32 ((uint8_t*)rtcmem_data_storage.nodeKey, sizeof (rtcmem_data) - sizeof (uint32_t));
454  DEBUG_VERBOSE ("Write RTCData: %s", printHexBuffer ((uint8_t*)&rtcmem_data, sizeof (rtcmem_data)));
455 #if DEBUG_LEVEL >= VERBOSE
457 #endif
458  return true;
459 #endif
460  return false;
461 }
462 #endif
463 
465  if (!FILESYSTEM.begin ()) {
466  DEBUG_ERROR ("Error on FILESYSTEM.begin()");
467  }
468 
469  DEBUG_WARN ("About to format Flash");
470  if (FILESYSTEM.format()) {
471  DEBUG_WARN ("Filesystem formatted");
472  }
473  /*if (FILESYSTEM.remove (CONFIG_FILE)) {
474  DEBUG_DBG ("%s deleted", CONFIG_FILE);
475  }*/ else {
476  DEBUG_ERROR ("Error on FILESYSTEM.format()", CONFIG_FILE);
477  }
478  FILESYSTEM.end ();
479 }
480 
482  AsyncWebServer server (80);
483  DNSServer dns;
484 
485  //regex_t regex;
486  bool regexResult = true;
487 
488  //char networkKey[33] = "";
489  char sleepy[5] = "10";
490  //char networkName[NETWORK_NAME_LENGTH] = "";
491  char nodeName[NODE_NAME_LENGTH] = "";
492 
493  wifiManager = new AsyncWiFiManager (&server, &dns);
494 #if DEBUG_LEVEL == NONE
495  wifiManager->setDebugOutput (false);
496 #endif
497 
498  //AsyncWiFiManagerParameter networkNameParam ("netname", "Network name", networkName, (int)NETWORK_NAME_LENGTH, "required type=\"text\" maxlength=20");
499  //AsyncWiFiManagerParameter netKeyParam ("netkey", "NetworkKey", networkKey, 33, "required type=\"password\" maxlength=32");
500  AsyncWiFiManagerParameter sleepyParam ("sleepy", "Sleep Time", sleepy, 5, "required type=\"number\" min=\"0\" max=\"13600\" step=\"1\"");
501  AsyncWiFiManagerParameter nodeNameParam ("nodename", "Node Name", nodeName, NODE_NAME_LENGTH, "type=\"text\" pattern=\"^[^/\\\\]+$\" maxlength=32");
502 
503  wifiManager->setCustomHeadElement ("<style>input:invalid {border: 2px dashed red;input:valid{border: 2px solid black;}</style>");
504  //wifiManager->addParameter (&networkNameParam);
505  //wifiManager->addParameter (&netKeyParam);
506  wifiManager->addParameter (&sleepyParam);
507  wifiManager->addParameter (&nodeNameParam);
508 
511  }
512  wifiManager->setConnectTimeout (30);
513  wifiManager->setBreakAfterConfig (true);
514  wifiManager->setTryConnectDuringConfigPortal (false);
515  char apname[64];
516 #ifdef ESP8266
517  snprintf (apname, 64, "EnigmaIoTNode%06x", ESP.getChipId ());
518  //String apname = "EnigmaIoTNode" + String (ESP.getChipId (), 16);
519 #elif defined ESP32
520  snprintf (apname, 64, "EnigmaIoTNode%06x", (uint32_t)(ESP.getEfuseMac () & (uint64_t)0x0000000000FFFFFF));
521  //String apname = "EnigmaIoTNode" + String (ESP.getEfuseMac (), 16);
522 #endif
523  DEBUG_VERBOSE ("Start AP: %s", apname);
524 
525  boolean result = wifiManager->startConfigPortal (apname, NULL);
526  if (result) {
527  DEBUG_DBG ("==== Config Portal result ====");
528 
529  DEBUG_DBG ("Network Name: %s", WiFi.SSID ().c_str ());
530 #ifdef ESP8266
531  station_config wifiConfig;
532  if (!wifi_station_get_config (&wifiConfig)) {
533  DEBUG_WARN ("Error getting WiFi config");
534  }
535  DEBUG_DBG ("WiFi password: %s", wifiConfig.password);
536  const char* netkey = (char*)(wifiConfig.password);
537 #elif defined ESP32
538  wifi_config_t wifiConfig;
539  if (esp_wifi_get_config (WIFI_IF_STA, &wifiConfig)) {
540  DEBUG_WARN ("Error getting WiFi config");
541  }
542  DEBUG_WARN ("WiFi password: %.*s", 64, wifiConfig.sta.password);
543  const char* netkey = (char*)(wifiConfig.sta.password);
544 #endif
545  DEBUG_DBG ("Network Key: %s", netkey);
546  DEBUG_DBG ("Sleppy time: %s", sleepyParam.getValue ());
547  DEBUG_DBG ("Node Name: %s", nodeNameParam.getValue ());
548 
549  data->lastMessageCounter = 0;
550 
551  strncpy ((char*)(data->networkKey), netkey, KEY_LENGTH);
552  DEBUG_DBG ("Stored network key before hash: %.*s", KEY_LENGTH, (char*)(data->networkKey));
553 
554  CryptModule::getSHA256 (data->networkKey, KEY_LENGTH);
555  DEBUG_DBG ("Calculated network key: %s", printHexBuffer (data->networkKey, KEY_LENGTH));
556  data->nodeRegisterStatus = UNREGISTERED;
557 
558  //const char* netName = WiFi.SSID ().c_str ();
559  DEBUG_DBG ("Temp network name: %s", WiFi.SSID ().c_str ());
560  strncpy (data->networkName, WiFi.SSID ().c_str (), NETWORK_NAME_LENGTH - 1);
561  DEBUG_DBG ("Stored network name: %s", data->networkName);
562 
563 #ifdef ESP32
564  std::regex sleepTimeRegex ("(\\d)+");
565  regexResult = std::regex_match (sleepyParam.getValue (), sleepTimeRegex);
566  if (regexResult) {
567 #endif
568  DEBUG_DBG ("Sleep time check ok");
569  int sleepyVal = atoi (sleepyParam.getValue ());
570  if (sleepyVal > 0) {
571  data->sleepy = true;
572  }
573  data->sleepTime = sleepyVal;
574 #ifdef ESP32
575  } else {
576  DEBUG_WARN ("Sleep time parameter error");
577  result = false;
578  }
579 #endif
580 
581  //char tempStr[NODE_NAME_LENGTH];
582  //strncpy (tempStr, nodeNameParam.getValue (), NODE_NAME_LENGTH - 1);
583 
584 #ifdef ESP32
585  std::regex nodeNameRegex ("^[^/\\\\]+$");
586  regexResult = std::regex_match (nodeNameParam.getValue (), nodeNameRegex);
587 #elif defined ESP8266
588  if (strstr (nodeNameParam.getValue (), "/")) {
589  regexResult = false;
590  DEBUG_WARN ("Node name parameter error. Contains '/'");
591  } else if (strstr (nodeNameParam.getValue (), "\\")) {
592  regexResult = false;
593  DEBUG_WARN ("Node name parameter error. Contains '\\'");
594  }
595 #endif
596  if (regexResult) {
597  strncpy (data->nodeName, nodeNameParam.getValue (), NODE_NAME_LENGTH);
598  DEBUG_DBG ("Node name: %s", data->nodeName);
599  } else {
600  DEBUG_WARN ("Node name parameter error");
601  result = false;
602  }
603 
604  data->nodeKeyValid = false;
605  data->crc32 = calculateCRC32 ((uint8_t*)(data->nodeKey), sizeof (rtcmem_data_t) - sizeof (uint32_t));
606  }
607 
608  if (notifyWiFiManagerExit) {
609  notifyWiFiManagerExit (result);
610  }
611 
612  delete (wifiManager);
613 
614  return result;
615 }
616 
617 void flashLed (void* led) {
618 #ifdef ESP8266
619  digitalWrite (*(int*)led, !digitalRead (*(int*)led));
620 #elif defined ESP32
621  bool led_on = !digitalRead (localLed);
622  DEBUG_VERBOSE ("Change LED %d to %d", localLed, led_on);
623  digitalWrite (localLed, led_on);
624 #endif
625 }
626 
627 void startFlash (time_t period) {
628 #ifdef ESP32
629  //static int id = 1;
630  DEBUG_INFO ("Start flash");
633  ledTimer = xTimerCreate ("led_flash", pdMS_TO_TICKS (period), pdTRUE, (void*)0, &flashLed);
634  if (xTimerStart (ledTimer, 0) != pdPASS) {
635  DEBUG_WARN ("Problem starting LED timer");
636  }
637  }
638 #elif defined (ESP8266)
639  ets_timer_disarm (&ledTimer);
642  ets_timer_arm_new (&ledTimer, period, true, true);
643  }
644 #endif // ESP32
645 }
646 
647 void stopFlash () {
648 #ifdef ESP32
651  xTimerStop (ledTimer, 0);
652  xTimerDelete (ledTimer, 0);
653  }
654 #elif defined(ESP8266)
657  ets_timer_disarm (&ledTimer);
658  digitalWrite (localLed, LED_OFF);
659  }
660 #endif // ESP32
661 }
662 
664  identifyStart = millis ();
665  indentifying = true;
666  startFlash (period);
667 }
668 
670  indentifying = false;
671  stopFlash ();
672 }
673 
675  if (resetPin > 0) {
676  pinMode (resetPin, INPUT_PULLUP);
677  digitalWrite (led, LED_ON); // Turn on LED
678  if (digitalRead (resetPin) == LOW) { // If pin is grounded
679  time_t resetPinGrounded = millis ();
680  while (digitalRead (resetPin) == LOW) {
681  if (millis () - resetPinGrounded > RESET_PIN_DURATION) {
682  DEBUG_WARN ("Produce reset. Reset pin %d", resetPin);
683  digitalWrite (led, LED_OFF); // Turn off LED
684  startFlash (50);
685  clearFlash ();
686  clearRTC ();
687  delay (5000);
688  ESP.restart ();
689  }
690  delay (50);
691  }
692  }
693  }
694 }
695 
696 void EnigmaIOTNodeClass::begin (Comms_halClass* comm, uint8_t* gateway, uint8_t* networkKey, bool useCounter, bool sleepy) {
697  cycleStartedTime = 0; // Calculate time from start
698  pinMode (led, OUTPUT);
699 #ifdef ESP8266
700  ets_timer_setfn (&ledTimer, flashLed, (void*)&led);
701 #endif
702  localLed = led;
703 
704  checkResetButton ();
705 
706  // startFlash (100); // Do not flash during setup for less battery drain
707 
708  digitalWrite (led, LED_OFF);
709 
710  this->comm = comm;
711 
712  this->useCounter = useCounter;
713 
714  node.setInitAsSleepy (sleepy);
715  node.setSleepy (sleepy);
716  DEBUG_DBG ("Set %s mode: %s", node.getSleepy () ? "sleepy" : "non sleepy", sleepy ? "sleepy" : "non sleepy");
717 
718  if (loadRTCData () && rtcmem_data.commErrors < COMM_ERRORS_BEFORE_SCAN) { // If data present on RTC node has waked up or it is just configured, continue
719 #if DEBUG_LEVEL >= DBG
720  char gwAddress[ENIGMAIOT_ADDR_LEN * 3];
721  DEBUG_DBG ("RTC data loaded. Gateway: %s", mac2str (rtcmem_data.gateway, gwAddress));
722  DEBUG_DBG ("Own address: %s", mac2str (node.getMacAddress (), gwAddress));
723 #endif
724  } else { // No RTC data, first boot or not configured
725  if (gateway && networkKey) { // If connection data has been passed to library
726  DEBUG_DBG ("EnigmaIot started with config data con begin() call");
727  memcpy (rtcmem_data.gateway, gateway, comm->getAddressLength ()); // setGateway
728  memcpy (rtcmem_data.networkKey, networkKey, KEY_LENGTH); // setNetworkKey
730  rtcmem_data.nodeKeyValid = false;
731  //rtcmem_data.channel = channel;
732  rtcmem_data.sleepy = sleepy;
734  } else { // Try read from flash
735  DEBUG_INFO ("Starting from Flash");
736  if (!FILESYSTEM.begin ()) {
737  DEBUG_ERROR ("Error mounting flash");
738  if (FILESYSTEM.format ()) {
739  DEBUG_INFO ("FILESYSTEM formatted");
740  } else {
741  DEBUG_ERROR ("Error formatting FILESYSTEM");
742  }
743  delay (2500);
744  ESP.restart ();
745  //return;
746  } else {
747  DEBUG_INFO ("FILESYSTEM mounted");
748  }
749  if (loadFlashData ()) { // If data present on flash, read and continue
751  DEBUG_DBG ("Flash data loaded");
752  uint8_t prevGwAddr[ENIGMAIOT_ADDR_LEN];
753  memcpy (prevGwAddr, rtcmem_data.gateway, 6);
754  if (searchForGateway (&rtcmem_data, true)) {
755  //DEBUG_DBG ("Found gateway. Storing");
757  }
758  } else { // Configuration empty. Enter config AP mode
759  DEBUG_DBG ("No flash data present. Starting Configuration AP");
760  bool result = configWiFiManager (&rtcmem_data);
761  if (result) {
762  DEBUG_DBG ("Got configuration. Searching for Gateway");
763  if (searchForGateway (&rtcmem_data, true)) {
764  DEBUG_DBG ("Found EnigmaIOT Gateway. Storing configuration");
765  if (!saveFlashData (true)) {
766  DEBUG_ERROR ("Error saving data on flash");
767  }
768  FILESYSTEM.end ();
769  ESP.restart ();
770  return;
771  }
772  FILESYSTEM.end ();
773  if (node.getSleepy ()) {
774  DEBUG_WARN ("No gateway found. Go to sleep for 120 seconds");
775  ESP.deepSleep (120);
776  } else {
777  DEBUG_WARN ("No gateway found. Restarting");
778  ESP.restart ();
779  }
780  } else { // Configuration error
781  DEBUG_ERROR ("Configuration error. Restarting");
782  ESP.restart ();
783  }
784  }
785  }
786  }
787 
790  comm->onDataRcvd (rx_cb);
791  comm->onDataSent (tx_cb);
792 
793 #ifdef ESP8266
794  wifi_set_channel (rtcmem_data.channel);
795 #elif defined ESP32
796  esp_err_t err_ok;
797  if ((err_ok = esp_wifi_set_promiscuous (true))) {
798  DEBUG_ERROR ("Error setting promiscuous mode: %s", esp_err_to_name (err_ok));
799  }
800  if ((err_ok = esp_wifi_set_channel (rtcmem_data.channel, WIFI_SECOND_CHAN_NONE))) {
801  DEBUG_ERROR ("Error setting wifi channel: %s", esp_err_to_name (err_ok));
802  }
803  if ((err_ok = esp_wifi_set_promiscuous (false))) {
804  DEBUG_ERROR ("Error setting promiscuous mode off: %s", esp_err_to_name (err_ok));
805  }
806 #endif
807 
808  DEBUG_DBG ("Comms started. Channel %u", rtcmem_data.channel);
809 }
810 
811 #ifdef ESP32
812 int scanGatewaySSID (char* name, int& wifiIndex) {
813  uint32_t scanStarted;
814  int16_t numAP = 0;
815  const int MAX_INDEXES = 10;
816  int numFound = 0;
817  int indexes[MAX_INDEXES];
818 
819  if (!name) {
820  DEBUG_WARN ("SSID Name is NULL");
821  return 0;
822  }
823 
824  scanStarted = millis ();
825  numAP = WiFi.scanNetworks (false, false, false, 300U);
826  DEBUG_DBG ("Found %d APs in %lu ms", numAP, millis () - scanStarted);
827  DEBUG_DBG ("Scan finished. Result = %d", WiFi.scanComplete ());
828  while (!(WiFi.scanComplete ()) && (millis () - scanStarted) > 1500) { //
829 #if DEBUG_LEVEL >= DBG
830  delay (250);
831  Serial.printf ("%lu.", millis () - scanStarted);
832 #else
833  delay (50);
834 #endif
835  }
836  DEBUG_DBG ("Scan finished. Result = %d", WiFi.scanComplete ());
837 
838  DEBUG_DBG ("Found %d APs in %lu ms", numAP, millis () - scanStarted);
839 
840  wifi_ap_record_t* wifiAP;
841 
842  for (int i = 0; i < numAP; i++) {
843  wifiAP = (wifi_ap_record_t*)WiFi.getScanInfoByIndex (i);
844  DEBUG_DBG ("Found AP %.*s with BSSID " MACSTR " and RSSI %d dBm", 32, wifiAP->ssid, MAC2STR (wifiAP->bssid), wifiAP->rssi);
845  if (!strncmp (name, (char*)(wifiAP->ssid), 32)) {
846  indexes[numFound] = i;
847  numFound++;
848  if (numFound >= MAX_INDEXES) {
849  break;
850  }
851  }
852  }
853 
854  wifiIndex = indexes[0];
855 
856  return numFound;
857 }
858 #endif
859 
861  DEBUG_DBG ("Searching for AP %s", data->networkName);
862 
863  //WiFi.mode (WIFI_STA);
864  int numWifi = 0;
865  int wifiIndex = 0;
866 
867  comm->enableTransmit (false);
868  DEBUG_DBG ("Transmission disabled");
869 #ifdef ESP8266
870  time_t scanStarted = millis ();
871  numWifi = WiFi.scanNetworks (false, false, 0, (uint8_t*)(data->networkName));
872  while (!(WiFi.scanComplete () || (millis () - scanStarted) > 1500)) {
873 #if DEBUG_LEVEL >= DBG
874  delay (250);
875  Serial.printf ("%lu.", millis () - scanStarted);
876 #else
877  delay (50);
878 #endif
879  }
880  WiFiMode_t mode = WiFi.getMode ();
881  DEBUG_DBG ("WiFi mode is %d. Restarting network interface after scan", mode);
882  WiFi.mode (WIFI_OFF);
883  WiFi.mode (mode);
884 #elif defined ESP32
885  numWifi = scanGatewaySSID (data->networkName, wifiIndex);
886 #endif // ESP8266
887  comm->enableTransmit (true);
888  DEBUG_DBG ("Transmission enabled");
889 
890  uint8_t prevGwAddr[ENIGMAIOT_ADDR_LEN];
891  memcpy (prevGwAddr, data->gateway, 6);
892 
893  if (numWifi > 0) {
894  DEBUG_INFO ("Gateway %s found: %d", data->networkName, numWifi);
895  DEBUG_INFO ("BSSID: %s", WiFi.BSSIDstr (wifiIndex).c_str ());
896  DEBUG_INFO ("Channel: %d", WiFi.channel (wifiIndex));
897  DEBUG_INFO ("RSSI: %d", WiFi.RSSI (wifiIndex));
898  data->channel = WiFi.channel (wifiIndex);
899  data->rssi = WiFi.RSSI (wifiIndex);
900  memcpy (data->gateway, WiFi.BSSID (wifiIndex), 6);
901 
902  if (shouldStoreData) {
903  DEBUG_DBG ("Found gateway. Storing");
904  if (!saveRTCData ()) {
905  DEBUG_ERROR ("Error saving data on RTC");
906  }
907  if (memcmp (prevGwAddr, data->gateway, 6)) {
908  if (!saveFlashData ()) {
909  DEBUG_ERROR ("Error saving data on flash");
910  }
911  }
912  }
913 
914  WiFi.scanDelete ();
915 
916 #ifdef ESP8266
917  wifi_set_channel (data->channel);
918 #elif defined ESP32
919  esp_err_t err_ok;
920  if ((err_ok = esp_wifi_set_promiscuous (true))) {
921  DEBUG_ERROR ("Error setting promiscuous mode: %s", esp_err_to_name (err_ok));
922  }
923  if ((err_ok = esp_wifi_set_channel (data->channel, WIFI_SECOND_CHAN_NONE))) {
924  DEBUG_ERROR ("Error setting wifi channel: %s", esp_err_to_name (err_ok));
925  }
926  if ((err_ok = esp_wifi_set_promiscuous (false))) {
927  DEBUG_ERROR ("Error setting promiscuous mode off: %s", esp_err_to_name (err_ok));
928  }
929 #endif
930 
931  requestReportRSSI = true;
932  return true;
933  }
934  DEBUG_WARN ("Gateway %s not found", data->networkName);
935  return false;
936 }
937 
939  comm->stop ();
940  DEBUG_DBG ("Communication layer uninitalized");
941 }
942 
944  node.setMacAddress (address);
945  return true;
946 }
947 
948 void EnigmaIOTNodeClass::setSleepTime (uint32_t sleepTime, bool forceSleepForever) {
949  if (node.getInitAsSleepy ()) {
950 #ifdef ESP8266 // ESP32 does not have this limitation
951  uint64_t maxSleepTime = (ESP.deepSleepMax () / (uint64_t)1000000);
952 #endif
953 
954  if (sleepTime == 0 && !forceSleepForever) {
955  node.setSleepy (false);
956  //rtcmem_data.sleepy = false; // This setting is temporary, do not store
957  } else if (sleepTime
958 #ifdef ESP8266
959  < maxSleepTime
960 #endif
961  ) {
962  node.setSleepy (true);
964  }
965 #ifdef ESP8266
966  else {
967  DEBUG_DBG ("Max sleep time is %lu", (uint32_t)maxSleepTime);
968  node.setSleepy (true);
969  rtcmem_data.sleepTime = (uint32_t)maxSleepTime;
970  }
971 #endif
972  this->sleepTime = (uint64_t)rtcmem_data.sleepTime * (uint64_t)1000000;
973  DEBUG_DBG ("Sleep time set to %d. Sleepy mode is %s",
975  node.getSleepy () ? "sleepy" : "non sleepy");
976 
977  } else {
978  DEBUG_WARN ("Cannot set sleep time to %u seconds as this node started as non sleepy", sleepTime);
979  }
980 }
981 
983  uint8_t buffer[MAX_MESSAGE_LENGTH];
984  uint8_t bufLength;
985 
986  DEBUG_DBG ("Report RSSI and channel");
987 
988  buffer[0] = control_message_type::RSSI_ANS;
989  buffer[1] = rtcmem_data.rssi;
990  buffer[2] = rtcmem_data.channel;
991  bufLength = 3;
992 
993  if (sendData (buffer, bufLength, CONTROL_TYPE)) {
994  DEBUG_DBG ("Sleep time is %d seconds", sleepTime / 1000000);
995  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
996  return true;
997  } else {
998  DEBUG_WARN ("Error sending version response");
999  return false;
1000  }
1001 }
1002 
1004  static unsigned long blueOntime;
1005 
1006  // Locate gateway address, channel and rssi
1007  if (requestSearchGateway) {
1008  requestSearchGateway = false;
1009  requestReportRSSI = true;
1010  searchForGateway (&rtcmem_data, true);
1011  }
1012 
1013  // Report RSSI to gateway
1014  if (requestReportRSSI && node.isRegistered ()) {
1015  requestReportRSSI = false;
1016  reportRSSI ();
1017  }
1018 
1019  // Flash led if programmed (when data is transferred)
1020  if (led >= 0) {
1021  if (flashBlue) {
1022  blueOntime = millis ();
1023  digitalWrite (led, LED_ON);
1024  flashBlue = false;
1025  }
1026 
1027  if (!indentifying) {
1028  if ( millis () - blueOntime > ledOnTime) {
1029  digitalWrite (led, LED_OFF);
1030  }
1031  }
1032  }
1033 
1034  // Check if this should go to sleep
1035  if (node.getSleepy () && !shouldRestart) {
1037  // Substract running time
1038  int64_t sleep_t = 0;
1039  if (sleepTime) {
1040  sleep_t = sleepTime - ((millis () - cycleStartedTime) * 1000);
1041  }
1042  if (sleep_t && sleep_t < 1000) {
1043  // Avoid negative values
1044  sleep_t = 1000;
1045  }
1046  //int64_t msSleep = sleep_t / 1000;
1047  if (sleep_t) {
1048  DEBUG_WARN ("Go to sleep for %ld ms", (int32_t)(sleep_t / 1000L));
1049  } else {
1050  DEBUG_WARN ("Go to sleep indefinitely");
1051  }
1052  DEBUG_WARN ("%d", millis ());
1053  comm->enableTransmit (false);
1054 #ifdef ESP8266
1055  ESP.deepSleep (sleep_t);
1056 #elif defined ESP32
1057  esp_deep_sleep (sleep_t);
1058 #endif
1059  }
1060  }
1061 
1062  // Check registration timeout
1063  static time_t lastRegistration = millis ();
1065  if (status == WAIT_FOR_SERVER_HELLO /*|| status == WAIT_FOR_CIPHER_FINISHED*/) {
1066  if (node.getSleepy ()) { // Sleep after registration timeout
1067  if (millis () - node.getLastMessageTime () > RECONNECTION_PERIOD) {
1068  DEBUG_INFO ("Current node status: %d", node.getStatus ());
1069  node.reset ();
1071 
1072  if (!saveRTCData ()) {
1073  DEBUG_ERROR ("Error saving data on RTC");
1074  }
1075 
1076  uint32_t rnd = Crypto.random (PRE_REG_DELAY * 1000); // nanoseconds
1077 
1078  DEBUG_INFO ("Registration timeout. Go to sleep for %lu ms", (uint32_t)(RECONNECTION_PERIOD * 4 + rnd / 1000));
1079 #ifdef ESP8266
1080  ESP.deepSleep (RECONNECTION_PERIOD * 4000 + rnd, RF_NO_CAL);
1081 #elif defined ESP32
1082  ESP.deepSleep (RECONNECTION_PERIOD * 4000 + rnd);
1083 #endif
1084  }
1085  } else { // Retry registration
1086  if (millis () - node.getLastMessageTime () > RECONNECTION_PERIOD * 5) {
1087  DEBUG_INFO ("Current node status: %d", node.getStatus ());
1088  node.reset ();
1089  node.setLastMessageTime (); // Set wait time start
1090  }
1091  }
1092  }
1093 
1094  // Retry registration
1095  if (node.getStatus () == UNREGISTERED) {
1096  if (millis () - lastRegistration > RECONNECTION_PERIOD) {
1097  DEBUG_DBG ("Current node status: %d", node.getStatus ());
1098  lastRegistration = millis (); // Set wait time start
1099  node.reset ();
1100  uint32_t rnd = Crypto.random (PRE_REG_DELAY);
1101  DEBUG_INFO ("Random delay (%u)", rnd);
1102  delay (1500 + rnd);
1103  clientHello ();
1104  delay (1500 + Crypto.random (POST_REG_DELAY)); // Wait for Server Hello
1105  }
1106  }
1107 
1108  // Check OTA update timeout
1109  if (otaRunning) {
1110  if (millis () - lastOTAmsg > OTA_TIMEOUT_TIME) {
1111  uint8_t responseBuffer[2];
1112  responseBuffer[0] = control_message_type::OTA_ANS;
1113  responseBuffer[1] = ota_status::OTA_TIMEOUT;
1114  if (sendData (responseBuffer, sizeof (responseBuffer), CONTROL_TYPE)) {
1115  DEBUG_INFO ("OTA TIMEOUT");
1116  }
1117  otaRunning = false;
1118  DEBUG_WARN ("Restart due to OTA timeout");
1119  restart (IRRELEVANT);
1120  }
1121  }
1122 
1123  // Check identifying LED timeout
1124  if (indentifying) {
1125  if (millis () - identifyStart > IDENTIFY_TIMEOUT) {
1126  stopIdentifying ();
1127  digitalWrite (led, LED_OFF);
1128  }
1129  }
1130 
1131  //if (!node.getSleepy () && node.isRegistered () && !node.hasClockSync())
1132  // clockRequest ();
1133 
1134  // Check time sync timeout
1135  if (clockSyncEnabled) {
1136  static time_t lastTimeSync;
1137  if (!node.getSleepy () && node.isRegistered ()) {
1138  if ((millis () - lastTimeSync > timeSyncPeriod)) {
1139  lastTimeSync = millis ();
1140  DEBUG_DBG ("Clock Request");
1141  clockRequest ();
1142  }
1143  }
1144  }
1145 
1146  // Check restart
1147  if (shouldRestart) {
1148  static bool restartSent = false;
1149  if (!restartSent) {
1150  DEBUG_WARN ("Send restart");
1151  sendRestart ();
1152  restartSent = true;
1153  }
1154  static unsigned long retartRequest = millis ();
1155  if (millis () - retartRequest > 2500) {
1156  DEBUG_WARN ("Restart");
1157  ESP.restart ();
1158  }
1159  }
1160 
1161  // In case of comm errors search for gateway again
1163  if (!gatewaySearchStarted) {
1164  gatewaySearchStarted = true;
1165 
1166  if (searchForGateway (&rtcmem_data, true)) {
1167  rtcmem_data.commErrors = 0;
1168  }
1169  }
1170  }
1171 
1172 }
1173 
1174 void EnigmaIOTNodeClass::rx_cb (uint8_t* mac_addr, uint8_t* data, uint8_t len) {
1175  EnigmaIOTNode.manageMessage (mac_addr, data, len);
1176 }
1177 
1178 void EnigmaIOTNodeClass::tx_cb (uint8_t* mac_addr, uint8_t status) {
1179  EnigmaIOTNode.getStatus (mac_addr, status);
1180 }
1181 
1182 bool EnigmaIOTNodeClass::checkCRC (const uint8_t* buf, size_t count, uint32_t* crc) {
1183  uint32_t recvdCRC;
1184 
1185  memcpy (&recvdCRC, crc, sizeof (uint32_t));
1186  //DEBUG_VERBOSE ("Received CRC32: 0x%08X", *crc32);
1187  uint32_t _crc = calculateCRC32 (buf, count);
1188  DEBUG_VERBOSE ("CRC32 = Calc: 0x%08X Recvd: 0x%08X Length: %d", _crc, recvdCRC, count);
1189  return (_crc == recvdCRC);
1190 }
1191 
1193  /*
1194  * ------------------------------------------------------------------------------------------------------------
1195  *| msgType (1) | IV (12) | DH Kmaster (32) | Random (30 bits) | Broadcast (1 bit) | Sleepy (1 bit) | Tag (16) |
1196  * ------------------------------------------------------------------------------------------------------------
1197  */
1198 
1199  struct __attribute__ ((packed, aligned (1))) {
1200  uint8_t msgType;
1201  uint8_t iv[IV_LENGTH];
1202  uint8_t publicKey[KEY_LENGTH];
1203  uint32_t random;
1204  uint8_t tag[TAG_LENGTH];
1205  } clientHello_msg;
1206 
1207 #define CHMSG_LEN sizeof(clientHello_msg)
1208 
1209  invalidateReason = UNKNOWN_ERROR; // reset any previous force disconnect
1210 
1211  Crypto.getDH1 ();
1212  node.setStatus (INIT);
1214  /*uint8_t macAddress[ENIGMAIOT_ADDR_LEN];
1215 #ifdef ESP8266
1216  if (wifi_get_macaddr (STATION_IF, macAddress)) {
1217 #elif defined ESP32
1218  if (esp_wifi_get_mac (WIFI_IF_STA, macAddress) == ESP_OK) {
1219 #endif
1220  node.setMacAddress (macAddress);
1221  }*/
1222 
1223  uint8_t* key = Crypto.getPubDHKey ();
1224 
1225  if (!key) {
1226  DEBUG_ERROR ("Error calculating public ECDH key");
1227  return false;
1228  }
1229 
1230  clientHello_msg.msgType = CLIENT_HELLO; // Client hello message
1231 
1232  CryptModule::random (clientHello_msg.iv, IV_LENGTH);
1233 
1234  DEBUG_VERBOSE ("IV: %s", printHexBuffer (clientHello_msg.iv, IV_LENGTH));
1235 
1236  for (int i = 0; i < KEY_LENGTH; i++) {
1237  clientHello_msg.publicKey[i] = key[i];
1238  }
1239 
1240  uint32_t random;
1241  random = Crypto.random ();
1242 
1243  if (node.getSleepy ()) {
1244  random = random | 0x00000001U; // Signal sleepy node
1245  DEBUG_DBG ("Signal sleepy node");
1246  } else {
1247  random = random & 0xFFFFFFFEU; // Signal always awake node
1248  DEBUG_DBG ("Signal non sleepy node");
1249  }
1250 
1251  if (node.broadcastIsEnabled ()) {
1252  random = random | 0x00000002U; // Signal broadcast mode enabled to request broadcast key
1254  DEBUG_DBG ("Signal sleepy node");
1255  } else {
1256  random = random & 0xFFFFFFFDU; // Signal broadcast disabled
1258  DEBUG_DBG ("Signal non sleepy node");
1259  }
1260 
1261  memcpy (&(clientHello_msg.random), &random, RANDOM_LENGTH);
1262 
1263  DEBUG_VERBOSE ("Client Hello message: %s", printHexBuffer ((uint8_t*)&clientHello_msg, CHMSG_LEN - TAG_LENGTH));
1264 
1265  uint8_t addDataLen = CHMSG_LEN - TAG_LENGTH - sizeof (uint32_t) - KEY_LENGTH;
1266  uint8_t aad[AAD_LENGTH + addDataLen];
1267 
1268  memcpy (aad, (uint8_t*)&clientHello_msg, addDataLen); // Copy message upto iv
1269 
1270  // Copy 8 last bytes from NetworkKey
1271  memcpy (aad + addDataLen, rtcmem_data.networkKey + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1272 
1273  if (!CryptModule::encryptBuffer (clientHello_msg.publicKey, KEY_LENGTH + sizeof (uint32_t), // Encrypt only from public key
1274  clientHello_msg.iv, IV_LENGTH,
1275  rtcmem_data.networkKey, KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
1276  aad, sizeof (aad), clientHello_msg.tag, TAG_LENGTH)) {
1277  DEBUG_ERROR ("Error during encryption");
1278  return false;
1279  }
1280 
1281  DEBUG_VERBOSE ("Encrypted Client Hello message: %s", printHexBuffer ((uint8_t*)&clientHello_msg, CHMSG_LEN));
1282 
1285 
1286  DEBUG_INFO (" -------> CLIENT HELLO");
1287 
1288  return comm->send (rtcmem_data.gateway, (uint8_t*)&clientHello_msg, CHMSG_LEN) == 0;
1289 }
1290 
1292  /*
1293  * ---------------------------------------------------------
1294  *| msgType (1) | IV (12) | Counter (2) | T1 (8) | tag (16) |
1295  * ---------------------------------------------------------
1296  */
1297  struct __attribute__ ((packed, aligned (1))) {
1298  uint8_t msgType;
1299  uint8_t iv[IV_LENGTH];
1300  int16_t counter;
1301  int64_t t1;
1302  uint8_t tag[TAG_LENGTH];
1303  } clockRequest_msg;
1304  uint16_t counter;
1305 
1306  static const uint8_t CRMSG_LEN = sizeof (clockRequest_msg);
1307 
1308  clockRequest_msg.msgType = CLOCK_REQUEST;
1309 
1310  CryptModule::random (clockRequest_msg.iv, IV_LENGTH);
1311 
1312  DEBUG_VERBOSE ("IV: %s", printHexBuffer (clockRequest_msg.iv, IV_LENGTH));
1313 
1314  if (useCounter) {
1315  counter = node.getLastControlCounter () + 1;
1316  node.setLastControlCounter (counter);
1317  rtcmem_data.lastControlCounter = counter;
1318  } else {
1319  counter = (uint16_t)(Crypto.random ());
1320  }
1321 
1322  DEBUG_INFO ("Control message #%d", counter);
1323 
1324  memcpy (&(clockRequest_msg.counter), &counter, sizeof (uint16_t));
1325 
1326  uint64_t t1 = TimeManager.clock_us ();
1327 
1328  memcpy (&(clockRequest_msg.t1), &t1, sizeof (int64_t));
1329 
1330  DEBUG_VERBOSE ("Clock Request message: %s", printHexBuffer ((uint8_t*)&clockRequest_msg, CRMSG_LEN - TAG_LENGTH));
1331  DEBUG_DBG ("T1: %llu", t1);
1332 
1333  uint8_t addDataLen = 1 + IV_LENGTH;
1334  uint8_t aad[AAD_LENGTH + addDataLen];
1335 
1336  memcpy (aad, (uint8_t*)&clockRequest_msg, addDataLen); // Copy message upto iv
1337 
1338  // Copy 8 last bytes from Node Key
1339  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1340 
1341  if (!CryptModule::encryptBuffer ((uint8_t*)&(clockRequest_msg.counter), CRMSG_LEN - IV_LENGTH - TAG_LENGTH - 1, // Encrypt only from counter
1342  clockRequest_msg.iv, IV_LENGTH,
1343  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
1344  aad, sizeof (aad), clockRequest_msg.tag, TAG_LENGTH)) {
1345  DEBUG_ERROR ("Error during encryption");
1346  return false;
1347  }
1348 
1349  DEBUG_VERBOSE ("Encrypted Clock Request message: %s", printHexBuffer ((uint8_t*)&clockRequest_msg, CRMSG_LEN));
1350 
1351  DEBUG_INFO (" -------> CLOCK REQUEST");
1352 
1354 
1355  flashBlue = true;
1356 
1357  if (useCounter && !otaRunning) { // RTC must not be written if OTA is running. OTA uses RTC memmory to signal 2nd firmware boot
1358  if (!saveRTCData ()) {
1359  DEBUG_ERROR ("Error saving data on RTC");
1360  }
1361  }
1362 
1363  return comm->send (rtcmem_data.gateway, (uint8_t*)&clockRequest_msg, CRMSG_LEN) == 0;
1364 
1365 }
1366 
1367 bool EnigmaIOTNodeClass::processClockResponse (const uint8_t* mac, const uint8_t* buf, size_t count) {
1368  struct __attribute__ ((packed, aligned (1))) {
1369  uint8_t msgType;
1370  uint8_t iv[IV_LENGTH];
1371  uint16_t counter;
1372  int64_t t1;
1373  int64_t t2;
1374  int64_t t3;
1375  uint8_t tag[TAG_LENGTH];
1376  } clockResponse_msg;
1377 
1378  uint64_t t1, t2, t3, t4;
1379 
1380  uint16_t counter;
1381 
1382  const unsigned int CRSMSG_LEN = sizeof (clockResponse_msg);
1383 
1384  memcpy (&clockResponse_msg, buf, count);
1385 
1386  uint8_t addDataLen = 1 + IV_LENGTH;
1387  uint8_t aad[AAD_LENGTH + addDataLen];
1388 
1389  memcpy (aad, buf, addDataLen); // Copy message upto iv
1390 
1391  // Copy 8 last bytes from Node Key
1392  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1393 
1394  //uint8_t packetLen = count - TAG_LENGTH;
1395 
1396  if (!CryptModule::decryptBuffer ((uint8_t*)&(clockResponse_msg.counter), CRSMSG_LEN - IV_LENGTH - TAG_LENGTH - 1, // Decrypt from counter, 18 bytes
1397  clockResponse_msg.iv, IV_LENGTH,
1398  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
1399  aad, sizeof (aad), clockResponse_msg.tag, TAG_LENGTH)) {
1400  DEBUG_ERROR ("Error during decryption");
1401  return false;
1402  }
1403 
1404  DEBUG_VERBOSE ("Decripted Clock Response message: %s", printHexBuffer ((uint8_t*)&clockResponse_msg, count - TAG_LENGTH));
1405 
1406  memcpy (&counter, &(clockResponse_msg.counter), sizeof (uint16_t));
1407  DEBUG_INFO ("Downlink msg #%d", counter);
1408  if (useCounter) {
1409  if (counter > node.getLastDownlinkMsgCounter ()) {
1410  DEBUG_INFO ("Accepted");
1411  node.setLastDownlinkMsgCounter (counter);
1413  } else {
1414  DEBUG_WARN ("Downlink msg rejected");
1415  return false;
1416  }
1417  }
1418 
1419  t1 = clockResponse_msg.t1;
1420  t2 = clockResponse_msg.t2;
1421  t3 = clockResponse_msg.t3;
1422  t4 = TimeManager.clock_us ();
1423 
1424  if (count < CRSMSG_LEN) {
1425  DEBUG_WARN ("Message too short");
1426  return false;
1427  }
1428 
1429  memcpy (&clockResponse_msg, buf, count);
1430 
1431  int64_t offset = TimeManager.adjustTime (t1, t2, t3, t4);
1432 
1433  if (offset < MIN_SYNC_ACCURACY && offset > (MIN_SYNC_ACCURACY * -1)) {
1435  } else {
1437  }
1438  DEBUG_VERBOSE ("Clock Response message: %s", printHexBuffer ((uint8_t*)&clockResponse_msg, CRSMSG_LEN - TAG_LENGTH));
1439 
1440  DEBUG_DBG ("T1: %llu", t1);
1441  DEBUG_DBG ("T2: %llu", t2);
1442  DEBUG_DBG ("T3: %llu", t3);
1443  DEBUG_DBG ("T4: %llu", t4);
1444  DEBUG_INFO ("Offest adjusted to %lld us, Roundtrip delay is %lld", offset, TimeManager.getDelay ());
1445 
1446  if (useCounter && !otaRunning) { // RTC must not be written if OTA is running. OTA uses RTC memmory to signal 2nd firmware boot
1447  if (!saveRTCData ()) {
1448  DEBUG_ERROR ("Error saving data on RTC");
1449  }
1450  }
1451 
1452  return true;
1453 }
1454 
1456  return TimeManager.clock ();
1457 
1458 }
1459 
1461  return TimeManager.unixtime ();
1462 }
1463 
1465  if (!node.getInitAsSleepy ())
1466  return TimeManager.isTimeAdjusted ();
1467  else
1468  return false;
1469 }
1470 
1471 bool EnigmaIOTNodeClass::processServerHello (const uint8_t* mac, const uint8_t* buf, size_t count) {
1472  /*
1473  * ------------------------------------------------------
1474  *| msgType (1) | random (12) | DH Kslave (32) | Tag (16) |
1475  * ------------------------------------------------------
1476  */
1477 
1478  struct __attribute__ ((packed, aligned (1))) {
1479  uint8_t msgType;
1480  uint8_t iv[IV_LENGTH];
1481  uint8_t publicKey[KEY_LENGTH];
1482  uint16_t nodeId;
1483  uint32_t random;
1484  uint8_t tag[TAG_LENGTH];
1485  } serverHello_msg;
1486 
1487 #define SHMSG_LEN sizeof(serverHello_msg)
1488 
1489  uint16_t nodeId;
1490 
1491  if (count < SHMSG_LEN) {
1492  DEBUG_WARN ("Message too short");
1493  return false;
1494  }
1495 
1496  memcpy (&serverHello_msg, buf, count);
1497 
1498  uint8_t addDataLen = SHMSG_LEN - TAG_LENGTH - sizeof (uint32_t) - sizeof (uint16_t) - KEY_LENGTH;
1499  uint8_t aad[AAD_LENGTH + addDataLen];
1500 
1501  memcpy (aad, (uint8_t*)&serverHello_msg, addDataLen); // Copy message upto iv
1502 
1503  // Copy 8 last bytes from NetworkKey
1504  memcpy (aad + addDataLen, rtcmem_data.networkKey + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1505 
1506  if (!CryptModule::decryptBuffer (serverHello_msg.publicKey, KEY_LENGTH + sizeof (uint16_t) + sizeof (uint32_t),
1507  serverHello_msg.iv, IV_LENGTH,
1508  rtcmem_data.networkKey, KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
1509  aad, sizeof (aad), serverHello_msg.tag, TAG_LENGTH)) {
1510  DEBUG_ERROR ("Error during decryption");
1511  return false;
1512  }
1513 
1514  DEBUG_VERBOSE ("Decrypted Server Hello message: %s", printHexBuffer ((uint8_t*)&serverHello_msg, SHMSG_LEN - TAG_LENGTH));
1515 
1516  bool cError = Crypto.getDH2 (serverHello_msg.publicKey);
1517 
1518  if (!cError) {
1519  DEBUG_ERROR ("DH2 error");
1520  return false;
1521  }
1522 
1523  memcpy (&nodeId, &serverHello_msg.nodeId, sizeof (uint16_t));
1524  node.setNodeId (nodeId);
1525  rtcmem_data.nodeKeyValid = nodeId;
1526  DEBUG_DBG ("Node ID: %u", node.getNodeId ());
1527 
1528  node.setEncryptionKey (CryptModule::getSHA256 (serverHello_msg.publicKey, KEY_LENGTH));
1530  DEBUG_INFO ("Node key: %s", printHexBuffer (node.getEncriptionKey (), KEY_LENGTH));
1531 
1532  return true;
1533 }
1534 
1535 bool EnigmaIOTNodeClass::sendData (const uint8_t* data, size_t len, dataMessageType_t dataMsgType, bool encrypt, nodePayloadEncoding_t payloadType) {
1536  if (!dataMsgType) {
1537  memcpy (dataMessageSent, data, len);
1538  dataMessageSentLength = len;
1539  dataMessageEncrypt = encrypt;
1540  dataMessageSendPending = true;
1541  dataMessageSendEncoding = payloadType;
1542  }
1543  node.setLastMessageTime (); // Mark message time to start RX window start
1544 
1545  if (node.getStatus () == REGISTERED && node.isKeyValid ()) {
1546  if (dataMsgType == CONTROL_TYPE) {
1547  DEBUG_VERBOSE ("Control message sent: %s", printHexBuffer (data, len));
1548  } else if (dataMsgType == HA_DISC_TYPE) {
1549  DEBUG_VERBOSE ("HA discovery message sent: %s", printHexBuffer (data, len));
1550  } else {
1551  DEBUG_VERBOSE ("%s data sent: %s", encrypt ? "Encrypted" : "Unencrypted", printHexBuffer (data, len));
1552  }
1553  flashBlue = true;
1554  if (dataMessage (data, len, dataMsgType, encrypt, payloadType)) {
1555  dataMessageSendPending = false; // Data sent. This setting can still be overriden by invalidateCommand
1556  return true;
1557  } else
1558  return false;
1559 
1560  }
1561  return false;
1562 }
1563 
1565  if (node.getSleepy ()) {
1566  DEBUG_DBG ("Sleep programmed for %lu ms", rtcmem_data.sleepTime * 1000);
1567  sleepTime = (uint64_t)rtcmem_data.sleepTime * (uint64_t)1000000;
1568  sleepRequested = true;
1569  } else {
1570  DEBUG_VERBOSE ("Node is non sleepy. Sleep rejected");
1571  }
1572 }
1573 
1574 bool EnigmaIOTNodeClass::unencryptedDataMessage (const uint8_t* data, size_t len, dataMessageType_t dataMsgType, nodePayloadEncoding_t payloadEncoding) {
1575  /*
1576  * ------------------------------------------------------------------------
1577  *| msgType (1) | NodeId (2) | Counter (2) | PayloadType (1) | Data (....) |
1578  * ------------------------------------------------------------------------
1579  */
1580 
1581  uint8_t buf[MAX_MESSAGE_LENGTH];
1582  uint16_t counter;
1583  uint16_t nodeId = node.getNodeId ();
1584 
1585  uint8_t nodeId_idx = 1;
1586  uint8_t counter_idx = nodeId_idx + sizeof (int16_t);
1587  uint8_t encoding_idx = counter_idx + sizeof (int16_t);
1588  uint8_t data_idx = encoding_idx + sizeof (int8_t);
1589 
1590  uint8_t packet_length = data_idx + len;
1591 
1592  if (!data) {
1593  return false;
1594  }
1595 
1596  if (dataMsgType != DATA_TYPE) {
1597  return false; // Unencrypted control data not implemented
1598  } else {
1599  buf[0] = (uint8_t)UNENCRYPTED_NODE_DATA;
1600  }
1601 
1602  memcpy (buf + nodeId_idx, &nodeId, sizeof (uint16_t));
1603 
1604  if (useCounter) {
1605  counter = node.getLastMessageCounter () + 1;
1606  node.setLastMessageCounter (counter);
1607  rtcmem_data.lastMessageCounter = counter;
1608  } else {
1609  counter = (uint16_t)(Crypto.random ());
1610  }
1611  memcpy (buf + counter_idx, &counter, sizeof (uint16_t));
1612 
1613  buf[encoding_idx] = (uint8_t)payloadEncoding;
1614 
1615  memcpy (buf + data_idx, data, len);
1616 
1617  DEBUG_INFO (" -------> UNENCRYPTED DATA");
1618  DEBUG_VERBOSE ("Unencrypted data message: %s", printHexBuffer (buf, packet_length));
1619 
1620 #if DEBUG_LEVEL >= VERBOSE
1621  char macStr[ENIGMAIOT_ADDR_LEN * 3];
1622  DEBUG_DBG ("Destination address: %s", mac2str (rtcmem_data.gateway, macStr));
1623 #endif
1624 
1625  if (useCounter && !otaRunning) { // RTC must not be written if OTA is running. OTA uses RTC memmory to signal 2nd firmware boot
1626  if (!saveRTCData ()) {
1627  DEBUG_ERROR ("Error saving data on RTC");
1628  }
1629  }
1630 
1631  return (comm->send (rtcmem_data.gateway, buf, packet_length) == 0);
1632 }
1633 
1634 
1635 bool EnigmaIOTNodeClass::dataMessage (const uint8_t* data, size_t len, dataMessageType_t dataMsgType, bool encrypt, nodePayloadEncoding_t payloadEncoding) {
1636  /*
1637  * ----------------------------------------------------------------------------------------
1638  *| msgType (1) | IV (12) | length (2) | NodeId (2) | Counter (2) | Data (....) | tag (16) |
1639  * ----------------------------------------------------------------------------------------
1640  */
1641 
1642  if (!encrypt) {
1643  return unencryptedDataMessage (data, len, dataMsgType, payloadEncoding);
1644  }
1645 
1646  uint8_t buf[MAX_MESSAGE_LENGTH];
1647  //uint8_t tag[TAG_LENGTH];
1648  uint16_t counter;
1649  uint16_t nodeId = node.getNodeId ();
1650 
1651  uint8_t iv_idx = 1;
1652  uint8_t length_idx = iv_idx + IV_LENGTH;
1653  uint8_t nodeId_idx = length_idx + sizeof (int16_t);
1654  uint8_t counter_idx = nodeId_idx + sizeof (int16_t);
1655  uint8_t encoding_idx;
1656  uint8_t data_idx;
1657  if (dataMsgType != CONTROL_TYPE) {
1658  encoding_idx = counter_idx + sizeof (int16_t);
1659  data_idx = encoding_idx + sizeof (int8_t);
1660  } else {
1661  data_idx = counter_idx + sizeof (int16_t);
1662  }
1663  uint8_t tag_idx = data_idx + len;
1664 
1665 
1666  if (!data) {
1667  return false;
1668  }
1669 
1670  if (dataMsgType == CONTROL_TYPE) {
1671  buf[0] = (uint8_t)CONTROL_DATA;
1672  } else if (dataMsgType == HA_DISC_TYPE) {
1673  buf[0] = (uint8_t)HA_DISCOVERY_MESSAGE;
1674  } else {
1675  buf[0] = (uint8_t)SENSOR_DATA;
1676  }
1677 
1678  CryptModule::random (buf + iv_idx, IV_LENGTH);
1679 
1680  DEBUG_VERBOSE ("IV: %s", printHexBuffer (buf + iv_idx, IV_LENGTH));
1681 
1682  memcpy (buf + nodeId_idx, &nodeId, sizeof (uint16_t));
1683 
1684  if (dataMsgType != CONTROL_TYPE) { // Control messages and data messages use different counters
1685  if (useCounter) {
1686  counter = node.getLastMessageCounter () + 1;
1687  node.setLastMessageCounter (counter);
1688  rtcmem_data.lastMessageCounter = counter;
1689  } else {
1690  counter = (uint16_t)(Crypto.random ());
1691  }
1692  } else {
1693  if (useCounter) {
1694  counter = node.getLastControlCounter () + 1;
1695  node.setLastControlCounter (counter);
1696  rtcmem_data.lastControlCounter = counter;
1697  } else {
1698  counter = (uint16_t)(Crypto.random ());
1699  }
1700  }
1701 
1702  if (dataMsgType != CONTROL_TYPE) {
1703  DEBUG_INFO ("Data message #%d", counter);
1704  } else {
1705  DEBUG_INFO ("Control message #%d", counter);
1706  }
1707 
1708  memcpy (buf + counter_idx, &counter, sizeof (uint16_t));
1709 
1710  buf[encoding_idx] = payloadEncoding;
1711 
1712  memcpy (buf + data_idx, data, len);
1713 
1714  uint16_t packet_length = tag_idx;
1715 
1716  memcpy (buf + length_idx, &packet_length, sizeof (uint16_t));
1717 
1718  DEBUG_VERBOSE ("Data message: %s", printHexBuffer (buf, packet_length));
1719  DEBUG_DBG ("Encoding: 0x%02X", payloadEncoding);
1720 
1721  uint8_t* crypt_buf = buf + length_idx;
1722 
1723  size_t cryptLen = packet_length - 1 - IV_LENGTH;
1724 
1725  uint8_t addDataLen = 1 + IV_LENGTH;
1726  uint8_t aad[AAD_LENGTH + addDataLen];
1727 
1728  memcpy (aad, buf, addDataLen); // Copy message upto iv
1729 
1730  // Copy 8 last bytes from Node Key
1731  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1732 
1733  if (!CryptModule::encryptBuffer (crypt_buf, cryptLen, // Encrypt from length
1734  buf + iv_idx, IV_LENGTH,
1735  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of node key
1736  aad, sizeof (aad), buf + tag_idx, TAG_LENGTH)) {
1737  DEBUG_ERROR ("Error during encryption");
1738  return false;
1739  }
1740 
1741  DEBUG_VERBOSE ("Encrypted data message: %s", printHexBuffer (buf, packet_length + TAG_LENGTH));
1742 
1743  if (dataMsgType == CONTROL_TYPE) {
1744  DEBUG_INFO (" -------> CONTROL MESSAGE");
1745  } else if (dataMsgType == HA_DISC_TYPE) {
1746  DEBUG_INFO (" -------> HA DISCOVERY MESSAGE");
1747  } else {
1748  DEBUG_INFO (" -------> DATA");
1749  }
1750 #if DEBUG_LEVEL >= VERBOSE
1751  char macStr[ENIGMAIOT_ADDR_LEN * 3];
1752  DEBUG_DBG ("Destination address: %s", mac2str (rtcmem_data.gateway, macStr));
1753 #endif
1754 
1755  if (useCounter) { // RTC must not be written if OTA is running. OTA uses RTC memmory to signal 2nd firmware boot
1756  if (!saveRTCData ()) {
1757  DEBUG_ERROR ("Error saving data on RTC");
1758  }
1759  }
1760 
1761  return (comm->send (rtcmem_data.gateway, buf, packet_length + TAG_LENGTH) == 0);
1762 }
1763 
1764 bool EnigmaIOTNodeClass::sendHADiscoveryMessage (const uint8_t* data, size_t len) {
1765  if (!data || !len) {
1766  DEBUG_WARN ("Empty buffer");
1767  return false;
1768  }
1769  return sendData (data, len, HA_DISC_TYPE, true, MSG_PACK);
1770 }
1771 
1772 bool EnigmaIOTNodeClass::processGetSleepTimeCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1773  uint8_t buffer[MAX_MESSAGE_LENGTH];
1774  uint8_t bufLength;
1775 
1776  DEBUG_DBG ("Get Sleep command received");
1777  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
1778 
1779  buffer[0] = control_message_type::SLEEP_ANS;
1780 
1781  uint32_t sleepTime = getSleepTime ();
1782  memcpy (buffer + 1, &sleepTime, sizeof (sleepTime));
1783  bufLength = 5;
1784 
1785  if (sendData (buffer, bufLength, CONTROL_TYPE)) {
1786  DEBUG_DBG ("Sleep time is %d seconds", sleepTime);
1787  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
1788  return true;
1789  } else {
1790  DEBUG_WARN ("Error sending version response");
1791  return false;
1792  }
1793 }
1794 
1795 bool EnigmaIOTNodeClass::processGetNameCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1796  uint8_t buffer[MAX_MESSAGE_LENGTH];
1797  uint8_t bufLength;
1798 
1799  DEBUG_DBG ("Get Name command received");
1800  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
1801 
1802  buffer[0] = control_message_type::NAME_ANS;
1803 
1804  uint8_t* nodeAddress = node.getMacAddress ();
1805 
1806  char* name = rtcmem_data.nodeName;
1807  size_t nameLen = 0;
1808  if (name) {
1809  nameLen = strlen (name);
1810  } else {
1811  DEBUG_WARN ("Emprty name");
1812  return false;
1813  }
1814 
1815  memcpy (buffer + 1, nodeAddress, ENIGMAIOT_ADDR_LEN);
1816  memcpy (buffer + 1 + ENIGMAIOT_ADDR_LEN, name, nameLen);
1817  bufLength = 1 + ENIGMAIOT_ADDR_LEN + nameLen;
1818 
1819  if (sendData (buffer, bufLength, CONTROL_TYPE)) {
1820  DEBUG_DBG ("Node name is %s", name ? name : "NULL name");
1821  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
1822  return true;
1823  } else {
1824  DEBUG_WARN ("Error sending name response");
1825  return false;
1826  }
1827 }
1828 
1829 bool EnigmaIOTNodeClass::processSetNameResponse (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1830  /*
1831  * ---------------------------------------------------
1832  *| msgType (1) | IV (12) | Result code (1) | tag (16) |
1833  * ---------------------------------------------------
1834  */
1835  struct __attribute__ ((packed, aligned (1))) {
1836  uint8_t msgType;
1837  uint8_t iv[IV_LENGTH];
1838  uint16_t counter;
1839  int8_t errorCode;
1840  uint8_t tag[TAG_LENGTH];
1841  } nodeNameSetResponse_msg;
1842 
1843  uint16_t counter;
1844 
1845  const unsigned int NNSRMSG_LEN = sizeof (nodeNameSetResponse_msg);
1846 
1847  if (len < NNSRMSG_LEN) {
1848  DEBUG_WARN ("Message too short");
1849  return false;
1850  }
1851  memcpy (&nodeNameSetResponse_msg, data, len);
1852 
1853  const uint8_t addDataLen = 1 + IV_LENGTH;
1854  uint8_t aad[AAD_LENGTH + addDataLen];
1855 
1856  memcpy (aad, (uint8_t*)&nodeNameSetResponse_msg, addDataLen); // Copy message upto iv
1857 
1858  // Copy 8 last bytes from NetworkKey
1859  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1860 
1861  if (!CryptModule::decryptBuffer ((uint8_t*)&(nodeNameSetResponse_msg.errorCode), sizeof (uint8_t),
1862  nodeNameSetResponse_msg.iv, IV_LENGTH,
1863  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
1864  aad, sizeof (aad), nodeNameSetResponse_msg.tag, TAG_LENGTH)) {
1865  DEBUG_ERROR ("Error during decryption");
1866  return false;
1867  }
1868 
1869  DEBUG_VERBOSE ("Decrypted Node Name Set response message: %s", printHexBuffer ((uint8_t*)&nodeNameSetResponse_msg, NNSRMSG_LEN - TAG_LENGTH));
1870 
1871  memcpy (&counter, &(nodeNameSetResponse_msg.counter), sizeof (uint16_t));
1872  DEBUG_INFO ("Downlink msg #%d", counter);
1873  if (useCounter) {
1874  if (counter > node.getLastDownlinkMsgCounter ()) {
1875  DEBUG_INFO ("Accepted");
1876  node.setLastDownlinkMsgCounter (counter);
1878  } else {
1879  DEBUG_WARN ("Downlink msg rejected");
1880  return false;
1881  }
1882  }
1883 
1884  if (nodeNameSetResponse_msg.errorCode != NAME_OK) {
1885  DEBUG_WARN ("Name error: %d", nodeNameSetResponse_msg.errorCode);
1886  } else {
1887  DEBUG_DBG ("Name set correctly");
1888  }
1889 
1890  if (useCounter && !otaRunning) { // RTC must not be written if OTA is running. OTA uses RTC memmory to signal 2nd firmware boot
1891  if (!saveRTCData ()) {
1892  DEBUG_ERROR ("Error saving data on RTC");
1893  }
1894  }
1895 
1896  return true;
1897 }
1898 
1899 bool EnigmaIOTNodeClass::processSetNameCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1900  uint8_t buffer[MAX_MESSAGE_LENGTH];
1901  uint8_t bufLength;
1902 
1903  DEBUG_DBG ("Set Name command received");
1904  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
1905 
1906  buffer[0] = control_message_type::NAME_ANS;
1907 
1908  uint8_t* nodeAddress = node.getMacAddress ();
1909 
1910  memcpy (rtcmem_data.nodeName, data + 1, len - 1);
1912 
1913  saveRTCData ();
1914  saveFlashData ();
1915 
1917  DEBUG_WARN ("Error sending set node name %s", rtcmem_data.nodeName);
1918  }
1919 
1920  size_t nameLen = strlen (rtcmem_data.nodeName);
1921 
1922  memcpy (buffer + 1, nodeAddress, ENIGMAIOT_ADDR_LEN);
1923  memcpy (buffer + 1 + ENIGMAIOT_ADDR_LEN, rtcmem_data.nodeName, nameLen);
1924  bufLength = 1 + ENIGMAIOT_ADDR_LEN + nameLen;
1925 
1926  if (sendData (buffer, bufLength, CONTROL_TYPE)) {
1927  DEBUG_DBG ("Node name is %s", rtcmem_data.nodeName);
1928  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
1929  return true;
1930  } else {
1931  DEBUG_WARN ("Error sending name response");
1932  return false;
1933  }
1934 }
1935 
1936 bool EnigmaIOTNodeClass::sendNodeNameSet (const char* name) {
1937  if (!name)
1938  return false;
1939 
1940  size_t nameLength = strlen (name);
1941 
1942  DEBUG_INFO ("Setting node name to %s. Size: %d", name, nameLength);
1943 
1944  if (!nameLength || (nameLength > NODE_NAME_LENGTH)) {
1945  return false;
1946  }
1947 
1948  /*
1949  * ------------------------------------------------------------------------------------
1950  *| msgType (1) | IV (12) | NodeID (2) | Counter (2) | Node name (up to 32) | tag (16) |
1951  * ------------------------------------------------------------------------------------
1952  */
1953 
1954  uint8_t buf[MAX_MESSAGE_LENGTH];
1955  //uint8_t tag[TAG_LENGTH];
1956  uint16_t nodeId = node.getNodeId ();
1957  uint16_t counter;
1958 
1959  uint8_t iv_idx = 1;
1960  uint8_t nodeId_idx = iv_idx + IV_LENGTH;
1961  uint8_t counter_idx = nodeId_idx + sizeof (int16_t);
1962  uint8_t nodeName_idx = counter_idx + sizeof (int16_t);
1963  uint8_t tag_idx = nodeName_idx + nameLength;
1964 
1965  size_t packet_length = 1 + IV_LENGTH + sizeof (int16_t) + sizeof (int16_t) + nameLength;
1966 
1967 
1968  buf[0] = (uint8_t)NODE_NAME_SET;
1969 
1970  CryptModule::random (buf + iv_idx, IV_LENGTH);
1971 
1972  DEBUG_VERBOSE ("IV: %s", printHexBuffer (buf + iv_idx, IV_LENGTH));
1973 
1974  if (useCounter) {
1975  counter = node.getLastControlCounter () + 1;
1976  node.setLastControlCounter (counter);
1977  rtcmem_data.lastControlCounter = counter;
1978  } else {
1979  counter = (uint16_t)(Crypto.random ());
1980  }
1981 
1982  DEBUG_INFO ("Control message #%d", counter);
1983 
1984  memcpy (buf + counter_idx, &counter, sizeof (uint16_t));
1985 
1986  memcpy (buf + nodeId_idx, &nodeId, sizeof (uint16_t));
1987 
1988  memcpy (buf + nodeName_idx, name, nameLength);
1989 
1990  DEBUG_VERBOSE ("Set node name message: %s", printHexBuffer (buf, packet_length));
1991 
1992  uint8_t* crypt_buf = buf + nodeId_idx;
1993 
1994  size_t cryptLen = packet_length - 1 - IV_LENGTH;
1995 
1996  uint8_t addDataLen = 1 + IV_LENGTH;
1997  uint8_t aad[AAD_LENGTH + addDataLen];
1998 
1999  memcpy (aad, buf, addDataLen); // Copy message upto iv
2000 
2001  // Copy 8 last bytes from Node Key
2002  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
2003 
2004  if (!CryptModule::encryptBuffer (crypt_buf, cryptLen, // Encrypt from length
2005  buf + iv_idx, IV_LENGTH,
2006  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of node key
2007  aad, sizeof (aad), buf + tag_idx, TAG_LENGTH)) {
2008  DEBUG_ERROR ("Error during encryption");
2009  return false;
2010  }
2011 
2012  DEBUG_VERBOSE ("Encrypted set node name message: %s", printHexBuffer (buf, packet_length + TAG_LENGTH));
2013 
2014 #if DEBUG_LEVEL >= VERBOSE
2015  char macStr[ENIGMAIOT_ADDR_LEN * 3];
2016  DEBUG_DBG ("Destination address: %s", mac2str (rtcmem_data.gateway, macStr));
2017 #endif
2018 
2019  flashBlue = true;
2020 
2021  DEBUG_INFO ("-------> NODE NAME SEND");
2022 
2023  if (useCounter && !otaRunning) { // RTC must not be written if OTA is running. OTA uses RTC memmory to signal 2nd firmware boot
2024  if (!saveRTCData ()) {
2025  DEBUG_ERROR ("Error saving data on RTC");
2026  }
2027  }
2028 
2029  return (comm->send (rtcmem_data.gateway, buf, packet_length + TAG_LENGTH) == 0);
2030 
2031 }
2032 
2033 bool EnigmaIOTNodeClass::processSetIdentifyCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
2034  //uint8_t buffer[MAX_MESSAGE_LENGTH];
2035  //uint8_t bufLength;
2036 
2037  DEBUG_DBG ("Set Identify command received");
2038  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
2039 
2040  DEBUG_WARN ("IDENTIFY");
2041  startIdentifying (1000);
2042 
2043  return true;
2044 }
2045 
2046 bool EnigmaIOTNodeClass::processGetRSSICommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
2047  requestSearchGateway = true;
2048  requestReportRSSI = true;
2049 
2050  return true;
2051 }
2052 
2053 bool EnigmaIOTNodeClass::processSetRestartCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
2054  DEBUG_WARN ("Restart due to command");
2056  return true;
2057 }
2058 
2059 bool EnigmaIOTNodeClass::processSetResetConfigCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
2060  uint8_t buffer[MAX_MESSAGE_LENGTH];
2061  uint8_t bufLength;
2062 
2063  DEBUG_DBG ("Reset Config command received");
2064  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
2065 
2066  buffer[0] = control_message_type::RESET_ANS;
2067  bufLength = 1;
2068 
2069  configCleared = true; // Disable any possible saving to flash or RTC memory
2070 
2071  bool result;
2072 
2073  if ((result = sendData (buffer, bufLength, CONTROL_TYPE))) {
2074  DEBUG_DBG ("Reset Config about to be executed", sleepTime);
2075  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
2076  } else {
2077  DEBUG_WARN ("Error sending Reset Config response");
2078  }
2079 
2080  DEBUG_WARN ("Send restart command before deleting config");
2082  sendRestart ();
2083 
2084  comm->enableTransmit (false);
2085  clearRTC ();
2086  clearFlash ();
2087 
2089 
2090  return result;
2091 }
2092 
2094  uint8_t data[sizeof (rtcmem_data)];
2095 
2096  if (protectOTA || otaRunning) {
2097  DEBUG_WARN ("Cannot write to RTC memory");
2098  return;
2099  }
2100 
2101  memset (data, 0, sizeof (rtcmem_data));
2102 
2103 #ifdef ESP8266
2104  ESP.rtcUserMemoryWrite (RTC_ADDRESS, (uint32_t*)data, sizeof (rtcmem_data));
2105 #elif defined ESP32
2106  memset (&rtcmem_data_storage, 0, sizeof (rtcmem_data));
2107 #endif
2108 
2109 #if USE_FLASH_INSTEAD_RTC
2110  FILESYSTEM.begin ();
2111  FILESYSTEM.remove (RTC_DATA_FILE);
2112  FILESYSTEM.end ();
2113 #endif
2114 
2115  DEBUG_DBG ("RTC Cleared");
2116 }
2117 
2118 bool EnigmaIOTNodeClass::processSetSleepTimeCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
2119  uint8_t buffer[MAX_MESSAGE_LENGTH];
2120  uint8_t bufLength;
2121 
2122  DEBUG_DBG ("Set Sleep command received");
2123  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
2124  if (!FILESYSTEM.begin ()) {
2125  DEBUG_ERROR ("Error mounting flash");
2126  }
2127  bool result = loadFlashData ();
2128  if (!result) {
2129  DEBUG_WARN ("Error loading configuration");
2130  }
2131 
2132  buffer[0] = control_message_type::SLEEP_ANS;
2133 
2134  uint32_t sleepTime;
2135  memcpy (&sleepTime, data + 1, sizeof (uint32_t));
2136  DEBUG_DBG ("Sleep time requested: %d", sleepTime);
2138  sleepTime = getSleepTime ();
2139  if (sleepTime > 0) {
2140  if (result) {
2141  if ((result = saveFlashData ())) {
2142  DEBUG_DBG ("Saved config data after set sleep time command");
2143  } else {
2144  DEBUG_WARN ("Error saving data after set sleep time command");
2145  }
2146  }
2147  FILESYSTEM.end ();
2148  }
2149  memcpy (buffer + 1, &sleepTime, sizeof (sleepTime));
2150  bufLength = 5;
2151 
2152  if (sendData (buffer, bufLength, CONTROL_TYPE)) {
2153  DEBUG_DBG ("Sleep time is %d seconds", sleepTime);
2154  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
2155  return result;
2156  } else {
2157  DEBUG_WARN ("Error sending version response");
2158  return false;
2159  }
2160 }
2161 
2162 
2163 bool EnigmaIOTNodeClass::processVersionCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
2164  uint8_t buffer[MAX_MESSAGE_LENGTH];
2165  uint8_t bufLength;
2166 
2168  memcpy (buffer + 1, ENIGMAIOT_PROT_VERS, sizeof (ENIGMAIOT_PROT_VERS));
2169  bufLength = sizeof (ENIGMAIOT_PROT_VERS) + 1;
2170  DEBUG_DBG ("Version command received");
2171  if (sendData (buffer, bufLength, CONTROL_TYPE)) {
2172  DEBUG_DBG ("Version is %s", ENIGMAIOT_PROT_VERS);
2173  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
2174  return true;
2175  } else {
2176  DEBUG_WARN ("Error sending version response");
2177  return false;
2178  }
2179 }
2180 
2181 bool EnigmaIOTNodeClass::processOTACommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
2182  const uint8_t MAX_OTA_RESPONSE_LENGTH = 4;
2183 
2184  uint8_t responseBuffer[MAX_OTA_RESPONSE_LENGTH];
2185 
2186  //DEBUG_VERBOSE ("Data: %s", printHexBuffer (data, len));
2187  uint16_t msgIdx;
2188  static char md5buffer[33];
2189  char md5calc[32];
2190  static uint16_t numMsgs;
2191  static uint32_t otaSize;
2192  static uint16_t oldIdx;
2193  static bool otaRecoverRequested = false;
2194  static MD5Builder _md5;
2195  uint8_t* dataPtr = (uint8_t*)(data + 1);
2196  uint8_t dataLen = len - 1;
2197 
2198  if (dataLen < 2) {
2199  DEBUG_ERROR ("OTA message is too short: %u bytes", dataLen + 1);
2200  return false;
2201  }
2202 
2203  memcpy (&msgIdx, dataPtr, sizeof (uint16_t));
2204  dataPtr += sizeof (uint16_t);
2205  dataLen -= sizeof (uint16_t);
2206  DEBUG_INFO ("OTA message #%u", msgIdx);
2207  if (msgIdx > 0 && otaRunning) {
2208  if (msgIdx != (oldIdx + 1)) {
2209  if (!otaRecoverRequested) {
2210  otaRecoverRequested = true;
2211  responseBuffer[0] = control_message_type::OTA_ANS;
2212  responseBuffer[1] = ota_status::OTA_OUT_OF_SEQUENCE;
2213  memcpy (responseBuffer + 2, (uint8_t*)&oldIdx, sizeof (oldIdx));
2214  sendData (responseBuffer, 4, CONTROL_TYPE);
2215  DEBUG_ERROR ("%u OTA messages missing before %u", msgIdx - oldIdx - 1, msgIdx);
2216  //otaRunning = false;
2217  //otaError = true;
2218  }
2219  return true;
2220  } else {
2221  oldIdx = msgIdx;
2222  otaRecoverRequested = false;
2223  }
2224  }
2225  lastOTAmsg = millis ();
2226 
2227  if (msgIdx == 0) {
2228  if (dataLen < 38) {
2229  DEBUG_ERROR ("OTA message #0 is too short: %u bytes", dataLen + 3);
2230  return false;
2231  }
2232  memcpy (&otaSize, dataPtr, sizeof (uint32_t));
2233  DEBUG_INFO ("OTA size: %u bytes", otaSize);
2234  dataPtr += sizeof (uint32_t);
2235  dataLen -= sizeof (uint32_t);
2236  memcpy (&numMsgs, dataPtr, sizeof (uint16_t));
2237  DEBUG_INFO ("Number of OTA messages: %u", numMsgs);
2238  dataPtr += sizeof (uint16_t);
2239  dataLen -= sizeof (uint16_t);
2240  memcpy (md5buffer, dataPtr, 32);
2241  md5buffer[32] = '\0';
2242  DEBUG_VERBOSE ("MD5: %s", printHexBuffer ((uint8_t*)md5buffer, 32));
2243  otaRunning = true;
2244  otaError = false;
2245  _md5.begin ();
2246  responseBuffer[0] = control_message_type::OTA_ANS;
2247  responseBuffer[1] = ota_status::OTA_STARTED;
2248  if (sendData (responseBuffer, 2, CONTROL_TYPE)) {
2249  DEBUG_WARN ("OTA STARTED");
2250  restart (IRRELEVANT, false); // Force unregistration after boot so that sleepy status is synchronized
2251  // on Gateway
2252  if (!Update.begin (otaSize)) {
2253  DEBUG_ERROR ("Error begginning OTA. OTA size: %u", otaSize);
2254  return false;
2255  }
2256 #ifdef ESP8266
2257  Update.runAsync (true);
2258 #endif
2259  if (!Update.setMD5 (md5buffer)) {
2260  DEBUG_ERROR ("Error setting MD5");
2261  return false;
2262  }
2263  }
2264  } else {
2265  if (otaRunning) {
2266  static size_t totalBytes = 0;
2267 
2268  _md5.add (dataPtr, dataLen);
2269  comm->enableTransmit (false);
2270  // Process OTA Update
2271 #if DEBUG_LEVEL >= INFO
2272  size_t numBytes =
2273 #endif
2274  Update.write (dataPtr, dataLen);
2275  comm->enableTransmit (true);
2276  totalBytes += dataLen;
2277  DEBUG_INFO ("%u bytes written. Total %u", numBytes, totalBytes);
2278  } else {
2279  if (!otaError) {
2280  otaError = true;
2281  responseBuffer[0] = control_message_type::OTA_ANS;
2282  responseBuffer[1] = ota_status::OTA_START_ERROR;
2283  sendData (responseBuffer, 2, CONTROL_TYPE);
2284  DEBUG_ERROR ("OTA error. Message 0 not received");
2285  }
2286  }
2287  }
2288 
2289  if (msgIdx == numMsgs && otaRunning) {
2290  StreamString otaErrorStr;
2291 
2292  DEBUG_INFO ("OTA end");
2293  _md5.calculate ();
2294  DEBUG_DBG ("OTA MD5 %s", _md5.toString ().c_str ());
2295  _md5.getChars (md5calc);
2296  if (!memcmp (md5calc, md5buffer, 32)) {
2297  responseBuffer[0] = control_message_type::OTA_ANS;
2298  responseBuffer[1] = ota_status::OTA_CHECK_OK;
2299  sendData (responseBuffer, 2, CONTROL_TYPE);
2300  DEBUG_WARN ("OTA MD5 check OK");
2301  } else {
2302  responseBuffer[0] = control_message_type::OTA_ANS;
2303  responseBuffer[1] = ota_status::OTA_CHECK_FAIL;
2304  sendData (responseBuffer, 2, CONTROL_TYPE);
2305  DEBUG_ERROR ("OTA MD5 check failed");
2306  }
2307  Serial.print ('.');
2308  while (!Update.isFinished ()) {
2309  Serial.print ('.');
2310  delay (100);
2311  }
2312  Serial.println ();
2313 
2314  if (Update.end ()) {
2315  responseBuffer[0] = control_message_type::OTA_ANS;
2316  responseBuffer[1] = ota_status::OTA_FINISHED;
2317  sendData (responseBuffer, 2, CONTROL_TYPE);
2318  //uint8_t otaErrorCode = Update.getError ();
2319  DEBUG_WARN ("OTA Finished OK");
2320  DEBUG_WARN ("OTA eror code: %d", Update.getError ());
2321  //ESP.restart ();
2322  protectOTA = true;
2323  //otaRunning = false;
2324  shouldRestart = true;
2326  //clearRTC ();
2327  return true; // Restart does not happen inmediatelly, so code goes on
2328  } else {
2329  responseBuffer[0] = control_message_type::OTA_ANS;
2330  responseBuffer[1] = ota_status::OTA_CHECK_FAIL;
2331  sendData (responseBuffer, 2, CONTROL_TYPE);
2332  //uint8_t otaErrorCode = Update.getError ();
2333  Update.printError (otaErrorStr);
2334  otaErrorStr.trim (); // remove line ending
2335  DEBUG_ERROR ("OTA Failed");
2336  DEBUG_WARN ("OTA eror code: %s", otaErrorStr.c_str ());
2337  Serial.println ("OTA failed");
2338  otaRunning = false;
2339  shouldRestart = true;
2341  return false;
2342  }
2343  delay (500);
2344  DEBUG_WARN ("Restart after OTA");
2346  }
2347 
2348  return true;
2349 }
2350 
2351 void EnigmaIOTNodeClass::restart (restartReason_t reason, bool reboot) {
2353  rtcmem_data.nodeKeyValid = false; // Force resync
2354  if (!saveRTCData ()) {
2355  DEBUG_ERROR ("Error saving data on RTC");
2356  }
2357  DEBUG_WARN ("Reset configuration data in RTC memory");
2358  // if (reboot)
2359  shouldRestart = reboot;
2360  if (reason != IRRELEVANT) {
2361  restartReason = reason;
2362  }
2363  //ESP.restart ();
2364 }
2365 
2366 bool EnigmaIOTNodeClass::processControlCommand (const uint8_t* mac, const uint8_t* data, size_t len, bool broadcast) {
2367 
2368  DEBUG_VERBOSE ("Data: %s", printHexBuffer (data, len));
2369  DEBUG_DBG ("%s control command", broadcast ? "Broadcast" : "Unicast");
2370  switch (data[0]) {
2372  return processVersionCommand (mac, data, len);
2374  return processGetSleepTimeCommand (mac, data, len);
2376  return processSetSleepTimeCommand (mac, data, len);
2378  return processSetIdentifyCommand (mac, data, len);
2380  return processSetResetConfigCommand (mac, data, len);
2382  return processGetRSSICommand (mac, data, len);
2384  return processGetNameCommand (mac, data, len);
2386  if (!broadcast) { // DO NOT PROCESS BROADCAST NAME SET
2387  return processSetNameCommand (mac, data, len);
2388  }
2389  break;
2391  return processSetRestartCommand (mac, data, len);
2393  return processBroadcastKeyMessage (mac, data, len);
2395  if (!broadcast) { // DO NOT PROCESS BROADCAST OTA MESSAGES
2396  if (processOTACommand (mac, data, len)) {
2397  return true;
2398  } else {
2399  DEBUG_ERROR ("Error processing OTA");
2401  }
2402  }
2403  break;
2404  }
2405  return false;
2406 }
2407 
2408 bool EnigmaIOTNodeClass::processBroadcastKeyMessage (const uint8_t* mac, const uint8_t* buf, size_t count) {
2409  if (!buf || count != KEY_LENGTH + 1) {
2410  DEBUG_WARN ("Invalid broadcast key message. Incorrect length %d", count);
2411  return false;
2412  }
2413 
2414  int broadcastKey_idx = 1;
2415 
2416  DEBUG_VERBOSE ("Broadcast key: %s", printHexBuffer (&buf[broadcastKey_idx], KEY_LENGTH));
2417 
2418  memcpy (rtcmem_data.broadcastKey, &buf[broadcastKey_idx], KEY_LENGTH);
2421 
2422  return true;
2423 }
2424 
2425 bool EnigmaIOTNodeClass::processDownstreamData (const uint8_t* mac, const uint8_t* buf, size_t count, bool control) {
2426  /*
2427  * --------------------------------------------------------------------------
2428  *| msgType (1) | IV (12) | length (2) | Counter (2) | NodeId (2) | Data (....) | Tag (16) |
2429  * --------------------------------------------------------------------------
2430  */
2431 
2432  uint8_t iv_idx = 1;
2433  uint8_t length_idx = iv_idx + IV_LENGTH;
2434  uint8_t nodeId_idx = length_idx + sizeof (int16_t);
2435  uint8_t counter_idx = nodeId_idx + sizeof (int16_t);
2436  uint8_t encoding_idx;
2437  uint8_t data_idx;
2438  if (!control) {
2439  encoding_idx = counter_idx + sizeof (int16_t);
2440  data_idx = encoding_idx + sizeof (int8_t);
2441  } else {
2442  data_idx = counter_idx + sizeof (int16_t);
2443  }
2444  uint8_t tag_idx = count - TAG_LENGTH;
2445 
2446  uint16_t counter;
2447  uint16_t nodeId;
2448  bool broadcast = (buf[0] & 0x80);
2449 
2450  //if (broadcast) {
2451  // DEBUG_WARN ("Broadcast message. Type: 0x%X", buf[0]);
2452  //}
2453 
2454  const uint8_t addDataLen = 1 + IV_LENGTH;
2455  uint8_t aad[AAD_LENGTH + addDataLen];
2456 
2457  memcpy (aad, buf, addDataLen); // Copy message upto iv
2458 
2459  uint8_t packetLen = count - TAG_LENGTH;
2460 
2461  if (broadcast) {
2462  memcpy (aad + addDataLen, rtcmem_data.broadcastKey + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH); // Copy 8 last bytes from Node Key
2463  if (!CryptModule::decryptBuffer (buf + length_idx, packetLen - 1 - IV_LENGTH, // Decrypt from nodeId
2464  buf + iv_idx, IV_LENGTH,
2465  rtcmem_data.broadcastKey, KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
2466  aad, sizeof (aad), buf + tag_idx, TAG_LENGTH)) {
2467  DEBUG_ERROR ("Error during decryption of broadcast message");
2468  return false;
2469  }
2470  } else {
2471  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH); // Copy 8 last bytes from Node Key
2472  if (!CryptModule::decryptBuffer (buf + length_idx, packetLen - 1 - IV_LENGTH, // Decrypt from nodeId
2473  buf + iv_idx, IV_LENGTH,
2474  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
2475  aad, sizeof (aad), buf + tag_idx, TAG_LENGTH)) {
2476  DEBUG_ERROR ("Error during decryption");
2477  return false;
2478  }
2479  }
2480 
2481  DEBUG_VERBOSE ("Decripted downstream message: %s", printHexBuffer (buf, count - TAG_LENGTH));
2482 
2483  memcpy (&nodeId, &(buf[nodeId_idx]), sizeof (uint16_t));
2484 
2485  memcpy (&counter, &(buf[counter_idx]), sizeof (uint16_t));
2486  DEBUG_INFO ("Downlink msg #%d", counter);
2487  if (useCounter) {
2488  if (broadcast) {
2489  if (counter > lastBroadcastMsgCounter) {
2490  DEBUG_INFO ("Accepted. Counter was %u", lastBroadcastMsgCounter);
2491  lastBroadcastMsgCounter = counter;
2492  }
2493  } else {
2494  if (counter > node.getLastDownlinkMsgCounter ()) {
2495  DEBUG_INFO ("Accepted. Counter was %u", node.getLastDownlinkMsgCounter ());
2496  node.setLastDownlinkMsgCounter (counter);
2498  } else {
2499  DEBUG_WARN ("Downlink msg rejected");
2500  return false;
2501  }
2502  }
2503  }
2504 
2505  if (useCounter && !otaRunning) { // RTC must not be written if OTA is running. OTA uses RTC memmory to signal 2nd firmware boot
2506  if (!saveRTCData ()) {
2507  DEBUG_ERROR ("Error saving data on RTC");
2508  }
2509  }
2510 
2511  if (control) {
2512  DEBUG_INFO ("Control command");
2513  DEBUG_VERBOSE ("Data: %s", printHexBuffer (&buf[data_idx], tag_idx - data_idx));
2514  return processControlCommand (mac, &buf[data_idx], tag_idx - data_idx, broadcast);
2515  }
2516 
2517  DEBUG_VERBOSE ("Sending data notification. Payload length: %d", tag_idx - data_idx);
2518  if (notifyData) {
2519  notifyData (mac, &buf[data_idx], tag_idx - data_idx, (nodeMessageType_t)(buf[0]), (nodePayloadEncoding_t)(buf[encoding_idx]));
2520  }
2521 
2522  return true;
2523 
2524 }
2525 
2526 
2527 nodeInvalidateReason_t EnigmaIOTNodeClass::processInvalidateKey (const uint8_t* mac, const uint8_t* buf, size_t count) {
2528 
2529  // TODO: Encrypt using network key, adding some random data.This is to avoid DoS attack.
2530  // I have to investigate if this may really work.
2531  // Other options:
2532  // - mark message using timestamp. May not work with gateways not connected to Internet.
2533  // - Adding a number calculated from node message (a byte should be sufficient).
2534  // For instance nth byte + 3. Most probable candidate
2535 
2536 #define IKMSG_LEN 2
2537  if (buf && count < IKMSG_LEN) {
2538  return UNKNOWN_ERROR;
2539  }
2540 
2541  DEBUG_WARN ("Invalidate key request. Reason: %u", buf[1]);
2542  uint8_t reason = buf[1];
2543  if (reason < KEY_EXPIRED) {
2544  if (dataMessageSentLength > 0)
2545  dataMessageSendPending = true; // Start last data retransmission
2546  }
2547 
2548  return (nodeInvalidateReason_t)reason;
2549 }
2550 
2551 void EnigmaIOTNodeClass::manageMessage (const uint8_t* mac, const uint8_t* buf, uint8_t count) {
2552  DEBUG_INFO ("Reveived message. Origin MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
2553  DEBUG_VERBOSE ("Received data: %s", printHexBuffer (const_cast<uint8_t*>(buf), count));
2554  flashBlue = true;
2555 
2556  if (count <= 1) {
2557  DEBUG_ERROR ("Empty message received");
2558  return;
2559  }
2560 
2561  // All downlink messages should come from gateway
2562  if (memcmp (mac, rtcmem_data.gateway, comm->getAddressLength ()) != 0) {
2563  DEBUG_ERROR ("Message doesn't come from gateway");
2564  return;
2565  }
2566 
2567  switch (buf[0]) {
2568  case SERVER_HELLO:
2569  DEBUG_INFO (" <------- SERVER HELLO");
2570  if (node.getStatus () == WAIT_FOR_SERVER_HELLO) {
2571  if (processServerHello (mac, buf, count)) {
2572  // mark node as registered
2573  //stopFlash (); // Do not flash during setup for less battery drain
2574  node.setKeyValid (true);
2575  rtcmem_data.nodeKeyValid = true;
2576  node.setKeyValidFrom (millis ());
2580 
2581  // save context to RTC memory
2587  DEBUG_INFO ("Reset counters");
2588  if (!saveRTCData ()) {
2589  DEBUG_ERROR ("Error saving data on RTC");
2590  }
2591 
2592  // request clock sync if non sleepy
2593  //if (!node.getSleepy () && node.isRegistered ())
2594  // clockRequest ();
2595 
2596 #if DEBUG_LEVEL >= INFO
2598 #endif
2600  DEBUG_WARN ("Error sending set node name %s", rtcmem_data.nodeName ? rtcmem_data.nodeName : "NULL name");
2601  }
2602 
2603  // send notification to user code
2604  if (notifyConnection) {
2605  notifyConnection ();
2606  }
2607  // Resend last message in case of it is still pending to be sent.
2608  // If key expired it was successfully sent before so retransmission is not needed
2609  if (invalidateReason < KEY_EXPIRED && dataMessageSentLength > 0) {
2610  if (node.getStatus () == REGISTERED && node.isKeyValid ()) {
2612  DEBUG_INFO ("Data pending to be sent. Length: %u", dataMessageSentLength);
2613  DEBUG_VERBOSE ("Data sent: %s", printHexBuffer (dataMessageSent, dataMessageSentLength));
2615  //dataMessageSentLength = 0;
2616  dataMessageSendPending = false;
2617 
2618  flashBlue = true;
2619  }
2620  }
2621  }
2622  cycleStartedTime = millis ();
2623 
2624 
2625  } else {
2626  node.reset ();
2627  }
2628  } else {
2629  node.reset ();
2630  }
2631  break;
2632  case INVALIDATE_KEY:
2633  DEBUG_INFO (" <------- INVALIDATE KEY");
2634  invalidateReason = processInvalidateKey (mac, buf, count);
2635  requestSearchGateway = true;
2636  node.reset ();
2641  TimeManager.reset ();
2643  if (notifyDisconnection) {
2645  }
2646  break;
2647 
2649  if (!node.broadcastIsEnabled ()) {
2650  break;
2651  }
2652  case DOWNSTREAM_DATA_SET:
2653  DEBUG_INFO (" <------- DOWNSTREAM DATA SET");
2654  if (processDownstreamData (mac, buf, count)) {
2655  DEBUG_INFO ("Downstream Data set OK");
2656  }
2657  break;
2658 
2660  if (!node.broadcastIsEnabled ()) {
2661  break;
2662  }
2663  case DOWNSTREAM_DATA_GET:
2664  DEBUG_INFO (" <------- DOWNSTREAM DATA GET");
2665  if (processDownstreamData (mac, buf, count)) {
2666  DEBUG_INFO ("Downstream Data set OK");
2667  }
2668  break;
2669 
2671  if (!node.broadcastIsEnabled ()) {
2672  break;
2673  }
2674  case DOWNSTREAM_CTRL_DATA:
2675  DEBUG_INFO (" <------- DOWNSTREAM CONTROL DATA");
2676  if (processDownstreamData (mac, buf, count, true)) {
2677  DEBUG_INFO ("Downstream Data OK");
2678  }
2679  break;
2680 
2681  case CLOCK_RESPONSE:
2682  DEBUG_INFO (" <------- CLOCK RESPONSE");
2683  if (clockSyncEnabled) {
2684  if (processClockResponse (mac, buf, count)) {
2685  DEBUG_INFO ("Clock Response OK");
2686  }
2687  }
2688  break;
2689  case NODE_NAME_RESULT:
2690  DEBUG_INFO (" <------- SET NODE NAME RESULT");
2691  if (processSetNameResponse (mac, buf, count)) {
2692  DEBUG_INFO ("Set Node Name OK");
2693  }
2694  break;
2696  DEBUG_INFO (" <------- BROADCAST KEY MESSAGE");
2697  if (processBroadcastKeyMessage (mac, buf, count)) {
2698  DEBUG_INFO ("Broadcast Key OK");
2699  }
2700  break;
2701  }
2702 }
2703 
2704 void EnigmaIOTNodeClass::getStatus (uint8_t* mac_addr, uint8_t status) {
2705  gatewaySearchStarted = false;
2706  if (status == 0) {
2707  DEBUG_DBG ("SENDStatus OK");
2708  rtcmem_data.commErrors = 0;
2709  } else {
2711  if (!saveRTCData ()) {
2712  DEBUG_ERROR ("Error saving data on RTC");
2713  }
2714  DEBUG_ERROR ("SENDStatus ERROR %d. Comm errors %u", status, rtcmem_data.commErrors);
2715  }
2716 }
2717 
2718 
2720 
2721 //#endif
OTA_CHECK_OK
@ OTA_CHECK_OK
Definition: NodeList.h:79
Comms_halClass::onDataRcvd
virtual void onDataRcvd(comms_hal_rcvd_data dataRcvd)=0
Attach a callback function to be run on every received message.
OTA_ERROR_RESTART
@ OTA_ERROR_RESTART
Definition: NodeList.h:43
EnigmaIOTNodeClass::otaRunning
bool otaRunning
True if OTA update has started.
Definition: EnigmaIOTNode.h:154
CryptModule::decryptBuffer
static bool decryptBuffer(const uint8_t *data, size_t length, const uint8_t *iv, uint8_t ivlen, const uint8_t *key, uint8_t keylen, const uint8_t *aad, uint8_t aadLen, const uint8_t *tag, uint8_t tagLen)
Decrypts a buffer using a shared key.
Definition: cryptModule.cpp:52
CLOCK_RESPONSE
@ CLOCK_RESPONSE
Definition: EnigmaIOTGateway.h:51
EnigmaIOTNodeClass::notifyWiFiManagerExit
onWiFiManagerExit_t notifyWiFiManagerExit
Function called when configuration portal exits.
Definition: EnigmaIOTNode.h:170
Node::setLastDownlinkMsgCounter
void setLastDownlinkMsgCounter(uint16_t counter)
Sets counter for last downlink message from gateway.
Definition: NodeList.h:258
EnigmaIOTNodeClass::otaError
bool otaError
True if OTA update has failed. This normally produces a restart.
Definition: EnigmaIOTNode.h:155
CryptModule::getPubDHKey
uint8_t * getPubDHKey()
Gets own public key used on Diffie Hellman algorithm.
Definition: cryptModule.h:136
EnigmaIOTNodeClass::notifyData
onNodeDataRx_t notifyData
Callback that will be called on every message reception.
Definition: EnigmaIOTNode.h:141
VERSION_ANS
@ VERSION_ANS
Definition: NodeList.h:53
IDENTIFY
@ IDENTIFY
Definition: NodeList.h:57
OTA_TIMEOUT_TIME
static const uint32_t OTA_TIMEOUT_TIME
Timeout between OTA messages. In milliseconds.
Definition: EnigmaIoTconfigAdvanced.h:46
EnigmaIOTNodeClass::unixtime
time_t unixtime()
Gets current time in seconds from 1970, if time is synchronized.
Definition: EnigmaIOTNode.cpp:1460
EnigmaIOTNodeClass::protectOTA
bool protectOTA
True if OTA update was launched. OTA flag is stored on RTC so this disables writting.
Definition: EnigmaIOTNode.h:156
Node::setLastMessageTime
void setLastMessageTime()
Sets current moment as last node message time.
Definition: NodeList.h:210
CryptModule::getDH1
void getDH1()
Starts first stage of Diffie Hellman key agreement algorithm.
Definition: cryptModule.cpp:141
SLEEP_SET
@ SLEEP_SET
Definition: NodeList.h:55
rtcmem_data_t::nodeKey
uint8_t nodeKey[KEY_LENGTH]
Definition: EnigmaIOTNode.h:91
RESTART_NODE
@ RESTART_NODE
Definition: NodeList.h:65
rtcmem_data_t::nodeId
uint16_t nodeId
Definition: EnigmaIOTNode.h:92
EnigmaIOTNodeClass::hasClockSync
bool hasClockSync()
Checks if internal clock is synchronized to gateway.
Definition: EnigmaIOTNode.cpp:1464
rtcmem_data_t::commErrors
uint8_t commErrors
Definition: EnigmaIOTNode.h:101
TAG_LENGTH
const uint8_t TAG_LENGTH
Authentication tag length. For Poly1305 it is always 16.
Definition: EnigmaIoTconfigAdvanced.h:72
ENIGMAIOT_ADDR_LEN
static const size_t ENIGMAIOT_ADDR_LEN
Address size. Mac address = 6 bytes.
Definition: EnigmaIoTconfigAdvanced.h:23
rtcmem_data_t::networkKey
uint8_t networkKey[KEY_LENGTH]
Definition: EnigmaIOTNode.h:96
Comms_halClass::onDataSent
virtual void onDataSent(comms_hal_sent_data dataRcvd)=0
Attach a callback function to be run after sending a message to receive its status.
rtcmem_data_t::broadcastKey
uint8_t broadcastKey[KEY_LENGTH]
Definition: EnigmaIOTNode.h:104
NODE_NAME_SET
@ NODE_NAME_SET
Definition: EnigmaIOTGateway.h:52
Node::setNodeName
void setNodeName(const char *name)
Sets Node name.
Definition: NodeList.h:164
rtcmem_data_t::gateway
uint8_t gateway[ENIGMAIOT_ADDR_LEN]
Definition: EnigmaIOTNode.h:94
timeManager.h
Clock synchronisation calculations.
TimeManagerClass::clock_us
int64_t clock_us()
Gets local clock.
Definition: timeManager.cpp:23
IDENTIFY_TIMEOUT
static const time_t IDENTIFY_TIMEOUT
How long LED will be flashing during identification.
Definition: EnigmaIoTconfig.h:42
EnigmaIOTNodeClass::clientHello
bool clientHello()
Build a ClientHello messange and send it to gateway.
Definition: EnigmaIOTNode.cpp:1192
nodeMessageType
nodeMessageType
Message code definition.
Definition: EnigmaIOTNode.h:35
CHMSG_LEN
#define CHMSG_LEN
Node::setStatus
void setStatus(status_t status)
Sets status for finite state machine that represents node.
Definition: NodeList.h:308
MAX_MESSAGE_LENGTH
static const uint8_t MAX_MESSAGE_LENGTH
Maximum payload size on ESP-NOW.
Definition: EnigmaIoTconfigAdvanced.h:21
Comms_halClass::begin
virtual void begin(uint8_t *gateway, uint8_t channel, peerType_t peerType=COMM_NODE)=0
Setup communication environment and establish the connection from node to gateway.
EnigmaIOTNodeClass::searchForGateway
bool searchForGateway(rtcmem_data_t *data, bool shouldStoreData=false)
Starts searching for a gateway that it using configured Network Name as WiFi AP. Stores this info for...
Definition: EnigmaIOTNode.cpp:860
NODE_NAME_LENGTH
static const uint8_t NODE_NAME_LENGTH
Maximum number of characters of node name.
Definition: EnigmaIoTconfigAdvanced.h:25
initWiFi
void initWiFi(uint8_t channel, const char *networkName, const char *networkKey, uint8_t role)
Initalizes WiFi interfaces on ESP8266 or ESP32.
Definition: helperFunctions.cpp:32
Node::isKeyValid
bool isKeyValid()
Gets shared key validity for this node.
Definition: NodeList.h:276
EnigmaIOTNodeClass::setResetPin
void setResetPin(int pin)
Sets a pin to be used to reset configuration it it is connected to ground during startup.
Definition: EnigmaIOTNode.cpp:94
EnigmaIOTNodeClass::led
int8_t led
IO Pin that corresponds to Tx LED. Default value disables LED. It is initialized with setLed method.
Definition: EnigmaIOTNode.h:138
Node::setInitAsSleepy
void setInitAsSleepy(bool sleepy)
Records if node started as a sleepy node or not. If it did not started so it will never accept sleep ...
Definition: NodeList.h:346
TimeManager
TimeManagerClass TimeManager
Definition: timeManager.cpp:65
DOWNSTREAM_BRCAST_DATA_GET
@ DOWNSTREAM_BRCAST_DATA_GET
Definition: EnigmaIOTGateway.h:45
EnigmaIOTNodeClass::checkCRC
bool checkCRC(const uint8_t *buf, size_t count, uint32_t *crc)
Check that a given CRC matches to calulated value from a buffer.
Definition: EnigmaIOTNode.cpp:1182
Node::setNodeId
void setNodeId(uint16_t nodeId)
Sets a new Node identifier.
Definition: NodeList.h:144
CryptModule::encryptBuffer
static bool encryptBuffer(const uint8_t *data, size_t length, const uint8_t *iv, uint8_t ivlen, const uint8_t *key, uint8_t keylen, const uint8_t *aad, uint8_t aadLen, const uint8_t *tag, uint8_t tagLen)
Decrypts a buffer using a shared key.
Definition: cryptModule.cpp:86
Crypto
CryptModule Crypto
Singleton Crypto class instance.
Definition: cryptModule.cpp:167
Node::broadcastIsEnabled
bool broadcastIsEnabled()
Returns if node broadcast mode is enabled. In that case, node is able to send and receive encrypted b...
Definition: NodeList.h:373
str2mac
uint8_t * str2mac(const char *macAddrString, uint8_t *macBytes)
Debug helper function that creates MAC address byte array from text representation.
Definition: helperFunctions.cpp:104
nodeConnectionLedFlashing
bool nodeConnectionLedFlashing
Definition: EnigmaIOTNode.cpp:37
TimeManagerClass::isTimeAdjusted
bool isTimeAdjusted()
Gets synchronization status.
Definition: timeManager.h:67
BRCAST_KEY
@ BRCAST_KEY
Definition: NodeList.h:67
rtcmem_data_t::rssi
int8_t rssi
Definition: EnigmaIOTNode.h:95
EnigmaIOTNodeClass::rx_cb
static void rx_cb(uint8_t *mac_addr, uint8_t *data, uint8_t len)
Function that will be called anytime this node receives a message.
Definition: EnigmaIOTNode.cpp:1174
EnigmaIOTNodeClass::processOTACommand
bool processOTACommand(const uint8_t *mac, const uint8_t *data, uint8_t len)
Processes a single OTA update command or data.
Definition: EnigmaIOTNode.cpp:2181
EnigmaIOTNodeClass::dataMessage
bool dataMessage(const uint8_t *data, size_t len, dataMessageType_t dataMsgType=DATA_TYPE, bool encrypt=true, nodePayloadEncoding_t payloadEncoding=CAYENNELPP)
Builds, encrypts and sends a Data message.
Definition: EnigmaIOTNode.cpp:1635
EnigmaIOTNodeClass::setSleepTime
void setSleepTime(uint32_t sleepTime, bool forceSleepForever=false)
Allows to configure a new sleep time period from user code.
Definition: EnigmaIOTNode.cpp:948
EnigmaIOTNodeClass::processSetSleepTimeCommand
bool processSetSleepTimeCommand(const uint8_t *mac, const uint8_t *buf, uint8_t len)
Processes a request to set new sleep time configuration.
Definition: EnigmaIOTNode.cpp:2118
COMM_ERRORS_BEFORE_SCAN
static const uint8_t COMM_ERRORS_BEFORE_SCAN
Node will search for a gateway if this number of communication errors have happened.
Definition: EnigmaIoTconfig.h:51
ENIGMAIOT_PROT_VERS
static const uint8_t ENIGMAIOT_PROT_VERS[3]
EnitmaIoT Version.
Definition: EnigmaIoTconfig.h:16
EnigmaIOTNodeClass::processGetNameCommand
bool processGetNameCommand(const uint8_t *mac, const uint8_t *data, uint8_t len)
Processes a request to get Node name and address.
Definition: EnigmaIOTNode.cpp:1795
TimeManagerClass::unixtime
time_t unixtime()
Gets local clock in seconds. It returns millis() / 1000 if not synchronized, local clock otherwise....
Definition: timeManager.h:40
rtcmem_data_t::crc32
uint32_t crc32
Definition: EnigmaIOTNode.h:90
rtcmem_data_t::broadcastKeyValid
bool broadcastKeyValid
Definition: EnigmaIOTNode.h:105
EnigmaIOTNodeClass::clearRTC
void clearRTC()
Clears configuration stored in RTC memory to recover factory state.
Definition: EnigmaIOTNode.cpp:2093
EnigmaIOTNodeClass::handle
void handle()
This method should be called periodically for instance inside loop() function. It is used for interna...
Definition: EnigmaIOTNode.cpp:1003
EnigmaIOTNodeClass::sendRestart
void sendRestart()
Sends a restart notification control message.
Definition: EnigmaIOTNode.cpp:56
TimeManagerClass::adjustTime
int64_t adjustTime(int64_t t1r, int64_t t2r, int64_t t3r, int64_t t4r)
Gets delay between Gateway time and local clock and adjust local clock accordingly....
Definition: timeManager.cpp:34
LED_OFF
#define LED_OFF
Definition: enigmaiot_led_flasher.cpp:40
OTA
@ OTA
Definition: NodeList.h:68
EnigmaIOTNodeClass::checkResetButton
void checkResetButton()
Checks reset button status during startup.
Definition: EnigmaIOTNode.cpp:674
NETWORK_NAME_LENGTH
static const uint8_t NETWORK_NAME_LENGTH
Maximum number of characters of network name.
Definition: EnigmaIoTconfigAdvanced.h:24
SHMSG_LEN
#define SHMSG_LEN
startFlash
void startFlash(time_t period)
Definition: EnigmaIOTNode.cpp:627
RESTART_CONFIRM
@ RESTART_CONFIRM
Definition: NodeList.h:66
MIN_SYNC_ACCURACY
static const int MIN_SYNC_ACCURACY
If calculated offset absolute value is higher than this value resync is done more often....
Definition: EnigmaIoTconfigAdvanced.h:47
RESET
@ RESET
Definition: NodeList.h:58
Node::getSleepy
bool getSleepy()
Gets node working mode regarding battery saving strategy. If node is sleepy it will turn into deep sl...
Definition: NodeList.h:363
DOWNSTREAM_DATA_GET
@ DOWNSTREAM_DATA_GET
Definition: EnigmaIOTGateway.h:44
EnigmaIOTNodeClass::resetPin
int resetPin
Pin used to reset configuration if it is connected to ground during startup.
Definition: EnigmaIOTNode.h:168
printHexBuffer
char * printHexBuffer(const uint8_t *buffer, uint16_t len)
Debug helper function that generates a string that represent a buffer hexadecimal values.
Definition: helperFunctions.cpp:16
Node::setKeyValid
void setKeyValid(bool status)
Sets shared key validity for this node.
Definition: NodeList.h:284
OTA_TIMEOUT
@ OTA_TIMEOUT
Definition: NodeList.h:82
rtcmem_data_t::lastDownlinkMsgCounter
uint16_t lastDownlinkMsgCounter
Definition: EnigmaIOTNode.h:110
EnigmaIOTNodeClass::notifyWiFiManagerStarted
simpleEventHandler_t notifyWiFiManagerStarted
Function called when configuration portal is started.
Definition: EnigmaIOTNode.h:171
DOWNSTREAM_DATA_SET
@ DOWNSTREAM_DATA_SET
Definition: EnigmaIOTGateway.h:42
EnigmaIOTNodeClass::requestReportRSSI
bool requestReportRSSI
Flag to control RSSI reporting.
Definition: EnigmaIOTNode.h:166
TIME_SYNC_PERIOD
static const uint32_t TIME_SYNC_PERIOD
Period of clock synchronization request.
Definition: EnigmaIoTconfig.h:44
RSSI_GET
@ RSSI_GET
Definition: NodeList.h:60
EnigmaIOTNodeClass::restartReason
restartReason_t restartReason
Reason of restart (OTA, restart requested, configuration reset)
Definition: EnigmaIOTNode.h:163
EnigmaIOTNodeClass::indentifying
boolean indentifying
True if node has its led flashing to be identified.
Definition: EnigmaIOTNode.h:158
EnigmaIOTNodeClass::processSetNameResponse
bool processSetNameResponse(const uint8_t *mac, const uint8_t *data, uint8_t len)
Processes a response to set Node name.
Definition: EnigmaIOTNode.cpp:1829
status_t
enum node_status status_t
Node state.
Definition: NodeList.h:39
EnigmaIOTNodeClass::flashBlue
bool flashBlue
If true Tx LED will be flashed.
Definition: EnigmaIOTNode.h:137
dataMessageType_t
dataMessageType_t
Definition: EnigmaIOTNode.h:68
Node::getStatus
status_t getStatus()
Gets status for finite state machine that represents node.
Definition: NodeList.h:300
OTA_START_ERROR
@ OTA_START_ERROR
Definition: NodeList.h:78
OTA_FINISHED
@ OTA_FINISHED
Definition: NodeList.h:83
rtcmem_data_t::sleepTime
uint32_t sleepTime
Definition: EnigmaIOTNode.h:99
EnigmaIOTNodeClass::getSleepTime
uint32_t getSleepTime()
Returns sleep period in seconds.
Definition: EnigmaIOTNode.cpp:77
Node::getNodeId
uint16_t getNodeId()
Gets Node identifier.
Definition: NodeList.h:136
DEBUG_ESP_PORT
#define DEBUG_ESP_PORT
Stream to output debug info. It will normally be Serial
Definition: EnigmaIoTconfig.h:58
Node::getLastMessageTime
time_t getLastMessageTime()
Gets last time that node sent a message.
Definition: NodeList.h:203
Node::setKeyValidFrom
void setKeyValidFrom(time_t keyValidFrom)
Sets time when key was agreed with gateway.
Definition: NodeList.h:195
INIT
@ INIT
Definition: NodeList.h:25
Node::setLastControlCounter
void setLastControlCounter(uint16_t counter)
Sets counter for last received control message from node.
Definition: NodeList.h:250
EnigmaIOTNodeClass::comm
Comms_halClass * comm
Comms abstraction layer.
Definition: EnigmaIOTNode.h:140
DOWNSTREAM_CTRL_DATA
@ DOWNSTREAM_CTRL_DATA
Definition: EnigmaIOTGateway.h:47
RSSI_ANS
@ RSSI_ANS
Definition: NodeList.h:61
EnigmaIOTNodeClass::dataMessageSent
uint8_t dataMessageSent[MAX_MESSAGE_LENGTH]
Buffer where sent message is stored in case of retransmission is needed.
Definition: EnigmaIOTNode.h:148
DATA_TYPE
@ DATA_TYPE
Definition: EnigmaIOTNode.h:69
CryptModule::getSHA256
static uint8_t * getSHA256(uint8_t *buffer, uint8_t length)
Generates a SHA256 hash from input.
Definition: cryptModule.cpp:20
EnigmaIOTNode
EnigmaIOTNodeClass EnigmaIOTNode
Definition: EnigmaIOTNode.cpp:2719
TimeManagerClass::getDelay
int64_t getDelay()
Gets propagation + processing delay between Node and Gateway in milliseconds.
Definition: timeManager.h:75
EnigmaIOTNodeClass::processSetIdentifyCommand
bool processSetIdentifyCommand(const uint8_t *mac, const uint8_t *buf, uint8_t len)
Processes a request to start indicate to identify a node visually.
Definition: EnigmaIOTNode.cpp:2033
EnigmaIOTNodeClass::timeSyncPeriod
clock_t timeSyncPeriod
Clock synchronization period.
Definition: EnigmaIOTNode.h:160
EnigmaIOTNodeClass::clockRequest
bool clockRequest()
Build a ClockRequest messange and send it to gateway.
Definition: EnigmaIOTNode.cpp:1291
SLEEP_GET
@ SLEEP_GET
Definition: NodeList.h:54
CONTROL_DATA
@ CONTROL_DATA
Definition: EnigmaIOTGateway.h:46
stopFlash
void stopFlash()
Definition: EnigmaIOTNode.cpp:647
EnigmaIOTNodeClass::sleep
void sleep()
Requests transition to sleep mode (low energy state)
Definition: EnigmaIOTNode.cpp:1564
AAD_LENGTH
const uint8_t AAD_LENGTH
Number of bytes from last part of key that will be used for additional authenticated data.
Definition: EnigmaIoTconfigAdvanced.h:73
NAME_OK
@ NAME_OK
Definition: NodeList.h:33
EnigmaIOTNodeClass::processSetResetConfigCommand
bool processSetResetConfigCommand(const uint8_t *mac, const uint8_t *buf, uint8_t len)
Processes a request to reset node configuration.
Definition: EnigmaIOTNode.cpp:2059
Node::setSleepy
void setSleepy(bool sleepy)
Sets node working mode regarding battery saving strategy. If node is sleepy it will turn into deep sl...
Definition: NodeList.h:334
EnigmaIOTNodeClass::tx_cb
static void tx_cb(uint8_t *mac_addr, uint8_t status)
Function that will be called anytime this node sends a message to indicate status result of sending p...
Definition: EnigmaIOTNode.cpp:1178
SENSOR_DATA
@ SENSOR_DATA
Definition: EnigmaIOTGateway.h:39
EnigmaIOTNodeClass::processServerHello
bool processServerHello(const uint8_t *mac, const uint8_t *buf, size_t count)
Gets a buffer containing a ServerHello message and process it. It uses that message to calculate a sh...
Definition: EnigmaIOTNode.cpp:1471
dumpRtcData
void dumpRtcData(rtcmem_data_t *data, uint8_t *gateway=NULL)
Definition: EnigmaIOTNode.cpp:113
QUICK_SYNC_TIME
static const unsigned int QUICK_SYNC_TIME
Period of clock synchronization request in case of resync is needed.
Definition: EnigmaIoTconfig.h:46
rtcmem_data_t::channel
uint8_t channel
Definition: EnigmaIOTNode.h:93
rtcmem_data_t::lastMessageCounter
uint16_t lastMessageCounter
Definition: EnigmaIOTNode.h:108
EnigmaIOTNodeClass::clearFlash
void clearFlash()
Clears configuration stored in flash to recover factory state.
Definition: EnigmaIOTNode.cpp:464
EnigmaIOTNodeClass::lastBroadcastMsgCounter
int16_t lastBroadcastMsgCounter
Counter for broadcast messages from gateway *‍/.
Definition: EnigmaIOTNode.h:173
WAIT_FOR_SERVER_HELLO
@ WAIT_FOR_SERVER_HELLO
Definition: NodeList.h:26
localLed
int localLed
Definition: EnigmaIOTNode.cpp:29
EnigmaIOTNodeClass::restart
void restart(restartReason_t reason, bool reboot=true)
Sets connection as unregistered to force a resyncrhonisation after boot.
Definition: EnigmaIOTNode.cpp:2351
Node::getLastControlCounter
uint16_t getLastControlCounter()
Gets counter for last received control message from node.
Definition: NodeList.h:226
EnigmaIOTNodeClass::configWiFiManager
bool configWiFiManager(rtcmem_data_t *data)
Starts configuration AP and web server and gets settings from it.
Definition: EnigmaIOTNode.cpp:481
Node::reset
void reset()
Resets all node fields to a default initial and not registered state.
Definition: NodeList.cpp:106
EnigmaIOTNodeClass::resetConfig
void resetConfig()
Deletes configuration file stored on flash. It makes neccessary to configure it again using WiFi Port...
Definition: EnigmaIOTNode.cpp:44
EnigmaIOTNodeClass::sleepTime
uint64_t sleepTime
Time in microseconds that this node will be slept between measurements.
Definition: EnigmaIOTNode.h:147
EnigmaIOTNodeClass::stopIdentifying
void stopIdentifying()
Stops node identification.
Definition: EnigmaIOTNode.cpp:669
Node::getInitAsSleepy
bool getInitAsSleepy()
Gets initial sleepy mode.
Definition: NodeList.h:354
Node::setEncryptionKey
void setEncryptionKey(const uint8_t *key)
Sets encryption key.
Definition: NodeList.cpp:11
Comms_halClass::send
virtual int32_t send(uint8_t *da, uint8_t *data, int len)=0
Sends data to the other peer.
CHECK_COMM_ERRORS
static const bool CHECK_COMM_ERRORS
Try to reconnect in case of communication errors.
Definition: EnigmaIoTconfigAdvanced.h:50
EnigmaIOTNodeClass::dataMessageSendPending
bool dataMessageSendPending
True in case of message retransmission is needed.
Definition: EnigmaIOTNode.h:150
EnigmaIOTNodeClass::notifyConnection
onConnected_t notifyConnection
Callback that will be called anytime a new node is registered.
Definition: EnigmaIOTNode.h:142
Comms_halClass::getAddressLength
virtual uint8_t getAddressLength()=0
Get address length that a specific communication subsystem uses.
nodePayloadEncoding_t
nodePayloadEncoding_t
Definition: EnigmaIOTNode.h:58
Node::getEncriptionKey
uint8_t * getEncriptionKey()
Gets Node encryption key.
Definition: NodeList.h:173
CryptModule::random
static uint32_t random()
Gets a random number.
Definition: cryptModule.cpp:119
RESTART_AFTER_OTA
@ RESTART_AFTER_OTA
Definition: NodeList.h:42
PRE_REG_DELAY
static const uint32_t PRE_REG_DELAY
Time to wait before registration so that other nodes have time to communicate. Real delay is a random...
Definition: EnigmaIoTconfig.h:48
restartReason_t
restartReason_t
Definition: NodeList.h:41
DOWNSTREAM_BRCAST_DATA_SET
@ DOWNSTREAM_BRCAST_DATA_SET
Definition: EnigmaIOTGateway.h:43
EnigmaIOTNodeClass::useCounter
bool useCounter
true means that data message counter will be used to mark message order
Definition: EnigmaIOTNode.h:144
POST_REG_DELAY
static const uint32_t POST_REG_DELAY
Time to wait before sending data after registration so that other nodes have time to finish their reg...
Definition: EnigmaIoTconfig.h:50
EnigmaIOTNodeClass::sendData
bool sendData(const uint8_t *data, size_t len, dataMessageType_t dataMsgType, bool encrypt=true, nodePayloadEncoding_t payloadEncoding=CAYENNELPP)
Initiades data transmission distinguissing if it is payload or control data.
Definition: EnigmaIOTNode.cpp:1535
EnigmaIOTNodeClass::processControlCommand
bool processControlCommand(const uint8_t *mac, const uint8_t *data, size_t len, bool broadcast)
Processes a control command. Does not propagate to user code.
Definition: EnigmaIOTNode.cpp:2366
Node::getLastMessageCounter
uint16_t getLastMessageCounter()
Gets counter for last received message from node.
Definition: NodeList.h:218
EnigmaIOTNodeClass::processSetNameCommand
bool processSetNameCommand(const uint8_t *mac, const uint8_t *data, uint8_t len)
Processes a request to set Node name.
Definition: EnigmaIOTNode.cpp:1899
rtcmem_data_t::lastControlCounter
uint16_t lastControlCounter
Definition: EnigmaIOTNode.h:109
EnigmaIOTNodeClass::ledOnTime
unsigned int ledOnTime
Time that LED is On during flash. Initalized on setLed
Definition: EnigmaIOTNode.h:139
EnigmaIOTNodeClass::node
Node node
Node abstraction to store context.
Definition: EnigmaIOTNode.h:136
EnigmaIOTNodeClass::sendNodeNameSet
bool sendNodeNameSet(const char *name)
Informs Gateway about custom node name.
Definition: EnigmaIOTNode.cpp:1936
EnigmaIOTNodeClass::processSetRestartCommand
bool processSetRestartCommand(const uint8_t *mac, const uint8_t *buf, uint8_t len)
Processes a request to restar node mcu.
Definition: EnigmaIOTNode.cpp:2053
OTA_OUT_OF_SEQUENCE
@ OTA_OUT_OF_SEQUENCE
Definition: NodeList.h:81
EnigmaIOTNodeClass::invalidateReason
nodeInvalidateReason_t invalidateReason
Last key invalidation reason.
Definition: EnigmaIOTNode.h:153
EnigmaIOTNodeClass::rtcmem_data
rtcmem_data_t rtcmem_data
Context data to be stored on persistent storage.
Definition: EnigmaIOTNode.h:145
NAME_ANS
@ NAME_ANS
Definition: NodeList.h:63
EnigmaIOTNodeClass::loadRTCData
bool loadRTCData()
Loads configuration from RTC data. Uses a CRC to check data integrity.
Definition: EnigmaIOTNode.cpp:221
RANDOM_LENGTH
const uint8_t RANDOM_LENGTH
Length of random number generator values.
Definition: cryptModule.h:27
rtcmem_data_t::nodeName
char nodeName[NODE_NAME_LENGTH+1]
Definition: EnigmaIOTNode.h:100
EnigmaIOTNodeClass::clockSyncEnabled
bool clockSyncEnabled
If true clock is synchronized with Gateway.
Definition: EnigmaIOTNode.h:161
Node::setMacAddress
void setMacAddress(const uint8_t *macAddress)
Sets node address.
Definition: NodeList.h:266
KEY_LENGTH
const uint8_t KEY_LENGTH
Key length used by selected crypto algorythm. The only tested value is 32. Change it only if you know...
Definition: EnigmaIoTconfigAdvanced.h:70
EnigmaIOTNodeClass::processBroadcastKeyMessage
bool processBroadcastKeyMessage(const uint8_t *mac, const uint8_t *buf, size_t count)
Gets a buffer containing a BroadcastKey message and process it. This key is used to send and receive ...
Definition: EnigmaIOTNode.cpp:2408
EnigmaIOTNodeClass::sleepRequested
bool sleepRequested
true means that this node will sleep as soon a message is sent and downlink wait time has passed
Definition: EnigmaIOTNode.h:146
EnigmaIOTNodeClass::processVersionCommand
bool processVersionCommand(const uint8_t *mac, const uint8_t *buf, uint8_t len)
Processes a request firmware version.
Definition: EnigmaIOTNode.cpp:2163
CONFIG_RESET
@ CONFIG_RESET
Definition: NodeList.h:45
EnigmaIOTNodeClass::processDownstreamData
bool processDownstreamData(const uint8_t *mac, const uint8_t *buf, size_t count, bool control=false)
Processes downstream data from gateway.
Definition: EnigmaIOTNode.cpp:2425
EnigmaIOTNodeClass::wifiManager
AsyncWiFiManager * wifiManager
Wifi configuration portal.
Definition: EnigmaIOTNode.h:169
EnigmaIOTNodeClass::processClockResponse
bool processClockResponse(const uint8_t *mac, const uint8_t *buf, size_t count)
Gets a buffer containing a ClockResponse message and process it. It uses that message to calculate cl...
Definition: EnigmaIOTNode.cpp:1367
EnigmaIOTNode.h
Library to build a node for EnigmaIoT system.
MSG_PACK
@ MSG_PACK
Definition: EnigmaIOTGateway.h:65
EnigmaIOTNodeClass::sendHADiscoveryMessage
bool sendHADiscoveryMessage(const uint8_t *data, size_t len)
Builds, encrypts and sends a HomeAssistant discovery message.
Definition: EnigmaIOTNode.cpp:1764
rtcmem_data_t::broadcastKeyRequested
bool broadcastKeyRequested
Definition: EnigmaIOTNode.h:106
EnigmaIOTNodeClass::dataMessageEncrypt
bool dataMessageEncrypt
Message encryption enabled. Stored for use in case of message retransmission is needed.
Definition: EnigmaIOTNode.h:152
MACSTR
#define MACSTR
Definition: helperFunctions.cpp:83
RTC_ADDRESS
static const uint32_t RTC_ADDRESS
RTC memory address where to store context. Modify it if you need place to store your own data during ...
Definition: EnigmaIoTconfigAdvanced.h:52
EnigmaIOTNodeClass::lastOTAmsg
time_t lastOTAmsg
Time when last OTA update message has received. This is used to control timeout.
Definition: EnigmaIOTNode.h:157
RECONNECTION_PERIOD
static const int16_t RECONNECTION_PERIOD
Time to retry Gateway connection.
Definition: EnigmaIoTconfig.h:39
rtcmem_data_t::nodeRegisterStatus
status_t nodeRegisterStatus
Definition: EnigmaIOTNode.h:107
CONFIG_FILE
const char CONFIG_FILE[]
Definition: EnigmaIOTNode.cpp:27
EnigmaIOTNodeClass::begin
void begin(Comms_halClass *comm, uint8_t *gateway=NULL, uint8_t *networkKey=NULL, bool useCounter=true, bool sleepy=true)
Initalizes communication basic data and starts node registration.
Definition: EnigmaIOTNode.cpp:696
UNREGISTERED
@ UNREGISTERED
Definition: NodeList.h:24
KEY_EXPIRED
@ KEY_EXPIRED
Definition: EnigmaIOTGateway.h:81
EnigmaIOTNodeClass::notifyDisconnection
onDisconnected_t notifyDisconnection
Callback that will be called anytime a node is disconnected.
Definition: EnigmaIOTNode.h:143
RESET_ANS
@ RESET_ANS
Definition: NodeList.h:59
Node::isRegistered
bool isRegistered()
Gets registration state of this node.
Definition: NodeList.h:292
TimeManagerClass::clock
int64_t clock()
Gets local clock.
Definition: timeManager.cpp:12
Node::getMacAddress
uint8_t * getMacAddress()
Gets address from Node.
Definition: NodeList.h:128
EnigmaIOTNodeClass::identifyStart
time_t identifyStart
Time when identification started flashing. Used to control identification timeout.
Definition: EnigmaIOTNode.h:159
EnigmaIOTNodeClass::processInvalidateKey
nodeInvalidateReason_t processInvalidateKey(const uint8_t *mac, const uint8_t *buf, size_t count)
Gets a buffer containing an InvalidateKey message and process it. This trigger a new key agreement to...
Definition: EnigmaIOTNode.cpp:2527
VERSION
@ VERSION
Definition: NodeList.h:52
EnigmaIOTNodeClass::setLed
void setLed(uint8_t led, time_t onTime=FLASH_LED_TIME)
Sets a LED to be flashed every time a message is transmitted.
Definition: EnigmaIOTNode.cpp:89
IKMSG_LEN
#define IKMSG_LEN
HA_DISCOVERY_MESSAGE
@ HA_DISCOVERY_MESSAGE
Definition: EnigmaIOTGateway.h:49
EnigmaIOTNodeClass::saveRTCData
bool saveRTCData()
Save configuration to RTC to store current status and recover it after deep sleep.
Definition: EnigmaIOTNode.cpp:433
EnigmaIOTNodeClass::loadFlashData
bool loadFlashData()
Loads configuration from flash memory.
Definition: EnigmaIOTNode.cpp:270
OTA_ANS
@ OTA_ANS
Definition: NodeList.h:69
Node::printToSerial
void printToSerial(Stream *port=&Serial)
Dumps node data to the given stream, Serial by default. This method may be used for debugging.
Definition: NodeList.cpp:32
NAME_GET
@ NAME_GET
Definition: NodeList.h:62
EnigmaIOTNodeClass::unencryptedDataMessage
bool unencryptedDataMessage(const uint8_t *data, size_t len, dataMessageType_t dataMsgType=DATA_TYPE, nodePayloadEncoding_t payloadEncoding=CAYENNELPP)
Builds and sends a Data message without encryption. Not recommended, use it only if you absolutely ne...
Definition: EnigmaIOTNode.cpp:1574
data
@ data
Definition: GwOutput_generic.h:23
DOWNLINK_WAIT_TIME
static const uint16_t DOWNLINK_WAIT_TIME
Time to wait for downlink message before sleep. Setting less than 180 ms causes ESP-NOW errors due to...
Definition: EnigmaIoTconfig.h:40
REGISTERED
@ REGISTERED
Definition: NodeList.h:28
SERVER_HELLO
@ SERVER_HELLO
Definition: EnigmaIOTGateway.h:57
EnigmaIOTNodeClass::reportRSSI
bool reportRSSI()
Sends RSSI value and channel to Gateway.
Definition: EnigmaIOTNode.cpp:982
EnigmaIOTNodeClass::shouldRestart
bool shouldRestart
Triggers a restart if true.
Definition: EnigmaIOTNode.h:162
EnigmaIOTNodeClass::getStatus
void getStatus(uint8_t *mac_addr, uint8_t status)
Functrion to debug send status.
Definition: EnigmaIOTNode.cpp:2704
CryptModule::getDH2
bool getDH2(const uint8_t *remotePubKey)
Starts second stage of Diffie Hellman key agreement algorithm and calculate shares key.
Definition: cryptModule.cpp:148
CLOCK_REQUEST
@ CLOCK_REQUEST
Definition: EnigmaIOTGateway.h:50
EnigmaIOTNodeClass
Main node class. Manages communication with gateway and allows sending and receiving user data.
Definition: EnigmaIOTNode.h:134
EnigmaIOTNodeClass::processGetSleepTimeCommand
bool processGetSleepTimeCommand(const uint8_t *mac, const uint8_t *buf, uint8_t len)
Processes a request of sleep time configuration.
Definition: EnigmaIOTNode.cpp:1772
RESET_PIN_DURATION
static const int RESET_PIN_DURATION
Number of milliseconds that reset pin has to be grounded to produce a configuration reset.
Definition: EnigmaIoTconfig.h:19
NODE_NAME_RESULT
@ NODE_NAME_RESULT
Definition: EnigmaIOTGateway.h:53
mac2str
char * mac2str(const uint8_t *mac, char *extBuffer)
Debug helper function that generates a string that represent a MAC address.
Definition: helperFunctions.cpp:85
EnigmaIOTNodeClass::stop
void stop()
Stops EnigmaIoT protocol.
Definition: EnigmaIOTNode.cpp:938
EnigmaIOTNodeClass::processGetRSSICommand
bool processGetRSSICommand(const uint8_t *mac, const uint8_t *data, uint8_t len)
Processes a request to measure RSSI.
Definition: EnigmaIOTNode.cpp:2046
EnigmaIOTNodeClass::setNodeAddress
bool setNodeAddress(uint8_t address[ENIGMAIOT_ADDR_LEN])
Set node address to be used in EnigmaIOT communication.
Definition: EnigmaIOTNode.cpp:943
Node::getLastDownlinkMsgCounter
uint16_t getLastDownlinkMsgCounter()
Gets counter for last downlink message from gateway.
Definition: NodeList.h:234
IV_LENGTH
const uint8_t IV_LENGTH
Initalization vector length used by selected crypto algorythm.
Definition: EnigmaIoTconfigAdvanced.h:71
EnigmaIOTNodeClass::requestSearchGateway
bool requestSearchGateway
Flag to control updating gateway address, RSSI and channel.
Definition: EnigmaIOTNode.h:165
nodeInvalidateReason_t
nodeInvalidateReason_t
Key invalidation reason definition.
Definition: EnigmaIOTNode.h:78
EnigmaIOTNodeClass::saveFlashData
bool saveFlashData(bool fsOpen=false)
Saves configuration to flash memory.
Definition: EnigmaIOTNode.cpp:352
OTA_CHECK_FAIL
@ OTA_CHECK_FAIL
Definition: NodeList.h:80
rtcmem_data_t::sleepy
bool sleepy
Definition: EnigmaIOTNode.h:98
nodeNameParam
const char * nodeNameParam
Definition: GatewayAPI.cpp:24
IRRELEVANT
@ IRRELEVANT
Definition: NodeList.h:47
EnigmaIOTNodeClass::clock
int64_t clock()
Gets current clock counter. millis() + offset.
Definition: EnigmaIOTNode.cpp:1455
UNKNOWN_ERROR
@ UNKNOWN_ERROR
Definition: EnigmaIOTGateway.h:76
rtcmem_data_t::networkName
char networkName[NETWORK_NAME_LENGTH]
Definition: EnigmaIOTNode.h:97
DOWNSTREAM_BRCAST_CTRL_DATA
@ DOWNSTREAM_BRCAST_CTRL_DATA
Definition: EnigmaIOTGateway.h:48
CLIENT_HELLO
@ CLIENT_HELLO
Definition: EnigmaIOTGateway.h:56
EnigmaIOTNodeClass::dataMessageSendEncoding
nodePayloadEncoding_t dataMessageSendEncoding
Encoding of the message pending to be sent.
Definition: EnigmaIOTNode.h:151
Comms_halClass::enableTransmit
virtual void enableTransmit(bool enable)=0
Enables or disables transmission of queued messages. Used to disable communication during wifi scan.
DEFAULT_SLEEP_TIME
static const uint32_t DEFAULT_SLEEP_TIME
Default sleep time if it was not set.
Definition: EnigmaIoTconfig.h:41
EnigmaIOTNodeClass::manageMessage
void manageMessage(const uint8_t *mac, const uint8_t *buf, uint8_t count)
Process every received message.
Definition: EnigmaIOTNode.cpp:2551
LED_ON
#define LED_ON
Definition: enigmaiot_led_flasher.cpp:39
rtcmem_data_t::nodeKeyValid
bool nodeKeyValid
Definition: EnigmaIOTNode.h:103
NAME_SET
@ NAME_SET
Definition: NodeList.h:64
calculateCRC32
uint32_t calculateCRC32(const uint8_t *data, size_t length)
Calculates CRC32 of a buffer.
Definition: helperFunctions.cpp:64
EnigmaIOTNodeClass::cycleStartedTime
time_t cycleStartedTime
Used to calculate exact sleep time by substracting awake time.
Definition: EnigmaIOTNode.h:172
HA_DISC_TYPE
@ HA_DISC_TYPE
Definition: EnigmaIOTNode.h:71
flashLed
void flashLed(void *led)
Definition: EnigmaIOTNode.cpp:617
Node::setLastMessageCounter
void setLastMessageCounter(uint16_t counter)
Sets counter for last received message from node.
Definition: NodeList.h:242
INVALIDATE_KEY
@ INVALIDATE_KEY
Definition: EnigmaIOTGateway.h:58
SLEEP_ANS
@ SLEEP_ANS
Definition: NodeList.h:56
EnigmaIOTNodeClass::gatewaySearchStarted
bool gatewaySearchStarted
Avoids start a new gateway scan if it already started.
Definition: EnigmaIOTNode.h:164
TimeManagerClass::reset
void reset()
Resets clock synchronization and sets values to initial status.
Definition: timeManager.h:82
EnigmaIOTNodeClass::configCleared
bool configCleared
This flag disables asy configuration save after triggering a factory reset.
Definition: EnigmaIOTNode.h:167
rtcmem_data_t
Context data to be stored con persistent storage to be used after wake from sleep mode.
Definition: EnigmaIOTNode.h:89
clearRtcData
void clearRtcData(rtcmem_data_t *data)
Definition: EnigmaIOTNode.cpp:98
RESTART_REQUESTED
@ RESTART_REQUESTED
Definition: NodeList.h:44
CONTROL_TYPE
@ CONTROL_TYPE
Definition: EnigmaIOTNode.h:70
status
@ status
Definition: GwOutput_generic.h:25
EnigmaIOTNodeClass::getRSSI
int8_t getRSSI()
Gets latest RSSI measurement. It is updated during start up or in case of transmission errors.
Definition: EnigmaIOTNode.cpp:85
EnigmaIOTNodeClass::startIdentifying
void startIdentifying(time_t period)
Starts node identification by flashing led.
Definition: EnigmaIOTNode.cpp:663
Comms_halClass
Interface for communication subsystem abstraction layer definition.
Definition: Comms_hal.h:41
OTA_STARTED
@ OTA_STARTED
Definition: NodeList.h:77
UNENCRYPTED_NODE_DATA
@ UNENCRYPTED_NODE_DATA
Definition: EnigmaIOTGateway.h:41
EnigmaIOTNodeClass::dataMessageSentLength
uint8_t dataMessageSentLength
Message length stored for use in case of message retransmission is needed.
Definition: EnigmaIOTNode.h:149
Comms_halClass::stop
virtual void stop()=0
Terminates communication and closes all connectrions.
BROADCAST_KEY_RESPONSE
@ BROADCAST_KEY_RESPONSE
Definition: EnigmaIOTGateway.h:55