Skip to content

Commit

Permalink
MQTT Hass: Implement category as enum instead of String
Browse files Browse the repository at this point in the history
  • Loading branch information
tbnobody committed Sep 24, 2024
1 parent 2fb0260 commit bb4be0b
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 50 deletions.
25 changes: 17 additions & 8 deletions include/MqttHandleHass.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,22 @@ enum {
DEVICE_CLS_REACTIVE_POWER
};
const char* const deviceClasses[] = { 0, "current", "energy", "power", "voltage", "frequency", "temperature", "power_factor", "reactive_power" };

enum {
STATE_CLS_NONE = 0,
STATE_CLS_MEASUREMENT,
STATE_CLS_TOTAL_INCREASING
};
const char* const stateClasses[] = { 0, "measurement", "total_increasing" };

enum CategoryType {
CATEGORY_NONE = 0,
CATEGORY_CONFIG,
CATEGORY_DIAGNOSTIC
};
const char* const category_name[] = { 0, "config", "diagnostic" };


typedef struct {
FieldId_t fieldId; // field id
uint8_t deviceClsId; // device class
Expand Down Expand Up @@ -62,18 +71,18 @@ class MqttHandleHassClass {
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 String& category);
static void publishDtuBinarySensor(const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& device_class, const String& category);
static void publishInverterBinarySensor(std::shared_ptr<InverterAbstract> inv, const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& device_class, const String& 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 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<InverterAbstract> inv, const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& 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 String& category);
static void publishDtuSensor(const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const String& device_class, const String& category);
static void publishInverterSensor(std::shared_ptr<InverterAbstract> inv, const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const String& device_class, const String& 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 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<InverterAbstract> 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 publishInverterField(std::shared_ptr<InverterAbstract> inv, const ChannelType_t type, const ChannelNum_t channel, const byteAssign_fieldDeviceClass_t fieldType, const bool clear = false);
static void publishInverterButton(std::shared_ptr<InverterAbstract> inv, const String& name, const String& state_topic, const String& payload, const String& icon, const String& device_class, const String& category);
static void publishInverterNumber(std::shared_ptr<InverterAbstract> 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 String& category);
static void publishInverterButton(std::shared_ptr<InverterAbstract> inv, const String& name, const String& state_topic, const String& payload, const String& icon, const String& device_class, const CategoryType category);
static void publishInverterNumber(std::shared_ptr<InverterAbstract> 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<InverterAbstract> inv);
static void createDtuInfo(JsonDocument& doc);
Expand Down
88 changes: 46 additions & 42 deletions src/MqttHandleHass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,45 +58,45 @@ void MqttHandleHassClass::publishConfig()
const CONFIG_T& config = Configuration.get();

// publish DTU sensors
publishDtuSensor("IP", "dtu/ip", "", "mdi:network-outline", "", "diagnostic");
publishDtuSensor("WiFi Signal", "dtu/rssi", "dBm", "", "signal_strength", "diagnostic");
publishDtuSensor("Uptime", "dtu/uptime", "s", "", "duration", "diagnostic");
publishDtuSensor("Temperature", "dtu/temperature", "°C", "mdi:thermometer", "temperature", "diagnostic");
publishDtuSensor("Heap Size", "dtu/heap/size", "Bytes", "mdi:memory", "", "diagnostic");
publishDtuSensor("Heap Free", "dtu/heap/free", "Bytes", "mdi:memory", "", "diagnostic");
publishDtuSensor("Largest Free Heap Block", "dtu/heap/maxalloc", "Bytes", "mdi:memory", "", "diagnostic");
publishDtuSensor("Lifetime Minimum Free Heap", "dtu/heap/minfree", "Bytes", "mdi:memory", "", "diagnostic");
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("Yield Total", "ac/yieldtotal", "kWh", "", "energy", "");
publishDtuSensor("Yield Day", "ac/yieldday", "Wh", "", "energy", "");
publishDtuSensor("AC Power", "ac/power", "W", "", "power", "");
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);

publishDtuBinarySensor("Status", config.Mqtt.Lwt.Topic, config.Mqtt.Lwt.Value_Online, config.Mqtt.Lwt.Value_Offline, "connectivity", "diagnostic");
publishDtuBinarySensor("Status", config.Mqtt.Lwt.Topic, config.Mqtt.Lwt.Value_Online, config.Mqtt.Lwt.Value_Offline, "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", "", "config");
publishInverterButton(inv, "Turn Inverter On", "cmd/power", "1", "mdi:power-plug", "", "config");
publishInverterButton(inv, "Restart Inverter", "cmd/restart", "1", "", "restart", "config");
publishInverterButton(inv, "Reset Radio Statistics", "cmd/reset_rf_stats", "1", "", "", "config");
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);

