This commit is contained in:
MichaelDvP
2022-12-07 07:41:25 +01:00
20 changed files with 97 additions and 45 deletions

View File

@@ -5,7 +5,6 @@
## **IMPORTANT! BREAKING CHANGES** ## **IMPORTANT! BREAKING CHANGES**
- When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade. - When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade.
- Since 3.5.0b11 we added support for multiple EMS-ESPs [#759] so they can co-exist with MQTT Discovery. The mqtt base is now included in each of the entity names to make them unique. Unfortunately this means in Home Assistant the entity IDs have also been renamed (for example from `number.boiler_burnminperiod` to `number.ems_esp_boiler_burnminperiod`) and any dashboards and automation scripts need to be adjusted accordingly.
## Added ## Added

View File

@@ -15,12 +15,12 @@
"@mui/material": "^5.10.16", "@mui/material": "^5.10.16",
"@table-library/react-table-library": "4.0.23", "@table-library/react-table-library": "4.0.23",
"@types/lodash": "^4.14.191", "@types/lodash": "^4.14.191",
"@types/node": "^18.11.10", "@types/node": "^18.11.11",
"@types/react": "^18.0.26", "@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9", "@types/react-dom": "^18.0.9",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
"async-validator": "^4.2.5", "async-validator": "^4.2.5",
"axios": "^1.2.0", "axios": "^1.2.1",
"http-proxy-middleware": "^2.0.6", "http-proxy-middleware": "^2.0.6",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
@@ -4017,9 +4017,9 @@
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.11.10", "version": "18.11.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz",
"integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" "integrity": "sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g=="
}, },
"node_modules/@types/parse-json": { "node_modules/@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -5030,9 +5030,9 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.2.0", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz",
"integrity": "sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==", "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.0", "follow-redirects": "^1.15.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",
@@ -20230,9 +20230,9 @@
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
}, },
"@types/node": { "@types/node": {
"version": "18.11.10", "version": "18.11.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz",
"integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" "integrity": "sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g=="
}, },
"@types/parse-json": { "@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -20998,9 +20998,9 @@
"integrity": "sha512-u2MVsXfew5HBvjsczCv+xlwdNnB1oQR9HlAcsejZttNjKKSkeDNVwB1vMThIUIFI9GoT57Vtk8iQLwqOfAkboA==" "integrity": "sha512-u2MVsXfew5HBvjsczCv+xlwdNnB1oQR9HlAcsejZttNjKKSkeDNVwB1vMThIUIFI9GoT57Vtk8iQLwqOfAkboA=="
}, },
"axios": { "axios": {
"version": "1.2.0", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz",
"integrity": "sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==", "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==",
"requires": { "requires": {
"follow-redirects": "^1.15.0", "follow-redirects": "^1.15.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",

View File

@@ -11,12 +11,12 @@
"@mui/material": "^5.10.16", "@mui/material": "^5.10.16",
"@table-library/react-table-library": "4.0.23", "@table-library/react-table-library": "4.0.23",
"@types/lodash": "^4.14.191", "@types/lodash": "^4.14.191",
"@types/node": "^18.11.10", "@types/node": "^18.11.11",
"@types/react": "^18.0.26", "@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9", "@types/react-dom": "^18.0.9",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
"async-validator": "^4.2.5", "async-validator": "^4.2.5",
"axios": "^1.2.0", "axios": "^1.2.1",
"http-proxy-middleware": "^2.0.6", "http-proxy-middleware": "^2.0.6",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",

View File

@@ -162,6 +162,10 @@ const MqttSettingsForm: FC = () => {
</ValidatedTextField> </ValidatedTextField>
</Grid> </Grid>
</Grid> </Grid>
<BlockFormControlLabel
control={<Checkbox name="multiple_instances" checked={data.multiple_instances} onChange={updateFormValue} />}
label={LL.MQTT_MULTIPLE_INSTANCES()}
/>
<BlockFormControlLabel <BlockFormControlLabel
control={<Checkbox name="clean_session" checked={data.clean_session} onChange={updateFormValue} />} control={<Checkbox name="clean_session" checked={data.clean_session} onChange={updateFormValue} />}
label={LL.MQTT_CLEAN_SESSION()} label={LL.MQTT_CLEAN_SESSION()}

View File

@@ -248,6 +248,7 @@ const de: Translation = {
MQTT_INT_HEARTBEAT: 'Heartbeat', MQTT_INT_HEARTBEAT: 'Heartbeat',
MQTT_QUEUE: 'MQTT Queue', MQTT_QUEUE: 'MQTT Queue',
DEFAULT: 'Standard', DEFAULT: 'Standard',
MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP',
MQTT_CLEAN_SESSION: 'Setze `Clean Session`', MQTT_CLEAN_SESSION: 'Setze `Clean Session`',
MQTT_RETAIN_FLAG: 'Setze `Retain flag` immer', MQTT_RETAIN_FLAG: 'Setze `Retain flag` immer',
INACTIVE: 'Inaktiv', INACTIVE: 'Inaktiv',

View File

@@ -248,6 +248,7 @@ const en: Translation = {
MQTT_INT_HEARTBEAT: 'Heartbeat', MQTT_INT_HEARTBEAT: 'Heartbeat',
MQTT_QUEUE: 'MQTT Queue', MQTT_QUEUE: 'MQTT Queue',
DEFAULT: 'Default', DEFAULT: 'Default',
MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP',
MQTT_CLEAN_SESSION: 'Set Clean Session', MQTT_CLEAN_SESSION: 'Set Clean Session',
MQTT_RETAIN_FLAG: 'Always set Retain flag', MQTT_RETAIN_FLAG: 'Always set Retain flag',
INACTIVE: 'Inactive', INACTIVE: 'Inactive',

View File

@@ -248,6 +248,7 @@ const nl: Translation = {
MQTT_INT_HEARTBEAT: 'Heartbeat', MQTT_INT_HEARTBEAT: 'Heartbeat',
MQTT_QUEUE: 'MQTT Queue', MQTT_QUEUE: 'MQTT Queue',
DEFAULT: 'Default', DEFAULT: 'Default',
MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP',
MQTT_CLEAN_SESSION: 'Clean Session aan', MQTT_CLEAN_SESSION: 'Clean Session aan',
MQTT_RETAIN_FLAG: 'Retain flag aan', MQTT_RETAIN_FLAG: 'Retain flag aan',
INACTIVE: 'Inactief', INACTIVE: 'Inactief',

View File

@@ -248,6 +248,7 @@ const no: Translation = {
MQTT_INT_HEARTBEAT: 'Heartbeat', MQTT_INT_HEARTBEAT: 'Heartbeat',
MQTT_QUEUE: 'MQTT Queue', MQTT_QUEUE: 'MQTT Queue',
DEFAULT: 'Standard', DEFAULT: 'Standard',
MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP',
MQTT_CLEAN_SESSION: 'Benytt Clean Session', MQTT_CLEAN_SESSION: 'Benytt Clean Session',
MQTT_RETAIN_FLAG: 'Alltid sett Retain flag', MQTT_RETAIN_FLAG: 'Alltid sett Retain flag',
INACTIVE: 'Innaktiv', INACTIVE: 'Innaktiv',

View File

@@ -248,6 +248,7 @@ const pl: BaseTranslation = {
MQTT_INT_HEARTBEAT: 'Heartbeat', MQTT_INT_HEARTBEAT: 'Heartbeat',
MQTT_QUEUE: 'Kolejka MQTT', MQTT_QUEUE: 'Kolejka MQTT',
DEFAULT: '{{Pozostałe|Domyślna|}}', DEFAULT: '{{Pozostałe|Domyślna|}}',
MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP',
MQTT_CLEAN_SESSION: 'Ustawiaj flagę "Clean session"', MQTT_CLEAN_SESSION: 'Ustawiaj flagę "Clean session"',
MQTT_RETAIN_FLAG: 'Ustawiaj flagę "Retain"', MQTT_RETAIN_FLAG: 'Ustawiaj flagę "Retain"',
INACTIVE: 'nieaktywny', INACTIVE: 'nieaktywny',

View File

@@ -248,6 +248,7 @@ const se: Translation = {
MQTT_INT_HEARTBEAT: 'Heartbeat', MQTT_INT_HEARTBEAT: 'Heartbeat',
MQTT_QUEUE: 'MQTT Queue', MQTT_QUEUE: 'MQTT Queue',
DEFAULT: 'Standard', DEFAULT: 'Standard',
MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP',
MQTT_CLEAN_SESSION: 'Använd "Clean Session"-flaggan', MQTT_CLEAN_SESSION: 'Använd "Clean Session"-flaggan',
MQTT_RETAIN_FLAG: 'Använd "Always Retain"-flaggan', MQTT_RETAIN_FLAG: 'Använd "Always Retain"-flaggan',
INACTIVE: 'Inaktiv', INACTIVE: 'Inaktiv',

View File

@@ -29,6 +29,7 @@ export interface MqttSettings {
client_id: string; client_id: string;
keep_alive: number; keep_alive: number;
clean_session: boolean; clean_session: boolean;
multiple_instances: boolean;
publish_time_boiler: number; publish_time_boiler: number;
publish_time_thermostat: number; publish_time_thermostat: number;
publish_time_solar: number; publish_time_solar: number;

View File

@@ -154,6 +154,7 @@ void MqttSettings::read(MqttSettings & settings, JsonObject & root) {
root["client_id"] = settings.clientId; root["client_id"] = settings.clientId;
root["keep_alive"] = settings.keepAlive; root["keep_alive"] = settings.keepAlive;
root["clean_session"] = settings.cleanSession; root["clean_session"] = settings.cleanSession;
root["multiple_instances"] = settings.multiple_instances;
// added by proddy for EMS-ESP // added by proddy for EMS-ESP
root["publish_time_boiler"] = settings.publish_time_boiler; root["publish_time_boiler"] = settings.publish_time_boiler;
@@ -186,6 +187,8 @@ StateUpdateResult MqttSettings::update(JsonObject & root, MqttSettings & setting
newSettings.clientId = root["client_id"] | FACTORY_MQTT_CLIENT_ID; newSettings.clientId = root["client_id"] | FACTORY_MQTT_CLIENT_ID;
newSettings.keepAlive = root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE; newSettings.keepAlive = root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE;
newSettings.cleanSession = root["clean_session"] | FACTORY_MQTT_CLEAN_SESSION; newSettings.cleanSession = root["clean_session"] | FACTORY_MQTT_CLEAN_SESSION;
newSettings.multiple_instances = root["multiple_instances"] | FACTORY_MQTT_MULTIPLE_INSTANCES;
newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS; newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS;
newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN; newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN;

View File

@@ -57,6 +57,10 @@ static String generateClientId() {
#define FACTORY_MQTT_MAX_TOPIC_LENGTH 128 #define FACTORY_MQTT_MAX_TOPIC_LENGTH 128
#endif #endif
#ifndef FACTORY_MQTT_MULTIPLE_INSTANCES
#define FACTORY_MQTT_MULTIPLE_INSTANCES false
#endif
class MqttSettings { class MqttSettings {
public: public:
// host and port - if enabled // host and port - if enabled
@@ -75,6 +79,9 @@ class MqttSettings {
uint16_t keepAlive; uint16_t keepAlive;
bool cleanSession; bool cleanSession;
// multiple instances
bool multiple_instances;
// proddy EMS-ESP specific // proddy EMS-ESP specific
String base; String base;
uint16_t publish_time_boiler; uint16_t publish_time_boiler;

View File

@@ -81,6 +81,7 @@ class DummySettings {
String username = ""; String username = "";
uint16_t keepAlive = 60; uint16_t keepAlive = 60;
bool cleanSession = false; bool cleanSession = false;
bool multiple_instances = false;
uint16_t publish_time_boiler = 10; uint16_t publish_time_boiler = 10;
uint16_t publish_time_thermostat = 10; uint16_t publish_time_thermostat = 10;

View File

@@ -219,6 +219,7 @@ mqtt_settings = {
client_id: 'ems-esp', client_id: 'ems-esp',
keep_alive: 60, keep_alive: 60,
clean_session: true, clean_session: true,
multiple_instances: false,
publish_time_boiler: 10, publish_time_boiler: 10,
publish_time_thermostat: 10, publish_time_thermostat: 10,
publish_time_solar: 10, publish_time_solar: 10,

View File

@@ -451,7 +451,12 @@ void AnalogSensor::publish_values(const bool force) {
} }
config["val_tpl"] = str; config["val_tpl"] = str;
if (Mqtt::multiple_instances()) {
snprintf(str, sizeof(str), "%s_analogsensor_%d", Mqtt::basename().c_str(), sensor.gpio()); snprintf(str, sizeof(str), "%s_analogsensor_%d", Mqtt::basename().c_str(), sensor.gpio());
} else {
snprintf(str, sizeof(str), "analogsensor_%d", sensor.gpio());
}
config["object_id"] = str; config["object_id"] = str;
config["uniq_id"] = str; // same as object_id config["uniq_id"] = str; // same as object_id

View File

@@ -518,7 +518,12 @@ void DallasSensor::publish_values(const bool force) {
} }
config["val_tpl"] = str; config["val_tpl"] = str;
if (Mqtt::multiple_instances()) {
snprintf(str, sizeof(str), "%s_dallassensor_%s", Mqtt::basename().c_str(), sensor.id().c_str()); snprintf(str, sizeof(str), "%s_dallassensor_%s", Mqtt::basename().c_str(), sensor.id().c_str());
} else {
snprintf(str, sizeof(str), "dallassensor_%s", sensor.id().c_str());
}
config["object_id"] = str; config["object_id"] = str;
config["uniq_id"] = str; // same as object_id config["uniq_id"] = str; // same as object_id

View File

@@ -38,6 +38,7 @@ uint32_t Mqtt::publish_time_sensor_;
uint32_t Mqtt::publish_time_other_; uint32_t Mqtt::publish_time_other_;
uint32_t Mqtt::publish_time_heartbeat_; uint32_t Mqtt::publish_time_heartbeat_;
bool Mqtt::mqtt_enabled_; bool Mqtt::mqtt_enabled_;
bool Mqtt::multiple_instances_;
bool Mqtt::ha_enabled_; bool Mqtt::ha_enabled_;
uint8_t Mqtt::nested_format_; uint8_t Mqtt::nested_format_;
std::string Mqtt::discovery_prefix_; std::string Mqtt::discovery_prefix_;
@@ -429,6 +430,7 @@ void Mqtt::load_settings() {
publish_single2cmd_ = mqttSettings.publish_single2cmd; publish_single2cmd_ = mqttSettings.publish_single2cmd;
send_response_ = mqttSettings.send_response; send_response_ = mqttSettings.send_response;
discovery_prefix_ = mqttSettings.discovery_prefix.c_str(); discovery_prefix_ = mqttSettings.discovery_prefix.c_str();
multiple_instances_ = mqttSettings.multiple_instances;
// convert to milliseconds // convert to milliseconds
publish_time_boiler_ = mqttSettings.publish_time_boiler * 1000; publish_time_boiler_ = mqttSettings.publish_time_boiler * 1000;
@@ -606,10 +608,10 @@ void Mqtt::ha_status() {
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc; StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
char uniq[70]; char uniq[70];
snprintf(uniq, sizeof(uniq), "%s_status", mqtt_basename_.c_str()); snprintf(uniq, sizeof(uniq), "%s_status", mqtt_basename_.c_str()); // always use basename
doc["uniq_id"] = uniq; doc["uniq_id"] = uniq;
doc["object_id"] = uniq; doc["object_id"] = uniq;
doc["~"] = mqtt_base_; // default ems-esp doc["~"] = mqtt_base_;
// doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes // doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes
// doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes // doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes
doc["stat_t"] = "~/status"; doc["stat_t"] = "~/status";
@@ -796,6 +798,7 @@ void Mqtt::process_queue() {
if (message->topic.find(discovery_prefix_) == 0) { if (message->topic.find(discovery_prefix_) == 0) {
strlcpy(topic, message->topic.c_str(), sizeof(topic)); // leave topic as it is strlcpy(topic, message->topic.c_str(), sizeof(topic)); // leave topic as it is
} else { } else {
// it's a discovery topic, added the mqtt base to the topic path
snprintf(topic, MQTT_TOPIC_MAX_SIZE, "%s/%s", mqtt_base_.c_str(), message->topic.c_str()); // uses base snprintf(topic, MQTT_TOPIC_MAX_SIZE, "%s/%s", mqtt_base_.c_str(), message->topic.c_str()); // uses base
} }
@@ -978,7 +981,12 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
// build unique identifier which will be used in the topic, also used as object_id // build unique identifier which will be used in the topic, also used as object_id
char uniq_id[70]; char uniq_id[70];
if (multiple_instances_) {
// prefix base name to each uniq_id
snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag); snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag);
} else {
snprintf(uniq_id, sizeof(uniq_id), "%s_%s", device_name, entity_with_tag);
}
// build a config topic that will be prefix onto a HA type (e.g. number, switch) // build a config topic that will be prefix onto a HA type (e.g. number, switch)
// e.g. homeassistant/number/ems-esp/thermostat_hc1_manualtemp // e.g. homeassistant/number/ems-esp/thermostat_hc1_manualtemp
@@ -1280,7 +1288,13 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
hc_mode_s); hc_mode_s);
snprintf(name_s, sizeof(name_s), "Hc%d", hc_num); snprintf(name_s, sizeof(name_s), "Hc%d", hc_num);
if (Mqtt::multiple_instances()) {
snprintf(uniq_id_s, sizeof(uniq_id_s), "%s_thermostat_hc%d", mqtt_basename_.c_str(), hc_num); // add basename snprintf(uniq_id_s, sizeof(uniq_id_s), "%s_thermostat_hc%d", mqtt_basename_.c_str(), hc_num); // add basename
} else {
snprintf(uniq_id_s, sizeof(uniq_id_s), "thermostat_hc%d", hc_num); // backward compatible with v3.4
}
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num); snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num);
snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num); snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num);

View File

@@ -180,6 +180,10 @@ class Mqtt {
return nested_format_ == NestedFormat::NESTED; return nested_format_ == NestedFormat::NESTED;
} }
static bool multiple_instances() {
return multiple_instances_;
}
static void nested_format(uint8_t nested_format) { static void nested_format(uint8_t nested_format) {
nested_format_ = nested_format; nested_format_ = nested_format;
} }
@@ -317,6 +321,7 @@ class Mqtt {
static bool mqtt_enabled_; static bool mqtt_enabled_;
static bool ha_enabled_; static bool ha_enabled_;
static uint8_t nested_format_; static uint8_t nested_format_;
static bool multiple_instances_;
static std::string discovery_prefix_; static std::string discovery_prefix_;
static bool publish_single_; static bool publish_single_;
static bool publish_single2cmd_; static bool publish_single2cmd_;

View File

@@ -1147,6 +1147,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
node["client id"] = settings.clientId; node["client id"] = settings.clientId;
node["keep alive"] = settings.keepAlive; node["keep alive"] = settings.keepAlive;
node["clean session"] = settings.cleanSession; node["clean session"] = settings.cleanSession;
node["multiple instances"] = settings.multiple_instances;
node["base"] = settings.base; node["base"] = settings.base;
node["discovery prefix"] = settings.discovery_prefix; node["discovery prefix"] = settings.discovery_prefix;
node["nested format"] = settings.nested_format; node["nested format"] = settings.nested_format;