thermostat errorcode + HA config,

This commit is contained in:
MichaelDvP
2020-10-13 17:14:44 +02:00
parent a9041b7818
commit 4b029df45b
6 changed files with 142 additions and 21 deletions

View File

@@ -34,14 +34,19 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
} }
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) { if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) {
if (device_id == 0x2A) {
register_telegram_type(0x07D6, F("SM100wwTemperatur"), false, [&](std::shared_ptr<const Telegram> t) { process_SM100wwTemperature(t); });
register_telegram_type(0x07AA, F("SM100wwStatus"), false, [&](std::shared_ptr<const Telegram> t) { process_SM100wwStatus(t); });
register_telegram_type(0x07AB, F("SM100wwCommand"), false, [&](std::shared_ptr<const Telegram> t) { process_SM100wwCommand(t); });
} else {
register_telegram_type(0x0362, F("SM100Monitor"), true, [&](std::shared_ptr<const Telegram> t) { process_SM100Monitor(t); }); register_telegram_type(0x0362, F("SM100Monitor"), true, [&](std::shared_ptr<const Telegram> t) { process_SM100Monitor(t); });
register_telegram_type(0x0363, F("SM100Monitor2"), true, [&](std::shared_ptr<const Telegram> t) { process_SM100Monitor2(t); }); register_telegram_type(0x0363, F("SM100Monitor2"), true, [&](std::shared_ptr<const Telegram> t) { process_SM100Monitor2(t); });
register_telegram_type(0x0366, F("SM100Config"), true, [&](std::shared_ptr<const Telegram> t) { process_SM100Config(t); }); register_telegram_type(0x0366, F("SM100Config"), true, [&](std::shared_ptr<const Telegram> t) { process_SM100Config(t); });
register_telegram_type(0x0364, F("SM100Status"), false, [&](std::shared_ptr<const Telegram> t) { process_SM100Status(t); }); register_telegram_type(0x0364, F("SM100Status"), false, [&](std::shared_ptr<const Telegram> t) { process_SM100Status(t); });
register_telegram_type(0x036A, F("SM100Status2"), false, [&](std::shared_ptr<const Telegram> t) { process_SM100Status2(t); }); register_telegram_type(0x036A, F("SM100Status2"), false, [&](std::shared_ptr<const Telegram> t) { process_SM100Status2(t); });
register_telegram_type(0x038E, F("SM100Energy"), true, [&](std::shared_ptr<const Telegram> t) { process_SM100Energy(t); }); register_telegram_type(0x038E, F("SM100Energy"), true, [&](std::shared_ptr<const Telegram> t) { process_SM100Energy(t); });
} }
}
if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) { if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) {
register_telegram_type(0x0103, F("ISM1StatusMessage"), true, [&](std::shared_ptr<const Telegram> t) { process_ISM1StatusMessage(t); }); register_telegram_type(0x0103, F("ISM1StatusMessage"), true, [&](std::shared_ptr<const Telegram> t) { process_ISM1StatusMessage(t); });
@@ -129,15 +134,18 @@ void Solar::publish_values(JsonObject & data) {
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc; StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
JsonObject output = doc.to<JsonObject>(); JsonObject output = doc.to<JsonObject>();
if (export_values(output)) { if (export_values(output)) {
if (device_id() == 0x2A) {
Mqtt::publish(F("ww_data"), doc.as<JsonObject>());
} else {
Mqtt::publish(F("solar_data"), doc.as<JsonObject>()); Mqtt::publish(F("solar_data"), doc.as<JsonObject>());
}
// if we're using Home Assistant and haven't created the MQTT Discovery topics, do it now // if we're using Home Assistant and haven't created the MQTT Discovery topics, do it now
if ((Mqtt::mqtt_format() == Mqtt::Format::HA) && (!mqtt_ha_config_)) { if ((Mqtt::mqtt_format() == Mqtt::Format::HA) && (!mqtt_ha_config_)) {
register_mqtt_ha_config(); register_mqtt_ha_config();
mqtt_ha_config_ = true; mqtt_ha_config_ = true;
} }
} }
}
}
// publish config topic for HA MQTT Discovery // publish config topic for HA MQTT Discovery
void Solar::register_mqtt_ha_config() { void Solar::register_mqtt_ha_config() {
@@ -286,6 +294,27 @@ void Solar::process_SM100Monitor2(std::shared_ptr<const Telegram> telegram) {
// not implemented yet // not implemented yet
} }
// SM100wwTemperatur - 0x07D6
// Solar Module(0x2A) -> (0x00), (0x7D6), data: 01 C1 00 00 02 5B 01 AF 01 AD 80 00 01 90
void Solar::process_SM100wwTemperature(std::shared_ptr<const Telegram> telegram) {
// changed_ |= telegram->read_value(wwTemp_1_, 0);
// changed_ |= telegram->read_value(wwTemp_3_, 4);
// changed_ |= telegram->read_value(wwTemp_4_, 6);
// changed_ |= telegram->read_value(wwTemp_5_, 8);
// changed_ |= telegram->read_value(wwTemp_7_, 12);
}
// SM100wwStatus - 0x07AA
// Solar Module(0x2A) -> (0x00), (0x7AA), data: 64 00 04 00 03 00 28 01 0F
void Solar::process_SM100wwStatus(std::shared_ptr<const Telegram> telegram) {
// changed_ |= telegram->read_value(wwPump_, 0);
}
// SM100wwCommand - 0x07AB
// Thermostat(0x10) -> Solar Module(0x2A), (0x7AB), data: 01 00 01
void Solar::process_SM100wwCommand(std::shared_ptr<const Telegram> telegram) {
// not implemented yet
}
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
// SM100Config - 0x0366 // SM100Config - 0x0366

View File

@@ -81,6 +81,10 @@ class Solar : public EMSdevice {
void process_SM100Status2(std::shared_ptr<const Telegram> telegram); void process_SM100Status2(std::shared_ptr<const Telegram> telegram);
void process_SM100Energy(std::shared_ptr<const Telegram> telegram); void process_SM100Energy(std::shared_ptr<const Telegram> telegram);
void process_SM100wwTemperature(std::shared_ptr<const Telegram> telegram);
void process_SM100wwStatus(std::shared_ptr<const Telegram> telegram);
void process_SM100wwCommand(std::shared_ptr<const Telegram> telegram);
void process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram); void process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram);
void process_ISM1Set(std::shared_ptr<const Telegram> telegram); void process_ISM1Set(std::shared_ptr<const Telegram> telegram);
}; };

