mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
Merge pull request #798 from proddy/dev
minor updates and renaming system status entity in HA
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
## **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.
|
||||
- Since 3.5.0b11 we have added support for multiple EMS-ESPs [#759] and also renamed the HA Entity IDs. For example what was previously `sensor.boiler_actual_boiler_temperature` is now using the shortname form `sensor.boiler_boiltemp` as opposed to the English description. Unfortunately this does means any HA dashboards, automation scripts and integrations (e.g. Grafana) need to be adjusted accordingly.
|
||||
|
||||
## Added
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"adapter": "react",
|
||||
"baseLocale": "pl",
|
||||
"$schema": "https://unpkg.com/typesafe-i18n@5.17.1/schema/typesafe-i18n.json"
|
||||
}
|
||||
"adapter": "react",
|
||||
"baseLocale": "pl",
|
||||
"$schema": "https://unpkg.com/typesafe-i18n@5.17.1/schema/typesafe-i18n.json"
|
||||
}
|
||||
|
||||
78
interface/package-lock.json
generated
78
interface/package-lock.json
generated
@@ -15,7 +15,7 @@
|
||||
"@mui/material": "^5.10.17",
|
||||
"@table-library/react-table-library": "4.0.23",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/node": "^18.11.11",
|
||||
"@types/node": "^18.11.12",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.9",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
@@ -31,11 +31,11 @@
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-icons": "^4.7.1",
|
||||
"react-router-dom": "^6.4.4",
|
||||
"react-router-dom": "^6.4.5",
|
||||
"react-scripts": "5.0.1",
|
||||
"sockette": "^2.0.6",
|
||||
"typesafe-i18n": "^5.17.1",
|
||||
"typescript": "^4.9.3"
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.20",
|
||||
@@ -3458,9 +3458,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/router": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.4.tgz",
|
||||
"integrity": "sha512-gTL8H5USTAKOyVA4xczzDJnC3HMssdFa3tRlwBicXynx9XfiXwneHnYQogwSKpdCkjXISrEKSTtX62rLpNEVQg==",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.5.tgz",
|
||||
"integrity": "sha512-my0Mycd+jruq/1lQuO5LBB6WTlL/e8DTCYWp44DfMTDcXz8DcTlgF0ISaLsGewt+ctHN+yA8xMq3q/N7uWJPug==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
@@ -4017,9 +4017,9 @@
|
||||
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.11.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz",
|
||||
"integrity": "sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g=="
|
||||
"version": "18.11.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.12.tgz",
|
||||
"integrity": "sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg=="
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
@@ -14561,11 +14561,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "6.4.4",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.4.tgz",
|
||||
"integrity": "sha512-SA6tSrUCRfuLWeYsTJDuriRqfFIsrSvuH7SqAJHegx9ZgxadE119rU8oOX/rG5FYEthpdEaEljdjDlnBxvfr+Q==",
|
||||
"version": "6.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.5.tgz",
|
||||
"integrity": "sha512-1RQJ8bM70YEumHIlNUYc6mFfUDoWa5EgPDenK/fq0bxD8DYpQUi/S6Zoft+9DBrh2xmtg92N5HMAJgGWDhKJ5Q==",
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.0.4"
|
||||
"@remix-run/router": "1.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
@@ -14575,12 +14575,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "6.4.4",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.4.tgz",
|
||||
"integrity": "sha512-0Axverhw5d+4SBhLqLpzPhNkmv7gahUwlUVIOrRLGJ4/uwt30JVajVJXqv2Qr/LCwyvHhQc7YyK1Do8a9Jj7qA==",
|
||||
"version": "6.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.5.tgz",
|
||||
"integrity": "sha512-a7HsgikBR0wNfroBHcZUCd9+mLRqZS8R5U1Z1mzLWxFXEkUT3vR1XXmSIVoVpxVX8Bar0nQYYYc9Yipq8dWwAA==",
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.0.4",
|
||||
"react-router": "6.4.4"
|
||||
"@remix-run/router": "1.0.5",
|
||||
"react-router": "6.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
@@ -16441,9 +16441,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
||||
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
|
||||
"version": "4.9.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
|
||||
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -19818,9 +19818,9 @@
|
||||
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
|
||||
},
|
||||
"@remix-run/router": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.4.tgz",
|
||||
"integrity": "sha512-gTL8H5USTAKOyVA4xczzDJnC3HMssdFa3tRlwBicXynx9XfiXwneHnYQogwSKpdCkjXISrEKSTtX62rLpNEVQg=="
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.5.tgz",
|
||||
"integrity": "sha512-my0Mycd+jruq/1lQuO5LBB6WTlL/e8DTCYWp44DfMTDcXz8DcTlgF0ISaLsGewt+ctHN+yA8xMq3q/N7uWJPug=="
|
||||
},
|
||||
"@rollup/plugin-babel": {
|
||||
"version": "5.3.1",
|
||||
@@ -20232,9 +20232,9 @@
|
||||
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.11.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz",
|
||||
"integrity": "sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g=="
|
||||
"version": "18.11.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.12.tgz",
|
||||
"integrity": "sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg=="
|
||||
},
|
||||
"@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
@@ -27723,20 +27723,20 @@
|
||||
"integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
|
||||
},
|
||||
"react-router": {
|
||||
"version": "6.4.4",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.4.tgz",
|
||||
"integrity": "sha512-SA6tSrUCRfuLWeYsTJDuriRqfFIsrSvuH7SqAJHegx9ZgxadE119rU8oOX/rG5FYEthpdEaEljdjDlnBxvfr+Q==",
|
||||
"version": "6.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.5.tgz",
|
||||
"integrity": "sha512-1RQJ8bM70YEumHIlNUYc6mFfUDoWa5EgPDenK/fq0bxD8DYpQUi/S6Zoft+9DBrh2xmtg92N5HMAJgGWDhKJ5Q==",
|
||||
"requires": {
|
||||
"@remix-run/router": "1.0.4"
|
||||
"@remix-run/router": "1.0.5"
|
||||
}
|
||||
},
|
||||
"react-router-dom": {
|
||||
"version": "6.4.4",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.4.tgz",
|
||||
"integrity": "sha512-0Axverhw5d+4SBhLqLpzPhNkmv7gahUwlUVIOrRLGJ4/uwt30JVajVJXqv2Qr/LCwyvHhQc7YyK1Do8a9Jj7qA==",
|
||||
"version": "6.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.5.tgz",
|
||||
"integrity": "sha512-a7HsgikBR0wNfroBHcZUCd9+mLRqZS8R5U1Z1mzLWxFXEkUT3vR1XXmSIVoVpxVX8Bar0nQYYYc9Yipq8dWwAA==",
|
||||
"requires": {
|
||||
"@remix-run/router": "1.0.4",
|
||||
"react-router": "6.4.4"
|
||||
"@remix-run/router": "1.0.5",
|
||||
"react-router": "6.4.5"
|
||||
}
|
||||
},
|
||||
"react-scripts": {
|
||||
@@ -29117,9 +29117,9 @@
|
||||
"requires": {}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
||||
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA=="
|
||||
"version": "4.9.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
|
||||
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg=="
|
||||
},
|
||||
"unbox-primitive": {
|
||||
"version": "1.0.2",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"@mui/material": "^5.10.17",
|
||||
"@table-library/react-table-library": "4.0.23",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/node": "^18.11.11",
|
||||
"@types/node": "^18.11.12",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.9",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
@@ -27,11 +27,11 @@
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-icons": "^4.7.1",
|
||||
"react-router-dom": "^6.4.4",
|
||||
"react-router-dom": "^6.4.5",
|
||||
"react-scripts": "5.0.1",
|
||||
"sockette": "^2.0.6",
|
||||
"typesafe-i18n": "^5.17.1",
|
||||
"typescript": "^4.9.3"
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-app-rewired start",
|
||||
|
||||
@@ -223,7 +223,13 @@ const MqttSettingsForm: FC = () => {
|
||||
<>
|
||||
<Grid item>
|
||||
<BlockFormControlLabel
|
||||
control={<Checkbox name="multiple_instances" checked={data.multiple_instances} onChange={updateFormValue} />}
|
||||
control={
|
||||
<Checkbox
|
||||
name="multiple_instances"
|
||||
checked={data.multiple_instances}
|
||||
onChange={updateFormValue}
|
||||
/>
|
||||
}
|
||||
label={LL.MQTT_MULTIPLE_INSTANCES()}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
@@ -288,18 +288,18 @@ const WiFiSettingsForm: FC = () => {
|
||||
</MessageBox>
|
||||
)}
|
||||
{!restartNeeded && (
|
||||
<ButtonRow>
|
||||
<Button
|
||||
startIcon={<SaveIcon />}
|
||||
disabled={saving}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
type="submit"
|
||||
onClick={validateAndSubmit}
|
||||
>
|
||||
{LL.SAVE()}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
<ButtonRow>
|
||||
<Button
|
||||
startIcon={<SaveIcon />}
|
||||
disabled={saving}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
type="submit"
|
||||
onClick={validateAndSubmit}
|
||||
>
|
||||
{LL.SAVE()}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -37,9 +37,9 @@ const DeviceIcon: FC<DeviceIconProps> = ({ type }) => {
|
||||
case 'Gateway':
|
||||
return <AiOutlineGateway />;
|
||||
case 'Alert':
|
||||
return <AiOutlineAlert />;
|
||||
return <AiOutlineAlert />;
|
||||
case 'Pump':
|
||||
return <AiOutlineChrome />;
|
||||
return <AiOutlineChrome />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ void AnalogSensor::publish_values(const bool force) {
|
||||
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> config;
|
||||
|
||||
char stat_t[50];
|
||||
snprintf(stat_t, sizeof(stat_t), "%s/analogsensor_data", Mqtt::base().c_str());
|
||||
snprintf(stat_t, sizeof(stat_t), "%s/analogsensor_data", Mqtt::base().c_str()); // use base path
|
||||
config["stat_t"] = stat_t;
|
||||
|
||||
char str[50];
|
||||
|
||||
@@ -505,7 +505,7 @@ void DallasSensor::publish_values(const bool force) {
|
||||
config["dev_cla"] = "temperature";
|
||||
|
||||
char stat_t[50];
|
||||
snprintf(stat_t, sizeof(stat_t), "%s/dallassensor_data", Mqtt::base().c_str());
|
||||
snprintf(stat_t, sizeof(stat_t), "%s/dallassensor_data", Mqtt::base().c_str()); // use base path
|
||||
config["stat_t"] = stat_t;
|
||||
|
||||
config["unit_of_meas"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
|
||||
|
||||
@@ -57,7 +57,7 @@ class DallasSensor {
|
||||
|
||||
std::string name() const;
|
||||
void set_name(const std::string & name) {
|
||||
name_ = name;
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
bool apply_customization();
|
||||
|
||||
21
src/mqtt.cpp
21
src/mqtt.cpp
@@ -443,6 +443,7 @@ void Mqtt::load_settings() {
|
||||
});
|
||||
|
||||
// create basename from base
|
||||
// by taking the MQTT base path and replacing all / with underscores
|
||||
mqtt_basename_ = mqtt_base_;
|
||||
std::replace(mqtt_basename_.begin(), mqtt_basename_.end(), '/', '_');
|
||||
}
|
||||
@@ -608,19 +609,25 @@ void Mqtt::ha_status() {
|
||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||
|
||||
char uniq[70];
|
||||
snprintf(uniq, sizeof(uniq), "%s_status", mqtt_basename_.c_str()); // always use basename
|
||||
if (Mqtt::multiple_instances()) {
|
||||
snprintf(uniq, sizeof(uniq), "%s_system_status", mqtt_basename_.c_str());
|
||||
} else {
|
||||
strcpy(uniq, "system_status");
|
||||
}
|
||||
|
||||
doc["uniq_id"] = uniq;
|
||||
doc["object_id"] = uniq;
|
||||
doc["~"] = mqtt_base_;
|
||||
// doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes
|
||||
// doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes
|
||||
doc["stat_t"] = "~/status";
|
||||
|
||||
doc["stat_t"] = mqtt_base_ + "/status";
|
||||
doc["name"] = "EMS-ESP status";
|
||||
doc["payload_on"] = "online";
|
||||
doc["payload_off"] = "offline";
|
||||
doc["state_class"] = "measurement";
|
||||
doc["device_class"] = "connectivity";
|
||||
|
||||
// doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes
|
||||
// doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes
|
||||
|
||||
JsonObject dev = doc.createNestedObject("dev");
|
||||
dev["name"] = "EMS-ESP";
|
||||
dev["sw"] = "v" + std::string(EMSESP_APP_VERSION);
|
||||
@@ -630,7 +637,7 @@ void Mqtt::ha_status() {
|
||||
ids.add("ems-esp");
|
||||
|
||||
char topic[MQTT_TOPIC_MAX_SIZE];
|
||||
snprintf(topic, sizeof(topic), "binary_sensor/%s/status/config", mqtt_basename_.c_str());
|
||||
snprintf(topic, sizeof(topic), "binary_sensor/%s/system_status/config", mqtt_basename_.c_str());
|
||||
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
|
||||
// create the sensors - must match the MQTT payload keys
|
||||
@@ -982,7 +989,7 @@ 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
|
||||
char uniq_id[70];
|
||||
if (multiple_instances_) {
|
||||
if (Mqtt::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);
|
||||
} else {
|
||||
|
||||
@@ -151,13 +151,17 @@ void Shower::set_shower_state(bool state, bool force) {
|
||||
ha_configdone_ = true;
|
||||
|
||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||
|
||||
doc["name"] = "Shower Active";
|
||||
|
||||
char str[70];
|
||||
snprintf(str, sizeof(str), "%s_shower_active", Mqtt::basename().c_str());
|
||||
doc["uniq_id"] = str;
|
||||
doc["object_id"] = str;
|
||||
doc["~"] = Mqtt::base();
|
||||
doc["stat_t"] = "~/shower_active";
|
||||
|
||||
char stat_t[50];
|
||||
snprintf(stat_t, sizeof(stat_t), "%s/shower_active", Mqtt::base().c_str()); // use base path
|
||||
doc["stat_t"] = stat_t;
|
||||
|
||||
// always render boolean as strings for HA
|
||||
char result[12];
|
||||
@@ -169,7 +173,7 @@ void Shower::set_shower_state(bool state, bool force) {
|
||||
ids.add("ems-esp");
|
||||
|
||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||
snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::base().c_str());
|
||||
snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::basename().c_str());
|
||||
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user