Skip to content

Commit 9da73ba

Browse files
committed
Support MQTT Discovery (AD) with Domoticz #2177
1 parent 2cd6088 commit 9da73ba

File tree

3 files changed

+27
-51
lines changed

3 files changed

+27
-51
lines changed

src/analogsensor.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ void AnalogSensor::publish_values(const bool force) {
533533
char val_obj[50];
534534
char val_cond[95];
535535
if (Mqtt::is_nested()) {
536-
snprintf(val_obj, sizeof(val_obj), "value_json['%02d'].value", sensor.gpio()); // TODO change for Domoticz
536+
snprintf(val_obj, sizeof(val_obj), "value_json['%02d']['value']", sensor.gpio());
537537
snprintf(val_cond, sizeof(val_cond), "value_json['%02d'] is defined and %s is defined", sensor.gpio(), val_obj);
538538
} else {
539539
snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str());

src/mqtt.cpp

+25-49
Original file line numberDiff line numberDiff line change
@@ -934,14 +934,12 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
934934
char config_topic[70];
935935
snprintf(config_topic, sizeof(config_topic), "%s/%s_%s/config", mqtt_basename_.c_str(), device_name, entity_with_tag);
936936

937-
bool add_ha_classes = true; // default we'll add the "unit_of_meas", "stat_cla" and "dev_cla" attributes
938-
939937
// create the topic
940-
// depending on the type and whether the device entity is writable (a command)
938+
// depending on the type and whether the device entity is writable (i.e. a command)
941939
// https://developers.home-assistant.io/docs/core/entity
942-
char topic[MQTT_TOPIC_MAX_SIZE];
943-
// if it's a command then we can use Number, Switch, Select or Text. Otherwise stick to Sensor
940+
char topic[MQTT_TOPIC_MAX_SIZE] = {0};
944941
if (has_cmd) {
942+
// if it's a command then we can use Number, Switch, Select or Text. Otherwise stick to Sensor
945943
switch (type) {
946944
case DeviceValueType::INT8:
947945
case DeviceValueType::UINT8:
@@ -950,45 +948,40 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
950948
case DeviceValueType::UINT24:
951949
case DeviceValueType::UINT32:
952950
// number - https://www.home-assistant.io/integrations/number.mqtt
953-
// older Domoticz does not support number, use sensor
951+
// older Domoticz does not support number, will default to Sensor
954952
if (discovery_type() == discoveryType::HOMEASSISTANT || discovery_type() == discoveryType::DOMOTICZ_LATEST) {
955953
snprintf(topic, sizeof(topic), "number/%s", config_topic);
956-
} else {
957-
snprintf(topic, sizeof(topic), "sensor/%s", config_topic);
958954
}
959955
break;
960956
case DeviceValueType::BOOL:
961957
// switch - https://www.home-assistant.io/integrations/switch.mqtt
962958
snprintf(topic, sizeof(topic), "switch/%s", config_topic);
963-
add_ha_classes = false;
964959
break;
965960
case DeviceValueType::ENUM:
961+
// select - https://www.home-assistant.io/integrations/select.mqtt
966962
snprintf(topic, sizeof(topic), "select/%s", config_topic);
967-
add_ha_classes = false;
968963
break;
969-
case DeviceValueType::CMD: // hardcoded commands are always ENUMS
970-
// select - https://www.home-assistant.io/integrations/select.mqtt
964+
case DeviceValueType::CMD:
971965
if (uom == DeviceValueUOM::NONE) {
972-
snprintf(topic, sizeof(topic), "select/%s", config_topic);
966+
snprintf(topic, sizeof(topic), "select/%s", config_topic); // hardcoded commands are always ENUMS
973967
} else if (discovery_type() == discoveryType::HOMEASSISTANT || discovery_type() == discoveryType::DOMOTICZ_LATEST) {
974968
snprintf(topic, sizeof(topic), "number/%s", config_topic);
975-
} else {
976-
snprintf(topic, sizeof(topic), "sensor/%s", config_topic);
977969
}
978-
add_ha_classes = false;
979970
break;
980971
case DeviceValueType::STRING:
981972
// text - https://www.home-assistant.io/integrations/text.mqtt
982-
snprintf(topic, sizeof(topic), "text/%s", config_topic); // e.g. set_datetime, set_holiday, set_wwswitchtime
983-
add_ha_classes = false;
973+
// Domoticz does not support text, will default to Sensor
974+
if (discovery_type() == discoveryType::HOMEASSISTANT) {
975+
snprintf(topic, sizeof(topic), "text/%s", config_topic); // e.g. set_datetime, set_holiday, set_wwswitchtime
976+
}
984977
break;
985978
default:
986-
// plain old sensor
987-
snprintf(topic, sizeof(topic), "sensor/%s", config_topic);
988979
break;
989980
}
990-
} else {
991-
// it is not a command and a read-only sensor. Use then either sensor or binary_sensor
981+
}
982+
983+
// if at this point we don't have a topic created yet, create a default sensor one. We always need a topic.
984+
if (strlen(topic) == 0) {
992985
snprintf(topic, sizeof(topic), (type == DeviceValueType::BOOL) ? "binary_sensor/%s" : "sensor/%s", config_topic); // binary sensor (for booleans)
993986
}
994987

@@ -1054,21 +1047,6 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
10541047
doc["max"] = dv_set_max;
10551048
snprintf(sample_val, sizeof(sample_val), "%i", dv_set_min);
10561049
}
1057-
1058-
// set icons
1059-
// since these don't have a device class we need to add the icon ourselves
1060-
switch (uom) {
1061-
case DeviceValueUOM::DEGREES:
1062-
case DeviceValueUOM::DEGREES_R:
1063-
case DeviceValueUOM::K:
1064-
doc["ic"] = F_(icondegrees);
1065-
break;
1066-
case DeviceValueUOM::PERCENT:
1067-
doc["ic"] = F_(iconpercent);
1068-
break;
1069-
default:
1070-
break;
1071-
}
10721050
}
10731051

