fix MQTT discovery of custom entity doesn't consider type of data #1587

This commit is contained in:
proddy
2024-02-10 09:51:29 +01:00
parent e6b61b7a51
commit 257b40c2e4
4 changed files with 113 additions and 104 deletions

View File

@@ -909,9 +909,6 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
doc["uniq_id"] = uniq_id; doc["uniq_id"] = uniq_id;
doc["obj_id"] = uniq_id; // same as unique_id doc["obj_id"] = uniq_id; // same as unique_id
const char * ic_ha = "ic"; // icon - only set this if there is no device class
const char * uom_ha = "unit_of_meas"; // unit of measure
char sample_val[30] = "0"; // sample, correct(!) entity value, used only to prevent warning/error in HA if real value is not published yet char sample_val[30] = "0"; // sample, correct(!) entity value, used only to prevent warning/error in HA if real value is not published yet
// we add the command topic parameter for commands // we add the command topic parameter for commands
@@ -970,10 +967,10 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
case DeviceValueUOM::DEGREES: case DeviceValueUOM::DEGREES:
case DeviceValueUOM::DEGREES_R: case DeviceValueUOM::DEGREES_R:
case DeviceValueUOM::K: case DeviceValueUOM::K:
doc[ic_ha] = F_(icondegrees); doc["ic"] = F_(icondegrees);
break; break;
case DeviceValueUOM::PERCENT: case DeviceValueUOM::PERCENT:
doc[ic_ha] = F_(iconpercent); doc["ic"] = F_(iconpercent);
break; break;
default: default:
break; break;
@@ -1027,9 +1024,35 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
doc["pl_off"] = Helpers::render_boolean(result, false); doc["pl_off"] = Helpers::render_boolean(result, false);
snprintf(sample_val, sizeof(sample_val), "'%s'", Helpers::render_boolean(result, false)); snprintf(sample_val, sizeof(sample_val), "'%s'", Helpers::render_boolean(result, false));
} }
} else { }
// always set the uom, using the standards except for hours/minutes/seconds
doc["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else " + sample_val + "}}";
// Add the state class, device class and sometimes the icon. Used only for read-only sensors like Sensor and Binary Sensor
if (readonly_sensors) {
// first set the catagory for System entities
// https://github.com/emsesp/EMS-ESP32/discussions/1459#discussioncomment-7694873
if (device_type == EMSdevice::DeviceType::SYSTEM) {
doc["ent_cat"] = "diagnostic";
}
add_ha_uom(doc.as<JsonObject>(), type, uom, entity); // add the UoM, device and state class
}
doc["dev"] = dev_json; // add the dev json object to the end
add_ha_sections_to_doc(nullptr, stat_t, doc, false, val_cond); // no name, since the "dev" has already been added
return queue_ha(topic, doc.as<JsonObject>());
}
void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, const char * entity) {
const char * dc_ha = "dev_cla"; // device class
const char * sc_ha = "stat_cla"; // state class
const char * uom_ha = "unit_of_meas"; // unit of measure
// set icon, except for booleans
// using HA specific codes from https://github.com/home-assistant/core/blob/dev/homeassistant/const.py // using HA specific codes from https://github.com/home-assistant/core/blob/dev/homeassistant/const.py
if (type != DeviceValueType::BOOL) {
if (uom == DeviceValueUOM::HOURS) { if (uom == DeviceValueUOM::HOURS) {
doc[uom_ha] = "h"; doc[uom_ha] = "h";
} else if (uom == DeviceValueUOM::MINUTES) { } else if (uom == DeviceValueUOM::MINUTES) {
@@ -1041,29 +1064,17 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
} }
} }
doc["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else " + sample_val + "}}"; // set state and device class
// Add the state class, device class and sometimes the icon. Used only for read-only sensors Sensor and Binary Sensor
if (readonly_sensors) {
// first set the catagory for System entities
// https://github.com/emsesp/EMS-ESP32/discussions/1459#discussioncomment-7694873
if (device_type == EMSdevice::DeviceType::SYSTEM) {
doc["ent_cat"] = "diagnostic";
}
const char * dc_ha = "dev_cla"; // device class
const char * sc_ha = "stat_cla"; // state class
switch (uom) { switch (uom) {
case DeviceValueUOM::DEGREES: case DeviceValueUOM::DEGREES:
case DeviceValueUOM::DEGREES_R: case DeviceValueUOM::DEGREES_R:
case DeviceValueUOM::K: case DeviceValueUOM::K:
doc[sc_ha] = F_(measurement); doc[sc_ha] = F_(measurement);
doc[dc_ha] = "temperature"; // no icon needed doc[dc_ha] = "temperature";
break; break;
case DeviceValueUOM::PERCENT: case DeviceValueUOM::PERCENT:
doc[sc_ha] = F_(measurement); doc[sc_ha] = F_(measurement);
doc[dc_ha] = "power_factor"; // no icon needed doc[dc_ha] = "power_factor";
break; break;
case DeviceValueUOM::SECONDS: case DeviceValueUOM::SECONDS:
case DeviceValueUOM::MINUTES: case DeviceValueUOM::MINUTES:
@@ -1076,10 +1087,10 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
doc[dc_ha] = "duration"; // https://github.com/emsesp/EMS-ESP32/issues/822 doc[dc_ha] = "duration"; // https://github.com/emsesp/EMS-ESP32/issues/822
break; break;
case DeviceValueUOM::KB: case DeviceValueUOM::KB:
doc[ic_ha] = F_(iconkb); doc["ic"] = F_(iconkb);
break; break;
case DeviceValueUOM::LMIN: case DeviceValueUOM::LMIN:
doc[ic_ha] = F_(iconlmin); doc["ic"] = F_(iconlmin);
doc[sc_ha] = F_(measurement); doc[sc_ha] = F_(measurement);
break; break;
case DeviceValueUOM::WH: case DeviceValueUOM::WH:
@@ -1095,7 +1106,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
doc[dc_ha] = "energy"; doc[dc_ha] = "energy";
break; break;
case DeviceValueUOM::UA: case DeviceValueUOM::UA:
doc[ic_ha] = F_(iconua); doc["ic"] = F_(iconua);
doc[sc_ha] = F_(measurement); doc[sc_ha] = F_(measurement);
break; break;
case DeviceValueUOM::BAR: case DeviceValueUOM::BAR:
@@ -1120,7 +1131,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
if ((type != DeviceValueType::STRING) if ((type != DeviceValueType::STRING)
&& (type == DeviceValueType::INT || type == DeviceValueType::UINT || type == DeviceValueType::SHORT || type == DeviceValueType::USHORT && (type == DeviceValueType::INT || type == DeviceValueType::UINT || type == DeviceValueType::SHORT || type == DeviceValueType::USHORT
|| type == DeviceValueType::ULONG)) { || type == DeviceValueType::ULONG)) {
doc[ic_ha] = F_(iconnum); // set icon doc["ic"] = F_(iconnum); // set icon
// determine if its a measurement or total increasing // determine if its a measurement or total increasing
// most of the values are measurement. for example Tx Reads will increment but can be reset to 0 after a restart // most of the values are measurement. for example Tx Reads will increment but can be reset to 0 after a restart
// all the starts are increasing, and they are ULONGs // all the starts are increasing, and they are ULONGs
@@ -1136,12 +1147,6 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
} }
} }
doc["dev"] = dev_json; // add the dev json object to the end
add_ha_sections_to_doc(nullptr, stat_t, doc, false, val_cond); // no name, since the "dev" has already been added
return queue_ha(topic, doc.as<JsonObject>());
}
bool Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, const bool remove, const int16_t min, const uint32_t max) { bool Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, const bool remove, const int16_t min, const uint32_t max) {
uint8_t hc_num = tag - DeviceValueTAG::TAG_HC1 + 1; uint8_t hc_num = tag - DeviceValueTAG::TAG_HC1 + 1;

View File

@@ -221,6 +221,8 @@ class Mqtt {
static std::string tag_to_topic(uint8_t device_type, uint8_t tag); static std::string tag_to_topic(uint8_t device_type, uint8_t tag);
static void add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, const char * entity = nullptr);
static void add_ha_sections_to_doc(const char * name, static void add_ha_sections_to_doc(const char * name,
const char * state_t, const char * state_t,
JsonDocument & config, JsonDocument & config,

View File

@@ -441,6 +441,8 @@ void WebCustomEntityService::publish(const bool force) {
} }
} }
Mqtt::add_ha_uom(config.as<JsonObject>(), entityItem.value_type, entityItem.uom); // add uom
Mqtt::add_ha_sections_to_doc("custom", stat_t, config, !ha_created, val_cond); Mqtt::add_ha_sections_to_doc("custom", stat_t, config, !ha_created, val_cond);
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>()); ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());

View File

@@ -32,7 +32,7 @@ class CustomEntityItem {
uint16_t type_id; uint16_t type_id;
uint8_t offset; uint8_t offset;
int8_t value_type; int8_t value_type;
uint8_t uom; uint8_t uom; // DeviceValueUOM
std::string name; std::string name;
double factor; double factor;
bool writeable; bool writeable;