publishInverterNumber(inv, "Limit NonPersistent Relative", "status/limit_relative", "cmd/limit_nonpersistent_relative", 0, 100, 0.1, "%", "mdi:speedometer", "config");
publishInverterNumber(inv, "Limit Persistent Relative", "status/limit_relative", "cmd/limit_persistent_relative", 0, 100, 0.1, "%", "mdi:speedometer", "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);

publishInverterNumber(inv, "Limit NonPersistent Absolute", "status/limit_absolute", "cmd/limit_nonpersistent_absolute", 0, MAX_INVERTER_LIMIT, 1, "W", "mdi:speedometer", "config");
publishInverterNumber(inv, "Limit Persistent Absolute", "status/limit_absolute", "cmd/limit_persistent_absolute", 0, MAX_INVERTER_LIMIT, 1, "W", "mdi:speedometer", "config");
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", "diagnostic");
publishInverterBinarySensor(inv, "Producing", "status/producing", "1", "0", "", "");
publishInverterBinarySensor(inv, "Reachable", "status/reachable", "1", "0", "connectivity", CATEGORY_DIAGNOSTIC);
publishInverterBinarySensor(inv, "Producing", "status/producing", "1", "0", "", CATEGORY_NONE);

publishInverterSensor(inv, "TX Requests", "radio/tx_request", "", "", "", "diagnostic");
publishInverterSensor(inv, "RX Success", "radio/rx_success", "", "", "", "diagnostic");
publishInverterSensor(inv, "RX Fail Receive Nothing", "radio/rx_fail_nothing", "", "", "", "diagnostic");
publishInverterSensor(inv, "RX Fail Receive Partial", "radio/rx_fail_partial", "", "", "", "diagnostic");
publishInverterSensor(inv, "RX Fail Receive Corrupt", "radio/rx_fail_corrupt", "", "", "", "diagnostic");
publishInverterSensor(inv, "TX Re-Request Fragment", "radio/tx_re_request", "", "", "", "diagnostic");
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);

// Loop all channels
for (auto& t : inv->Statistics()->getChannelTypes()) {
Expand Down Expand Up @@ -181,7 +181,7 @@ void MqttHandleHassClass::publishInverterField(std::shared_ptr<InverterAbstract>
}
}

