From e3d06e15a32e4ff9328434367424927c1e367f81 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 13 Oct 2019 21:03:15 +0200 Subject: [PATCH] added MQTT QOS and Keep Alive configurable --- CHANGELOG.md | 1 + src/MyESP.cpp | 35 ++++++++++++++++++++++++++++++----- src/MyESP.h | 7 ++++--- src/ems-esp.cpp | 33 --------------------------------- src/ems_utils.cpp | 33 +++++++++++++++++++++++++++++++++ src/ems_utils.h | 30 +++++++++++++++++------------- src/version.h | 2 +- src/websrc/myesp.htm | 26 +++++++++++++++++++++++--- src/websrc/myesp.js | 6 ++++++ tools/wsemulator/wserver.js | 2 ++ 10 files changed, 117 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e87d73b2..94bdf1900 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Retrieve/display mode for Junkers FW100/120 thermostats (thanks @Neonox31) - Added sending of Mixer Module data via MQTT (thanks @peclik) - Reporting of MQTT publish and subscribe errors +- Added MQTT QOS (default 1) and Keep Alive (default 60 seconds) as parameters to both telnet and WebUI ### Fixed diff --git a/src/MyESP.cpp b/src/MyESP.cpp index 9f9a969e3..8b712e306 100644 --- a/src/MyESP.cpp +++ b/src/MyESP.cpp @@ -677,8 +677,10 @@ void MyESP::_printSetCommands() { myDebug_P(PSTR(" set mqtt_enabled ")); myDebug_P(PSTR(" set [value]")); myDebug_P(PSTR(" set mqtt_heartbeat ")); - myDebug_P(PSTR(" set mqtt_base [value]")); - myDebug_P(PSTR(" set mqtt_port [value]")); + myDebug_P(PSTR(" set mqtt_base [string]")); + myDebug_P(PSTR(" set mqtt_port [number]")); + myDebug_P(PSTR(" set mqtt_qos [0,1,2,3]")); + myDebug_P(PSTR(" set mqtt_keepalive [seconds]")); myDebug_P(PSTR(" set ntp_enabled ")); myDebug_P(PSTR(" set serial ")); myDebug_P(PSTR(" set log_events ")); @@ -732,6 +734,8 @@ void MyESP::_printSetCommands() { myDebug_P(PSTR(" mqtt_base=")); } myDebug_P(PSTR(" mqtt_port=%d"), _mqtt_port); + myDebug_P(PSTR(" mqtt_keepalive=%d"), _mqtt_keepalive); + myDebug_P(PSTR(" mqtt_qos=%d"), _mqtt_qos); myDebug_P(PSTR(" mqtt_heartbeat=%s"), (_mqtt_heartbeat) ? "on" : "off"); #ifdef FORCE_SERIAL @@ -815,6 +819,10 @@ bool MyESP::_changeSetting(uint8_t wc, const char * setting, const char * value) save_config = fs_setSettingValue(&_mqtt_base, value, MQTT_BASE_DEFAULT); } else if (strcmp(setting, "mqtt_port") == 0) { save_config = fs_setSettingValue(&_mqtt_port, value, MQTT_PORT); + } else if (strcmp(setting, "mqtt_keepalive") == 0) { + save_config = fs_setSettingValue(&_mqtt_keepalive, value, MQTT_KEEPALIVE); + } else if (strcmp(setting, "mqtt_qos") == 0) { + save_config = fs_setSettingValue(&_mqtt_qos, value, MQTT_QOS); } else if (strcmp(setting, "mqtt_enabled") == 0) { save_config = fs_setSettingValue(&_mqtt_enabled, value, false); } else if (strcmp(setting, "serial") == 0) { @@ -1690,6 +1698,8 @@ bool MyESP::_fs_loadConfig() { _mqtt_ip = strdup(mqtt["ip"] | ""); _mqtt_user = strdup(mqtt["user"] | ""); _mqtt_port = mqtt["port"] | MQTT_PORT; + _mqtt_keepalive = mqtt["keepalive"] | MQTT_KEEPALIVE; + _mqtt_qos = mqtt["qos"] | MQTT_QOS; _mqtt_password = strdup(mqtt["password"] | ""); _mqtt_base = strdup(mqtt["base"] | MQTT_BASE_DEFAULT); @@ -1721,7 +1731,7 @@ bool MyESP::fs_setSettingValue(char ** setting, const char * value, const char * return true; } -// saves a integer into a config setting, using default value if non set +// saves a 2-byte short integer into a config setting, using default value if non set // returns true if successful bool MyESP::fs_setSettingValue(uint16_t * setting, const char * value, uint16_t value_default) { if (_hasValue(value)) { @@ -1733,6 +1743,18 @@ bool MyESP::fs_setSettingValue(uint16_t * setting, const char * value, uint16_t return true; } +// saves an 8-bit integer into a config setting, using default value if non set +// returns true if successful +bool MyESP::fs_setSettingValue(uint8_t * setting, const char * value, uint8_t value_default) { + if (_hasValue(value)) { + *setting = (uint8_t)atoi(value); + } else { + *setting = value_default; // use the default value + } + + return true; +} + // saves a bool into a config setting, using default value if non set // returns true if successful bool MyESP::fs_setSettingValue(bool * setting, const char * value, bool value_default) { @@ -1879,8 +1901,11 @@ bool MyESP::_fs_writeConfig() { mqtt["ip"] = _mqtt_ip; mqtt["user"] = _mqtt_user; mqtt["port"] = _mqtt_port; - mqtt["password"] = _mqtt_password; - mqtt["base"] = _mqtt_base; + mqtt["qos"] = _mqtt_qos; + mqtt["keepalive"] = _mqtt_keepalive; + + mqtt["password"] = _mqtt_password; + mqtt["base"] = _mqtt_base; JsonObject ntp = doc.createNestedObject("ntp"); ntp["server"] = _ntp_server; diff --git a/src/MyESP.h b/src/MyESP.h index 4f90de789..3d10e8a36 100644 --- a/src/MyESP.h +++ b/src/MyESP.h @@ -80,8 +80,8 @@ extern struct rst_info resetInfo; #define MQTT_WILL_OFFLINE_PAYLOAD "offline" // for last will & testament payload #define MQTT_BASE_DEFAULT "home" // default MQTT prefix to topics #define MQTT_RETAIN false -#define MQTT_KEEPALIVE 60 // 1 minute -#define MQTT_QOS 1 +#define MQTT_KEEPALIVE 60 // default keepalive 1 minute +#define MQTT_QOS 1 // default qos #define MQTT_WILL_TOPIC "status" // for last will & testament topic name #define MQTT_MAX_TOPIC_SIZE 50 // max length of MQTT topic #define MQTT_MAX_PAYLOAD_SIZE 700 // max size of a JSON object. See https://arduinojson.org/v6/assistant/ @@ -293,6 +293,7 @@ class MyESP { bool fs_saveCustomConfig(JsonObject root); bool fs_setSettingValue(char ** setting, const char * value, const char * value_default); bool fs_setSettingValue(uint16_t * setting, const char * value, uint16_t value_default); + bool fs_setSettingValue(uint8_t * setting, const char * value, uint8_t value_default); bool fs_setSettingValue(bool * setting, const char * value, bool value_default); // Web @@ -340,7 +341,7 @@ class MyESP { uint16_t _mqtt_port; char * _mqtt_base; bool _mqtt_enabled; - uint32_t _mqtt_keepalive; + uint16_t _mqtt_keepalive; uint8_t _mqtt_qos; bool _mqtt_retain; char * _mqtt_will_topic; diff --git a/src/ems-esp.cpp b/src/ems-esp.cpp index de55ddbd0..32ce146e0 100644 --- a/src/ems-esp.cpp +++ b/src/ems-esp.cpp @@ -873,39 +873,6 @@ void publishValues(bool force) { } } -// used to read the next string from an input buffer and convert to an 8 bit int -uint8_t _readIntNumber() { - char * numTextPtr = strtok(nullptr, ", \n"); - if (numTextPtr == nullptr) { - return 0; - } - return atoi(numTextPtr); -} - -// used to read the next string from an input buffer and convert to a double -float _readFloatNumber() { - char * numTextPtr = strtok(nullptr, ", \n"); - if (numTextPtr == nullptr) { - return 0; - } - return atof(numTextPtr); -} - -// used to read the next string from an input buffer as a hex value and convert to a 16 bit int -uint16_t _readHexNumber() { - char * numTextPtr = strtok(nullptr, ", \n"); - if (numTextPtr == nullptr) { - return 0; - } - return (uint16_t)strtol(numTextPtr, 0, 16); -} - -// used to read the next string from an input buffer -char * _readWord() { - char * word = strtok(nullptr, ", \n"); - return word; -} - // publish external dallas sensor temperature values to MQTT void do_publishSensorValues() { if ((EMSESP_Settings.dallas_sensors) && (EMSESP_Settings.publish_time)) { diff --git a/src/ems_utils.cpp b/src/ems_utils.cpp index fedae1984..bc68a8436 100644 --- a/src/ems_utils.cpp +++ b/src/ems_utils.cpp @@ -260,3 +260,36 @@ char * _smallitoa3(uint16_t value, char * buffer) { buffer[3] = '\0'; return buffer; } + +// used to read the next string from an input buffer and convert to an 8 bit int +uint8_t _readIntNumber() { + char * numTextPtr = strtok(nullptr, ", \n"); + if (numTextPtr == nullptr) { + return 0; + } + return atoi(numTextPtr); +} + +// used to read the next string from an input buffer and convert to a double +float _readFloatNumber() { + char * numTextPtr = strtok(nullptr, ", \n"); + if (numTextPtr == nullptr) { + return 0; + } + return atof(numTextPtr); +} + +// used to read the next string from an input buffer as a hex value and convert to a 16 bit int +uint16_t _readHexNumber() { + char * numTextPtr = strtok(nullptr, ", \n"); + if (numTextPtr == nullptr) { + return 0; + } + return (uint16_t)strtol(numTextPtr, 0, 16); +} + +// used to read the next string from an input buffer +char * _readWord() { + char * word = strtok(nullptr, ", \n"); + return word; +} diff --git a/src/ems_utils.h b/src/ems_utils.h index e08856038..c3c624f63 100644 --- a/src/ems_utils.h +++ b/src/ems_utils.h @@ -14,16 +14,20 @@ #define myDebug(...) myESP.myDebug(__VA_ARGS__) #define myDebug_P(...) myESP.myDebug_P(__VA_ARGS__) -char * _float_to_char(char * a, float f, uint8_t precision = 2); -char * _bool_to_char(char * s, uint8_t value); -char * _short_to_char(char * s, int16_t value, uint8_t decimals = 1); -char * _ushort_to_char(char * s, uint16_t value, uint8_t decimals = 1); -void _renderShortValue(const char * prefix, const char * postfix, int16_t value, uint8_t decimals = 1); -void _renderUShortValue(const char * prefix, const char * postfix, uint16_t value, uint8_t decimals = 1); -char * _int_to_char(char * s, uint8_t value, uint8_t div = 1); -void _renderIntValue(const char * prefix, const char * postfix, uint8_t value, uint8_t div = 1); -void _renderLongValue(const char * prefix, const char * postfix, uint32_t value); -void _renderBoolValue(const char * prefix, uint8_t value); -char * _hextoa(uint8_t value, char * buffer); -char * _smallitoa(uint8_t value, char * buffer); -char * _smallitoa3(uint16_t value, char * buffer); +char * _float_to_char(char * a, float f, uint8_t precision = 2); +char * _bool_to_char(char * s, uint8_t value); +char * _short_to_char(char * s, int16_t value, uint8_t decimals = 1); +char * _ushort_to_char(char * s, uint16_t value, uint8_t decimals = 1); +void _renderShortValue(const char * prefix, const char * postfix, int16_t value, uint8_t decimals = 1); +void _renderUShortValue(const char * prefix, const char * postfix, uint16_t value, uint8_t decimals = 1); +char * _int_to_char(char * s, uint8_t value, uint8_t div = 1); +void _renderIntValue(const char * prefix, const char * postfix, uint8_t value, uint8_t div = 1); +void _renderLongValue(const char * prefix, const char * postfix, uint32_t value); +void _renderBoolValue(const char * prefix, uint8_t value); +char * _hextoa(uint8_t value, char * buffer); +char * _smallitoa(uint8_t value, char * buffer); +char * _smallitoa3(uint16_t value, char * buffer); +uint8_t _readIntNumber(); +float _readFloatNumber(); +uint16_t _readHexNumber(); +char * _readWord(); diff --git a/src/version.h b/src/version.h index 6e4a789cb..35ce183a7 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define APP_VERSION "1.9.2b7" +#define APP_VERSION "1.9.2b8" diff --git a/src/websrc/myesp.htm b/src/websrc/myesp.htm index c741d7a43..ddb56ead1 100644 --- a/src/websrc/myesp.htm +++ b/src/websrc/myesp.htm @@ -191,7 +191,7 @@ data-toggle="popover" data-trigger="hover" data-placement="right" data-content="MQTT Server IP Address"> -
@@ -201,11 +201,31 @@ aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right" data-content="MQTT Server port number"> -
+
+ + + + +
+
+
+ + + + +
+
-
diff --git a/src/websrc/myesp.js b/src/websrc/myesp.js index 0677b582e..ab5e940e6 100644 --- a/src/websrc/myesp.js +++ b/src/websrc/myesp.js @@ -25,6 +25,8 @@ var config = { "enabled": false, "ip": "", "port": 1883, + "qos": 1, + "keepalive": 60, "base": "", "user": "", "password": "", @@ -173,6 +175,8 @@ function savemqtt() { config.mqtt.ip = document.getElementById("mqttip").value; config.mqtt.port = parseInt(document.getElementById("mqttport").value); + config.mqtt.qos = parseInt(document.getElementById("mqttqos").value); + config.mqtt.keepalive = parseInt(document.getElementById("mqttkeepalive").value); config.mqtt.base = document.getElementById("mqttbase").value; config.mqtt.user = document.getElementById("mqttuser").value; config.mqtt.password = document.getElementById("mqttpwd").value; @@ -323,6 +327,8 @@ function listmqtt() { document.getElementById("mqttip").value = config.mqtt.ip; document.getElementById("mqttport").value = config.mqtt.port; + document.getElementById("mqttqos").value = config.mqtt.qos; + document.getElementById("mqttkeepalive").value = config.mqtt.keepalive; document.getElementById("mqttbase").value = config.mqtt.base; document.getElementById("mqttuser").value = config.mqtt.user; document.getElementById("mqttpwd").value = config.mqtt.password; diff --git a/tools/wsemulator/wserver.js b/tools/wsemulator/wserver.js index 2d7f8c969..dbaa64e5d 100644 --- a/tools/wsemulator/wserver.js +++ b/tools/wsemulator/wserver.js @@ -76,6 +76,8 @@ var configfile = { "enabled": false, "ip": "ip", "port": "port", + "qos": "qos", + "keepalive": "keepalive", "base": "base", "user": "user", "password": "password",