10741052
// friendly name = <tag> <name>
@@ -1129,26 +1107,23 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
11291107
// Domoticz doesn't support value templates, so we just use the value directly
11301108
// Also omit the uom and other state classes
11311109
doc["val_tpl"] = (std::string) "{{" + val_obj + "}}";
1132-
// add_ha_classes = false; // don't add the classes, categories of uom (dev_cla, stat_cla)
11331110
}
11341111
}
11351112

1136-
// Add the state class, device class and sometimes the icon.
1137-
// Used only for read-only sensors like Sensor and Binary Sensor but also Numbers
1138-
if (add_ha_classes) {
1139-
// first set the catagory for System entities
1140-
// https://github.com/emsesp/EMS-ESP32/discussions/1459#discussioncomment-7694873
1141-
if (device_type == EMSdevice::DeviceType::SYSTEM) {
1142-
doc["ent_cat"] = "diagnostic";
1143-
}
1144-
add_ha_uom(doc.as<JsonObject>(), type, uom, entity); // add the UoM, device and state class
1113+
// Add the state class, device class and an optional icon based on the uom
1114+
// first set the catagory for System entities
1115+
// https://github.com/emsesp/EMS-ESP32/discussions/1459#discussioncomment-7694873
1116+
if (device_type == EMSdevice::DeviceType::SYSTEM) {
1117+
doc["ent_cat"] = "diagnostic"; // instead of config
11451118
}
1119+
add_ha_uom(doc.as<JsonObject>(), type, uom, entity);
11461120

11471121
doc["dev"] = dev_json;
11481122

11491123
return queue_ha(topic, doc.as<JsonObject>());
11501124
}
11511125

1126+
// Add the state class, device class and an optional icon based on the uom
11521127
void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, const char * entity) {
11531128
const char * dc_ha = "dev_cla"; // device class
11541129
const char * sc_ha = "stat_cla"; // state class
@@ -1169,16 +1144,19 @@ void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, con
11691144
}
11701145

11711146
// set state and device class
1147+
// also icon, when there is no device class that sets one
11721148
switch (uom) {
11731149
case DeviceValueUOM::DEGREES:
11741150
case DeviceValueUOM::DEGREES_R:
11751151
case DeviceValueUOM::K:
11761152
doc[sc_ha] = F_(measurement);
11771153
doc[dc_ha] = "temperature";
1154+
doc["ic"] = F_(icondegrees); // icon
11781155
break;
11791156
case DeviceValueUOM::PERCENT:
11801157
doc[sc_ha] = F_(measurement);
11811158
doc[dc_ha] = "power_factor";
1159+
doc["ic"] = F_(iconpercent); // icon
11821160
break;
11831161
case DeviceValueUOM::SECONDS:
11841162
case DeviceValueUOM::MINUTES:
@@ -1256,8 +1234,6 @@ void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, con
12561234
}
12571235

12581236
bool Mqtt::publish_ha_climate_config(const int8_t tag, const bool has_roomtemp, const bool remove, const int16_t min, const uint32_t max) {
1259-
// TODO: check if Domoticz supports climate via MQTT discovery, otherwise exit this function if (discovery_type() != discoveryType::HOMEASSISTANT
1260-
12611237
uint8_t hc_num = tag;
12621238

12631239
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];

src/temperaturesensor.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ void TemperatureSensor::publish_values(const bool force) {
482482
char val_obj[70];
483483
char val_cond[170];
484484
if (Mqtt::is_nested()) {
485-
snprintf(val_obj, sizeof(val_obj), "value_json['%s'].temp", sensor.id().c_str()); // TODO change for Domoticz
485+
snprintf(val_obj, sizeof(val_obj), "value_json['%s']['temp']", sensor.id().c_str());
486486
snprintf(val_cond, sizeof(val_cond), "value_json['%s'] is defined and %s is defined", sensor.id().c_str(), val_obj);
487487
} else {
488488
snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str());

0 commit comments

Comments
 (0)