diff --git a/CHANGELOG.md b/CHANGELOG.md index 8baf20f0d..784a34b2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.5.5] 2019-03-07 + +### Fixed +- Support the latest ArduinoJson v6 and espressif8266 2.0.4 libraries (in PlatformIO do a `pio lib update` and `pio update`) + +### Changed + +- MQTT keep alive to 2 minutes (60 seconds was just too short for slower networks) +- Improved MQTT startup time +- Setting wifi or mqtt settings are immediate, no need to restart the ESP +- Text changes in the help + +### Added +- Show if MQTT is connected +- Show version of MyESP (the custom MQTT, Wifi, OTA, MDNS, Telnet library) +- EMS-OT OpenTherm connector + ## [1.5.4] 2019-03-03 ### Changed @@ -14,7 +31,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Callback for OTA. This is used to disable EMS bus during a firmware OTA update, which caused problems with the latest ESP89266 core libraries - Added rough estimate of WiFi signal strength to info page -- Added the build time & date to the info page (optional in platformio.ini)## [1.5.3] 2019-02-22 +- Added the build time & date to the info page (optional in platformio.ini) + +## [1.5.3] 2019-02-22 ### Changed @@ -84,7 +103,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - some minor improvements to autodetect - ## [1.4.0] 2019-01-27 ### Changed diff --git a/README.md b/README.md index a1720f54b..ba258a043 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ EMS-ESP is a project to build an electronic controller circuit using an Espressi There are 3 parts to this project, first the design of the circuit, secondly the code for the ESP8266 microcontroller firmware with telnet and MQTT support, and lastly an example configuration for Home Assistant to monitor the data and issue direct commands via a MQTT broker. [![Codacy Badge](https://api.codacy.com/project/badge/Grade/b8880625bdf841d4adb2829732030887)](https://app.codacy.com/app/proddy/EMS-ESP?utm_source=github.com&utm_medium=referral&utm_content=proddy/EMS-ESP&utm_campaign=Badge_Grade_Settings) -[![version](https://img.shields.io/badge/version-1.5.4-brightgreen.svg)](CHANGELOG.md) +[![version](https://img.shields.io/badge/version-1.5.5-brightgreen.svg)](CHANGELOG.md) - [EMS-ESP](#ems-esp) - [Introduction](#introduction) diff --git a/firmware/firmware_d1_mini.bin b/firmware/emsesp_155_d1_mini.bin similarity index 53% rename from firmware/firmware_d1_mini.bin rename to firmware/emsesp_155_d1_mini.bin index 15ca8a6fc..154585dce 100644 Binary files a/firmware/firmware_d1_mini.bin and b/firmware/emsesp_155_d1_mini.bin differ diff --git a/lib/myESP/MyESP.cpp b/lib/myESP/MyESP.cpp index 93398633b..46a5736a7 100644 --- a/lib/myESP/MyESP.cpp +++ b/lib/myESP/MyESP.cpp @@ -2,21 +2,27 @@ * MyESP - my ESP helper class to handle Wifi, MQTT and Telnet * * Paul Derbyshire - December 2018 - * Version 1.1 - Feb 22 2019. Added support for ESP32 - * Version 1.1.1 - March 3 2019. Added OTA callback * * Ideas borrowed from Espurna https://github.com/xoseperez/espurna */ #include "MyESP.h" +#define RTC_LEAP_YEAR(year) ((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0)) + +/* Days in a month */ +static uint8_t RTC_Months[2][12] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* Not leap year */ + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} /* Leap year */ +}; + // constructor MyESP::MyESP() { _app_hostname = strdup("MyESP"); _app_name = strdup("MyESP"); - _app_version = strdup("1.1.1"); + _app_version = strdup(MYESP_VERSION); - _boottime = strdup("unknown"); + _boottime = strdup(""); _load_average = 100; // calculated load average _telnetcommand_callback = NULL; @@ -42,14 +48,14 @@ MyESP::MyESP() { _mqtt_topic = NULL; _mqtt_qos = 0; _mqtt_reconnect_delay = MQTT_RECONNECT_DELAY_MIN; + _mqtt_last_connection = 0; + _mqtt_connecting = false; _wifi_password = NULL; _wifi_ssid = NULL; _wifi_callback = NULL; _wifi_connected = false; - _ota_callback = NULL; - _suspendOutput = false; } @@ -240,6 +246,8 @@ void MyESP::_mqttOnConnect() { myDebug_P(PSTR("[MQTT] Connected")); _mqtt_reconnect_delay = MQTT_RECONNECT_DELAY_MIN; + _mqtt_last_connection = millis(); + // say we're alive to the Last Will topic mqttClient.publish(_mqttTopic(_mqtt_will_topic), 1, true, _mqtt_will_online_payload); @@ -253,8 +261,6 @@ void MyESP::_mqtt_setup() { myDebug_P(PSTR("[MQTT] disabled")); } - _mqtt_reconnect_delay = MQTT_RECONNECT_DELAY_MIN; - mqttClient.onConnect([this](bool sessionPresent) { _mqttOnConnect(); }); mqttClient.onDisconnect([this](AsyncMqttClientDisconnectReason reason) { @@ -274,6 +280,10 @@ void MyESP::_mqtt_setup() { if (reason == AsyncMqttClientDisconnectReason::MQTT_NOT_AUTHORIZED) { myDebug_P(PSTR("[MQTT] Not authorized")); } + + // Reset reconnection delay + _mqtt_last_connection = millis(); + _mqtt_connecting = false; }); //mqttClient.onSubscribe([this](uint16_t packetId, uint8_t qos) { myDebug_P(PSTR("[MQTT] Subscribe ACK for PID %d"), packetId); }); @@ -391,15 +401,6 @@ void MyESP::_telnet_setup() { memset(_command, 0, TELNET_MAX_COMMAND_LENGTH); } - -#define RTC_LEAP_YEAR(year) ((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0)) - -/* Days in a month */ -static uint8_t RTC_Months[2][12] = { - {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* Not leap year */ - {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} /* Leap year */ -}; - // https://stackoverflow.com/questions/43063071/the-arduino-ntp-i-want-print-out-datadd-mm-yyyy void MyESP::_printBuildTime(unsigned long unix) { // compensate for summer/winter time and CET. Can't be bothered to work out DST. @@ -462,7 +463,7 @@ void MyESP::_consoleShowHelp() { SerialAndTelnet.println(); if (WiFi.getMode() & WIFI_AP) { - SerialAndTelnet.printf("* ESP8266 is in AP mode with SSID %s", jw.getAPSSID().c_str()); + SerialAndTelnet.printf("* ESP is in AP mode with SSID %s", jw.getAPSSID().c_str()); SerialAndTelnet.println(); } else { #if defined(ARDUINO_ARCH_ESP32) @@ -477,6 +478,7 @@ void MyESP::_consoleShowHelp() { #ifdef ARDUINO_BOARD SerialAndTelnet.printf(" Board: %s", ARDUINO_BOARD); #endif + SerialAndTelnet.printf(" (MyESP v%s)", MYESP_VERSION); #ifdef BUILD_TIME SerialAndTelnet.print(" (Build "); @@ -486,10 +488,13 @@ void MyESP::_consoleShowHelp() { SerialAndTelnet.println(); SerialAndTelnet.printf("* Connected to WiFi SSID: %s (signal %d%%)", WiFi.SSID().c_str(), getWifiQuality()); SerialAndTelnet.println(); + SerialAndTelnet.printf("* MQTT is %s", mqttClient.connected() ? "connected" : "disconnected"); + SerialAndTelnet.println(); SerialAndTelnet.printf("* Boot time: %s", _boottime); SerialAndTelnet.println(); } - SerialAndTelnet.printf("* Free RAM:%d KB, Load:%d%%", (ESP.getFreeHeap() / 1024), getSystemLoadAverage()); + + SerialAndTelnet.printf("* Free RAM: %d KB Load: %d%%", (ESP.getFreeHeap() / 1024), getSystemLoadAverage()); SerialAndTelnet.println(); // for battery power is ESP.getVcc() @@ -498,7 +503,7 @@ void MyESP::_consoleShowHelp() { SerialAndTelnet.println(FPSTR("* ?=help, CTRL-D=quit")); SerialAndTelnet.println(FPSTR("* reboot")); SerialAndTelnet.println(FPSTR("* set")); - SerialAndTelnet.println(FPSTR("* set wifi ")); + SerialAndTelnet.println(FPSTR("* set wifi [ssid] [password]")); SerialAndTelnet.println(FPSTR("* set [value]")); SerialAndTelnet.println(FPSTR("* set erase")); SerialAndTelnet.println(FPSTR("* set serial")); @@ -538,8 +543,7 @@ void MyESP::resetESP() { // read next word from string buffer char * MyESP::_telnet_readWord() { - char * word = strtok(NULL, ", \n"); - return word; + return (strtok(NULL, ", \n")); } // change setting for 2 params (set ) @@ -561,7 +565,10 @@ void MyESP::_changeSetting2(const char * setting, const char * value1, const cha } (void)fs_saveConfig(); - SerialAndTelnet.println("Wifi credentials set. Type 'reboot' to restart..."); + SerialAndTelnet.println("WiFi settings changed. Reconnecting..."); + jw.disconnect(); + jw.cleanNetworks(); + jw.addNetwork(_wifi_ssid, _wifi_password); } } @@ -778,15 +785,20 @@ void MyESP::_telnetHandle() { // ensure we have a connection to MQTT broker void MyESP::_mqttConnect() { - if (!_mqtt_host || mqttClient.connected() || (WiFi.status() != WL_CONNECTED)) { + if (!_mqtt_host) + return; // MQTT not enabled + + // Do not connect if already connected or still trying to connect + if (mqttClient.connected() || _mqtt_connecting || (WiFi.status() != WL_CONNECTED)) { return; } // Check reconnect interval - static unsigned long last = 0; - if (millis() - last < _mqtt_reconnect_delay) + if (millis() - _mqtt_last_connection < _mqtt_reconnect_delay) { return; - last = millis(); + } + + _mqtt_connecting = true; // we're doing a connection // Increase the reconnect delay _mqtt_reconnect_delay += MQTT_RECONNECT_DELAY_STEP; @@ -801,7 +813,7 @@ void MyESP::_mqttConnect() { // last will if (_mqtt_will_topic) { - myDebug_P(PSTR("[MQTT] Setting last will topic %s"), _mqttTopic(_mqtt_will_topic)); + //myDebug_P(PSTR("[MQTT] Setting last will topic %s"), _mqttTopic(_mqtt_will_topic)); mqttClient.setWill(_mqttTopic(_mqtt_will_topic), 1, true, _mqtt_will_offline_payload); // retain always true } @@ -923,15 +935,21 @@ char * MyESP::_mqttTopic(const char * topic) { // print contents of file -// assume Serial is open +// assumes Serial is open void MyESP::_fs_printConfig() { myDebug_P(PSTR("[FS] Contents:")); File configFile = SPIFFS.open(MYEMS_CONFIG_FILE, "r"); + if (!configFile) { + Serial.println(F("[FS] Failed to read file for printing")); + return; + } + while (configFile.available()) { SerialAndTelnet.print((char)configFile.read()); } - myDebug_P(PSTR("")); + SerialAndTelnet.println(); + configFile.close(); } @@ -965,14 +983,15 @@ bool MyESP::_fs_loadConfig() { return false; } - // assign buffer - std::unique_ptr buf(new char[size]); + StaticJsonDocument doc; + JsonObject json = doc.to(); - // use configFile.readString - configFile.readBytes(buf.get(), size); - - StaticJsonBuffer jsonBuffer; - JsonObject & json = jsonBuffer.parseObject(buf.get()); + // Deserialize the JSON document + DeserializationError error = deserializeJson(doc, configFile); + if (error) { + Serial.println(F("[FS] Failed to read file")); + return false; + } const char * value; @@ -991,18 +1010,12 @@ bool MyESP::_fs_loadConfig() { value = json["mqtt_password"]; _mqtt_password = (value) ? strdup(value) : NULL; + _use_serial = (bool)json["use_serial"]; + // callback for loading custom settings // ok is false if there's a problem loading a custom setting (e.g. does not exist) bool ok = (_fs_callback)(MYESP_FSACTION_LOAD, json); - // new configs after release 1.3.x - if (json.containsKey("use_serial")) { - _use_serial = (bool)json["use_serial"]; - } else { - _use_serial = false; // if first time, set serial to off - ok = false; - } - configFile.close(); return ok; @@ -1010,9 +1023,10 @@ bool MyESP::_fs_loadConfig() { // save settings to spiffs bool MyESP::fs_saveConfig() { - StaticJsonBuffer jsonBuffer; - JsonObject & json = jsonBuffer.createObject(); + StaticJsonDocument doc; + JsonObject json = doc.to(); + json["app_version"] = _app_version; json["wifi_ssid"] = _wifi_ssid; json["wifi_password"] = _wifi_password; json["mqtt_host"] = _mqtt_host; @@ -1029,7 +1043,10 @@ bool MyESP::fs_saveConfig() { return false; } - json.printTo(configFile); + // Serialize JSON to file + if (serializeJson(json, configFile) == 0) { + Serial.println(F("[FS] Failed to write to file")); + } configFile.close(); @@ -1042,16 +1059,17 @@ bool MyESP::fs_saveConfig() { void MyESP::_fs_setup() { if (!SPIFFS.begin()) { Serial.println("[FS] Failed to mount the file system"); + _fs_eraseConfig(); // fix for ESP32 return; } - // load the config file. if it doesn't exist create it + // load the config file. if it doesn't exist (function returns false) create it if (!_fs_loadConfig()) { - Serial.println("[FS] Re-creating config file"); + // Serial.println("[FS] Re-creating config file"); fs_saveConfig(); } - // _fs_printConfig(); // for debugging + // _fs_printConfig(); // TODO: for debugging } uint16_t MyESP::getSystemLoadAverage() { @@ -1078,7 +1096,8 @@ void MyESP::_calculateLoad() { } } -// return true if wifi is connected: +// return true if wifi is connected +// WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library // WL_IDLE_STATUS = 0, // WL_NO_SSID_AVAIL = 1, // WL_SCAN_COMPLETED = 2, @@ -1091,13 +1110,16 @@ bool MyESP::isWifiConnected() { } /* - * Return the quality (Received Signal Strength Indicator) of the WiFi network. - * Returns -1 if WiFi is disconnected. - * High quality: 90% ~= -55dBm - * Medium quality: 50% ~= -75dBm - * Low quality: 30% ~= -85dBm - * Unusable quality: 8% ~= -96dBm - */ + Return the quality (Received Signal Strength Indicator) + of the WiFi network. + Returns a number between 0 and 100 if WiFi is connected. + Returns -1 if WiFi is disconnected. + + High quality: 90% ~= -55dBm + Medium quality: 50% ~= -75dBm + Low quality: 30% ~= -85dBm + Unusable quality: 8% ~= -96dBm +*/ int MyESP::getWifiQuality() { if (WiFi.status() != WL_CONNECTED) return -1; diff --git a/lib/myESP/MyESP.h b/lib/myESP/MyESP.h index 2753add6f..773d3014e 100644 --- a/lib/myESP/MyESP.h +++ b/lib/myESP/MyESP.h @@ -1,5 +1,5 @@ /* - * MyEsp.h + * MyESP.h * * Paul Derbyshire - December 2018 */ @@ -9,6 +9,8 @@ #ifndef MyEMS_h #define MyEMS_h +#define MYESP_VERSION "1.1.4" + #include #include #include // https://github.com/marvinroger/async-mqtt-client and for ESP32 see https://github.com/marvinroger/async-mqtt-client/issues/127 @@ -38,8 +40,8 @@ // MQTT #define MQTT_PORT 1883 // MQTT port -#define MQTT_RECONNECT_DELAY_MIN 5000 // Try to reconnect in 5 seconds upon disconnection -#define MQTT_RECONNECT_DELAY_STEP 5000 // Increase the reconnect delay in 5 seconds after each failed attempt +#define MQTT_RECONNECT_DELAY_MIN 2000 // Try to reconnect in 3 seconds upon disconnection +#define MQTT_RECONNECT_DELAY_STEP 3000 // Increase the reconnect delay in 3 seconds after each failed attempt #define MQTT_RECONNECT_DELAY_MAX 120000 // Set reconnect time to 2 minutes at most #define MQTT_MAX_SIZE 600 // max length of MQTT message #define MQTT_MAX_TOPIC_SIZE 50 // max length of MQTT message @@ -68,7 +70,6 @@ #define COLOR_BOLD_ON "\x1B[1m" #define COLOR_BOLD_OFF "\x1B[21m" - // SPIFFS #define SPIFFS_MAXSIZE 500 // https://arduinojson.org/v5/assistant/ @@ -84,7 +85,7 @@ typedef std::function typedef std::function ota_callback_f; typedef std::function telnetcommand_callback_f; typedef std::function telnet_callback_f; -typedef std::function fs_callback_f; +typedef std::function fs_callback_f; typedef std::function fs_settings_callback_f; // calculates size of an 2d array at compile time @@ -165,6 +166,8 @@ class MyESP { char * _mqtt_will_online_payload; char * _mqtt_will_offline_payload; char * _mqtt_topic; + unsigned long _mqtt_last_connection; + bool _mqtt_connecting; // wifi DNSServer dnsServer; // For Access Point (AP) support diff --git a/platformio.ini-example b/platformio.ini-example index dc3b61954..fdbbeb257 100644 --- a/platformio.ini-example +++ b/platformio.ini-example @@ -16,8 +16,8 @@ lib_deps = CircularBuffer JustWifi AsyncMqttClient -; ArduinoJson - https://github.com/bblanchon/ArduinoJson#v5.13.5 + ArduinoJson +; https://github.com/bblanchon/ArduinoJson#v5.13.5 OneWire [env:d1_mini] diff --git a/src/ems-esp.ino b/src/ems-esp.ino index d6c51965a..396e7280e 100644 --- a/src/ems-esp.ino +++ b/src/ems-esp.ino @@ -79,24 +79,24 @@ command_t PROGMEM project_cmds[] = { {"set led ", "toggle status LED on/off"}, {"set led_gpio ", "set the LED pin. Default is the onboard LED (D1=5)"}, - {"set dallas_gpio ", "set the pin for the external Dallas temperature sensor (D5=14)"}, - {"set thermostat_type ", "set the thermostat type id (e.g. 10 for 0x10)"}, - {"set boiler_type ", "set the boiler type id (e.g. 8 for 0x08)"}, - {"info", "show the values"}, + {"set dallas_gpio ", "set the pin for external Dallas temperature sensors (D5=14)"}, + {"set thermostat_type ", "set the thermostat type id (e.g. 10 for 0x10)"}, + {"set boiler_type ", "set the boiler type id (e.g. 8 for 0x08)"}, + {"info", "show data captured on the EMS bus"}, {"log ", "set logging mode to none, basic, thermostat only, raw or verbose"}, - {"publish", "publish values to MQTT"}, + {"publish", "forice a publish of all values to MQTT"}, {"types", "list supported EMS telegram type IDs"}, - {"queue", "list Tx queue"}, - {"autodetect", "discover EMS devices and set boiler and thermostat automatically"}, + {"queue", "show current Tx queue"}, + {"autodetect", "discover EMS devices and attempt to automatically set boiler and thermostat"}, {"shower ", "toggle either timer or alert on/off"}, - {"send XX...", "send raw telegram data in hex to EMS bus"}, - {"thermostat read ", "send read request to thermostat"}, + {"send XX ...", "send raw telegram data as hex to EMS bus"}, + {"thermostat read ", "send read request to the thermostat"}, {"thermostat temp ", "set current thermostat temperature"}, {"thermostat mode ", "set mode (0=low/night, 1=manual/day, 2=auto)"}, - {"thermostat scan ", "do a force read on all type IDs starting at n"}, - {"boiler read ", "send read request to boiler"}, - {"boiler wwtemp ", "set warm water temperature"}, - {"boiler tapwater ", "set warm tap water on or off"} + {"thermostat scan ", "do a read on all type IDs"}, + {"boiler read ", "send read request to boiler"}, + {"boiler wwtemp ", "set boiler warm water temperature"}, + {"boiler tapwater ", "set boiler warm tap water on/off"} }; @@ -400,7 +400,7 @@ void showInfo() { // show the Shower Info if (EMSESP_Status.shower_timer) { myDebug("%sShower stats:%s", COLOR_BOLD_ON, COLOR_BOLD_OFF); - myDebug(" Shower Timer is %s", (EMSESP_Shower.showerOn ? "active" : "off")); + myDebug(" Shower is %s", (EMSESP_Shower.showerOn ? "running" : "off")); } } @@ -408,18 +408,18 @@ void showInfo() { // a json object is created for the boiler and one for the thermostat // CRC check is done to see if there are changes in the values since the last send to avoid too much wifi traffic void publishValues(bool force) { - char s[20] = {0}; // for formatting strings - StaticJsonBuffer jsonBuffer; - char data[MQTT_MAX_SIZE] = {0}; - JsonObject & rootBoiler = jsonBuffer.createObject(); - size_t rlen; - CRC32 crc; - uint32_t fchecksum; + char s[20] = {0}; // for formatting strings + StaticJsonDocument doc; + char data[MQTT_MAX_SIZE] = {0}; + CRC32 crc; + uint32_t fchecksum; static uint8_t last_boilerActive = 0xFF; // for remembering last setting of the tap water or heating on/off static uint32_t previousBoilerPublishCRC = 0; // CRC check static uint32_t previousThermostatPublishCRC = 0; // CRC check + JsonObject rootBoiler = doc.to(); + rootBoiler["wWSelTemp"] = _int_to_char(s, EMS_Boiler.wWSelTemp); rootBoiler["selFlowTemp"] = _float_to_char(s, EMS_Boiler.selFlowTemp); rootBoiler["outdoorTemp"] = _float_to_char(s, EMS_Boiler.extTemp); @@ -443,11 +443,10 @@ void publishValues(bool force) { rootBoiler["pumpMod"] = _int_to_char(s, EMS_Boiler.pumpMod); rootBoiler["ServiceCode"] = EMS_Boiler.serviceCodeChar; - rlen = rootBoiler.measureLength(); - rootBoiler.printTo(data, rlen + 1); // form the json string + serializeJson(doc, data, sizeof(data)); // calculate hash and send values if something has changed, to save unnecessary wifi traffic - for (size_t i = 0; i < rlen - 1; i++) { + for (size_t i = 0; i < measureJson(doc) - 1; i++) { crc.update(data[i]); } fchecksum = crc.finalize(); @@ -470,13 +469,16 @@ void publishValues(bool force) { } // handle the thermostat values separately - if (ems_getThermostatEnabled()) { + //if (ems_getThermostatEnabled()) { + if (true) { // only send thermostat values if we actually have them if (((int)EMS_Thermostat.curr_roomTemp == (int)0) || ((int)EMS_Thermostat.setpoint_roomTemp == (int)0)) return; - // build json object - JsonObject & rootThermostat = jsonBuffer.createObject(); + // build new json object + doc.clear(); + JsonObject rootThermostat = doc.to(); + rootThermostat[THERMOSTAT_CURRTEMP] = _float_to_char(s, EMS_Thermostat.curr_roomTemp); rootThermostat[THERMOSTAT_SELTEMP] = _float_to_char(s, EMS_Thermostat.setpoint_roomTemp); @@ -500,12 +502,11 @@ void publishValues(bool force) { } data[0] = '\0'; // reset data for next package - rlen = rootThermostat.measureLength(); - rootThermostat.printTo(data, rlen + 1); // form the json string + serializeJson(doc, data, sizeof(data)); // calculate new CRC crc.reset(); - for (size_t i = 0; i < rlen - 1; i++) { + for (size_t i = 0; i < measureJson(doc) - 1; i++) { crc.update(data[i]); } uint32_t checksum = crc.finalize(); @@ -579,48 +580,34 @@ void startThermostatScan(uint8_t start) { } // callback for loading/saving settings to the file system (SPIFFS) -bool FSCallback(MYESP_FSACTION action, JsonObject & json) { - bool ok = true; +bool FSCallback(MYESP_FSACTION action, const JsonObject json) { if (action == MYESP_FSACTION_LOAD) { // led - if (json.containsKey("led")) { - EMSESP_Status.led_enabled = (bool)json["led"]; - } else { + if (!(EMSESP_Status.led_enabled = json["led"])) { EMSESP_Status.led_enabled = LED_BUILTIN; // default value - ok = false; } // led_gpio - if (json.containsKey("led_gpio")) { - EMSESP_Status.led_gpio = json["led_gpio"]; - } else { + if (!(EMSESP_Status.led_gpio = json["led_gpio"])) { EMSESP_Status.led_gpio = EMSESP_LED_GPIO; // default value - ok = false; } // dallas_gpio - if (json.containsKey("dallas_gpio")) { - EMSESP_Status.dallas_gpio = json["dallas_gpio"]; - } else { + if (!(EMSESP_Status.dallas_gpio = json["dallas_gpio"])) { EMSESP_Status.dallas_gpio = EMSESP_DALLAS_GPIO; // default value - ok = false; } // thermostat_type - if (json.containsKey("thermostat_type")) { - EMS_Thermostat.type_id = json["thermostat_type"]; - } else { + if (!(EMS_Thermostat.type_id = json["thermostat_type"])) { EMS_Thermostat.type_id = EMSESP_THERMOSTAT_TYPE; // set default - ok = false; } // boiler_type - if (json.containsKey("boiler_type")) { - EMS_Boiler.type_id = json["boiler_type"]; - } else { + if (!(EMS_Boiler.type_id = json["boiler_type"])) { EMS_Boiler.type_id = EMSESP_BOILER_TYPE; // set default - ok = false; } + + return false; // always save the settings } if (action == MYESP_FSACTION_SAVE) { @@ -629,9 +616,9 @@ bool FSCallback(MYESP_FSACTION action, JsonObject & json) { json["dallas_gpio"] = EMSESP_Status.dallas_gpio; json["thermostat_type"] = EMS_Thermostat.type_id; json["boiler_type"] = EMS_Boiler.type_id; - } - return ok; // all ok + return true; + } } // callback for custom settings when showing Stored Settings @@ -949,7 +936,7 @@ void WIFICallback() { // This is done after we have a WiFi signal to avoid any resource conflicts if (myESP.getUseSerial()) { - myDebug("EMS UART disabled when in Serial mode. Use 'set serial off' to change."); + myDebug("Warning! EMS bus disabled when in Serial mode. Use 'set serial off' to enable."); } else { emsuart_init(); myDebug("[UART] Opened Rx/Tx connection"); diff --git a/src/ems.cpp b/src/ems.cpp index 8f144e1da..3b06f81a3 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -1447,7 +1447,7 @@ char * ems_getBoilerDescription(char * buffer) { * Find the versions of our connected devices */ void ems_scanDevices() { - myDebug("Scanning EMS bus for devices."); + myDebug("Started scan of EMS bus for known devices"); std::list Device_Ids; // new list diff --git a/src/ems_devices.h b/src/ems_devices.h index 8f6309267..4ac8ab238 100644 --- a/src/ems_devices.h +++ b/src/ems_devices.h @@ -102,7 +102,8 @@ typedef enum { EMS_MODEL_EASY, EMS_MODEL_BOSCHEASY, EMS_MODEL_RC310, - EMS_MODEL_CW100 + EMS_MODEL_CW100, + EMS_MODEL_OT } _EMS_MODEL_ID; @@ -139,6 +140,7 @@ const _Thermostat_Type Thermostat_Types[] = { {EMS_MODEL_EASY, 202, 0x18, "TC100/Nefit Easy", EMS_THERMOSTAT_READ_YES, EMS_THERMOSTAT_WRITE_NO}, {EMS_MODEL_BOSCHEASY, 206, 0x02, "Bosch Easy", EMS_THERMOSTAT_READ_YES, EMS_THERMOSTAT_WRITE_NO}, {EMS_MODEL_RC310, 158, 0x10, "RC310", EMS_THERMOSTAT_READ_NO, EMS_THERMOSTAT_WRITE_NO}, - {EMS_MODEL_CW100, 255, 0x18, "Bosch CW100", EMS_THERMOSTAT_READ_NO, EMS_THERMOSTAT_WRITE_NO} + {EMS_MODEL_CW100, 255, 0x18, "Bosch CW100", EMS_THERMOSTAT_READ_NO, EMS_THERMOSTAT_WRITE_NO}, + {EMS_MODEL_OT, 171, 0x02, "EMS-OT OpenTherm converter", EMS_THERMOSTAT_READ_YES, EMS_THERMOSTAT_WRITE_YES} }; diff --git a/src/my_config.h b/src/my_config.h index e6cf8f4b7..2c23d611b 100644 --- a/src/my_config.h +++ b/src/my_config.h @@ -20,7 +20,7 @@ #define MQTT_WILL_ONLINE_PAYLOAD "online" // for last will & testament payload #define MQTT_WILL_OFFLINE_PAYLOAD "offline" // for last will & testament payload #define MQTT_RETAIN false -#define MQTT_KEEPALIVE 60 // 1 minute +#define MQTT_KEEPALIVE 120 // 2 minutes #define MQTT_QOS 1 // MQTT for thermostat diff --git a/src/version.h b/src/version.h index 77cc3d6c5..f76abbf74 100644 --- a/src/version.h +++ b/src/version.h @@ -6,5 +6,5 @@ #pragma once #define APP_NAME "EMS-ESP" -#define APP_VERSION "1.5.4" +#define APP_VERSION "1.5.5" #define APP_HOSTNAME "ems-esp"