Merge remote-tracking branch 'origin/v3.4' into dev

This commit is contained in:
proddy
2022-01-23 17:56:52 +01:00
parent 02e2b51814
commit 77e1898512
538 changed files with 32282 additions and 38655 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -25,9 +25,7 @@ namespace emsesp {
class Boiler : public EMSdevice {
public:
Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand);
virtual bool publish_ha_device_config();
Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand);
private:
static uuid::log::Logger logger_;
@@ -52,50 +50,46 @@ class Boiler : public EMSdevice {
static constexpr uint16_t EMS_TYPE_UBAInformation = 0x495;
static constexpr uint16_t EMS_TYPE_UBAEnergySupplied = 0x494;
static constexpr uint8_t EMS_BOILER_SELFLOWTEMP_HEATING = 20; // was originally 70, changed to 30 for issue #193, then to 20 with issue #344
// ww
uint8_t wwSetTemp_; // Warm Water set temperature
uint8_t wwSelTemp_; // Warm Water selected temperature
uint8_t wwSelTempLow_; // Warm Water lower selected temperature
uint8_t wwSelTempOff_; // Warm Water selected temperature for off position
uint8_t wwSelTempSingle_; // Warm Water single charge temperature
uint8_t wwSetTemp_; // DHW set temperature
uint8_t wwSelTemp_; // DHW selected temperature
uint8_t wwSelTempLow_; // DHW lower selected temperature
uint8_t wwSelTempOff_; // DHW selected temperature for off position
uint8_t wwSelTempSingle_; // DHW single charge temperature
uint8_t wwType_; // 0-off, 1-flow, 2-flowbuffer, 3-buffer, 4-layered buffer
uint8_t wwComfort_; // WW comfort mode
uint8_t wwCircPump_; // Warm Water circulation pump available
uint8_t wwChargeType_; // Warm Water charge type (pump or 3-way-valve)
uint8_t wwDisinfectionTemp_; // Warm Water disinfection temperature to prevent infection
uint8_t wwCircMode_; // Warm Water circulation pump mode
uint8_t wwCircPump_; // DHW circulation pump available
uint8_t wwChargeType_; // DHW charge type (pump or 3-way-valve)
uint8_t wwDisinfectionTemp_; // DHW disinfection temperature to prevent infection
uint8_t wwCircMode_; // DHW circulation pump mode
uint8_t wwCirc_; // Circulation on/off
uint16_t wwCurTemp_; // Warm Water current temperature
uint16_t wwCurTemp2_; // Warm Water current temperature storage
uint8_t wwCurFlow_; // Warm Water current flow temp in l/min
uint16_t wwStorageTemp1_; // warm water storage temp 1
uint16_t wwStorageTemp2_; // warm water storage temp 2
uint8_t wwActivated_; // Warm Water activated
uint8_t wwOneTime_; // Warm Water one time function on/off
uint8_t wwDisinfect_; // Warm Water disinfection on/off
uint8_t wwCharging_; // Warm Water charging on/off
uint8_t wwRecharging_; // Warm Water recharge on/off
uint8_t wwTempOK_; // Warm Water temperature ok on/off
uint16_t wwCurTemp_; // DHW current temperature
uint16_t wwCurTemp2_; // DHW current temperature storage
uint8_t wwCurFlow_; // DHW current flow temp in l/min
uint16_t wwStorageTemp1_; // DHW storage temp 1
uint16_t wwStorageTemp2_; // DHW storage temp 2
uint8_t wwActivated_; // DHW activated
uint8_t wwOneTime_; // DHW one time function on/off
uint8_t wwDisinfect_; // DHW disinfection on/off
uint8_t wwCharging_; // DHW charging on/off
uint8_t wwRecharging_; // DHW recharge on/off
uint8_t wwTempOK_; // DHW temperature ok on/off
uint8_t wwActive_; //
uint8_t wwHeat_; // 3-way valve on WW
uint8_t ww3wayValve_; // 3-way valve on WW
uint8_t wwSetPumpPower_; // ww pump speed/power?
uint8_t wwFlowTempOffset_; // Boiler offset for ww heating
uint8_t wwMaxPower_; // Warm Water maximum power
uint32_t wwStarts_; // Warm Water starts
uint32_t wwStarts2_; // Warm water control starts
uint32_t wwWorkM_; // Warm Water minutes
uint8_t wwMaxPower_; // DHW maximum power
uint32_t wwStarts_; // DHW starts
uint32_t wwStarts2_; // DHW control starts
uint32_t wwWorkM_; // DHW minutes
int8_t wwHystOn_;
int8_t wwHystOff_;
uint8_t wwTapActivated_; // maintenance-mode to switch DHW off
uint16_t wwMixerTemp_; // mixing temperature
uint16_t wwTankMiddleTemp_; // Tank middle temperature (TS3)
uint8_t wwTapActivated_; // maintenance-mode to switch DHW off
uint16_t wwMixerTemp_; // mixing temperature
uint16_t wwCylMiddleTemp_; // Cyl middle temperature (TS3)
// main
uint8_t id_; // product id
uint8_t dummy8u_; // for commands with no output
uint8_t dummybool_; // for commands with no output
uint8_t reset_; // for reset command
uint8_t heatingActive_; // Central heating is on/off
uint8_t tapwaterActive_; // Hot tap water is on/off
uint8_t selFlowTemp_; // Selected flow temperature
@@ -110,10 +104,12 @@ class Boiler : public EMSdevice {
uint16_t boilTemp_; // Boiler temperature
uint16_t exhaustTemp_; // Exhaust temperature
uint8_t burnGas_; // Gas on/off
uint8_t burnGas2_; // Gas stage 2 on/off
uint16_t flameCurr_; // Flame current in micro amps
uint8_t heatingPump_; // Boiler heating pump on/off
uint8_t fanWork_; // Fan on/off
uint8_t ignWork_; // Ignition on/off
uint8_t oilPreHeat_; // oil preheating on
uint8_t heatingActivated_; // Heating activated on the boiler
uint8_t heatingTemp_; // Heating temperature setting on the boiler
uint8_t pumpModMax_; // Boiler circuit pump modulation max. power %
@@ -131,7 +127,7 @@ class Boiler : public EMSdevice {
uint32_t burnWorkMin_; // Total burner operating time
uint32_t heatWorkMin_; // Total heat operating time
uint32_t UBAuptime_; // Total UBA working hours
char lastCode_[60]; // last error code
char lastCode_[75]; // last error code
char serviceCode_[4]; // 3 character status/service code
uint16_t serviceCodeNumber_; // error/service code
@@ -139,21 +135,21 @@ class Boiler : public EMSdevice {
uint32_t upTimeControl_; // Operating time control
uint32_t upTimeCompHeating_; // Operating time compressor heating
uint32_t upTimeCompCooling_; // Operating time compressor cooling
uint32_t upTimeCompWw_; // Operating time compressor warm water
uint32_t upTimeCompWw_; // Operating time compressor DHW
uint32_t upTimeCompPool_; // Operating time compressor pool
uint32_t totalCompStarts_; // Total Commpressor control starts
uint32_t heatingStarts_; // Heating control starts
uint32_t coolingStarts_; // Cooling control starts
uint32_t poolStarts_; // Warm water control starts
uint32_t poolStarts_; // DHW control starts
uint32_t nrgConsTotal_; // Energy consumption total
uint32_t nrgConsCompTotal_; // Energy consumption compressor total
uint32_t nrgConsCompHeating_; // Energy consumption compressor heating
uint32_t nrgConsCompWw_; // Energy consumption compressor warm water
uint32_t nrgConsCompWw_; // Energy consumption compressor DHW
uint32_t nrgConsCompCooling_; // Energy consumption compressor cooling
uint32_t nrgConsCompPool_; // Energy consumption compressor pool
uint32_t nrgSuppTotal_; // Energy supplied total
uint32_t nrgSuppHeating_; // Energy supplied heating
uint32_t nrgSuppWw_; // Energy supplied warm water
uint32_t nrgSuppWw_; // Energy supplied DHW
uint32_t nrgSuppCooling_; // Energy supplied cooling
uint32_t nrgSuppPool_; // Energy supplied pool
uint32_t auxElecHeatNrgConsTotal_; // Auxiliary electrical heater energy consumption total

View File

@@ -22,15 +22,8 @@ namespace emsesp {
REGISTER_FACTORY(Connect, EMSdevice::DeviceType::CONNECT);
uuid::log::Logger Connect::logger_{F_(connect), uuid::log::Facility::CONSOLE};
Connect::Connect(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)
Connect::Connect(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) {
}
// publish HA config
bool Connect::publish_ha_device_config() {
return true;
}
} // namespace emsesp

View File

@@ -25,12 +25,7 @@ namespace emsesp {
class Connect : public EMSdevice {
public:
Connect(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);
virtual bool publish_ha_device_config();
private:
static uuid::log::Logger logger_;
Connect(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);
};
} // namespace emsesp

View File

@@ -22,15 +22,8 @@ namespace emsesp {
REGISTER_FACTORY(Controller, EMSdevice::DeviceType::CONTROLLER);
uuid::log::Logger Controller::logger_{F_(controller), uuid::log::Facility::CONSOLE};
Controller::Controller(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)
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) {
}
// publish HA config
bool Controller::publish_ha_device_config() {
return true;
}
} // namespace emsesp

View File

@@ -25,12 +25,7 @@ namespace emsesp {
class Controller : public EMSdevice {
public:
Controller(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);
virtual bool publish_ha_device_config();
private:
static uuid::log::Logger logger_;
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);
};
} // namespace emsesp

View File

@@ -22,15 +22,8 @@ namespace emsesp {
REGISTER_FACTORY(Gateway, EMSdevice::DeviceType::GATEWAY);
uuid::log::Logger Gateway::logger_{F_(gateway), uuid::log::Facility::CONSOLE};
Gateway::Gateway(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)
Gateway::Gateway(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) {
}
// publish HA config
bool Gateway::publish_ha_device_config() {
return true;
}
} // namespace emsesp

View File

@@ -25,12 +25,7 @@ namespace emsesp {
class Gateway : public EMSdevice {
public:
Gateway(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);
virtual bool publish_ha_device_config();
private:
static uuid::log::Logger logger_;
Gateway(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);
};
} // namespace emsesp

View File

@@ -24,23 +24,18 @@ REGISTER_FACTORY(Generic, EMSdevice::DeviceType::GENERIC);
uuid::log::Logger Generic::logger_{F_(generic), uuid::log::Facility::CONSOLE};
Generic::Generic(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)
Generic::Generic(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) {
// RF-Sensor 0x40 sending temperature in telegram 0x435, see https://github.com/emsesp/EMS-ESP32/issues/103
if (device_id == 0x40) {
register_telegram_type(0x435, F("RFSensorMessage"), false, MAKE_PF_CB(process_RFSensorMessage));
register_device_value(TAG_NONE, &rfTemp_, DeviceValueType::SHORT, FL_(div10), FL_(RFTemp), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE, &rfTemp_, DeviceValueType::SHORT, FL_(div10), FL_(RFTemp), DeviceValueUOM::DEGREES);
}
}
// publish HA config
bool Generic::publish_ha_device_config() {
return true;
}
// type 0x435 rf remote sensor
void Generic::process_RFSensorMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(rfTemp_, 0)); // is * 10
has_update(telegram, rfTemp_, 0); // is * 10
}
} // namespace emsesp
} // namespace emsesp

