EnigmaIOT  0.9.8
Secure sensor and gateway platform based on ESP8266 and ESP32
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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