fixed thermostat model detection - #474

This commit is contained in:
proddy
2020-08-30 20:49:42 +02:00
parent b68d72f6de
commit 46ce2ce3b4
3 changed files with 55 additions and 23 deletions

View File

@@ -26,18 +26,20 @@ uuid::log::Logger Thermostat::logger_{F_(thermostat), uuid::log::Facility::CONSO
Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand) Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand)
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) { : EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
uint8_t actual_master_thermostat = EMSESP::actual_master_thermostat(); // what we're actually using uint8_t actual_master_thermostat = EMSESP::actual_master_thermostat(); // what we're actually using
uint8_t master_thermostat = EMSESP_DEFAULT_MASTER_THERMOSTAT; uint8_t master_thermostat = EMSESP_DEFAULT_MASTER_THERMOSTAT;
EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) { EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) {
master_thermostat = settings.master_thermostat; // what the user has defined master_thermostat = settings.master_thermostat; // what the user has defined
}); });
uint8_t model = this->model();
// if we're on auto mode, register this thermostat if it has a device id of 0x10, 0x17 or 0x18 // if we're on auto mode, register this thermostat if it has a device id of 0x10, 0x17 or 0x18
// or if its the master thermostat we defined // or if its the master thermostat we defined
// see https://github.com/proddy/EMS-ESP/issues/362#issuecomment-629628161 // see https://github.com/proddy/EMS-ESP/issues/362#issuecomment-629628161
if ((master_thermostat == device_id) || ((master_thermostat == EMSESP_DEFAULT_MASTER_THERMOSTAT) && (device_id < 0x19) && if ((master_thermostat == device_id)
((actual_master_thermostat == EMSESP_DEFAULT_MASTER_THERMOSTAT) || (device_id < actual_master_thermostat)))) { || ((master_thermostat == EMSESP_DEFAULT_MASTER_THERMOSTAT) && (device_id < 0x19)
&& ((actual_master_thermostat == EMSESP_DEFAULT_MASTER_THERMOSTAT) || (device_id < actual_master_thermostat)))) {
EMSESP::actual_master_thermostat(device_id); EMSESP::actual_master_thermostat(device_id);
actual_master_thermostat = device_id; actual_master_thermostat = device_id;
this->reserve_mem(25); // reserve some space for the telegram registries, to avoid memory fragmentation this->reserve_mem(25); // reserve some space for the telegram registries, to avoid memory fragmentation
@@ -47,7 +49,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
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); });
} }
// RC10 // RC10
if (flags == EMSdevice::EMS_DEVICE_FLAG_RC10) { if (model == EMSdevice::EMS_DEVICE_FLAG_RC10) {
monitor_typeids = {0xB1}; monitor_typeids = {0xB1};
set_typeids = {0xB0}; set_typeids = {0xB0};
for (uint8_t i = 0; i < monitor_typeids.size(); i++) { for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
@@ -56,7 +58,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
} }
// RC35 // RC35
} else if ((flags == EMSdevice::EMS_DEVICE_FLAG_RC35) || (flags == EMSdevice::EMS_DEVICE_FLAG_RC30_1)) { } else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC35) || (model == EMSdevice::EMS_DEVICE_FLAG_RC30_1)) {
monitor_typeids = {0x3E, 0x48, 0x52, 0x5C}; monitor_typeids = {0x3E, 0x48, 0x52, 0x5C};
set_typeids = {0x3D, 0x47, 0x51, 0x5B}; set_typeids = {0x3D, 0x47, 0x51, 0x5B};
timer_typeids = {0x3F, 0x49, 0x53, 0x5D}; timer_typeids = {0x3F, 0x49, 0x53, 0x5D};
@@ -68,7 +70,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(EMS_TYPE_wwSettings, F("WWSettings"), true, [&](std::shared_ptr<const Telegram> t) { process_RC35wwSettings(t); }); register_telegram_type(EMS_TYPE_wwSettings, F("WWSettings"), true, [&](std::shared_ptr<const Telegram> t) { process_RC35wwSettings(t); });
// RC20 // RC20
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20) { } else if (model == EMSdevice::EMS_DEVICE_FLAG_RC20) {
monitor_typeids = {0x91}; monitor_typeids = {0x91};
set_typeids = {0xA8}; set_typeids = {0xA8};
if (actual_master_thermostat == device_id) { if (actual_master_thermostat == device_id) {
@@ -80,7 +82,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(0xAF, F("RC20Remote"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Remote(t); }); register_telegram_type(0xAF, F("RC20Remote"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Remote(t); });
} }
// RC20 newer // RC20 newer
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20_2) { } else if (model == EMSdevice::EMS_DEVICE_FLAG_RC20_2) {
monitor_typeids = {0xAE}; monitor_typeids = {0xAE};
set_typeids = {0xAD}; set_typeids = {0xAD};
if (actual_master_thermostat == device_id) { if (actual_master_thermostat == device_id) {
@@ -92,7 +94,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(0xAF, F("RC20Remote"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Remote(t); }); register_telegram_type(0xAF, F("RC20Remote"), false, [&](std::shared_ptr<const Telegram> t) { process_RC20Remote(t); });
} }
// RC30 // RC30
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC30) { } else if (model == EMSdevice::EMS_DEVICE_FLAG_RC30) {
monitor_typeids = {0x41}; monitor_typeids = {0x41};
set_typeids = {0xA7}; set_typeids = {0xA7};
for (uint8_t i = 0; i < monitor_typeids.size(); i++) { for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
@@ -101,13 +103,13 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
} }
// EASY // EASY
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_EASY) { } else if (model == EMSdevice::EMS_DEVICE_FLAG_EASY) {
monitor_typeids = {0x0A}; monitor_typeids = {0x0A};
set_typeids = {}; set_typeids = {};
register_telegram_type(monitor_typeids[0], F("EasyMonitor"), false, [&](std::shared_ptr<const Telegram> t) { process_EasyMonitor(t); }); register_telegram_type(monitor_typeids[0], F("EasyMonitor"), false, [&](std::shared_ptr<const Telegram> t) { process_EasyMonitor(t); });
// RC300/RC100 // RC300/RC100
} else if ((flags == EMSdevice::EMS_DEVICE_FLAG_RC300) || (flags == EMSdevice::EMS_DEVICE_FLAG_RC100)) { } else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC300) || (model == EMSdevice::EMS_DEVICE_FLAG_RC100)) {
monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8}; monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8};
set_typeids = {0x02B9, 0x02BA, 0x02BB, 0x02BC}; set_typeids = {0x02B9, 0x02BA, 0x02BB, 0x02BC};
for (uint8_t i = 0; i < monitor_typeids.size(); i++) { for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
@@ -118,7 +120,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(0x31E, F("RC300WWmode"), false, [&](std::shared_ptr<const Telegram> t) { process_RC300WWmode(t); }); register_telegram_type(0x31E, F("RC300WWmode"), false, [&](std::shared_ptr<const Telegram> t) { process_RC300WWmode(t); });
// JUNKERS/HT3 // JUNKERS/HT3
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) { } else if (model == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
monitor_typeids = {0x016F, 0x0170, 0x0171, 0x0172}; monitor_typeids = {0x016F, 0x0170, 0x0171, 0x0172};
set_typeids = {0x0165, 0x0166, 0x0167, 0x0168}; set_typeids = {0x0165, 0x0166, 0x0167, 0x0168};
for (uint8_t i = 0; i < monitor_typeids.size(); i++) { for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
@@ -126,7 +128,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(set_typeids[i], F("JunkersSet"), false, [&](std::shared_ptr<const Telegram> t) { process_JunkersSet(t); }); register_telegram_type(set_typeids[i], F("JunkersSet"), false, [&](std::shared_ptr<const Telegram> t) { process_JunkersSet(t); });
} }
} else if (flags == (EMSdevice::EMS_DEVICE_FLAG_JUNKERS | EMSdevice::EMS_DEVICE_FLAG_JUNKERS_2)) { } else if (model == (EMSdevice::EMS_DEVICE_FLAG_JUNKERS | EMSdevice::EMS_DEVICE_FLAG_JUNKERS_2)) {
monitor_typeids = {0x016F, 0x0170, 0x0171, 0x0172}; monitor_typeids = {0x016F, 0x0170, 0x0171, 0x0172};
set_typeids = {0x0179, 0x017A, 0x017B, 0x017C}; set_typeids = {0x0179, 0x017A, 0x017B, 0x017C};
for (uint8_t i = 0; i < monitor_typeids.size(); i++) { for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
@@ -162,7 +164,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
// prepare data for Web UI // prepare data for Web UI
void Thermostat::device_info(JsonArray & root) { void Thermostat::device_info(JsonArray & root) {
uint8_t flags = (this->flags() & 0x0F); // specific thermostat characteristics, strip the option bits uint8_t flags = this->model();
for (const auto & hc : heating_circuits_) { for (const auto & hc : heating_circuits_) {
if (!Helpers::hasValue(hc->setpoint_roomTemp)) { if (!Helpers::hasValue(hc->setpoint_roomTemp)) {
@@ -267,7 +269,7 @@ void Thermostat::publish_values() {
return; return;
} }
uint8_t flags = (this->flags() & 0x0F); // specific thermostat characteristics, stripping the option bits uint8_t flags = this->model();
bool has_data = false; bool has_data = false;
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc; StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
@@ -580,7 +582,7 @@ void Thermostat::register_mqtt_ha_config(uint8_t hc_num) {
doc["temp_step"] = "0.5"; doc["temp_step"] = "0.5";
JsonArray modes = doc.createNestedArray("modes"); JsonArray modes = doc.createNestedArray("modes");
uint8_t flags = (this->flags() & 0x0F); uint8_t flags = this->model();
if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20_2) { if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20_2) {
modes.add("night"); modes.add("night");
modes.add("day"); modes.add("day");
@@ -741,7 +743,7 @@ std::string Thermostat::mode_tostring(uint8_t mode) {
void Thermostat::show_values(uuid::console::Shell & shell) { void Thermostat::show_values(uuid::console::Shell & shell) {
EMSdevice::show_values(shell); // always call this to show header EMSdevice::show_values(shell); // always call this to show header
uint8_t flags = (this->flags() & 0x0F); // specific thermostat characteristics, strip the option bits uint8_t flags = this->model();
if (datetime_.size()) { if (datetime_.size()) {
shell.printfln(F(" Clock: %s"), datetime_.c_str()); shell.printfln(F(" Clock: %s"), datetime_.c_str());
@@ -1513,7 +1515,7 @@ void Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) {
break; break;
} }
switch (this->flags() & 0x0F) { switch (this->model()) {
case EMSdevice::EMS_DEVICE_FLAG_RC20: case EMSdevice::EMS_DEVICE_FLAG_RC20:
offset = EMS_OFFSET_RC20Set_mode; offset = EMS_OFFSET_RC20Set_mode;
validate_typeid = set_typeids[hc_p]; validate_typeid = set_typeids[hc_p];
@@ -1610,7 +1612,7 @@ void Thermostat::set_temperature(const float temperature, const uint8_t mode, co
return; return;
} }
uint8_t model = this->flags() & 0x0F; uint8_t model = this->model();
int8_t offset = -1; // we use -1 to check if there is a value int8_t offset = -1; // we use -1 to check if there is a value
uint8_t factor = 2; // some temperatures only use 1 uint8_t factor = 2; // some temperatures only use 1
uint16_t validate_typeid = monitor_typeids[hc->hc_num() - 1]; uint16_t validate_typeid = monitor_typeids[hc->hc_num() - 1];
@@ -1819,7 +1821,7 @@ void Thermostat::add_commands() {
register_mqtt_cmd(F("temp"), [&](const char * value, const int8_t id) { set_temp(value, id); }); register_mqtt_cmd(F("temp"), [&](const char * value, const int8_t id) { set_temp(value, id); });
register_mqtt_cmd(F("mode"), [&](const char * value, const int8_t id) { set_mode(value, id); }); register_mqtt_cmd(F("mode"), [&](const char * value, const int8_t id) { set_mode(value, id); });
uint8_t model = this->flags() & 0x0F; uint8_t model = this->model();
switch (model) { switch (model) {
case EMS_DEVICE_FLAG_RC20_2: case EMS_DEVICE_FLAG_RC20_2:
register_mqtt_cmd(F("nighttemp"), [&](const char * value, const int8_t id) { set_nighttemp(value, id); }); register_mqtt_cmd(F("nighttemp"), [&](const char * value, const int8_t id) { set_nighttemp(value, id); });

View File

@@ -105,6 +105,11 @@ class Thermostat : public EMSdevice {
void console_commands(Shell & shell, unsigned int context); void console_commands(Shell & shell, unsigned int context);
void add_commands(); void add_commands();
// specific thermostat characteristics, stripping the option bits at pos 6 and 7
inline uint8_t model() const {
return (this->flags() & 0x0F);
}
// each thermostat has a list of heating controller type IDs for reading and writing // each thermostat has a list of heating controller type IDs for reading and writing
std::vector<uint16_t> monitor_typeids; std::vector<uint16_t> monitor_typeids;
std::vector<uint16_t> set_typeids; std::vector<uint16_t> set_typeids;

View File

@@ -239,6 +239,31 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
shell.loop_all(); shell.loop_all();
} }
if (command == "tc100") {
shell.printfln(F("Testing adding a TC100 thermostat to the EMS bus..."));
// add_device(0x10, 165, version, EMSdevice::Brand::BUDERUS);
// add_device(0x17, 125, version, EMSdevice::Brand::BUDERUS); // test unknown class test
// add_device(0x17, 93, version, EMSdevice::Brand::BUDERUS);
// add_device(0x17, 254, version, EMSdevice::Brand::BUDERUS); // test unknown product_id
// EMSESP::add_device(0x18, 157, version, EMSdevice::Brand::BOSCH); // Bosch CR100 - https://github.com/proddy/EMS-ESP/issues/355
std::string version("02.21");
// add a boiler
// EMSESP::add_device(0x08, 123, version, EMSdevice::Brand::BUDERUS); // Nefit Trendline
// add a thermostat
EMSESP::add_device(0x18, 202, version, EMSdevice::Brand::BOSCH); // Bosch TC100 - https://github.com/proddy/EMS-ESP/issues/474
// RCPLUSStatusMessage_HC1(0x01A5)
// uart_telegram({0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24,
// 0x03, 0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03});
shell.loop_all();
}
if (command == "solar") { if (command == "solar") {
shell.printfln(F("Testing Solar")); shell.printfln(F("Testing Solar"));