This commit is contained in:
MichaelDvP
2022-05-29 18:48:43 +02:00
40 changed files with 1236 additions and 919 deletions

View File

@@ -68,7 +68,7 @@
{224, DeviceType::CONTROLLER, F("9000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{229, DeviceType::CONTROLLER, F("8700i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{240, DeviceType::CONTROLLER, F("Rego 3000"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{240, DeviceType::CONTROLLER, F("Rego 3000"), DeviceFlags::EMS_DEVICE_FLAG_IVT}, // 0x09
{241, DeviceType::CONTROLLER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
// Thermostat - not currently supporting write operations, like the Easy/100 types - 0x18

View File

@@ -206,6 +206,22 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
FL_(maintenanceDate),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_maintenancedate));
register_device_value(DeviceValueTAG::TAG_BOILER_DATA,
&emergencyOps_,
DeviceValueType::BOOL,
nullptr,
FL_(emergencyOps),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_emergency_ops));
register_device_value(DeviceValueTAG::TAG_BOILER_DATA,
&emergencyTemp_,
DeviceValueType::UINT,
nullptr,
FL_(emergencyTemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_emergency_temp),
40,
70);
/*
* Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat
@@ -425,6 +441,15 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
MAKE_CF_CB(set_ww_maxpower),
0,
130);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW,
&wwMaxTemp_,
DeviceValueType::UINT,
nullptr,
FL_(wwMaxTemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_ww_maxtemp),
0,
70);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW,
&wwCircPump_,
DeviceValueType::BOOL,
@@ -775,6 +800,9 @@ void Boiler::process_UBAParametersPlus(std::shared_ptr<const Telegram> telegram)
has_update(telegram, boilHystOff_, 8);
has_update(telegram, boilHystOn_, 9);
has_update(telegram, burnMinPeriod_, 10);
has_update(telegram, emergencyOps_, 18);
has_update(telegram, emergencyTemp_, 19);
// has_update(telegram, pumpType_, 11); // guess, RC300 manual: power controlled, pressure controlled 1-4?
// has_update(telegram, pumpDelay_, 12); // guess
// has_update(telegram, pumpModMax_, 13); // guess
@@ -795,6 +823,7 @@ void Boiler::process_UBAParameterWWPlus(std::shared_ptr<const Telegram> telegram
has_update(telegram, wwDisinfectionTemp_, 12); // setting here, status in E9
has_update(telegram, wwSelTempSingle_, 16);
has_update(telegram, wwSelTempLow_, 18);
has_update(telegram, wwMaxTemp_, 20);
has_update(telegram, wwChargeOptimization_, 25);
uint8_t wwComfort1 = EMS_VALUE_UINT_NOTSET;
@@ -1412,6 +1441,18 @@ bool Boiler::set_ww_maxpower(const char * value, const int8_t id) {
return true;
}
// set dhw maximum temperature
bool Boiler::set_ww_maxtemp(const char * value, const int8_t id) {
int v = 0;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(EMS_TYPE_UBAParameterWWPlus, 20, v, EMS_TYPE_UBAParameterWWPlus);
return true;
}
// set min pump modulation
bool Boiler::set_min_pump(const char * value, const int8_t id) {
int v = 0;
@@ -1832,4 +1873,24 @@ bool Boiler::set_pool_temp(const char * value, const int8_t id) {
return true;
}
bool Boiler::set_emergency_temp(const char * value, const int8_t id) {
int v = 0;
if (!Helpers::value2temperature(value, v)) {
return false;
}
write_command(EMS_TYPE_UBAParametersPlus, 19, v, EMS_TYPE_UBAParametersPlus);
return true;
}
bool Boiler::set_emergency_ops(const char * value, const int8_t id) {
bool v = false;
if (!Helpers::value2bool(value, v)) {
return false;
}
write_command(EMS_TYPE_UBAParametersPlus, 18, v ? 0x01 : 0x00, EMS_TYPE_UBAParametersPlus);
return true;
}
} // namespace emsesp

View File

@@ -81,6 +81,7 @@ class Boiler : public EMSdevice {
uint8_t wwSetPumpPower_; // ww pump speed/power?
uint8_t wwFlowTempOffset_; // Boiler offset for ww heating
uint8_t wwMaxPower_; // DHW maximum power
uint8_t wwMaxTemp_; // DHW maximum temperature
uint32_t wwStarts_; // DHW starts
uint32_t wwStarts2_; // DHW control starts
uint32_t wwWorkM_; // DHW minutes
@@ -133,6 +134,8 @@ class Boiler : public EMSdevice {
char lastCode_[50]; // last error code
char serviceCode_[4]; // 3 character status/service code
uint16_t serviceCodeNumber_; // error/service code
uint8_t emergencyOps_;
uint8_t emergencyTemp_;
// info
uint32_t upTimeControl_; // Operating time control
@@ -255,6 +258,7 @@ class Boiler : public EMSdevice {
bool set_ww_temp_single(const char * value, const int8_t id);
bool set_ww_disinfect_temp(const char * value, const int8_t id);
bool set_ww_maxpower(const char * value, const int8_t id);
bool set_ww_maxtemp(const char * value, const int8_t id);
bool set_ww_flowTempOffset(const char * value, const int8_t id);
bool set_ww_chargeOptimization(const char * value, const int8_t id);
bool set_flow_temp(const char * value, const int8_t id);
@@ -276,6 +280,8 @@ class Boiler : public EMSdevice {
bool set_ww_hyst_on(const char * value, const int8_t id);
bool set_ww_hyst_off(const char * value, const int8_t id);
bool set_pool_temp(const char * value, const int8_t id);
bool set_emergency_temp(const char * value, const int8_t id);
bool set_emergency_ops(const char * value, const int8_t id);
/*
bool set_hybridStrategy(const char * value, const int8_t id);
bool set_switchOverTemp(const char * value, const int8_t id);

View File

@@ -25,8 +25,10 @@ REGISTER_FACTORY(Controller, EMSdevice::DeviceType::CONTROLLER);
Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
// IVT broadcasts Thermostat time from controller (0x09) if display is off.
register_telegram_type(0x06, F("RCTime"), false, MAKE_PF_CB(process_dateTime));
register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE);
if ((flags & 0x0F) == EMS_DEVICE_FLAG_IVT) {
register_telegram_type(0x06, F("RCTime"), false, MAKE_PF_CB(process_dateTime));
register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE);
}
}
// process_dateTime - type 0x06 - date and time from a thermostat - 14 bytes long, IVT only
@@ -35,7 +37,7 @@ void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) {
return;
}
char newdatetime[sizeof(dateTime_)];
// publich as dd.mm.yyyy hh:mmF
// publish as dd.mm.yyyy hh:mm
snprintf(newdatetime,
sizeof(dateTime_),
"%02d.%02d.%04d %02d:%02d",
@@ -47,5 +49,4 @@ void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) {
has_update(dateTime_, newdatetime, sizeof(dateTime_));
}
} // namespace emsesp

View File

@@ -135,6 +135,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
} else if ((model == EMSdevice::EMS_DEVICE_FLAG_RC300) || (model == EMSdevice::EMS_DEVICE_FLAG_RC100)) {
monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC};
set_typeids = {0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, 0x02C0};
set2_typeids = {0x02CC, 0x02CE, 0x02D0, 0x02D2}; // max. 4 heating circuits supported ny RC310
summer_typeids = {0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6};
curve_typeids = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2};
summer2_typeids = {0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478};
@@ -145,6 +146,9 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(curve_typeids[i], F("RC300Curves"), false, MAKE_PF_CB(process_RC300Curve));
register_telegram_type(summer2_typeids[i], F("RC300Summer2"), false, MAKE_PF_CB(process_RC300Summer2));
}
for (uint8_t i = 0; i < set2_typeids.size(); i++) {
register_telegram_type(set2_typeids[i], F("RC300Set2"), false, MAKE_PF_CB(process_RC300Set2));
}
register_telegram_type(0x2F5, F("RC300WWmode"), true, MAKE_PF_CB(process_RC300WWmode));
register_telegram_type(0x31B, F("RC300WWtemp"), true, MAKE_PF_CB(process_RC300WWtemp));
register_telegram_type(0x31D, F("RC300WWmode2"), false, MAKE_PF_CB(process_RC300WWmode2));
@@ -253,6 +257,16 @@ std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(std::sha
}
}
// not found, search set2 types
if (hc_num == 0) {
for (uint8_t i = 0; i < set2_typeids.size(); i++) {
if (set2_typeids[i] == telegram->type_id) {
hc_num = i + 1;
break;
}
}
}
// not found, search summer message types
if (hc_num == 0) {
for (uint8_t i = 0; i < summer_typeids.size(); i++) {
@@ -365,6 +379,9 @@ std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(std::sha
if (set_typeids.size()) {
toggle_fetch(set_typeids[hc_num - 1], toggle_);
}
if (hc_num <= set2_typeids.size()) {
toggle_fetch(set2_typeids[hc_num - 1], toggle_);
}
if (summer_typeids.size()) {
toggle_fetch(summer_typeids[hc_num - 1], toggle_);
}
@@ -959,6 +976,10 @@ void Thermostat::process_RC300Set(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, hc->manualtemp, 10); // is * 2
has_enumupdate(telegram, hc->program, 11, 1); // timer program 1 or 2
has_enumupdate(telegram, hc->reducemode, 5, 1); // 1-outdoor temp threshold, 2-room temp threshold, 3-reduced mode
has_update(telegram, hc->reducetemp, 9);
has_update(telegram, hc->noreducetemp, 12);
}
// types 0x2AF ff
@@ -1004,8 +1025,10 @@ void Thermostat::process_RC300Curve(std::shared_ptr<const Telegram> telegram) {
return;
}
has_update(telegram, hc->controlmode, 0); // 1-outdoor, 2-simple, 3-MPC, 4-room, 5-power, 6-const
has_update(telegram, hc->heatingtype, 1); // 1=radiator, 2=convector, 3=floor
has_enumupdate(telegram, hc->controlmode, 0, 1); // 1-weather_compensated, 2-outside_footpoint,3-n/a, 4-room -- RC310
has_update(telegram, hc->heatingtype, 1); // 1=radiator, 2=convector, 3=floor
has_update(telegram, hc->switchonoptimization, 4);
has_enumupdate(telegram, hc->nofrostmode, 5, 1); // 1-room, 2-outdoor, 3- room & outdoor
has_update(telegram, hc->nofrosttemp, 6);
if (hc->heatingtype < 3) {
@@ -1059,10 +1082,24 @@ void Thermostat::process_RC300OutdoorTemp(std::shared_ptr<const Telegram> telegr
// 0x240 RC300 parameter
void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, ibaDamping_, 8);
has_enumupdate(telegram, ibaBuildingType_, 9, 1); // 1=light, 2=medium, 3=heavy
has_update(telegram, ibaMinExtTemperature_, 10);
}
// 0x2CC - e.g. wwprio for RC310 hcx parameter
void Thermostat::process_RC300Set2(std::shared_ptr<const Telegram> telegram) {
// typeids are not in a raw. hc:0x2CC, hc2: 0x2CE for RC310
// telegram is either offset 3 with data lenght of 1 and values 0/1 (radiators) - 10 0B FF 03 01 CC 01 F6
// or offset 0 with data lenght of 6 bytes - offset 3 values are 0x00 or 0xFF - 10 0B FF 00 01 CE FF 13 0A FF 1E 00 20
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram);
if (hc == nullptr) {
return;
}
has_update(telegram, hc->wwprio, 3);
}
// 0x267 RC300 floordrying
void Thermostat::process_RC300Floordry(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, floordrystatus_, 0);
@@ -1635,14 +1672,20 @@ bool Thermostat::set_heatingpid(const char * value, const int8_t id) {
return true;
}
// 0xA5 - Set the damping settings
// 0xA5 and 0x0240- Set the damping settings
bool Thermostat::set_damping(const char * value, const int8_t id) {
bool dmp;
if (Helpers::value2bool(value, dmp)) {
write_command(EMS_TYPE_IBASettings, 21, dmp ? 0xFF : 0, EMS_TYPE_IBASettings);
return true;
if (model() == EMS_DEVICE_FLAG_RC300) {
if (Helpers::value2bool(value, dmp)) {
write_command(0x240, 8, dmp ? 0xFF : 0, 0x240);
return true;
}
} else {
if (Helpers::value2bool(value, dmp)) {
write_command(EMS_TYPE_IBASettings, 21, dmp ? 0xFF : 0, EMS_TYPE_IBASettings);
return true;
}
}
return false;
}
@@ -1788,12 +1831,16 @@ bool Thermostat::set_wwprio(const char * value, const int8_t id) {
if (!Helpers::value2bool(value, b)) {
return false;
}
write_command(set_typeids[hc->hc()], 21, b ? 0xFF : 0x00, set_typeids[hc->hc()]);
if ((model() == EMS_DEVICE_FLAG_RC300)) {
write_command(set2_typeids[hc->hc()], 3, b ? 0xFF : 0x00, set2_typeids[hc->hc()]);
} else {
write_command(set_typeids[hc->hc()], 21, b ? 0xFF : 0x00, set_typeids[hc->hc()]);
}
return true;
}
// sets the thermostat ww circulation working mode, where mode is a string
bool Thermostat::set_wwcircmode(const char * value, const int8_t id) {
uint8_t set = 0xFF;
@@ -2382,7 +2429,25 @@ bool Thermostat::set_fastheatup(const char * value, const int8_t id) {
return true;
}
// sets the thermostat reducemode for RC35
// Set switchonoptimization RC310
bool Thermostat::set_switchonoptimization(const char * value, const int8_t 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;
}
bool b = false;
if (!Helpers::value2bool(value, b)) {
return false;
}
write_command(curve_typeids[hc->hc()], 4, b ? 0xFF : 0x00, curve_typeids[hc->hc()]);
return true;
}
// sets the thermostat reducemode for RC35 and RC310
bool Thermostat::set_reducemode(const char * value, const int8_t id) {
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
@@ -2391,14 +2456,20 @@ bool Thermostat::set_reducemode(const char * value, const int8_t id) {
}
uint8_t set = 0xFF;
if (!Helpers::value2enum(value, set, FL_(enum_reducemode))) {
return false;
if (model() == EMS_DEVICE_FLAG_RC300) {
if (Helpers::value2enum(value, set, FL_(enum_reducemode1))) {
write_command(set_typeids[hc->hc()], 5, set + 1, set_typeids[hc->hc()]);
}
} else {
if (Helpers::value2enum(value, set, FL_(enum_reducemode))) {
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_reducemode, set, set_typeids[hc->hc()]);
return true;
}
}
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_reducemode, set, set_typeids[hc->hc()]);
return true;
}
// sets the thermostat reducemode for RC35 vacations
bool Thermostat::set_vacreducemode(const char * value, const int8_t id) {
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
@@ -2416,20 +2487,25 @@ bool Thermostat::set_vacreducemode(const char * value, const int8_t id) {
return true;
}
// sets the thermostat nofrost mode for RC35
// sets the thermostat nofrost mode for RC35, RC300/RC310
bool Thermostat::set_nofrostmode(const char * value, const int8_t 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;
}
uint8_t set = 0xFF;
if (!Helpers::value2enum(value, set, FL_(enum_nofrostmode))) {
return false;
if (model() == EMS_DEVICE_FLAG_RC300) {
if (Helpers::value2enum(value, set, FL_(enum_nofrostmode1))) {
write_command(curve_typeids[hc->hc()], 5, set + 1, curve_typeids[hc->hc()]);
return true;
}
} else {
if (Helpers::value2enum(value, set, FL_(enum_nofrostmode))) {
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_nofrostmode, set, set_typeids[hc->hc()]);
return true;
}
}
write_command(set_typeids[hc->hc()], EMS_OFFSET_RC35Set_nofrostmode, set, set_typeids[hc->hc()]);
return true;
}
@@ -2467,11 +2543,16 @@ bool Thermostat::set_controlmode(const char * value, const int8_t id) {
}
uint8_t set = 0xFF;
if (model() == EMS_DEVICE_FLAG_RC300 || model() == EMS_DEVICE_FLAG_RC100) {
if (model() == EMS_DEVICE_FLAG_RC100) {
if (Helpers::value2enum(value, set, FL_(enum_controlmode))) {
write_command(curve_typeids[hc->hc()], 0, set, curve_typeids[hc->hc()]);
return true;
}
} else if (model() == EMS_DEVICE_FLAG_RC300) {
if (Helpers::value2enum(value, set, FL_(enum_controlmode1))) {
write_command(curve_typeids[hc->hc()], 0, set + 1, curve_typeids[hc->hc()]);
return true;
}
} else if (model() == EMS_DEVICE_FLAG_RC30) {
if (Helpers::value2enum(value, set, FL_(enum_controlmode2))) {
write_command(curve_typeids[hc->hc()], 1, set, curve_typeids[hc->hc()]);
@@ -2894,6 +2975,16 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
offset = 0;
factor = 1;
break;
case HeatingCircuit::Mode::NOREDUCE:
validate_typeid = set_typeid;
offset = 12;
factor = 1;
break;
case HeatingCircuit::Mode::REDUCE:
validate_typeid = set_typeid;
offset = 9;
factor = 1;
break;
default:
// HeatingCircuit::Mode::AUTO:
uint8_t mode_ = hc->get_mode();
@@ -3262,6 +3353,8 @@ void Thermostat::register_device_values() {
FL_(ibaMinExtTemperature),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_minexttemp));
register_device_value(
DeviceValueTAG::TAG_THERMOSTAT_DATA, &ibaDamping_, DeviceValueType::BOOL, nullptr, FL_(damping), DeviceValueUOM::NONE, MAKE_CF_CB(set_damping));
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA_WW, &wwSetTemp_, DeviceValueType::UINT, nullptr, FL_(wwSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwtemp));
register_device_value(
@@ -3829,6 +3922,8 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
register_device_value(
tag, &hc->roominfl_factor, DeviceValueType::UINT, FL_(div10), FL_(roominfl_factor), DeviceValueUOM::NONE, MAKE_CF_CB(set_roominfl_factor));
register_device_value(tag, &hc->curroominfl, DeviceValueType::SHORT, FL_(div10), FL_(curroominfl), DeviceValueUOM::DEGREES_R);
register_device_value(
tag, &hc->nofrostmode, DeviceValueType::ENUM, FL_(enum_nofrostmode1), FL_(nofrostmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_nofrostmode));
register_device_value(tag, &hc->nofrosttemp, DeviceValueType::INT, nullptr, FL_(nofrosttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nofrosttemp));
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, nullptr, FL_(targetflowtemp), DeviceValueUOM::DEGREES);
register_device_value(
@@ -3844,11 +3939,22 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
MAKE_CF_CB(set_summermode));
register_device_value(tag, &hc->summermode, DeviceValueType::ENUM, FL_(enum_summer), FL_(summermode), DeviceValueUOM::NONE);
register_device_value(
tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode));
tag, &hc->controlmode, DeviceValueType::ENUM, FL_(enum_controlmode1), FL_(controlmode), DeviceValueUOM::NONE, MAKE_CF_CB(set_controlmode));
register_device_value(tag, &hc->program, DeviceValueType::ENUM, FL_(enum_progMode), FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program));
register_device_value(
tag, &hc->tempautotemp, DeviceValueType::INT, FL_(div2), FL_(tempautotemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_tempautotemp), -1, 30);
register_device_value(tag, &hc->fastHeatup, DeviceValueType::UINT, nullptr, FL_(fastheatup), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_fastheatup));
register_device_value(tag,
&hc->switchonoptimization,
DeviceValueType::BOOL,
nullptr,
FL_(switchonoptimization),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_switchonoptimization));
register_device_value(tag, &hc->reducemode, DeviceValueType::ENUM, FL_(enum_reducemode1), FL_(reducemode), DeviceValueUOM::NONE, MAKE_CF_CB(set_reducemode));
register_device_value(tag, &hc->noreducetemp, DeviceValueType::INT, nullptr, FL_(noreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_noreducetemp));
register_device_value(tag, &hc->reducetemp, DeviceValueType::INT, nullptr, FL_(reducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_reducetemp));
register_device_value(tag, &hc->wwprio, DeviceValueType::BOOL, nullptr, FL_(wwprio), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwprio));
break;
case EMS_DEVICE_FLAG_CRF:
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode5), FL_(mode), DeviceValueUOM::NONE);

View File

@@ -80,6 +80,7 @@ class Thermostat : public EMSdevice {
char switchtime1[16];
char switchtime2[16];
uint8_t climate;
uint8_t switchonoptimization;
// RC 10
uint8_t reducehours; // night reduce duration
@@ -160,6 +161,7 @@ class Thermostat : public EMSdevice {
// each thermostat has a list of heating controller type IDs for reading and writing
std::vector<uint16_t> monitor_typeids;
std::vector<uint16_t> set_typeids;
std::vector<uint16_t> set2_typeids;
std::vector<uint16_t> timer_typeids;
std::vector<uint16_t> timer2_typeids;
std::vector<uint16_t> summer_typeids;
@@ -357,6 +359,7 @@ class Thermostat : public EMSdevice {
void process_CRFMonitor(std::shared_ptr<const Telegram> telegram);
void process_RC300Monitor(std::shared_ptr<const Telegram> telegram);
void process_RC300Set(std::shared_ptr<const Telegram> telegram);
void process_RC300Set2(std::shared_ptr<const Telegram> telegram);
void process_RC300Summer(std::shared_ptr<const Telegram> telegram);
void process_RC300Summer2(std::shared_ptr<const Telegram> telegram);
void process_RC300WWmode(std::shared_ptr<const Telegram> telegram);
@@ -412,7 +415,6 @@ class Thermostat : public EMSdevice {
bool set_vacreducetemp(const char * value, const int8_t id);
bool set_vacreducemode(const char * value, const int8_t id);
bool set_nofrostmode(const char * value, const int8_t id);
bool set_remotetemp(const char * value, const int8_t id);
bool set_roominfluence(const char * value, const int8_t id);
bool set_roominfl_factor(const char * value, const int8_t id);
@@ -426,6 +428,7 @@ class Thermostat : public EMSdevice {
bool set_controlmode(const char * value, const int8_t id);
bool set_wwprio(const char * value, const int8_t id);
bool set_fastheatup(const char * value, const int8_t id);
bool set_switchonoptimization(const char * value, const int8_t id);
// set functions - these don't use the id/hc, the parameters are ignored
bool set_wwmode(const char * value, const int8_t id);

View File

@@ -716,11 +716,9 @@ void EMSdevice::generate_values_web(JsonObject & output) {
auto mask = Helpers::hextoa((uint8_t)(dv.state >> 4), false); // create mask to a 2-char string
// add name, prefixing the tag if it exists. This is the id used for the table sorting
// add name, prefixing the tag if it exists. This is the id used in the WebUI table and must be unique
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
obj["id"] = mask + read_flash_string(dv.full_name);
} else if (dv.tag < DeviceValueTAG::TAG_HC1) {
obj["id"] = mask + tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name);
} else {
obj["id"] = mask + tag_to_string(dv.tag) + " " + read_flash_string(dv.full_name);
}
@@ -775,7 +773,7 @@ void EMSdevice::generate_values_web(JsonObject & output) {
// as generate_values_web() but stripped down to only show all entities and their state
// this is used only for WebCustomizationService::device_entities()
void EMSdevice::generate_values_web_all(JsonArray & output) {
void EMSdevice::generate_values_web_customization(JsonArray & output) {
for (const auto & dv : devicevalues_) {
// also show commands and entities that have an empty full name
JsonObject obj = output.createNestedObject();
@@ -831,29 +829,29 @@ void EMSdevice::generate_values_web_all(JsonArray & output) {
obj["v"] = (divider > 0) ? time_value / divider : time_value * factor; // sometimes we need to divide by 60
}
}
} else {
// must always have v for sorting to work in web
obj["v"] = "";
}
// add name, prefixing the tag if it exists as the id (key for table sorting)
if (dv.full_name) {
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
obj["id"] = dv.full_name;
} else {
char name[50];
snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag).c_str(), read_flash_string(dv.full_name).c_str());
obj["id"] = name;
// id holds the shortname and must always have a value for the WebUI table to work
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
obj["id"] = tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
} else {
obj["id"] = read_flash_string(dv.short_name);
}
// n is the fullname, and can be optional
// don't add the fullname if its a command
if (dv.type != DeviceValueType::CMD) {
if (dv.full_name) {
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
obj["n"] = dv.full_name;
} else {
char name[50];
snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag).c_str(), read_flash_string(dv.full_name).c_str());
obj["n"] = name;
}
}
} else {
obj["id"] = "";
}
// shortname
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
obj["s"] = tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
} else {
obj["s"] = dv.short_name;
obj["n"] = "";
}
obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble

View File

@@ -200,7 +200,7 @@ class EMSdevice {
enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT, CONSOLE };
bool generate_values(JsonObject & output, const uint8_t tag_filter, const bool nested, const uint8_t output_target);
void generate_values_web(JsonObject & output);
void generate_values_web_all(JsonArray & output);
void generate_values_web_customization(JsonArray & output);
void register_device_value(uint8_t tag,
void * value_p,
@@ -315,6 +315,9 @@ class EMSdevice {
// device flags: The lower 4 bits hold the unique identifier, the upper 4 bits are used for specific flags
static constexpr uint8_t EMS_DEVICE_FLAG_NONE = 0;
// Controller
static constexpr uint8_t EMS_DEVICE_FLAG_IVT = 1;
// Boiler
static constexpr uint8_t EMS_DEVICE_FLAG_EMS = 1;
static constexpr uint8_t EMS_DEVICE_FLAG_EMSPLUS = 2;

View File

@@ -183,9 +183,11 @@ uint8_t EMSESP::check_master_device(const uint8_t device_id, const uint16_t type
uint16_t curve_ids[] = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2};
uint16_t summer2_ids[] = {0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478};
uint16_t master_ids[] = {0x02F5, 0x031B, 0x031D, 0x031E, 0x023A, 0x0267, 0x0240};
uint16_t set2_ids[] = {0x02CC, 0x02CE, 0x02D0, 0x02D2};
// look for heating circuits
for (uint8_t i = 0; i < sizeof(mon_ids) / 2; i++) {
if (type_id == mon_ids[i] || type_id == set_ids[i] || type_id == summer_ids[i] || type_id == curve_ids[i] || type_id == summer2_ids[i]) {
if (type_id == mon_ids[i] || type_id == set_ids[i] || type_id == summer_ids[i] || type_id == curve_ids[i] || type_id == summer2_ids[i]
|| (i < 4 && type_id == set2_ids[i])) {
if (read) {
// receiving telegrams and map all to master thermostat at 0x18 (src manipulated)
return 0x18;

View File

@@ -313,6 +313,7 @@ MAKE_PSTR_WORD(winter)
MAKE_PSTR_WORD(outdoor)
MAKE_PSTR_WORD(mpc)
MAKE_PSTR_WORD(room)
MAKE_PSTR_WORD(room_outdoor)
MAKE_PSTR_WORD(power)
MAKE_PSTR_WORD(constant)
MAKE_PSTR_WORD(simple)
@@ -383,9 +384,12 @@ MAKE_PSTR_LIST(enum_modetype4, F_(nofrost), F_(eco), F_(heat))
MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on))
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
MAKE_PSTR_LIST(enum_reducemode1, F_(outdoor), F_(room), F_(reduce)) // RC310 values: 1-3
MAKE_PSTR_LIST(enum_nofrostmode, F_(off), F_(room), F_(outdoor))
MAKE_PSTR_LIST(enum_nofrostmode1, F_(room), F_(outdoor), F_(room_outdoor))
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant))
MAKE_PSTR_LIST(enum_controlmode1, F("weather-compensated"), F("outside-basepoint"), F("n/a"), F_(room)) // RC310 1-4
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
// MAKE_PSTR_LIST(enum_controlmode3, F_(off), F_(room), F_(outdoor), F("room+outdoor"))
MAKE_PSTR_LIST(enum_control, F_(off), F_(rc20), F_(rc3x))
@@ -465,6 +469,8 @@ MAKE_PSTR_LIST(maintenanceMessage, F("maintenancemessage"), F("maintenance messa
MAKE_PSTR_LIST(maintenanceDate, F("maintenancedate"), F("next maintenance date"))
MAKE_PSTR_LIST(maintenanceType, F_(maintenance), F("maintenance scheduled"))
MAKE_PSTR_LIST(maintenanceTime, F("maintenancetime"), F("time to next maintenance"))
MAKE_PSTR_LIST(emergencyOps, F("emergencyops"), F("emergency operation"))
MAKE_PSTR_LIST(emergencyTemp, F("emergencytemp"), F("emergency temperature"))
// heatpump/compress specific
MAKE_PSTR_LIST(upTimeControl, F("uptimecontrol"), F("total operating time heat"))
@@ -614,7 +620,7 @@ MAKE_PSTR_LIST(wwDailyHeating, F("wwdailyheating"), F("daily heating"))
MAKE_PSTR_LIST(wwDailyHeatTime, F("wwdailyheattime"), F("daily heating time"))
MAKE_PSTR_LIST(wwWhenModeOff, F("wwwhenmodeoff"), F("when thermostat mode off"))
// thermostat hc
MAKE_PSTR_LIST(climate, F("climate"))
MAKE_PSTR_LIST(climate, F("HA climate config creation")) // no full-name, hidden, only for creation
MAKE_PSTR_LIST(selRoomTemp, F("seltemp"), F("selected room temperature"))
MAKE_PSTR_LIST(roomTemp, F("currtemp"), F("current room temperature"))
MAKE_PSTR_LIST(mode, F("mode"), F("mode"))
@@ -662,9 +668,11 @@ MAKE_PSTR_LIST(reducetemp, F("reducetemp"), F("off/reduce switch temperature"))
MAKE_PSTR_LIST(vacreducetemp, F("vacreducetemp"), F("vacations off/reduce switch temperature"))
MAKE_PSTR_LIST(vacreducemode, F("vacreducemode"), F("vacations reduce mode"))
MAKE_PSTR_LIST(nofrostmode, F("nofrostmode"), F("nofrost mode"))
MAKE_PSTR_LIST(nofrostmode1, F("nofrostmode1"), F("nofrost mode")) // RC310
MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("room temperature from remote"))
MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp"))
MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode"))
MAKE_PSTR_LIST(switchonoptimization, F("switchonoptimization"), F("switch-on optimization"))
// heatpump
MAKE_PSTR_LIST(airHumidity, F("airhumidity"), F("relative air humidity"))

View File

@@ -418,7 +418,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
// emsdevice->generate_values_web(root);
JsonArray output = doc.to<JsonArray>();
emsdevice->generate_values_web_all(output);
emsdevice->generate_values_web_customization(output);
Serial.print(COLOR_BRIGHT_MAGENTA);
serializeJson(doc, Serial);

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.4.0b18idf4"
#define EMSESP_APP_VERSION "3.4.2b1"

View File

@@ -132,6 +132,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) {
JsonVariant data = output["api_data"];
request->send(200, "text/plain; charset=utf-8", data.as<String>());
api_count_++;
delete response;
return;
}

View File

@@ -196,7 +196,7 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J
if (emsdevice->unique_id() == json["id"]) {
#ifndef EMSESP_STANDALONE
JsonArray output = response->getRoot();
emsdevice->generate_values_web_all(output);
emsdevice->generate_values_web_customization(output);
#endif
response->setLength();
request->send(response);