void MqttHandleHassClass::publishInverterButton(std::shared_ptr<InverterAbstract> inv, const String& name, const String& state_topic, const String& payload, const String& icon, const String& device_class, const String& category)
void MqttHandleHassClass::publishInverterButton(std::shared_ptr<InverterAbstract> inv, const String& name, const String& state_topic, const String& payload, const String& icon, const String& device_class, const CategoryType category)
{
const String serial = inv->serialString();

Expand All @@ -205,7 +205,9 @@ void MqttHandleHassClass::publishInverterButton(std::shared_ptr<InverterAbstract
if (device_class != "") {
root["dev_cla"] = device_class;
}
root["ent_cat"] = category;
if (category != CATEGORY_NONE) {
root["ent_cat"] = category_name[category];
}
root["cmd_t"] = cmdTopic;
root["payload_press"] = payload;

Expand All @@ -218,7 +220,7 @@ void MqttHandleHassClass::publishInverterNumber(
std::shared_ptr<InverterAbstract> inv, const String& name,
const String& stateTopic, const String& command_topic,
const int16_t min, const int16_t max, float step,
const String& unit_of_measure, const String& icon, const String& category)
const String& unit_of_measure, const String& icon, const CategoryType category)
{
const String serial = inv->serialString();

Expand All @@ -240,7 +242,9 @@ void MqttHandleHassClass::publishInverterNumber(
if (icon != "") {
root["ic"] = icon;
}
root["ent_cat"] = category;
if (category != CATEGORY_NONE) {
root["ent_cat"] = category_name[category];
}
root["cmd_t"] = cmdTopic;
root["stat_t"] = statTopic;
root["unit_of_meas"] = unit_of_measure;
Expand Down Expand Up @@ -326,7 +330,7 @@ void MqttHandleHassClass::publish(const String& subtopic, const JsonDocument& do
publish(subtopic, buffer);
}

void MqttHandleHassClass::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 String& category)
void MqttHandleHassClass::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)
{
String sensor_id = name;
sensor_id.toLowerCase();
Expand All @@ -341,15 +345,15 @@ void MqttHandleHassClass::publishBinarySensor(JsonDocument& doc, const String& r
if (device_class != "") {
doc["dev_cla"] = device_class;
}
if (category != "") {
doc["ent_cat"] = category;
if (category != CATEGORY_NONE) {
doc["ent_cat"] = category_name[category];
}

const String configTopic = "binary_sensor/" + root_device + "/" + sensor_id + "/config";
publish(configTopic, doc);
}

void MqttHandleHassClass::publishDtuBinarySensor(const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& device_class, const String& category)
void MqttHandleHassClass::publishDtuBinarySensor(const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& device_class, const CategoryType category)
{
const String dtuId = getDtuUniqueId();

Expand All @@ -358,7 +362,7 @@ void MqttHandleHassClass::publishDtuBinarySensor(const String& name, const Strin
publishBinarySensor(root, dtuId, dtuId, name, state_topic, payload_on, payload_off, device_class, category);
}

void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr<InverterAbstract> inv, const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& device_class, const String& category)
void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr<InverterAbstract> inv, const String& name, const String& state_topic, const String& payload_on, const String& payload_off, const String& device_class, const CategoryType category)
{
const String serial = inv->serialString();

Expand All @@ -367,7 +371,7 @@ void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr<InverterAb
publishBinarySensor(root, "dtu_" + serial, serial, name, serial + "/" + state_topic, payload_on, payload_off, device_class, category);
}

void MqttHandleHassClass::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 String& category)
void MqttHandleHassClass::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)
{
String sensor_id = name;
sensor_id.toLowerCase();
Expand All @@ -386,8 +390,8 @@ void MqttHandleHassClass::publishSensor(JsonDocument& doc, const String& root_de
if (device_class != "") {
doc["dev_cla"] = device_class;
}
if (category != "") {
doc["ent_cat"] = category;
if (category != CATEGORY_NONE) {
doc["ent_cat"] = category_name[category];
}

const CONFIG_T& config = Configuration.get();
Expand All @@ -399,7 +403,7 @@ void MqttHandleHassClass::publishSensor(JsonDocument& doc, const String& root_de
publish(configTopic, doc);
}

void MqttHandleHassClass::publishDtuSensor(const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const String& device_class, const String& category)
void MqttHandleHassClass::publishDtuSensor(const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const String& device_class, const CategoryType category)
{
const String dtuId = getDtuUniqueId();

Expand All @@ -408,7 +412,7 @@ void MqttHandleHassClass::publishDtuSensor(const String& name, const String& sta
publishSensor(root, dtuId, dtuId, name, state_topic, unit_of_measure, icon, device_class, category);
}

void MqttHandleHassClass::publishInverterSensor(std::shared_ptr<InverterAbstract> inv, const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const String& device_class, const String& category)
void MqttHandleHassClass::publishInverterSensor(std::shared_ptr<InverterAbstract> inv, const String& name, const String& state_topic, const String& unit_of_measure, const String& icon, const String& device_class, const CategoryType category)
{
const String serial = inv->serialString();

Expand Down

0 comments on commit bb4be0b

Please sign in to comment.