From 31a0d269465168221b76d85bbed69d570bf1abd5 Mon Sep 17 00:00:00 2001 From: Rob Roos Date: Sun, 16 Jul 2023 22:23:06 +0200 Subject: [PATCH 1/5] Heap optimization --- .DS_Store | Bin 10244 -> 14340 bytes .vscode/arduino.json | 6 +- Debug.h | 2 +- FSexplorer.ino | 18 +-- MQTTstuff.ino | 58 ++++----- ModbusRTU-ESP8266-webui.h | 21 +++- ModbusRTU-ESP8266-webui.ino | 31 +++-- ModbusStuff.h | 2 +- ModbusStuff.ino | 234 +++++++++++++++++++----------------- README.md | 1 + data/Daytimemap org.cfg | 2 +- data/Daytimemap.cfg | 2 +- data/FSexplorer.css | 2 +- data/FSexplorer.html | 2 +- data/MBmapSolarEdge.cfg | 2 +- data/MBmapUMG96.cfg | 2 +- data/Modbusmap.cfg | 2 +- data/Modbusmaptest.cfg | 2 +- data/index.css | 2 +- data/index.html | 2 +- data/index.js | 3 +- handleDebug.ino | 56 ++++----- helperStuff.ino | 40 +++--- jsonStuff.ino | 4 +- networkStuff.h | 122 +++++++++++++++---- restAPI.ino | 13 +- safeTimers.h | 2 +- settingStuff.ino | 12 +- version.h | 24 ++-- 29 files changed, 389 insertions(+), 280 deletions(-) diff --git a/.DS_Store b/.DS_Store index 17b6fa21b92c69456f5afe95bfb227007d7427df..7c847e7882e0a117fc6c637c7eb412f66f6b92f6 100644 GIT binary patch delta 789 zcmZn(Xem%&U|?W$DortDU@!nOIe-{M3-ADmHU5vVjVVB}f4a7^g5KA}auj0gY{VXfykWBSR)b2}~nY{OQI*XZFqP z94s8R{HWSfz~-Z92U!6%z97ReI5|JJ04NW1T?519e`0a`=}2PACJB@CWaTzTiyN|u zpjm2a=W)alBny;4u?8+7fMULK0s~OBZVod;4$uopImq@fXdDB&04jrK4}0k1!;Z+Z zD3+ngqS(j~u(5C&`^1KndS0M@76v_rbWq@-*gWG{HL@I<-A|p2j)Lrl>qYY_hCGV> zCq4kRGO#n~)iaba6f-0<4Dib%~6lP}z0QFR?W&i*H delta 165 zcmZoEXbF&DU|?W$DortDU{C-uIe-{M3-C-V6q~3gIoZI3MH0wo-~?hupg2QPd2vBf zPJR-QzhkqY#A5c%>>Ml{jGU826hCcNQetMC>@5(z`HFx6+vI8D{2Q<2FbOh)3;>$T y4J2GaW^cUsoq009i7q3ffWEng(CF; diff --git a/.vscode/arduino.json b/.vscode/arduino.json index d02e89b..3041112 100644 --- a/.vscode/arduino.json +++ b/.vscode/arduino.json @@ -1,8 +1,8 @@ { - "board": "esp8266:esp8266:nodemcuv2", - "configuration": "xtal=160,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,eesz=4M2M,led=2,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=115200", + "board": "esp8266:esp8266:d1_mini_pro", + "configuration": "xtal=160,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,eesz=16M14M,ip=lm2f,dbg=Serial,lvl=None____,wipe=none,baud=460800", "sketch": "ModbusRTU-ESP8266-webui.ino", "output": "../buildmodbus", - "port": "/dev/cu.usbserial-0001", + "port": "/dev/tty.usbserial-210", "prebuild": "/Users/robroosm1/Documents/Arduino/autoinc-semver-master/semver-incr-build.sh ./version.h" } \ No newline at end of file diff --git a/Debug.h b/Debug.h index cf52ea0..30c3234 100644 --- a/Debug.h +++ b/Debug.h @@ -3,7 +3,7 @@ ** Program : Debug.h, part of ModbusRTU-webui ** Version 1.8.0 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** diff --git a/FSexplorer.ino b/FSexplorer.ino index b462681..f7a557b 100644 --- a/FSexplorer.ino +++ b/FSexplorer.ino @@ -4,7 +4,7 @@ ** Version 1.8.1 ** ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -90,7 +90,7 @@ void startWebserver(){ // Set up first message as the IP address DebugTln("HTTP Server started\r"); sprintf(cMsg, "%03d.%03d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]); - DebugTf("Assigned IP=%s\r\n", cMsg); + DebugTf(PSTR("Assigned IP=%s\r\n"), cMsg); } //===================================================================================== void setupFSexplorer(){ @@ -111,10 +111,10 @@ void setupFSexplorer(){ httpServer.onNotFound([]() { - if (bDebugRestAPI) DebugTf("in 'onNotFound()'!! [%s] => \r\n", String(httpServer.uri()).c_str()); + if (bDebugRestAPI) DebugTf(PSTR("in 'onNotFound()'!! [%s] => \r\n"), String(httpServer.uri()).c_str()); if (httpServer.uri().indexOf("/api/") == 0) { - if (bDebugRestAPI) DebugTf("next: processAPI(%s)\r\n", String(httpServer.uri()).c_str()); + if (bDebugRestAPI) DebugTf(PSTR("next: processAPI(%s)\r\n"), String(httpServer.uri()).c_str()); processAPI(); } // else if (httpServer.uri() == "/") @@ -124,7 +124,7 @@ void setupFSexplorer(){ // } else { - if (bDebugRestAPI) DebugTf("next: handleFile(%s)\r\n" + if (bDebugRestAPI) DebugTf(PSTR("next: handleFile(%s)\r\n") , String(httpServer.urlDecode(httpServer.uri())).c_str()); if (!handleFile(httpServer.urlDecode(httpServer.uri()))) { @@ -158,13 +158,13 @@ void apilistfiles() // Senden aller Daten an den Client dirMap[fileNr].Size = dir.fileSize(); fileNr++; } - //DebugTf("fileNr[%d], Max[%d]\r\n", fileNr, MAX_FILES_IN_LIST); + //DebugTf(PSTR("fileNr[%d], Max[%d]\r\n"), fileNr, MAX_FILES_IN_LIST); // -- bubble sort dirMap op .Name-- for (int8_t y = 0; y < fileNr; y++) { yield(); for (int8_t x = y + 1; x < fileNr; x++) { - //DebugTf("y[%d], x[%d] => seq[y][%s] / seq[x][%s] ", y, x, dirMap[y].Name, dirMap[x].Name); + //DebugTf(PSTR("y[%d], x[%d] => seq[y][%s] / seq[x][%s] "), y, x, dirMap[y].Name, dirMap[x].Name); if (strcasecmp(dirMap[x].Name, dirMap[y].Name) <= 0) { //Debug(" !switch!"); @@ -190,7 +190,7 @@ void apilistfiles() // Senden aller Daten an den Client String temp = "["; for (int f=0; f < fileNr; f++) { - DebugTf("[%3d] >> [%s]\r\n", f, dirMap[f].Name); + DebugTf(PSTR("[%3d] >> [%s]\r\n"), f, dirMap[f].Name); temp += R"({"name":")" + String(dirMap[f].Name) + R"(","size":")" + formatBytes(dirMap[f].Size) + R"("},)"; } @@ -209,7 +209,7 @@ bool handleFile(String&& path) { if (httpServer.hasArg("delete")) { - DebugTf("Delete -> [%s]\n\r", httpServer.arg("delete").c_str()); + DebugTf(PSTR("Delete -> [%s]\n\r"), httpServer.arg("delete").c_str()); LittleFS.remove(httpServer.arg("delete")); // Datei löschen httpServer.sendContent(Header); return true; diff --git a/MQTTstuff.ino b/MQTTstuff.ino index a4bee08..4e8e245 100644 --- a/MQTTstuff.ino +++ b/MQTTstuff.ino @@ -1,9 +1,9 @@ /* *************************************************************************** ** Program : MQTTstuff -** Version 1.8.0 +** Version 1.10.0 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** TERMS OF USE: MIT License. See bottom of file. @@ -69,11 +69,11 @@ void handleMQTTcallback(char *topic, byte *payload, unsigned int length) { if (bDebugMQTT) { DebugT("Message arrived on topic ["); Debug(topic); Debug("] = ["); - for (int i = 0; i < length; i++) + for (unsigned int i = 0; i < length; i++) { Debug((char)payload[i]); } - Debug("] ("); Debug(length); Debug(")"); Debugln(); + Debug("] ("); Debug(length); Debug(")"); Debugln(); DebugFlush(); } char subscribeTopic[100]; // naming convention /set// @@ -82,8 +82,8 @@ if (bDebugMQTT) { //what is the incoming message? if (stricmp(topic, subscribeTopic) == 0) { - //incoming command to be forwarded to MODBUS - sendModbus((char *)payload, length); + //incoming command to be analysed and processed + processMQcommand((char *)payload, length); } } @@ -108,7 +108,7 @@ void handleMQTT() sprintf(MQTTbrokerIPchar, "%d.%d.%d.%d", MQTTbrokerIP[0], MQTTbrokerIP[1], MQTTbrokerIP[2], MQTTbrokerIP[3]); if (isValidIP(MQTTbrokerIP)) { - MQTTDebugTf("[%s] => setServer(%s, %d)\r\n", CSTR(settingMQTTbroker), MQTTbrokerIPchar, settingMQTTbrokerPort); + MQTTDebugTf(PSTR("[%s] => setServer(%s, %d)\r\n"), CSTR(settingMQTTbroker), MQTTbrokerIPchar, settingMQTTbrokerPort); MQTTclient.disconnect(); MQTTclient.setServer(MQTTbrokerIPchar, settingMQTTbrokerPort); MQTTclient.setCallback(handleMQTTcallback); @@ -120,7 +120,7 @@ void handleMQTT() } else { // invalid IP, then goto error state - MQTTDebugTf("ERROR: [%s] => is not a valid URL\r\n", CSTR(settingMQTTbroker)); + MQTTDebugTf(PSTR("ERROR: [%s] => is not a valid URL\r\n"), CSTR(settingMQTTbroker)); stateMQTT = MQTT_STATE_ERROR; //DebugTln(F("Next State: MQTT_STATE_ERROR")); } @@ -129,9 +129,9 @@ void handleMQTT() case MQTT_STATE_TRY_TO_CONNECT: MQTTDebugTln(F("MQTT State: MQTT try to connect")); - MQTTDebugTf("MQTT server is [%s], IP[%s]\r\n", settingMQTTbroker.c_str(), MQTTbrokerIPchar); - MQTTDebugTf("MQTT clientid [%s] \r\n", MQTTclientId.c_str()); - MQTTDebugTf("MQTT PubNamespace [%s], SubNamespace [%s]\r\n", MQTTPubNamespace.c_str(), MQTTSubNamespace.c_str()); + MQTTDebugTf(PSTR("MQTT server is [%s], IP[%s]\r\n"), settingMQTTbroker.c_str(), MQTTbrokerIPchar); + MQTTDebugTf(PSTR("MQTT clientid [%s] \r\n"), MQTTclientId.c_str()); + MQTTDebugTf(PSTR("MQTT PubNamespace [%s], SubNamespace [%s]\r\n"), MQTTPubNamespace.c_str(), MQTTSubNamespace.c_str()); MQTTDebugT(F("Attempting MQTT connection .. ")); reconnectAttempts++; @@ -163,21 +163,21 @@ void handleMQTT() char topic[100]; strcpy(topic, CSTR(MQTTSubNamespace)); strlcat(topic, "/#", sizeof(topic)); - MQTTDebugTf("Subscribe to MQTT: TopicId [%s]\r\n", topic); + MQTTDebugTf(PSTR("Subscribe to MQTT: TopicId [%s]\r\n"), topic); if (MQTTclient.subscribe(topic)) { - MQTTDebugTf("MQTT: Subscribed successfully to TopicId [%s]\r\n", topic); + MQTTDebugTf(PSTR("MQTT: Subscribed successfully to TopicId [%s]\r\n"), topic); } else { - MQTTDebugTf("MQTT: Subscribe TopicId [%s] FAILED! \r\n", topic); + MQTTDebugTf(PSTR("MQTT: Subscribe TopicId [%s] FAILED! \r\n"), topic); } sendMQTTversioninfo(); } else { // no connection, try again, do a non-blocking wait for 3 seconds. MQTTDebugln(F(" .. \r")); - MQTTDebugTf("failed, retrycount=[%d], rc=[%d] .. try again in 3 seconds\r\n", reconnectAttempts, MQTTclient.state()); + MQTTDebugTf(PSTR("failed, retrycount=[%d], rc=[%d] .. try again in 3 seconds\r\n"), reconnectAttempts, MQTTclient.state()); RESTART_TIMER(timerMQTTwaitforretry); stateMQTT = MQTT_STATE_WAIT_CONNECTION_ATTEMPT; // if the re-connect did not work, then return to wait for reconnect MQTTDebugTln(F("Next State: MQTT_STATE_WAIT_CONNECTION_ATTEMPT")); @@ -282,12 +282,12 @@ void sendMQTTData(const char *topic, const char *json, const bool retain = false { if (!settingMQTTenable) return; if (!MQTTclient.connected() || !isValidIP(MQTTbrokerIP)) return; - MQTTDebugTf("Sending data to MQTT server [%s]:[%d]\r\n", settingMQTTbroker.c_str(), settingMQTTbrokerPort); + MQTTDebugTf(PSTR("Sending data to MQTT server [%s]:[%d]\r\n"), settingMQTTbroker.c_str(), settingMQTTbrokerPort); char full_topic[100]; snprintf(full_topic, sizeof(full_topic), "%s/", CSTR(MQTTPubNamespace)); strlcat(full_topic, topic, sizeof(full_topic)); - MQTTDebugTf("Sending MQTT: TopicId [%s] Message [%s]\r\n", full_topic, json); - if (!MQTTclient.publish(full_topic, json, retain)) DebugTln("MQTT publish failed."); + MQTTDebugTf(PSTR("Sending MQTT: TopicId [%s] Message [%s]\r\n"), full_topic, json); + if (!MQTTclient.publish(full_topic, json, retain)) DebugTln(F("MQTT publish failed.")); // feedWatchDog(); //feed the dog } // sendMQTTData() @@ -306,8 +306,8 @@ void sendMQTT(const char *topic, const char *json, const size_t len) { if (!settingMQTTenable) return; if (!MQTTclient.connected() || !isValidIP(MQTTbrokerIP)) return; - MQTTDebugTf("Sending data to MQTT server [%s]:[%d] ", settingMQTTbroker.c_str(), settingMQTTbrokerPort); - MQTTDebugTf("Sending MQTT: TopicId [%s] Message [%s]\r\n", topic, json); + MQTTDebugTf(PSTR("Sending data to MQTT server [%s]:[%d] "), settingMQTTbroker.c_str(), settingMQTTbrokerPort); + MQTTDebugTf(PSTR("Sending MQTT: TopicId [%s] Message [%s]\r\n"), topic, json); if (MQTTclient.getBufferSize() < len) MQTTclient.setBufferSize(len); //resize buffer when needed @@ -327,9 +327,9 @@ Publish usefull firmware version information to MQTT broker. */ void sendMQTTversioninfo() { - MQTTDebugln("sendMQTT versioninfo"); + MQTTDebugln(F("sendMQTT versioninfo")); sendMQTTData("ModbusRTU-webui/version", _VERSION); - MQTTDebugln("sendMQTT rebootcount"); + MQTTDebugln(F("sendMQTT rebootcount")); sendMQTTData("ModbusRTU-webui/reboot_count", CSTR(String(rebootCount))); // sendMQTTData("ModbusRTU-webui/reboot_count", rebootCount.c_str); @@ -337,7 +337,7 @@ void sendMQTTversioninfo() // char _msg[15]{0}; // itoa(_value, _msg, 10); // sendMQTTData("ModbusRTU-webui/reboot_count", _msg); - MQTTDebugln("end versioninfo "); + MQTTDebugln(F("end versioninfo ")); } //=========================================================================================== void resetMQTTBufferSize() @@ -380,7 +380,7 @@ void doAutoConfigure() return; } - MQTTDebugln("Start doAutoConfigureMB"); + MQTTDebugln(F("Start doAutoConfigureMB")); // String sTopic_template = "%homeassistant%/sensor/%node_id%/%label%/config"; // String sMsg_template = "{\"avty_t\":\"%mqtt_pub_topic%\",\"dev\":{\"identifiers\":\"%node_id%\",\"manufacturer\":\"Rob Roos\",\"model\":\"modbusRTUrdr\",\"name\":\"ModbusRTU reader(%hostname%)\",\"sw_version\":\"%version%\"},\"uniq_id\":\"%node_id%-%label%\",\"device_class\":\"%devclass%\",\"state_class\":\"%stateclass%\",\"name\":\"%hostname%_%friendlyname%\", \"stat_t\":\"%mqtt_pub_topic%/%label%\",\"unit_of_measurement\": \"%unit%\", \"value_template\": \"{{ value }}\" }" ; @@ -393,7 +393,7 @@ void doAutoConfigure() sTopic_template.replace("%homeassistant%", CSTR(settingMQTThaprefix)); // node sTopic_template.replace("%node_id%", CSTR(settingMQTTuniqueid)); - MQTTDebugTf("sTopic_template[%s]\r\n", CSTR(sTopic_template)); + MQTTDebugTf(PSTR("sTopic_template[%s]\r\n"), CSTR(sTopic_template)); /// node sMsg_template.replace("%node_id%", CSTR(settingMQTTuniqueid)); @@ -410,7 +410,7 @@ void doAutoConfigure() // sub topics sMsg_template.replace("%mqtt_sub_topic%", CSTR(MQTTSubNamespace)); - MQTTDebugTf("sMsg_template[%s]\r\n", CSTR(sMsg_template)); + MQTTDebugTf(PSTR("sMsg_template[%s]\r\n"), CSTR(sMsg_template)); /// ---------------------- // Now for all records in Modbusmap, convert sTopic and sMsg @@ -418,7 +418,7 @@ void doAutoConfigure() { if ((Modbusmap[i].oper == Modbus_READ || Modbusmap[i].oper == Modbus_RW) && Modbusmap[i].mqenable == 1 ) { - MQTTDebugTf("Record: %d, id %d, oper: %d, label:%s \r\n", i, Modbusmap[i].id, Modbusmap[i].oper, Modbusmap[i].label); + MQTTDebugTf(PSTR("Record: %d, id %d, oper: %d, label:%s \r\n"), i, Modbusmap[i].id, Modbusmap[i].oper, Modbusmap[i].label); sTopic = sTopic_template; sMsg = sMsg_template; @@ -436,8 +436,8 @@ void doAutoConfigure() // unit sMsg.replace("%unit%", Modbusmap[i].unit); - MQTTDebugTf("sTopic[%s]\r\n", CSTR(sTopic)); - MQTTDebugTf("sMsg[%s]==>\r\n", CSTR(sMsg)); + MQTTDebugTf(PSTR("sTopic[%s]\r\n"), CSTR(sTopic)); + MQTTDebugTf(PSTR("sMsg[%s]==>\r\n"), CSTR(sMsg)); DebugFlush(); //sendMQTT(CSTR(sTopic), CSTR(sMsg), (sTopic.length() + sMsg.length()+2)); diff --git a/ModbusRTU-ESP8266-webui.h b/ModbusRTU-ESP8266-webui.h index 51fd4c2..763f518 100644 --- a/ModbusRTU-ESP8266-webui.h +++ b/ModbusRTU-ESP8266-webui.h @@ -1,9 +1,9 @@ /* *************************************************************************** ** Program : Modbus-firmware.h -** Version 1.8.1 +** Version 1.10.0 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -39,7 +39,7 @@ void setLed(int8_t, uint8_t); #define _HOSTNAME "ModbusRTU" #define SETTINGS_FILE "/settings.ini" #define NTP_DEFAULT_TIMEZONE "Europe/Amsterdam" -#define NTP_HOST_DEFAULT "nl.pool.ntp.org" +#define NTP_HOST_DEFAULT "pool.ntp.org" #define NTP_RESYNC_TIME 1800 //seconds = every 30 minutes #define HOME_ASSISTANT_DISCOVERY_PREFIX "homeassistant" // Home Assistant discovery prefix @@ -65,10 +65,17 @@ String NodeId = ""; //Use acetime using namespace ace_time; -static BasicZoneProcessor timeProcessor; +// static BasicZoneProcessor timeProcessor; +// static const int CACHE_SIZE = 3; +// static BasicZoneProcessorCache zoneProcessorCache; +// static BasicZoneManager timezoneManager(zonedb::kZoneRegistrySize, zonedb::kZoneRegistry, zoneProcessorCache); +static ExtendedZoneProcessor tzProcessor; static const int CACHE_SIZE = 3; -static BasicZoneProcessorCache zoneProcessorCache; -static BasicZoneManager timezoneManager(zonedb::kZoneRegistrySize, zonedb::kZoneRegistry, zoneProcessorCache); +static ExtendedZoneProcessorCache zoneProcessorCache; +static ExtendedZoneManager timezoneManager( + zonedbx::kZoneAndLinkRegistrySize, + zonedbx::kZoneAndLinkRegistry, + zoneProcessorCache); const char *weekDayName[] { "Unknown", "Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Unknown" }; const char *flashMode[] { "QIO", "QOUT", "DIO", "DOUT", "Unknown" }; @@ -108,6 +115,8 @@ bool settingRelayAllwaysOnSwitch = false; uint8_t statusRelay = false; //debug flags +bool settingDebugAfterBoot = false; // setting in front end + bool bDebugMBmsg = false; bool bDebugMBlogic = false; // when set to true during compile time, Modbusmaptest.cfg file is selected during boot diff --git a/ModbusRTU-ESP8266-webui.ino b/ModbusRTU-ESP8266-webui.ino index 7697977..322cde2 100644 --- a/ModbusRTU-ESP8266-webui.ino +++ b/ModbusRTU-ESP8266-webui.ino @@ -2,9 +2,9 @@ /* *************************************************************************** ** Program : ModbusRTU-webui.ino -** Version 1.9.1 +** Version 1.10.0 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -68,7 +68,13 @@ void setup() setLed(LED2, ON); LittleFS.begin(); - readSettings(true); + readSettings(true); + + if (settingDebugAfterBoot) { + bDebugMBmsg = true; + bDebugRestAPI = true; + bDebugMQTT = true; + } if (settingRelayAllwaysOnSwitch) setRelay(RELAYON); else setRelay(RELAYOFF); @@ -80,6 +86,11 @@ void setup() Serial.println(F("Attempting to connect to WiFi network\r")); + + //setup NTP before connecting to wifi will enable DHCP to overrule the NTP setting + startNTP(); + + setLed(LED1, ON); startWiFi(CSTR(settingHostname), 240); // timeout 240 seconds blinkLED(LED1, 3, 100); @@ -90,7 +101,6 @@ void setup() startMDNS(CSTR(settingHostname)); startLLMNR(CSTR(settingHostname)); startMQTT(); - startNTP(); setupFSexplorer(); startWebserver(); @@ -100,11 +110,12 @@ void setup() while (settingTimebasedSwitch && settingNTPenable && (NtpStatus != TIME_SYNC)) { loopNTP(); // Make sure time is set + // delayms(1000) ; } // log last reset reason after all above has started lastReset = ESP.getResetReason(); - DebugTf("Last reset reason: [%s]\r\n", CSTR(ESP.getResetReason())); + DebugTf(PSTR("Last reset reason: [%s]\r\n"), CSTR(ESP.getResetReason())); rebootCount = updateRebootCount(); // updateRebootLog(ESP.getResetReason()); updateRebootLog("Startup"); @@ -123,7 +134,7 @@ void setup() if (WiFi.status() != WL_CONNECTED) { //disconnected, try to reconnect then... - DebugTln("Wifi not Connected !!! Restart Wifi"); + DebugTln(F("Wifi not Connected !!! Restart Wifi")); reconnectWiFiCount++; restartWiFi(CSTR(settingHostname), 240); MDNS.update(); @@ -136,8 +147,8 @@ void setup() if (pinger.Ping(WiFi.gatewayIP(), 1) == false) { - DebugTf("Pinging default gateway with IP %s, FAILED\n", WiFi.gatewayIP().toString().c_str()); - DebugTln("Error during last ping command. Restart Wifi"); + DebugTf(PSTR("Pinging default gateway with IP %s, FAILED\n"), WiFi.gatewayIP().toString().c_str()); + DebugTln(F("Error during last ping command. Restart Wifi")); restartWiFiCount++; if (restartWiFiCount > 5) { @@ -151,7 +162,7 @@ void setup() startTelnet(); } - Debugf("Reboot count = [%d]\r\n", rebootCount); + Debugf(PSTR("Reboot count = [%d]\r\n"), rebootCount); Debugln(F("Setup finished!")); //Blink LED2 to signal setup done @@ -251,7 +262,7 @@ void doTaskEvery60s(){ if(pinger.Ping(WiFi.gatewayIP(),1) == false) { - DebugTf("Pinging default gateway with IP %s, FAILED\n", WiFi.gatewayIP().toString().c_str()); + DebugTf(PSTR("Pinging default gateway with IP %s, FAILED\n"), WiFi.gatewayIP().toString().c_str()); DebugTln("Error during last ping command. Restart Wifi"); restartWiFiCount++ ; if (restartWiFiCount > 5) { diff --git a/ModbusStuff.h b/ModbusStuff.h index f3b8119..3cca88e 100644 --- a/ModbusStuff.h +++ b/ModbusStuff.h @@ -3,7 +3,7 @@ ** Program : Header file: ModbusStuff.h ** Version 1.9.1 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** diff --git a/ModbusStuff.ino b/ModbusStuff.ino index b2a279e..1403aef 100644 --- a/ModbusStuff.ino +++ b/ModbusStuff.ino @@ -1,9 +1,9 @@ /* *************************************************************************** ** Program : ModbusStuff -** Version 1.8.1 +** Version 1.10.0 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -60,7 +60,7 @@ uint32_t cfuint32(uint16_t u1, uint16_t u2) void setupModbus() { - if (bDebugMBmsg) Debugf("Init Serial with baudrate:\r\n"); + if (bDebugMBmsg) Debugf(PSTR("Init Serial with baudrate:\r\n")); if (bDebugMBmsg) Debugln(settingModbusBaudrate); #if defined(ESP8266) @@ -77,7 +77,7 @@ void setupModbus() #endif mb.master(); - DebugTf("Modbus Serial init completed\r\n"); + DebugTf(PSTR("Modbus Serial init completed\r\n")); } void waitMBslave() { while (mb.slave()) @@ -89,12 +89,12 @@ void waitMBslave() { void MBtestreadHreg(uint16_t MBmapidx, uint16_t MBaddress, uint16_t value[], uint16_t numregs) { - DebugTf("Args MBtestreadHreg MBmapidx[%d], MBaddress[%d] , .address[%d], numregs[%d]\r\n ",MBmapidx, MBaddress, Modbusmap[MBmapidx].address,numregs); + DebugTf(PSTR("Args MBtestreadHreg MBmapidx[%d], MBaddress[%d] , .address[%d], numregs[%d]\r\n "),MBmapidx, MBaddress, Modbusmap[MBmapidx].address,numregs); ModbusdataObject.LastResult = 0; switch (Modbusmap[MBmapidx].regformat) { case Modbus_short: - if (numregs != 1) { DebugTln("ERROR numregs read for short should be 1"); break; } + if (numregs != 1) { DebugTln(F("ERROR numregs read for short should be 1")); break; } switch (Modbusmap[MBmapidx].address) { case 1: @@ -108,7 +108,7 @@ void MBtestreadHreg(uint16_t MBmapidx, uint16_t MBaddress, uint16_t value[], uin } break; case Modbus_ushort: - if (numregs != 1) { DebugTln("ERROR numregs read for ushort should be 1"); break; } + if (numregs != 1) { DebugTln(F("ERROR numregs read for ushort should be 1")); break; } switch (Modbusmap[MBmapidx].address) { case 3: @@ -122,7 +122,7 @@ void MBtestreadHreg(uint16_t MBmapidx, uint16_t MBaddress, uint16_t value[], uin } break; case Modbus_int: - if (numregs != 2) { DebugTln("ERROR numregs read for int should be 2"); break; } + if (numregs != 2) { DebugTln(F("ERROR numregs read for int should be 2")); break; } switch (Modbusmap[MBmapidx].address) { case 5: @@ -139,7 +139,7 @@ void MBtestreadHreg(uint16_t MBmapidx, uint16_t MBaddress, uint16_t value[], uin } break; case Modbus_uint: - if (numregs != 2) { DebugTln("ERROR numregs read for uint should be 2"); break;} + if (numregs != 2) { DebugTln(F("ERROR numregs read for uint should be 2")); break;} switch (Modbusmap[MBmapidx].address) { case 7: @@ -156,7 +156,7 @@ void MBtestreadHreg(uint16_t MBmapidx, uint16_t MBaddress, uint16_t value[], uin } break; case Modbus_float: - if (numregs != 2) { DebugTln("ERROR numregs read for float should be 2"); } + if (numregs != 2) { DebugTln(F("ERROR numregs read for float should be 2")); } switch (Modbusmap[MBmapidx].address) { case 9: @@ -179,7 +179,7 @@ void MBtestreadHreg(uint16_t MBmapidx, uint16_t MBaddress, uint16_t value[], uin } break; } - // DebugTf("########## MBmapidx[%d] Value0[%d] value1[]\r\n",MBmapidx,value[0],value[1]) ; + // DebugTf(PSTR("########## MBmapidx[%d] Value0[%d] value1[]\r\n"),MBmapidx,value[0],value[1]) ; } //============ Read register functions V2 (short ) @@ -199,16 +199,16 @@ bool Modbus_Read_short(uint16_t i) if (ModbusdataObject.LastResult == 0) { - // determine value from multiple registers for (int i = 0 ; i < 1 ; i++) { Debugf("Reg: %d, Val: %d \r\n", i+readreg, shortres[i]); } + // determine value from multiple registers for (int i = 0 ; i < 1 ; i++) { Debugf(PSTR("Reg: %d, Val: %d \r\n"), i+readreg, shortres[i]); } mb_convert.mb_uint16 = shortres[0] ; - if (bDebugMBlogic) DebugTf("shortres[%d] md_uint16 [%d] md_int16 [%d]\r\n",shortres[0], mb_convert.mb_uint16, mb_convert.mb_int16 ); + if (bDebugMBlogic) DebugTf(PSTR("shortres[%d] md_uint16 [%d] md_int16 [%d]\r\n"),shortres[0], mb_convert.mb_uint16, mb_convert.mb_int16 ); // Convert when factor is set other than 1 if (Modbusmap[i].factor != 1) Modbusmap[i].Modbus_short = round(mb_convert.mb_int16 * Modbusmap[i].factor); else Modbusmap[i].Modbus_short = mb_convert.mb_int16; if (bDebugMBmsg) - DebugTf("Modbus Read short Reg:[%d] , Result:[%d]\r\n", Modbusmap[i].address, Modbusmap[i].Modbus_short); + DebugTf(PSTR("Modbus Read short Reg:[%d] , Result:[%d]\r\n"), Modbusmap[i].address, Modbusmap[i].Modbus_short); if (settingMQTTenable && Modbusmap[i].mqenable == 1) { toMQTT_short(i); @@ -216,14 +216,14 @@ bool Modbus_Read_short(uint16_t i) } else { - DebugTf("Modbus Read short Reg:[%d] , Result: 0x%02X \r\n", Modbusmap[i].address, ModbusdataObject.LastResult); + DebugTf(PSTR("Modbus Read short Reg:[%d] , Result: 0x%02X \r\n"), Modbusmap[i].address, ModbusdataObject.LastResult); tempError = true; } } else { // this should never happen - DebugTln("Error: Modbus Read while transaction active"); + DebugTln(F("Error: Modbus Read while transaction active")); ModbusdataObject.LastResult = 99; } @@ -246,15 +246,15 @@ bool Modbus_Read_ushort(uint16_t i) if (ModbusdataObject.LastResult == 0) { - // determine value from multiple registers for (int i = 0 ; i < 1 ; i++) { Debugf("Reg: %d, Val: %d \r\n", i+readreg, shortres[i]); } - if (bDebugMBlogic) DebugTf("ushortres0[%d] \r\n",ushortres[0]); + // determine value from multiple registers for (int i = 0 ; i < 1 ; i++) { Debugf(PSTR("Reg: %d, Val: %d \r\n"), i+readreg, shortres[i]); } + if (bDebugMBlogic) DebugTf(PSTR("ushortres0[%d] \r\n"),ushortres[0]); // Convert when factor is set other than 1 if (Modbusmap[i].factor != 1) Modbusmap[i].Modbus_ushort = round(ushortres[0] * Modbusmap[i].factor); else Modbusmap[i].Modbus_ushort = ushortres[0]; if (bDebugMBmsg) - DebugTf("Modbus Read ushort Reg:[%d] , Result:[%u]\r\n", Modbusmap[i].address, Modbusmap[i].Modbus_ushort); + DebugTf(PSTR("Modbus Read ushort Reg:[%d] , Result:[%u]\r\n"), Modbusmap[i].address, Modbusmap[i].Modbus_ushort); if (settingMQTTenable && Modbusmap[i].mqenable == 1) { toMQTT_ushort(i); @@ -262,14 +262,14 @@ bool Modbus_Read_ushort(uint16_t i) } else { - DebugTf("Modbus Read ushort Reg:[%d] , Result: 0x%02X \r\n", Modbusmap[i].address, ModbusdataObject.LastResult); + DebugTf(PSTR("Modbus Read ushort Reg:[%d] , Result: 0x%02X \r\n"), Modbusmap[i].address, ModbusdataObject.LastResult); tempError = true; } } else { // this should never happen - DebugTln("Error: Modbus Read while transaction active"); + DebugTln(F("Error: Modbus Read while transaction active")); ModbusdataObject.LastResult = 99; } @@ -292,16 +292,16 @@ bool Modbus_Read_int(uint16_t i) if (ModbusdataObject.LastResult == 0) { - // determine value from multiple registers for (int i = 0 ; i < 1 ; i++) { Debugf("Reg: %d, Val: %d \r\n", i+readreg, shortres[i]); } + // determine value from multiple registers for (int i = 0 ; i < 1 ; i++) { Debugf(PSTR("Reg: %d, Val: %d \r\n"), i+readreg, shortres[i]); } tempint = cfint32(intres[0], intres[1]); - if (bDebugMBlogic) DebugTf("intres0[%d] intres1[%d] tempint[%d]\r\n",intres[0], intres[1], tempint ); + if (bDebugMBlogic) DebugTf(PSTR("intres0[%d] intres1[%d] tempint[%d]\r\n"),intres[0], intres[1], tempint ); // Convert when factor is set other than 1 if (Modbusmap[i].factor != 1) Modbusmap[i].Modbus_int = round(tempint * Modbusmap[i].factor); else Modbusmap[i].Modbus_int = tempint; if (bDebugMBmsg) - DebugTf("Modbus Read int Reg:[%d] , Result:[%d]\r\n", Modbusmap[i].address, Modbusmap[i].Modbus_int); + DebugTf(PSTR("Modbus Read int Reg:[%d] , Result:[%d]\r\n"), Modbusmap[i].address, Modbusmap[i].Modbus_int); if (settingMQTTenable && Modbusmap[i].mqenable == 1) { toMQTT_int(i); @@ -309,14 +309,14 @@ bool Modbus_Read_int(uint16_t i) } else { - DebugTf("Modbus Read int Reg:[%d] , Result: 0x%02X \r\n", Modbusmap[i].address, ModbusdataObject.LastResult); + DebugTf(PSTR("Modbus Read int Reg:[%d] , Result: 0x%02X \r\n"), Modbusmap[i].address, ModbusdataObject.LastResult); tempError = true; } } else { // this should never happen - DebugTln("Error: Modbus Read while transaction active"); + DebugTln(PSTR("Error: Modbus Read while transaction active")); ModbusdataObject.LastResult = 99; } @@ -339,16 +339,16 @@ bool Modbus_Read_uint(uint16_t i) if (ModbusdataObject.LastResult == 0) { - // determine value from multiple registers for (int i = 0 ; i < 1 ; i++) { Debugf("Reg: %d, Val: %d \r\n", i+readreg, shortres[i]); } + // determine value from multiple registers for (int i = 0 ; i < 1 ; i++) { Debugf(PSTR("Reg: %d, Val: %d \r\n"), i+readreg, shortres[i]); } tempuint = cfuint32(uintres[0], uintres[1]); - if (bDebugMBlogic) DebugTf("uintres0[%d] uintres1[%d] tempuint[%d]\r\n",uintres[0], uintres[1], tempuint ); + if (bDebugMBlogic) DebugTf(PSTR("uintres0[%d] uintres1[%d] tempuint[%d]\r\n"),uintres[0], uintres[1], tempuint ); // Convert when factor is set other than 1 if (Modbusmap[i].factor != 1) Modbusmap[i].Modbus_uint = round(tempuint * Modbusmap[i].factor); else Modbusmap[i].Modbus_uint = tempuint; if (bDebugMBmsg) - DebugTf("Modbus Read uint Reg:[%d] , Result:[%u]\r\n", Modbusmap[i].address, Modbusmap[i].Modbus_uint); + DebugTf(PSTR("Modbus Read uint Reg:[%d] , Result:[%u]\r\n"), Modbusmap[i].address, Modbusmap[i].Modbus_uint); if (settingMQTTenable && Modbusmap[i].mqenable == 1) { @@ -357,14 +357,14 @@ bool Modbus_Read_uint(uint16_t i) } else { - DebugTf("Modbus Read uint Reg:[%d] , Result: 0x%02X \r\n", Modbusmap[i].address, ModbusdataObject.LastResult); + DebugTf(PSTR("Modbus Read uint Reg:[%d] , Result: 0x%02X \r\n"), Modbusmap[i].address, ModbusdataObject.LastResult); tempError = true; } } else { // this should never happen - DebugTln("Error: Modbus Read while transaction active"); + DebugTln(PSTR("Error: Modbus Read while transaction active")); ModbusdataObject.LastResult = 99; } @@ -387,16 +387,16 @@ bool Modbus_Read_float(uint16_t i) if (ModbusdataObject.LastResult == 0) { - // determine value from multiple registers for (int i = 0 ; i < 1 ; i++) { Debugf("Reg: %d, Val: %d \r\n", i+readreg, shortres[i]); } + // determine value from multiple registers for (int i = 0 ; i < 1 ; i++) { Debugf(PSTR("Reg: %d, Val: %d \r\n"), i+readreg, shortres[i]); } tempfloat = cf32(floatres[0], floatres[1]); - if (bDebugMBlogic) DebugTf("floatres0[%d] floatres1[%d] tempfloat[%f]\r\n",floatres[0], floatres[1], tempfloat ); + if (bDebugMBlogic) DebugTf(PSTR("floatres0[%d] floatres1[%d] tempfloat[%f]\r\n"),floatres[0], floatres[1], tempfloat ); // Convert when factor is set other than 1 if (Modbusmap[i].factor != 1) Modbusmap[i].Modbus_float = tempfloat * Modbusmap[i].factor; else Modbusmap[i].Modbus_float = tempfloat; if (bDebugMBmsg) - DebugTf("Modbus Read float Reg:[%d] , Result:[%f]\r\n", Modbusmap[i].address, Modbusmap[i].Modbus_float); + DebugTf(PSTR("Modbus Read float Reg:[%d] , Result:[%f]\r\n"), Modbusmap[i].address, Modbusmap[i].Modbus_float); if (settingMQTTenable && Modbusmap[i].mqenable == 1) { @@ -405,14 +405,14 @@ bool Modbus_Read_float(uint16_t i) } else { - DebugTf("Modbus Read float Reg:[%d] , Result: 0x%02X \r\n", Modbusmap[i].address, ModbusdataObject.LastResult); + DebugTf(PSTR("Modbus Read float Reg:[%d] , Result: 0x%02X \r\n"), Modbusmap[i].address, ModbusdataObject.LastResult); tempError = true; } } else { // this should never happen - DebugTln("Error: Modbus Read while transaction active"); + DebugTln(F("Error: Modbus Read while transaction active")); ModbusdataObject.LastResult = 99; } @@ -430,7 +430,7 @@ bool Modbus_Read_string(uint16_t i) // char mb_charconv[32]; // } mb_reg2char ; - if (bDebugMBlogic) DebugTf("Modbus_Read_string Number of registers[%d]\r\n",numregs); + if (bDebugMBlogic) DebugTf(PSTR("Modbus_Read_string Number of registers[%d]\r\n"),numregs); if (!mb.slave()) { @@ -441,7 +441,7 @@ bool Modbus_Read_string(uint16_t i) if (ModbusdataObject.LastResult == 0) { - // determine value from multiple registers for (int r = 0 ; r < count ; r++) { Debugf("Reg: %d, Val: %d \r\n", r+readreg, shortres[r]); } + // determine value from multiple registers for (int r = 0 ; r < count ; r++) { Debugf(PSTR("Reg: %d, Val: %d \r\n"), r+readreg, shortres[r]); } char *ctemp = new char[Modbusmap[i].formatstringlen + 1]; if (settingModbusByteswap) { for (int r = 0; r < Modbusmap[i].formatstringlen ; r=r+2) { @@ -454,7 +454,7 @@ bool Modbus_Read_string(uint16_t i) delete ctemp; if (bDebugMBmsg) - DebugTf("Modbus Read string Reg:[%d] , Result:[%s]\r\n", Modbusmap[i].address, CSTR(Modbusmap[i].Modbus_string)); + DebugTf(PSTR("Modbus Read string Reg:[%d] , Result:[%s]\r\n"), Modbusmap[i].address, CSTR(Modbusmap[i].Modbus_string)); if (settingMQTTenable && Modbusmap[i].mqenable == 1) { toMQTT_string(i); @@ -462,14 +462,14 @@ bool Modbus_Read_string(uint16_t i) } else { - DebugTf("Modbus Read string Reg:[%d] , Result: 0x%02X \r\n", Modbusmap[i].address, ModbusdataObject.LastResult); + DebugTf(PSTR("Modbus Read string Reg:[%d] , Result: 0x%02X \r\n"), Modbusmap[i].address, ModbusdataObject.LastResult); tempError = true; } } else { // this should never happen - DebugTln("Error: Modbus Read while transaction active"); + DebugTln(F("Error: Modbus Read while transaction active")); ModbusdataObject.LastResult = 99; } @@ -487,7 +487,7 @@ void toMQTT_short(int id) char _msg[15]{0}; itoa(_value, _msg, 10); if (bDebugMBmsg) - DebugTf("To MQTT_short %s %s %s\r\n", Modbusmap[id].label, _msg, Modbusmap[id].unit); + DebugTf(PSTR("To MQTT_short %s %s %s\r\n"), Modbusmap[id].label, _msg, Modbusmap[id].unit); //SendMQTT sendMQTTData(Modbusmap[id].label, _msg); } @@ -499,7 +499,7 @@ void toMQTT_ushort(int id) char _msg[15]{0}; itoa(_value, _msg, 10); if (bDebugMBmsg) - DebugTf("To MQTT_short %s %s %s\r\n", Modbusmap[id].label, _msg, Modbusmap[id].unit); + DebugTf(PSTR("To MQTT_short %s %s %s\r\n"), Modbusmap[id].label, _msg, Modbusmap[id].unit); //SendMQTT sendMQTTData(Modbusmap[id].label, _msg); } @@ -511,7 +511,7 @@ void toMQTT_int(int id) char _msg[15]{0}; itoa(_value, _msg, 10); if (bDebugMBmsg) - DebugTf("To MQTT_short %s %s %s\r\n", Modbusmap[id].label, _msg, Modbusmap[id].unit); + DebugTf(PSTR("To MQTT_short %s %s %s\r\n"), Modbusmap[id].label, _msg, Modbusmap[id].unit); //SendMQTT sendMQTTData(Modbusmap[id].label, _msg); } @@ -523,7 +523,7 @@ void toMQTT_uint(int id) char _msg[15]{0}; itoa(_value, _msg, 10); if (bDebugMBmsg) - DebugTf("To MQTT_short %s %s %s\r\n", Modbusmap[id].label, _msg, Modbusmap[id].unit); + DebugTf(PSTR("To MQTT_short %s %s %s\r\n"), Modbusmap[id].label, _msg, Modbusmap[id].unit); //SendMQTT sendMQTTData(Modbusmap[id].label, _msg); } @@ -535,7 +535,7 @@ void toMQTT_float(int id) char _msg[15]{0}; dtostrf(_value, 3, 2, _msg); - if (bDebugMBmsg) DebugTf("To MQTT_float %s %s %s\r\n", Modbusmap[id].label, _msg, Modbusmap[id].unit); + if (bDebugMBmsg) DebugTf(PSTR("To MQTT_float %s %s %s\r\n"), Modbusmap[id].label, _msg, Modbusmap[id].unit); //SendMQTT sendMQTTData(Modbusmap[id].label, _msg); @@ -545,7 +545,7 @@ void toMQTT_string(int id) { //function to push string data to MQTT - if (bDebugMBmsg) DebugTf("To MQTT_string %s %s %s\r\n", Modbusmap[id].label, CSTR(Modbusmap[id].Modbus_string)); + if (bDebugMBmsg) DebugTf(PSTR("To MQTT_string %s %s %s\r\n"), Modbusmap[id].label, CSTR(Modbusmap[id].Modbus_string)); //SendMQTT sendMQTTData(Modbusmap[id].label, CSTR(Modbusmap[id].Modbus_string)); @@ -573,9 +573,9 @@ void Modbus2MQTT() { case Modbus_string: toMQTT_string(i); break; case Modbus_undef: - DebugTf("ERROR: MQTT Not implemented for %d = %s \r\n", i, Modbusmap[i].label); break; + DebugTf(PSTR("ERROR: MQTT Not implemented for %d = %s \r\n"), i, Modbusmap[i].label); break; default: - DebugTf("ERROR: MQTT Error undef type %d = %s \r\n", i, Modbusmap[i].label); break; + DebugTf(PSTR("ERROR: MQTT Error undef type %d = %s \r\n"), i, Modbusmap[i].label); break; } } } @@ -613,10 +613,10 @@ void readModbus() case Modbus_string: if (Modbus_Read_string(i)) countError++; break; case Modbus_undef: - DebugTf("ERROR: undef type %d = %s \r\n", i, Modbusmap[i].label); + DebugTf(PSTR("ERROR: undef type %d = %s \r\n"), i, Modbusmap[i].label); break; default: - DebugTf("ERROR: undef type %d = %s \r\n", i, Modbusmap[i].label); + DebugTf(PSTR("ERROR: undef type %d = %s \r\n"), i, Modbusmap[i].label); break; } } @@ -625,7 +625,7 @@ void readModbus() if (countError > 0) { - DebugTf("readModbus ended with errors count[%d] FreeHeap:[%d] \r\n", countError, ESP.getFreeHeap()); + DebugTf(PSTR("readModbus ended with errors count[%d] FreeHeap:[%d] \r\n"), countError, ESP.getFreeHeap()); } if (settingLEDblink) blinkLEDnow(LED1); @@ -634,7 +634,7 @@ void readModbus() void readModbusSetup() { - if (bDebugMBmsg) Debugf("readModbus2 started\r\n"); + if (bDebugMBmsg) Debugf(PSTR("readModbus2 started\r\n")); uint16_t offset = 0; uint16_t count = 8; @@ -645,19 +645,28 @@ void readModbusSetup() mb.readHreg(settingModbusSlaveAdr, offset, resval, count, cb); // Send Read Hreg from Modbus Server while(mb.slave()) { // Check if transaction is active - // Debugf("readModbus slave true\r\n"); + // Debugf(PSTR("readModbus slave true\r\n")); mb.task(); delay(10); } - Debugf("readModbus2 result\r\n"); + Debugf(PSTR("readModbus2 result\r\n")); for (int i = 0 ; i < count ; i++) { - Debugf("Reg: %d, Val: %d \r\n", i+offset, resval[i]); + Debugf(PSTR("Reg: %d, Val: %d \r\n"), i+offset, resval[i]); // Debugln(resval[i]); } } - if (bDebugMBmsg) Debugf("readModbus ended \r\n"); + if (bDebugMBmsg) Debugf(PSTR("readModbus ended \r\n")); } +void processMQcommand(const char* buf, int len) +// analyse the incomming MQ command and process +{ + + DebugTf(PSTR("processMQcommand")); + if (bDebugMQTT) DebugTf(PSTR("processMQcommand len: [%s] buf: [%s]\r\n"), len, buf); + + +} void sendModbus(const char* buf, int len) { @@ -665,10 +674,10 @@ void sendModbus(const char* buf, int len) // Needs to be Mudbus RTU !!! // - if (bDebugMBmsg) DebugTf("sendModbus len: [%s] buf: [%s]\r\n", len, buf); + if (bDebugMBmsg) DebugTf(PSTR("sendModbus len: [%s] buf: [%s]\r\n"), len, buf); // if (Serial) { // //check the write buffer - // Debugf("Serial Write Buffer space = [%d] - needed [%d]\r\n",Serial.availableForWrite(), (len+2)); + // Debugf(PSTR("Serial Write Buffer space = [%d] - needed [%d]\r\n"),Serial.availableForWrite(), (len+2)); // DebugT("Sending to Serial ["); // for (int i = 0; i < len; i++) { // Debug((char)buf[i]); @@ -720,11 +729,11 @@ void sendModbus(const char* buf, int len) if (sLine.startsWith("#") || sLine.startsWith("//")) { - if (bDebugMBmsg) DebugTf("Either comment or invalid config line: [%s]\r\n", sLine.c_str()); + if (bDebugMBmsg) DebugTf(PSTR("Either comment or invalid config line: [%s]\r\n"), sLine.c_str()); } else { - if (bDebugMBmsg) DebugTf("sline[%s]\r\n", sLine.c_str()); + if (bDebugMBmsg) DebugTf(PSTR("sline[%s]\r\n"), sLine.c_str()); // #file format is CSV, all values as string without "", fields are // #day, starthour, startmin, endhour, endmin // #day = daynumber, Numeric representation of the day of the week(1 = Sunday) @@ -738,14 +747,14 @@ void sendModbus(const char* buf, int len) Index3 = sLine.indexOf(',', Index2 + 1); Index4 = sLine.indexOf(',', Index3 + 1); if (bDebugMBmsg) - DebugTf("Index1[%d],Index2[%d],Index3[%d],Index4[%d]\r\n", Index1, Index2, Index3, Index4); + DebugTf(PSTR("Index1[%d],Index2[%d],Index3[%d],Index4[%d]\r\n"), Index1, Index2, Index3, Index4); if (Index4 <= 0) { if (bDebugMBmsg) { - DebugTf("Index1[%d],Index2[%d],Index3[%d],Index4[%d]\r\n", Index1, Index2, Index3, Index4); - DebugTln("ERROR: Missing parameters in Daytimemap, skip line"); + DebugTf(PSTR("Index1[%d],Index2[%d],Index3[%d],Index4[%d]\r\n"), Index1, Index2, Index3, Index4); + DebugTln(PSTR("ERROR: Missing parameters in Daytimemap, skip line")); } break; } @@ -762,13 +771,13 @@ void sendModbus(const char* buf, int len) sEndhour.trim(); sEndmin.trim(); - if (bDebugMBmsg) { DebugTf("sDay[%s], sStarthour[%s], sStartmin[%s], sEndhour[%s], sEndmin[%s]\r\n", sDay.c_str(), sStarthour.c_str(), sStartmin.c_str(), sEndhour.c_str(), sEndmin.c_str()); + if (bDebugMBmsg) { DebugTf(PSTR("sDay[%s], sStarthour[%s], sStartmin[%s], sEndhour[%s], sEndmin[%s]\r\n"), sDay.c_str(), sStarthour.c_str(), sStartmin.c_str(), sEndhour.c_str(), sEndmin.c_str()); delay(10); } daynum = sDay.toInt(); if (daynum >7 || daynum != id ) { - DebugTf("DAYNUM NOT IN SEQUENCE sDay[%s], sStarthour[%s], sStartmin[%s], sEndhour[%s], sEndmin[%s]\r\n", sDay.c_str(), sStarthour.c_str(), sStartmin.c_str(), sEndhour.c_str(), sEndmin.c_str()); + DebugTf(PSTR("DAYNUM NOT IN SEQUENCE sDay[%s], sStarthour[%s], sStartmin[%s], sEndhour[%s], sEndmin[%s]\r\n"), sDay.c_str(), sStarthour.c_str(), sStartmin.c_str(), sEndhour.c_str(), sEndmin.c_str()); } else { @@ -782,7 +791,7 @@ void sendModbus(const char* buf, int len) } } // while available() - if (bDebugMBmsg) DebugTf("Number of Daytimemap registers initialized:, %d \r\n", id-1); + if (bDebugMBmsg) DebugTf(PSTR("Number of Daytimemap registers initialized:, %d \r\n"), id-1); fh.close(); } } @@ -790,11 +799,11 @@ void sendModbus(const char* buf, int len) //=========================================================================================== void printDaytimemap() { - if (bDebugMBmsg) DebugTf("printDaytimemap begin for: %d, records \r\n",7); + if (bDebugMBmsg) DebugTf(PSTR("printDaytimemap begin for: %d, records \r\n"),7); for (int i = 1; i <= 7; i++) { - // DebugTf("Day: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n", dayStr(Daytimemap[i].day).c_str(), Daytimemap[i].starthour, Daytimemap[i].startmin, Daytimemap[i].endhour, Daytimemap[i].endmin); - DebugTf("Day: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n", dayStr(Daytimemap[i].day), Daytimemap[i].starthour, Daytimemap[i].startmin, Daytimemap[i].endhour, Daytimemap[i].endmin); + // DebugTf(PSTR("Day: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[i].day).c_str(), Daytimemap[i].starthour, Daytimemap[i].startmin, Daytimemap[i].endhour, Daytimemap[i].endmin); + DebugTf(PSTR("Day: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[i].day), Daytimemap[i].starthour, Daytimemap[i].startmin, Daytimemap[i].endhour, Daytimemap[i].endmin); } Debugln(); @@ -807,7 +816,7 @@ void sendModbus(const char* buf, int len) String cfgFilename = "/" + settingModbusCfgfile ; // const char* cfgFilename = "/" + settingModbusCfgfile; if (bDebugMBlogic) cfgFilename = "/Modbusmaptest.cfg" ; - DebugTf("Modbusmap config file[%s]\r\n",CSTR(settingModbusCfgfile)); + DebugTf(PSTR("Modbusmap config file[%s]\r\n"),CSTR(settingModbusCfgfile)); // Comment lines start with # or // // Configuration file to map modbus registers @@ -862,9 +871,9 @@ void sendModbus(const char* buf, int len) if (sLine.startsWith("#") || sLine.startsWith("//") ) { - if (bDebugMBmsg) DebugTf("INFO: Either comment or invalid config line: [%s]\r\n", sLine.c_str()); + if (bDebugMBmsg) DebugTf(PSTR("INFO: Either comment or invalid config line: [%s]\r\n"), sLine.c_str()); } else { - if (bDebugMBmsg) DebugTf("sline[%s]\r\n", sLine.c_str()); + if (bDebugMBmsg) DebugTf(PSTR("sline[%s]\r\n"), sLine.c_str()); // reg, format, type, label, friendlyname, devclass, stateclass, unit, phase, mqenable Index1 = sLine.indexOf(','); Index2 = sLine.indexOf(',', Index1 + 1); @@ -876,13 +885,13 @@ void sendModbus(const char* buf, int len) Index8 = sLine.indexOf(',', Index7 + 1); Index9 = sLine.indexOf(',', Index8 + 1); Index10 = sLine.indexOf(',', Index9 + 1); - if (bDebugMBmsg) DebugTf("Index1[%d],Index2[%d],Index3[%d],Index4[%d],Index5[%d],Index6[%d],Index7[%d],Index8[%d],Index9[%d],Index10[%d]\r\n", Index1, Index2, Index3, Index4, Index5, Index6, Index7, Index8, Index9, Index10); + if (bDebugMBmsg) DebugTf(PSTR("Index1[%d],Index2[%d],Index3[%d],Index4[%d],Index5[%d],Index6[%d],Index7[%d],Index8[%d],Index9[%d],Index10[%d]\r\n"), Index1, Index2, Index3, Index4, Index5, Index6, Index7, Index8, Index9, Index10); if (Index10 <= 0) { if (bDebugMBmsg) { - DebugTf("Index1[%d],Index2[%d],Index3[%d],Index4[%d],Index5[%d],Index6[%d],Index7[%d],Index8[%d],Index9[%d],Index10[%d]\r\n", Index1, Index2, Index3, Index4, Index5, Index6, Index7, Index8, Index9,Index10); - DebugTln("ERROR: Missing parameters in config line, skip line"); + DebugTf(PSTR("Index1[%d],Index2[%d],Index3[%d],Index4[%d],Index5[%d],Index6[%d],Index7[%d],Index8[%d],Index9[%d],Index10[%d]\r\n"), Index1, Index2, Index3, Index4, Index5, Index6, Index7, Index8, Index9,Index10); + DebugTln(PSTR("ERROR: Missing parameters in config line, skip line")); } break; } @@ -910,7 +919,7 @@ void sendModbus(const char* buf, int len) sFactor.trim(); sMQEnable.trim(); if (bDebugMBmsg) { - DebugTf("sReg[%s], sFormat[%s], sRegoper[%s], sLabel[%s], sName[%s], sDeviceclass[%s], sStateclass[%s] , sUnit[%s], sPhase[%s], sFactor[%s], sMQEnable[%s]\r\n", sReg.c_str(), sFormat.c_str(), sOper.c_str(), sLabel.c_str(), sName.c_str(), sDevclass.c_str(), sStateclass.c_str(), sUnit.c_str(), sPhase.c_str(),sFactor.c_str(),sMQEnable.c_str()); + DebugTf(PSTR("sReg[%s], sFormat[%s], sRegoper[%s], sLabel[%s], sName[%s], sDeviceclass[%s], sStateclass[%s] , sUnit[%s], sPhase[%s], sFactor[%s], sMQEnable[%s]\r\n"), sReg.c_str(), sFormat.c_str(), sOper.c_str(), sLabel.c_str(), sName.c_str(), sDevclass.c_str(), sStateclass.c_str(), sUnit.c_str(), sPhase.c_str(),sFactor.c_str(),sMQEnable.c_str()); delay(10); } id++; @@ -920,7 +929,7 @@ void sendModbus(const char* buf, int len) else if (sOper == "Modbus_RW" ) { Modbusmap[id].oper = Modbus_RW ; } else { Modbusmap[id].oper = Modbus_UNDEF ; - if (bDebugMBmsg) DebugTln("WARNING: Not read or RW, Modbus_UNDEF"); + if (bDebugMBmsg) DebugTln(F("WARNING: Not read or RW, Modbus_UNDEF")); } if (sFormat == "Modbus_short" ) { Modbusmap[id].regformat = Modbus_short ; } @@ -935,29 +944,29 @@ void sendModbus(const char* buf, int len) if (Index2 > 0) { Modbusmap[id].regformat = Modbus_string; Formatcnt = sFormatcnt.toInt(); - if (bDebugMBmsg) DebugTf("Modbus_string detected, sFormat[%s], sFormatcnt[%s], length[%d]\r\n",CSTR(sFormat), CSTR(sFormatcnt),Formatcnt); + if (bDebugMBmsg) DebugTf(PSTR("Modbus_string detected, sFormat[%s], sFormatcnt[%s], length[%d]\r\n"),CSTR(sFormat), CSTR(sFormatcnt),Formatcnt); if (Formatcnt > 64 || Formatcnt == 0) { - DebugTf("sReg[%s], sFormat[%s], sRegoper[%s], sLabel[%s], sName[%s], sDeviceclass[%s], sStateclass[%s] , sUnit[%s], sPhase[%s], sFactor[%s], sMQEnable[%s]\r\n", sReg.c_str(), sFormat.c_str(), sOper.c_str(), sLabel.c_str(), sName.c_str(), sDevclass.c_str(), sStateclass.c_str(), sUnit.c_str(), sPhase.c_str(),sFactor.c_str(),sMQEnable.c_str()); - DebugTf("ERROR Modbus_string length[%d] outside allowed range\r\n",Formatcnt); + DebugTf(PSTR("sReg[%s], sFormat[%s], sRegoper[%s], sLabel[%s], sName[%s], sDeviceclass[%s], sStateclass[%s] , sUnit[%s], sPhase[%s], sFactor[%s], sMQEnable[%s]\r\n"), sReg.c_str(), sFormat.c_str(), sOper.c_str(), sLabel.c_str(), sName.c_str(), sDevclass.c_str(), sStateclass.c_str(), sUnit.c_str(), sPhase.c_str(),sFactor.c_str(),sMQEnable.c_str()); + DebugTf(PSTR("ERROR Modbus_string length[%d] outside allowed range\r\n"),Formatcnt); Formatcnt = 0; Modbusmap[id].regformat = Modbus_undef; } else if ((Formatcnt % 2) != 0) { - DebugTf("sReg[%s], sFormat[%s], sRegoper[%s], sLabel[%s], sName[%s], sDeviceclass[%s] , sStateclass[%s] , sUnit[%s], sPhase[%s], sFactor[%s], sMQEnable[%s]\r\n", sReg.c_str(), sFormat.c_str(), sOper.c_str(), sLabel.c_str(), sName.c_str(), sDevclass.c_str(), sStateclass.c_str(), sUnit.c_str(), sPhase.c_str(),sFactor.c_str(),sMQEnable.c_str()); - DebugTf("ERROR Modbus_string length[%d] not even\r\n",Formatcnt); + DebugTf(PSTR("sReg[%s], sFormat[%s], sRegoper[%s], sLabel[%s], sName[%s], sDeviceclass[%s] , sStateclass[%s] , sUnit[%s], sPhase[%s], sFactor[%s], sMQEnable[%s]\r\n"), sReg.c_str(), sFormat.c_str(), sOper.c_str(), sLabel.c_str(), sName.c_str(), sDevclass.c_str(), sStateclass.c_str(), sUnit.c_str(), sPhase.c_str(),sFactor.c_str(),sMQEnable.c_str()); + DebugTf(PSTR("ERROR Modbus_string length[%d] not even\r\n"),Formatcnt); Formatcnt = 0; Modbusmap[id].regformat = Modbus_undef; } } else { - DebugTf("WARNING: Modbus_string defined without lenght") ; + DebugTf(PSTR("WARNING: Modbus_string defined without lenght")) ; Modbusmap[id].regformat = Modbus_undef; } } else { Modbusmap[id].regformat = Modbus_undef; - if (bDebugMBmsg) DebugTln("WARNING: Modbus_undef detected"); + if (bDebugMBmsg) DebugTln(F("WARNING: Modbus_undef detected")); } } // assign values to Modbusmap @@ -1007,11 +1016,11 @@ void sendModbus(const char* buf, int len) } // while available() ModbusdataObject.NumberRegisters = id ; - if (bDebugMBmsg) DebugTf("INFO: Number of Modbus registers initialized:, %d \r\n", ModbusdataObject.NumberRegisters); + if (bDebugMBmsg) DebugTf(PSTR("INFO: Number of Modbus registers initialized:, %d \r\n"), ModbusdataObject.NumberRegisters); fh.close(); } - } else DebugTf("ERROR, Modbus configfile[%s] doesnt exist.\r\n",CSTR(cfgFilename)) ; + } else DebugTf(PSTR("ERROR, Modbus configfile[%s] doesnt exist.\r\n"),CSTR(cfgFilename)) ; } // help routines @@ -1026,24 +1035,24 @@ String getStringForModbusformat(int enum_val) } void printModbusmapln(int16_t i) { - Debugf("Id[%d] Reg[%d] Oper[%s] Format[%s] ", Modbusmap[i].id, Modbusmap[i].address, CSTR(getStringForModbusoper(Modbusmap[i].oper)), CSTR(getStringForModbusformat(Modbusmap[i].regformat))); + Debugf(PSTR("Id[%d] Reg[%d] Oper[%s] Format[%s] "), Modbusmap[i].id, Modbusmap[i].address, CSTR(getStringForModbusoper(Modbusmap[i].oper)), CSTR(getStringForModbusformat(Modbusmap[i].regformat))); switch (Modbusmap[i].regformat) { - case Modbus_short: Debugf("Value[%d]", Modbusmap[i].Modbus_short); break; - case Modbus_ushort: Debugf("Value[%d]", Modbusmap[i].Modbus_ushort); break; - case Modbus_int: Debugf("Value[%d]", Modbusmap[i].Modbus_int); break; - case Modbus_uint: Debugf("Value[%d]", Modbusmap[i].Modbus_uint); break; - case Modbus_float: Debugf("Value[%f]", Modbusmap[i].Modbus_float); break; - case Modbus_string: Debugf("Length[%d] Value[%s]",Modbusmap[i].formatstringlen, CSTR(Modbusmap[i].Modbus_string)); break; - case Modbus_undef: DebugTf("ERROR: undef type %d = %s \r\n", i, Modbusmap[i].label); break; - default: DebugTf("ERROR: undef type %d = %s \r\n", i, Modbusmap[i].label); break; + case Modbus_short: Debugf(PSTR("Value[%d]"), Modbusmap[i].Modbus_short); break; + case Modbus_ushort: Debugf(PSTR("Value[%d]"), Modbusmap[i].Modbus_ushort); break; + case Modbus_int: Debugf(PSTR("Value[%d]"), Modbusmap[i].Modbus_int); break; + case Modbus_uint: Debugf(PSTR("Value[%d]"), Modbusmap[i].Modbus_uint); break; + case Modbus_float: Debugf(PSTR("Value[%f]"), Modbusmap[i].Modbus_float); break; + case Modbus_string: Debugf(PSTR("Length[%d] Value[%s]"),Modbusmap[i].formatstringlen, CSTR(Modbusmap[i].Modbus_string)); break; + case Modbus_undef: DebugTf(PSTR("ERROR: undef type %d = %s \r\n"), i, Modbusmap[i].label); break; + default: DebugTf(PSTR("ERROR: undef type %d = %s \r\n"), i, Modbusmap[i].label); break; } - Debugf(" Label[%s] Name[%s] Phase[%d] ", Modbusmap[i].label, Modbusmap[i].friendlyname, Modbusmap[i].phase); - Debugf("Devclass[%s] Stateclass[%s] Unit[%s] Factor[%f] MQEnable[%d]\r\n", Modbusmap[i].devclass, Modbusmap[i].stateclass, Modbusmap[i].unit, Modbusmap[i].factor, Modbusmap[i].mqenable); + Debugf(PSTR(" Label[%s] Name[%s] Phase[%d] "), Modbusmap[i].label, Modbusmap[i].friendlyname, Modbusmap[i].phase); + Debugf(PSTR("Devclass[%s] Stateclass[%s] Unit[%s] Factor[%f] MQEnable[%d]\r\n"), Modbusmap[i].devclass, Modbusmap[i].stateclass, Modbusmap[i].unit, Modbusmap[i].factor, Modbusmap[i].mqenable); } void printModbusmap() { - Debugf("printModbusmap begin for: %d, records\r\n", ModbusdataObject.NumberRegisters) ; + Debugf(PSTR("printModbusmap begin for: %d, records\r\n"), ModbusdataObject.NumberRegisters) ; for (int i = 1; i <= ModbusdataObject.NumberRegisters ; i++) { printModbusmapln(i); } @@ -1069,14 +1078,14 @@ void checkactivateRelay(bool activaterelay) { loopNTP(); // Make sure time is set if (NtpStatus != TIME_SYNC) { - DebugTln("Warning: Time not synced, exit activate relay check"); + DebugTln(PSTR("Warning: Time not synced, exit activate relay check")); } else { - // DebugTf("Schedule for today: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n", dayStr(Daytimemap[weekday()].day).c_str(), Daytimemap[weekday()].starthour, Daytimemap[weekday()].startmin, Daytimemap[weekday()].endhour, Daytimemap[weekday()].endmin); - DebugTf("Schedule for today: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n", dayStr(Daytimemap[weekday()].day), Daytimemap[weekday()].starthour, Daytimemap[weekday()].startmin, Daytimemap[weekday()].endhour, Daytimemap[weekday()].endmin); + // DebugTf(PSTR("Schedule for today: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[weekday()].day).c_str(), Daytimemap[weekday()].starthour, Daytimemap[weekday()].startmin, Daytimemap[weekday()].endhour, Daytimemap[weekday()].endmin); + DebugTf(PSTR("Schedule for today: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[weekday()].day), Daytimemap[weekday()].starthour, Daytimemap[weekday()].startmin, Daytimemap[weekday()].endhour, Daytimemap[weekday()].endmin); if (tempsettingRelayOn && activaterelay) { - DebugTln("Warning: Relay Temporary On until next on cycle"); + DebugTln(PSTR("Warning: Relay Temporary On until next on cycle")); setRelay(RELAYON); } dagcurmin = hour() * 60 + minute(); @@ -1087,10 +1096,10 @@ void checkactivateRelay(bool activaterelay) { if (dagcurmin >= dagstartmin && dagcurmin < dagendmin) { - DebugTf("Tijd:%02d:%02d Binnen tijdslot, set relay on\r\n", hour(), minute()); + DebugTf(PSTR("Tijd:%02d:%02d Binnen tijdslot, set relay on\r\n"), hour(), minute()); if (tempsettingRelayOn) { tempsettingRelayOn = false ; // Turn the temporary on switch of at next cycle - DebugTln("Info: Relay Temporary On switch turned off"); + DebugTln(PSTR("Info: Relay Temporary On switch turned off")); } if (activaterelay && statusRelay == RELAYOFF) { setRelay(RELAYON); @@ -1098,7 +1107,7 @@ void checkactivateRelay(bool activaterelay) } else { - DebugTf("Tijd:%02d:%02d Buiten tijdslot, set relay off\r\n", hour(), minute()); + DebugTf(PSTR("Tijd:%02d:%02d Buiten tijdslot, set relay off\r\n"), hour(), minute()); if ((activaterelay && statusRelay == RELAYON) && !tempsettingRelayOn) setRelay(RELAYOFF); } } @@ -1106,10 +1115,10 @@ void checkactivateRelay(bool activaterelay) { if (dagcurmin >= dagstartmin || dagcurmin < dagendmin) { - DebugTf("Tijd:%02d:%02d Binnen tijdslot, set relay on\r\n", hour(), minute()); + DebugTf(PSTR("Tijd:%02d:%02d Binnen tijdslot, set relay on\r\n"), hour(), minute()); if (tempsettingRelayOn) { tempsettingRelayOn = false ; // Turn the temporary on switch of at next cycle - DebugTln("Info: Relay Temporary On switch turned off"); + DebugTln(PSTR("Info: Relay Temporary On switch turned off")); } if (activaterelay && statusRelay == RELAYOFF) { setRelay(RELAYON); @@ -1117,17 +1126,16 @@ void checkactivateRelay(bool activaterelay) } else { - DebugTf("Tijd:%02d:%02d Buiten tijdslot, set relay off\r\n", hour(), minute()); + DebugTf(PSTR("Tijd:%02d:%02d Buiten tijdslot, set relay off\r\n"), hour(), minute()); if ((activaterelay && statusRelay == RELAYON) && !tempsettingRelayOn) setRelay(RELAYOFF); } } if (settingRelayAllwaysOnSwitch) { - DebugTln("WARNING, Relay set to ON"); - DebugTln("WARNING, Relay set to ON"); + DebugTln(PSTR("#$#$# WARNING, Relay set to ON")); setRelay(RELAYON) ; } - if (activaterelay) DebugTf("statusRelay[%d]\r\n", statusRelay); + if (activaterelay) DebugTf(PSTR("statusRelay[%d]\r\n"), statusRelay); } } } @@ -1136,7 +1144,7 @@ void setRelay(uint8_t status) { pinMode(RELAY, OUTPUT); digitalWrite(RELAY, status); - if (bDebugMBmsg) DebugTf("INFO: Relay set to %d \r\n", status); + if (bDebugMBmsg) DebugTf(PSTR("INFO: Relay set to %d \r\n"), status); statusRelay = status; } diff --git a/README.md b/README.md index e5a3740..38163e0 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ Looking for the documentation?, see the Documentation folder (work in progress). | Version | Release notes | |-|-| +| 1.10.0 | Add on off command via MQ to switch relay and setting in UI for debug after boot | | 1.9.1 | Updated libraries, expanded errorlog to find reboot reason, relay allways on failed bug fixed, Wifi sleepmode off| | 1.9.0 | Breaking change , added stateclass to MQ Autoconfigure for HA , additional parameter in Modbusmap.cfg see examples| | 1.8.1 | Implement a bootlog to register reboot reason and debug info, copied from rlagerweij
Changed: removed ezTime NTP library, moved to ConfigTime NTP and AceTime | diff --git a/data/Daytimemap org.cfg b/data/Daytimemap org.cfg index 42b75cf..ce0af51 100644 --- a/data/Daytimemap org.cfg +++ b/data/Daytimemap org.cfg @@ -1,6 +1,6 @@ # Config file for day / time based relay control # ** Version 1.8.0 -# Copyright (c) 2021 Rob Roos +# Copyright (c) 2022 Rob Roos # file format is CSV , all values as string without "" , fields are # day, starthour, startmin, endhour, endmin # day = daynumber, Numeric representation of the day of the week (1 = Sunday) diff --git a/data/Daytimemap.cfg b/data/Daytimemap.cfg index 42b75cf..ce0af51 100644 --- a/data/Daytimemap.cfg +++ b/data/Daytimemap.cfg @@ -1,6 +1,6 @@ # Config file for day / time based relay control # ** Version 1.8.0 -# Copyright (c) 2021 Rob Roos +# Copyright (c) 2022 Rob Roos # file format is CSV , all values as string without "" , fields are # day, starthour, startmin, endhour, endmin # day = daynumber, Numeric representation of the day of the week (1 = Sunday) diff --git a/data/FSexplorer.css b/data/FSexplorer.css index 55aae26..3c098b8 100644 --- a/data/FSexplorer.css +++ b/data/FSexplorer.css @@ -3,7 +3,7 @@ ** Program : FSexplorer.html, ** Version 1.8.0 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** For more information visit: https://fipsok.de diff --git a/data/FSexplorer.html b/data/FSexplorer.html index 1ece141..d8e431b 100644 --- a/data/FSexplorer.html +++ b/data/FSexplorer.html @@ -3,7 +3,7 @@ ** Program : FSexplorer.html ** Version 1.8.0 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** diff --git a/data/MBmapSolarEdge.cfg b/data/MBmapSolarEdge.cfg index 77b2fb6..e3f8b7b 100644 --- a/data/MBmapSolarEdge.cfg +++ b/data/MBmapSolarEdge.cfg @@ -1,6 +1,6 @@ # Configuration file to map modbus registers for SolarEdge # ** Version 1.8.0 -# Copyright (c) 2021 Rob Roos +# Copyright (c) 2022 Rob Roos # file format is CSV , all values as string without "" , syntax of fields is only marginally checked, be carefull # reg = register address # format = (Modbus_short, Modbus_ushort, Modbus_int, Modbus_uint, Modbus_float, Modbus_string[length], Modbus_undef) diff --git a/data/MBmapUMG96.cfg b/data/MBmapUMG96.cfg index cafedaf..f09b713 100644 --- a/data/MBmapUMG96.cfg +++ b/data/MBmapUMG96.cfg @@ -1,6 +1,6 @@ # Configuration file to map modbus registers for Janitza UMG96RM # ** Version 1.8.0 -# Copyright (c) 2021 Rob Roos +# Copyright (c) 2022 Rob Roos # file format is CSV , all values as string without "" , syntax of fields is only marginally checked, be carefull # reg = register address # format = (Modbus_short, Modbus_ushort, Modbus_int, Modbus_uint, Modbus_float, Modbus_string[length], Modbus_undef) diff --git a/data/Modbusmap.cfg b/data/Modbusmap.cfg index 6832e46..a9525da 100644 --- a/data/Modbusmap.cfg +++ b/data/Modbusmap.cfg @@ -1,6 +1,6 @@ # Configuration file to map modbus registers # ** Version 1.8.0 -# Copyright (c) 2021 Rob Roos +# Copyright (c) 2022 Rob Roos # file format is CSV , all values as string without "" , syntax of fields is only marginally checked, be carefull # reg = register address # format = (Modbus_short, Modbus_ushort, Modbus_int, Modbus_uint, Modbus_float, Modbus_string[length], Modbus_undef) diff --git a/data/Modbusmaptest.cfg b/data/Modbusmaptest.cfg index b154323..e58f8b6 100644 --- a/data/Modbusmaptest.cfg +++ b/data/Modbusmaptest.cfg @@ -1,6 +1,6 @@ # Configuration test file to map modbus registers when debugflag Modbuslogic (bDebugMBlogic) is true (during compile) # ** Version 1.8.0 -# Copyright (c) 2021 Rob Roos +# Copyright (c) 2022 Rob Roos # file format is CSV , all values as string without "" , syntax of fields is only marginally checked, be carefull # reg = register address # format = (Modbus_short, Modbus_ushort, Modbus_int, Modbus_uint, Modbus_float, Modbus_string[length], Modbus_undef) diff --git a/data/index.css b/data/index.css index 00bbe48..6154d41 100644 --- a/data/index.css +++ b/data/index.css @@ -2,7 +2,7 @@ *************************************************************************** ** Program : index.css, ** Version 1.8.1 -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** TERMS OF USE: MIT License. See bottom of file. diff --git a/data/index.html b/data/index.html index f3d1706..868b591 100644 --- a/data/index.html +++ b/data/index.html @@ -3,7 +3,7 @@ ** Program : index.html ** Version 1.8.0 ** Main entry for Modbusrtu ESP8266 WebUI -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** diff --git a/data/index.js b/data/index.js index d470867..0e6c89e 100644 --- a/data/index.js +++ b/data/index.js @@ -3,7 +3,7 @@ ** Program : index.js, part of Modbus-firmware project ** Version 1.8.1 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -553,6 +553,7 @@ function sendPostSetting(field, value) { , ["modbussinglephase", "Modbus Single Phase"] , ["timebasedswitch", "Day and timebased switching"] , ["relayallwayson", "Relay allways on"] + , ["debugbootswitch", "Debuglog all on after reboot"] , ["wifireconnect", "Wifi reconnect count (reset at reboot)"] , ["wifirestart", "Wifi restart count (reset at reboot)"] , ["rebootcount", "ESP reboot count"] diff --git a/handleDebug.ino b/handleDebug.ino index f7a2208..33c5d8b 100644 --- a/handleDebug.ino +++ b/handleDebug.ino @@ -4,7 +4,7 @@ ** Version 1.8.0 ** ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -18,35 +18,35 @@ void handleDebug(){ c = TelnetStream.read(); switch (c){ case 'h': - Debugln("Available commands are:"); - Debugln("p : Print (list) Modbusmap "); - Debugln("l : List Daytimemap"); - Debugln("d : Re-read Daytimemap from Daytimemap.cfg"); - Debugln("t : Toggle Timebased Relay"); - Debugln("m : Configure MQTT Discovery"); - Debugln("r : Reconnecting to wifi"); - Debugf("1 : Toggle debug Modbus msg, status: %s\r\n", CBOOLEAN(bDebugMBmsg)); - Debugf("2 : Toggle debug RestAPI status %s\r\n", CBOOLEAN(bDebugRestAPI)); - Debugf("3 : Toggle debug MQTT, status: %s\r\n", CBOOLEAN(bDebugMQTT)); - Debugf("8 : Toggle Modbus Byteswap: %s\r\n", CBOOLEAN(settingModbusByteswap)); - Debugf("9 : Toggle debug Modbuslogic, status: %s\r\n", CBOOLEAN(bDebugMBlogic)); + Debugln(F("Available commands are:")); + Debugln(F("p : Print (list) Modbusmap ")); + Debugln(F("l : List Daytimemap")); + Debugln(F("d : Re-read Daytimemap from Daytimemap.cfg")); + Debugln(F("t : Toggle Timebased Relay")); + Debugln(F("m : Configure MQTT Discovery")); + Debugln(F("r : Reconnecting to wifi")); + Debugf(PSTR("1 : Toggle debug Modbus msg, status: %s\r\n"), CBOOLEAN(bDebugMBmsg)); + Debugf(PSTR("2 : Toggle debug RestAPI status %s\r\n"), CBOOLEAN(bDebugRestAPI)); + Debugf(PSTR("3 : Toggle debug MQTT, status: %s\r\n"), CBOOLEAN(bDebugMQTT)); + Debugf(PSTR("8 : Toggle Modbus Byteswap: %s\r\n"), CBOOLEAN(settingModbusByteswap)); + Debugf(PSTR("9 : Toggle debug Modbuslogic, status: %s\r\n"), CBOOLEAN(bDebugMBlogic)); break; case 'd': - DebugTln("Read Daytimemap"); + DebugTln(F("Read Daytimemap")); doInitDaytimemap() ; printDaytimemap(); break; case 'l': - DebugTln("List Daytimemap"); + DebugTln(F("List Daytimemap")); printDaytimemap(); break; case 'p': - DebugTln("Print Modbusmap"); + DebugTln(F("Print Modbusmap")); printModbusmap(); break; case 't': - DebugTln("Toggle Timebased Relay"); + DebugTln(F("Toggle Timebased Relay")); if (settingTimebasedSwitch && settingNTPenable) { DebugTf("Relay current status %d \r\n", statusRelay); @@ -55,51 +55,51 @@ void handleDebug(){ else setRelay(RELAYOFF); } else { - DebugTln("NOT POSSIBLE, TIMEBASED SWITCHING NOT ACTIVATED"); + DebugTln(F("NOT POSSIBLE, TIMEBASED SWITCHING NOT ACTIVATED")); } case 'm': - DebugTln("Configure MQTT Discovery"); + DebugTln(F("Configure MQTT Discovery")); DebugTf("Enable MQTT: %s", CBOOLEAN(settingMQTTenable)); doAutoConfigure(); break; case 'r': if (WiFi.status() != WL_CONNECTED) { - DebugTln("Reconnecting to wifi"); + DebugTln(F("Reconnecting to wifi")); restartWiFi(CSTR(settingHostname), 240); startTelnet(); } else - DebugTln("Wifi is connected"); + DebugTln(F("Wifi is connected")); if (!statusMQTTconnection) { - DebugTln("Reconnecting MQTT"); + DebugTln(F("Reconnecting MQTT")); startMQTT(); } else - DebugTln("MQTT is connected"); + DebugTln(F("MQTT is connected")); break; case '1': bDebugMBmsg = !bDebugMBmsg; - Debugf("\r\nDebug Modbus msg: %s\r\n", CBOOLEAN(bDebugMBmsg)); + Debugf(PSTR("\r\nDebug Modbus msg: %s\r\n"), CBOOLEAN(bDebugMBmsg)); break; case '2': bDebugRestAPI = !bDebugRestAPI; - Debugf("\r\nDebug RestAPI: %s\r\n", CBOOLEAN(bDebugRestAPI)); + Debugf(PSTR("\r\nDebug RestAPI: %s\r\n"), CBOOLEAN(bDebugRestAPI)); break; case '3': bDebugMQTT = !bDebugMQTT; - Debugf("\r\nDebug MQTT: %s\r\n", CBOOLEAN(bDebugMQTT)); + Debugf(PSTR("\r\nDebug MQTT: %s\r\n"), CBOOLEAN(bDebugMQTT)); break; case '8': settingModbusByteswap = !settingModbusByteswap; - Debugf("\r\nModbus ByteSwap: %s\r\n", CBOOLEAN(settingModbusByteswap)); + Debugf(PSTR("\r\nModbus ByteSwap: %s\r\n"), CBOOLEAN(settingModbusByteswap)); break; case '9': bDebugMBlogic = !bDebugMBlogic; - Debugf("\r\nDebug Modbuslogic: %s\r\n", CBOOLEAN(bDebugMBlogic)); + Debugf(PSTR("\r\nDebug Modbuslogic: %s\r\n"), CBOOLEAN(bDebugMBlogic)); break; default: break; } diff --git a/helperStuff.ino b/helperStuff.ino index 01094cc..278b5b7 100644 --- a/helperStuff.ino +++ b/helperStuff.ino @@ -1,10 +1,10 @@ /* *************************************************************************** ** Program : helperStuff -** Version 1.9.1 +** Version 1.10.0 ** ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -118,7 +118,7 @@ int8_t splitString(String inStrng, char delimiter, String wOut[], uint8_t maxWor inxE = inStrng.indexOf(delimiter, inxS); //finds location of first , wOut[wordCount] = inStrng.substring(inxS, inxE); //captures first data String wOut[wordCount].trim(); - //DebugTf("[%d] => [%c] @[%d] found[%s]\r\n", wordCount, delimiter, inxE, wOut[wordCount].c_str()); + //DebugTf(PSTR("[%d] => [%c] @[%d] found[%s]\r\n"), wordCount, delimiter, inxE, wOut[wordCount].c_str()); inxS = inxE; inxS++; wordCount++; @@ -149,7 +149,7 @@ void strConcat(char *dest, int maxLen, const char *src) } else { - DebugTf("Combined string > %d chars\r\n", maxLen); + DebugTf(PSTR("Combined string > %d chars\r\n"), maxLen); } } // strConcat() @@ -173,7 +173,7 @@ void strConcat(char *dest, int maxLen, float v, int dec) } else { - DebugTf("Combined string > %d chars\r\n", maxLen); + DebugTf(PSTR("Combined string > %d chars\r\n"), maxLen); } } // strConcat() @@ -191,7 +191,7 @@ void strConcat(char *dest, int maxLen, int v) } else { - DebugTf("Combined string > %d chars\r\n", maxLen); + DebugTf(PSTR("Combined string > %d chars\r\n"), maxLen); } } // strConcat() @@ -213,7 +213,7 @@ void strToLower(char *src) void strCopy(char *dest, int maxLen, const char *src, int frm, int to) { int d=0; -//DebugTf("dest[%s], src[%s] max[%d], frm[%d], to[%d] =>\r\n", dest, src, maxLen, frm, to); +//DebugTf(PSTR("dest[%s], src[%s] max[%d], frm[%d], to[%d] =>\r\n"), dest, src, maxLen, frm, to); dest[0] = '\0'; for (int i=0; i<=frm; i++) { @@ -345,7 +345,7 @@ int strIndex(const char *haystack, const char *needle, int start) { char *p = strstr (haystack+start, needle); if (p) { - //DebugTf("found [%s] at position [%d]\r\n", needle, (p - haystack)); + //DebugTf(PSTR("found [%s] at position [%d]\r\n"), needle, (p - haystack)); return (p - haystack); } return -1; @@ -411,7 +411,7 @@ float strToFloat(const char *s, int dec) r = strtof(s, NULL); p = (int)(r*pow(10, dec)); r = p / pow(10, dec); - //DebugTf("[%s][%d] => p[%d] -> r[%f]\r\n", s, dec, p, r); + //DebugTf(PSTR("[%s][%d] => p[%d] -> r[%f]\r\n"), s, dec, p, r); return r; } // strToFloat() @@ -570,7 +570,7 @@ bool updateRebootLog(String text) struct rst_info *rtc_info = system_get_rst_info(); if (rtc_info == NULL) { - DebugTf("no reset info available: %x\r\n", errorCode); + DebugTf(PSTR("no reset info available: %x\r\n"), errorCode); } else { @@ -587,16 +587,16 @@ bool updateRebootLog(String text) errorCode = rtc_info->reason; switch(rtc_info->reason) { - case 0: snprintf(log_line_reason, LOG_LINE_LENGTH, "0 - Power reboot"); break; - case 1: snprintf(log_line_reason, LOG_LINE_LENGTH, "1 - Hardware WDT reset"); break; - case 2: snprintf(log_line_reason, LOG_LINE_LENGTH, "2 - Fatal exception"); break; - case 3: snprintf(log_line_reason, LOG_LINE_LENGTH, "3 - Software watchdog reset"); break; - case 4: snprintf(log_line_reason, LOG_LINE_LENGTH, "4 - Software reset"); break; - case 5: snprintf(log_line_reason, LOG_LINE_LENGTH, "5 - Deep-sleep"); break; - case 6: snprintf(log_line_reason, LOG_LINE_LENGTH, "6 - Hardware reset"); break; - default: snprintf(log_line_reason, LOG_LINE_LENGTH, "- Other (not specified) (%d)", rtc_info->reason); break; + case 0: snprintf(log_line_reason, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d Power reboot\r\n",year(), month(), day(), hour(), minute(), second()); break; + case 1: snprintf(log_line_reason, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d Hardware WDT reset\r\n",year(), month(), day(), hour(), minute(), second()); break; + case 2: snprintf(log_line_reason, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d Fatal exception\r\n",year(), month(), day(), hour(), minute(), second()); break; + case 3: snprintf(log_line_reason, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d Software watchdog reset\r\n,", year(), month(), day(), hour(), minute(), second()); break; + case 4: snprintf(log_line_reason, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d Software reset\r\n", year(), month(), day(), hour(), minute(), second()); break; + case 5: snprintf(log_line_reason, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d Deep-sleep\r\n", year(), month(), day(), hour(), minute(), second()); break; + case 6: snprintf(log_line_reason, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d Hardware reset\r\n", year(), month(), day(), hour(), minute(), second()); break; + default: snprintf(log_line_reason, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d Other (not specified) (%d)\r\n", year(), month(), day(), hour(), minute(), second(), rtc_info->reason); break; } - DebugTf("reset reason: %s\r\n", log_line_reason); + DebugTf(PSTR("reset reason: %s\r\n"), log_line_reason); if (rtc_info->reason == REASON_WDT_RST || rtc_info->reason == REASON_EXCEPTION_RST || rtc_info->reason == REASON_SOFT_WDT_RST) { @@ -635,7 +635,7 @@ bool updateRebootLog(String text) } - DebugTf("Fatal exception (%d): %s\r\n", rtc_info->exccause, log_line_excpt); + DebugTf(PSTR("Fatal exception (%d): %s\r\n"), rtc_info->exccause, log_line_excpt); } } diff --git a/jsonStuff.ino b/jsonStuff.ino index 02113f5..de9d032 100644 --- a/jsonStuff.ino +++ b/jsonStuff.ino @@ -3,7 +3,7 @@ ** Program : jsonStuff ** Version 1.8.0 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -58,7 +58,7 @@ void sendNestedJsonObj(const char *cName, String sValue) if (sValue.length() > (JSON_BUFF_MAX - 65) ) { - DebugTf("[2] sValue.length() [%d]\r\n", sValue.length()); + DebugTf(PSTR("[2] sValue.length() [%d]\r\n"), sValue.length()); } snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": \"%s\"}" diff --git a/networkStuff.h b/networkStuff.h index 6dc4f55..9eb5772 100644 --- a/networkStuff.h +++ b/networkStuff.h @@ -3,7 +3,7 @@ ** Program : networkStuff.h ** Version 1.9.1 ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -32,6 +32,7 @@ bool updateRebootLog(String text) ; //Use the NTP SDK ESP 8266 #include +extern "C" int clock_gettime(clockid_t unused, struct timespec *tp); enum NtpStatus_t { TIME_NOTSET, @@ -41,6 +42,7 @@ enum NtpStatus_t { }; NtpStatus_t NtpStatus = TIME_NOTSET; +static const time_t EPOCH_2000_01_01 = 946684800; time_t NtpLastSync = 0; //last sync moment in EPOCH seconds @@ -177,68 +179,136 @@ void startLLMNR(const char *hostname) } // startLLMNR() -//====[ startNTP ]=== +//==[ NTP stuff ]============================================================== + + void startNTP(){ - // Initialisation Time + // Initialisation ezTime if (!settingNTPenable) return; if (settingNTPtimezone.length()==0) settingNTPtimezone = NTP_DEFAULT_TIMEZONE; //set back to default timezone if (settingNTPhostname.length()==0) settingNTPhostname = NTP_HOST_DEFAULT; //set back to default timezone //void configTime(int timezone_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3) configTime(0, 0, CSTR(settingNTPhostname), nullptr, nullptr); + // Configure NTP before WiFi, so DHCP can override the NTP server(s) + NtpStatus = TIME_WAITFORSYNC; } + +void getNTPtime(){ + struct timespec tp; //to enable clock_gettime() + double tNow; + long dt_sec, dt_ms, dt_nsec; + clock_gettime(CLOCK_REALTIME, &tp); + tNow = tp.tv_sec+(tp.tv_nsec/1.0e9); + dt_sec = tp.tv_sec; + dt_ms = tp.tv_nsec / 1000000UL; + dt_nsec = tp.tv_nsec; + DebugTf(PSTR("tNow=%20.10f tNow_sec=%16.10ld tNow_nsec=%16.10ld dt_sec=%16li(s) dt_msec=%16li(sm) dt_nsec=%16li(ns)\r\n"), (double)tNow, tp.tv_sec,tp.tv_nsec, dt_sec, dt_ms, dt_nsec); + DebugFlush(); +} + void loopNTP(){ +time_t now; +now = time(nullptr); //this is now... +configTime(0, 0, CSTR(settingNTPhostname), nullptr, nullptr); + if (!settingNTPenable) return; switch (NtpStatus){ case TIME_NOTSET: - DebugTln(F("Time not set")); case TIME_NEEDSYNC: - NtpLastSync = time(nullptr); //remember last sync + NtpLastSync = now; //remember last sync DebugTln(F("Start time syncing")); startNTP(); + DebugTf(PSTR("Starting timezone lookup for [%s]\r\n"), CSTR(settingNTPtimezone)); NtpStatus = TIME_WAITFORSYNC; - break; + break; case TIME_WAITFORSYNC: - if ((time(nullptr)>0) || (time(nullptr) >= NtpLastSync)) { - NtpLastSync = time(nullptr); //remember last sync - - DebugTf("Timezone lookup for [%s]\r\n", CSTR(settingNTPtimezone)); - auto myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); - + if ((now > EPOCH_2000_01_01) && (now >= NtpLastSync)) { + //DebugTf(PSTR("Waited for sync: epoch: %lld\r\n"), time(nullptr)); + NtpLastSync = now; //remember last sync + TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); if (myTz.isError()){ - DebugTf("Error: Timezone Invalid/Not Found: [%s]\r\n", CSTR(settingNTPtimezone)); + DebugTf(PSTR("Error: Timezone Invalid/Not Found: [%s]\r\n"), CSTR(settingNTPtimezone)); settingNTPtimezone = NTP_DEFAULT_TIMEZONE; myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); //try with default Timezone instead - } else DebugTln(F("Timezone lookup: successful")); - - auto myTime = ZonedDateTime::forUnixSeconds(NtpLastSync, myTz); - if (myTime.isError()) { - DebugTln("Error: Time not set correctly, wait for sync"); - // NtpStatus = TIME_NEEDSYNC; } else { - setTime(myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year()); - NtpStatus = TIME_SYNC; - DebugTln(F("Time synced!")); + //found the timezone, now set the time + ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now, myTz); + DebugTf(PSTR("%02d:%02d:%02d %02d-%02d-%04d\n\r"), myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year()); + if (!myTime.isError()) { + //finally time is synced! + //setTime(myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year()); + NtpStatus = TIME_SYNC; + DebugTln(F("Time synced!")); + } } } break; case TIME_SYNC: - if ((time(nullptr)-NtpLastSync) > NTP_RESYNC_TIME){ + if ((now - NtpLastSync) > NTP_RESYNC_TIME){ //when xx seconds have passed, resync using NTP DebugTln(F("Time resync needed")); NtpStatus = TIME_NEEDSYNC; } break; } - - // DECLARE_TIMER_SEC(timerNTPtime, 10, CATCH_UP_MISSED_TICKS); - // if DUE(timerNTPtime) Debugf("Epoch Seconds: %d\r\n", time(nullptr)); //timeout, then break out of this loop + // if DUE(timerNTPtime) + // { + // //DebugTf(PSTR("Epoch Seconds: %lld\r\n"), now); //timeout, then break out of this loop + // DebugT("Now: "); + // Debug(now); + // Debugln(); + // DebugT("Timezone : "); + // Debugln(CSTR(settingNTPtimezone)); + // TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); + // ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now, myTz); + + // DebugTf(PSTR("%02d:%02d:%02d %02d-%02d-%04d\r\n"), myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year()); + // } + // if DUE(timerNTPtime) getNTPtime(); } +bool isNTPtimeSet(){ + return NtpStatus == TIME_SYNC; +} + +// void waitforNTPsync(int16_t timeout = 30){ +// //wait for time is synced to NTP server, for maximum of timeout seconds +// //feed the watchdog while waiting +// //update NTP status +// time_t t = time(nullptr); //get current time +// DebugTf(PSTR("Waiting for NTP sync, timeout: %d\r\n"), timeout); +// DECLARE_TIMER_SEC(waitforNTPsync, timeout, CATCH_UP_MISSED_TICKS); +// DECLARE_TIMER_SEC(timerWaiting, 5, CATCH_UP_MISSED_TICKS); +// while (true){ +// //feed the watchdog while waiting +// Wire.beginTransmission(0x26); +// Wire.write(0xA5); +// Wire.endTransmission(); +// delay(100); +// if DUE(timerWaiting) DebugTf(PSTR("Waiting for NTP sync: %lu seconds\r\n"), (time(nullptr)-t)); +// // update NTP status +// loopNTP(); +// //stop waiting when NTP is synced +// if (isNTPtimeSet()) { +// Debugln(F("NTP time synced!")); +// break; +// } +// //stop waiting when timeout is reached +// if DUE(waitforNTPsync) { +// DebugTln(F("NTP sync timeout!")); +// break; +// } +// } +// } + + +//==[ end of NTP stuff ]======================================================= + String getMacAddress() { uint8_t baseMac[6]; diff --git a/restAPI.ino b/restAPI.ino index cc45433..c1f39e9 100644 --- a/restAPI.ino +++ b/restAPI.ino @@ -1,10 +1,10 @@ /* *************************************************************************** ** Program : restAPI.ino -** Version 1.8.1 +** Version 1.10.0 ** ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -23,13 +23,13 @@ void processAPI() if (httpServer.method() == HTTP_GET) if (bDebugRestAPI) - DebugTf("from[%s] URI[%s] method[GET] \r\n", httpServer.client().remoteIP().toString().c_str(), URI); + DebugTf(PSTR("from[%s] URI[%s] method[GET] \r\n"), httpServer.client().remoteIP().toString().c_str(), URI); else if (bDebugRestAPI) - DebugTf("from[%s] URI[%s] method[PUT] \r\n", httpServer.client().remoteIP().toString().c_str(), URI); + DebugTf(PSTR("from[%s] URI[%s] method[PUT] \r\n"), httpServer.client().remoteIP().toString().c_str(), URI); if (ESP.getFreeHeap() < 8500) // to prevent firmware from crashing! { - if (bDebugRestAPI) DebugTf("==> Bailout due to low heap (%d bytes))\r\n", ESP.getFreeHeap()); + if (bDebugRestAPI) DebugTf(PSTR("==> Bailout due to low heap (%d bytes))\r\n"), ESP.getFreeHeap()); httpServer.send(500, "text/plain", "500: internal server error (low heap)\r\n"); return; } @@ -378,6 +378,7 @@ void sendDeviceSettings() sendJsonSettingObj("modbussinglephase", settingModbusSinglephase, "b"); sendJsonSettingObj("timebasedswitch", settingTimebasedSwitch, "b"); sendJsonSettingObj("relayallwayson", settingRelayAllwaysOnSwitch, "b"); + sendJsonSettingObj("debugbootswitch", settingDebugAfterBoot, "b"); sendEndJsonObj(); } // sendDeviceSettings() @@ -409,7 +410,7 @@ void postSettings() if (wOut[0].equalsIgnoreCase("name")) strCopy(field, sizeof(field), wOut[1].c_str()); if (wOut[0].equalsIgnoreCase("value")) strCopy(newValue, sizeof(newValue), wOut[1].c_str()); } - DebugTf("--> field[%s] => newValue[%s]\r\n", field, newValue); + DebugTf(PSTR("--> field[%s] => newValue[%s]\r\n"), field, newValue); updateSetting(field, newValue); httpServer.send(200, "application/json", httpServer.arg(0)); diff --git a/safeTimers.h b/safeTimers.h index d8ccc5b..c1927a0 100644 --- a/safeTimers.h +++ b/safeTimers.h @@ -4,7 +4,7 @@ ** Version 1.8.0 ** ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** diff --git a/settingStuff.ino b/settingStuff.ino index f727e3a..0c73ab0 100644 --- a/settingStuff.ino +++ b/settingStuff.ino @@ -1,10 +1,10 @@ /* *************************************************************************** ** Program : settingStuff.ino -** Version 1.8.1 +** Version 1.10.0 ** ** -** Copyright (c) 2021 Rob Roos +** Copyright (c) 2022 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -51,6 +51,7 @@ void writeSettings(bool show) root["modbussinglephase"] = settingModbusSinglephase; root["timebasedswitch"] = settingTimebasedSwitch; root["relayallwayson"] = settingRelayAllwaysOnSwitch; + root["debugbootswitch"] = settingDebugAfterBoot; serializeJsonPretty(root, TelnetStream); serializeJsonPretty(root, file); @@ -124,6 +125,7 @@ void readSettings(bool show) settingModbusSinglephase = doc["modbussinglephase"]|settingModbusSinglephase; settingTimebasedSwitch = doc["timebasedswitch"] | settingTimebasedSwitch; settingRelayAllwaysOnSwitch = doc["relayallwayson"] | settingRelayAllwaysOnSwitch; + settingDebugAfterBoot = doc["debugbootswitch"] | settingDebugAfterBoot; // Close the file (Curiously, File's destructor doesn't close the file) @@ -132,7 +134,7 @@ void readSettings(bool show) DebugTln(F(" .. done\r")); - if (show) { + if (show | settingDebugAfterBoot) { Debugln(F("\r\n==== read Settings ===================================================\r")); Debugf("Hostname : %s\r\n", CSTR(settingHostname)); Debugf("MQTT enabled : %s\r\n", CBOOLEAN(settingMQTTenable)); @@ -154,6 +156,7 @@ void readSettings(bool show) Debugf("Modbus singlephase : %s\r\n", CBOOLEAN(settingModbusSinglephase)); Debugf("Timebased switch : %s\r\n", CBOOLEAN(settingTimebasedSwitch)); Debugf("Relay Allways On switch : %s\r\n", CBOOLEAN(settingRelayAllwaysOnSwitch)); + Debugf("Debug after boot switch : %s\r\n", CBOOLEAN(settingDebugAfterBoot)); } Debugln(F("-\r")); @@ -240,6 +243,9 @@ void updateSetting(const char *field, const char *newValue) settingRelayAllwaysOnSwitch = EVALBOOLEAN(newValue); checkactivateRelay(true) ; } + if (stricmp(field, "debugbootswitch") == 0) { + settingDebugAfterBoot = EVALBOOLEAN(newValue); + } // without NTP no timebased switching if (!settingNTPenable) { diff --git a/version.h b/version.h index 7c6d883..e296e24 100644 --- a/version.h +++ b/version.h @@ -1,14 +1,16 @@ //The version number conforms to semver.org format #define _VERSION_MAJOR 1 -#define _VERSION_MINOR 9 -#define _VERSION_PATCH 1 -#define _VERSION_BUILD 419 -//#define _VERSION_PRERELEASE beta //uncomment to define prerelease labels: alpha - beta - rc -#define _VERSION_DATE "26/07/2022" -#define _VERSION_TIME "21:24:07" -#define _SEMVER_CORE "1.9.1" -#define _SEMVER_NOBUILD "1.9.1" -#define _SEMVER_CORE "1.9.1" -#define _SEMVER_FULL "1.9.1 (26/07/2022)" -#define _VERSION "1.9.1+419 (26/07/2022)" +#define _VERSION_MINOR 10 +#define _VERSION_PATCH 0 +#define _VERSION_BUILD 463 +#define _VERSION_GITHASH "0000000" +#define _VERSION_PRERELEASE beta +#define _VERSION_DATE "16/07/2023" +#define _VERSION_TIME "22:20:45" +#define _SEMVER_CORE "1.10.0" +#define _SEMVER_BUILD "1.10.0+463" +#define _SEMVER_GITHASH "1.10.0+0000000" +#define _SEMVER_FULL "1.10.0 beta (16/07/2023)" +#define _SEMVER_NOBUILD "1.10.0 (16/07/2023)" +#define _VERSION "1.10.0+463 (16/07/2023)" //The version information is created automatically, more information here: https://github.com/rvdbreemen/autoinc-semver From 62a0789b649cfb7cde4bb1eeedee006243b8d23f Mon Sep 17 00:00:00 2001 From: Rob Roos Date: Sun, 16 Jul 2023 22:35:07 +0200 Subject: [PATCH 2/5] Fix git ignore --- .DS_Store | Bin 14340 -> 14340 bytes .vscode/.gitignore | 11 +++++++++++ README.md | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 .vscode/.gitignore diff --git a/.DS_Store b/.DS_Store index 7c847e7882e0a117fc6c637c7eb412f66f6b92f6..fb065b88de63e64fafb7c37788b5f7fcd785aac6 100644 GIT binary patch delta 151 zcmZoEXepR*nDPB)K?!H}&Fma<5^=NS!WbABSQzve(it)tN^l`qIJ3{K9^Edc6aU^qQtazFDH delta 150 zcmZoEXepR*nDOamK?!H}&Fma<5^*z*RWmR!urTN`q%&kPl;q~SxFqG|CjrGc7#JF! zIvE{xM3qm$D_@Xd7@VA+TL9FChanged: removed ezTime NTP library, moved to ConfigTime NTP and AceTime | From c89ecf4765ac099b61c20d8f1aee76125d3e6d20 Mon Sep 17 00:00:00 2001 From: Rob Roos Date: Sun, 16 Jul 2023 22:35:17 +0200 Subject: [PATCH 3/5] Fix gitignore --- .DS_Store | Bin 14340 -> 14340 bytes .vscode/.gitignore => .gitignore | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename .vscode/.gitignore => .gitignore (100%) diff --git a/.DS_Store b/.DS_Store index fb065b88de63e64fafb7c37788b5f7fcd785aac6..761765a9e1297dfa3f55bc851ae62480725f6b46 100644 GIT binary patch delta 242 zcmZoEXepTB&nQ1JAVD}dIX}060R(25MgvI}2EEOK5-#kU**RDw#P}g14CxG+3?(VW z$vH{+`8kY}c@(7TVX7f=x%n Date: Sat, 29 Jul 2023 22:21:40 +0200 Subject: [PATCH 4/5] Update to 11.1 --- .DS_Store | Bin 14340 -> 14340 bytes Debug.h | 56 ++++++++++++++++++++++++++------ FSexplorer.ino | 4 +-- MQTTstuff.ino | 6 ++-- ModbusRTU-ESP8266-webui.h | 14 ++++---- ModbusRTU-ESP8266-webui.ino | 13 ++++---- ModbusStuff.h | 6 ++-- ModbusStuff.ino | 62 +++++++++++++++++++++--------------- README.md | 5 ++- data/Daytimemap org.cfg | 4 +-- data/Daytimemap.cfg | 12 +++---- data/FSexplorer.css | 4 +-- data/FSexplorer.html | 4 +-- data/MBmapSolarEdge.cfg | 4 +-- data/MBmapUMG96.cfg | 4 +-- data/Modbusmap.cfg | 4 +-- data/Modbusmaptest.cfg | 4 +-- data/index.css | 4 +-- data/index.html | 6 ++-- data/index.js | 4 +-- handleDebug.ino | 4 +-- helperStuff.ino | 57 ++++++++++----------------------- jsonStuff.ino | 26 ++++++++++----- networkStuff.h | 27 +++++++++------- restAPI.ino | 46 +++++++++++++++----------- safeTimers.h | 4 +-- settingStuff.ino | 4 +-- version.h | 22 ++++++------- 28 files changed, 231 insertions(+), 179 deletions(-) diff --git a/.DS_Store b/.DS_Store index 761765a9e1297dfa3f55bc851ae62480725f6b46..73249ed2d59118d62381d1c7819791090b6b3867 100644 GIT binary patch delta 78 zcmZoEXepSmN|<571EZsk!O8i#1q>iC%VpBWy~*;743iZVq?lYLO}15#UiC%QSl9-eh@3#>t8bQcR}NlWi3wSoc3Y{MU7I cl!7#rRiz-qbo#^Q847C{8DloPD(x2q0FYcB1^@s6 diff --git a/Debug.h b/Debug.h index 30c3234..b523feb 100644 --- a/Debug.h +++ b/Debug.h @@ -1,9 +1,9 @@ /* *************************************************************************** ** Program : Debug.h, part of ModbusRTU-webui -** Version 1.8.0 +** Version 1.11.0 ** -** Copyright (c) 2022 Rob Roos +** Copyright (c) 2023 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -63,17 +63,53 @@ // needs #include // Version 0.0.1 - https://github.com/jandrassy/TelnetStream -char _bol[128]; +//#include +// #include +// extern "C" int clock_gettime(clockid_t unused, struct timespec *tp); + void _debugBOL(const char *fn, int line) { + char _bol[128]; + // This commented out code is using mix of system time and acetime to print, but it will not work on microsecond level correctly + // // //calculate fractional seconds to millis fraction + // double fractional_seconds; + // int microseconds; + // struct timespec tp; //to enable clock_gettime() + // clock_gettime(CLOCK_REALTIME, &tp); + // fractional_seconds = (double) tp.tv_nsec; + // fractional_seconds /= 1e3; + // fractional_seconds = round(fractional_seconds); + // microseconds = (int) fractional_seconds; + + /* snprintf(_bol, sizeof(_bol), "%02d:%02d:%02d.%06d (%7u|%6u) %-12.12s(%4d): ", \ + hour(), minute(), second(), microseconds, \ + ESP.getFreeHeap(), ESP.getMaxFreeBlockSize(),\ + fn, line); + */ + + //Alternative based on localtime function + timeval now; + //struct tm *tod; + gettimeofday(&now, nullptr); + //tod = localtime(&now.tv_sec); - snprintf(_bol, sizeof(_bol), "[%02d:%02d:%02d][%7u|%6u] %-12.12s(%4d): ", \ - hour(), minute(), second(), \ - ESP.getFreeHeap(), ESP.getMaxFreeBlockSize(),\ - fn, line); + /* + snprintf(_bol, sizeof(_bol), "%02d:%02d:%02d.%06d (%7u|%6u) %-12.12s(%4d): ", \ + tod->tm_hour, tod->tm_min, tod->tm_sec, (int)now.tv_usec, \ + ESP.getFreeHeap(), ESP.getMaxFreeBlockSize(),\ + fn, line); + */ - DEBUG_PORT.print (_bol); - TelnetStream.print(_bol); -} + TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); + ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(time(nullptr), myTz); + + //DebugTf(PSTR("%02d:%02d:%02d %02d-%02d-%04d\r\n"), myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year()); + snprintf(_bol, sizeof(_bol), "%02d:%02d:%02d.%06d (%7u|%6u) %-12.12s(%4d): ", \ + myTime.hour(), myTime.minute(), myTime.second(), (int)now.tv_usec, \ + ESP.getFreeHeap(), ESP.getMaxFreeBlockSize(),\ + fn, line); + + TelnetStream.print (_bol); +} #endif // DEBUG_H diff --git a/FSexplorer.ino b/FSexplorer.ino index f7a557b..31bfc41 100644 --- a/FSexplorer.ino +++ b/FSexplorer.ino @@ -1,10 +1,10 @@ /* *************************************************************************** ** Program : FSexplorer -** Version 1.8.1 +** Version 1.11.0 ** ** -** Copyright (c) 2022 Rob Roos +** Copyright (c) 2023 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** diff --git a/MQTTstuff.ino b/MQTTstuff.ino index 4e8e245..dbb9d77 100644 --- a/MQTTstuff.ino +++ b/MQTTstuff.ino @@ -1,9 +1,9 @@ /* *************************************************************************** ** Program : MQTTstuff -** Version 1.10.0 +** Version 1.11.0 ** -** Copyright (c) 2022 Rob Roos +** Copyright (c) 2023 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** TERMS OF USE: MIT License. See bottom of file. @@ -384,7 +384,7 @@ void doAutoConfigure() // String sTopic_template = "%homeassistant%/sensor/%node_id%/%label%/config"; // String sMsg_template = "{\"avty_t\":\"%mqtt_pub_topic%\",\"dev\":{\"identifiers\":\"%node_id%\",\"manufacturer\":\"Rob Roos\",\"model\":\"modbusRTUrdr\",\"name\":\"ModbusRTU reader(%hostname%)\",\"sw_version\":\"%version%\"},\"uniq_id\":\"%node_id%-%label%\",\"device_class\":\"%devclass%\",\"state_class\":\"%stateclass%\",\"name\":\"%hostname%_%friendlyname%\", \"stat_t\":\"%mqtt_pub_topic%/%label%\",\"unit_of_measurement\": \"%unit%\", \"value_template\": \"{{ value }}\" }" ; - String sTopic_template = "%homeassistant%/sensor/%label%/config"; + String sTopic_template = "%homeassistant%/sensor/%node_id%/%label%/config"; String sMsg_template = "{\"avty_t\": \"%mqtt_pub_topic%\", \"dev\": {\"identifiers\": \"%node_id%\", \"manufacturer\": \"Rob Roos\", \"model\": \"modbusRTUrdr\", \"name\": \"ModbusRTU reader(%hostname%)\", \"sw_version\": \"%version%\"}, \"uniq_id\": \"%node_id%-%label%\", \"device_class\": \"%devclass%\", \"state_class\": \"%stateclass%\", \"name\": \"%hostname%_%friendlyname%\", \"stat_t\": \"%mqtt_pub_topic%/%label%\", \"unit_of_measurement\": \"%unit%\", \"value_template\": \"{{ value }}\" }"; String sTopic = ""; String sMsg = ""; diff --git a/ModbusRTU-ESP8266-webui.h b/ModbusRTU-ESP8266-webui.h index 763f518..e774ba7 100644 --- a/ModbusRTU-ESP8266-webui.h +++ b/ModbusRTU-ESP8266-webui.h @@ -1,9 +1,9 @@ /* *************************************************************************** ** Program : Modbus-firmware.h -** Version 1.10.0 +** Version 1.11.1 ** -** Copyright (c) 2022 Rob Roos +** Copyright (c) 2023 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -14,15 +14,14 @@ //#include #include -#include -#include +#include +// #include #include // https://github.com/jandrassy/TelnetStream/commit/1294a9ee5cc9b1f7e51005091e351d60c8cddecf #include // https://arduinojson.org/ #include "Wire.h" #include "ModbusStuff.h" -#include "Debug.h" #include "safeTimers.h" @@ -77,7 +76,7 @@ static ExtendedZoneManager timezoneManager( zonedbx::kZoneAndLinkRegistry, zoneProcessorCache); -const char *weekDayName[] { "Unknown", "Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Unknown" }; +const char *weekDayName[] { "Unknown", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag", "Unknown" }; const char *flashMode[] { "QIO", "QOUT", "DIO", "DOUT", "Unknown" }; @@ -123,6 +122,7 @@ bool bDebugMBlogic = false; // when set to true during compile time, Modbusmapte bool bDebugRestAPI = false; bool bDebugMQTT = false; -//Now load network suff +//Now load Debug & network library +#include "Debug.h" #include "networkStuff.h" // eof diff --git a/ModbusRTU-ESP8266-webui.ino b/ModbusRTU-ESP8266-webui.ino index 322cde2..624f8bd 100644 --- a/ModbusRTU-ESP8266-webui.ino +++ b/ModbusRTU-ESP8266-webui.ino @@ -2,9 +2,9 @@ /* *************************************************************************** ** Program : ModbusRTU-webui.ino -** Version 1.10.0 +** Version 1.11.0 ** -** Copyright (c) 2022 Rob Roos +** Copyright (c) 2023 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -16,7 +16,7 @@ * How to install the ModbusRTU-webui on your nodeMCU * * Make sure you have all required library's installed: - * - AceTime v1.8.0 - https://github.com/bxparks/AceTime + * - AceTime v2.3.0 - https://github.com/bxparks/AceTime * - TelnetStream - https://github.com/jandrassy/TelnetStream/commit/1294a9ee5cc9b1f7e51005091e351d60c8cddecf * - ArduinoJson - https://arduinojson.org/ * - modbus-esp8266 -https://github.com/emelianov/modbus-esp8266 @@ -110,7 +110,7 @@ void setup() while (settingTimebasedSwitch && settingNTPenable && (NtpStatus != TIME_SYNC)) { loopNTP(); // Make sure time is set - // delayms(1000) ; + delayms(1000) ; } // log last reset reason after all above has started @@ -245,6 +245,7 @@ void doTaskEvery30s(){ //===[ Do task every 60s ]=== void doTaskEvery60s(){ //== do tasks == + loopNTP() ; checkactivateRelay(true); //if no wifi, try reconnecting (once a minute) if (WiFi.status() != WL_CONNECTED) @@ -275,7 +276,7 @@ void doTaskEvery60s(){ //check telnet startTelnet(); } - + } // end doTaskEvery60s() @@ -287,7 +288,7 @@ void doBackgroundTasks() handleDebug(); handleMQTT(); // MQTT transmissions httpServer.handleClient(); - loopNTP(); + // loopNTP(); } yield(); } diff --git a/ModbusStuff.h b/ModbusStuff.h index 3cca88e..4381a36 100644 --- a/ModbusStuff.h +++ b/ModbusStuff.h @@ -1,9 +1,9 @@ /* *************************************************************************** ** Program : Header file: ModbusStuff.h -** Version 1.9.1 +** Version 1.11.0 ** -** Copyright (c) 2022 Rob Roos +** Copyright (c) 2023 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -11,7 +11,7 @@ *************************************************************************** */ #include // https://github.com/emelianov/modbus-esp8266 version 4.1.1 -#include "Debug.h" +// #include "Debug.h" // Modbus RTU Specific API #define MODBUS_RX D7 // RX D7 = GPIO 13 #define MODBUS_TX D5 // TX D5 = GPIO 14 diff --git a/ModbusStuff.ino b/ModbusStuff.ino index 1403aef..02d9dd0 100644 --- a/ModbusStuff.ino +++ b/ModbusStuff.ino @@ -1,9 +1,9 @@ /* *************************************************************************** ** Program : ModbusStuff -** Version 1.10.0 +** Version 1.11.0 ** -** Copyright (c) 2022 Rob Roos +** Copyright (c) 2023 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** @@ -316,7 +316,7 @@ bool Modbus_Read_int(uint16_t i) else { // this should never happen - DebugTln(PSTR("Error: Modbus Read while transaction active")); + DebugTln(F("Error: Modbus Read while transaction active")); ModbusdataObject.LastResult = 99; } @@ -364,7 +364,7 @@ bool Modbus_Read_uint(uint16_t i) else { // this should never happen - DebugTln(PSTR("Error: Modbus Read while transaction active")); + DebugTln(F("Error: Modbus Read while transaction active")); ModbusdataObject.LastResult = 99; } @@ -658,12 +658,16 @@ void readModbusSetup() if (bDebugMBmsg) Debugf(PSTR("readModbus ended \r\n")); } -void processMQcommand(const char* buf, int len) +void processMQcommand(const char* buf, unsigned int len) // analyse the incomming MQ command and process { - DebugTf(PSTR("processMQcommand")); - if (bDebugMQTT) DebugTf(PSTR("processMQcommand len: [%s] buf: [%s]\r\n"), len, buf); + DebugTln(F("processMQcommand")); + char msgPayload[50]; + int msglen = min((int)(len)+1, (int)sizeof(msgPayload)); + strlcpy(msgPayload, (char *)buf, msglen); + + if (bDebugMQTT) DebugTf(PSTR("processMQcommand len: [%d] buf: [%s]\r\n"), msglen, msgPayload); } @@ -754,7 +758,7 @@ void sendModbus(const char* buf, int len) if (bDebugMBmsg) { DebugTf(PSTR("Index1[%d],Index2[%d],Index3[%d],Index4[%d]\r\n"), Index1, Index2, Index3, Index4); - DebugTln(PSTR("ERROR: Missing parameters in Daytimemap, skip line")); + DebugTln(F("ERROR: Missing parameters in Daytimemap, skip line")); } break; } @@ -803,7 +807,8 @@ void sendModbus(const char* buf, int len) for (int i = 1; i <= 7; i++) { // DebugTf(PSTR("Day: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[i].day).c_str(), Daytimemap[i].starthour, Daytimemap[i].startmin, Daytimemap[i].endhour, Daytimemap[i].endmin); - DebugTf(PSTR("Day: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[i].day), Daytimemap[i].starthour, Daytimemap[i].startmin, Daytimemap[i].endhour, Daytimemap[i].endmin); + // DebugTf(PSTR("Day: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[i].day), Daytimemap[i].starthour, Daytimemap[i].startmin, Daytimemap[i].endhour, Daytimemap[i].endmin); + DebugTf(PSTR("Day: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), weekDayName[Daytimemap[i].day], Daytimemap[i].starthour, Daytimemap[i].startmin, Daytimemap[i].endhour, Daytimemap[i].endmin); } Debugln(); @@ -891,7 +896,7 @@ void sendModbus(const char* buf, int len) { if (bDebugMBmsg) { DebugTf(PSTR("Index1[%d],Index2[%d],Index3[%d],Index4[%d],Index5[%d],Index6[%d],Index7[%d],Index8[%d],Index9[%d],Index10[%d]\r\n"), Index1, Index2, Index3, Index4, Index5, Index6, Index7, Index8, Index9,Index10); - DebugTln(PSTR("ERROR: Missing parameters in config line, skip line")); + DebugTln(F("ERROR: Missing parameters in config line, skip line")); } break; } @@ -1078,28 +1083,35 @@ void checkactivateRelay(bool activaterelay) { loopNTP(); // Make sure time is set if (NtpStatus != TIME_SYNC) { - DebugTln(PSTR("Warning: Time not synced, exit activate relay check")); + DebugTln(F("Warning: Time not synced, exit activate relay check")); } else { - // DebugTf(PSTR("Schedule for today: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[weekday()].day).c_str(), Daytimemap[weekday()].starthour, Daytimemap[weekday()].startmin, Daytimemap[weekday()].endhour, Daytimemap[weekday()].endmin); - DebugTf(PSTR("Schedule for today: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[weekday()].day), Daytimemap[weekday()].starthour, Daytimemap[weekday()].startmin, Daytimemap[weekday()].endhour, Daytimemap[weekday()].endmin); + + time_t now = time(nullptr); + TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); + ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now, myTz); + DebugTf(PSTR("%02d:%02d:%02d %02d-%02d-%04d\r\n"), myTime.hour(), myTime.minute(), myTime.second(), myTime.day(), myTime.month(), myTime.year()); + // DebugTf(PSTR("Schedule for today: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[myTime.dayOfWeek()].day).c_str(), Daytimemap[myTime.dayOfWeek()].starthour, Daytimemap[myTime.dayOfWeek()].startmin, Daytimemap[myTime.dayOfWeek()].endhour, Daytimemap[myTime.dayOfWeek()].endmin); + // DebugTf(PSTR("Schedule for today: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), dayStr(Daytimemap[myTime.dayOfWeek()].day), Daytimemap[myTime.dayOfWeek()].starthour, Daytimemap[myTime.dayOfWeek()].startmin, Daytimemap[myTime.dayOfWeek()].endhour, Daytimemap[myTime.dayOfWeek()].endmin); + DebugTf(PSTR("Schedule for today: %s, starttime: %02d:%02d, endtime: %02d:%02d \r\n"), weekDayName[(Daytimemap[myTime.dayOfWeek()].day)], Daytimemap[myTime.dayOfWeek()].starthour, Daytimemap[myTime.dayOfWeek()].startmin, Daytimemap[myTime.dayOfWeek()].endhour, Daytimemap[myTime.dayOfWeek()].endmin); if (tempsettingRelayOn && activaterelay) { - DebugTln(PSTR("Warning: Relay Temporary On until next on cycle")); + DebugTln(F("Warning: Relay Temporary On until next on cycle")); setRelay(RELAYON); } - dagcurmin = hour() * 60 + minute(); - dagstartmin = Daytimemap[weekday()].starthour * 60 + Daytimemap[weekday()].startmin; - dagendmin = Daytimemap[weekday()].endhour * 60 + Daytimemap[weekday()].endmin ; - + // dagcurmin = hour() * 60 + minute(); + dagcurmin = myTime.hour() * 60 + myTime.minute() ; + dagstartmin = Daytimemap[myTime.dayOfWeek()].starthour * 60 + Daytimemap[myTime.dayOfWeek()].startmin; + dagendmin = Daytimemap[myTime.dayOfWeek()].endhour * 60 + Daytimemap[myTime.dayOfWeek()].endmin ; + if (dagstartmin < dagendmin) { if (dagcurmin >= dagstartmin && dagcurmin < dagendmin) { - DebugTf(PSTR("Tijd:%02d:%02d Binnen tijdslot, set relay on\r\n"), hour(), minute()); + DebugTf(PSTR("Tijd:%02d:%02d Binnen tijdslot, set relay on\r\n"), myTime.hour(), myTime.minute()); if (tempsettingRelayOn) { tempsettingRelayOn = false ; // Turn the temporary on switch of at next cycle - DebugTln(PSTR("Info: Relay Temporary On switch turned off")); + DebugTln(F("Info: Relay Temporary On switch turned off")); } if (activaterelay && statusRelay == RELAYOFF) { setRelay(RELAYON); @@ -1107,7 +1119,7 @@ void checkactivateRelay(bool activaterelay) } else { - DebugTf(PSTR("Tijd:%02d:%02d Buiten tijdslot, set relay off\r\n"), hour(), minute()); + DebugTf(PSTR("Tijd:%02d:%02d Buiten tijdslot, set relay off\r\n"), myTime.hour(), myTime.minute()); if ((activaterelay && statusRelay == RELAYON) && !tempsettingRelayOn) setRelay(RELAYOFF); } } @@ -1115,10 +1127,10 @@ void checkactivateRelay(bool activaterelay) { if (dagcurmin >= dagstartmin || dagcurmin < dagendmin) { - DebugTf(PSTR("Tijd:%02d:%02d Binnen tijdslot, set relay on\r\n"), hour(), minute()); + DebugTf(PSTR("Tijd:%02d:%02d Binnen tijdslot, set relay on\r\n"), myTime.hour(), myTime.minute()); if (tempsettingRelayOn) { tempsettingRelayOn = false ; // Turn the temporary on switch of at next cycle - DebugTln(PSTR("Info: Relay Temporary On switch turned off")); + DebugTln(F("Info: Relay Temporary On switch turned off")); } if (activaterelay && statusRelay == RELAYOFF) { setRelay(RELAYON); @@ -1126,13 +1138,13 @@ void checkactivateRelay(bool activaterelay) } else { - DebugTf(PSTR("Tijd:%02d:%02d Buiten tijdslot, set relay off\r\n"), hour(), minute()); + DebugTf(PSTR("Tijd:%02d:%02d Buiten tijdslot, set relay off\r\n"), myTime.hour(), myTime.minute()); if ((activaterelay && statusRelay == RELAYON) && !tempsettingRelayOn) setRelay(RELAYOFF); } } if (settingRelayAllwaysOnSwitch) { - DebugTln(PSTR("#$#$# WARNING, Relay set to ON")); + DebugTln(F("#$#$# WARNING, Relay set to ON")); setRelay(RELAYON) ; } if (activaterelay) DebugTf(PSTR("statusRelay[%d]\r\n"), statusRelay); diff --git a/README.md b/README.md index 7d5b3cf..ad6e88e 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,10 @@ Looking for the documentation?, see the Documentation folder (work in progress). | Version | Release notes | |-|-| -| 1.10.0 | WIP: Add on off command via MQ to switch relay (TODO), setting in UI for debug after boot, ACETIME lib update, Heap optimization | +| 1.11.1 | WIP: Add on off command via MQ to switch relay (TODO), fix Togglerelay to always work| +| 1.11.0 | BREAKING CHANGE : fix missing MQ top topic nodeid in HA config | +| 1.10.1 | WIP: Add on off command via MQ to switch relay (TODO), update core 3.1.2 | +| 1.10.0 | setting in UI for debug after boot, ACETIME lib update, Heap optimization | | 1.9.1 | Updated libraries, expanded errorlog to find reboot reason, relay allways on failed bug fixed, Wifi sleepmode off| | 1.9.0 | Breaking change , added stateclass to MQ Autoconfigure for HA , additional parameter in Modbusmap.cfg see examples| | 1.8.1 | Implement a bootlog to register reboot reason and debug info, copied from rlagerweij
Changed: removed ezTime NTP library, moved to ConfigTime NTP and AceTime | diff --git a/data/Daytimemap org.cfg b/data/Daytimemap org.cfg index ce0af51..e764667 100644 --- a/data/Daytimemap org.cfg +++ b/data/Daytimemap org.cfg @@ -1,6 +1,6 @@ # Config file for day / time based relay control -# ** Version 1.8.0 -# Copyright (c) 2022 Rob Roos +# ** Version 1.11.0 +# Copyright (c) 2023 Rob Roos # file format is CSV , all values as string without "" , fields are # day, starthour, startmin, endhour, endmin # day = daynumber, Numeric representation of the day of the week (1 = Sunday) diff --git a/data/Daytimemap.cfg b/data/Daytimemap.cfg index ce0af51..5daae30 100644 --- a/data/Daytimemap.cfg +++ b/data/Daytimemap.cfg @@ -1,9 +1,9 @@ # Config file for day / time based relay control -# ** Version 1.8.0 -# Copyright (c) 2022 Rob Roos +# ** Version 1.11.0 +# Copyright (c) 2023 Rob Roos # file format is CSV , all values as string without "" , fields are # day, starthour, startmin, endhour, endmin -# day = daynumber, Numeric representation of the day of the week (1 = Sunday) +# day = daynumber, Numeric representation of the day of the week (1 = Monday, 7 = Sunday ) # starthour = start hour of relay on # startmin = start min of relay on # endhour = end hour of relay off @@ -14,10 +14,10 @@ # Special case, whole day on # 6, 00, 00, 24, 00 # There are max 7 lines, 1 for each weekday -1, 00, 00, 24, 00 +1, 02, 00, 11, 00 2, 23, 00, 08, 00 3, 23, 00, 08, 00 4, 23, 00, 08, 00 5, 23, 00, 08, 00 -6, 23, 00, 08, 00 -7, 00, 00, 24, 00 \ No newline at end of file +6, 02, 00, 11, 00 +7, 02, 00, 11, 00 \ No newline at end of file diff --git a/data/FSexplorer.css b/data/FSexplorer.css index 3c098b8..8b0fe7b 100644 --- a/data/FSexplorer.css +++ b/data/FSexplorer.css @@ -1,9 +1,9 @@ /* *************************************************************************** ** Program : FSexplorer.html, -** Version 1.8.0 +** Version 1.11.0 ** -** Copyright (c) 2022 Rob Roos +** Copyright (c) 2023 Rob Roos ** based on Framework ESP8266 from Willem Aandewiel and modifications ** from Robert van Breemen ** For more information visit: https://fipsok.de diff --git a/data/FSexplorer.html b/data/FSexplorer.html index d8e431b..b864d52 100644 --- a/data/FSexplorer.html +++ b/data/FSexplorer.html @@ -1,9 +1,9 @@ -
2021 © Rob Roos
+
2023 © Rob Roos
-
diff --git a/data/index.js b/data/index.js index 0f7ec3e..515e08f 100644 --- a/data/index.js +++ b/data/index.js @@ -191,40 +191,50 @@ function initMainPage() { console.log("then(json => ..)"); // console.log("parsed .., data is ["+ JSON.stringify(json)+"]"); data = json.Modbusmonitor; + + let modbusMonPage = document.getElementById('mainPage'); + while (modbusMonPage.lastChild) { + modbusMonPage.lastChild.remove(); + } + let modbusMonTable = document.createElement("div"); + modbusMonTable.setAttribute("class", "modbusMonTable"); + for( let i in data ) { - document.getElementById("waiting").innerHTML = ""; + // document.getElementById("waiting").innerHTML = ""; // console.log("["+data[i].name+"]=>["+data[i].value+"]"); - var mainPage = document.getElementById('mainPage'); - if( ( document.getElementById("Modbusmon_"+data[i].name)) == null ) + // var mainPage = document.getElementById('mainPage'); + if( ( document.getElementById("modbusmon_"+data[i].name)) == null ) { // if element does not exists yet, then build page var rowDiv = document.createElement("div"); - rowDiv.setAttribute("class", "Modbusmonrow"); - //rowDiv.setAttribute("id", "Modbusmon_"+data[i].name); + rowDiv.setAttribute("class", "modbusmonrow"); + //rowDiv.setAttribute("id", "modbusmon_"+data[i].name); rowDiv.style.background = "lightblue"; //--- field Name --- var fldDiv = document.createElement("div"); - fldDiv.setAttribute("class", "Modbusmoncolumn1"); + fldDiv.setAttribute("class", "modbusmoncolumn1"); fldDiv.textContent = translateToHuman(data[i].name); rowDiv.appendChild(fldDiv); //--- Value --- var valDiv = document.createElement("div"); - valDiv.setAttribute("class", "Modbusmoncolumn2"); - valDiv.setAttribute("id", "Modbusmon_"+data[i].name); + valDiv.setAttribute("class", "modbusmoncolumn2"); + valDiv.setAttribute("id", "modbusmon_"+data[i].name); valDiv.textContent = data[i].value; rowDiv.appendChild(valDiv); //--- Unit --- var unitDiv = document.createElement("div"); - unitDiv.setAttribute("class", "Modbusmoncolumn3"); + unitDiv.setAttribute("class", "modbusmoncolumn3"); unitDiv.textContent = data[i].unit; rowDiv.appendChild(unitDiv); - mainPage.appendChild(rowDiv); + modbusMonTable.appendChild(rowDiv); } else { //if the element exists, then update the value - document.getElementById("Modbusmon_"+data[i].name).textContent = data[i].value; + document.getElementById("modbusmon_"+data[i].name).textContent = data[i].value; } } + modbusMonPage.appendChild(modbusMonTable); + if (needReload) window.location.reload(true); }) .catch(function(error) { @@ -558,6 +568,7 @@ function sendPostSetting(field, value) { , ["wifirestart", "Wifi restart count (reset at reboot)"] , ["rebootcount", "ESP reboot count"] , ["modbusreaderrors", "Modbus read errors"] + , ["lastmqcmd", "Last MQ command received"] ]; /* diff --git a/jsonStuff.ino b/jsonStuff.ino index c474c51..53a16d7 100644 --- a/jsonStuff.ino +++ b/jsonStuff.ino @@ -10,35 +10,48 @@ ** TERMS OF USE: MIT License. See bottom of file. *************************************************************************** */ -static char objSprtr[10] = ""; +static int iIdentlevel = 0; +char sBeforenext[10] =""; +bool bFirst = true; + //======================================================================= void sendStartJsonObj(const char *objName) { char sBuff[50] = ""; - objSprtr[0] = '\0'; + sBeforenext[0]='\0'; - snprintf(sBuff, sizeof(sBuff), "{\"%s\":[\r\n", objName); + if (strlen(objName)==0){ + snprintf(sBuff, sizeof(sBuff), "{\r\n"); + }else { + snprintf(sBuff, sizeof(sBuff), "{\"%s\":[\r\n", objName); + } httpServer.sendHeader("Access-Control-Allow-Origin", "*"); httpServer.setContentLength(CONTENT_LENGTH_UNKNOWN); httpServer.send(200, "application/json", sBuff); + iIdentlevel++; + bFirst = true; } // sendStartJsonObj() - //======================================================================= -// void sendEndJsonObj() -// { -// httpServer.sendContent("\r\n]}\r\n"); -// //httpServer.sendHeader( "Content-Length", "0"); -// //httpServer.send ( 200, "application/json", ""); - -// } // sendEndJsonObj() +void sendIdent(){ + for (int i = iIdentlevel; i >0; i--){ + httpServer.sendContent(" "); + } +} //sendIdent() +//======================================================================= +void sendBeforenext(){ + if (!bFirst){ + httpServer.sendContent(",\r\n"); + } + bFirst = false; +} //sendBeforenext() void sendEndJsonObj(const char *objName) { - // iIdentlevel--; + iIdentlevel--; if (strlen(objName)==0){ httpServer.sendContent("\r\n}\r\n"); } else { @@ -52,11 +65,11 @@ void sendNestedJsonObj(const char *cName, const char *cValue) { char jsonBuff[JSON_BUFF_MAX] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": \"%s\"}" - , objSprtr, cName, cValue); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": \"%s\"}", cName, cValue); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendNestedJsonObj(*char, *char) @@ -71,11 +84,11 @@ void sendNestedJsonObj(const char *cName, String sValue) DebugTf(PSTR("[2] sValue.length() [%d]\r\n"), sValue.length()); } - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": \"%s\"}" - , objSprtr, cName, sValue.c_str()); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": \"%s\"}", cName, sValue.c_str()); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendNestedJsonObj(*char, String) @@ -85,11 +98,11 @@ void sendNestedJsonObj(const char *cName, int32_t iValue) { char jsonBuff[200] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %d}" - , objSprtr, cName, iValue); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %d}", cName, iValue); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendNestedJsonObj(*char, int) @@ -98,11 +111,11 @@ void sendNestedJsonObj(const char *cName, uint32_t uValue) { char jsonBuff[200] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %u }" - , objSprtr, cName, uValue); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %u}", cName, uValue); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendNestedJsonObj(*char, uint) @@ -112,11 +125,11 @@ void sendNestedJsonObj(const char *cName, float fValue) { char jsonBuff[200] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %.3f }" - , objSprtr, cName, fValue); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %.3f}", cName, fValue); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendNestedJsonObj(*char, float) @@ -125,11 +138,12 @@ void sendJsonModbusmonObj(const char *cName, const char *cValue, const char *cUn { char jsonBuff[JSON_BUFF_MAX] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": \"%s\", \"unit\": \"%s\"}" - , objSprtr, cName, cValue, cUnit); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": \"%s\", \"unit\": \"%s\"}" + , cName, cValue, cUnit); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendJsonModbusmonObj(*char, *char, *char) @@ -138,11 +152,12 @@ void sendJsonModbusmonObj(const char *cName, int32_t iValue, const char *cUnit) { char jsonBuff[200] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %d, \"unit\": \"%s\"}" - , objSprtr, cName, iValue, cUnit); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %d, \"unit\": \"%s\"}" + , cName, iValue, cUnit); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendJsonModbusmonObj(*char, int, *char) @@ -151,11 +166,12 @@ void sendJsonModbusmonObj(const char *cName, uint32_t uValue, const char *cUnit) { char jsonBuff[200] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %u, \"unit\": \"%s\"}" - , objSprtr, cName, uValue, cUnit); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %u, \"unit\": \"%s\"}" + , cName, uValue, cUnit); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendNestedJsonObj(*char, uint, *char) @@ -165,11 +181,12 @@ void sendJsonModbusmonObj(const char *cName, float fValue, const char *cUnit) { char jsonBuff[200] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %.2f, \"unit\": \"%s\"}" - , objSprtr, cName, fValue, cUnit); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %.2f, \"unit\": \"%s\"}" + , cName, fValue, cUnit); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendJsonModbusmonObj(*char, float, *char) @@ -181,11 +198,12 @@ void sendJsonSettingObj(const char *cName, float fValue, const char *fType, int { char jsonBuff[200] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %.3f, \"type\": \"%s\", \"min\": %d, \"max\": %d}" - , objSprtr, cName, fValue, fType, minValue, maxValue); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %.3f, \"type\": \"%s\", \"min\": %d, \"max\": %d}" + , cName, fValue, fType, minValue, maxValue); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendJsonSettingObj(*char, float, *char, int, int) @@ -197,25 +215,26 @@ void sendJsonSettingObj(const char *cName, float fValue, const char *fType, int switch(decPlaces) { case 0: - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %.0f, \"type\": \"%s\", \"min\": %d, \"max\": %d}" - , objSprtr, cName, fValue, fType, minValue, maxValue); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %.0f, \"type\": \"%s\", \"min\": %d, \"max\": %d}" + , cName, fValue, fType, minValue, maxValue); break; case 2: - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %.2f, \"type\": \"%s\", \"min\": %d, \"max\": %d}" - , objSprtr, cName, fValue, fType, minValue, maxValue); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %.2f, \"type\": \"%s\", \"min\": %d, \"max\": %d}" + , cName, fValue, fType, minValue, maxValue); break; case 5: - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %.5f, \"type\": \"%s\", \"min\": %d, \"max\": %d}" - , objSprtr, cName, fValue, fType, minValue, maxValue); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %.5f, \"type\": \"%s\", \"min\": %d, \"max\": %d}" + , cName, fValue, fType, minValue, maxValue); break; default: - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %f, \"type\": \"%s\", \"min\": %d, \"max\": %d}" - , objSprtr, cName, fValue, fType, minValue, maxValue); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %f, \"type\": \"%s\", \"min\": %d, \"max\": %d}" + , cName, fValue, fType, minValue, maxValue); } + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendJsonSettingObj(*char, float, *char, int, int, int) @@ -224,11 +243,12 @@ void sendJsonSettingObj(const char *cName, bool bValue, const char *bType) { char jsonBuff[200] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\":\"%s\", \"type\": \"%s\"}" - , objSprtr, cName, CBOOLEAN(bValue), bType); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\":\"%s\", \"type\": \"%s\"}" + , cName, CBOOLEAN(bValue), bType); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendJsonSettingObj(*char, bool, *char) //======================================================================= @@ -236,11 +256,12 @@ void sendJsonSettingObj(const char *cName, int iValue, const char *iType, int mi { char jsonBuff[200] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\": %d, \"type\": \"%s\", \"min\": %d, \"max\": %d, \"step\": %d}" - ,objSprtr, cName, iValue, iType, minValue, maxValue, stepValue); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\": %d, \"type\": \"%s\", \"min\": %d, \"max\": %d, \"step\": %d}" + , cName, iValue, iType, minValue, maxValue, stepValue); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendJsonSettingObj(*char, int, *char, int, int, int) @@ -250,11 +271,12 @@ void sendJsonSettingObj(const char *cName, const char *cValue, const char *sType { char jsonBuff[200] = ""; - snprintf(jsonBuff, sizeof(jsonBuff), "%s{\"name\": \"%s\", \"value\":\"%s\", \"type\": \"%s\", \"maxlen\": %d}" - , objSprtr, cName, cValue, sType, maxLen); + snprintf(jsonBuff, sizeof(jsonBuff), "{\"name\": \"%s\", \"value\":\"%s\", \"type\": \"%s\", \"maxlen\": %d}" + , cName, cValue, sType, maxLen); + sendBeforenext(); + sendIdent(); httpServer.sendContent(jsonBuff); - sprintf(objSprtr, ",\r\n"); } // sendJsonSettingObj(*char, *char, *char, int, int) diff --git a/restAPI.ino b/restAPI.ino index aa5c003..a0c9c4a 100644 --- a/restAPI.ino +++ b/restAPI.ino @@ -93,10 +93,12 @@ void processAPI() else if (words[3] == "relayToggle"){ if (tempsettingRelayOn ) { tempsettingRelayOn = false ; + lastMQcommandrcvd = "" ; setRelay(RELAYOFF); } else { tempsettingRelayOn = true ; + lastMQcommandrcvd = "" ; setRelay(RELAYON); } // Set the relay according to the schedule and the tempsetting @@ -212,15 +214,19 @@ void sendModbusmonitor() sendStartJsonObj("Modbusmonitor"); if (ModbusdataObject.NumberRegisters == 0) sendJsonModbusmonObj("ERROR: No or invalid config file", "NO FILE", "ERR"); - - if (settingTimebasedSwitch && settingNTPenable) { + + if (lastMQcommandrcvd != "" ) sendJsonModbusmonObj("Last MQ command", lastMQcommandrcvd.c_str(), ""); + + if (settingTimebasedSwitch) { if (settingRelayAllwaysOnSwitch) { sendJsonModbusmonObj("Warning: Relay set to allways", "ON", ""); } - - } else if (!settingNTPenable) { + else if (!settingNTPenable) { sendJsonModbusmonObj("Timebasedswitching", "NO NTP", "ERR"); + } + else sendJsonModbusmonObj("Timebasedswitching", "Active", ""); } + else sendJsonModbusmonObj("Timebasedswitching", "Disabled", ""); if (tempsettingRelayOn) { sendJsonModbusmonObj("Warning: Relay temp. set to", "ON", ""); @@ -330,7 +336,8 @@ void sendDeviceInfo() sendNestedJsonObj("lastreset", lastReset); sendNestedJsonObj("modbusreaderrors", ModbusdataObject.ModbusErrors); - + + sendNestedJsonObj("lastmqcmd", lastMQcommandrcvd.c_str()); sendEndJsonObj("devinfo"); diff --git a/version.h b/version.h index 8370ad7..e29e045 100644 --- a/version.h +++ b/version.h @@ -2,15 +2,15 @@ #define _VERSION_MAJOR 1 #define _VERSION_MINOR 11 #define _VERSION_PATCH 1 -#define _VERSION_BUILD 519 +#define _VERSION_BUILD 530 #define _VERSION_GITHASH "0000000" #define _VERSION_PRERELEASE beta -#define _VERSION_DATE "29/07/2023" -#define _VERSION_TIME "22:20:23" +#define _VERSION_DATE "31/07/2023" +#define _VERSION_TIME "14:32:14" #define _SEMVER_CORE "1.11.1" -#define _SEMVER_BUILD "1.11.1+519" +#define _SEMVER_BUILD "1.11.1+530" #define _SEMVER_GITHASH "1.11.1+0000000" -#define _SEMVER_FULL "1.11.1 beta (29/07/2023)" -#define _SEMVER_NOBUILD "1.11.1 (29/07/2023)" -#define _VERSION "1.11.1+519 (29/07/2023)" +#define _SEMVER_FULL "1.11.1 beta (31/07/2023)" +#define _SEMVER_NOBUILD "1.11.1 (31/07/2023)" +#define _VERSION "1.11.1+530 (31/07/2023)" //The version information is created automatically, more information here: https://github.com/rvdbreemen/autoinc-semver