From 22308502015e76debf2bed789d242282da02f136 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Tue, 24 Sep 2024 22:55:18 +0200 Subject: [PATCH] MQTT Hass: Implement device class as enum instead of String --- include/MqttHandleHass.h | 33 +++++++++-------- src/MqttHandleHass.cpp | 78 ++++++++++++++++++++-------------------- 2 files changed, 58 insertions(+), 53 deletions(-) diff --git a/include/MqttHandleHass.h b/include/MqttHandleHass.h index 426713d..201992c 100644 --- a/include/MqttHandleHass.h +++ b/include/MqttHandleHass.h @@ -6,7 +6,7 @@ #include // mqtt discovery device classes -enum { +enum DeviceClassType { DEVICE_CLS_NONE = 0, DEVICE_CLS_CURRENT, DEVICE_CLS_ENERGY, @@ -15,16 +15,21 @@ enum { DEVICE_CLS_FREQ, DEVICE_CLS_TEMP, DEVICE_CLS_POWER_FACTOR, - DEVICE_CLS_REACTIVE_POWER + DEVICE_CLS_REACTIVE_POWER, + DEVICE_CLS_CONNECTIVITY, + DEVICE_CLS_DURATION, + DEVICE_CLS_SIGNAL_STRENGTH, + DEVICE_CLS_TEMPERATURE, + DEVICE_CLS_RESTART }; -const char* const deviceClasses[] = { 0, "current", "energy", "power", "voltage", "frequency", "temperature", "power_factor", "reactive_power" }; +const char* const deviceClass_name[] = { 0, "current", "energy", "power", "voltage", "frequency", "temperature", "power_factor", "reactive_power", "connectivity", "duration", "signal_strength", "temperature", "restart" }; -enum { +enum StateClassType { STATE_CLS_NONE = 0, STATE_CLS_MEASUREMENT, STATE_CLS_TOTAL_INCREASING }; -const char* const stateClasses[] = { 0, "measurement", "total_increasing" }; +const char* const stateClass_name[] = { 0, "measurement", "total_increasing" }; enum CategoryType { CATEGORY_NONE = 0, @@ -36,8 +41,8 @@ const char* const category_name[] = { 0, "config", "diagnostic" }; typedef struct { FieldId_t fieldId; // field id - uint8_t deviceClsId; // device class - uint8_t stateClsId; // state class + DeviceClassType deviceClsId; // device class + StateClassType stateClsId; // state class } byteAssign_fieldDeviceClass_t; const byteAssign_fieldDeviceClass_t deviceFieldAssignment[] = { @@ -71,17 +76,17 @@ private: static void publish(const String& subtopic, const JsonDocument& doc); // Binary Sensor - static void publishBinarySensor(JsonDocument& doc, const String& root_device, const String& unique_id_prefix, const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& device_class, const CategoryType category); - static void publishDtuBinarySensor(const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& device_class, const CategoryType category); - static void publishInverterBinarySensor(std::shared_ptr inv, const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& device_class, const CategoryType category); + static void publishBinarySensor(JsonDocument& doc, const String& root_device, const String& unique_id_prefix, const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const DeviceClassType device_class, const CategoryType category); + static void publishDtuBinarySensor(const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const DeviceClassType device_class, const CategoryType category); + static void publishInverterBinarySensor(std::shared_ptr inv, const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const DeviceClassType device_class, const CategoryType category); // Sensor - static void publishSensor(JsonDocument& doc, const String& root_device, const String& unique_id_prefix, const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const String& device_class, const CategoryType category); - static void publishDtuSensor(const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const String& device_class, const CategoryType category); - static void publishInverterSensor(std::shared_ptr inv, const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const String& device_class, const CategoryType category); + static void publishSensor(JsonDocument& doc, const String& root_device, const String& unique_id_prefix, const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const DeviceClassType device_class, const CategoryType category); + static void publishDtuSensor(const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const DeviceClassType device_class, const CategoryType category); + static void publishInverterSensor(std::shared_ptr inv, const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const DeviceClassType device_class, const CategoryType category); static void publishInverterField(std::shared_ptr inv, const ChannelType_t type, const ChannelNum_t channel, const byteAssign_fieldDeviceClass_t fieldType, const bool clear = false); - static void publishInverterButton(std::shared_ptr inv, const String& name, const String& state_topic, const String& payload, const String& icon, const String& device_class, const CategoryType category); + static void publishInverterButton(std::shared_ptr inv, const String& name, const String& state_topic, const String& payload, const String& icon, const DeviceClassType device_class, const CategoryType category); static void publishInverterNumber(std::shared_ptr inv, const String& name, const String& state_topic, const String& command_topic, const int16_t min, const int16_t max, float step, const String& unit_of_measure, const String& icon, const CategoryType category); static void createInverterInfo(JsonDocument& doc, std::shared_ptr inv); diff --git a/src/MqttHandleHass.cpp b/src/MqttHandleHass.cpp index 4137b02..3f9e070 100644 --- a/src/MqttHandleHass.cpp +++ b/src/MqttHandleHass.cpp @@ -58,29 +58,29 @@ void MqttHandleHassClass::publishConfig() const CONFIG_T& config = Configuration.get(); // publish DTU sensors - publishDtuSensor("IP", "dtu/ip", "", "mdi:network-outline", "", CATEGORY_DIAGNOSTIC); - publishDtuSensor("WiFi Signal", "dtu/rssi", "dBm", "", "signal_strength", CATEGORY_DIAGNOSTIC); - publishDtuSensor("Uptime", "dtu/uptime", "s", "", "duration", CATEGORY_DIAGNOSTIC); - publishDtuSensor("Temperature", "dtu/temperature", "°C", "mdi:thermometer", "temperature", CATEGORY_DIAGNOSTIC); - publishDtuSensor("Heap Size", "dtu/heap/size", "Bytes", "mdi:memory", "", CATEGORY_DIAGNOSTIC); - publishDtuSensor("Heap Free", "dtu/heap/free", "Bytes", "mdi:memory", "", CATEGORY_DIAGNOSTIC); - publishDtuSensor("Largest Free Heap Block", "dtu/heap/maxalloc", "Bytes", "mdi:memory", "", CATEGORY_DIAGNOSTIC); - publishDtuSensor("Lifetime Minimum Free Heap", "dtu/heap/minfree", "Bytes", "mdi:memory", "", CATEGORY_DIAGNOSTIC); + publishDtuSensor("IP", "dtu/ip", "", "mdi:network-outline", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); + publishDtuSensor("WiFi Signal", "dtu/rssi", "dBm", "", DEVICE_CLS_SIGNAL_STRENGTH, CATEGORY_DIAGNOSTIC); + publishDtuSensor("Uptime", "dtu/uptime", "s", "", DEVICE_CLS_DURATION, CATEGORY_DIAGNOSTIC); + publishDtuSensor("Temperature", "dtu/temperature", "°C", "mdi:thermometer", DEVICE_CLS_TEMPERATURE, CATEGORY_DIAGNOSTIC); + publishDtuSensor("Heap Size", "dtu/heap/size", "Bytes", "mdi:memory", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); + publishDtuSensor("Heap Free", "dtu/heap/free", "Bytes", "mdi:memory", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); + publishDtuSensor("Largest Free Heap Block", "dtu/heap/maxalloc", "Bytes", "mdi:memory", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); + publishDtuSensor("Lifetime Minimum Free Heap", "dtu/heap/minfree", "Bytes", "mdi:memory", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); - publishDtuSensor("Yield Total", "ac/yieldtotal", "kWh", "", "energy", CATEGORY_NONE); - publishDtuSensor("Yield Day", "ac/yieldday", "Wh", "", "energy", CATEGORY_NONE); - publishDtuSensor("AC Power", "ac/power", "W", "", "power", CATEGORY_NONE); + publishDtuSensor("Yield Total", "ac/yieldtotal", "kWh", "", DEVICE_CLS_ENERGY, CATEGORY_NONE); + publishDtuSensor("Yield Day", "ac/yieldday", "Wh", "", DEVICE_CLS_ENERGY, CATEGORY_NONE); + publishDtuSensor("AC Power", "ac/power", "W", "", DEVICE_CLS_PWR, CATEGORY_NONE); - publishDtuBinarySensor("Status", config.Mqtt.Lwt.Topic, config.Mqtt.Lwt.Value_Online, config.Mqtt.Lwt.Value_Offline, "connectivity", CATEGORY_DIAGNOSTIC); + publishDtuBinarySensor("Status", config.Mqtt.Lwt.Topic, config.Mqtt.Lwt.Value_Online, config.Mqtt.Lwt.Value_Offline, DEVICE_CLS_CONNECTIVITY, CATEGORY_DIAGNOSTIC); // Loop all inverters for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); - publishInverterButton(inv, "Turn Inverter Off", "cmd/power", "0", "mdi:power-plug-off", "", CATEGORY_CONFIG); - publishInverterButton(inv, "Turn Inverter On", "cmd/power", "1", "mdi:power-plug", "", CATEGORY_CONFIG); - publishInverterButton(inv, "Restart Inverter", "cmd/restart", "1", "", "restart", CATEGORY_CONFIG); - publishInverterButton(inv, "Reset Radio Statistics", "cmd/reset_rf_stats", "1", "", "", CATEGORY_CONFIG); + publishInverterButton(inv, "Turn Inverter Off", "cmd/power", "0", "mdi:power-plug-off", DEVICE_CLS_NONE, CATEGORY_CONFIG); + publishInverterButton(inv, "Turn Inverter On", "cmd/power", "1", "mdi:power-plug", DEVICE_CLS_NONE, CATEGORY_CONFIG); + publishInverterButton(inv, "Restart Inverter", "cmd/restart", "1", "", DEVICE_CLS_RESTART, CATEGORY_CONFIG); + publishInverterButton(inv, "Reset Radio Statistics", "cmd/reset_rf_stats", "1", "", DEVICE_CLS_NONE, CATEGORY_CONFIG); publishInverterNumber(inv, "Limit NonPersistent Relative", "status/limit_relative", "cmd/limit_nonpersistent_relative", 0, 100, 0.1, "%", "mdi:speedometer", CATEGORY_CONFIG); publishInverterNumber(inv, "Limit Persistent Relative", "status/limit_relative", "cmd/limit_persistent_relative", 0, 100, 0.1, "%", "mdi:speedometer", CATEGORY_CONFIG); @@ -88,15 +88,15 @@ void MqttHandleHassClass::publishConfig() publishInverterNumber(inv, "Limit NonPersistent Absolute", "status/limit_absolute", "cmd/limit_nonpersistent_absolute", 0, MAX_INVERTER_LIMIT, 1, "W", "mdi:speedometer", CATEGORY_CONFIG); publishInverterNumber(inv, "Limit Persistent Absolute", "status/limit_absolute", "cmd/limit_persistent_absolute", 0, MAX_INVERTER_LIMIT, 1, "W", "mdi:speedometer", CATEGORY_CONFIG); - publishInverterBinarySensor(inv, "Reachable", "status/reachable", "1", "0", "connectivity", CATEGORY_DIAGNOSTIC); - publishInverterBinarySensor(inv, "Producing", "status/producing", "1", "0", "", CATEGORY_NONE); + publishInverterBinarySensor(inv, "Reachable", "status/reachable", "1", "0", DEVICE_CLS_CONNECTIVITY, CATEGORY_DIAGNOSTIC); + publishInverterBinarySensor(inv, "Producing", "status/producing", "1", "0", DEVICE_CLS_NONE, CATEGORY_NONE); - publishInverterSensor(inv, "TX Requests", "radio/tx_request", "", "", "", CATEGORY_DIAGNOSTIC); - publishInverterSensor(inv, "RX Success", "radio/rx_success", "", "", "", CATEGORY_DIAGNOSTIC); - publishInverterSensor(inv, "RX Fail Receive Nothing", "radio/rx_fail_nothing", "", "", "", CATEGORY_DIAGNOSTIC); - publishInverterSensor(inv, "RX Fail Receive Partial", "radio/rx_fail_partial", "", "", "", CATEGORY_DIAGNOSTIC); - publishInverterSensor(inv, "RX Fail Receive Corrupt", "radio/rx_fail_corrupt", "", "", "", CATEGORY_DIAGNOSTIC); - publishInverterSensor(inv, "TX Re-Request Fragment", "radio/tx_re_request", "", "", "", CATEGORY_DIAGNOSTIC); + publishInverterSensor(inv, "TX Requests", "radio/tx_request", "", "", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); + publishInverterSensor(inv, "RX Success", "radio/rx_success", "", "", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); + publishInverterSensor(inv, "RX Fail Receive Nothing", "radio/rx_fail_nothing", "", "", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); + publishInverterSensor(inv, "RX Fail Receive Partial", "radio/rx_fail_partial", "", "", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); + publishInverterSensor(inv, "RX Fail Receive Corrupt", "radio/rx_fail_corrupt", "", "", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); + publishInverterSensor(inv, "TX Re-Request Fragment", "radio/tx_re_request", "", "", DEVICE_CLS_NONE, CATEGORY_DIAGNOSTIC); // Loop all channels for (auto& t : inv->Statistics()->getChannelTypes()) { @@ -142,8 +142,8 @@ void MqttHandleHassClass::publishInverterField(std::shared_ptr if (!clear) { const String stateTopic = MqttSettings.getPrefix() + MqttHandleInverter.getTopic(inv, type, channel, fieldType.fieldId); - const char* devCls = deviceClasses[fieldType.deviceClsId]; - const char* stateCls = stateClasses[fieldType.stateClsId]; + const char* devCls = deviceClass_name[fieldType.deviceClsId]; + const char* stateCls = stateClass_name[fieldType.stateClsId]; String name; if (type != TYPE_DC) { @@ -181,7 +181,7 @@ void MqttHandleHassClass::publishInverterField(std::shared_ptr } } -void MqttHandleHassClass::publishInverterButton(std::shared_ptr inv, const String& name, const String& state_topic, const String& payload, const String& icon, const String& device_class, const CategoryType category) +void MqttHandleHassClass::publishInverterButton(std::shared_ptr inv, const String& name, const String& state_topic, const String& payload, const String& icon, const DeviceClassType device_class, const CategoryType category) { const String serial = inv->serialString(); @@ -202,8 +202,8 @@ void MqttHandleHassClass::publishInverterButton(std::shared_ptr inv, const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& device_class, const CategoryType category) +void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr inv, const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const DeviceClassType device_class, const CategoryType category) { const String serial = inv->serialString(); @@ -371,7 +371,7 @@ void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr inv, const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const String& device_class, const CategoryType category) +void MqttHandleHassClass::publishInverterSensor(std::shared_ptr inv, const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const DeviceClassType device_class, const CategoryType category) { const String serial = inv->serialString();