EnigmaIOT  0.9.3
Secure sensor and gateway platform based on ESP8266 and ESP32
EnigmaIOTGatewayDummy.ino
Go to the documentation of this file.
1 
10 #include <Arduino.h>
11 
12 #include <GwOutput_generic.h>
13 #include "GwOutput_dummy.h"
14 
15 #ifdef ESP32
16 #include <WiFi.h>
17 #include <AsyncTCP.h> // Comment to compile for ESP8266
18 #include <SPIFFS.h>
19 #include "esp_system.h"
20 #include "esp_event.h"
21 #include "esp_tls.h"
22 #include "soc/soc.h" // Disable brownout problems
23 #include "soc/rtc_cntl_reg.h" // Disable brownout problems
24 #elif defined(ESP8266)
25 #include <ESP8266WiFi.h>
26 //#include <ESPAsyncTCP.h> // Comment to compile for ESP32
27 #include <Hash.h>
28 #include <SPI.h>
29 #endif // ESP32
30 
31 
32 #include <CayenneLPP.h>
33 #include <FS.h>
34 
35 #include <EnigmaIOTGateway.h>
36 #include <helperFunctions.h>
37 #include <debug.h>
38 #include <espnow_hal.h>
39 #include <Curve25519.h>
40 #include <ChaChaPoly.h>
41 #include <Poly1305.h>
42 #include <SHA256.h>
43 #include <ArduinoJson.h>
44 #include <DNSServer.h>
45 #include <ESPAsyncWebServer.h>
46 #include <ESPAsyncWiFiManager.h>
47 
48 #ifndef BUILTIN_LED
49 #define BUILTIN_LED 5
50 #endif // BUILTIN_LED
51 
52 #define BLUE_LED BUILTIN_LED
53 #define RED_LED BUILTIN_LED
54 
55 #ifdef ESP32
56 TimerHandle_t connectionLedTimer;
57 #elif defined(ESP8266)
58 ETSTimer connectionLedTimer;
59 #endif // ESP32
60 
62 boolean connectionLedFlashing = false;
63 
64 void flashConnectionLed (void* led) {
65  //digitalWrite (*(int*)led, !digitalRead (*(int*)led));
66  digitalWrite (BUILTIN_LED, !digitalRead (BUILTIN_LED));
67 }
68 
69 void startConnectionFlash (int period) {
70 #ifdef ESP32
71  if (!connectionLedFlashing) {
72  connectionLedFlashing = true;
73  connectionLedTimer = xTimerCreate ("led_flash", pdMS_TO_TICKS (period), pdTRUE, (void*)0, flashConnectionLed);
74  xTimerStart (connectionLedTimer, 0);
75  }
76 #elif defined (ESP8266)
77  ets_timer_disarm (&connectionLedTimer);
78  if (!connectionLedFlashing) {
79  connectionLedFlashing = true;
80  ets_timer_arm_new (&connectionLedTimer, period, true, true);
81  }
82 #endif // ESP32
83 }
84 
86 #ifdef ESP32
88  connectionLedFlashing = false;
89  xTimerStop (connectionLedTimer, 0);
90  xTimerDelete (connectionLedTimer, 0);
91  }
92 #elif defined(ESP8266)
94  connectionLedFlashing = false;
95  ets_timer_disarm (&connectionLedTimer);
96  digitalWrite (connectionLed, HIGH);
97  }
98 #endif // ESP32
99 }
100 
101 void wifiManagerExit (boolean status) {
103 }
104 
107 }
108 
109 void processRxControlData (char* macStr, uint8_t* data, uint8_t length) {
110  if (data) {
111  GwOutput.outputControlSend (macStr, data, length);
112  }
113 }
114 
115 void processRxData (uint8_t* mac, uint8_t* buffer, uint8_t length, uint16_t lostMessages, bool control, gatewayPayloadEncoding_t payload_type, char* nodeName = NULL) {
116  //uint8_t *addr = mac;
117  char* payload;
118  size_t pld_size;
119  const int PAYLOAD_SIZE = 512;
120 
121  payload = (char*)malloc (PAYLOAD_SIZE);
122 
123  char mac_str[ENIGMAIOT_ADDR_LEN * 3];
124  mac2str (mac, mac_str);
125  if (control) {
126  processRxControlData (nodeName ? nodeName : mac_str, buffer, length);
127  return;
128  }
129  //char* netName = EnigmaIOTGateway.getNetworkName ();
130  if (payload_type == CAYENNELPP) {
131  const int capacity = JSON_ARRAY_SIZE (25) + 25 * JSON_OBJECT_SIZE (4);
132  DynamicJsonDocument jsonBuffer (capacity);
133  JsonArray root = jsonBuffer.createNestedArray ();
134  CayenneLPP cayennelpp (MAX_DATA_PAYLOAD_SIZE);
135 
136  cayennelpp.decode ((uint8_t*)buffer, length, root);
137  uint8_t error = cayennelpp.getError ();
138  if (error != LPP_ERROR_OK) {
139  DEBUG_ERROR ("Error decoding CayenneLPP data: %d", error);
140  return;
141  }
142  pld_size = serializeJson (root, payload, PAYLOAD_SIZE);
143  } else if (payload_type == MSG_PACK) {
144  const int capacity = JSON_ARRAY_SIZE (25) + 25 * JSON_OBJECT_SIZE (4);
145  DynamicJsonDocument jsonBuffer (capacity);
146  DeserializationError error = deserializeMsgPack (jsonBuffer, buffer, length);
147  if (error != DeserializationError::Ok) {
148  DEBUG_ERROR ("Error decoding MSG Pack data: %s", error.c_str ());
149  return;
150  }
151  pld_size = serializeJson (jsonBuffer, payload, PAYLOAD_SIZE);
152  } else if (payload_type == RAW) {
153  if (length <= PAYLOAD_SIZE) {
154  memcpy (payload, buffer, length);
155  pld_size = length;
156  } else { // This will not happen but may lead to errors in case of using another physical transport
157  memcpy (payload, buffer, PAYLOAD_SIZE);
158  pld_size = PAYLOAD_SIZE;
159  }
160  }
161 
162  GwOutput.outputDataSend (mac_str, payload, pld_size);
163  DEBUG_INFO ("Published data message from %s: %s", mac_str, payload);
164  if (lostMessages > 0) {
165  pld_size = snprintf (payload, PAYLOAD_SIZE, "%u", lostMessages);
166  GwOutput.outputDataSend (mac_str, payload, pld_size, GwOutput_data_type::lostmessages);
167  //DEBUG_INFO ("Published MQTT from %s: %s", mac_str, payload);
168  }
169  pld_size = snprintf (payload, PAYLOAD_SIZE, "{\"per\":%e,\"lostmessages\":%u,\"totalmessages\":%u,\"packetshour\":%.2f}",
170  EnigmaIOTGateway.getPER ((uint8_t*)mac),
171  EnigmaIOTGateway.getErrorPackets ((uint8_t*)mac),
172  EnigmaIOTGateway.getTotalPackets ((uint8_t*)mac),
173  EnigmaIOTGateway.getPacketsHour ((uint8_t*)mac));
174  GwOutput.outputDataSend (mac_str, payload, pld_size, GwOutput_data_type::status);
175  //DEBUG_INFO ("Published MQTT from %s: %s", mac_str, payload);
176  free (payload);
177 }
178 
179 void onDownlinkData (uint8_t* address, char* nodeName, control_message_type_t msgType, char* data, unsigned int len){
180  char *buffer;
181  unsigned int bufferLen = len;
182 
183  if (nodeName) {
184  DEBUG_INFO ("DL Message for %s. Type 0x%02X", nodeName, msgType);
185  } else {
186  DEBUG_INFO ("DL Message for " MACSTR ". Type 0x%02X", MAC2STR (address), msgType);
187  }
188  DEBUG_DBG ("Data: %.*s", len, data);
189 
190  buffer = (char*)malloc (len + 1);
191  sprintf (buffer, "%.*s", len, data);
192  bufferLen ++;
193 
194  if (!EnigmaIOTGateway.sendDownstream (address, (uint8_t*)buffer, bufferLen, msgType)) {
195  DEBUG_ERROR ("Error sending esp_now message to " MACSTR, MAC2STR (address));
196  } else {
197  DEBUG_DBG ("Esp-now message sent or queued correctly");
198  }
199 
200  free (buffer);
201 }
202 
203 void newNodeConnected (uint8_t * mac, uint16_t node_id, char* nodeName = NULL) {
204  if (nodeName) {
205  if (!GwOutput.newNodeSend (nodeName, node_id)) {
206  DEBUG_WARN ("Error sending new node %s", nodeName);
207  } else {
208  DEBUG_DBG ("New node %s message sent", nodeName);
209  }
210  } else {
211  char macstr[ENIGMAIOT_ADDR_LEN * 3];
212  mac2str (mac, macstr);
213  if (!GwOutput.newNodeSend (macstr, node_id)) {
214  DEBUG_WARN ("Error sending new node %s", macstr);
215  } else {
216  DEBUG_DBG ("New node %s message sent", macstr);
217  }
218  }
219 
220 }
221 
222 void nodeDisconnected (uint8_t * mac, gwInvalidateReason_t reason) {
223  char macstr[ENIGMAIOT_ADDR_LEN * 3];
224  mac2str (mac, macstr);
225  //Serial.printf ("Node %s disconnected. Reason %u\n", macstr, reason);
226  if (!GwOutput.nodeDisconnectedSend (macstr, reason)) {
227  DEBUG_WARN ("Error sending node disconnected %s reason %d", macstr, reason);
228  } else {
229  DEBUG_DBG ("Node %s disconnected message sent. Reason %d", macstr, reason);
230  }
231 }
232 
233 #ifdef ESP32
234 void EnigmaIOTGateway_handle (void * param) {
235  for (;;) {
237  vTaskDelay (0);
238  }
239 }
240 
241 void GwOutput_handle (void* param) {
242  for (;;) {
243  GwOutput.loop ();
244  vTaskDelay (0);
245  }
246 }
247 
248 TaskHandle_t xEnigmaIOTGateway_handle = NULL;
249 TaskHandle_t gwoutput_handle = NULL;
250 #endif // ESP32
251 
252 void setup () {
253  Serial.begin (115200); Serial.println (); Serial.println ();
254 
255 #ifdef ESP32
256  // Turn-off the 'brownout detector' to avoid random restarts during wake up,
257  // normally due to bad quality regulator on board
258  WRITE_PERI_REG (RTC_CNTL_BROWN_OUT_REG, 0);
259 #endif
260 
261 #ifdef ESP8266
262  ets_timer_setfn (&connectionLedTimer, flashConnectionLed, (void*)&connectionLed);
263 #elif defined ESP32
264 
265 #endif
266  pinMode (BUILTIN_LED, OUTPUT);
267  digitalWrite (BUILTIN_LED, HIGH);
268  startConnectionFlash (100);
269 
270 
271  if (!GwOutput.loadConfig ()) {
272  DEBUG_WARN ("Error reading config file");
273  }
274 
283 
284 #if CONNECT_TO_WIFI_AP == 1
285  WiFi.mode (WIFI_AP_STA);
286  WiFi.begin ();
288 #else
289  //WiFi.mode (WIFI_AP);
290 #endif // CONNECT_TO_WIFI_AP
291 
292 
295 
296  DEBUG_INFO ("STA MAC Address: %s", WiFi.macAddress ().c_str());
297  DEBUG_INFO ("AP MAC Address: %s", WiFi.softAPmacAddress().c_str ());
298  DEBUG_INFO ("BSSID Address: %s", WiFi.BSSIDstr().c_str ());
299 
300  DEBUG_INFO ("IP address: %s", WiFi.localIP ().toString ().c_str ());
301  DEBUG_INFO ("AP IP address: %s", WiFi.softAPIP ().toString ().c_str ());
302  DEBUG_INFO ("WiFi Channel: %d", WiFi.channel ());
303 
304  DEBUG_INFO ("WiFi SSID: %s", WiFi.SSID ().c_str ());
305  DEBUG_INFO ("Network Name: %s", EnigmaIOTGateway.getNetworkName ());
306 
308  GwOutput.begin ();
309 
310 #ifdef ESP32
311  //xTaskCreate (EnigmaIOTGateway_handle, "handle", 10000, NULL, 1, &xEnigmaIOTGateway_handle);
312  //xTaskCreatePinnedToCore (EnigmaIOTGateway_handle, "handle", 4096, NULL, 0, &xEnigmaIOTGateway_handle, 1);
313  //xTaskCreatePinnedToCore (GwOutput_handle, "gwoutput", 10000, NULL, 2, &gwoutput_handle, 1);
314 #endif
315  }
316 
317 void loop () {
318 
319  GwOutput.loop ();
321 
322 }
EnigmaIOTGatewayClass::onWiFiManagerExit
void onWiFiManagerExit(onWiFiManagerExit_t handle)
Register callback to be called on wifi manager exit.
Definition: EnigmaIOTGateway.h:429
GatewayOutput_dummy::loadConfig
bool loadConfig()
Loads output module configuration.
Definition: GwOutput_dummy.cpp:39
processRxControlData
void processRxControlData(char *macStr, uint8_t *data, uint8_t length)
Definition: EnigmaIOTGatewayDummy.ino:109
EnigmaIOTGatewayClass::onNodeDisconnected
void onNodeDisconnected(onNodeDisconnected_t handler)
Defines a function callback that will be called every time a node is disconnected.
Definition: EnigmaIOTGateway.h:597
GatewayOutput_dummy::configManagerStart
void configManagerStart(EnigmaIOTGatewayClass *enigmaIotGw)
Called when wifi manager starts config portal.
Definition: GwOutput_dummy.cpp:31
EnigmaIOTGatewayClass::onDataRx
void onDataRx(onGwDataRx_t handler)
Defines a function callback that will be called on every downlink data message that is received from ...
Definition: EnigmaIOTGateway.h:500
MAX_DATA_PAYLOAD_SIZE
static const int MAX_DATA_PAYLOAD_SIZE
Maximun payload size for data packets.
Definition: EnigmaIoTconfig.h:48
GwOutput_generic.h
Generic Gateway output module template.
stopConnectionFlash
void stopConnectionFlash()
Definition: EnigmaIOTGatewayDummy.ino:85
GatewayOutput_dummy::nodeDisconnectedSend
bool nodeDisconnectedSend(char *address, gwInvalidateReason_t reason)
Send node disconnection notification.
Definition: GwOutput_dummy.cpp:73
EnigmaIOTGatewayClass::configWiFiManager
bool configWiFiManager()
Starts configuration AP and web server and gets settings from it.
Definition: EnigmaIOTGateway.cpp:443
connectionLed
const int connectionLed
Definition: EnigmaIOTGatewayDummy.ino:61
RAW
@ RAW
Definition: EnigmaIOTGateway.h:51
BLUE_LED
#define BLUE_LED
Definition: EnigmaIOTGatewayDummy.ino:52
ENIGMAIOT_ADDR_LEN
static const size_t ENIGMAIOT_ADDR_LEN
Address size. Mac address = 6 bytes.
Definition: EnigmaIoTconfig.h:14
EnigmaIOTGatewayClass::getNetworkName
char * getNetworkName()
Gets EnigmaIOT network name.
Definition: EnigmaIOTGateway.h:400
GwOutput
GatewayOutput_dummy GwOutput
Definition: GwOutput_dummy.cpp:29
setup
void setup()
Definition: EnigmaIOTGatewayDummy.ino:252
connectionLedFlashing
boolean connectionLedFlashing
Definition: EnigmaIOTGatewayDummy.ino:62
GatewayOutput_dummy::begin
bool begin()
Starts output module.
Definition: GwOutput_dummy.cpp:48
onDownlinkData
void onDownlinkData(uint8_t *address, char *nodeName, control_message_type_t msgType, char *data, unsigned int len)
Definition: EnigmaIOTGatewayDummy.ino:179
EnigmaIOTGatewayClass::setRxLed
void setRxLed(uint8_t led, time_t onTime=FLASH_LED_TIME)
Sets a LED to be flashed every time a message is received.
Definition: EnigmaIOTGateway.cpp:50
EnigmaIOTGatewayClass::handle
void handle()
This method should be called periodically for instance inside loop() function. It is used for interna...
Definition: EnigmaIOTGateway.cpp:787
processRxData
void processRxData(uint8_t *mac, uint8_t *buffer, uint8_t length, uint16_t lostMessages, bool control, gatewayPayloadEncoding_t payload_type, char *nodeName=NULL)
Definition: EnigmaIOTGatewayDummy.ino:115
EnigmaIOTGatewayClass::setTxLed
void setTxLed(uint8_t led, time_t onTime=FLASH_LED_TIME)
Sets a LED to be flashed every time a message is transmitted.
Definition: EnigmaIOTGateway.cpp:43
GatewayOutput_dummy::loop
void loop()
Should be called often for module management.
Definition: GwOutput_dummy.cpp:54
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
nodeDisconnected
void nodeDisconnected(uint8_t *mac, gwInvalidateReason_t reason)
Definition: EnigmaIOTGatewayDummy.ino:222
gatewayPayloadEncoding_t
gatewayPayloadEncoding_t
Definition: EnigmaIOTGateway.h:50
EnigmaIOTGatewayClass::getTotalPackets
uint32_t getTotalPackets(uint8_t *address)
Gets total packets sent by node that has a specific address.
Definition: EnigmaIOTGateway.cpp:1309
EnigmaIOTGatewayClass::onNewNode
void onNewNode(onNewNode_t handler)
Defines a function callback that will be called every time a node gets connected or reconnected.
Definition: EnigmaIOTGateway.h:568
EnigmaIOTGateway
EnigmaIOTGatewayClass EnigmaIOTGateway
Definition: EnigmaIOTGateway.cpp:1747
GatewayOutput_dummy::newNodeSend
bool newNodeSend(char *address, uint16_t node_id)
Send new node notification.
Definition: GwOutput_dummy.cpp:68
RED_LED
#define RED_LED
Definition: EnigmaIOTGatewayDummy.ino:53
MSG_PACK
@ MSG_PACK
Definition: EnigmaIOTGateway.h:54
MACSTR
#define MACSTR
Definition: helperFunctions.cpp:82
GatewayOutput_dummy::outputControlSend
bool outputControlSend(char *address, uint8_t *data, size_t length)
Send control data from nodes.
Definition: GwOutput_dummy.cpp:63
BUILTIN_LED
#define BUILTIN_LED
Definition: EnigmaIOTGatewayDummy.ino:49
GatewayOutput_dummy::configManagerExit
void configManagerExit(bool status)
Called when wifi manager exits config portal.
Definition: GwOutput_dummy.cpp:44
wifiManagerStarted
void wifiManagerStarted()
Definition: EnigmaIOTGatewayDummy.ino:105
data
@ data
Definition: GwOutput_generic.h:23
flashConnectionLed
void flashConnectionLed(void *led)
Definition: EnigmaIOTGatewayDummy.ino:64
Espnow_hal
Espnow_halClass Espnow_hal
Singleton instance of ESP-NOW class.
Definition: espnow_hal.cpp:20
EnigmaIOTGatewayClass::sendDownstream
bool sendDownstream(uint8_t *mac, const uint8_t *data, size_t len, control_message_type_t controlData, gatewayPayloadEncoding_t payload_type=RAW, char *nodeName=NULL)
Starts a downstream data message transmission.
Definition: EnigmaIOTGateway.cpp:325
EnigmaIOTGatewayClass::getErrorPackets
uint32_t getErrorPackets(uint8_t *address)
Gets number of errored packets of node that has a specific address.
Definition: EnigmaIOTGateway.cpp:1315
lostmessages
@ lostmessages
Definition: GwOutput_generic.h:24
loop
void loop()
Definition: EnigmaIOTGatewayDummy.ino:317
EnigmaIOTGatewayClass::getPacketsHour
double getPacketsHour(uint8_t *address)
Gets packet rate sent by node that has a specific address, in packets per hour.
Definition: EnigmaIOTGateway.cpp:1321
helperFunctions.h
Auxiliary function definition.
GatewayOutput_dummy::outputDataSend
bool outputDataSend(char *address, char *data, size_t length, GwOutput_data_type_t type=data)
Send data from nodes.
Definition: GwOutput_dummy.cpp:58
wifiManagerExit
void wifiManagerExit(boolean status)
Definition: EnigmaIOTGatewayDummy.ino:101
EnigmaIOTGateway.h
Library to build a gateway for EnigmaIoT system.
gwInvalidateReason_t
gwInvalidateReason_t
Key invalidation reason definition.
Definition: EnigmaIOTGateway.h:64
control_message_type_t
enum control_message_type control_message_type_t
EnigmaIOTGatewayClass::getPER
double getPER(uint8_t *address)
Gets packet error rate of node that has a specific address.
Definition: EnigmaIOTGateway.cpp:1299
CAYENNELPP
@ CAYENNELPP
Definition: EnigmaIOTGateway.h:52
startConnectionFlash
void startConnectionFlash(int period)
Definition: EnigmaIOTGatewayDummy.ino:69
EnigmaIOTGatewayClass::getNetworkKey
char * getNetworkKey(bool plain=false)
Gets hashed EnigmaIOT network key.
Definition: EnigmaIOTGateway.h:408
EnigmaIOTGatewayClass::begin
void begin(Comms_halClass *comm, uint8_t *networkKey=NULL, bool useDataCounter=true)
Initalizes communication basic data and starts accepting node registration.
Definition: EnigmaIOTGateway.cpp:667
EnigmaIOTGatewayClass::onWiFiManagerStarted
void onWiFiManagerStarted(onWiFiManagerStarted_t handle)
Register callback to be called on wifi manager start.
Definition: EnigmaIOTGateway.h:437
espnow_hal.h
ESP-NOW communication system abstraction layer. To be used on ESP8266 or ESP32 platforms.
status
@ status
Definition: GwOutput_generic.h:25
GwOutput_dummy.h
Dummy Gateway output module.
debug.h
Auxiliary functions for debugging over Serial.
GatewayOutput_dummy::setDlCallback
void setDlCallback(onDlData_t cb)
Set data processing function.
Definition: GwOutput_dummy.h:109
newNodeConnected
void newNodeConnected(uint8_t *mac, uint16_t node_id, char *nodeName=NULL)
Definition: EnigmaIOTGatewayDummy.ino:203