From a0303f070412f988496b9fa5a857bbc3d7dbd505 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 4 Feb 2019 21:44:13 +0100 Subject: [PATCH] 1.5.2 --- CHANGELOG.md | 12 ++++++ README.md | 18 +++++++-- lib/myESP/MyESP.cpp | 97 ++++++++++++++++++++++++++++----------------- lib/myESP/MyESP.h | 1 + src/ems-esp.ino | 12 +++++- src/ems.cpp | 11 ++--- src/my_config.h | 9 +++-- src/version.h | 2 +- 8 files changed, 109 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8caf990c..3aef047cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +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.2] 2019-02-04 + +### Changed + +- Change wifi settings using the `set wifi ` command + +### Added + +- Added incoming MQTT "TOPIC_BOILER_WWACTIVATED" to set the warm water on/off. Payload is 1 or 0. See [issue](https://github.com/proddy/EMS-ESP/issues/46#issuecomment-460375689). +- Added the list of all MQTT topics to the README file + ## [1.5.1] 2019-02-03 ### Fixed - issue with Serial monitoring conflicting with UART when both running +- Fixed typo with -D settings in the example platformio.ini ### Changed diff --git a/README.md b/README.md index 5410b80df..b5700850e 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.4.0-brightgreen.svg)](CHANGELOG.md) +[![version](https://img.shields.io/badge/version-1.5.2-brightgreen.svg)](CHANGELOG.md) - [EMS-ESP](#ems-esp) - [Introduction](#introduction) @@ -233,7 +233,15 @@ Similarly the thermostat values are also sent as a JSON package with the topic ` `{"thermostat_currtemp":"19.8","thermostat_seltemp":"16.0","thermostat_mode":"manual"}` -If MQTT is not used set the MQTT_HOST to `NULL`. +These incoming MQTT topics are also handled: + +| topic | ID in my_config.h | Payload | Description | +| ------------------- | ------------------------- | ---------------------- | ---------------------------------------- | +| thermostat_cmd_temp | TOPIC_THERMOSTAT_CMD_TEMP | temperature as a float | sets the thermostat current setpoint | +| thermostat_cmd_mode | TOPIC_THERMOSTAT_CMD_MODE | auto, day, night | sets the thermostat mode | +| wwactivated | TOPIC_BOILER_WWACTIVATED | 0 or 1 | turns boiler warm water on/off (not tap) | + +If MQTT is not used use 'set mqtt_host' to remove it. Some home automation systems such as Domoticz and OpenHab have special formats for their MQTT messages so I would advise to use [node-red](https://nodered.org/) as a parser like in [this example](https://www.domoticz.com/forum/download/file.php?id=18977&sid=67d048f1b4c8833822175eac6b55ecff). @@ -305,9 +313,11 @@ pre-baked firmwares for some ESP8266 devices are available in the directory `/fi 3. Connect the ESP via USB, figure out the COM port 4. run `esptool.py -p write_flash 0x00000 ` where firmware is the `.bin` file and \ is the COM port, e.g. `COM3` -The ESP8266 will start in Access Point (AP) mode. Connect via WiFi to the SSID **EMS-ESP** and telnet to **192.168.4.1**. Then use the set command to configure your own network settings. Alternatively connect the ESP8266 to your PC and open a Serial monitor to configure the settings. Make sure you disable Serial support before connecting the EMS lines using `set serial off`. +The ESP8266 will start in Access Point (AP) mode. Connect via WiFi to the SSID **EMS-ESP** and telnet to **192.168.4.1**. Then use the `set wifi` command to configure your own network settings like `set wifi your_ssid your_password`. Alternatively connect the ESP8266 to your PC and open a Serial monitor to configure the settings. Make sure you disable Serial support before connecting the EMS lines using `set serial off`. -`set erase` will clear all settings. `set` wil show all settings. +`set erase` will clear all settings. + +`set` wil list all currently stored settings. ## Troubleshooting diff --git a/lib/myESP/MyESP.cpp b/lib/myESP/MyESP.cpp index 9d1a86fba..2d514d9e6 100644 --- a/lib/myESP/MyESP.cpp +++ b/lib/myESP/MyESP.cpp @@ -410,9 +410,11 @@ void MyESP::_consoleShowHelp() { SerialAndTelnet.println(FPSTR("*")); SerialAndTelnet.println(FPSTR("* Commands:")); - SerialAndTelnet.println(FPSTR("* ?=help, CTRL-D=quit, !=reboot")); + SerialAndTelnet.println(FPSTR("* ?=help, CTRL-D=quit")); + SerialAndTelnet.println(FPSTR("* reboot")); SerialAndTelnet.println(FPSTR("* set")); - SerialAndTelnet.println(FPSTR("* set [value]")); + SerialAndTelnet.println(FPSTR("* set wifi ")); + SerialAndTelnet.println(FPSTR("* set [value]")); SerialAndTelnet.println(FPSTR("* set erase")); SerialAndTelnet.println(FPSTR("* set serial")); @@ -456,8 +458,32 @@ char * MyESP::_telnet_readWord() { return word; } +// change setting for 2 params (set ) +void MyESP::_changeSetting2(const char * setting, const char * value1, const char * value2) { + if (strcmp(setting, "wifi") == 0) { + if (_wifi_ssid) + free(_wifi_ssid); + if (_wifi_password) + free(_wifi_password); + _wifi_ssid = NULL; + _wifi_password = NULL; + + if (value1) { + _wifi_ssid = strdup(value1); + } + + if (value2) { + _wifi_password = strdup(value2); + } + + (void)fs_saveConfig(); + SerialAndTelnet.println("Wifi credentials set. Type 'reboot' to restart..."); + } +} + // change settings - always as strings // messy code but effective since we don't have too many settings +// wc is word count, number of parameters after the 'set' command void MyESP::_changeSetting(uint8_t wc, const char * setting, const char * value) { bool ok = false; @@ -465,24 +491,14 @@ void MyESP::_changeSetting(uint8_t wc, const char * setting, const char * value) if (strcmp(setting, "erase") == 0) { _fs_eraseConfig(); return; - } - - if (strcmp(setting, "wifi_ssid") == 0) { + } else if ((strcmp(setting, "wifi") == 0) && (wc == 1)) { // erase wifi settings if (_wifi_ssid) free(_wifi_ssid); - _wifi_ssid = NULL; // just to be sure - if (value) { - _wifi_ssid = strdup(value); - } - ok = true; - } else if (strcmp(setting, "wifi_password") == 0) { if (_wifi_password) free(_wifi_password); - _wifi_password = NULL; // just to be sure - if (value) { - _wifi_password = strdup(value); - } - ok = true; + _wifi_ssid = NULL; + _wifi_password = NULL; + ok = true; } else if (strcmp(setting, "mqtt_host") == 0) { if (_mqtt_host) free(_mqtt_host); @@ -533,16 +549,14 @@ void MyESP::_changeSetting(uint8_t wc, const char * setting, const char * value) // check for 2 params if (value == nullptr) { - SerialAndTelnet.printf("%s setting reset to its default value", setting); + SerialAndTelnet.printf("%s setting reset to its default value.", setting); } else { // must be 3 params - SerialAndTelnet.printf("%s changed to %s", setting, value); + SerialAndTelnet.printf("%s changed.", setting); } SerialAndTelnet.println(); - if (fs_saveConfig()) { - SerialAndTelnet.println("Note, some changes will only have effect after the ESP is restarted (use ! command)"); - } + (void)fs_saveConfig(); } void MyESP::_telnetCommand(char * commandLine) { @@ -563,13 +577,13 @@ void MyESP::_telnetCommand(char * commandLine) { // check first for reserved commands char * temp = strdup(commandLine); // because strotok kills original string buffer char * ptrToCommandName = strtok((char *)temp, ", \n"); + + // set command if (strcmp(ptrToCommandName, "set") == 0) { if (wc == 1) { SerialAndTelnet.println(); SerialAndTelnet.println("Stored settings:"); - SerialAndTelnet.printf(" wifi_ssid=%s", (!_wifi_ssid) ? "" : _wifi_ssid); - SerialAndTelnet.println(); - SerialAndTelnet.printf(" wifi_password="); + SerialAndTelnet.printf(" wifi=%s ", (!_wifi_ssid) ? "" : _wifi_ssid); if (!_wifi_password) { SerialAndTelnet.print(""); } else { @@ -598,7 +612,7 @@ void MyESP::_telnetCommand(char * commandLine) { (_fs_settings_callback)(MYESP_FSACTION_LIST, 0, NULL, NULL); SerialAndTelnet.println(); - SerialAndTelnet.println("Usage: set [value]"); + SerialAndTelnet.println("Usage: set [value...]"); } else if (wc == 2) { char * setting = _telnet_readWord(); _changeSetting(1, setting, NULL); @@ -606,10 +620,20 @@ void MyESP::_telnetCommand(char * commandLine) { char * setting = _telnet_readWord(); char * value = _telnet_readWord(); _changeSetting(2, setting, value); + } else if (wc == 4) { + char * setting = _telnet_readWord(); + char * value1 = _telnet_readWord(); + char * value2 = _telnet_readWord(); + _changeSetting2(setting, value1, value2); } return; } + // reboot command + if ((strcmp(ptrToCommandName, "reboot") == 0) && (wc == 1)) { + resetESP(); + } + // call callback function (_telnetcommand_callback)(wc, commandLine); } @@ -632,7 +656,7 @@ void MyESP::_telnetHandle() { case '\n': _command[charsRead] = '\0'; // null terminate our command char array if (charsRead > 0) { - charsRead = 0; // is static, so have to reset + charsRead = 0; // is static, so have to reset _suspendOutput = false; if (_use_serial) { SerialAndTelnet.println(); // force newline if in Telnet @@ -640,19 +664,20 @@ void MyESP::_telnetHandle() { _telnetCommand(_command); } break; - case '\b': // handle backspace in input: put a space in last char - if (charsRead > 0) { // and adjust commandLine and charsRead + case '\b': // handle backspace in input: put a space in last char + if (charsRead > 0) { _command[--charsRead] = '\0'; - SerialAndTelnet << byte('\b') << byte(' ') << byte('\b'); //no idea how this works, found it on the Internet + SerialAndTelnet << byte('\b') << byte(' ') << byte('\b'); } break; case '?': - _consoleShowHelp(); + if (!_suspendOutput) { + _consoleShowHelp(); + } else { + _command[charsRead++] = c; // add it to buffer as its part of the string entered + } break; - case '!': - resetESP(); - break; - case 0x04: // EOT + case 0x04: // EOT, CTRL-D myDebug_P(PSTR("* exiting telnet session")); SerialAndTelnet.disconnectClient(); break; @@ -825,7 +850,7 @@ void MyESP::_fs_eraseConfig() { myDebug_P(PSTR("[FS] Erasing settings, please wait a few seconds. ESP will automatically restart when finished.")); if (SPIFFS.format()) { - delay(2000); // wait 2 seconds + delay(1000); // wait 1 seconds resetESP(); } } @@ -928,7 +953,7 @@ void MyESP::_fs_setup() { return; } - //_fs_printConfig(); // for debugging + // _fs_printConfig(); // for debugging // load the config file. if it doesn't exist create it if (!_fs_loadConfig()) { diff --git a/lib/myESP/MyESP.h b/lib/myESP/MyESP.h index e244abfda..e2c62e677 100644 --- a/lib/myESP/MyESP.h +++ b/lib/myESP/MyESP.h @@ -178,6 +178,7 @@ class MyESP { telnetcommand_callback_f _telnetcommand_callback; // Callable for projects commands telnet_callback_f _telnet_callback; // callback for connect/disconnect void _changeSetting(uint8_t wc, const char * setting, const char * value); + void _changeSetting2(const char * setting, const char * value1, const char * value2); // fs void _fs_setup(); diff --git a/src/ems-esp.ino b/src/ems-esp.ino index ae475748d..b250801b4 100644 --- a/src/ems-esp.ino +++ b/src/ems-esp.ino @@ -82,7 +82,6 @@ command_t PROGMEM project_cmds[] = { {"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"}, {"log ", "set logging mode to none, basic, thermostat only, raw or verbose"}, {"publish", "publish values to MQTT"}, @@ -845,6 +844,7 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) { if (type == MQTT_CONNECT_EVENT) { myESP.mqttSubscribe(TOPIC_THERMOSTAT_CMD_TEMP); myESP.mqttSubscribe(TOPIC_THERMOSTAT_CMD_MODE); + myESP.mqttSubscribe(TOPIC_BOILER_WWACTIVATED); myESP.mqttSubscribe(TOPIC_SHOWER_TIMER); myESP.mqttSubscribe(TOPIC_SHOWER_ALERT); myESP.mqttSubscribe(TOPIC_SHOWER_COLDSHOT); @@ -888,6 +888,16 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) { } } + // wwActivated + if (strcmp(topic, TOPIC_BOILER_WWACTIVATED) == 0) { + if (message[0] == '1') { + ems_setWarmWaterActivated(true); + } else if (message[0] == '0') { + ems_setWarmWaterActivated(false); + } + publishValues(true); // publish back immediately + } + // shower timer if (strcmp(topic, TOPIC_SHOWER_TIMER) == 0) { if (message[0] == '1') { diff --git a/src/ems.cpp b/src/ems.cpp index 24f520399..2b654ca40 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -768,9 +768,10 @@ void _processType(uint8_t * telegram, uint8_t length) { EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE; // at this point we can assume Txstatus is EMS_TX_STATUS_WAIT - // for READ, WRITE or VALIDATE the dest is always us, so check this - // if not just process and quit + // for READ, WRITE or VALIDATE the dest (telegram[1]) is always us, so check for this + // if not we probably didn't get any response so remove the last Tx from the queue and process the telegram if ((telegram[1] & 0x7F) != EMS_ID_ME) { + _removeTxQueue(); _ems_processTelegram(telegram, length); return; } @@ -1443,11 +1444,7 @@ char * ems_getBoilerDescription(char * buffer) { * Find the versions of our connected devices */ void ems_scanDevices() { - myDebug("Scanning EMS bus for devices..."); - - // start refresh when scanning and forget anything devices we may have already set - EMS_Thermostat.type_id = EMS_ID_NONE; // forget thermostat - EMS_Thermostat.model_id = EMS_MODEL_NONE; + myDebug("Scanning EMS bus for devices."); std::list Device_Ids; // new list diff --git a/src/my_config.h b/src/my_config.h index f093d6439..4ec9cffed 100644 --- a/src/my_config.h +++ b/src/my_config.h @@ -23,17 +23,18 @@ #define MQTT_QOS 1 // MQTT for thermostat -#define TOPIC_THERMOSTAT_DATA "thermostat_data" // for sending thermostat values -#define TOPIC_THERMOSTAT_CMD_TEMP "thermostat_cmd_temp" // for received thermostat temp changes -#define TOPIC_THERMOSTAT_CMD_MODE "thermostat_cmd_mode" // for received thermostat mode changes +#define TOPIC_THERMOSTAT_DATA "thermostat_data" // for sending thermostat values to MQTT +#define TOPIC_THERMOSTAT_CMD_TEMP "thermostat_cmd_temp" // for received thermostat temp changes via MQTT +#define TOPIC_THERMOSTAT_CMD_MODE "thermostat_cmd_mode" // for received thermostat mode changes via MQTT #define THERMOSTAT_CURRTEMP "thermostat_currtemp" // current temperature #define THERMOSTAT_SELTEMP "thermostat_seltemp" // selected temperature #define THERMOSTAT_MODE "thermostat_mode" // mode // MQTT for boiler -#define TOPIC_BOILER_DATA "boiler_data" // for sending boiler values +#define TOPIC_BOILER_DATA "boiler_data" // for sending boiler values to MQTT #define TOPIC_BOILER_TAPWATER_ACTIVE "tapwater_active" // if hot tap water is running #define TOPIC_BOILER_HEATING_ACTIVE "heating_active" // if heating is on +#define TOPIC_BOILER_WWACTIVATED "wwactivated" // for receiving MQTT message to change water on/off // shower time #define TOPIC_SHOWERTIME "showertime" // for sending shower time results diff --git a/src/version.h b/src/version.h index 647e3714f..1e5918eae 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.1" +#define APP_VERSION "1.5.2" #define APP_HOSTNAME "ems-esp"