14 #define MQTT_MAX_PACKET_SIZE 2048
15 #include <PubSubClient.h>
17 #include <WiFiClientSecure.h>
19 #include <WiFiClient.h>
30 #include "esp_system.h"
31 #include "esp_event.h"
35 #include "soc/rtc_cntl_reg.h"
36 #elif defined(ESP8266)
37 #include <ESP8266WiFi.h>
39 #include <ESP8266mDNS.h>
44 #include <ArduinoOTA.h>
46 #include <CayenneLPP.h>
53 #include <Curve25519.h>
54 #include <ChaChaPoly.h>
57 #include <ArduinoJson.h>
58 #include <DNSServer.h>
59 #include <ESPAsyncWebServer.h>
60 #include <ESPAsyncWiFiManager.h>
65 #include <DallasTemperature.h>
67 const time_t statusPeriod = 300 * 1000;
68 const int DS18B20_PIN = 16;
69 const int DS18B20_PREC = 12;
70 OneWire ow (DS18B20_PIN);
71 DallasTemperature ds18b20 (&ow);
72 DeviceAddress dsAddress;
80 #define BLUE_LED LED_BUILTIN
81 #define RED_LED LED_BUILTIN
84 TimerHandle_t connectionLedTimer;
85 #elif defined(ESP8266)
86 ETSTimer connectionLedTimer;
101 connectionLedTimer = xTimerCreate (
"led_flash", pdMS_TO_TICKS (period), pdTRUE, (
void*)0,
flashConnectionLed);
102 xTimerStart (connectionLedTimer, 0);
104 #elif defined (ESP8266)
105 ets_timer_disarm (&connectionLedTimer);
108 ets_timer_arm_new (&connectionLedTimer, period,
true,
true);
117 xTimerStop (connectionLedTimer, 0);
118 xTimerDelete (connectionLedTimer, 0);
120 #elif defined(ESP8266)
123 ets_timer_disarm (&connectionLedTimer);
143 ArduinoOTA.onStart ([]() {
144 if (ArduinoOTA.getCommand () == U_FLASH) {
145 DEBUG_WARN (
"Start updating sketch");
147 DEBUG_WARN (
"Start updating filesystem");
151 ArduinoOTA.onEnd ([]() {
152 DEBUG_WARN (
"OTA Finished");
154 ArduinoOTA.onProgress ([](
unsigned int progress,
unsigned int total) {
155 static bool printed =
false;
156 unsigned int percent = progress / (total / 100);
158 if (!(percent % 1)) {
161 if (!(percent % 20) && !printed && percent != 0) {
162 DEBUG_WARN (
" %d%%\n", percent);
164 }
else if (percent % 20) {
167 if (progress == total) {
168 DEBUG_WARN (
"OTA transfer finished");
171 ArduinoOTA.onError ([](ota_error_t error) {
172 DEBUG_WARN (
"OTA Error[%u]: ", error);
173 if (error == OTA_AUTH_ERROR) { DEBUG_WARN (
"OTA Auth Failed"); }
174 else if (error == OTA_BEGIN_ERROR) { DEBUG_WARN (
"OTA Begin Failed"); }
175 else if (error == OTA_CONNECT_ERROR) { DEBUG_WARN (
"OTA Connect Failed"); }
176 else if (error == OTA_RECEIVE_ERROR) { DEBUG_WARN (
"OTA Receive Failed"); }
177 else if (error == OTA_END_ERROR) { DEBUG_WARN (
"OTA End Failed"); }
200 const int PAYLOAD_SIZE = 1024;
202 char payload[PAYLOAD_SIZE];
213 DEBUG_INFO (
"CayenneLPP message");
214 const int capacity = JSON_ARRAY_SIZE (25) + 25 * JSON_OBJECT_SIZE (4);
215 DynamicJsonDocument jsonBuffer (capacity);
216 JsonArray root = jsonBuffer.createNestedArray ();
219 cayennelpp.decode ((uint8_t*)buffer, length, root);
220 uint8_t error = cayennelpp.getError ();
221 if (error != LPP_ERROR_OK) {
222 DEBUG_ERROR (
"Error decoding CayenneLPP data: %d", error);
225 pld_size = serializeJson (root, payload, PAYLOAD_SIZE);
226 }
else if (payload_type ==
MSG_PACK) {
227 DEBUG_INFO (
"MsgPack message");
228 const int capacity = JSON_ARRAY_SIZE (25) + 25 * JSON_OBJECT_SIZE (4);
229 DynamicJsonDocument jsonBuffer (capacity);
230 DeserializationError error = deserializeMsgPack (jsonBuffer, buffer, length);
231 if (error != DeserializationError::Ok) {
232 DEBUG_ERROR (
"Error decoding MSG Pack data: %s", error.c_str ());
235 pld_size = serializeJson (jsonBuffer, payload, PAYLOAD_SIZE);
236 }
else if (payload_type ==
RAW) {
237 DEBUG_INFO (
"RAW message");
238 if (length <= PAYLOAD_SIZE) {
239 memcpy (payload, buffer, length);
242 memcpy (payload, buffer, PAYLOAD_SIZE);
243 pld_size = PAYLOAD_SIZE;
248 DEBUG_INFO (
"Published data message from %s, length %d: %s, Encoding 0x%02X", nodeName ? nodeName : mac_str, pld_size, payload, payload_type);
249 if (lostMessages > 0) {
250 pld_size = snprintf (payload, PAYLOAD_SIZE,
"%u", lostMessages);
252 DEBUG_INFO (
"Published MQTT from %s: %s", nodeName ? nodeName : mac_str, payload);
254 pld_size = snprintf (payload, PAYLOAD_SIZE,
"{\"per\":%e,\"lostmessages\":%u,\"totalmessages\":%u,\"packetshour\":%.2f}",
260 DEBUG_INFO (
"Published MQTT from %s: %s", nodeName ? nodeName : mac_str, payload);
265 unsigned int bufferLen = len;
269 DEBUG_INFO (
"DL Message for %s. Type 0x%02X", nodeName, msgType);
271 DEBUG_INFO (
"DL Message for " MACSTR ". Type 0x%02X", MAC2STR (address), msgType);
273 DEBUG_DBG (
"Data: %.*s Length: %d", len,
data, len);
276 const int capacity = JSON_ARRAY_SIZE (25) + 25 * JSON_OBJECT_SIZE (4);
277 DynamicJsonDocument json (capacity);
278 DeserializationError error = deserializeJson (json,
data, len, DeserializationOption::NestingLimit (3));
279 if (error == DeserializationError::Ok) {
280 DEBUG_INFO (
"JSON Message. Result %s", error.c_str ());
281 bufferLen = measureMsgPack (json) + 1;
282 buffer = (uint8_t*)malloc (bufferLen);
283 bufferLen = serializeMsgPack (json, (
char*)buffer, bufferLen);
286 DEBUG_INFO (
"Not JSON Message. Error %s", error.c_str ());
288 buffer = (uint8_t*)malloc (bufferLen);
289 sprintf ((
char*)buffer,
"%.*s", len,
data);
294 buffer = (uint8_t*)calloc (
sizeof (uint8_t), bufferLen);
295 memcpy (buffer,
data, len);
301 DEBUG_WARN (
"Error sending esp_now message to %s", nodeName);
303 DEBUG_WARN (
"Error sending esp_now message to " MACSTR, MAC2STR (address));
306 DEBUG_DBG (
"Esp-now message sent or queued correctly");
318 DEBUG_WARN (
"Error sending new node %s", nodeName);
320 DEBUG_DBG (
"New node %s message sent", nodeName);
326 DEBUG_WARN (
"Error sending new node %s", macstr);
328 DEBUG_DBG (
"New node %s message sent", macstr);
339 DEBUG_WARN (
"Error sending node disconnected %s reason %d", macstr, reason);
341 DEBUG_DBG (
"Node %s disconnected message sent. Reason %d", macstr, reason);
365 Serial.begin (115200); Serial.println (); Serial.println ();
370 WRITE_PERI_REG (RTC_CNTL_BROWN_OUT_REG, 0);
384 if (ds18b20.getDeviceCount () > 0) {
385 ds18b20.getAddress (dsAddress, 0);
386 DEBUG_INFO (
"DS18B20 address: %02X %02X %02X %02X %02X %02X %02X %02X",
387 dsAddress[0], dsAddress[1], dsAddress[2], dsAddress[3],
388 dsAddress[4], dsAddress[5], dsAddress[6], dsAddress[7]);
390 DEBUG_WARN (
"No DS18B20 found");
392 ds18b20.setWaitForConversion (
false);
393 ds18b20.setResolution (DS18B20_PREC);
397 DEBUG_WARN (
"Error reading config file");
409 WiFi.mode (WIFI_AP_STA);
417 DEBUG_INFO (
"STA MAC Address: %s", WiFi.macAddress ().c_str ());
418 DEBUG_INFO (
"AP MAC Address: %s", WiFi.softAPmacAddress ().c_str ());
419 DEBUG_INFO (
"BSSID Address: %s", WiFi.BSSIDstr ().c_str ());
421 DEBUG_INFO (
"IP address: %s", WiFi.localIP ().toString ().c_str ());
422 DEBUG_INFO (
"WiFi Channel: %d", WiFi.channel ());
423 DEBUG_INFO (
"WiFi SSID: %s", WiFi.SSID ().c_str ());
439 void sendStatus (
float temperature) {
440 const size_t capacity = JSON_OBJECT_SIZE (1) + JSON_OBJECT_SIZE (3) + 30;;
444 DynamicJsonDocument doc (capacity);
446 JsonObject
status = doc.createNestedObject (
"status");
447 status[
"temp"] = temperature;
449 status[
"mem"] = ESP.getFreeHeap ();
451 len = measureJson (doc) + 1;
452 payload = (
char*)malloc (len);
453 serializeJson (doc,(
char*)payload,len);
454 char addr[] =
"gateway";
463 ArduinoOTA.handle ();
466 static bool tempRequested =
false;
467 static time_t lastTempTime;
469 if (ds18b20.validAddress (dsAddress)) {
470 if (millis () - lastTempTime > statusPeriod && !tempRequested) {
471 ds18b20.requestTemperatures ();
472 DEBUG_WARN (
"Temperature requested");
473 lastTempTime = millis ();
474 tempRequested =
true;
477 if (ds18b20.isConversionComplete ()) {
478 temperature = ds18b20.getTempC (dsAddress);
479 sendStatus (temperature);
480 DEBUG_WARN (
"Temperature: %f", temperature);
481 tempRequested =
false;