View File

@@ -25,9 +25,7 @@ namespace emsesp {
class Generic : public EMSdevice {
public:
Generic(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);
virtual bool publish_ha_device_config();
Generic(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);
private:
static uuid::log::Logger logger_;

View File

@@ -22,50 +22,15 @@ namespace emsesp {
REGISTER_FACTORY(Heatpump, EMSdevice::DeviceType::HEATPUMP);
uuid::log::Logger Heatpump::logger_{F_(heatpump), uuid::log::Facility::CONSOLE};
Heatpump::Heatpump(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)
Heatpump::Heatpump(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) {
// telegram handlers
register_telegram_type(0x042B, F("HP1"), true, MAKE_PF_CB(process_HPMonitor1));
register_telegram_type(0x047B, F("HP2"), true, MAKE_PF_CB(process_HPMonitor2));
// device values
register_device_value(TAG_NONE, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
register_device_value(TAG_NONE, &airHumidity_, DeviceValueType::UINT, FL_(div2), FL_(airHumidity), DeviceValueUOM::PERCENT);
register_device_value(TAG_NONE, &dewTemperature_, DeviceValueType::UINT, nullptr, FL_(dewTemperature), DeviceValueUOM::DEGREES);
id_ = product_id;
}
// publish HA config
bool Heatpump::publish_ha_device_config() {
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
doc["uniq_id"] = F_(heatpump);
doc["ic"] = F_(icondevice);
char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf(stat_t, sizeof(stat_t), "%s/%s", Mqtt::base().c_str(), Mqtt::tag_to_topic(device_type(), DeviceValueTAG::TAG_NONE).c_str());
doc["stat_t"] = stat_t;
char name_s[40];
snprintf(name_s, sizeof(name_s), FSTR_(productid_fmt), device_type_name().c_str());
doc["name"] = name_s;
doc["val_tpl"] = FJSON("{{value_json.id}}");
JsonObject dev = doc.createNestedObject("dev");
dev["name"] = FJSON("EMS-ESP Heat Pump");
dev["sw"] = EMSESP_APP_VERSION;
dev["mf"] = brand_to_string();
dev["mdl"] = this->name();
JsonArray ids = dev.createNestedArray("ids");
ids.add("ems-esp-heatpump");
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf(topic, sizeof(topic), "sensor/%s/heatpump/config", Mqtt::base().c_str());
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
return true;
register_device_value(DeviceValueTAG::TAG_NONE, &airHumidity_, DeviceValueType::UINT, FL_(div2), FL_(airHumidity), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_NONE, &dewTemperature_, DeviceValueType::UINT, nullptr, FL_(dewTemperature), DeviceValueUOM::DEGREES);
}
/*
@@ -73,8 +38,8 @@ bool Heatpump::publish_ha_device_config() {
* e.g. "38 10 FF 00 03 7B 08 24 00 4B"
*/
void Heatpump::process_HPMonitor2(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(dewTemperature_, 0));
has_update(telegram->read_value(airHumidity_, 1));
has_update(telegram, dewTemperature_, 0);
has_update(telegram, airHumidity_, 1);
}
#pragma GCC diagnostic push
@@ -90,4 +55,4 @@ void Heatpump::process_HPMonitor1(std::shared_ptr<const Telegram> telegram) {
#pragma GCC diagnostic pop
} // namespace emsesp
} // namespace emsesp

View File

@@ -25,16 +25,11 @@ namespace emsesp {
class Heatpump : public EMSdevice {
public:
Heatpump(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);
virtual bool publish_ha_device_config();
Heatpump(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);
private:
static uuid::log::Logger logger_;
uint8_t airHumidity_;
uint8_t dewTemperature_;
uint8_t id_;
void process_HPMonitor1(std::shared_ptr<const Telegram> telegram);
void process_HPMonitor2(std::shared_ptr<const Telegram> telegram);

View File

@@ -24,41 +24,59 @@ REGISTER_FACTORY(Mixer, EMSdevice::DeviceType::MIXER);
uuid::log::Logger Mixer::logger_{F_(mixer), uuid::log::Facility::CONSOLE};
Mixer::Mixer(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)
Mixer::Mixer(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) {
// Pool module
if (flags == EMSdevice::EMS_DEVICE_FLAG_MP) {
register_telegram_type(0x5BA, F("HpPoolStatus"), true, MAKE_PF_CB(process_HpPoolStatus));
type_ = Type::MP;
register_device_value(TAG_NONE, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
register_device_value(TAG_NONE, &poolTemp_, DeviceValueType::SHORT, FL_(div10), FL_(poolTemp), DeviceValueUOM::DEGREES);
register_device_value(TAG_NONE, &poolShuntStatus_, DeviceValueType::ENUM, FL_(enum_shunt), FL_(poolShuntStatus), DeviceValueUOM::NONE);
register_device_value(TAG_NONE, &poolShunt_, DeviceValueType::UINT, nullptr, FL_(poolShunt), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_NONE, &poolTemp_, DeviceValueType::SHORT, FL_(div10), FL_(poolTemp), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE, &poolShuntStatus_, DeviceValueType::ENUM, FL_(enum_shunt), FL_(poolShuntStatus), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &poolShunt_, DeviceValueType::UINT, nullptr, FL_(poolShunt), DeviceValueUOM::PERCENT);
}
// EMS+
if (flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) {
if (device_id >= 0x20 && device_id <= 0x27) {
register_telegram_type(device_id - 0x20 + 0x02D7, F("MMPLUSStatusMessage_HC"), true, MAKE_PF_CB(process_MMPLUSStatusMessage_HC));
register_telegram_type(device_id - 0x20 + 0x02D7, F("MMPLUSStatusMessage_HC"), false, MAKE_PF_CB(process_MMPLUSStatusMessage_HC));
// register_telegram_type(device_id - 0x20 + 0x02E1, F("MMPLUSStetMessage_HC"), true, MAKE_PF_CB(process_MMPLUSSetMessage_HC));
type_ = Type::HC;
hc_ = device_id - 0x20 + 1;
uint8_t tag = TAG_HC1 + hc_ - 1;
register_device_value(tag, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1;
register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
register_device_value(tag, &status_, DeviceValueType::INT, nullptr, FL_(mixerStatus), DeviceValueUOM::PERCENT);
register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, nullptr, FL_(flowSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowSetTemp));
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump));
} else if (device_id >= 0x28 && device_id <= 0x29) {
register_telegram_type(device_id - 0x28 + 0x0331, F("MMPLUSStatusMessage_WWC"), true, MAKE_PF_CB(process_MMPLUSStatusMessage_WWC));
register_telegram_type(device_id - 0x28 + 0x0331, F("MMPLUSStatusMessage_WWC"), false, MAKE_PF_CB(process_MMPLUSStatusMessage_WWC));
register_telegram_type(device_id - 0x28 + 0x0313, F("MMPLUSConfigMessage_WWC"), true, MAKE_PF_CB(process_MMPLUSConfigMessage_WWC));
// register_telegram_type(device_id - 0x28 + 0x033B, F("MMPLUSSetMessage_WWC"), true, MAKE_PF_CB(process_MMPLUSSetMessage_WWC));
type_ = Type::WWC;
hc_ = device_id - 0x28 + 1;
uint8_t tag = TAG_WWC1 + hc_ - 1;
register_device_value(tag, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
uint8_t tag = DeviceValueTAG::TAG_WWC1 + hc_ - 1;
register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(wwTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(wwPumpStatus), DeviceValueUOM::NONE);
register_device_value(tag, &status_, DeviceValueType::INT, nullptr, FL_(wwTempStatus), DeviceValueUOM::NONE);
register_device_value(tag, &wwMaxTemp_, DeviceValueType::UINT, nullptr, FL_(wwMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwMaxTemp));
register_device_value(tag, &wwDiffTemp_, DeviceValueType::INT, nullptr, FL_(wwDiffTemp), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_wwDiffTemp));
register_device_value(tag,
&wwDisinfectionTemp_,
DeviceValueType::UINT,
nullptr,
FL_(wwDisinfectionTemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_wwDisinfectionTemp));
register_device_value(tag, &wwReducedTemp_, DeviceValueType::UINT, nullptr, FL_(wwRedTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwReducedTemp));
register_device_value(tag, &wwRequiredTemp_, DeviceValueType::UINT, nullptr, FL_(wwRequiredTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_wwRequiredTemp));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW,
&wwCircPump_,
DeviceValueType::BOOL,
nullptr,
FL_(wwCircPump),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_wwCircPump));
register_device_value(tag, &wwCircMode_, DeviceValueType::ENUM, FL_(enum_wwCircMode), FL_(wwCircMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_wwCircMode));
}
}
@@ -67,17 +85,16 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
register_telegram_type(0x00AA, F("MMConfigMessage"), true, MAKE_PF_CB(process_MMConfigMessage));
register_telegram_type(0x00AB, F("MMStatusMessage"), false, MAKE_PF_CB(process_MMStatusMessage));
register_telegram_type(0x00AC, F("MMSetMessage"), false, MAKE_PF_CB(process_MMSetMessage));
// EMSESP::send_read_request(0xAA, device_id);
type_ = Type::HC;
hc_ = device_id - 0x20 + 1;
uint8_t tag = TAG_HC1 + hc_ - 1;
register_device_value(tag, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1;
register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
register_device_value(tag, &status_, DeviceValueType::INT, nullptr, FL_(mixerStatus), DeviceValueUOM::PERCENT);
register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, nullptr, FL_(flowSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowSetTemp));
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump));
register_device_value(tag, &activated_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::NONE, MAKE_CF_CB(set_activated));
register_device_value(tag, &setValveTime_, DeviceValueType::UINT, FL_(mul10), FL_(mixerSetTime), DeviceValueUOM::SECONDS, MAKE_CF_CB(set_setValveTime), 1, 12);
register_device_value(
tag, &setValveTime_, DeviceValueType::UINT, FL_(mul10), FL_(mixerSetTime), DeviceValueUOM::SECONDS, MAKE_CF_CB(set_setValveTime), 10, 120);
}
// HT3
@@ -87,99 +104,32 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
// register_telegram_type(0x0123, F("IPMSetMessage"), false, MAKE_PF_CB(process_IPMSetMessage));
type_ = Type::HC;
hc_ = device_id - 0x20 + 1;
uint8_t tag = TAG_HC1 + hc_ - 1;
register_device_value(tag, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1;
register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
register_device_value(tag, &status_, DeviceValueType::INT, nullptr, FL_(mixerStatus), DeviceValueUOM::PERCENT);
register_device_value(tag, &flowSetTemp_, DeviceValueType::UINT, nullptr, FL_(flowSetTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flowSetTemp));
register_device_value(tag, &pumpStatus_, DeviceValueType::BOOL, nullptr, FL_(pumpStatus), DeviceValueUOM::NONE, MAKE_CF_CB(set_pump));
register_device_value(tag, &flowTempVf_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempVf), DeviceValueUOM::DEGREES);
}
id_ = product_id;
}
// publish HA config
bool Mixer::publish_ha_device_config() {
// if we don't have valid values for this HC don't add it ever again
if (!Helpers::hasValue(pumpStatus_)) {
return false;
}
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
char uniq_id[20];
if (type_ == Type::MP) {
snprintf(uniq_id, sizeof(uniq_id), "MixerMP");
} else {
snprintf(uniq_id, sizeof(uniq_id), "Mixer%02X", device_id() - 0x20 + 1);
}
doc["uniq_id"] = uniq_id;
doc["ic"] = F_(icondevice);
char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf(stat_t, sizeof(stat_t), "%s/%s", Mqtt::base().c_str(), Mqtt::tag_to_topic(device_type(), DeviceValueTAG::TAG_NONE).c_str());
doc["stat_t"] = stat_t;
char name[20];
if (type_ == Type::MP) {
snprintf(name, sizeof(name), "Mixer MP");
} else {
snprintf(name, sizeof(name), "Mixer %02X", device_id() - 0x20 + 1);
}
doc["name"] = name;
char tpl[30];
if (type_ == Type::HC) {
snprintf(tpl, sizeof(tpl), "{{value_json.hc%d.id}}", device_id() - 0x20 + 1);
} else if (type_ == Type::WWC) {
snprintf(tpl, sizeof(tpl), "{{value_json.wwc%d.id}}", device_id() - 0x28 + 1);
} else {
snprintf(tpl, sizeof(tpl), "{{value_json.id}}");
}
doc["val_tpl"] = tpl;
JsonObject dev = doc.createNestedObject("dev");
dev["name"] = FJSON("EMS-ESP Mixer");
dev["sw"] = EMSESP_APP_VERSION;
dev["mf"] = brand_to_string();
dev["mdl"] = this->name();
JsonArray ids = dev.createNestedArray("ids");
ids.add("ems-esp-mixer");
// determine the topic, if its HC and WWC. This is determined by the incoming telegram types.
std::string topic(Mqtt::MQTT_TOPIC_MAX_SIZE, '\0');
if (type_ == Type::HC) {
snprintf(&topic[0], topic.capacity() + 1, "sensor/%s/mixer_hc%d/config", Mqtt::base().c_str(), hc_);
} else if (type_ == Type::WWC) {
snprintf(&topic[0], topic.capacity() + 1, "sensor/%s/mixer_wwc%d/config", Mqtt::base().c_str(), hc_); // WWC
} else if (type_ == Type::MP) {
snprintf(&topic[0], topic.capacity() + 1, "sensor/%s/mixer_mp/config", Mqtt::base().c_str());
}
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
return true;
}
// heating circuits 0x02D7, 0x02D8 etc...
// e.g. A0 00 FF 00 01 D7 00 00 00 80 00 00 00 00 03 C5
// A0 0B FF 00 01 D7 00 00 00 80 00 00 00 00 03 80
void Mixer::process_MMPLUSStatusMessage_HC(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(flowTempHc_, 3)); // is * 10
has_update(telegram->read_value(flowSetTemp_, 5));
has_update(telegram->read_bitvalue(pumpStatus_, 0, 0));
has_update(telegram->read_value(status_, 2)); // valve status
has_update(telegram, flowTempHc_, 3); // is * 10
has_update(telegram, flowSetTemp_, 5);
has_bitupdate(telegram, pumpStatus_, 0, 0);
has_update(telegram, status_, 2); // valve status
}
// Mixer warm water loading/DHW - 0x0331, 0x0332
// e.g. A9 00 FF 00 02 32 02 6C 00 3C 00 3C 3C 46 02 03 03 00 3C // on 0x28
// A8 00 FF 00 02 31 02 35 00 3C 00 3C 3C 46 02 03 03 00 3C // in 0x29
void Mixer::process_MMPLUSStatusMessage_WWC(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(flowTempHc_, 0)); // is * 10
has_update(telegram->read_bitvalue(pumpStatus_, 2, 0));
has_update(telegram->read_value(status_, 11)); // temp status
has_update(telegram, flowTempHc_, 0); // is * 10
has_bitupdate(telegram, pumpStatus_, 2, 0);
has_update(telegram, status_, 11); // temp status
}
// Mixer IPM - 0x010C
@@ -195,18 +145,27 @@ void Mixer::process_IPMStatusMessage(std::shared_ptr<const Telegram> telegram) {
// do we have a mixed circuit
if (ismixed == 2) {
has_update(telegram->read_value(flowTempHc_, 3)); // is * 10
has_update(telegram->read_value(status_, 2)); // valve status
has_update(telegram, flowTempHc_, 3); // is * 10
has_update(telegram, status_, 2); // valve status
}
has_update(telegram->read_bitvalue(pumpStatus_, 1, 0)); // pump is also in unmixed circuits
has_update(telegram->read_value(flowSetTemp_, 5)); // flowSettemp is also in unmixed circuits, see #711
has_bitupdate(telegram, pumpStatus_, 1, 0); // pump is also in unmixed circuits
has_update(telegram, flowSetTemp_, 5); // flowSettemp is also in unmixed circuits, see #711
}
// Mixer IPM - 0x001E Temperature Message in unmixed circuits
// in unmixed circuits FlowTemp in 10C is zero, this is the measured flowtemp in header
void Mixer::process_IPMTempMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(flowTempVf_, 0)); // TC1, is * 10
has_update(telegram, flowTempVf_, 0); // TC1, is * 10
}
// Mixer MP100 for pools - 0x5BA
void Mixer::process_HpPoolStatus(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, poolTemp_, 0);
has_update(telegram, poolShunt_, 3); // 0-100% how much is the shunt open?
telegram->read_value(poolShuntStatus__, 2);
uint8_t pss = poolShunt_ == 100 ? 3 : (poolShunt_ == 0 ? 4 : poolShuntStatus__);
has_update(poolShuntStatus_, pss);
}
// Mixer on a MM10 - 0xAB
@@ -217,41 +176,67 @@ void Mixer::process_MMStatusMessage(std::shared_ptr<const Telegram> telegram) {
// 0x21 is position 2. 0x20 is typically reserved for the WM10 switch module
// see https://github.com/emsesp/EMS-ESP/issues/270 and https://github.com/emsesp/EMS-ESP/issues/386#issuecomment-629610918
has_update(telegram->read_value(flowTempHc_, 1)); // is * 10
has_update(telegram->read_bitvalue(pumpStatus_, 3, 2)); // is 0 or 0x64 (100%), check only bit 2
has_update(telegram->read_value(flowSetTemp_, 0));
has_update(telegram->read_value(status_, 4)); // valve status -100 to 100
has_update(telegram, flowTempHc_, 1); // is * 10
has_bitupdate(telegram, pumpStatus_, 3, 2); // is 0 or 0x64 (100%), check only bit 2
has_update(telegram, flowSetTemp_, 0);
has_update(telegram, status_, 4); // valve status -100 to 100
}
// Pool mixer MP100, - 0x5BA
void Mixer::process_HpPoolStatus(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(poolTemp_, 0));
has_update(telegram->read_value(poolShuntStatus__, 2));
has_update(telegram->read_value(poolShunt_, 3)); // 0-100% how much is the shunt open?
poolShuntStatus_ = poolShunt_ == 100 ? 3 : (poolShunt_ == 0 ? 4 : poolShuntStatus__);
}
/*
* The set-messages are not broadcasted and send from thermostat to mixer,
* we have to fetch for processing
*/
// Mixer on a MM10 - 0xAA
// e.g. Thermostat -> Mixer Module, type 0xAA, telegram: 10 21 AA 00 FF 0C 0A 11 0A 32 xx
void Mixer::process_MMConfigMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(activated_, 0)); // on = 0xFF
has_update(telegram->read_value(setValveTime_, 1)); // valve runtime in 10 sec, max 120 s
has_update(telegram, activated_, 0); // on = 0xFF
has_update(telegram, setValveTime_, 1); // valve runtime in 10 sec, max 120 s
}
// Config message 0x313, has to be fetched
void Mixer::process_MMPLUSConfigMessage_WWC(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, wwRequiredTemp_, 4);
has_update(telegram, wwReducedTemp_, 5);
has_update(telegram, wwDiffTemp_, 7);
has_update(telegram, wwDisinfectionTemp_, 9);
has_update(telegram, wwMaxTemp_, 10);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
// Thermostat(0x10) -> Mixer(0x20), ?(0x2E1), data: 01 1C 64 00 01
// Thermostat(0x10) -> Mixing Module(0x20), (0x2E1), data: 01 00 00 00 01
// Thermostat(0x10) -> Mixing Module(0x20), (0x2EB), data: 00
void Mixer::process_MMPLUSSetMessage_HC(std::shared_ptr<const Telegram> telegram) {
// pos 1: setpoint
// pos2: pump
}
// unknown, 2 examples from older threads
// Thermostat(0x10) -> Mixer(0x28), ?(0x33B), data: 01 01 00
// Thermostat -> Mixing Module, type 0x023B, telegram: 90 28 FF 00 02 3B 00 02 00 (CRC=68)
void Mixer::process_MMPLUSSetMessage_WWC(std::shared_ptr<const Telegram> telegram) {
}
// MMPLUS telegram 0x345 unknown
// Solar Module -> Mixing Module, type 0x0245, telegram: B0 28 FF 00 02 45 64 01 01 (CRC=36)
// ?
// Mixer on a MM10 - 0xAC
// e.g. Thermostat -> Mixer Module, type 0xAC, telegram: 10 21 AC 00 1E 64 01 AB
void Mixer::process_MMSetMessage(std::shared_ptr<const Telegram> telegram) {
// pos 0: flowtemp setpoint 1E = 30°C
// pos 1: position in %
// pos 1: pump in %
// pos 2 flags (mostly 01)
// LOG_INFO("MM10 SetMessage received");
}
// Thermostat(0x10) -> Mixer(0x21), ?(0x23), data: 1A 64 00 90 21 23 00 1A 64 00 89
void Mixer::process_IPMSetMessage(std::shared_ptr<const Telegram> telegram) {
// pos 0: flowtemp setpoint 1A = 26°C
// pos 1: position in %?
// pos 1: pump in %?
}
#pragma GCC diagnostic pop
@@ -261,7 +246,6 @@ bool Mixer::set_flowSetTemp(const char * value, const int8_t id) {
if (!Helpers::value2number(value, v)) {
return false;
}
LOG_INFO(F("Setting mixer flow set temperature to %d"), v);
if (flags() == EMSdevice::EMS_DEVICE_FLAG_MM10) {
write_command(0xAC, 0, v, 0xAB);
return true;
@@ -283,7 +267,6 @@ bool Mixer::set_pump(const char * value, const int8_t id) {
if (!Helpers::value2bool(value, b)) {
return false;
}
LOG_INFO(F("Setting mixer pump %s"), b ? "on" : "off");
if (flags() == EMSdevice::EMS_DEVICE_FLAG_MM10) {
write_command(0xAC, 1, b ? 0x64 : 0, 0xAB);
return true;
@@ -306,7 +289,6 @@ bool Mixer::set_activated(const char * value, const int8_t id) {
return false;
}
if (flags() == EMSdevice::EMS_DEVICE_FLAG_MM10) {
LOG_INFO(F("Setting mixer %s"), value);
write_command(0xAA, 0, b ? 0xFF : 0, 0xAA);
return true;
}
@@ -320,11 +302,81 @@ bool Mixer::set_setValveTime(const char * value, const int8_t id) {
}
if (flags() == EMSdevice::EMS_DEVICE_FLAG_MM10) {
v = (v + 5) / 10;
LOG_INFO(F("Setting mixer valve time to %ds"), v * 10);
write_command(0xAA, 1, v, 0xAA);
return true;
}
return false;
}
bool Mixer::set_wwMaxTemp(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
float v = 0;
if (!Helpers::value2temperature(value, v)) {
return false;
}
write_command(0x313 + wwc, 10, (uint8_t)v, 0x313 + wwc);
return true;
}
bool Mixer::set_wwDiffTemp(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
float v = 0;
if (!Helpers::value2temperature(value, v)) {
return false;
}
write_command(0x313 + wwc, 7, (int8_t)(v * 10), 0x313 + wwc);
return true;
}
bool Mixer::set_wwReducedTemp(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
float v = 0;
if (!Helpers::value2temperature(value, v)) {
return false;
}
write_command(0x313 + wwc, 5, (uint8_t)v, 0x313 + wwc);
return true;
}
bool Mixer::set_wwRequiredTemp(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
float v = 0;
if (!Helpers::value2temperature(value, v)) {
return false;
}
write_command(0x313 + wwc, 4, (uint8_t)v, 0x313 + wwc);
return true;
}
bool Mixer::set_wwDisinfectionTemp(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
float v = 0;
if (!Helpers::value2temperature(value, v)) {
return false;
}
write_command(0x313 + wwc, 9, (uint8_t)v, 0x313 + wwc);
return true;
}
bool Mixer::set_wwCircPump(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
bool v = false;
if (!Helpers::value2bool(value, v)) {
return false;
}
write_command(0x33B + wwc, 0, v ? 0x01 : 0x00, 0x33B + wwc);
return true;
}
bool Mixer::set_wwCircMode(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
uint8_t n;
if (!Helpers::value2enum(value, n, FL_(enum_wwCircMode))) {
return false;
}
write_command(0x313 + wwc, 0, n, 0x313 + wwc);
return true;
}
} // namespace emsesp

View File

@@ -25,15 +25,16 @@ namespace emsesp {
class Mixer : public EMSdevice {
public:
Mixer(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);
virtual bool publish_ha_device_config();
Mixer(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);
private:
static uuid::log::Logger logger_;
void process_MMPLUSStatusMessage_HC(std::shared_ptr<const Telegram> telegram);
void process_MMPLUSSetMessage_HC(std::shared_ptr<const Telegram> telegram);
void process_MMPLUSStatusMessage_WWC(std::shared_ptr<const Telegram> telegram);
void process_MMPLUSSetMessage_WWC(std::shared_ptr<const Telegram> telegram);
void process_MMPLUSConfigMessage_WWC(std::shared_ptr<const Telegram> telegram);
void process_IPMStatusMessage(std::shared_ptr<const Telegram> telegram);
void process_IPMTempMessage(std::shared_ptr<const Telegram> telegram);
void process_IPMSetMessage(std::shared_ptr<const Telegram> telegram);
@@ -47,12 +48,20 @@ class Mixer : public EMSdevice {
bool set_activated(const char * value, const int8_t id);
bool set_setValveTime(const char * value, const int8_t id);
bool set_wwMaxTemp(const char * value, const int8_t id);
bool set_wwDiffTemp(const char * value, const int8_t id);
bool set_wwReducedTemp(const char * value, const int8_t id);
bool set_wwRequiredTemp(const char * value, const int8_t id);
bool set_wwDisinfectionTemp(const char * value, const int8_t id);
bool set_wwCircPump(const char * value, const int8_t id);
bool set_wwCircMode(const char * value, const int8_t id);
enum class Type {
NONE,
HC, // heating circuit
WWC, // warm water circuit
MP // pool
};
private:
@@ -64,14 +73,23 @@ class Mixer : public EMSdevice {
uint8_t activated_;
uint8_t setValveTime_;
// MM100wwParam - 0x0313, 0x033B
uint8_t wwMaxTemp_;
uint8_t wwRequiredTemp_;
uint8_t wwReducedTemp_;
uint8_t wwDiffTemp_;
uint8_t wwDisinfectionTemp_;
uint8_t wwCircPump_;
uint8_t wwCircMode_;
// MP100 pool
int16_t poolTemp_;
int8_t poolShuntStatus_;
int8_t poolShunt_;
uint8_t poolShuntStatus_;
uint8_t poolShunt_;
Type type_ = Type::NONE;
uint16_t hc_ = EMS_VALUE_USHORT_NOTSET;
int8_t poolShuntStatus__ = EMS_VALUE_INT_NOTSET; // temp value
uint8_t id_;
uint8_t poolShuntStatus__ = EMS_VALUE_UINT_NOTSET; // temp value
};
} // namespace emsesp

File diff suppressed because it is too large Load Diff

View File

@@ -25,26 +25,42 @@ namespace emsesp {
class Solar : public EMSdevice {
public:
Solar(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);
virtual bool publish_ha_device_config();
Solar(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);
private:
static uuid::log::Logger logger_;
int16_t collectorTemp_; // TS1: Temperature sensor for collector array 1
int16_t tankBottomTemp_; // TS2: Temperature sensor 1 cylinder, bottom tank (solar thermal system)
int16_t tankBottomTemp2_; // TS5: Temperature sensor 2 cylinder, bottom tank, or swimming pool (solar thermal system)
int16_t heatExchangerTemp_; // TS6: Heat exchanger temperature sensor
uint8_t solarPumpModulation_; // PS1: modulation solar pump
uint8_t cylinderPumpModulation_; // PS5: modulation cylinder pump
uint8_t solarPump_; // PS1: solar pump active
uint8_t valveStatus_; // VS2: status 3-way valve for cylinder 2 (solar thermal system) with valve
int16_t collectorTemp_; // TS1: Temperature sensor for collector array 1
int16_t cylBottomTemp_; // TS2: Temperature sensor 1 cylinder, bottom cyl (solar thermal system)
int16_t cylBottomTemp2_; // TS5: Temperature sensor 2 cylinder, bottom cyl, or swimming pool (solar thermal system)
int16_t heatExchangerTemp_; // TS6: Heat exchanger temperature sensor
int16_t collector2Temp_; // TS7: Temperature sensor for collector array 2
int16_t cylMiddleTemp_; // TS14: Cylinder middle temp
int16_t retHeatAssist_; // TS15: return temperature heating assistance
uint8_t solarPumpMod_; // PS1: modulation solar pump
uint8_t cylPumpMod_; // PS5: modulation cylinder pump
uint8_t solarPump_; // PS1: solar pump active
uint8_t valveStatus_; // VS2: status 3-way valve for cylinder 2 (solar thermal system) with valve
uint8_t solarPump2_; // PS4: solar pump 2 active
uint8_t solarPump2Mod_; // PS4: modulation solar pump
uint8_t m1Valve_; // M1: heat assistance valve
uint8_t m1Power_; // M1: heat assistance valve
// 0x363 heat counter
uint16_t heatCntFlowTemp_;
uint16_t heatCntRetTemp_;
uint8_t heatCnt_;
uint16_t swapFlowTemp_;
uint16_t swapRetTemp_;
// 0x38E
uint32_t energyLastHour_;
uint32_t energyToday_;
uint32_t energyTotal_;
uint32_t pumpWorkTime_; // Total solar pump operating time
uint8_t tankHeated_;
uint32_t pumpWorkTime_; // Total solar pump operating time
uint32_t pump2WorkTime_; // Total solar pump 2 operating time
uint32_t m1WorkTime_; // differential control work time
uint8_t cylHeated_;
uint8_t collectorShutdown_; // Collector shutdown on/off
uint8_t availabilityFlag_;
@@ -53,57 +69,104 @@ class Solar : public EMSdevice {
// telegram 0x0358
uint8_t heatTransferSystem_; // Umladesystem, 00=no
uint8_t externalTank_; // Heat exchanger, 00=no
uint8_t externalCyl_; // Heat exchanger, 00=no
uint8_t thermalDisinfect_; // Daily heatup for disinfection, 00=no
uint8_t heatMetering_; // Wärmemengenzählung, 00=no
uint8_t heatMetering_; // Heat quantity metering, 00=no
uint8_t solarIsEnabled_; // System enable, 00=no
// telegram 0x035A
uint8_t collectorMaxTemp_; // maximum allowed collectorTemp array 1
uint8_t tankMaxTemp_; // Current value for max tank temp
uint8_t collectorMaxTemp_; // maximum allowed collectorTemp array 1
uint8_t cylMaxTemp_; // Current value for max cyl temp
// uint8_t cyl2MaxTemp_; // Current value for max cyl temp
uint8_t collectorMinTemp_; // minimum allowed collectorTemp array 1
uint8_t solarPumpMode_; // 00=off, 01=PWM, 02=10V
uint8_t solarPumpMinMod_; // minimum modulation setting, *5 %
uint8_t solarPumpTurnoffDiff_; // solar pump turnoff collector/tank diff
uint8_t solarPumpTurnonDiff_; // solar pump turnon collector/tank diff
uint8_t solarPumpMinMod_; // minimum modulation setting
uint8_t solarPumpTurnoffDiff_; // solar pump turnoff collector/cyl diff
uint8_t solarPumpTurnonDiff_; // solar pump turnon collector/cyl diff
uint8_t solarPumpKick_; // pump kick for vacuum collector, 00=off
uint8_t plainWaterMode_; // system does not use antifreeze, 00=off
uint8_t doubleMatchFlow_; // double Match Flow, 00=off
// telegram 0x035D
uint8_t collector2MaxTemp_; // maximum allowed collectorTemp array 1
uint8_t collector2MinTemp_; // minimum allowed collectorTemp array 1
uint8_t solarPump2MinMod_; // minimum modulation setting
uint8_t solarPump2TurnoffDiff_; // solar pump turnoff collector/cyl diff
uint8_t solarPump2TurnonDiff_; // solar pump turnon collector/cyl diff
uint8_t solarPump2Kick_; // pump kick for vacuum collector, 00=off
uint8_t solarPump2Mode_; // 00=off, 01=PWM, 02=10V
// telegram 0x35C Heat assistance
uint8_t solarHeatAssist_; // is *10
// telegram 0x035F
uint8_t cylPriority_; // 0 or 1
// telegram 0x361 Differential control
uint8_t diffControl_; // is *10
// telegram 0x380
uint8_t climateZone_; // climate zone identifier
uint16_t collector1Area_; // Area of collector field 1
uint8_t collector1Type_; // Type of collector field 1, 01=flat, 02=vacuum
uint16_t collector2Area_; // Area of collector field 2
uint8_t collector2Type_; // Type of collector field 2, 01=flat, 02=vacuum
// SM100wwTemperature - 0x07D6
uint8_t wwTemp_1_;
uint8_t wwTemp_3_;
uint8_t wwTemp_4_;
uint8_t wwTemp_5_;
uint8_t wwTemp_7_;
uint16_t wwTemp_1_;
uint16_t wwTemp_3_;
uint16_t wwTemp_4_;
uint16_t wwTemp_5_;
uint16_t wwTemp_7_;
// SM100wwStatus - 0x07AA
uint8_t wwPump_;
// SM100wwParam - 0x07A6
uint8_t wwMaxTemp_;
uint8_t wwTemp_;
uint8_t wwRedTemp_;
uint8_t wwDailyTemp_;
uint8_t wwDisinfectionTemp_;
// SM100wwKeepWarm - 0x07AE
uint8_t wwKeepWarm_;
// SM100wwCirc - 0x07A5
uint8_t wwCirc_;
uint8_t wwCircMode_;
// SM100wwStatus2 - 0x07E0
uint8_t wwFlow_;
uint8_t wwPumpMod_;
uint8_t wwStatus2_;
// SM10Config - 0x96
uint8_t wwMinTemp_;
uint8_t maxFlow_; // set this to calculate power
uint32_t solarPower_; // calculated from maxFlow
uint8_t wwMinTemp_;
uint8_t maxFlow_; // set this to calculate power
int16_t solarPower_; // calculated from maxFlow
std::deque<uint16_t> energy;
uint8_t data0_;
uint8_t data1_;
uint8_t data11_;
uint8_t data12_;
uint8_t setting3_;
uint8_t setting4_;
char type_[20]; // Solar of WWC
uint8_t id_;
std::deque<int16_t> energy;
void process_SM10Monitor(std::shared_ptr<const Telegram> telegram);
void process_SM10Config(std::shared_ptr<const Telegram> telegram);
void process_SM100SystemConfig(std::shared_ptr<const Telegram> telegram);
void process_SM100SolarCircuitConfig(std::shared_ptr<const Telegram> telegram);
void process_SM100CircuitConfig(std::shared_ptr<const Telegram> telegram);
void process_SM100Circuit2Config(std::shared_ptr<const Telegram> telegram);
void process_SM100ParamCfg(std::shared_ptr<const Telegram> telegram);
void process_SM100Monitor(std::shared_ptr<const Telegram> telegram);
void process_SM100Monitor2(std::shared_ptr<const Telegram> telegram);
void process_SM100Config(std::shared_ptr<const Telegram> telegram);
void process_SM100Config1(std::shared_ptr<const Telegram> telegram);
void process_SM100Status(std::shared_ptr<const Telegram> telegram);
void process_SM100Status2(std::shared_ptr<const Telegram> telegram);
@@ -111,9 +174,16 @@ class Solar : public EMSdevice {
void process_SM100Energy(std::shared_ptr<const Telegram> telegram);
void process_SM100Time(std::shared_ptr<const Telegram> telegram);
void process_SM100HeatAssist(std::shared_ptr<const Telegram> telegram);
void process_SM100Differential(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_SM100wwStatus2(std::shared_ptr<const Telegram> telegram);
void process_SM100wwCommand(std::shared_ptr<const Telegram> telegram);
void process_SM100wwCirc(std::shared_ptr<const Telegram> telegram);
void process_SM100wwParam(std::shared_ptr<const Telegram> telegram);
void process_SM100wwKeepWarm(std::shared_ptr<const Telegram> telegram);
void process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram);
void process_ISM1Set(std::shared_ptr<const Telegram> telegram);
@@ -121,26 +191,47 @@ class Solar : public EMSdevice {
bool set_CollectorMaxTemp(const char * value, const int8_t id);
bool set_CollectorMinTemp(const char * value, const int8_t id);
bool set_TankMaxTemp(const char * value, const int8_t id);
bool set_cylMaxTemp(const char * value, const int8_t id);
bool set_PumpMinMod(const char * value, const int8_t id);
bool set_wwMinTemp(const char * value, const int8_t id);
bool set_TurnonDiff(const char * value, const int8_t id);
bool set_TurnoffDiff(const char * value, const int8_t id);
bool set_Collector2MaxTemp(const char * value, const int8_t id);
bool set_Collector2MinTemp(const char * value, const int8_t id);
bool set_Pump2MinMod(const char * value, const int8_t id);
bool set_TurnonDiff2(const char * value, const int8_t id);
bool set_TurnoffDiff2(const char * value, const int8_t id);
bool set_SM10MaxFlow(const char * value, const int8_t id);
// SM100
bool set_heatTransferSystem(const char * value, const int8_t id);
bool set_externalTank(const char * value, const int8_t id);
bool set_externalCyl(const char * value, const int8_t id);
bool set_thermalDisinfect(const char * value, const int8_t id);
bool set_heatMetering(const char * value, const int8_t id);
bool set_solarEnabled(const char * value, const int8_t id);
bool set_solarMode(const char * value, const int8_t id);
bool set_solarPumpKick(const char * value, const int8_t id);
bool set_solarPump2Kick(const char * value, const int8_t id);
bool set_plainWaterMode(const char * value, const int8_t id);
bool set_doubleMatchFlow(const char * value, const int8_t id);
bool set_climateZone(const char * value, const int8_t id);
bool set_collector1Area(const char * value, const int8_t id);
bool set_collector1Type(const char * value, const int8_t id);
bool set_collector2Area(const char * value, const int8_t id);
bool set_collector2Type(const char * value, const int8_t id);
bool set_cylPriority(const char * value, const int8_t id);
bool set_heatAssist(const char * value, const int8_t id);
bool set_diffControl(const char * value, const int8_t id);
bool set_wwTemp(const char * value, const int8_t id);
bool set_wwMaxTemp(const char * value, const int8_t id);
bool set_wwRedTemp(const char * value, const int8_t id);
bool set_wwCirc(const char * value, const int8_t id);
bool set_wwCircMode(const char * value, const int8_t id);
bool set_wwKeepWarm(const char * value, const int8_t id);
bool set_wwDisinfectionTemp(const char * value, const int8_t id);
bool set_wwDailyTemp(const char * value, const int8_t id);
};
} // namespace emsesp

View File

@@ -22,76 +22,35 @@ namespace emsesp {
REGISTER_FACTORY(Switch, EMSdevice::DeviceType::SWITCH);
uuid::log::Logger Switch::logger_ {
F_(switch), uuid::log::Facility::CONSOLE
};
Switch::Switch(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)
Switch::Switch(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) {
register_telegram_type(0x9C, F("WM10MonitorMessage"), false, MAKE_PF_CB(process_WM10MonitorMessage));
register_telegram_type(0x9D, F("WM10SetMessage"), false, MAKE_PF_CB(process_WM10SetMessage));
register_telegram_type(0x1E, F("WM10TempMessage"), false, MAKE_PF_CB(process_WM10TempMessage));
register_device_value(TAG_NONE, &id_, DeviceValueType::UINT, nullptr, FL_(ID), DeviceValueUOM::NONE);
register_device_value(TAG_NONE, &activated_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::NONE);
register_device_value(TAG_NONE, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
register_device_value(TAG_NONE, &status_, DeviceValueType::INT, nullptr, FL_(status), DeviceValueUOM::NONE);
id_ = product_id;
}
// publish HA config
bool Switch::publish_ha_device_config() {
// if we don't have valid values don't add it ever again
if (!Helpers::hasValue(flowTempHc_)) {
return false;
}
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
doc["uniq_id"] = F_(switch);
doc["ic"] = F_(icondevice);
char stat_t[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf(stat_t, sizeof(stat_t), "%s/%s", Mqtt::base().c_str(), Mqtt::tag_to_topic(device_type(), DeviceValueTAG::TAG_NONE).c_str());
doc["stat_t"] = stat_t;
char name_s[40];
snprintf(name_s, sizeof(name_s), FSTR_(productid_fmt), device_type_name().c_str());
doc["name"] = name_s;
doc["val_tpl"] = FJSON("{{value_json.id}}");
JsonObject dev = doc.createNestedObject("dev");
dev["name"] = FJSON("EMS-ESP Switch");
dev["sw"] = EMSESP_APP_VERSION;
dev["mf"] = brand_to_string();
dev["mdl"] = this->name();
JsonArray ids = dev.createNestedArray("ids");
ids.add("ems-esp-switch");
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf(topic, sizeof(topic), "sensor/%s/switch/config", Mqtt::base().c_str());
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
return true;
register_device_value(DeviceValueTAG::TAG_NONE, &activated_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_NONE, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_NONE, &status_, DeviceValueType::INT, nullptr, FL_(status), DeviceValueUOM::NONE);
}
// message 0x9D switch on/off
// Thermostat(0x10) -> Switch(0x11), ?(0x9D), data: 00
void Switch::process_WM10SetMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(activated_, 0));
has_update(telegram, activated_, 0);
}
// message 0x9C holds flowtemp and unknown status value
// Switch(0x11) -> All(0x00), ?(0x9C), data: 01 BA 00 01 00
void Switch::process_WM10MonitorMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(flowTempHc_, 0)); // is * 10
has_update(telegram->read_value(status_, 2));
// has_update(telegram->read_value(status2_, 3)); // unknown
has_update(telegram, flowTempHc_, 0); // is * 10
has_update(telegram, status_, 2);
// has_update(telegram, status2_, 3)); // unknown
}
// message 0x1E flow temperature, same as in 9C, published often, republished also by boiler UBAFast 0x18
// Switch(0x11) -> Boiler(0x08), ?(0x1E), data: 01 BA
void Switch::process_WM10TempMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram->read_value(flowTempHc_, 0)); // is * 10
has_update(telegram, flowTempHc_, 0); // is * 10
}
} // namespace emsesp
} // namespace emsesp

View File

@@ -25,13 +25,9 @@ namespace emsesp {
class Switch : public EMSdevice {
public:
Switch(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);
virtual bool publish_ha_device_config();
Switch(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);
private:
static uuid::log::Logger logger_;
void process_WM10SetMessage(std::shared_ptr<const Telegram> telegram);
void process_WM10MonitorMessage(std::shared_ptr<const Telegram> telegram);
void process_WM10TempMessage(std::shared_ptr<const Telegram> telegram);
@@ -39,7 +35,6 @@ class Switch : public EMSdevice {
uint16_t flowTempHc_;
uint8_t status_;
uint8_t activated_;
uint8_t id_;
};
} // namespace emsesp

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,7 @@ namespace emsesp {
class Thermostat : public EMSdevice {
public:
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(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);
class HeatingCircuit {
public:
HeatingCircuit(const uint8_t hc_num, const uint8_t model)
@@ -34,12 +34,11 @@ class Thermostat : public EMSdevice {
}
~HeatingCircuit() = default;
int16_t setpoint_roomTemp;
int16_t curr_roomTemp;
int16_t selTemp;
int16_t roomTemp;
int16_t remotetemp; // for readback
uint8_t tempautotemp;
uint8_t mode;
uint8_t hamode; // special mode for HA. See https://github.com/emsesp/EMS-ESP32/issues/66
uint8_t modetype;
uint8_t summermode;
uint8_t holidaymode;
@@ -68,8 +67,11 @@ class Thermostat : public EMSdevice {
int8_t noreducetemp; // signed -20°C to +10°C
uint8_t wwprio;
uint8_t fastHeatup;
char holiday[22];
char vacation[22];
char holiday[26];
char vacation[26];
char switchtime1[16];
char switchtime2[16];
// RC 10
uint8_t reducehours; // night reduce duration
uint16_t reduceminutes; // remaining minutes to night->day
@@ -78,13 +80,25 @@ class Thermostat : public EMSdevice {
return hc_num_;
}
uint8_t hc() const {
return hc_num_ - 1;
}
uint8_t get_model() const {
return model_;
}
// determines if the heating circuit is actually present and has data
bool is_active() {
return Helpers::hasValue(setpoint_roomTemp);
return Helpers::hasValue(selTemp);
}
bool ha_climate_created() {
return ha_climate_created_;
}
void ha_climate_created(bool ha_climate_created) {
ha_climate_created_ = ha_climate_created;
}
uint8_t get_mode() const;
@@ -116,19 +130,18 @@ class Thermostat : public EMSdevice {
};
// for sorting based on hc number
friend inline bool operator<(const std::shared_ptr<HeatingCircuit> & lhs, const std::shared_ptr<HeatingCircuit> & rhs) {
return (lhs->hc_num_ < rhs->hc_num_);
friend inline bool operator<(const std::shared_ptr<HeatingCircuit> & a, const std::shared_ptr<HeatingCircuit> & b) {
return (a->hc_num_ < b->hc_num_);
}
private:
uint8_t hc_num_; // heating circuit number 1..10
uint8_t model_; // the model type
uint8_t hc_num_; // heating circuit number 1..10
uint8_t model_; // the model type
bool ha_climate_created_; // if we need to create the HA climate control
};
static std::string mode_tostring(uint8_t mode);
virtual bool publish_ha_device_config();
private:
static uuid::log::Logger logger_;
@@ -144,18 +157,17 @@ class Thermostat : public EMSdevice {
std::vector<uint16_t> monitor_typeids;
std::vector<uint16_t> set_typeids;
std::vector<uint16_t> timer_typeids;
std::vector<uint16_t> timer2_typeids;
std::vector<uint16_t> summer_typeids;
std::vector<uint16_t> summer2_typeids;
std::vector<uint16_t> curve_typeids;
// standard for all thermostats
uint8_t id_; // product id
char status_[20]; // online or offline
char dateTime_[25]; // date and time stamp
char errorCode_[15]; // code from 0xA2 as string i.e. "A22(816)"
uint16_t errorNumber_; // used internally to build error code
char lastCode_[30]; // error log
uint8_t dummy_; // for commands with no output
char lastCode_[50]; // error log
// Installation parameters
uint8_t ibaMainDisplay_; // display on Thermostat: 0 int temp, 1 int setpoint, 2 ext temp, 3 burner temp, 4 ww temp, 5 functioning mode, 6 time, 7 data, 9 smoke temp
@@ -184,13 +196,17 @@ class Thermostat : public EMSdevice {
uint8_t wwSetTempLow_;
uint8_t wwCharge_;
uint8_t wwChargeDuration_;
uint8_t wwDisinfect_;
uint8_t wwDisinfecting_;
uint8_t wwDisinfectDay_;
uint8_t wwDisinfectHour_;
uint8_t wwMaxTemp_;
uint8_t wwOneTimeKey_;
uint8_t wwProgMode_;
uint8_t wwCircProg_;
char wwSwitchTime_[16];
char wwCircSwitchTime_[16];
uint8_t wwDailyHeating_;
uint8_t wwDailyHeatTime_;
std::vector<std::shared_ptr<HeatingCircuit>> heating_circuits_; // each thermostat can have multiple heating circuits
@@ -208,7 +224,8 @@ class Thermostat : public EMSdevice {
static constexpr uint8_t EMS_OFFSET_RC20StatusMessage_setpoint = 1; // setpoint temp
static constexpr uint8_t EMS_OFFSET_RC20StatusMessage_curr = 2; // current temp
static constexpr uint8_t EMS_OFFSET_RC20Set_mode = 23; // position of thermostat mode
static constexpr uint8_t EMS_OFFSET_RC20Set_temp = 28; // position of thermostat setpoint temperature
static constexpr uint8_t EMS_OFFSET_RC20Set_temp_auto = 28; // position of thermostat setpoint temperature
static constexpr uint8_t EMS_OFFSET_RC20Set_temp_manual = 29; // position of thermostat setpoint temperature
static constexpr uint8_t EMS_OFFSET_RC20_2_Set_mode = 3; // ES72 - see https://github.com/emsesp/EMS-ESP/issues/334
static constexpr uint8_t EMS_OFFSET_RC20_2_Set_temp_night = 1; // ES72
@@ -280,6 +297,7 @@ class Thermostat : public EMSdevice {
void register_device_values_hc(std::shared_ptr<Thermostat::HeatingCircuit> hc);
bool thermostat_ha_cmd(const char * message, uint8_t hc_num);
void add_ha_climate(std::shared_ptr<HeatingCircuit> hc);
void process_RCOutdoorTemp(std::shared_ptr<const Telegram> telegram);
void process_IBASettings(std::shared_ptr<const Telegram> telegram);
@@ -287,6 +305,7 @@ class Thermostat : public EMSdevice {
void process_RCError(std::shared_ptr<const Telegram> telegram);
void process_RCErrorMessage(std::shared_ptr<const Telegram> telegram);
void process_RC35wwSettings(std::shared_ptr<const Telegram> telegram);
void process_RC35wwTimer(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_RC35Timer(std::shared_ptr<const Telegram> telegram);
@@ -316,12 +335,14 @@ class Thermostat : public EMSdevice {
void process_JunkersSet(std::shared_ptr<const Telegram> telegram);
void process_JunkersSet2(std::shared_ptr<const Telegram> telegram);
void process_EasyMonitor(std::shared_ptr<const Telegram> telegram);
void process_JunkersRemoteMonitor(std::shared_ptr<const Telegram> telegram);
// internal helper functions
bool set_mode_n(const uint8_t mode, const uint8_t hc_num);
bool set_temperature_value(const char * value, const int8_t id, const uint8_t mode);
bool set_temperature_value(const char * value, const int8_t id, const uint8_t mode, bool relative = false);
bool set_temperature(const float temperature, const uint8_t mode, const uint8_t hc_num);
bool set_switchtime(const char * value, const uint16_t type_id, char * out, size_t len);
// set functions - these use the id/hc
bool set_mode(const char * value, const int8_t id);
@@ -354,7 +375,8 @@ class Thermostat : public EMSdevice {
bool set_minflowtemp(const char * value, const int8_t id);
bool set_maxflowtemp(const char * value, const int8_t id);
bool set_reducemode(const char * value, const int8_t id);
bool set_switchtime(const char * value, const int8_t id);
bool set_switchtime1(const char * value, const int8_t id);
bool set_switchtime2(const char * value, const int8_t id);
bool set_program(const char * value, const int8_t id);
bool set_controlmode(const char * value, const int8_t id);
bool set_wwprio(const char * value, const int8_t id);
@@ -374,6 +396,10 @@ class Thermostat : public EMSdevice {
bool set_wwOneTimeKey(const char * value, const int8_t id);
bool set_wwProgMode(const char * value, const int8_t id);
bool set_wwCircProg(const char * value, const int8_t id);
bool set_wwSwitchTime(const char * value, const int8_t id);
bool set_wwCircSwitchTime(const char * value, const int8_t id);
bool set_wwDailyHeating(const char * value, const int8_t id);
bool set_wwDailyHeatTime(const char * value, const int8_t id);
bool set_datetime(const char * value, const int8_t id);
bool set_minexttemp(const char * value, const int8_t id);