mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
rename HA dev_i, SRC: do not fetch inactive circuits, long names, HA climated
This commit is contained in:
@@ -1896,7 +1896,12 @@ void EMSdevice::mqtt_ha_entity_config_create() {
|
||||
create_device_config = false; // only create the main config once
|
||||
count++;
|
||||
}
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// SRC thermostats mapped to connect/hs1/...
|
||||
if (dv.tag >= DeviceValueTAG::TAG_HS1 && !strcmp(dv.short_name, FL_(roomtemp)[0])) {
|
||||
Mqtt::publish_ha_climate_config(dv.tag, true, false, dv.min, dv.max);
|
||||
}
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// always create minimum one config
|
||||
if (count && (heap_caps_get_free_size(MALLOC_CAP_8BIT) < 65 * 1024)) { // checks free Heap+PSRAM
|
||||
break;
|
||||
|
||||
@@ -529,7 +529,7 @@ void Mqtt::ha_status() {
|
||||
}
|
||||
|
||||
doc["uniq_id"] = uniq;
|
||||
doc["obj_id"] = uniq;
|
||||
doc["default_entity_id"] = uniq;
|
||||
|
||||
doc["stat_t"] = Mqtt::base() + "/status";
|
||||
doc["name"] = "System status";
|
||||
@@ -827,7 +827,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
||||
snprintf(entity_with_tag, sizeof(entity_with_tag), "%s", entity);
|
||||
}
|
||||
|
||||
// build unique identifier also used as object_id which also becomes the Entity ID in HA
|
||||
// build unique identifier also used as default_entity_id which also becomes the Entity ID in HA
|
||||
char uniq_id[80];
|
||||
|
||||
// list of boiler entities that need conversion for 3.6 compatibility, add ww suffix
|
||||
@@ -981,7 +981,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
||||
// build the full payload
|
||||
JsonDocument doc;
|
||||
doc["uniq_id"] = uniq_id;
|
||||
doc["obj_id"] = uniq_id; // same as unique_id
|
||||
doc["default_entity_id"] = uniq_id; // same as unique_id
|
||||
|
||||
char sample_val[30] = "0"; // sample, correct(!) entity value, used only to prevent warning/error in HA if real value is not published yet
|
||||
|
||||
@@ -1235,7 +1235,9 @@ void Mqtt::add_ha_classes(JsonObject doc, const uint8_t device_type, const uint8
|
||||
}
|
||||
|
||||
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) {
|
||||
uint8_t hc_num = tag;
|
||||
uint8_t hc_num = tag < DeviceValueTAG::TAG_HS1 ? tag : tag - DeviceValueTAG::TAG_HS1 + 1;
|
||||
const char * devicename = tag < DeviceValueTAG::TAG_HS1 ? "thermostat" : "connect";
|
||||
const char * tagname = tag < DeviceValueTAG::TAG_HS1 ? "hc" : "hs";
|
||||
|
||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||
char topic_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||
@@ -1253,21 +1255,21 @@ bool Mqtt::publish_ha_climate_config(const int8_t tag, const bool has_roomtemp,
|
||||
char min_s[10];
|
||||
char max_s[10];
|
||||
|
||||
snprintf(topic, sizeof(topic), "climate/%s/thermostat_hc%d/config", Mqtt::basename().c_str(), hc_num);
|
||||
snprintf(topic, sizeof(topic), "climate/%s/%s_%s%d/config", Mqtt::basename().c_str(), devicename, tagname, hc_num);
|
||||
if (remove) {
|
||||
return queue_remove_topic(topic); // publish empty payload with retain flag
|
||||
}
|
||||
|
||||
if (Mqtt::is_nested()) {
|
||||
// nested format
|
||||
snprintf(hc_mode_s, sizeof(hc_mode_s), "value_json.hc%d.mode", hc_num);
|
||||
snprintf(hc_mode_cond, sizeof(hc_mode_cond), "value_json.hc%d is undefined or %s is undefined", hc_num, hc_mode_s);
|
||||
snprintf(seltemp_s, sizeof(seltemp_s), "value_json.hc%d.seltemp", hc_num);
|
||||
snprintf(seltemp_cond, sizeof(seltemp_cond), "value_json.hc%d is defined and %s is defined", hc_num, seltemp_s);
|
||||
snprintf(hc_mode_s, sizeof(hc_mode_s), "value_json.%s%d.mode", tagname, hc_num);
|
||||
snprintf(hc_mode_cond, sizeof(hc_mode_cond), "value_json.%s%d is undefined or %s is undefined", tagname, hc_num, hc_mode_s);
|
||||
snprintf(seltemp_s, sizeof(seltemp_s), "value_json.%s%d.seltemp", tagname, hc_num);
|
||||
snprintf(seltemp_cond, sizeof(seltemp_cond), "value_json.%s%d is defined and %s is defined", tagname, hc_num, seltemp_s);
|
||||
|
||||
if (has_roomtemp) {
|
||||
snprintf(currtemp_s, sizeof(currtemp_s), "value_json.hc%d.currtemp", hc_num);
|
||||
snprintf(currtemp_cond, sizeof(currtemp_cond), "value_json.hc%d is defined and %s is defined", hc_num, currtemp_s);
|
||||
snprintf(currtemp_s, sizeof(currtemp_s), "value_json.%s%d.currtemp", tagname, hc_num);
|
||||
snprintf(currtemp_cond, sizeof(currtemp_cond), "value_json.%s%d is defined and %s is defined", tagname, hc_num, currtemp_s);
|
||||
}
|
||||
snprintf(topic_t, sizeof(topic_t), "~/%s", Mqtt::tag_to_topic(EMSdevice::DeviceType::THERMOSTAT, DeviceValueTAG::TAG_NONE).c_str());
|
||||
} else {
|
||||
@@ -1281,7 +1283,10 @@ bool Mqtt::publish_ha_climate_config(const int8_t tag, const bool has_roomtemp,
|
||||
snprintf(currtemp_s, sizeof(currtemp_s), "value_json.currtemp");
|
||||
snprintf(currtemp_cond, sizeof(currtemp_cond), "%s is defined", currtemp_s);
|
||||
}
|
||||
snprintf(topic_t, sizeof(topic_t), "~/%s", Mqtt::tag_to_topic(EMSdevice::DeviceType::THERMOSTAT, DeviceValueTAG::TAG_HC1 + hc_num - 1).c_str());
|
||||
snprintf(topic_t,
|
||||
sizeof(topic_t),
|
||||
"~/%s",
|
||||
Mqtt::tag_to_topic(tag < DeviceValueTAG::TAG_HS1 ? EMSdevice::DeviceType::THERMOSTAT : EMSdevice::DeviceType::CONNECT, tag).c_str());
|
||||
}
|
||||
|
||||
snprintf(mode_str_tpl,
|
||||
@@ -1297,22 +1302,22 @@ bool Mqtt::publish_ha_climate_config(const int8_t tag, const bool has_roomtemp,
|
||||
hc_mode_s,
|
||||
Helpers::translated_word(FL_(off)));
|
||||
|
||||
snprintf(name_s, sizeof(name_s), "Hc%d", hc_num);
|
||||
snprintf(name_s, sizeof(name_s), "%s%d", tag < DeviceValueTAG::TAG_HS1 ? "Hc" : "Hs", hc_num);
|
||||
|
||||
if (Mqtt::entity_format() == entityFormat::MULTI_SHORT) {
|
||||
snprintf(uniq_id_s, sizeof(uniq_id_s), "%s_thermostat_hc%d", Mqtt::basename().c_str(), hc_num); // add basename
|
||||
snprintf(uniq_id_s, sizeof(uniq_id_s), "%s_%s%s%d", Mqtt::basename().c_str(), devicename, tagname, hc_num); // add basename
|
||||
} else {
|
||||
snprintf(uniq_id_s, sizeof(uniq_id_s), "thermostat_hc%d", hc_num); // backward compatible with v3.4
|
||||
snprintf(uniq_id_s, sizeof(uniq_id_s), "%s%d", devicename, hc_num); // backward compatible with v3.4
|
||||
}
|
||||
|
||||
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num);
|
||||
snprintf(mode_cmd_s, sizeof(mode_cmd_s), "~/thermostat/hc%d/mode", hc_num);
|
||||
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/%s/%s%d/seltemp", devicename, tagname, hc_num);
|
||||
snprintf(mode_cmd_s, sizeof(mode_cmd_s), "~/%s/%s%d/mode", devicename, tagname, hc_num);
|
||||
|
||||
JsonDocument doc;
|
||||
|
||||
doc["~"] = Mqtt::base();
|
||||
doc["uniq_id"] = uniq_id_s;
|
||||
doc["obj_id"] = uniq_id_s; // same as uniq_id
|
||||
doc["default_entity_id"] = uniq_id_s; // same as uniq_id
|
||||
doc["name"] = name_s;
|
||||
doc["mode_stat_t"] = topic_t;
|
||||
doc["mode_stat_tpl"] = mode_str_tpl;
|
||||
@@ -1341,7 +1346,7 @@ bool Mqtt::publish_ha_climate_config(const int8_t tag, const bool has_roomtemp,
|
||||
modes.add("heat");
|
||||
modes.add("off");
|
||||
|
||||
add_ha_dev_section(doc.as<JsonObject>(), "thermostat", nullptr, nullptr, nullptr, false); // add dev section
|
||||
add_ha_dev_section(doc.as<JsonObject>(), devicename, nullptr, nullptr, nullptr, false); // add dev section
|
||||
add_ha_avail_section(doc.as<JsonObject>(), topic_t, false, seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond); // add availability section
|
||||
|
||||
return queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
|
||||
@@ -34,11 +34,11 @@ Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
|
||||
DeviceValueUOM::DEGREES);
|
||||
// Roomthermostats
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
register_telegram_type(0x0BDD + i, "Room", false, MAKE_PF_CB(process_roomThermostat));
|
||||
register_telegram_type(0x0B3D + i, "Roomname", true, MAKE_PF_CB(process_roomThermostatName));
|
||||
register_telegram_type(0x0BB5 + i, "Roomsettings", true, MAKE_PF_CB(process_roomThermostatMode));
|
||||
register_telegram_type(0x1230 + i, "Roomparams", true, MAKE_PF_CB(process_roomThermostatParam));
|
||||
register_telegram_type(0x1244 + i, "Roomdata", false, MAKE_PF_CB(process_roomThermostatData));
|
||||
register_telegram_type(0x0BDD + i, "Room", false, MAKE_PF_CB(process_roomThermostat)); // broadcasted
|
||||
register_telegram_type(0x0B3D + i, "Roomname", false, MAKE_PF_CB(process_roomThermostatName)); // fetch for active circuits
|
||||
register_telegram_type(0x0BB5 + i, "Roomsettings", false, MAKE_PF_CB(process_roomThermostatMode)); // fetch for active circuits
|
||||
register_telegram_type(0x1230 + i, "Roomparams", false, MAKE_PF_CB(process_roomThermostatParam)); // fetch for active circuits
|
||||
register_telegram_type(0x1244 + i, "Roomdata", false, MAKE_PF_CB(process_roomThermostatData)); // broadcasted
|
||||
}
|
||||
// register_telegram_type(0xDB65, "Roomschedule", true, MAKE_PF_CB(process_roomSchedule));
|
||||
// 0x2040, broadcast 36 bytes:
|
||||
@@ -84,6 +84,9 @@ std::shared_ptr<Connect::RoomCircuit> Connect::room_circuit(const uint8_t num, c
|
||||
room_circuits_.push_back(new_room);
|
||||
// register the device values
|
||||
register_device_values_room(new_room);
|
||||
toggle_fetch(0x0B3D + num, true); // name
|
||||
toggle_fetch(0x0BB5 + num, true); // mode
|
||||
toggle_fetch(0x1230 + num, true); // unknown
|
||||
|
||||
return new_room; // return back point to new HC object
|
||||
}
|
||||
@@ -115,16 +118,13 @@ void Connect::process_roomThermostatName(std::shared_ptr<const Telegram> telegra
|
||||
if (rc == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (telegram->offset > 1 || telegram->message_length < 3) {
|
||||
return;
|
||||
|
||||
for (uint8_t i = telegram->offset; i < telegram->message_length + telegram->offset && i < 100; i++) {
|
||||
if ((i > 1) && (i % 2) == 0) {
|
||||
rc->name_[(i - 2) / 2] = telegram->message_data[i];
|
||||
}
|
||||
std::string s;
|
||||
for (uint8_t i = 2 - telegram->offset; (i < telegram->message_length) && (telegram->message_data[i] != 0); i += 2) {
|
||||
s += (char)telegram->message_data[i];
|
||||
}
|
||||
if (s.length()) {
|
||||
has_update(rc->name_, s.c_str(), s.length() + 1);
|
||||
}
|
||||
rc->name_[50] = ' \0'; // make sure name is terminated
|
||||
}
|
||||
|
||||
// settings 0-mode, 1-tempautotemp, 3 - manualtemp, 6,7 - ?
|
||||
@@ -137,10 +137,20 @@ void Connect::process_roomThermostatMode(std::shared_ptr<const Telegram> telegra
|
||||
has_update(telegram, rc->mode_, 0);
|
||||
}
|
||||
|
||||
// unknown telegrams, needs fetch
|
||||
void Connect::process_roomThermostatParam(std::shared_ptr<const Telegram> telegram) {
|
||||
auto rc = room_circuit(telegram->type_id - 0x1230);
|
||||
if (rc == nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// unknown broadcasted telegrams
|
||||
void Connect::process_roomThermostatData(std::shared_ptr<const Telegram> telegram) {
|
||||
auto rc = room_circuit(telegram->type_id - 0x1244);
|
||||
if (rc == nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Settings:
|
||||
@@ -175,17 +185,22 @@ bool Connect::set_seltemp(const char * value, const int8_t id) {
|
||||
|
||||
bool Connect::set_name(const char * value, const int8_t id) {
|
||||
auto rc = room_circuit(id - DeviceValueTAG::TAG_HS1);
|
||||
if (rc == nullptr || value == nullptr || strlen(value) > 12) {
|
||||
if (rc == nullptr || value == nullptr || strlen(value) > 50) {
|
||||
return false;
|
||||
}
|
||||
uint8_t data[strlen(value) * 2];
|
||||
uint8_t * d = data;
|
||||
const char * c = value;
|
||||
while (*c != 0) {
|
||||
*d++ = 0;
|
||||
*d++ = *c++;
|
||||
uint8_t len = strlen(value) * 2 + 2;
|
||||
uint8_t data[len];
|
||||
for (uint8_t i = 0; i < strlen(value) + 1; i++) { // include terminating '\0'
|
||||
data[2 * i] = 0;
|
||||
data[2 * i + 1] = value[i];
|
||||
}
|
||||
uint8_t ofs = 0;
|
||||
while (len > 0) {
|
||||
uint8_t part = len > 25 ? 25 : len;
|
||||
write_command(0x0B3D + rc->room(), ofs + 1, &data[ofs], part, 0);
|
||||
ofs += part;
|
||||
len -= part;
|
||||
}
|
||||
write_command(0x0B3D + rc->room(), 1, data, sizeof(data), 0x0B3D + rc->room());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class Connect : public EMSdevice {
|
||||
int8_t humidity_;
|
||||
uint8_t seltemp_;
|
||||
uint8_t mode_;
|
||||
char name_[25];
|
||||
char name_[51];
|
||||
int16_t dewtemp_;
|
||||
|
||||
uint8_t room() {
|
||||
|
||||
Reference in New Issue
Block a user