EnigmaIOT  0.9.3
Secure sensor and gateway platform based on ESP8266 and ESP32
EnigmaIOTNode.cpp
Go to the documentation of this file.
1 
9 //#define ESP8266
10 
11 //#ifdef ESP8266
12 #include <Arduino.h>
13 #include "EnigmaIOTNode.h"
14 #include "timeManager.h"
15 #include <FS.h>
16 #include <MD5Builder.h>
17 #ifdef ESP8266
18 #include <Updater.h>
19 #elif defined ESP32
20 #include <Update.h>
21 #include <SPIFFS.h>
22 #include "esp_wifi.h"
23 #endif
24 #include <StreamString.h>
25 #include <ArduinoJson.h>
26 #include <regex>
27 
28 const char CONFIG_FILE[] = "/config.json";
29 
30 int localLed = -1;
31 
32 #ifdef ESP32
33 TimerHandle_t ledTimer;
34 #elif defined(ESP8266)
35 ETSTimer ledTimer;
36 #endif // ESP32
37 
39 
40 #ifdef ESP32
41 RTC_DATA_ATTR rtcmem_data_t rtcmem_data_storage;
42 #endif
43 
44 
46  SPIFFS.begin ();
47  SPIFFS.remove (CONFIG_FILE);
48  SPIFFS.end ();
49  DEBUG_WARN ("Config file %s deleted. Restarting");
50 
51  clearRTC ();
52  ESP.restart ();
53 }
54 
56  if (!node.getSleepy ()) {
57  return 0;
58  } else {
59  return rtcmem_data.sleepTime;
60  }
61 }
62 
64  return rtcmem_data.rssi;
65 }
66 
67 void EnigmaIOTNodeClass::setLed (uint8_t led, time_t onTime) {
68  this->led = led;
69  ledOnTime = onTime;
70 }
71 
73  resetPin = pin;
74 }
75 
77  memset (data->nodeKey, 0, KEY_LENGTH);
78  data->lastMessageCounter = 0;
79  data->nodeId = 0;
80  data->channel = 3;
81  memset (data->gateway, 0, 6);
82  memset (data->networkKey, 0, KEY_LENGTH);
83  data->nodeRegisterStatus = UNREGISTERED;
84  data->sleepy = false;
85  data->nodeKeyValid = false;
86 }
87 
88 void dumpRtcData (rtcmem_data_t* data, uint8_t* gateway = NULL) {
89  Serial.println ("RTC MEM DATA:");
90  if (data) {
91  Serial.printf (" -- CRC: %s\n", printHexBuffer ((uint8_t*)&(data->crc32), sizeof (uint32_t)));
92  Serial.printf (" -- Node Key: %s\n", printHexBuffer (data->nodeKey, KEY_LENGTH));
93  Serial.printf (" -- Node key is %svalid\n", data->nodeKeyValid ? "" : "NOT ");
94  Serial.printf (" -- Node status is %d: %s\n", data->nodeRegisterStatus, data->nodeRegisterStatus == REGISTERED ? "REGISTERED" : "NOT REGISTERED");
95  Serial.printf (" -- Node name: %s\n", data->nodeName);
96  Serial.printf (" -- Last message counter: %d\n", data->lastMessageCounter);
97  Serial.printf (" -- NodeID: %d\n", data->nodeId);
98  Serial.printf (" -- Channel: %d\n", data->channel);
99  Serial.printf (" -- RSSI: %d\n", data->rssi);
100  Serial.printf (" -- Network name: %s\n", data->networkName);
101  char gwAddress[ENIGMAIOT_ADDR_LEN * 3];
102  Serial.printf (" -- Gateway: %s\n", mac2str (data->gateway, gwAddress));
103  Serial.printf (" -- Comm errors: %d\n", data->commErrors);
104  if (gateway)
105  Serial.printf (" -- Gateway address: %s\n", mac2str (gateway, gwAddress));
106  Serial.printf (" -- Network Key: %s\n", printHexBuffer (data->networkKey, KEY_LENGTH));
107  Serial.printf (" -- Mode: %s\n", data->sleepy ? "sleepy" : "non sleepy");
108  } else {
109  Serial.println ("rtcmem_data pointer is NULL");
110  }
111 }
112 
114 #ifdef ESP8266
115  if (ESP.rtcUserMemoryRead (RTC_ADDRESS, (uint32_t*)&rtcmem_data, sizeof (rtcmem_data))) {
116  DEBUG_VERBOSE ("Read RTCData: %s", printHexBuffer ((uint8_t*)&rtcmem_data, sizeof (rtcmem_data)));
117  } else {
118  DEBUG_ERROR ("Error reading RTC memory");
120  return false;
121  }
122 #elif defined ESP32
123  memcpy ((uint8_t*)&rtcmem_data, (uint8_t*)&rtcmem_data_storage, sizeof (rtcmem_data));
124  DEBUG_VERBOSE ("----- Read RTCData: %s", printHexBuffer ((uint8_t*)&rtcmem_data, sizeof (rtcmem_data)));
125 #endif
126  if (!checkCRC ((uint8_t*)rtcmem_data.nodeKey, sizeof (rtcmem_data) - sizeof (uint32_t), &rtcmem_data.crc32)) {
127  DEBUG_DBG ("RTC Data is not valid");
129  return false;
130  } else {
134  node.setKeyValidFrom (millis ());
138  // setChannel (rtcmem_data.channel);
139  //channel = rtcmem_data.channel;
140  //memcpy (gateway, rtcmem_data.gateway, comm->getAddressLength ()); // setGateway
141  //memcpy (networkKey, rtcmem_data.networkKey, KEY_LENGTH);
144  // set default sleep time if it was not set
145  if (rtcmem_data.sleepy && rtcmem_data.sleepTime == 0) {
147  }
149  DEBUG_DBG ("Set %s mode", node.getSleepy () ? "sleepy" : "non sleepy");
150 #if DEBUG_LEVEL >= VERBOSE
152 #endif
153 
154  }
155  return true;
156 
157 }
158 
160  //SPIFFS.remove (CONFIG_FILE); // Only for testing
161  bool json_correct = false;
162 
163  if (SPIFFS.exists (CONFIG_FILE)) {
164  DEBUG_DBG ("Opening %s file", CONFIG_FILE);
165  File configFile = SPIFFS.open (CONFIG_FILE, "r");
166  if (configFile) {
167  DEBUG_DBG ("%s opened", CONFIG_FILE);
168  size_t size = configFile.size ();
169 
170  const size_t capacity = JSON_ARRAY_SIZE (32) + JSON_OBJECT_SIZE (5) + 100;
171  DynamicJsonDocument doc (capacity);
172  DeserializationError error = deserializeJson (doc, configFile);
173  if (error) {
174  DEBUG_ERROR ("Failed to parse file");
175  } else {
176  DEBUG_DBG ("JSON file parsed");
177  }
178 
179  if (doc.containsKey ("networkName") && doc.containsKey ("networkKey")
180  && doc.containsKey ("sleepTime")) {
181  json_correct = true;
182  }
183 
184  strlcpy (rtcmem_data.networkName, doc["networkName"] | "", sizeof (rtcmem_data.networkName));
185  rtcmem_data.sleepTime = doc["sleepTime"].as<int> ();
187 
188  memset (rtcmem_data.networkKey, 0, KEY_LENGTH);
189  JsonArray netKeyJson = doc["networkKey"];
190  if (netKeyJson.size () != KEY_LENGTH) {
191  DEBUG_WARN ("Error in stored network key. Expected length: %d, actual length %d", KEY_LENGTH, netKeyJson.size ());
192  return false;
193  }
194  for (int i = 0; i < KEY_LENGTH; i++) {
195  rtcmem_data.networkKey[i] = netKeyJson[i].as<int> ();
196  }
197  DEBUG_DBG ("Network Key dump: %s", printHexBuffer (rtcmem_data.networkKey, KEY_LENGTH));
198  strncpy ((char*)rtcmem_data.nodeName, doc["nodeName"] | "", NODE_NAME_LENGTH);
200 
201  uint8_t gwAddr[ENIGMAIOT_ADDR_LEN];
202  char gwAddrStr[ENIGMAIOT_ADDR_LEN * 3];
203  if (doc.containsKey ("gateway")) {
204  strncpy (gwAddrStr, doc["gateway"], sizeof (gwAddrStr));
205  str2mac (gwAddrStr, gwAddr);
206  memcpy (rtcmem_data.gateway, gwAddr, 6);
207  }
208 
209  configFile.close ();
210  if (json_correct) {
211  DEBUG_VERBOSE ("Configuration successfuly read");
212  }
213 
214  DEBUG_DBG ("==== EnigmaIOT Node Configuration ====");
215  DEBUG_DBG ("Network name: %s", rtcmem_data.networkName);
216  DEBUG_DBG ("Sleep time: %u", rtcmem_data.sleepTime);
217  DEBUG_DBG ("Node name: %s", rtcmem_data.nodeName);
218  DEBUG_DBG ("Gateway: %s", gwAddrStr);
219  DEBUG_VERBOSE ("Network key: %s", printHexBuffer (rtcmem_data.networkKey, KEY_LENGTH));
220 
221  String output;
222  serializeJsonPretty (doc, output);
223 
224  DEBUG_DBG ("JSON file %s", output.c_str ());
225  }
226  } else {
227  DEBUG_WARN ("%s do not exist", CONFIG_FILE);
228  }
229 
230  return json_correct;
231 }
232 
234  if (configCleared)
235  return false;
236 
237  if (!fsOpen)
238  SPIFFS.begin ();
239 
240  File configFile = SPIFFS.open (CONFIG_FILE, "w");
241  if (!configFile) {
242  DEBUG_WARN ("failed to open config file %s for writing", CONFIG_FILE);
243  return false;
244  }
245 
246  const size_t capacity = JSON_ARRAY_SIZE (32) + JSON_OBJECT_SIZE (5) + 100;
247  DynamicJsonDocument doc (capacity);
248 
249  char gwAddrStr[ENIGMAIOT_ADDR_LEN * 3];
250  mac2str (rtcmem_data.gateway, gwAddrStr);
251 
252  doc["networkName"] = rtcmem_data.networkName;
253  JsonArray netKeyJson = doc.createNestedArray ("networkKey");
254  for (int i = 0; i < KEY_LENGTH; i++) {
255  netKeyJson.add (rtcmem_data.networkKey[i]);
256  }
257  doc["sleepTime"] = rtcmem_data.sleepTime;
258  doc["gateway"] = gwAddrStr;
259  doc["nodeName"] = rtcmem_data.nodeName;
260 
261  if (serializeJson (doc, configFile) == 0) {
262  DEBUG_ERROR ("Failed to write to file");
263  configFile.close ();
264  //SPIFFS.remove (CONFIG_FILE); // Testing
265  return false;
266  }
267 
268  String output;
269  serializeJsonPretty (doc, output);
270 
271  DEBUG_DBG ("%s", output.c_str ());
272 
273  configFile.flush ();
274  size_t size = configFile.size ();
275 
276  configFile.close ();
277  DEBUG_DBG ("Configuration saved to flash. %u bytes", size);
278 #if DEBUG_LEVEL >= DBG
280 #endif
281  if (!fsOpen)
282  SPIFFS.end ();
283  return true;
284 }
285 
287  if (configCleared)
288  return false;
289 #ifdef ESP8266
290  rtcmem_data.crc32 = calculateCRC32 ((uint8_t*)rtcmem_data.nodeKey, sizeof (rtcmem_data) - sizeof (uint32_t));
291  if (ESP.rtcUserMemoryWrite (RTC_ADDRESS, (uint32_t*)&rtcmem_data, sizeof (rtcmem_data))) {
292  DEBUG_DBG ("Write configuration data to RTC memory");
293 #if DEBUG_LEVEL >= VERBOSE
294  DEBUG_VERBOSE ("Write RTCData: %s", printHexBuffer ((uint8_t*)&rtcmem_data, sizeof (rtcmem_data)));
296 #endif
297  return true;
298  }
299 #elif defined ESP32
300  rtcmem_data.crc32 = calculateCRC32 ((uint8_t*)rtcmem_data.nodeKey, sizeof (rtcmem_data) - sizeof (uint32_t));
301  memcpy ((uint8_t*)&rtcmem_data_storage, (uint8_t*)&rtcmem_data, sizeof (rtcmem_data));
302  rtcmem_data_storage.crc32 = calculateCRC32 ((uint8_t*)rtcmem_data_storage.nodeKey, sizeof (rtcmem_data) - sizeof (uint32_t));
303  DEBUG_VERBOSE ("----- Write RTCData: %s", printHexBuffer ((uint8_t*)&rtcmem_data, sizeof (rtcmem_data)));
304  return true;
305 #endif
306  return false;
307 }
308 
310  if (!SPIFFS.begin ()) {
311  DEBUG_ERROR ("Error on SPIFFS.begin()");
312  }
313  if (SPIFFS.remove (CONFIG_FILE)) {
314  DEBUG_DBG ("%s deleted", CONFIG_FILE);
315  } else {
316  DEBUG_ERROR ("Error on SPIFFS.remove(\"%s\")", CONFIG_FILE);
317  }
318  SPIFFS.end ();
319 }
320 
322  AsyncWebServer server (80);
323  DNSServer dns;
324 
325  //regex_t regex;
326  bool regexResult;
327 
328  //char networkKey[33] = "";
329  char sleepy[5] = "10";
330  //char networkName[NETWORK_NAME_LENGTH] = "";
331  char nodeName[NODE_NAME_LENGTH] = "";
332 
333  wifiManager = new AsyncWiFiManager (&server, &dns);
334 
335  //AsyncWiFiManagerParameter networkNameParam ("netname", "Network name", networkName, (int)NETWORK_NAME_LENGTH, "required type=\"text\" maxlength=20");
336  //AsyncWiFiManagerParameter netKeyParam ("netkey", "NetworkKey", networkKey, 33, "required type=\"password\" maxlength=32");
337  AsyncWiFiManagerParameter sleepyParam ("sleepy", "Sleep Time", sleepy, 5, "required type=\"number\" min=\"0\" max=\"13600\" step=\"1\"");
338  AsyncWiFiManagerParameter nodeNameParam ("nodename", "Node Name", nodeName, NODE_NAME_LENGTH, "type=\"text\" pattern=\"^[^/\\\\]+$\" maxlength=32");
339 
340  wifiManager->setCustomHeadElement ("<style>input:invalid {border: 2px dashed red;input:valid{border: 2px solid black;}</style>");
341  //wifiManager->addParameter (&networkNameParam);
342  //wifiManager->addParameter (&netKeyParam);
343  wifiManager->addParameter (&sleepyParam);
344  wifiManager->addParameter (&nodeNameParam);
345 
348  }
349 
350  wifiManager->setDebugOutput (true);
351  wifiManager->setConnectTimeout (30);
352  wifiManager->setBreakAfterConfig (true);
353  wifiManager->setTryConnectDuringConfigPortal (false);
354  char apname[64];
355 #ifdef ESP8266
356  snprintf (apname, 64, "EnigmaIoTNode%06x", ESP.getChipId ());
357  //String apname = "EnigmaIoTNode" + String (ESP.getChipId (), 16);
358 #elif defined ESP32
359  snprintf (apname, 64, "EnigmaIoTNode%06x", (uint32_t)(ESP.getEfuseMac ()) & (uint64_t)0x0000000000FFFFFF);
360  //String apname = "EnigmaIoTNode" + String (ESP.getEfuseMac (), 16);
361 #endif
362  DEBUG_VERBOSE ("Start AP: %s", apname);
363 
364  boolean result = wifiManager->startConfigPortal (apname, NULL);
365  if (result) {
366  DEBUG_DBG ("==== Config Portal result ====");
367 
368  DEBUG_DBG ("Network Name: %s", WiFi.SSID ().c_str ());
369 #ifdef ESP8266
370  station_config wifiConfig;
371  if (!wifi_station_get_config (&wifiConfig)) {
372  DEBUG_WARN ("Error getting WiFi config");
373  }
374  DEBUG_DBG ("WiFi password: %s", wifiConfig.password);
375  const char* netkey = (char*)(wifiConfig.password);
376 #elif defined ESP32
377  const char* netkey = WiFi.psk ().c_str ();
378 #endif
379  DEBUG_DBG ("Network Key: %s", netkey);
380  DEBUG_DBG ("Sleppy time: %s", sleepyParam.getValue ());
381  DEBUG_DBG ("Node Name: %s", nodeNameParam.getValue ());
382 
383  data->lastMessageCounter = 0;
384 
385  strncpy ((char*)(data->networkKey), netkey, KEY_LENGTH);
386  DEBUG_DBG ("Stored network key before hash: %.*s", KEY_LENGTH, (char*)(data->networkKey));
387 
388  CryptModule::getSHA256 (data->networkKey, KEY_LENGTH);
389  DEBUG_DBG ("Calculated network key: %s", printHexBuffer (data->networkKey, KEY_LENGTH));
390  data->nodeRegisterStatus = UNREGISTERED;
391 
392  const char* netName = WiFi.SSID ().c_str ();
393  memcpy (data->networkName, netName, strlen (netName));
394  DEBUG_DBG ("Stored network name: %s", data->networkName);
395 
396  std::regex sleepTimeRegex ("(\\d)+");
397  regexResult = std::regex_match (sleepyParam.getValue (), sleepTimeRegex);
398  if (regexResult) {
399  DEBUG_DBG ("Sleep time check ok");
400  int sleepyVal = atoi (sleepyParam.getValue ());
401  if (sleepyVal > 0) {
402  data->sleepy = true;
403  }
404  data->sleepTime = sleepyVal;
405  } else {
406  DEBUG_WARN ("Sleep time parameter error");
407  result = false;
408  }
409 
410  std::regex nodeNameRegex ("^[^/\\\\]+$");
411  regexResult = std::regex_match (nodeNameParam.getValue (), nodeNameRegex);
412  if (regexResult) {
413  strncpy (data->nodeName, nodeNameParam.getValue (), NODE_NAME_LENGTH);
414  DEBUG_DBG ("Node name: %s", data->nodeName);
415  } else {
416  DEBUG_WARN ("Node name parameter error");
417  result = false;
418  }
419 
420  data->nodeKeyValid = false;
421  data->crc32 = calculateCRC32 ((uint8_t*)(data->nodeKey), sizeof (rtcmem_data_t) - sizeof (uint32_t));
422  }
423 
424  if (notifyWiFiManagerExit) {
425  notifyWiFiManagerExit (result);
426  }
427 
428  return result;
429 }
430 
431 void flashLed (void* led) {
432 #ifdef ESP8266
433  digitalWrite (*(int*)led, !digitalRead (*(int*)led));
434 #elif defined ESP32
435  bool led_on = !digitalRead (localLed);
436  DEBUG_VERBOSE ("Change LED %d to %d", localLed, led_on);
437  digitalWrite (localLed, led_on);
438 #endif
439 }
440 
441 void startFlash (time_t period) {
442 #ifdef ESP32
443  static int id = 1;
444  DEBUG_INFO ("Start flash");
447  ledTimer = xTimerCreate ("led_flash", pdMS_TO_TICKS (period), pdTRUE, (void*)0, &flashLed);
448  if (xTimerStart (ledTimer, 0) != pdPASS) {
449  DEBUG_WARN ("Problem starting LED timer");
450  }
451  }
452 #elif defined (ESP8266)
453  ets_timer_disarm (&ledTimer);
456  ets_timer_arm_new (&ledTimer, period, true, true);
457  }
458 #endif // ESP32
459 }
460 
461 void stopFlash () {
462 #ifdef ESP32
465  xTimerStop (ledTimer, 0);
466  xTimerDelete (ledTimer, 0);
467 }
468 #elif defined(ESP8266)
471  ets_timer_disarm (&ledTimer);
472  digitalWrite (localLed, LED_OFF);
473  }
474 #endif // ESP32
475 }
476 
478  identifyStart = millis ();
479  indentifying = true;
480  startFlash (period);
481 }
482 
484  indentifying = false;
485  stopFlash ();
486 }
487 
489  if (resetPin > 0) {
490  pinMode (resetPin, INPUT_PULLUP);
491  digitalWrite (led, LED_ON); // Turn on LED
492  if (digitalRead (resetPin) == LOW) { // If pin is grounded
493  time_t resetPinGrounded = millis ();
494  while (digitalRead (resetPin) == LOW) {
495  if (millis () - resetPinGrounded > RESET_PIN_DURATION) {
496  DEBUG_WARN ("Produce reset");
497  digitalWrite (led, LED_OFF); // Turn off LED
498  startFlash (50);
499  clearFlash ();
500  clearRTC ();
501  delay (5000);
502  ESP.restart ();
503  }
504  delay (50);
505  }
506  }
507  }
508 }
509 
510 void EnigmaIOTNodeClass::begin (Comms_halClass* comm, uint8_t* gateway, uint8_t* networkKey, bool useCounter, bool sleepy) {
511  pinMode (led, OUTPUT);
512 #ifdef ESP8266
513  ets_timer_setfn (&ledTimer, flashLed, (void*)&led);
514 #endif
515  localLed = led;
516 
517  checkResetButton ();
518 
519  // startFlash (100); // Do not flash during setup for less battery drain
520 
521  digitalWrite (led, LED_OFF);
522 
523  this->comm = comm;
524 
525  this->useCounter = useCounter;
526 
527  node.setInitAsSleepy (sleepy);
528  node.setSleepy (sleepy);
529  DEBUG_DBG ("Set %s mode: %s", node.getSleepy () ? "sleepy" : "non sleepy", sleepy ? "sleepy" : "non sleepy");
530 
531  if (loadRTCData () && rtcmem_data.commErrors < COMM_ERRORS_BEFORE_SCAN) { // If data present on RTC node has waked up or it is just configured, continue
532 #if DEBUG_LEVEL >= DBG
533  char gwAddress[ENIGMAIOT_ADDR_LEN * 3];
534  DEBUG_DBG ("RTC data loaded. Gateway: %s", mac2str (rtcmem_data.gateway, gwAddress));
535  DEBUG_DBG ("Own address: %s", mac2str (node.getMacAddress (), gwAddress));
536 #endif
537  } else { // No RTC data, first boot or not configured
538  if (gateway && networkKey) { // If connection data has been passed to library
539  DEBUG_DBG ("EnigmaIot started with config data con begin() call");
540  memcpy (rtcmem_data.gateway, gateway, comm->getAddressLength ()); // setGateway
541  memcpy (rtcmem_data.networkKey, networkKey, KEY_LENGTH); // setNetworkKey
543  rtcmem_data.nodeKeyValid = false;
544  //rtcmem_data.channel = channel;
545  rtcmem_data.sleepy = sleepy;
547  } else { // Try read from flash
548  if (!SPIFFS.begin ()) {
549  DEBUG_ERROR ("Error mounting flash");
550  if (SPIFFS.format ()) {
551  DEBUG_INFO ("SPIFFS formatted");
552  } else {
553  DEBUG_ERROR ("Error formatting SPIFFS");
554  }
555  delay (2500);
556  ESP.restart ();
557  //return;
558  }
559  if (loadFlashData ()) { // If data present on flash, read and continue
561  DEBUG_DBG ("Flash data loaded");
562  uint8_t prevGwAddr[ENIGMAIOT_ADDR_LEN];
563  memcpy (prevGwAddr, rtcmem_data.gateway, 6);
564  if (searchForGateway (&rtcmem_data), true) {
565  //DEBUG_DBG ("Found gateway. Storing");
567  }
568  } else { // Configuration empty. Enter config AP mode
569  DEBUG_DBG ("No flash data present. Starting Configuration AP");
570  bool result = configWiFiManager (&rtcmem_data);
571  if (result) {
572  DEBUG_DBG ("Got configuration. Searching for Gateway");
573  if (!searchForGateway (&rtcmem_data), true) {
574  DEBUG_DBG ("Found EnigmaIOT Gateway. Storing configuration");
575  if (!saveFlashData (true)) {
576  DEBUG_ERROR ("Error saving data on flash");
577  }
578  SPIFFS.end ();
579  ESP.restart ();
580  return;
581  }
582  SPIFFS.end ();
583  ESP.restart ();
584  } else { // Configuration error
585  DEBUG_ERROR ("Configuration error. Restarting");
586  ESP.restart ();
587  }
588  }
589  }
590  }
591 
594  comm->onDataRcvd (rx_cb);
595  comm->onDataSent (tx_cb);
596 
597 #ifdef ESP8266
598  wifi_set_channel (rtcmem_data.channel);
599 #elif defined ESP32
600  esp_err_t err_ok;
601  if ((err_ok = esp_wifi_set_promiscuous (true))) {
602  DEBUG_ERROR ("Error setting promiscuous mode: %s", esp_err_to_name (err_ok));
603  }
604  if ((err_ok = esp_wifi_set_channel (rtcmem_data.channel, WIFI_SECOND_CHAN_NONE))) {
605  DEBUG_ERROR ("Error setting wifi channel: %s", esp_err_to_name (err_ok));
606  }
607  if ((err_ok = esp_wifi_set_promiscuous (false))) {
608  DEBUG_ERROR ("Error setting promiscuous mode off: %s", esp_err_to_name (err_ok));
609  }
610 #endif
611 
612  DEBUG_DBG ("Comms started. Channel %u", rtcmem_data.channel);
613 }
614 
615 #ifdef ESP32
616 int scanGatewaySSID (char* name, int& wifiIndex) {
617  uint32_t scanStarted;
618  int16_t numAP = 0;
619  const int MAX_INDEXES = 10;
620  int numFound = 0;
621  int indexes[MAX_INDEXES];
622 
623  if (!name) {
624  DEBUG_WARN ("SSID Name is NULL");
625  return 0;
626  }
627 
628  scanStarted = millis ();
629  numAP = WiFi.scanNetworks (false, false, false, 300U);
630  DEBUG_DBG ("Found %d APs in %lu ms", numAP, millis () - scanStarted);
631  DEBUG_DBG ("Scan finished. Result = %d", WiFi.scanComplete ());
632  while (!(WiFi.scanComplete ()) && (millis () - scanStarted) > 1500) { //
633 #if DEBUG_LEVEL >= DBG
634  delay (250);
635  Serial.printf ("%lu.", millis () - scanStarted);
636 #else
637  delay (50);
638 #endif
639  }
640  DEBUG_DBG ("Scan finished. Result = %d", WiFi.scanComplete ());
641 
642  DEBUG_DBG ("Found %d APs in %lu ms", numAP, millis () - scanStarted);
643 
644  wifi_ap_record_t* wifiAP;
645 
646  for (int i = 0; i < numAP; i++) {
647  wifiAP = (wifi_ap_record_t*)WiFi.getScanInfoByIndex (i);
648  DEBUG_DBG ("Found AP %.*s with BSSID " MACSTR " and RSSI %d dBm", 32, wifiAP->ssid, MAC2STR (wifiAP->bssid), wifiAP->rssi);
649  if (!strncmp (name, (char*)(wifiAP->ssid), 32)) {
650  indexes[numFound] = i;
651  numFound++;
652  if (numFound >= MAX_INDEXES) {
653  break;
654  }
655  }
656  }
657 
658  wifiIndex = indexes[0];
659 
660  return numFound;
661 }
662 #endif
663 
665  DEBUG_DBG ("Searching for AP %s", data->networkName);
666 
667  //WiFi.mode (WIFI_STA);
668  int numWifi = 0;
669  int wifiIndex = 0;
670 
671  time_t scanStarted = millis ();
672 #ifdef ESP8266
673  numWifi = WiFi.scanNetworks (false, false, 0, (uint8_t*)(data->networkName));
674  while (!(WiFi.scanComplete () || (millis () - scanStarted) > 1500)) {
675 #if DEBUG_LEVEL >= DBG
676  delay (250);
677  Serial.printf ("%lu.", millis () - scanStarted);
678 #else
679  delay (50);
680 #endif
681 }
682 #elif defined ESP32
683  numWifi = scanGatewaySSID (data->networkName, wifiIndex);
684 #endif // ESP8266
685 
686  uint8_t prevGwAddr[ENIGMAIOT_ADDR_LEN];
687  memcpy (prevGwAddr, data->gateway, 6);
688 
689  if (numWifi > 0) {
690  DEBUG_INFO ("Gateway %s found: %d", data->networkName, numWifi);
691  DEBUG_INFO ("BSSID: %s", WiFi.BSSIDstr (wifiIndex).c_str ());
692  DEBUG_INFO ("Channel: %d", WiFi.channel (wifiIndex));
693  DEBUG_INFO ("RSSI: %d", WiFi.RSSI (wifiIndex));
694  data->channel = WiFi.channel (wifiIndex);
695  data->rssi = WiFi.RSSI (wifiIndex);
696  memcpy (data->gateway, WiFi.BSSID (wifiIndex), 6);
697 
698  if (shouldStoreData) {
699  DEBUG_DBG ("Found gateway. Storing");
700  if (!saveRTCData ()) {
701  DEBUG_ERROR ("Error saving data on RTC");
702  }
703  if (memcmp (prevGwAddr, data->gateway, 6)) {
704  if (!saveFlashData ()) {
705  DEBUG_ERROR ("Error saving data on flash");
706  }
707  }
708  }
709 
710  WiFi.scanDelete ();
711  //WiFi.mode (WIFI_AP);
712  //WiFi.softAPdisconnect ();
713 
714 #ifdef ESP8266
715  wifi_set_channel (data->channel);
716 #elif defined ESP32
717  esp_err_t err_ok;
718  if ((err_ok = esp_wifi_set_promiscuous (true))) {
719  DEBUG_ERROR ("Error setting promiscuous mode: %s", esp_err_to_name (err_ok));
720  }
721  if ((err_ok = esp_wifi_set_channel (data->channel, WIFI_SECOND_CHAN_NONE))) {
722  DEBUG_ERROR ("Error setting wifi channel: %s", esp_err_to_name (err_ok));
723  }
724  if ((err_ok = esp_wifi_set_promiscuous (false))) {
725  DEBUG_ERROR ("Error setting promiscuous mode off: %s", esp_err_to_name (err_ok));
726  }
727 #endif
728 
729  requestReportRSSI = true;
730  return true;
731  }
732  DEBUG_WARN ("Gateway %s not found", data->networkName);
733  return false;
734 }
735 
737  comm->stop ();
738  DEBUG_DBG ("Communication layer uninitalized");
739 }
740 
742  node.setMacAddress (address);
743  return true;
744 }
745 
746 void EnigmaIOTNodeClass::setSleepTime (uint32_t sleepTime) {
747  if (node.getInitAsSleepy ()) {
748 #ifdef ESP8266 // ESP32 does not have this limitation
749  uint64_t maxSleepTime = (ESP.deepSleepMax () / (uint64_t)1000000);
750 #endif
751 
752  if (sleepTime == 0) {
753  node.setSleepy (false);
754  //rtcmem_data.sleepy = false; // This setting is temporary, do not store
755  } else if (sleepTime
756 #ifdef ESP8266
757  < maxSleepTime
758 #endif
759  ) {
760  node.setSleepy (true);
762  }
763 #ifdef ESP8266
764  else {
765  DEBUG_DBG ("Max sleep time is %lu", (uint32_t)maxSleepTime);
766  node.setSleepy (true);
767  rtcmem_data.sleepTime = (uint32_t)maxSleepTime;
768  }
769 #endif
770  this->sleepTime = (uint64_t)rtcmem_data.sleepTime * (uint64_t)1000000;
771  DEBUG_DBG ("Sleep time set to %d. Sleepy mode is %s",
773  node.getSleepy () ? "sleepy" : "non sleepy");
774 
775  } else {
776  DEBUG_WARN ("Cannot set sleep time to %u seconds as this node started as non sleepy", sleepTime);
777  }
778 }
779 
781  uint8_t buffer[MAX_MESSAGE_LENGTH];
782  uint8_t bufLength;
783 
784  DEBUG_DBG ("Report RSSI and channel");
785 
786  buffer[0] = control_message_type::RSSI_ANS;
787  buffer[1] = rtcmem_data.rssi;
788  buffer[2] = rtcmem_data.channel;
789  bufLength = 3;
790 
791  if (sendData (buffer, bufLength, true)) {
792  DEBUG_DBG ("Sleep time is %d seconds", sleepTime / 1000000);
793  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
794  return true;
795  } else {
796  DEBUG_WARN ("Error sending version response");
797  return false;
798  }
799 }
800 
802  static unsigned long blueOntime;
803 
804  // Locate gateway address, channel and rssi
805  if (requestSearchGateway) {
806  requestSearchGateway = false;
807  requestReportRSSI = true;
808  searchForGateway (&rtcmem_data, true);
809  }
810 
811  // Report RSSI to gateway
812  if (requestReportRSSI && node.isRegistered ()) {
813  requestReportRSSI = false;
814  reportRSSI ();
815  }
816 
817  // Flash led if programmed (when data is transferred)
818  if (led >= 0) {
819  if (flashBlue) {
820  blueOntime = millis ();
821  digitalWrite (led, LED_ON);
822  flashBlue = false;
823  }
824 
825  if (!indentifying) {
826  if ( millis () - blueOntime > ledOnTime) {
827  digitalWrite (led, LED_OFF);
828  }
829  }
830  }
831 
832  // Check if this should go to sleep
833  if (node.getSleepy ()) {
835  uint64_t msSleep = sleepTime / (uint64_t)1000;
836  DEBUG_INFO ("Go to sleep for %lu ms", (uint32_t)(msSleep));
837 #ifdef ESP8266
838  ESP.deepSleep (sleepTime);
839 #elif defined ESP32
840  esp_deep_sleep (sleepTime);
841 #endif
842  }
843  }
844 
845  // Check registration timeout
846  static time_t lastRegistration = millis ();
848  if (status == WAIT_FOR_SERVER_HELLO /*|| status == WAIT_FOR_CIPHER_FINISHED*/) {
849  if (node.getSleepy ()) { // Sleep after registration timeout
850  if (millis () - node.getLastMessageTime () > RECONNECTION_PERIOD) {
851  DEBUG_INFO ("Current node status: %d", node.getStatus ());
852  node.reset ();
854 
855  if (!saveRTCData ()) {
856  DEBUG_ERROR ("Error saving data on RTC");
857  }
858 
859  uint32_t rnd = Crypto.random (PRE_REG_DELAY * 1000); // nanoseconds
860 
861  DEBUG_INFO ("Registration timeout. Go to sleep for %lu ms", (uint32_t)(RECONNECTION_PERIOD * 4 + rnd/1000));
862 #ifdef ESP8266
863  ESP.deepSleep (RECONNECTION_PERIOD * 4000 + rnd, RF_NO_CAL);
864 #elif defined ESP32
865  ESP.deepSleep (RECONNECTION_PERIOD * 4000 + rnd);
866 #endif
867  }
868  } else { // Retry registration
869  if (millis () - node.getLastMessageTime () > RECONNECTION_PERIOD * 5) {
870  DEBUG_INFO ("Current node status: %d", node.getStatus ());
871  node.reset ();
872  node.setLastMessageTime (); // Set wait time start
873  }
874  }
875  }
876 
877  // Retry registration
878  if (node.getStatus () == UNREGISTERED) {
879  if (millis () - lastRegistration > RECONNECTION_PERIOD) {
880  DEBUG_DBG ("Current node status: %d", node.getStatus ());
881  lastRegistration = millis (); // Set wait time start
882  node.reset ();
883  uint32_t rnd = Crypto.random (PRE_REG_DELAY);
884  DEBUG_INFO ("Random delay (%u)", rnd);
885  delay (1500 + rnd);
886  clientHello ();
887  delay (1500 + Crypto.random (POST_REG_DELAY)); // Wait for Server Hello
888  }
889  }
890 
891  // Check OTA update timeout
892  if (otaRunning) {
893  if (millis () - lastOTAmsg > OTA_TIMEOUT_TIME) {
894  uint8_t responseBuffer[2];
895  responseBuffer[0] = control_message_type::OTA_ANS;
896  responseBuffer[1] = ota_status::OTA_TIMEOUT;
897  if (sendData (responseBuffer, sizeof (responseBuffer), true)) {
898  DEBUG_INFO ("OTA TIMEOUT");
899  }
900  otaRunning = false;
901  restart ();
902  }
903  }
904 
905  // Check identifying LED timeout
906  if (indentifying) {
907  if (millis () - identifyStart > IDENTIFY_TIMEOUT) {
908  stopIdentifying ();
909  digitalWrite (led, LED_OFF);
910  }
911  }
912 
913  //if (!node.getSleepy () && node.isRegistered () && !node.hasClockSync())
914  // clockRequest ();
915 
916  // Check time sync timeout
917  if (clockSyncEnabled) {
918  static time_t lastTimeSync;
919  if (!node.getSleepy () && node.isRegistered ()) {
920  if ((millis () - lastTimeSync > timeSyncPeriod)) {
921  lastTimeSync = millis ();
922  DEBUG_DBG ("Clock Request");
923  clockRequest ();
924  }
925  }
926  }
927 
928  // Check restart
929  if (shouldRestart) {
930  static unsigned long retartRequest = millis ();
931  if (millis () - retartRequest > 2500) {
932  DEBUG_WARN ("Restart");
933  ESP.restart ();
934  }
935  }
936 
937  // In case of comm errors search for gateway again
939  if (!gatewaySearchStarted) {
940  gatewaySearchStarted = true;
941 
942  if (searchForGateway (&rtcmem_data), true) {
944  }
945  }
946  }
947 
948 }
949 
950 void EnigmaIOTNodeClass::rx_cb (uint8_t* mac_addr, uint8_t* data, uint8_t len) {
951  EnigmaIOTNode.manageMessage (mac_addr, data, len);
952 }
953 
954 void EnigmaIOTNodeClass::tx_cb (uint8_t* mac_addr, uint8_t status) {
955  EnigmaIOTNode.getStatus (mac_addr, status);
956 }
957 
958 bool EnigmaIOTNodeClass::checkCRC (const uint8_t* buf, size_t count, uint32_t* crc) {
959  uint32_t recvdCRC;
960 
961  memcpy (&recvdCRC, crc, sizeof (uint32_t));
962  //DEBUG_VERBOSE ("Received CRC32: 0x%08X", *crc32);
963  uint32_t _crc = calculateCRC32 (buf, count);
964  DEBUG_VERBOSE ("CRC32 = Calc: 0x%08X Recvd: 0x%08X Length: %d", _crc, recvdCRC, count);
965  return (_crc == recvdCRC);
966 }
967 
969  /*
970  * -------------------------------------------------------
971  *| msgType (1) | random (12) | DH Kmaster (32) | Tag (16) |
972  * -------------------------------------------------------
973  */
974 
975  struct __attribute__ ((packed, aligned (1))) {
976  uint8_t msgType;
977  uint8_t iv[IV_LENGTH];
978  uint8_t publicKey[KEY_LENGTH];
979  uint32_t random;
980  uint8_t tag[TAG_LENGTH];
981  } clientHello_msg;
982 
983 #define CHMSG_LEN sizeof(clientHello_msg)
984 
985  invalidateReason = UNKNOWN_ERROR; // reset any previous force disconnect
986 
987  Crypto.getDH1 ();
988  node.setStatus (INIT);
990  /*uint8_t macAddress[ENIGMAIOT_ADDR_LEN];
991 #ifdef ESP8266
992  if (wifi_get_macaddr (STATION_IF, macAddress)) {
993 #elif defined ESP32
994  if (esp_wifi_get_mac (WIFI_IF_STA, macAddress) == ESP_OK) {
995 #endif
996  node.setMacAddress (macAddress);
997  }*/
998 
999  uint8_t* key = Crypto.getPubDHKey ();
1000 
1001  if (!key) {
1002  DEBUG_ERROR ("Error calculating public ECDH key");
1003  return false;
1004  }
1005 
1006  clientHello_msg.msgType = CLIENT_HELLO; // Client hello message
1007 
1008  CryptModule::random (clientHello_msg.iv, IV_LENGTH);
1009 
1010  DEBUG_VERBOSE ("IV: %s", printHexBuffer (clientHello_msg.iv, IV_LENGTH));
1011 
1012  for (int i = 0; i < KEY_LENGTH; i++) {
1013  clientHello_msg.publicKey[i] = key[i];
1014  }
1015 
1016  uint32_t random;
1017  random = Crypto.random ();
1018 
1019  if (node.getSleepy ()) {
1020  random = random | 0x00000001U; // Signal sleepy node
1021  DEBUG_DBG ("Signal sleepy node");
1022  } else {
1023  random = random & 0xFFFFFFFEU; // Signal always awake node
1024  DEBUG_DBG ("Signal non sleepy node");
1025  }
1026 
1027  memcpy (&(clientHello_msg.random), &random, RANDOM_LENGTH);
1028 
1029  DEBUG_VERBOSE ("Client Hello message: %s", printHexBuffer ((uint8_t*)&clientHello_msg, CHMSG_LEN - TAG_LENGTH));
1030 
1031  uint8_t addDataLen = CHMSG_LEN - TAG_LENGTH - sizeof (uint32_t) - KEY_LENGTH;
1032  uint8_t aad[AAD_LENGTH + addDataLen];
1033 
1034  memcpy (aad, (uint8_t*)&clientHello_msg, addDataLen); // Copy message upto iv
1035 
1036  // Copy 8 last bytes from NetworkKey
1037  memcpy (aad + addDataLen, rtcmem_data.networkKey + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1038 
1039  if (!CryptModule::encryptBuffer (clientHello_msg.publicKey, KEY_LENGTH + sizeof (uint32_t), // Encrypt only from public key
1040  clientHello_msg.iv, IV_LENGTH,
1041  rtcmem_data.networkKey, KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
1042  aad, sizeof (aad), clientHello_msg.tag, TAG_LENGTH)) {
1043  DEBUG_ERROR ("Error during encryption");
1044  return false;
1045  }
1046 
1047  DEBUG_VERBOSE ("Encrypted Client Hello message: %s", printHexBuffer ((uint8_t*)&clientHello_msg, CHMSG_LEN));
1048 
1051 
1052  DEBUG_INFO (" -------> CLIENT HELLO");
1053 
1054  return comm->send (rtcmem_data.gateway, (uint8_t*)&clientHello_msg, CHMSG_LEN) == 0;
1055 }
1056 
1058  struct __attribute__ ((packed, aligned (1))) {
1059  uint8_t msgType;
1060  uint8_t iv[IV_LENGTH];
1061  int64_t t1;
1062  uint8_t tag[TAG_LENGTH];
1063  } clockRequest_msg;
1064 
1065  static const uint8_t CRMSG_LEN = sizeof (clockRequest_msg);
1066 
1067  clockRequest_msg.msgType = CLOCK_REQUEST;
1068 
1069  CryptModule::random (clockRequest_msg.iv, IV_LENGTH);
1070 
1071  DEBUG_VERBOSE ("IV: %s", printHexBuffer (clockRequest_msg.iv, IV_LENGTH));
1072 
1073 
1075 
1076  memcpy (&(clockRequest_msg.t1), &(node.t1), sizeof (int64_t));
1077 
1078  DEBUG_VERBOSE ("Clock Request message: %s", printHexBuffer ((uint8_t*)&clockRequest_msg, CRMSG_LEN - TAG_LENGTH));
1079  DEBUG_DBG ("T1: %llu", node.t1);
1080 
1081  uint8_t addDataLen = 1 + IV_LENGTH;
1082  uint8_t aad[AAD_LENGTH + addDataLen];
1083 
1084  memcpy (aad, (uint8_t*)&clockRequest_msg, addDataLen); // Copy message upto iv
1085 
1086  // Copy 8 last bytes from Node Key
1087  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1088 
1089  if (!CryptModule::encryptBuffer ((uint8_t*)&(clockRequest_msg.t1), sizeof (clock_t), // Encrypt only from public key
1090  clockRequest_msg.iv, IV_LENGTH,
1091  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
1092  aad, sizeof (aad), clockRequest_msg.tag, TAG_LENGTH)) {
1093  DEBUG_ERROR ("Error during encryption");
1094  return false;
1095  }
1096 
1097  DEBUG_VERBOSE ("Encrypted Clock Request message: %s", printHexBuffer ((uint8_t*)&clockRequest_msg, CRMSG_LEN));
1098 
1099  DEBUG_INFO (" -------> CLOCK REQUEST");
1100 
1102 
1103  flashBlue = true;
1104 
1105  return comm->send (rtcmem_data.gateway, (uint8_t*)&clockRequest_msg, CRMSG_LEN) == 0;
1106 
1107 }
1108 
1109 bool EnigmaIOTNodeClass::processClockResponse (const uint8_t* mac, const uint8_t* buf, size_t count) {
1110  struct __attribute__ ((packed, aligned (1))) {
1111  uint8_t msgType;
1112  uint8_t iv[IV_LENGTH];
1113  int64_t t2;
1114  int64_t t3;
1115  uint8_t tag[TAG_LENGTH];
1116  } clockResponse_msg;
1117 
1118 #define CRSMSG_LEN sizeof(clockResponse_msg)
1119 
1120  memcpy (&clockResponse_msg, buf, count);
1121 
1122  uint8_t addDataLen = 1 + IV_LENGTH;
1123  uint8_t aad[AAD_LENGTH + addDataLen];
1124 
1125  memcpy (aad, buf, addDataLen); // Copy message upto iv
1126 
1127  // Copy 8 last bytes from Node Key
1128  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1129 
1130  uint8_t packetLen = count - TAG_LENGTH;
1131 
1132  if (!CryptModule::decryptBuffer ((uint8_t*)&(clockResponse_msg.t2), sizeof (int64_t) << 1, // Decrypt from t2, 16 bytes
1133  clockResponse_msg.iv, IV_LENGTH,
1134  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
1135  aad, sizeof (aad), clockResponse_msg.tag, TAG_LENGTH)) {
1136  DEBUG_ERROR ("Error during decryption");
1137  return false;
1138  }
1139 
1140  DEBUG_VERBOSE ("Decripted Clock Response message: %s", printHexBuffer ((uint8_t*)&clockResponse_msg, packetLen));
1141 
1142 
1143  node.t2 = clockResponse_msg.t2;
1144  node.t3 = clockResponse_msg.t3;
1145  node.t4 = TimeManager.clock ();
1146 
1147  if (count < CRSMSG_LEN) {
1148  DEBUG_WARN ("Message too short");
1149  return false;
1150  }
1151 
1152  memcpy (&clockResponse_msg, buf, count);
1153 
1154  int64_t offset = TimeManager.adjustTime (node.t1, node.t2, node.t3, node.t4);
1155 
1156  if (offset < MIN_SYNC_ACCURACY && offset > (MIN_SYNC_ACCURACY * -1)) {
1158  } else {
1160  }
1161  DEBUG_VERBOSE ("Clock Response message: %s", printHexBuffer ((uint8_t*)&clockResponse_msg, CRSMSG_LEN - TAG_LENGTH));
1162 
1163  DEBUG_DBG ("T1: %llu", node.t1);
1164  DEBUG_DBG ("T2: %llu", node.t2);
1165  DEBUG_DBG ("T3: %llu", node.t3);
1166  DEBUG_DBG ("T4: %llu", node.t4);
1167  DEBUG_DBG ("Offest adjusted to %lld ms, Roundtrip delay is %lld", offset, TimeManager.getDelay ());
1168 
1169  return true;
1170 }
1171 
1173  if (node.getInitAsSleepy ()) {
1174  return millis ();
1175  } else {
1176  return TimeManager.clock ();
1177  }
1178 
1179 }
1180 
1182  if (node.getInitAsSleepy ()) {
1183  return millis () / 1000;
1184  } else {
1185  return TimeManager.unixtime ();
1186  }
1187 }
1188 
1190  if (!node.getInitAsSleepy ())
1191  return TimeManager.isTimeAdjusted ();
1192  else
1193  return false;
1194 }
1195 
1196 bool EnigmaIOTNodeClass::processServerHello (const uint8_t* mac, const uint8_t* buf, size_t count) {
1197  /*
1198  * ------------------------------------------------------
1199  *| msgType (1) | random (12) | DH Kslave (32) | Tag (16) |
1200  * ------------------------------------------------------
1201  */
1202 
1203  struct __attribute__ ((packed, aligned (1))) {
1204  uint8_t msgType;
1205  uint8_t iv[IV_LENGTH];
1206  uint8_t publicKey[KEY_LENGTH];
1207  uint16_t nodeId;
1208  uint32_t random;
1209  uint8_t tag[TAG_LENGTH];
1210  } serverHello_msg;
1211 
1212 #define SHMSG_LEN sizeof(serverHello_msg)
1213 
1214  uint16_t nodeId;
1215 
1216  if (count < SHMSG_LEN) {
1217  DEBUG_WARN ("Message too short");
1218  return false;
1219  }
1220 
1221  memcpy (&serverHello_msg, buf, count);
1222 
1223  uint8_t addDataLen = SHMSG_LEN - TAG_LENGTH - sizeof (uint32_t) - sizeof (uint16_t) - KEY_LENGTH;
1224  uint8_t aad[AAD_LENGTH + addDataLen];
1225 
1226  memcpy (aad, (uint8_t*)&serverHello_msg, addDataLen); // Copy message upto iv
1227 
1228  // Copy 8 last bytes from NetworkKey
1229  memcpy (aad + addDataLen, rtcmem_data.networkKey + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1230 
1231  if (!CryptModule::decryptBuffer (serverHello_msg.publicKey, KEY_LENGTH + sizeof (uint16_t) + sizeof (uint32_t),
1232  serverHello_msg.iv, IV_LENGTH,
1233  rtcmem_data.networkKey, KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
1234  aad, sizeof (aad), serverHello_msg.tag, TAG_LENGTH)) {
1235  DEBUG_ERROR ("Error during decryption");
1236  return false;
1237  }
1238 
1239  DEBUG_VERBOSE ("Decrypted Server Hello message: %s", printHexBuffer ((uint8_t*)&serverHello_msg, SHMSG_LEN - TAG_LENGTH));
1240 
1241  bool cError = Crypto.getDH2 (serverHello_msg.publicKey);
1242 
1243  if (!cError) {
1244  DEBUG_ERROR ("DH2 error");
1245  return false;
1246  }
1247 
1248  memcpy (&nodeId, &serverHello_msg.nodeId, sizeof (uint16_t));
1249  node.setNodeId (nodeId);
1250  rtcmem_data.nodeKeyValid = nodeId;
1251  DEBUG_DBG ("Node ID: %u", node.getNodeId ());
1252 
1253  node.setEncryptionKey (CryptModule::getSHA256 (serverHello_msg.publicKey, KEY_LENGTH));
1255  DEBUG_INFO ("Node key: %s", printHexBuffer (node.getEncriptionKey (), KEY_LENGTH));
1256 
1257  return true;
1258 }
1259 
1260 bool EnigmaIOTNodeClass::sendData (const uint8_t* data, size_t len, bool controlMessage, bool encrypt, nodePayloadEncoding_t payloadType) {
1261  if (!controlMessage) {
1262  memcpy (dataMessageSent, data, len);
1263  dataMessageSentLength = len;
1264  dataMessageEncrypt = encrypt;
1265  dataMessageSendPending = true;
1266  dataMessageSendEncoding = payloadType;
1267  }
1268  node.setLastMessageTime (); // Mark message time to start RX window start
1269 
1270  if (node.getStatus () == REGISTERED && node.isKeyValid ()) {
1271  if (controlMessage) {
1272  DEBUG_VERBOSE ("Control message sent: %s", printHexBuffer (data, len));
1273  } else {
1274  DEBUG_VERBOSE ("%s data sent: %s", encrypt ? "Encrypted" : "Unencrypted", printHexBuffer (data, len));
1275  }
1276  flashBlue = true;
1277  if (dataMessage (data, len, controlMessage, encrypt, payloadType)) {
1278  dataMessageSendPending = false; // Data sent. This setting can still be overriden by invalidateCommand
1279  return true;
1280  } else
1281  return false;
1282 
1283  }
1284  return false;
1285 }
1286 
1288  if (node.getSleepy ()) {
1289  DEBUG_DBG ("Sleep programmed for %lu ms", rtcmem_data.sleepTime * 1000);
1290  sleepTime = (uint64_t)rtcmem_data.sleepTime * (uint64_t)1000000;
1291  sleepRequested = true;
1292  } else {
1293  DEBUG_VERBOSE ("Node is non sleepy. Sleep rejected");
1294  }
1295 }
1296 
1297 bool EnigmaIOTNodeClass::unencryptedDataMessage (const uint8_t* data, size_t len, bool controlMessage, nodePayloadEncoding_t payloadEncoding) {
1298  /*
1299  * ------------------------------------------------------------------------
1300  *| msgType (1) | NodeId (2) | Counter (2) | PayloadType (1) | Data (....) |
1301  * ------------------------------------------------------------------------
1302  */
1303 
1304  uint8_t buf[MAX_MESSAGE_LENGTH];
1305  uint16_t counter;
1306  uint16_t nodeId = node.getNodeId ();
1307 
1308  uint8_t nodeId_idx = 1;
1309  uint8_t counter_idx = nodeId_idx + sizeof (int16_t);
1310  uint8_t encoding_idx = counter_idx + sizeof (int16_t);
1311  uint8_t data_idx = encoding_idx + sizeof (int8_t);
1312 
1313  uint8_t packet_length = data_idx + len;
1314 
1315  if (!data) {
1316  return false;
1317  }
1318 
1319  if (controlMessage) {
1320  return false; // Unencrypted control data not implemented
1321  } else {
1322  buf[0] = (uint8_t)UNENCRYPTED_NODE_DATA;
1323  }
1324 
1325  memcpy (buf + nodeId_idx, &nodeId, sizeof (uint16_t));
1326 
1327  if (!controlMessage) { // Control messages do not use counter
1328  if (useCounter) {
1329  counter = node.getLastMessageCounter () + 1;
1330  node.setLastMessageCounter (counter);
1331  rtcmem_data.lastMessageCounter = counter;
1332  } else {
1333  counter = (uint16_t)(Crypto.random ());
1334  }
1335 
1336  memcpy (buf + counter_idx, &counter, sizeof (uint16_t));
1337  }
1338 
1339  buf[encoding_idx] = (uint8_t)payloadEncoding;
1340 
1341  memcpy (buf + data_idx, data, len);
1342 
1343  DEBUG_INFO (" -------> UNENCRYPTED DATA");
1344  DEBUG_VERBOSE ("Unencrypted data message: %s", printHexBuffer (buf, packet_length));
1345 
1346 #if DEBUG_LEVEL >= VERBOSE
1347  char macStr[ENIGMAIOT_ADDR_LEN * 3];
1348  DEBUG_DBG ("Destination address: %s", mac2str (rtcmem_data.gateway, macStr));
1349 #endif
1350 
1351  if (useCounter && !otaRunning) { // RTC must not be written if OTA is running. OTA uses RTC memmory to signal 2nd firmware boot
1352  if (!saveRTCData ()) {
1353  DEBUG_ERROR ("Error saving data on RTC");
1354  }
1355  }
1356 
1357  return (comm->send (rtcmem_data.gateway, buf, packet_length) == 0);
1358 }
1359 
1360 
1361 bool EnigmaIOTNodeClass::dataMessage (const uint8_t* data, size_t len, bool controlMessage, bool encrypt, nodePayloadEncoding_t payloadEncoding) {
1362  /*
1363  * ----------------------------------------------------------------------------------------
1364  *| msgType (1) | IV (12) | length (2) | NodeId (2) | Counter (2) | Data (....) | tag (16) |
1365  * ----------------------------------------------------------------------------------------
1366  */
1367 
1368  if (!encrypt) {
1369  return unencryptedDataMessage (data, len, controlMessage, payloadEncoding);
1370  }
1371 
1372  uint8_t buf[MAX_MESSAGE_LENGTH];
1373  uint8_t tag[TAG_LENGTH];
1374  uint16_t counter;
1375  uint16_t nodeId = node.getNodeId ();
1376 
1377  uint8_t iv_idx = 1;
1378  uint8_t length_idx = iv_idx + IV_LENGTH;
1379  uint8_t nodeId_idx = length_idx + sizeof (int16_t);
1380  uint8_t counter_idx = nodeId_idx + sizeof (int16_t);
1381  uint8_t encoding_idx;
1382  uint8_t data_idx;
1383  if (!controlMessage) {
1384  encoding_idx = counter_idx + sizeof (int16_t);
1385  data_idx = encoding_idx + sizeof (int8_t);
1386  } else {
1387  data_idx = counter_idx + sizeof (int16_t);
1388  }
1389  uint8_t tag_idx = data_idx + len;
1390 
1391 
1392  if (!data) {
1393  return false;
1394  }
1395 
1396  if (controlMessage) {
1397  buf[0] = (uint8_t)CONTROL_DATA;
1398  } else {
1399  buf[0] = (uint8_t)SENSOR_DATA;
1400  }
1401 
1402  CryptModule::random (buf + iv_idx, IV_LENGTH);
1403 
1404  DEBUG_VERBOSE ("IV: %s", printHexBuffer (buf + iv_idx, IV_LENGTH));
1405 
1406  memcpy (buf + nodeId_idx, &nodeId, sizeof (uint16_t));
1407 
1408  if (!controlMessage) { // Control messages do not use counter
1409  if (useCounter) {
1410  counter = node.getLastMessageCounter () + 1;
1411  node.setLastMessageCounter (counter);
1412  rtcmem_data.lastMessageCounter = counter;
1413  } else {
1414  counter = (uint16_t)(Crypto.random ());
1415  }
1416 
1417  memcpy (buf + counter_idx, &counter, sizeof (uint16_t));
1418  }
1419 
1420  buf[encoding_idx] = payloadEncoding;
1421 
1422  memcpy (buf + data_idx, data, len);
1423 
1424  uint16_t packet_length = tag_idx;
1425 
1426  memcpy (buf + length_idx, &packet_length, sizeof (uint16_t));
1427 
1428  DEBUG_VERBOSE ("Data message: %s", printHexBuffer (buf, packet_length));
1429  DEBUG_DBG ("Encoding: 0x%02X", payloadEncoding);
1430 
1431  uint8_t* crypt_buf = buf + length_idx;
1432 
1433  size_t cryptLen = packet_length - 1 - IV_LENGTH;
1434 
1435  uint8_t addDataLen = 1 + IV_LENGTH;
1436  uint8_t aad[AAD_LENGTH + addDataLen];
1437 
1438  memcpy (aad, buf, addDataLen); // Copy message upto iv
1439 
1440  // Copy 8 last bytes from Node Key
1441  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1442 
1443  if (!CryptModule::encryptBuffer (crypt_buf, cryptLen, // Encrypt from length
1444  buf + iv_idx, IV_LENGTH,
1445  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of node key
1446  aad, sizeof (aad), buf + tag_idx, TAG_LENGTH)) {
1447  DEBUG_ERROR ("Error during encryption");
1448  return false;
1449  }
1450 
1451  DEBUG_VERBOSE ("Encrypted data message: %s", printHexBuffer (buf, packet_length + TAG_LENGTH));
1452 
1453  if (controlMessage) {
1454  DEBUG_INFO (" -------> CONTROL MESSAGE");
1455  } else {
1456  DEBUG_INFO (" -------> DATA");
1457  }
1458 #if DEBUG_LEVEL >= VERBOSE
1459  char macStr[ENIGMAIOT_ADDR_LEN * 3];
1460  DEBUG_DBG ("Destination address: %s", mac2str (rtcmem_data.gateway, macStr));
1461 #endif
1462 
1463  if (useCounter && !otaRunning) { // RTC must not be written if OTA is running. OTA uses RTC memmory to signal 2nd firmware boot
1464  if (!saveRTCData ()) {
1465  DEBUG_ERROR ("Error saving data on RTC");
1466  }
1467  }
1468 
1469  return (comm->send (rtcmem_data.gateway, buf, packet_length + TAG_LENGTH) == 0);
1470 }
1471 
1472 bool EnigmaIOTNodeClass::processGetSleepTimeCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1473  uint8_t buffer[MAX_MESSAGE_LENGTH];
1474  uint8_t bufLength;
1475 
1476  DEBUG_DBG ("Get Sleep command received");
1477  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
1478 
1479  buffer[0] = control_message_type::SLEEP_ANS;
1480  // TODO get real sleep time
1481  uint32_t sleepTime = getSleepTime ();
1482  memcpy (buffer + 1, &sleepTime, sizeof (sleepTime));
1483  bufLength = 5;
1484 
1485  if (sendData (buffer, bufLength, true)) {
1486  DEBUG_DBG ("Sleep time is %d seconds", sleepTime);
1487  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
1488  return true;
1489  } else {
1490  DEBUG_WARN ("Error sending version response");
1491  return false;
1492  }
1493 }
1494 
1495 bool EnigmaIOTNodeClass::processGetNameCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1496  uint8_t buffer[MAX_MESSAGE_LENGTH];
1497  uint8_t bufLength;
1498 
1499  DEBUG_DBG ("Get Name command received");
1500  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
1501 
1502  buffer[0] = control_message_type::NAME_ANS;
1503 
1504  uint8_t* nodeAddress = node.getMacAddress ();
1505 
1506  char* name = rtcmem_data.nodeName;
1507  size_t nameLen = 0;
1508  if (name) {
1509  nameLen = strlen (name);
1510  } else {
1511  DEBUG_WARN ("Emprty name");
1512  return false;
1513  }
1514 
1515  memcpy (buffer + 1, nodeAddress, ENIGMAIOT_ADDR_LEN);
1516  memcpy (buffer + 1 + ENIGMAIOT_ADDR_LEN, name, nameLen);
1517  bufLength = 1 + ENIGMAIOT_ADDR_LEN + nameLen;
1518 
1519  if (sendData (buffer, bufLength, true)) {
1520  DEBUG_DBG ("Node name is %s", name ? name : "NULL name");
1521  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
1522  return true;
1523  } else {
1524  DEBUG_WARN ("Error sending name response");
1525  return false;
1526  }
1527 }
1528 
1529 bool EnigmaIOTNodeClass::processSetNameResponse (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1530  /*
1531  * ---------------------------------------------------
1532  *| msgType (1) | IV (12) | Result code (1) | tag (16) |
1533  * ---------------------------------------------------
1534  */
1535  struct __attribute__ ((packed, aligned (1))) {
1536  uint8_t msgType;
1537  uint8_t iv[IV_LENGTH];
1538  int8_t errorCode;
1539  uint8_t tag[TAG_LENGTH];
1540  } nodeNameSetResponse_msg;
1541 
1542  const unsigned int NNSRMSG_LEN = sizeof (nodeNameSetResponse_msg);
1543 
1544  if (len < NNSRMSG_LEN) {
1545  DEBUG_WARN ("Message too short");
1546  return false;
1547  }
1548  memcpy (&nodeNameSetResponse_msg, data, len);
1549 
1550  const uint8_t addDataLen = 1 + IV_LENGTH;
1551  uint8_t aad[AAD_LENGTH + addDataLen];
1552 
1553  memcpy (aad, (uint8_t*)&nodeNameSetResponse_msg, addDataLen); // Copy message upto iv
1554 
1555  // Copy 8 last bytes from NetworkKey
1556  memcpy (aad + addDataLen, node.getEncriptionKey() + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1557 
1558  if (!CryptModule::decryptBuffer ((uint8_t*)&(nodeNameSetResponse_msg.errorCode), sizeof(uint8_t),
1559  nodeNameSetResponse_msg.iv, IV_LENGTH,
1560  node.getEncriptionKey(), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
1561  aad, sizeof (aad), nodeNameSetResponse_msg.tag, TAG_LENGTH)) {
1562  DEBUG_ERROR ("Error during decryption");
1563  return false;
1564  }
1565 
1566  DEBUG_VERBOSE ("Decrypted Node Name Set response message: %s", printHexBuffer ((uint8_t*)&nodeNameSetResponse_msg, NNSRMSG_LEN - TAG_LENGTH));
1567 
1568  if (nodeNameSetResponse_msg.errorCode != NAME_OK) {
1569  DEBUG_WARN ("Name error: %d", nodeNameSetResponse_msg.errorCode);
1570  } else {
1571  DEBUG_DBG ("Name set correctly");
1572  }
1573 
1574  return true;
1575 }
1576 
1577 bool EnigmaIOTNodeClass::processSetNameCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1578  uint8_t buffer[MAX_MESSAGE_LENGTH];
1579  uint8_t bufLength;
1580 
1581  DEBUG_DBG ("Set Name command received");
1582  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
1583 
1584  buffer[0] = control_message_type::NAME_ANS;
1585 
1586  uint8_t* nodeAddress = node.getMacAddress ();
1587 
1588  memcpy (rtcmem_data.nodeName, data + 1, len - 1);
1590 
1591  saveRTCData ();
1592  saveFlashData ();
1593 
1595  DEBUG_WARN ("Error sending set node name %s", rtcmem_data.nodeName);
1596  }
1597 
1598  size_t nameLen = strlen (rtcmem_data.nodeName);
1599 
1600  memcpy (buffer + 1, nodeAddress, ENIGMAIOT_ADDR_LEN);
1601  memcpy (buffer + 1 + ENIGMAIOT_ADDR_LEN, rtcmem_data.nodeName, nameLen);
1602  bufLength = 1 + ENIGMAIOT_ADDR_LEN + nameLen;
1603 
1604  if (sendData (buffer, bufLength, true)) {
1605  DEBUG_DBG ("Node name is %s", rtcmem_data.nodeName);
1606  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
1607  return true;
1608  } else {
1609  DEBUG_WARN ("Error sending name response");
1610  return false;
1611  }
1612 }
1613 
1614 bool EnigmaIOTNodeClass::sendNodeNameSet (const char* name) {
1615  if (!name)
1616  return false;
1617 
1618  size_t nameLength = strlen (name);
1619 
1620  DEBUG_INFO ("Setting node name to %s. Size: %d", name, nameLength);
1621 
1622  if (!nameLength || (nameLength > NODE_NAME_LENGTH)) {
1623  return false;
1624  }
1625 
1626  /*
1627  * ----------------------------------------------------------------------
1628  *| msgType (1) | IV (12) | NodeID (2) | Node name (up to 32) | tag (16) |
1629  * ----------------------------------------------------------------------
1630  */
1631 
1632  uint8_t buf[MAX_MESSAGE_LENGTH];
1633  uint8_t tag[TAG_LENGTH];
1634  uint16_t nodeId = node.getNodeId ();
1635 
1636  uint8_t iv_idx = 1;
1637  uint8_t nodeId_idx = iv_idx + IV_LENGTH;
1638  uint8_t nodeName_idx = nodeId_idx + sizeof (int16_t);
1639  uint8_t tag_idx = nodeName_idx + nameLength;
1640 
1641  size_t packet_length = 1 + IV_LENGTH + sizeof (int16_t) + nameLength;
1642 
1643 
1644  buf[0] = (uint8_t)NODE_NAME_SET;
1645 
1646  CryptModule::random (buf + iv_idx, IV_LENGTH);
1647 
1648  DEBUG_VERBOSE ("IV: %s", printHexBuffer (buf + iv_idx, IV_LENGTH));
1649 
1650  memcpy (buf + nodeId_idx, &nodeId, sizeof (uint16_t));
1651 
1652  memcpy (buf + nodeName_idx, name, nameLength);
1653 
1654  DEBUG_VERBOSE ("Set node name message: %s", printHexBuffer (buf, packet_length));
1655 
1656  uint8_t* crypt_buf = buf + nodeId_idx;
1657 
1658  size_t cryptLen = packet_length - 1 - IV_LENGTH;
1659 
1660  uint8_t addDataLen = 1 + IV_LENGTH;
1661  uint8_t aad[AAD_LENGTH + addDataLen];
1662 
1663  memcpy (aad, buf, addDataLen); // Copy message upto iv
1664 
1665  // Copy 8 last bytes from Node Key
1666  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
1667 
1668  if (!CryptModule::encryptBuffer (crypt_buf, cryptLen, // Encrypt from length
1669  buf + iv_idx, IV_LENGTH,
1670  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of node key
1671  aad, sizeof (aad), buf + tag_idx, TAG_LENGTH)) {
1672  DEBUG_ERROR ("Error during encryption");
1673  return false;
1674  }
1675 
1676  DEBUG_VERBOSE ("Encrypted set node name message: %s", printHexBuffer (buf, packet_length + TAG_LENGTH));
1677 
1678 #if DEBUG_LEVEL >= VERBOSE
1679  char macStr[ENIGMAIOT_ADDR_LEN * 3];
1680  DEBUG_DBG ("Destination address: %s", mac2str (rtcmem_data.gateway, macStr));
1681 #endif
1682 
1683  flashBlue = true;
1684 
1685  DEBUG_INFO ("-------> NODE NAME SEND");
1686 
1687  return (comm->send (rtcmem_data.gateway, buf, packet_length + TAG_LENGTH) == 0);
1688 
1689 }
1690 
1691 bool EnigmaIOTNodeClass::processSetIdentifyCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1692  uint8_t buffer[MAX_MESSAGE_LENGTH];
1693  uint8_t bufLength;
1694 
1695  DEBUG_DBG ("Set Identify command received");
1696  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
1697 
1698  DEBUG_WARN ("IDENTIFY");
1699  startIdentifying (1000);
1700 
1701  return true;
1702 }
1703 
1704 bool EnigmaIOTNodeClass::processGetRSSICommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1705  requestSearchGateway = true;
1706  requestReportRSSI = true;
1707 
1708  return true;
1709 }
1710 
1711 bool EnigmaIOTNodeClass::processSetResetConfigCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1712  uint8_t buffer[MAX_MESSAGE_LENGTH];
1713  uint8_t bufLength;
1714 
1715  DEBUG_DBG ("Reset Config command received");
1716  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
1717 
1718  buffer[0] = control_message_type::RESET_ANS;
1719  bufLength = 1;
1720 
1721  configCleared = true; // Disable any possible saving to flash or RTC memory
1722 
1723  bool result;
1724 
1725  if ((result = sendData (buffer, bufLength, true))) {
1726  DEBUG_DBG ("Reset Config about to be executed", sleepTime);
1727  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
1728  } else {
1729  DEBUG_WARN ("Error sending Reset Config response");
1730  }
1731 
1732  clearRTC ();
1733  clearFlash ();
1734 
1735  ESP.restart ();
1736 
1737  return result;
1738 }
1739 
1741  uint8_t data[sizeof (rtcmem_data)];
1742 
1743  memset (data, 0, sizeof (rtcmem_data));
1744 
1745 #ifdef ESP8266
1746  ESP.rtcUserMemoryWrite (RTC_ADDRESS, (uint32_t*)data, sizeof (rtcmem_data));
1747 #elif defined ESP32
1748  memset (&rtcmem_data_storage, 0, sizeof (rtcmem_data));
1749 #endif
1750 
1751  DEBUG_DBG ("RTC Cleared");
1752 }
1753 
1754 bool EnigmaIOTNodeClass::processSetSleepTimeCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1755  uint8_t buffer[MAX_MESSAGE_LENGTH];
1756  uint8_t bufLength;
1757 
1758  DEBUG_DBG ("Set Sleep command received");
1759  DEBUG_VERBOSE ("%s", printHexBuffer (data, len));
1760  if (!SPIFFS.begin ()) {
1761  DEBUG_ERROR ("Error mounting flash");
1762  }
1763  bool result = loadFlashData ();
1764  if (!result) {
1765  DEBUG_WARN ("Error loading configuration");
1766  }
1767 
1768  buffer[0] = control_message_type::SLEEP_ANS;
1769 
1770  uint32_t sleepTime;
1771  memcpy (&sleepTime, data + 1, sizeof (uint32_t));
1772  DEBUG_DBG ("Sleep time requested: %d", sleepTime);
1774  sleepTime = getSleepTime ();
1775  if (sleepTime > 0) {
1776  if (result) {
1777  if (result = saveFlashData ()) {
1778  DEBUG_DBG ("Saved config data after set sleep time command");
1779  } else {
1780  DEBUG_WARN ("Error saving data after set sleep time command");
1781  }
1782  }
1783  SPIFFS.end ();
1784  }
1785  memcpy (buffer + 1, &sleepTime, sizeof (sleepTime));
1786  bufLength = 5;
1787 
1788  if (sendData (buffer, bufLength, true)) {
1789  DEBUG_DBG ("Sleep time is %d seconds", sleepTime);
1790  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
1791  return result;
1792  } else {
1793  DEBUG_WARN ("Error sending version response");
1794  return false;
1795  }
1796 }
1797 
1798 
1799 bool EnigmaIOTNodeClass::processVersionCommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1800  uint8_t buffer[MAX_MESSAGE_LENGTH];
1801  uint8_t bufLength;
1802 
1804  memcpy (buffer + 1, (uint8_t*)ENIGMAIOT_PROT_VERS, strlen (ENIGMAIOT_PROT_VERS));
1805  bufLength = strlen (ENIGMAIOT_PROT_VERS) + 1;
1806  DEBUG_DBG ("Version command received");
1807  if (sendData (buffer, bufLength, true)) {
1808  DEBUG_DBG ("Version is %s", ENIGMAIOT_PROT_VERS);
1809  DEBUG_VERBOSE ("Data: %s", printHexBuffer (buffer, bufLength));
1810  return true;
1811  } else {
1812  DEBUG_WARN ("Error sending version response");
1813  return false;
1814  }
1815 }
1816 
1817 bool EnigmaIOTNodeClass::processOTACommand (const uint8_t* mac, const uint8_t* data, uint8_t len) {
1818  const uint8_t MAX_OTA_RESPONSE_LENGTH = 4;
1819 
1820  uint8_t responseBuffer[MAX_OTA_RESPONSE_LENGTH];
1821 
1822  //DEBUG_VERBOSE ("Data: %s", printHexBuffer (data, len));
1823  uint16_t msgIdx;
1824  static char md5buffer[33];
1825  char md5calc[32];
1826  static uint16_t numMsgs;
1827  static uint32_t otaSize;
1828  static uint16_t oldIdx;
1829  static bool otaRecoverRequested = false;
1830  static MD5Builder _md5;
1831  uint8_t* dataPtr = (uint8_t*)(data + 1);
1832  uint8_t dataLen = len - 1;
1833 
1834  if (dataLen < 2) {
1835  DEBUG_ERROR ("OTA message is too short: %u bytes", dataLen + 1);
1836  return false;
1837  }
1838 
1839  memcpy (&msgIdx, dataPtr, sizeof (uint16_t));
1840  dataPtr += sizeof (uint16_t);
1841  dataLen -= sizeof (uint16_t);
1842  DEBUG_WARN ("OTA message #%u", msgIdx);
1843  if (msgIdx > 0 && otaRunning) {
1844  if (msgIdx != (oldIdx + 1)) {
1845  if (!otaRecoverRequested) {
1846  otaRecoverRequested = true;
1847  responseBuffer[0] = control_message_type::OTA_ANS;
1848  responseBuffer[1] = ota_status::OTA_OUT_OF_SEQUENCE;
1849  memcpy (responseBuffer + 2, (uint8_t*)&oldIdx, sizeof (oldIdx));
1850  sendData (responseBuffer, 4, true);
1851  DEBUG_ERROR ("%u OTA messages missing before %u", msgIdx - oldIdx - 1, msgIdx);
1852  //otaRunning = false;
1853  //otaError = true;
1854  }
1855  return true;
1856  } else {
1857  oldIdx = msgIdx;
1858  otaRecoverRequested = false;
1859  }
1860  }
1861  lastOTAmsg = millis ();
1862 
1863  if (msgIdx == 0) {
1864  if (dataLen < 38) {
1865  DEBUG_ERROR ("OTA message #0 is too short: %u bytes", dataLen + 3);
1866  return false;
1867  }
1868  memcpy (&otaSize, dataPtr, sizeof (uint32_t));
1869  DEBUG_INFO ("OTA size: %u bytes", otaSize);
1870  dataPtr += sizeof (uint32_t);
1871  dataLen -= sizeof (uint32_t);
1872  memcpy (&numMsgs, dataPtr, sizeof (uint16_t));
1873  DEBUG_INFO ("Number of OTA messages: %u", numMsgs);
1874  dataPtr += sizeof (uint16_t);
1875  dataLen -= sizeof (uint16_t);
1876  memcpy (md5buffer, dataPtr, 32);
1877  md5buffer[32] = '\0';
1878  DEBUG_VERBOSE ("MD5: %s", printHexBuffer ((uint8_t*)md5buffer, 32));
1879  otaRunning = true;
1880  otaError = false;
1881  _md5.begin ();
1882  responseBuffer[0] = control_message_type::OTA_ANS;
1883  responseBuffer[1] = ota_status::OTA_STARTED;
1884  if (sendData (responseBuffer, 2, true)) {
1885  DEBUG_WARN ("OTA STARTED");
1886  restart (false); // Force unregistration after boot so that sleepy status is synchronized
1887  // on Gateway
1888  if (!Update.begin (otaSize)) {
1889  DEBUG_ERROR ("Error begginning OTA. OTA size: %u", otaSize);
1890  return false;
1891  }
1892 #ifdef ESP8266
1893  Update.runAsync (true);
1894 #endif
1895  if (!Update.setMD5 (md5buffer)) {
1896  DEBUG_ERROR ("Error setting MD5");
1897  return false;
1898  }
1899  }
1900  } else {
1901  if (otaRunning) {
1902  static size_t totalBytes = 0;
1903 
1904  _md5.add (dataPtr, dataLen);
1905  // Process OTA Update
1906  size_t numBytes = Update.write (dataPtr, dataLen);
1907  totalBytes += dataLen;
1908  DEBUG_WARN ("%u bytes written. Total %u", numBytes, totalBytes);
1909  } else {
1910  if (!otaError) {
1911  otaError = true;
1912  responseBuffer[0] = control_message_type::OTA_ANS;
1913  responseBuffer[1] = ota_status::OTA_START_ERROR;
1914  sendData (responseBuffer, 2, true);
1915  DEBUG_ERROR ("OTA error. Message 0 not received");
1916  }
1917  }
1918  }
1919 
1920  if (msgIdx == numMsgs && otaRunning) {
1921  StreamString otaErrorStr;
1922 
1923  DEBUG_INFO ("OTA end");
1924  _md5.calculate ();
1925  DEBUG_DBG ("OTA MD5 %s", _md5.toString ().c_str ());
1926  _md5.getChars (md5calc);
1927  if (!memcmp (md5calc, md5buffer, 32)) {
1928  responseBuffer[0] = control_message_type::OTA_ANS;
1929  responseBuffer[1] = ota_status::OTA_CHECK_OK;
1930  sendData (responseBuffer, 2, true);
1931  DEBUG_WARN ("OTA MD5 check OK");
1932  } else {
1933  responseBuffer[0] = control_message_type::OTA_ANS;
1934  responseBuffer[1] = ota_status::OTA_CHECK_FAIL;
1935  sendData (responseBuffer, 2, true);
1936  DEBUG_ERROR ("OTA MD5 check failed");
1937  }
1938  Serial.print ('.');
1939  while (!Update.isFinished ()) {
1940  Serial.print ('.');
1941  delay (100);
1942  }
1943  Serial.println ();
1944 
1945  if (Update.end ()) {
1946  responseBuffer[0] = control_message_type::OTA_ANS;
1947  responseBuffer[1] = ota_status::OTA_FINISHED;
1948  sendData (responseBuffer, 2, true);
1949  uint8_t otaErrorCode = Update.getError ();
1950  DEBUG_WARN ("OTA Finished OK");
1951  DEBUG_WARN ("OTA eror code: %d", otaErrorCode);
1952  //ESP.restart ();
1953  otaRunning = false;
1954  shouldRestart = true;
1955  clearRTC ();
1956  return true; // Restart does not happen inmediatelly, so code goes on
1957  } else {
1958  responseBuffer[0] = control_message_type::OTA_ANS;
1959  responseBuffer[1] = ota_status::OTA_CHECK_FAIL;
1960  sendData (responseBuffer, 2, true);
1961  uint8_t otaErrorCode = Update.getError ();
1962  Update.printError (otaErrorStr);
1963  otaErrorStr.trim (); // remove line ending
1964  DEBUG_ERROR ("OTA Failed");
1965  DEBUG_WARN ("OTA eror code: %s", otaErrorStr.c_str ());
1966  Serial.println ("OTA failed");
1967  return false;
1968  }
1969  delay (500);
1970  restart ();
1971  }
1972 
1973  return true;
1974 }
1975 
1976 void EnigmaIOTNodeClass::restart (bool reboot) {
1978  rtcmem_data.nodeKeyValid = false; // Force resync
1979  if (!saveRTCData ()) {
1980  DEBUG_ERROR ("Error saving data on RTC");
1981  }
1982  DEBUG_WARN ("Reset configuration data in RTC memory");
1983  if (reboot)
1984  ESP.restart (); // Reboot to recover normal status
1985 }
1986 
1987 bool EnigmaIOTNodeClass::processControlCommand (const uint8_t* mac, const uint8_t* data, size_t len) {
1988 
1989  DEBUG_VERBOSE ("Data: %s", printHexBuffer (data, len));
1990  switch (data[0]) {
1992  return processVersionCommand (mac, data, len);
1994  return processGetSleepTimeCommand (mac, data, len);
1996  return processSetSleepTimeCommand (mac, data, len);
1998  return processSetIdentifyCommand (mac, data, len);
2000  return processSetResetConfigCommand (mac, data, len);
2002  return processGetRSSICommand (mac, data, len);
2004  return processGetNameCommand (mac, data, len);
2006  return processSetNameCommand (mac, data, len);
2008  if (processOTACommand (mac, data, len)) {
2009  return true;
2010  } else {
2011  DEBUG_ERROR ("Error processing OTA");
2012  restart ();
2013  }
2014  }
2015  return false;
2016 }
2017 
2018 bool EnigmaIOTNodeClass::processDownstreamData (const uint8_t* mac, const uint8_t* buf, size_t count, bool control) {
2019  /*
2020  * --------------------------------------------------------------------------
2021  *| msgType (1) | IV (12) | length (2) | NodeId (2) | Data (....) | Tag (16) |
2022  * --------------------------------------------------------------------------
2023  */
2024 
2025  uint8_t iv_idx = 1;
2026  uint8_t length_idx = iv_idx + IV_LENGTH;
2027  uint8_t nodeId_idx = length_idx + sizeof (int16_t);
2028  uint8_t encoding_idx;
2029  uint8_t data_idx;
2030  if (!control) {
2031  encoding_idx = nodeId_idx + sizeof (int16_t);
2032  data_idx = encoding_idx + sizeof (int8_t);
2033  } else {
2034  data_idx = nodeId_idx + sizeof (int16_t);
2035  }
2036  uint8_t tag_idx = count - TAG_LENGTH;
2037 
2038  uint8_t addDataLen = 1 + IV_LENGTH;
2039  uint8_t aad[AAD_LENGTH + addDataLen];
2040 
2041  memcpy (aad, buf, addDataLen); // Copy message upto iv
2042 
2043  // Copy 8 last bytes from Node Key
2044  memcpy (aad + addDataLen, node.getEncriptionKey () + KEY_LENGTH - AAD_LENGTH, AAD_LENGTH);
2045 
2046  uint8_t packetLen = count - TAG_LENGTH;
2047 
2048  if (!CryptModule::decryptBuffer (buf + length_idx, packetLen - 1 - IV_LENGTH, // Decrypt from nodeId
2049  buf + iv_idx, IV_LENGTH,
2050  node.getEncriptionKey (), KEY_LENGTH - AAD_LENGTH, // Use first 24 bytes of network key
2051  aad, sizeof (aad), buf + tag_idx, TAG_LENGTH)) {
2052  DEBUG_ERROR ("Error during decryption");
2053  return false;
2054  }
2055 
2056  DEBUG_VERBOSE ("Decripted downstream message: %s", printHexBuffer (buf, count - TAG_LENGTH));
2057 
2058  if (control) {
2059  DEBUG_INFO ("Control command");
2060  DEBUG_VERBOSE ("Data: %s", printHexBuffer (&buf[data_idx], tag_idx - data_idx));
2061  return processControlCommand (mac, &buf[data_idx], tag_idx - data_idx);
2062  }
2063 
2064  DEBUG_VERBOSE ("Sending data notification. Payload length: %d", tag_idx - data_idx);
2065  if (notifyData) {
2066  notifyData (mac, &buf[data_idx], tag_idx - data_idx, (nodeMessageType_t)(buf[0]), (nodePayloadEncoding_t)(buf[encoding_idx]));
2067  }
2068 
2069  return true;
2070 
2071 }
2072 
2073 
2074 nodeInvalidateReason_t EnigmaIOTNodeClass::processInvalidateKey (const uint8_t* mac, const uint8_t* buf, size_t count) {
2075 #define IKMSG_LEN 2
2076  if (buf && count < IKMSG_LEN) {
2077  return UNKNOWN_ERROR;
2078  }
2079 
2080  DEBUG_WARN ("Invalidate key request. Reason: %u", buf[1]);
2081  uint8_t reason = buf[1];
2082  if (reason < KEY_EXPIRED) {
2083  if (dataMessageSentLength > 0)
2084  dataMessageSendPending = true; // Start last data retransmission
2085  }
2086 
2087  return (nodeInvalidateReason_t)reason;
2088 }
2089 
2090 void EnigmaIOTNodeClass::manageMessage (const uint8_t* mac, const uint8_t* buf, uint8_t count) {
2091  DEBUG_INFO ("Reveived message. Origin MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
2092  DEBUG_VERBOSE ("Received data: %s", printHexBuffer (const_cast<uint8_t*>(buf), count));
2093  flashBlue = true;
2094 
2095  if (count <= 1) {
2096  DEBUG_ERROR ("Empty message received");
2097  return;
2098  }
2099 
2100  // All downlink messages should come from gateway
2101  if (memcmp (mac, rtcmem_data.gateway, comm->getAddressLength ()) != 0) {
2102  DEBUG_ERROR ("Message comes not from gateway");
2103  return;
2104  }
2105 
2106  switch (buf[0]) {
2107  case SERVER_HELLO:
2108  DEBUG_INFO (" <------- SERVER HELLO");
2109  if (node.getStatus () == WAIT_FOR_SERVER_HELLO) {
2110  if (processServerHello (mac, buf, count)) {
2111  // mark node as registered
2112  //stopFlash (); // Do not flash during setup for less battery drain
2113  node.setKeyValid (true);
2114  rtcmem_data.nodeKeyValid = true;
2115  node.setKeyValidFrom (millis ());
2119 
2120  // save context to RTC memory
2124 
2125  if (!saveRTCData ()) {
2126  DEBUG_ERROR ("Error saving data on RTC");
2127  }
2128 
2129  // request clock sync if non sleepy
2130  //if (!node.getSleepy () && node.isRegistered ())
2131  // clockRequest ();
2132 
2133 #if DEBUG_LEVEL >= INFO
2135 #endif
2137  DEBUG_WARN ("Error sending set node name %s", rtcmem_data.nodeName ? rtcmem_data.nodeName : "NULL name");
2138  }
2139 
2140  // send notification to user code
2141  if (notifyConnection) {
2142  notifyConnection ();
2143  }
2144  // Resend last message in case of it is still pending to be sent.
2145  // If key expired it was successfully sent before so retransmission is not needed
2146  if (invalidateReason < KEY_EXPIRED && dataMessageSentLength > 0) {
2147  if (node.getStatus () == REGISTERED && node.isKeyValid ()) {
2149  DEBUG_INFO ("Data pending to be sent. Length: %u", dataMessageSentLength);
2150  DEBUG_VERBOSE ("Data sent: %s", printHexBuffer (dataMessageSent, dataMessageSentLength));
2152  //dataMessageSentLength = 0;
2153  dataMessageSendPending = false;
2154 
2155  flashBlue = true;
2156  }
2157  }
2158  }
2159 
2160 
2161  } else {
2162  node.reset ();
2163  }
2164  } else {
2165  node.reset ();
2166  }
2167  break;
2168  case INVALIDATE_KEY:
2169  DEBUG_INFO (" <------- INVALIDATE KEY");
2170  invalidateReason = processInvalidateKey (mac, buf, count);
2171  requestSearchGateway = true;
2172  node.reset ();
2173  TimeManager.reset ();
2175  if (notifyDisconnection) {
2177  }
2178  break;
2179  case DOWNSTREAM_DATA_SET:
2180  DEBUG_INFO (" <------- DOWNSTREAM DATA SET");
2181  if (processDownstreamData (mac, buf, count)) {
2182  DEBUG_INFO ("Downstream Data set OK");
2183  }
2184  break;
2185  case DOWNSTREAM_DATA_GET:
2186  DEBUG_INFO (" <------- DOWNSTREAM DATA GET");
2187  if (processDownstreamData (mac, buf, count)) {
2188  DEBUG_INFO ("Downstream Data set OK");
2189  }
2190  break;
2191  case DOWNSTREAM_CTRL_DATA:
2192  DEBUG_INFO (" <------- DOWNSTREAM CONTROL DATA");
2193  if (processDownstreamData (mac, buf, count, true)) {
2194  DEBUG_INFO ("Downstream Data OK");
2195  }
2196  break;
2197  case CLOCK_RESPONSE:
2198  DEBUG_INFO (" <------- CLOCK RESPONSE");
2199  if (clockSyncEnabled) {
2200  if (processClockResponse (mac, buf, count)) {
2201  DEBUG_INFO ("Clock Response OK");
2202  }
2203  }
2204  break;
2205  case NODE_NAME_RESULT:
2206  DEBUG_INFO (" <------- SET NODE NAME RESULT");
2207  if (processSetNameResponse (mac, buf, count)) {
2208  DEBUG_INFO ("Set Node Name OK");
2209  }
2210  }
2211 }
2212 
2213 
2214 void EnigmaIOTNodeClass::getStatus (uint8_t* mac_addr, uint8_t status) {
2215  gatewaySearchStarted = false;
2216  if (status == 0) {
2217  DEBUG_DBG ("SENDStatus OK");
2218  rtcmem_data.commErrors = 0;
2219  } else {
2221  if (!saveRTCData ()) {
2222  DEBUG_ERROR ("Error saving data on RTC");
2223  }
2224  DEBUG_ERROR ("SENDStatus ERROR %d. Comm errors %u", status, rtcmem_data.commErrors);
2225  }
2226 }
2227 
2228 
2230 
2231 //#endif
OTA_CHECK_OK
@ OTA_CHECK_OK
Definition: NodeList.h:66
Comms_halClass::onDataRcvd
virtual void onDataRcvd(comms_hal_rcvd_data dataRcvd)=0
Attach a callback function to be run on every received message.
EnigmaIOTNodeClass::otaRunning
bool otaRunning
True if OTA update has started.
Definition: EnigmaIOTNode.h:136
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:42
EnigmaIOTNodeClass::notifyWiFiManagerExit
onWiFiManagerExit_t notifyWiFiManagerExit
Function called when configuration portal exits.
Definition: EnigmaIOTNode.h:150
EnigmaIOTNodeClass::otaError
bool otaError
True if OTA update has failed. This normally produces a restart.
Definition: EnigmaIOTNode.h:137
CryptModule::getPubDHKey
uint8_t * getPubDHKey()
Gets own public key used on Diffie Hellman algorithm.
Definition: cryptModule.h:133
EnigmaIOTNodeClass::notifyData
onNodeDataRx_t notifyData
Callback that will be called on every message reception.
Definition: EnigmaIOTNode.h:123
VERSION_ANS
@ VERSION_ANS
Definition: NodeList.h:43
IDENTIFY
@ IDENTIFY
Definition: NodeList.h:47
EnigmaIOTNodeClass::unixtime
time_t unixtime()
Gets current time in seconds from 1970, if time is synchronized.
Definition: EnigmaIOTNode.cpp:1181
Node::setLastMessageTime
void setLastMessageTime()
Sets current moment as last node message time.
Definition: NodeList.h:194
ENIGMAIOT_PROT_VERS
static const char ENIGMAIOT_PROT_VERS[]
EnitmaIoT Version.
Definition: EnigmaIoTconfig.h:15
CryptModule::getDH1
void getDH1()
Starts first stage of Diffie Hellman key agreement algorithm.
Definition: cryptModule.cpp:141
SLEEP_SET
@ SLEEP_SET
Definition: NodeList.h:45
rtcmem_data_t::nodeKey
uint8_t nodeKey[KEY_LENGTH]
Definition: EnigmaIOTNode.h:78
rtcmem_data_t::nodeId
uint16_t nodeId
Definition: EnigmaIOTNode.h:79
EnigmaIOTNodeClass::hasClockSync
bool hasClockSync()
Checks if internal clock is synchronized to gateway.
Definition: EnigmaIOTNode.cpp:1189
rtcmem_data_t::commErrors
uint8_t commErrors
Definition: EnigmaIOTNode.h:88
EnigmaIOTNodeClass::sendData
bool sendData(const uint8_t *data, size_t len, bool controlMessage, bool encrypt=true, nodePayloadEncoding_t payloadEncoding=CAYENNELPP)
Initiades data transmission distinguissing if it is payload or control data.
Definition: EnigmaIOTNode.cpp:1260
rtcmem_data_t::networkKey
uint8_t networkKey[KEY_LENGTH]
Definition: EnigmaIOTNode.h:83
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.
NODE_NAME_SET
@ NODE_NAME_SET
Definition: EnigmaIOTGateway.h:43
Node::setNodeName
void setNodeName(const char *name)
Sets Node name.
Definition: NodeList.h:148
rtcmem_data_t::gateway
uint8_t gateway[ENIGMAIOT_ADDR_LEN]
Definition: EnigmaIOTNode.h:81
timeManager.h
Clock synchronisation calculations.
CRMSG_LEN
#define CRMSG_LEN
IDENTIFY_TIMEOUT
static const time_t IDENTIFY_TIMEOUT
How long LED will be flashing during identification.
Definition: EnigmaIoTconfig.h:44
EnigmaIOTNodeClass::clientHello
bool clientHello()
Build a ClientHello messange and send it to gateway.
Definition: EnigmaIOTNode.cpp:968
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:260
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:664
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:31
Node::isKeyValid
bool isKeyValid()
Gets shared key validity for this node.
Definition: NodeList.h:228
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:72
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:120
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:298
TimeManager
TimeManagerClass TimeManager
Definition: timeManager.cpp:51
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:958
Node::setNodeId
void setNodeId(uint16_t nodeId)
Sets a new Node identifier.
Definition: NodeList.h:128
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
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:94
nodeConnectionLedFlashing
bool nodeConnectionLedFlashing
Definition: EnigmaIOTNode.cpp:38
TimeManagerClass::isTimeAdjusted
bool isTimeAdjusted()
Gets synchronization status.
Definition: timeManager.h:66
rtcmem_data_t::rssi
int8_t rssi
Definition: EnigmaIOTNode.h:82
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:950
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:1817
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:1754
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:54
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:1495
TimeManagerClass::unixtime
time_t unixtime()
Gets local clock in seconds. It returns millis() / 1000 if not synchronized, local clock otherwise....
Definition: timeManager.h:39
rtcmem_data_t::crc32
uint32_t crc32
Definition: EnigmaIOTNode.h:77
ENIGMAIOT_ADDR_LEN
static const size_t ENIGMAIOT_ADDR_LEN
Address size. Mac address = 6 bytes.
Definition: EnigmaIoTconfig.h:14
EnigmaIOTNodeClass::clearRTC
void clearRTC()
Clears configuration stored in RTC memory to recover factory state.
Definition: EnigmaIOTNode.cpp:1740
EnigmaIOTNodeClass::handle
void handle()
This method should be called periodically for instance inside loop() function. It is used for interna...
Definition: EnigmaIOTNode.cpp:801
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:30
OTA_TIMEOUT_TIME
static const uint32_t OTA_TIMEOUT_TIME
Timeout between OTA messages. In milliseconds.
Definition: EnigmaIoTconfig.h:43
LED_ON
#define LED_ON
Definition: enigmaiot_led_flasher.ino:39
NODE_NAME_LENGTH
static const uint8_t NODE_NAME_LENGTH
Maximum number of characters of node name.
Definition: EnigmaIoTconfig.h:19
OTA
@ OTA
Definition: NodeList.h:55
EnigmaIOTNodeClass::checkResetButton
void checkResetButton()
Checks reset button status during startup.
Definition: EnigmaIOTNode.cpp:488
SHMSG_LEN
#define SHMSG_LEN
startFlash
void startFlash(time_t period)
Definition: EnigmaIOTNode.cpp:441
Node::t4
int64_t t4
Timestaps to calculate clock offset.
Definition: NodeList.h:333
RESET
@ RESET
Definition: NodeList.h:48
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:315
DOWNSTREAM_DATA_GET
@ DOWNSTREAM_DATA_GET
Definition: EnigmaIOTGateway.h:38
EnigmaIOTNodeClass::resetPin
int resetPin
Pin used to reset configuration if it is connected to ground during startup.
Definition: EnigmaIOTNode.h:148
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:17
Node::setKeyValid
void setKeyValid(bool status)
Sets shared key validity for this node.
Definition: NodeList.h:236
OTA_TIMEOUT
@ OTA_TIMEOUT
Definition: NodeList.h:69
DOWNSTREAM_DATA_SET
@ DOWNSTREAM_DATA_SET
Definition: EnigmaIOTGateway.h:37
IV_LENGTH
const uint8_t IV_LENGTH
Initalization vector length used by selected crypto algorythm.
Definition: EnigmaIoTconfig.h:59
EnigmaIOTNodeClass::requestReportRSSI
bool requestReportRSSI
Flag to control RSSI reporting.
Definition: EnigmaIOTNode.h:146
TIME_SYNC_PERIOD
static const uint32_t TIME_SYNC_PERIOD
Period of clock synchronization request.
Definition: EnigmaIoTconfig.h:45
RSSI_GET
@ RSSI_GET
Definition: NodeList.h:50
EnigmaIOTNodeClass::setSleepTime
void setSleepTime(uint32_t sleepTime)
Allows to configure a new sleep time period from user code.
Definition: EnigmaIOTNode.cpp:746
EnigmaIOTNodeClass::indentifying
boolean indentifying
True if node has its led flashing to be identified.
Definition: EnigmaIOTNode.h:139
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:1529
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:119
Node::getStatus
status_t getStatus()
Gets status for finite state machine that represents node.
Definition: NodeList.h:252
OTA_START_ERROR
@ OTA_START_ERROR
Definition: NodeList.h:65
OTA_FINISHED
@ OTA_FINISHED
Definition: NodeList.h:70
rtcmem_data_t::sleepTime
uint32_t sleepTime
Definition: EnigmaIOTNode.h:86
EnigmaIOTNodeClass::getSleepTime
uint32_t getSleepTime()
Returns sleep period in seconds.
Definition: EnigmaIOTNode.cpp:55
Node::getNodeId
uint16_t getNodeId()
Gets Node identifier.
Definition: NodeList.h:120
DEBUG_ESP_PORT
#define DEBUG_ESP_PORT
Stream to output debug info. It will normally be Serial
Definition: EnigmaIoTconfig.h:65
Node::getLastMessageTime
time_t getLastMessageTime()
Gets last time that node sent a message.
Definition: NodeList.h:187
Node::setKeyValidFrom
void setKeyValidFrom(time_t keyValidFrom)
Sets time when key was agreed with gateway.
Definition: NodeList.h:179
INIT
@ INIT
Definition: NodeList.h:25
EnigmaIOTNodeClass::comm
Comms_halClass * comm
Comms abstraction layer.
Definition: EnigmaIOTNode.h:122
DOWNSTREAM_CTRL_DATA
@ DOWNSTREAM_CTRL_DATA
Definition: EnigmaIOTGateway.h:40
RSSI_ANS
@ RSSI_ANS
Definition: NodeList.h:51
Node::setMacAddress
void setMacAddress(uint8_t *macAddress)
Sets node address.
Definition: NodeList.h:218
EnigmaIOTNodeClass::dataMessageSent
uint8_t dataMessageSent[MAX_MESSAGE_LENGTH]
Buffer where sent message is stored in case of retransmission is needed.
Definition: EnigmaIOTNode.h:130
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:2229
TimeManagerClass::getDelay
int64_t getDelay()
Gets propagation + processing delay between Node and Gateway in milliseconds.
Definition: timeManager.h:74
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:1691
EnigmaIOTNodeClass::timeSyncPeriod
clock_t timeSyncPeriod
Clock synchronization period.
Definition: EnigmaIOTNode.h:141
EnigmaIOTNodeClass::clockRequest
bool clockRequest()
Build a ClockRequest messange and send it to gateway.
Definition: EnigmaIOTNode.cpp:1057
SLEEP_GET
@ SLEEP_GET
Definition: NodeList.h:44
CONTROL_DATA
@ CONTROL_DATA
Definition: EnigmaIOTGateway.h:39
stopFlash
void stopFlash()
Definition: EnigmaIOTNode.cpp:461
EnigmaIOTNodeClass::sleep
void sleep()
Requests transition to sleep mode (low energy state)
Definition: EnigmaIOTNode.cpp:1287
NAME_OK
@ NAME_OK
Definition: NodeList.h:33
Node::t3
int64_t t3
Definition: NodeList.h:333
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:1711
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:286
Node::t2
int64_t t2
Definition: NodeList.h:333
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:954
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: EnigmaIoTconfig.h:47
SENSOR_DATA
@ SENSOR_DATA
Definition: EnigmaIOTGateway.h:35
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:1196
dumpRtcData
void dumpRtcData(rtcmem_data_t *data, uint8_t *gateway=NULL)
Definition: EnigmaIOTNode.cpp:88
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:80
rtcmem_data_t::lastMessageCounter
uint16_t lastMessageCounter
Definition: EnigmaIOTNode.h:92
EnigmaIOTNodeClass::clearFlash
void clearFlash()
Clears configuration stored in flash to recover factory state.
Definition: EnigmaIOTNode.cpp:309
WAIT_FOR_SERVER_HELLO
@ WAIT_FOR_SERVER_HELLO
Definition: NodeList.h:26
localLed
int localLed
Definition: EnigmaIOTNode.cpp:30
mac2str
char * mac2str(const uint8_t *mac, char *buffer)
Debug helper function that generates a string that represent a MAC address.
Definition: helperFunctions.cpp:84
EnigmaIOTNodeClass::configWiFiManager
bool configWiFiManager(rtcmem_data_t *data)
Starts configuration AP and web server and gets settings from it.
Definition: EnigmaIOTNode.cpp:321
Node::reset
void reset()
Resets all node fields to a default initial and not registered state.
Definition: NodeList.cpp:104
EnigmaIOTNodeClass::resetConfig
void resetConfig()
Deletes configuration file stored on SPIFFS. It makes neccessary to configure it again using WiFi Por...
Definition: EnigmaIOTNode.cpp:45
EnigmaIOTNodeClass::sleepTime
uint64_t sleepTime
Time in microseconds that this node will be slept between measurements.
Definition: EnigmaIOTNode.h:129
EnigmaIOTNodeClass::dataMessage
bool dataMessage(const uint8_t *data, size_t len, bool controlMessage=false, bool encrypt=true, nodePayloadEncoding_t payloadEncoding=CAYENNELPP)
Builds, encrypts and sends a Data message.
Definition: EnigmaIOTNode.cpp:1361
AAD_LENGTH
const uint8_t AAD_LENGTH
Number of bytes from last part of key that will be used for additional authenticated data.
Definition: EnigmaIoTconfig.h:61
EnigmaIOTNodeClass::stopIdentifying
void stopIdentifying()
Stops node identification.
Definition: EnigmaIOTNode.cpp:483
Node::getInitAsSleepy
bool getInitAsSleepy()
Gets initial sleepy mode.
Definition: NodeList.h:306
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.
EnigmaIOTNodeClass::dataMessageSendPending
bool dataMessageSendPending
True in case of message retransmission is needed.
Definition: EnigmaIOTNode.h:132
EnigmaIOTNodeClass::notifyConnection
onConnected_t notifyConnection
Callback that will be called anytime a new node is registered.
Definition: EnigmaIOTNode.h:124
Comms_halClass::getAddressLength
virtual uint8_t getAddressLength()=0
Get address length that a specific communication subsystem uses.
EnigmaIOTNodeClass::processControlCommand
bool processControlCommand(const uint8_t *mac, const uint8_t *data, size_t len)
Processes a control command. Does not propagate to user code.
Definition: EnigmaIOTNode.cpp:1987
EnigmaIOTNodeClass::unencryptedDataMessage
bool unencryptedDataMessage(const uint8_t *data, size_t len, bool controlMessage=false, nodePayloadEncoding_t payloadEncoding=CAYENNELPP)
Builds and sends a Data message without encryption. Not recommended, use it only if you absolutely ne...
Definition: EnigmaIOTNode.cpp:1297
nodePayloadEncoding_t
nodePayloadEncoding_t
Definition: EnigmaIOTNode.h:51
Node::getEncriptionKey
uint8_t * getEncriptionKey()
Gets Node encryption key.
Definition: NodeList.h:157
CryptModule::random
static uint32_t random()
Gets a random number.
Definition: cryptModule.cpp:119
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:49
EnigmaIOTNodeClass::useCounter
bool useCounter
true means that data message counter will be used to mark message order
Definition: EnigmaIOTNode.h:126
POST_REG_DELAY
static const uint32_t POST_REG_DELAY
Time to waif before sending data after registration so that other nodes have time to finish their reg...
Definition: EnigmaIoTconfig.h:50
Node::getLastMessageCounter
uint16_t getLastMessageCounter()
Gets counter for last received message from node.
Definition: NodeList.h:202
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:1577
EnigmaIOTNodeClass::ledOnTime
unsigned int ledOnTime
Time that LED is On during flash. Initalized on setLed
Definition: EnigmaIOTNode.h:121
EnigmaIOTNodeClass::node
Node node
Node abstraction to store context.
Definition: EnigmaIOTNode.h:118
EnigmaIOTNodeClass::sendNodeNameSet
bool sendNodeNameSet(const char *name)
Informs Gateway about custom node name.
Definition: EnigmaIOTNode.cpp:1614
OTA_OUT_OF_SEQUENCE
@ OTA_OUT_OF_SEQUENCE
Definition: NodeList.h:68
EnigmaIOTNodeClass::invalidateReason
nodeInvalidateReason_t invalidateReason
Last key invalidation reason.
Definition: EnigmaIOTNode.h:135
EnigmaIOTNodeClass::rtcmem_data
rtcmem_data_t rtcmem_data
Context data to be stored on persistent storage.
Definition: EnigmaIOTNode.h:127
NAME_ANS
@ NAME_ANS
Definition: NodeList.h:53
EnigmaIOTNodeClass::loadRTCData
bool loadRTCData()
Loads configuration from RTC data. Uses a CRC to check data integrity.
Definition: EnigmaIOTNode.cpp:113
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:87
EnigmaIOTNodeClass::clockSyncEnabled
bool clockSyncEnabled
If true clock is synchronized with Gateway.
Definition: EnigmaIOTNode.h:142
MAX_MESSAGE_LENGTH
static const uint8_t MAX_MESSAGE_LENGTH
Maximum payload size on ESP-NOW.
Definition: EnigmaIoTconfig.h:13
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:128
EnigmaIOTNodeClass::processVersionCommand
bool processVersionCommand(const uint8_t *mac, const uint8_t *buf, uint8_t len)
Processes a request firmware version.
Definition: EnigmaIOTNode.cpp:1799
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:2018
EnigmaIOTNodeClass::wifiManager
AsyncWiFiManager * wifiManager
Wifi configuration portal.
Definition: EnigmaIOTNode.h:149
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:1109
EnigmaIOTNode.h
Library to build a node for EnigmaIoT system.
CRSMSG_LEN
#define CRSMSG_LEN
EnigmaIOTNodeClass::dataMessageEncrypt
bool dataMessageEncrypt
Message encryption enabled. Stored for use in case of message retransmission is needed.
Definition: EnigmaIOTNode.h:134
EnigmaIOTNodeClass::notifyWiFiManagerStarted
onWiFiManagerStarted_t notifyWiFiManagerStarted
Function called when configuration portal is started.
Definition: EnigmaIOTNode.h:151
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: EnigmaIoTconfig.h:55
MACSTR
#define MACSTR
Definition: helperFunctions.cpp:82
EnigmaIOTNodeClass::lastOTAmsg
time_t lastOTAmsg
Time when last OTA update message has received. This is used to control timeout.
Definition: EnigmaIOTNode.h:138
RECONNECTION_PERIOD
static const int16_t RECONNECTION_PERIOD
Time to retry Gateway connection.
Definition: EnigmaIoTconfig.h:40
rtcmem_data_t::nodeRegisterStatus
status_t nodeRegisterStatus
Definition: EnigmaIOTNode.h:91
CONFIG_FILE
const char CONFIG_FILE[]
Definition: EnigmaIOTNode.cpp:28
TimeManagerClass::setOrigin
int64_t setOrigin()
Inits time synchronization getting local clock to be assigned to T1.
Definition: timeManager.cpp:12
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:510
UNREGISTERED
@ UNREGISTERED
Definition: NodeList.h:24
KEY_EXPIRED
@ KEY_EXPIRED
Definition: EnigmaIOTGateway.h:70
EnigmaIOTNodeClass::notifyDisconnection
onDisconnected_t notifyDisconnection
Callback that will be called anytime a node is disconnected.
Definition: EnigmaIOTNode.h:125
RESET_ANS
@ RESET_ANS
Definition: NodeList.h:49
Node::isRegistered
bool isRegistered()
Gets registration state of this node.
Definition: NodeList.h:244
LED_OFF
#define LED_OFF
Definition: enigmaiot_led_flasher.ino:40
TimeManagerClass::clock
int64_t clock()
Gets local clock. It returns millis() if not synchronized, local clock otherwise.
Definition: timeManager.cpp:20
Node::getMacAddress
uint8_t * getMacAddress()
Gets address from Node.
Definition: NodeList.h:112
EnigmaIOTNodeClass::identifyStart
time_t identifyStart
Time when identification started flashing. Used to control identification timeout.
Definition: EnigmaIOTNode.h:140
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:2074
VERSION
@ VERSION
Definition: NodeList.h:42
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:67
IKMSG_LEN
#define IKMSG_LEN
EnigmaIOTNodeClass::saveRTCData
bool saveRTCData()
Save configuration to RTC to store current status and recover it after deep sleep.
Definition: EnigmaIOTNode.cpp:286
EnigmaIOTNodeClass::loadFlashData
bool loadFlashData()
Loads configuration from flash memory.
Definition: EnigmaIOTNode.cpp:159
OTA_ANS
@ OTA_ANS
Definition: NodeList.h:56
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:31
NAME_GET
@ NAME_GET
Definition: NodeList.h:52
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:41
REGISTERED
@ REGISTERED
Definition: NodeList.h:28
SERVER_HELLO
@ SERVER_HELLO
Definition: EnigmaIOTGateway.h:46
EnigmaIOTNodeClass::reportRSSI
bool reportRSSI()
Sends RSSI value and channel to Gateway.
Definition: EnigmaIOTNode.cpp:780
EnigmaIOTNodeClass::shouldRestart
bool shouldRestart
Triggers a restart if true.
Definition: EnigmaIOTNode.h:143
EnigmaIOTNodeClass::getStatus
void getStatus(uint8_t *mac_addr, uint8_t status)
Functrion to debug send status.
Definition: EnigmaIOTNode.cpp:2214
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:41
EnigmaIOTNodeClass
Main node class. Manages communication with gateway and allows sending and receiving user data.
Definition: EnigmaIOTNode.h:116
CHECK_COMM_ERRORS
static const bool CHECK_COMM_ERRORS
Try to reconnect in case of communication errors.
Definition: EnigmaIoTconfig.h:52
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:1472
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:20
NODE_NAME_RESULT
@ NODE_NAME_RESULT
Definition: EnigmaIOTGateway.h:44
EnigmaIOTNodeClass::stop
void stop()
Stops EnigmaIoT protocol.
Definition: EnigmaIOTNode.cpp:736
EnigmaIOTNodeClass::processGetRSSICommand
bool processGetRSSICommand(const uint8_t *mac, const uint8_t *data, uint8_t len)
Processes a request to measure RSSI.
Definition: EnigmaIOTNode.cpp:1704
EnigmaIOTNodeClass::setNodeAddress
bool setNodeAddress(uint8_t address[ENIGMAIOT_ADDR_LEN])
Set node address to be used in EnigmaIOT communication.
Definition: EnigmaIOTNode.cpp:741
EnigmaIOTNodeClass::requestSearchGateway
bool requestSearchGateway
Flag to control updating gateway address, RSSI and channel.
Definition: EnigmaIOTNode.h:145
nodeInvalidateReason_t
nodeInvalidateReason_t
Key invalidation reason definition.
Definition: EnigmaIOTNode.h:65
EnigmaIOTNodeClass::saveFlashData
bool saveFlashData(bool fsOpen=false)
Saves configuration to flash memory.
Definition: EnigmaIOTNode.cpp:233
OTA_CHECK_FAIL
@ OTA_CHECK_FAIL
Definition: NodeList.h:67
rtcmem_data_t::sleepy
bool sleepy
Definition: EnigmaIOTNode.h:85
EnigmaIOTNodeClass::clock
int64_t clock()
Gets current clock counter. millis() + offset.
Definition: EnigmaIOTNode.cpp:1172
UNKNOWN_ERROR
@ UNKNOWN_ERROR
Definition: EnigmaIOTGateway.h:65
rtcmem_data_t::networkName
char networkName[NETWORK_NAME_LENGTH]
Definition: EnigmaIOTNode.h:84
CLIENT_HELLO
@ CLIENT_HELLO
Definition: EnigmaIOTGateway.h:45
EnigmaIOTNodeClass::dataMessageSendEncoding
nodePayloadEncoding_t dataMessageSendEncoding
Encoding of the message pending to be sent.
Definition: EnigmaIOTNode.h:133
DEFAULT_SLEEP_TIME
static const uint32_t DEFAULT_SLEEP_TIME
Default sleep time if it was not set.
Definition: EnigmaIoTconfig.h:42
Node::t1
int64_t t1
Definition: NodeList.h:333
EnigmaIOTNodeClass::manageMessage
void manageMessage(const uint8_t *mac, const uint8_t *buf, uint8_t count)
Process every received message.
Definition: EnigmaIOTNode.cpp:2090
rtcmem_data_t::nodeKeyValid
bool nodeKeyValid
Definition: EnigmaIOTNode.h:90
NAME_SET
@ NAME_SET
Definition: NodeList.h:54
calculateCRC32
uint32_t calculateCRC32(const uint8_t *data, size_t length)
Calculates CRC32 of a buffer.
Definition: helperFunctions.cpp:63
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: EnigmaIoTconfig.h:58
flashLed
void flashLed(void *led)
Definition: EnigmaIOTNode.cpp:431
TAG_LENGTH
const uint8_t TAG_LENGTH
Authentication tag length. For Poly1305 it is always 16.
Definition: EnigmaIoTconfig.h:60
Node::setLastMessageCounter
void setLastMessageCounter(uint16_t counter)
Sets counter for last received message from node.
Definition: NodeList.h:210
INVALIDATE_KEY
@ INVALIDATE_KEY
Definition: EnigmaIOTGateway.h:47
SLEEP_ANS
@ SLEEP_ANS
Definition: NodeList.h:46
EnigmaIOTNodeClass::gatewaySearchStarted
bool gatewaySearchStarted
Avoids start a new gateway scan if it already started.
Definition: EnigmaIOTNode.h:144
TimeManagerClass::reset
void reset()
Resets clock synchronization and sets values to initial status.
Definition: timeManager.h:81
EnigmaIOTNodeClass::configCleared
bool configCleared
This flag disables asy configuration save after triggering a factory reset.
Definition: EnigmaIOTNode.h:147
rtcmem_data_t
Context data to be stored con persistent storage to be used after wake from sleep mode.
Definition: EnigmaIOTNode.h:76
clearRtcData
void clearRtcData(rtcmem_data_t *data)
Definition: EnigmaIOTNode.cpp:76
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:63
EnigmaIOTNodeClass::startIdentifying
void startIdentifying(time_t period)
Starts node identification by flashing led.
Definition: EnigmaIOTNode.cpp:477
Comms_halClass
Interface for communication subsystem abstraction layer definition.
Definition: Comms_hal.h:33
EnigmaIOTNodeClass::restart
void restart(bool reboot=true)
Sets connection as unregistered to force a resyncrhonisation after boot.
Definition: EnigmaIOTNode.cpp:1976
OTA_STARTED
@ OTA_STARTED
Definition: NodeList.h:64
UNENCRYPTED_NODE_DATA
@ UNENCRYPTED_NODE_DATA
Definition: EnigmaIOTGateway.h:36
EnigmaIOTNodeClass::dataMessageSentLength
uint8_t dataMessageSentLength
Message length stored for use in case of message retransmission is needed.
Definition: EnigmaIOTNode.h:131
Comms_halClass::stop
virtual void stop()=0
Terminates communication and closes all connectrions.