From 94a53b38b8cef8b1e3949af090680fe1a1395fb6 Mon Sep 17 00:00:00 2001 From: CaCO3 Date: Sat, 1 Mar 2025 00:28:38 +0100 Subject: [PATCH] Update Homeassistant discovery (#3580) * use "total" for Homeassistant discovery topic "raw" if AllowNegativeRates is activ (same as for "value") * update webUI * . * . * . * formating * use state class "measurement" in case of a thermometer * Update edit_config_template.html --------- Co-authored-by: CaCO3 --- .../jomjol_flowcontroll/ClassFlowMQTT.cpp | 10 ++++---- code/components/jomjol_mqtt/server_mqtt.cpp | 25 +++++++++++-------- param-docs/parameter-pages/MQTT/MeterType.md | 23 ++++++++++++++--- sd-card/html/common.js | 3 ++- sd-card/html/edit_config_template.html | 6 ++--- 5 files changed, 44 insertions(+), 23 deletions(-) diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp index 137d98e3..bda315d9 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp @@ -156,7 +156,7 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) mqttServer_setMeterType("water", "L", "h", "L/h"); } else if (toUpper(splitted[1]) == "WATER_FT3") { - mqttServer_setMeterType("water", "ft³", "m", "ft³/m"); // m = Minutes + mqttServer_setMeterType("water", "ft³", "min", "ft³/min"); // min = Minutes } else if (toUpper(splitted[1]) == "WATER_GAL") { mqttServer_setMeterType("water", "gal", "h", "gal/h"); @@ -165,7 +165,7 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) mqttServer_setMeterType("gas", "m³", "h", "m³/h"); } else if (toUpper(splitted[1]) == "GAS_FT3") { - mqttServer_setMeterType("gas", "ft³", "m", "ft³/m"); // m = Minutes + mqttServer_setMeterType("gas", "ft³", "min", "ft³/min"); // min = Minutes } else if (toUpper(splitted[1]) == "ENERGY_WH") { mqttServer_setMeterType("energy", "Wh", "h", "W"); @@ -180,13 +180,13 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) mqttServer_setMeterType("energy", "GJ", "h", "GJ/h"); } else if (toUpper(splitted[1]) == "TEMPERATURE_C") { - mqttServer_setMeterType("temperature", "°C", "m", "°C/m"); // m = Minutes + mqttServer_setMeterType("temperature", "°C", "min", "°C/min"); // min = Minutes } else if (toUpper(splitted[1]) == "TEMPERATURE_F") { - mqttServer_setMeterType("temperature", "°F", "m", "°F/m"); // m = Minutes + mqttServer_setMeterType("temperature", "°F", "min", "°F/min"); // min = Minutes } else if (toUpper(splitted[1]) == "TEMPERATURE_K") { - mqttServer_setMeterType("temperature", "K", "m", "K/m"); // m = Minutes + mqttServer_setMeterType("temperature", "K", "min", "K/m"); // min = Minutes } } diff --git a/code/components/jomjol_mqtt/server_mqtt.cpp b/code/components/jomjol_mqtt/server_mqtt.cpp index 9869bb44..fe9d918e 100644 --- a/code/components/jomjol_mqtt/server_mqtt.cpp +++ b/code/components/jomjol_mqtt/server_mqtt.cpp @@ -195,9 +195,12 @@ bool MQTThomeassistantDiscovery(int qos) { /* If "Allow neg. rate" is true, use "measurement" instead of "total_increasing" for the State Class, see https://github.com/jomjol/AI-on-the-edge-device/issues/3331 */ std::string value_state_class = "total_increasing"; - if ((*NUMBERS)[i]->AllowNegativeRates) { + if (meterType == "temperature") { value_state_class = "measurement"; } + else if ((*NUMBERS)[i]->AllowNegativeRates) { + value_state_class = "total"; + } /* Energy meters need a different Device Class, see https://github.com/jomjol/AI-on-the-edge-device/issues/3333 */ std::string rate_device_class = "volume_flow_rate"; @@ -205,17 +208,17 @@ bool MQTThomeassistantDiscovery(int qos) { rate_device_class = "power"; } - // Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category - allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "value", "Value", "gauge", valueUnit, meterType, value_state_class, "", qos); // State Class = "total_increasing" if .AllowNegativeRates = false, else use "measurement" - allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "raw", "Raw Value", "raw", valueUnit, meterType, "measurement", "diagnostic", qos); - allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "error", "Error", "alert-circle-outline", "", "", "", "diagnostic", qos); + // Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category | QoS + allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "value", "Value", "gauge", valueUnit, meterType, value_state_class, "", qos); // State Class = "total_increasing" if .AllowNegativeRates = false, "measurement" in case of a thermometer, else use "total". + allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "raw", "Raw Value", "raw", valueUnit, meterType, value_state_class, "diagnostic", qos); + allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "error", "Error", "alert-circle-outline", "", "", "", "diagnostic", qos); /* Not announcing "rate" as it is better to use rate_per_time_unit resp. rate_per_digitization_round */ - // allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate", "Rate (Unit/Minute)", "swap-vertical", "", "", "", ""); // Legacy, always Unit per Minute - allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate_per_time_unit", "Rate (" + rateUnit + ")", "swap-vertical", rateUnit, rate_device_class, "measurement", "", qos); - allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate_per_digitization_round", "Change since last Digitization round", "arrow-expand-vertical", valueUnit, "", "measurement", "", qos); // correctly the Unit is Unit/Interval! - allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "timestamp", "Timestamp", "clock-time-eight-outline", "", "timestamp", "", "diagnostic", qos); - allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "json", "JSON", "code-json", "", "", "", "diagnostic", qos); - allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "problem", "Problem", "alert-outline", "", "problem", "", "", qos); // Special binary sensor which is based on error topic + // allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate", "Rate (Unit/Minute)", "swap-vertical", "", "", "", "", qos); // Legacy, always Unit per Minute + allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate_per_time_unit", "Rate (" + rateUnit + ")", "swap-vertical", rateUnit, rate_device_class, "measurement", "", qos); + allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate_per_digitization_round","Change since last Digitization round", "arrow-expand-vertical", valueUnit, "", "measurement", "", qos); // correctly the Unit is Unit/Interval! + allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "timestamp", "Timestamp", "clock-time-eight-outline", "", "timestamp", "", "diagnostic", qos); + allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "json", "JSON", "code-json", "", "", "", "diagnostic", qos); + allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "problem", "Problem", "alert-outline", "", "problem", "", "", qos); // Special binary sensor which is based on error topic } LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Successfully published all Homeassistant Discovery MQTT topics"); diff --git a/param-docs/parameter-pages/MQTT/MeterType.md b/param-docs/parameter-pages/MQTT/MeterType.md index a65bd03a..72044c17 100644 --- a/param-docs/parameter-pages/MQTT/MeterType.md +++ b/param-docs/parameter-pages/MQTT/MeterType.md @@ -3,9 +3,26 @@ Default Value: `other` Select the Meter Type so the sensors have the right units in Homeassistant. -!!! Note - For `Watermeter` you need to have Homeassistant 2022.11 or newer! - Please also make sure that the selected Meter Type matches the dimension of the value provided by the meter! Eg. if your meter provides `m³`, you need to also set it to `m³`. Alternatively you can set the parameter `DecimalShift` to `3` so the value is converted to `liters`! + +List of supported options: + +- `other` +- `water_m3` (uses `m^3/min` as rate) +- `water_l` (uses `l/h` as rate, not officially supported by Homeassistant!) +- `water_gal` (uses `gal/h` as rate, not officially supported by Homeassistant!) +- `water_ft3` (uses `ft^3/min` as rate) +- `gas_m3` (uses `m^3/min` as rate) +- `gas_ft3` (uses `ft^3/min` as rate) +- `energy_wh` (uses `W` as rate) +- `energy_kwh` (uses `KW` as rate) +- `energy_mwh` (uses `MW` as rate) +- `energy_gj` (uses `GJ/h` as rate, not officially supported by Homeassistant!) +- `temperature_c` (uses `+C/min` as rate) +- `temperature_f` (uses `°F/min` as rate) +- `temperature_k` (uses `K/min` as rate) + +!!! Note + Not all options are supported by Homeassistant, see `SensorDeviceClass.VOLUME_FLOW_RATE` in [https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes](https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes)! diff --git a/sd-card/html/common.js b/sd-card/html/common.js index e7079178..0bcfb732 100644 --- a/sd-card/html/common.js +++ b/sd-card/html/common.js @@ -1,6 +1,7 @@ -/* The UI can also be run locally, but you have to set the IP of your devide accordingly. +/* The UI can also be run locally, but you have to set the IP of your device accordingly. * And you also might have to disable CORS in your webbrowser! + * Eg using https://chromewebstore.google.com/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?utm_source=ext_app_menu on chrome * Keep empty to disable using it. Enabling it will break access through a forwared port, see * https://github.com/jomjol/AI-on-the-edge-device/issues/2681 */ var domainname_for_testing = ""; diff --git a/sd-card/html/edit_config_template.html b/sd-card/html/edit_config_template.html index 7da7c409..4502dbb5 100644 --- a/sd-card/html/edit_config_template.html +++ b/sd-card/html/edit_config_template.html @@ -1183,15 +1183,15 @@