View File

@@ -47,6 +47,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
// common telegram handlers // common telegram handlers
register_telegram_type(EMS_TYPE_RCOutdoorTemp, F("RCOutdoorTemp"), false, [&](std::shared_ptr<const Telegram> t) { process_RCOutdoorTemp(t); }); register_telegram_type(EMS_TYPE_RCOutdoorTemp, F("RCOutdoorTemp"), false, [&](std::shared_ptr<const Telegram> t) { process_RCOutdoorTemp(t); });
register_telegram_type(EMS_TYPE_RCTime, F("RCTime"), false, [&](std::shared_ptr<const Telegram> t) { process_RCTime(t); }); register_telegram_type(EMS_TYPE_RCTime, F("RCTime"), false, [&](std::shared_ptr<const Telegram> t) { process_RCTime(t); });
register_telegram_type(0xA2, F("RCError"), false, [&](std::shared_ptr<const Telegram> t) { process_RCError(t); });
} }
// RC10 // RC10
if (model == EMSdevice::EMS_DEVICE_FLAG_RC10) { if (model == EMSdevice::EMS_DEVICE_FLAG_RC10) {
@@ -175,6 +176,7 @@ void Thermostat::device_info_web(JsonArray & root) {
JsonObject output_main = doc_main.to<JsonObject>(); JsonObject output_main = doc_main.to<JsonObject>();
if (export_values_main(output_main)) { if (export_values_main(output_main)) {
print_value_json(root, F("time"), nullptr, F_(time), nullptr, output_main); print_value_json(root, F("time"), nullptr, F_(time), nullptr, output_main);
print_value_json(root, F("errorcode"), nullptr, F_(error), nullptr, output_main);
print_value_json(root, F("display"), nullptr, F_(display), nullptr, output_main); print_value_json(root, F("display"), nullptr, F_(display), nullptr, output_main);
print_value_json(root, F("language"), nullptr, F_(language), nullptr, output_main); print_value_json(root, F("language"), nullptr, F_(language), nullptr, output_main);
print_value_json(root, F("offsetclock"), nullptr, F_(offsetclock), nullptr, output_main); print_value_json(root, F("offsetclock"), nullptr, F_(offsetclock), nullptr, output_main);
@@ -256,6 +258,7 @@ void Thermostat::show_values(uuid::console::Shell & shell) {
JsonObject output_main = doc_main.to<JsonObject>(); JsonObject output_main = doc_main.to<JsonObject>();
if (export_values_main(output_main)) { if (export_values_main(output_main)) {
print_value_json(shell, F("time"), nullptr, F_(time), nullptr, output_main); print_value_json(shell, F("time"), nullptr, F_(time), nullptr, output_main);
print_value_json(shell, F("errorcode"), nullptr, F_(error), nullptr, output_main);
print_value_json(shell, F("display"), nullptr, F_(display), nullptr, output_main); print_value_json(shell, F("display"), nullptr, F_(display), nullptr, output_main);
print_value_json(shell, F("language"), nullptr, F_(language), nullptr, output_main); print_value_json(shell, F("language"), nullptr, F_(language), nullptr, output_main);
print_value_json(shell, F("offsetclock"), nullptr, F_(offsetclock), nullptr, output_main); print_value_json(shell, F("offsetclock"), nullptr, F_(offsetclock), nullptr, output_main);
@@ -343,6 +346,10 @@ bool Thermostat::export_values_main(JsonObject & rootThermostat) {
rootThermostat["time"] = datetime_.c_str(); rootThermostat["time"] = datetime_.c_str();
} }
if (Helpers::hasValue(errorNumber_)) {
rootThermostat["errorcode"] = errorCode_.c_str();
}
if (model == EMSdevice::EMS_DEVICE_FLAG_RC30_1) { if (model == EMSdevice::EMS_DEVICE_FLAG_RC30_1) {
// Display // Display
if (Helpers::hasValue(ibaMainDisplay_)) { if (Helpers::hasValue(ibaMainDisplay_)) {
@@ -443,6 +450,12 @@ bool Thermostat::export_values_main(JsonObject & rootThermostat) {
rootThermostat["wwcircmode"] = Helpers::render_enum(s, {"off", "on", "auto"}, wwCircMode_); rootThermostat["wwcircmode"] = Helpers::render_enum(s, {"off", "on", "auto"}, wwCircMode_);
} }
if ((Mqtt::mqtt_format() == Mqtt::Format::HA) && (!ha_registered())) {
// see if we have already registered this with HA MQTT Discovery, if not send the config
register_mqtt_ha_config();
ha_registered(true);
}
return (rootThermostat.size()); return (rootThermostat.size());
} }
@@ -720,6 +733,43 @@ std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(std::sha
return heating_circuits_.back(); // even after sorting, this should still point back to the newly created HC return heating_circuits_.back(); // even after sorting, this should still point back to the newly created HC
} }
// publish config topic for HA MQTT Discovery
// homeassistant/climate/ems-esp/thermostat_/config
void Thermostat::register_mqtt_ha_config() {
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
doc["name"] = F("Thermostat");
doc["uniq_id"] = F("thermostat");
doc["ic"] = F("mdi:home-thermometer-outline");
char stat_t[50];
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/thermostat_data"), System::hostname().c_str());
doc["stat_t"] = stat_t;
doc["val_tpl"] = F("{{value_json.time}}");
JsonObject dev = doc.createNestedObject("dev");
dev["name"] = F("EMS-ESP Thermostat");
dev["sw"] = EMSESP_APP_VERSION;
dev["mf"] = this->brand_to_string();
dev["mdl"] = this->name();
JsonArray ids = dev.createNestedArray("ids");
ids.add("ems-esp-thermostat");
Mqtt::publish_retain(F("homeassistant/sensor/ems-esp/thermostat/config"), doc.as<JsonObject>(), true); // publish the config payload with retain flag
Mqtt::register_mqtt_ha_sensor(nullptr, F_(time), this->device_type(), "time", nullptr, nullptr);
Mqtt::register_mqtt_ha_sensor(nullptr, F_(error), this->device_type(), "errorcode", nullptr, nullptr);
uint8_t model = this->model();
if (model == EMS_DEVICE_FLAG_RC35 || model == EMS_DEVICE_FLAG_RC35) {
Mqtt::register_mqtt_ha_sensor(nullptr, F_(dampedtemp), this->device_type(), "dampedtemp", F_(degrees), F_(icontemperature));
Mqtt::register_mqtt_ha_sensor(nullptr, F_(building), this->device_type(), "building", nullptr, nullptr);
Mqtt::register_mqtt_ha_sensor(nullptr, F_(minexttemp), this->device_type(), "minexttemp", F_(degrees), F_(icontemperature));
Mqtt::register_mqtt_ha_sensor(nullptr, F_(wwmode), this->device_type(), "wwmode", nullptr, nullptr);
Mqtt::register_mqtt_ha_sensor(nullptr, F_(wwtemp), this->device_type(), "wwtemp", F_(degrees), F_(icontemperature));
Mqtt::register_mqtt_ha_sensor(nullptr, F_(wwtemplow), this->device_type(), "wwtemplow", F_(degrees), F_(icontemperature));
Mqtt::register_mqtt_ha_sensor(nullptr, F_(wwcircmode), this->device_type(), "wwcircmode", nullptr, nullptr);
}
}
// publish config topic for HA MQTT Discovery // publish config topic for HA MQTT Discovery
// homeassistant/climate/ems-esp/thermostat_hc1/config // homeassistant/climate/ems-esp/thermostat_hc1/config
void Thermostat::register_mqtt_ha_config(uint8_t hc_num) { void Thermostat::register_mqtt_ha_config(uint8_t hc_num) {
@@ -1290,6 +1340,28 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
} }
} }
// process_RCError - type 0xA2 - error maeesage - 14 bytes long
// 10 00 A2 00 41 32 32 03 30 00 02 00 00 00 00 00 00 02 CRC
// A 2 2 816
void Thermostat::process_RCError(std::shared_ptr<const Telegram> telegram) {
if (errorCode_.empty()) {
errorCode_.resize(10, '\0');
}
char buf[4];
buf[0] = telegram->message_data[0];
buf[1] = telegram->message_data[1];
buf[2] = telegram->message_data[2];
buf[3] = 0;
changed_ |= telegram->read_value(errorNumber_, 3);
snprintf_P(&errorCode_[0],
errorCode_.capacity() + 1,
PSTR("%s(%d)"),
buf,
errorNumber_
);
}
// 0xA5 - Set minimum external temperature // 0xA5 - Set minimum external temperature
bool Thermostat::set_minexttemp(const char * value, const int8_t id) { bool Thermostat::set_minexttemp(const char * value, const int8_t id) {
int mt = 0; int mt = 0;
@@ -1354,11 +1426,15 @@ bool Thermostat::set_remotetemp(const char * value, const int8_t id) {
} }
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
if (hc == nullptr) {
return false;
}
if (f > 100 || f < 0) { if (f > 100 || f < 0) {
Roomctrl::set_remotetemp(hc_num - 1, EMS_VALUE_SHORT_NOTSET); Roomctrl::set_remotetemp(hc->hc_num() - 1, EMS_VALUE_SHORT_NOTSET);
} else { } else {
Roomctrl::set_remotetemp(hc_num - 1, (int16_t)(f * 10)); Roomctrl::set_remotetemp(hc->hc_num() - 1, (int16_t)(f * 10));
} }
return true; return true;

View File

@@ -110,6 +110,12 @@ class Thermostat : public EMSdevice {
void add_commands(); void add_commands();
bool export_values_main(JsonObject & doc); bool export_values_main(JsonObject & doc);
bool export_values_hc(uint8_t mqtt_format, JsonObject & doc); bool export_values_hc(uint8_t mqtt_format, JsonObject & doc);
bool ha_registered() const {
return ha_registered_;
}
void ha_registered(bool b) {
ha_registered_ = b;
}
// specific thermostat characteristics, stripping the last 4 bits // specific thermostat characteristics, stripping the last 4 bits
inline uint8_t model() const { inline uint8_t model() const {
@@ -123,8 +129,10 @@ class Thermostat : public EMSdevice {
std::vector<uint16_t> summer_typeids; std::vector<uint16_t> summer_typeids;
std::string datetime_; // date and time stamp std::string datetime_; // date and time stamp
std::string errorCode_; // code as string i.e. "A22(816)"
bool changed_ = false; bool changed_ = false;
bool ha_registered_ = false;
// Installation parameters // Installation parameters
uint8_t ibaMainDisplay_ = uint8_t ibaMainDisplay_ =
@@ -135,6 +143,7 @@ class Thermostat : public EMSdevice {
uint8_t ibaBuildingType_ = EMS_VALUE_UINT_NOTSET; // building type: 0 = light, 1 = medium, 2 = heavy uint8_t ibaBuildingType_ = EMS_VALUE_UINT_NOTSET; // building type: 0 = light, 1 = medium, 2 = heavy
uint8_t ibaClockOffset_ = EMS_VALUE_UINT_NOTSET; // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s uint8_t ibaClockOffset_ = EMS_VALUE_UINT_NOTSET; // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
uint16_t errorNumber_ = EMS_VALUE_USHORT_NOTSET;
int8_t dampedoutdoortemp_ = EMS_VALUE_INT_NOTSET; int8_t dampedoutdoortemp_ = EMS_VALUE_INT_NOTSET;
uint16_t tempsensor1_ = EMS_VALUE_USHORT_NOTSET; uint16_t tempsensor1_ = EMS_VALUE_USHORT_NOTSET;
uint16_t tempsensor2_ = EMS_VALUE_USHORT_NOTSET; uint16_t tempsensor2_ = EMS_VALUE_USHORT_NOTSET;
@@ -226,6 +235,7 @@ class Thermostat : public EMSdevice {
std::shared_ptr<Thermostat::HeatingCircuit> heating_circuit(std::shared_ptr<const Telegram> telegram); std::shared_ptr<Thermostat::HeatingCircuit> heating_circuit(std::shared_ptr<const Telegram> telegram);
std::shared_ptr<Thermostat::HeatingCircuit> heating_circuit(const uint8_t hc_num); std::shared_ptr<Thermostat::HeatingCircuit> heating_circuit(const uint8_t hc_num);
void register_mqtt_ha_config();
void register_mqtt_ha_config(uint8_t hc_num); void register_mqtt_ha_config(uint8_t hc_num);
bool thermostat_ha_cmd(const char * message, uint8_t hc_num); bool thermostat_ha_cmd(const char * message, uint8_t hc_num);
@@ -234,6 +244,7 @@ class Thermostat : public EMSdevice {
void process_RCOutdoorTemp(std::shared_ptr<const Telegram> telegram); void process_RCOutdoorTemp(std::shared_ptr<const Telegram> telegram);
void process_IBASettings(std::shared_ptr<const Telegram> telegram); void process_IBASettings(std::shared_ptr<const Telegram> telegram);
void process_RCTime(std::shared_ptr<const Telegram> telegram); void process_RCTime(std::shared_ptr<const Telegram> telegram);
void process_RCError(std::shared_ptr<const Telegram> telegram);
void process_RC35wwSettings(std::shared_ptr<const Telegram> telegram); void process_RC35wwSettings(std::shared_ptr<const Telegram> telegram);
void process_RC35Monitor(std::shared_ptr<const Telegram> telegram); void process_RC35Monitor(std::shared_ptr<const Telegram> telegram);
void process_RC35Set(std::shared_ptr<const Telegram> telegram); void process_RC35Set(std::shared_ptr<const Telegram> telegram);

View File

@@ -224,6 +224,7 @@ MAKE_PSTR(flowSetTemp, "Setpoint flow temperature")
// thermostat // thermostat
MAKE_PSTR(time, "Time") MAKE_PSTR(time, "Time")
MAKE_PSTR(error, "Error code")
MAKE_PSTR(display, "Display") MAKE_PSTR(display, "Display")
MAKE_PSTR(language, "Language") MAKE_PSTR(language, "Language")
MAKE_PSTR(offsetclock, "Offset clock") MAKE_PSTR(offsetclock, "Offset clock")

View File

@@ -696,7 +696,7 @@ void Mqtt::register_mqtt_ha_binary_sensor(const __FlashStringHelper * name, cons
char state_t[50]; char state_t[50];
snprintf_P(state_t, sizeof(state_t), PSTR("%s/%s"), hostname_.c_str(), entity); snprintf_P(state_t, sizeof(state_t), PSTR("%s/%s"), hostname_.c_str(), entity);
doc["stat_t"] = state_t; doc["stat_t"] = state_t;
/*
EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) { EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) {
if (settings.bool_format == BOOL_FORMAT_ONOFF) { if (settings.bool_format == BOOL_FORMAT_ONOFF) {
doc[F("payload_on")] = F("on"); doc[F("payload_on")] = F("on");
@@ -709,7 +709,7 @@ void Mqtt::register_mqtt_ha_binary_sensor(const __FlashStringHelper * name, cons
doc[F("payload_off")] = "0"; doc[F("payload_off")] = "0";
} }
}); });
*/
JsonObject dev = doc.createNestedObject(F("dev")); JsonObject dev = doc.createNestedObject(F("dev"));
JsonArray ids = dev.createNestedArray(F("ids")); JsonArray ids = dev.createNestedArray(F("ids"));
char ha_device[40]; char ha_device[40];