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