mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-09 17:29:50 +03:00
refactor device value rendering (to Web, Console or MQTT) to base class #632
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -38,23 +38,14 @@ 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 void publish_values(JsonObject & json, bool force);
|
||||
virtual bool export_values(JsonObject & json);
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual bool publish_ha_config();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void register_mqtt_ha_config();
|
||||
void register_mqtt_ha_config_ww();
|
||||
void check_active(const bool force = false);
|
||||
bool export_values_main(JsonObject & doc, const bool textformat = false);
|
||||
bool export_values_ww(JsonObject & doc, const bool textformat = false);
|
||||
|
||||
bool changed_ = false;
|
||||
bool mqtt_ha_config_ = false; // HA MQTT Discovery
|
||||
bool mqtt_ha_config_ww_ = false; // HA MQTT Discovery
|
||||
uint8_t boilerState_ = EMS_VALUE_UINT_NOTSET; // Boiler state flag - FOR INTERNAL USE
|
||||
|
||||
static constexpr uint8_t EMS_TYPE_UBAParameterWW = 0x33;
|
||||
static constexpr uint8_t EMS_TYPE_UBAFunctionTest = 0x1D;
|
||||
@@ -68,120 +59,99 @@ class Boiler : public EMSdevice {
|
||||
|
||||
static constexpr uint8_t EMS_BOILER_SELFLOWTEMP_HEATING = 20; // was originally 70, changed to 30 for issue #193, then to 20 with issue #344
|
||||
|
||||
// UBAParameterWW
|
||||
uint8_t wWActivated_ = EMS_VALUE_BOOL_NOTSET; // Warm Water activated
|
||||
uint8_t wWSelTemp_ = EMS_VALUE_UINT_NOTSET; // Warm Water selected temperature
|
||||
uint8_t wWCircPump_ = EMS_VALUE_BOOL_NOTSET; // Warm Water circulation pump available
|
||||
uint8_t wWCircPumpMode_ = EMS_VALUE_UINT_NOTSET; // Warm Water circulation pump mode
|
||||
uint8_t wWChargeType_ = EMS_VALUE_BOOL_NOTSET; // Warm Water charge type (pump or 3-way-valve)
|
||||
uint8_t wWDisinfectionTemp_ = EMS_VALUE_UINT_NOTSET; // Warm Water disinfection temperature to prevent infection
|
||||
uint8_t wWComfort_ = EMS_VALUE_UINT_NOTSET; // WW comfort mode
|
||||
// ww
|
||||
uint8_t wWSetTemp_; // Warm Water set temperature
|
||||
uint8_t wWSelTemp_; // Warm Water selected 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 wWCircPumpMode_; // Warm Water 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 wWDisinfecting_; // 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
|
||||
uint8_t wWActive_;
|
||||
uint8_t wWHeat_; // 3-way valve on WW
|
||||
uint8_t wWSetPumpPower_; // ww pump speed/power?
|
||||
uint16_t wwMixTemperature_; // mixing temperature
|
||||
uint16_t wwBufferTemperature_; // buffertemperature
|
||||
uint32_t wWStarts_; // Warm Water # starts
|
||||
uint32_t wWStarts2_; // Warm water starts (control)
|
||||
uint32_t wWWorkM_; // Warm Water # minutes
|
||||
|
||||
// MC10Status
|
||||
uint16_t wwMixTemperature_ = EMS_VALUE_USHORT_NOTSET; // mengertemperatuur
|
||||
uint16_t wwBufferTemperature_ = EMS_VALUE_USHORT_NOTSET; // buffertemperature
|
||||
|
||||
// UBAMonitorFast - 0x18 on EMS1
|
||||
uint8_t selFlowTemp_ = EMS_VALUE_UINT_NOTSET; // Selected flow temperature
|
||||
uint16_t curFlowTemp_ = EMS_VALUE_USHORT_NOTSET; // Current flow temperature
|
||||
uint16_t wwStorageTemp1_ = EMS_VALUE_USHORT_NOTSET; // warm water storage temp 1
|
||||
uint16_t wwStorageTemp2_ = EMS_VALUE_USHORT_NOTSET; // warm water storage temp 2
|
||||
uint16_t retTemp_ = EMS_VALUE_USHORT_NOTSET; // Return temperature
|
||||
uint8_t burnGas_ = EMS_VALUE_BOOL_NOTSET; // Gas on/off
|
||||
uint8_t fanWork_ = EMS_VALUE_BOOL_NOTSET; // Fan on/off
|
||||
uint8_t ignWork_ = EMS_VALUE_BOOL_NOTSET; // Ignition on/off
|
||||
uint8_t heatPump_ = EMS_VALUE_BOOL_NOTSET; // Boiler pump on/off
|
||||
uint8_t wWHeat_ = EMS_VALUE_BOOL_NOTSET; // 3-way valve on WW
|
||||
uint8_t wWCirc_ = EMS_VALUE_BOOL_NOTSET; // Circulation on/off
|
||||
uint8_t selBurnPow_ = EMS_VALUE_UINT_NOTSET; // Burner max power %
|
||||
uint8_t curBurnPow_ = EMS_VALUE_UINT_NOTSET; // Burner current power %
|
||||
uint16_t flameCurr_ = EMS_VALUE_USHORT_NOTSET; // Flame current in micro amps
|
||||
uint8_t sysPress_ = EMS_VALUE_UINT_NOTSET; // System pressure
|
||||
char serviceCode_[4] = {'\0'}; // 3 character status/service code
|
||||
uint16_t serviceCodeNumber_ = EMS_VALUE_USHORT_NOTSET; // error/service code
|
||||
uint8_t boilerState_ = EMS_VALUE_UINT_NOTSET; // Boiler state flag
|
||||
char lastCode_[30] = {'\0'};
|
||||
uint32_t lastCodeDate_ = 0;
|
||||
|
||||
// UBAMonitorSlow - 0x19 on EMS1
|
||||
int16_t outdoorTemp_ = EMS_VALUE_SHORT_NOTSET; // Outside temperature
|
||||
uint16_t boilTemp_ = EMS_VALUE_USHORT_NOTSET; // Boiler temperature
|
||||
uint16_t exhaustTemp_ = EMS_VALUE_USHORT_NOTSET; // Exhaust temperature
|
||||
uint8_t pumpMod_ = EMS_VALUE_UINT_NOTSET; // Pump modulation %
|
||||
uint32_t burnStarts_ = EMS_VALUE_ULONG_NOTSET; // # burner restarts
|
||||
uint32_t burnWorkMin_ = EMS_VALUE_ULONG_NOTSET; // Total burner operating time
|
||||
uint32_t heatWorkMin_ = EMS_VALUE_ULONG_NOTSET; // Total heat operating time
|
||||
uint16_t switchTemp_ = EMS_VALUE_USHORT_NOTSET; // Switch temperature
|
||||
|
||||
// UBAMonitorWW
|
||||
uint8_t wWSetTemp_ = EMS_VALUE_UINT_NOTSET; // Warm Water set temperature
|
||||
uint16_t wWCurTemp_ = EMS_VALUE_USHORT_NOTSET; // Warm Water current temperature
|
||||
uint16_t wWCurTemp2_ = EMS_VALUE_USHORT_NOTSET; // Warm Water current temperature storage
|
||||
uint32_t wWStarts_ = EMS_VALUE_ULONG_NOTSET; // Warm Water # starts
|
||||
uint32_t wWWorkM_ = EMS_VALUE_ULONG_NOTSET; // Warm Water # minutes
|
||||
uint8_t wWOneTime_ = EMS_VALUE_BOOL_NOTSET; // Warm Water one time function on/off
|
||||
uint8_t wWDisinfecting_ = EMS_VALUE_BOOL_NOTSET; // Warm Water disinfection on/off
|
||||
uint8_t wWCharging_ = EMS_VALUE_BOOL_NOTSET; // Warm Water charging on/off
|
||||
uint8_t wWRecharging_ = EMS_VALUE_BOOL_NOTSET; // Warm Water recharge on/off
|
||||
uint8_t wWTempOK_ = EMS_VALUE_BOOL_NOTSET; // Warm Water temperature ok on/off
|
||||
uint8_t wWCurFlow_ = EMS_VALUE_UINT_NOTSET; // Warm Water current flow temp in l/min
|
||||
uint8_t wWType_ = EMS_VALUE_UINT_NOTSET; // 0-off, 1-flow, 2-flowbuffer, 3-buffer, 4-layered buffer
|
||||
uint8_t wWActive_ = EMS_VALUE_BOOL_NOTSET;
|
||||
|
||||
// UBATotalUptime
|
||||
uint32_t UBAuptime_ = EMS_VALUE_ULONG_NOTSET; // Total UBA working hours
|
||||
|
||||
// UBAParameters
|
||||
uint8_t heatingActivated_ = EMS_VALUE_BOOL_NOTSET; // Heating activated on the boiler
|
||||
uint8_t heatingTemp_ = EMS_VALUE_UINT_NOTSET; // Heating temperature setting on the boiler
|
||||
uint8_t pumpModMax_ = EMS_VALUE_UINT_NOTSET; // Boiler circuit pump modulation max. power %
|
||||
uint8_t pumpModMin_ = EMS_VALUE_UINT_NOTSET; // Boiler circuit pump modulation min. power
|
||||
uint8_t burnMinPower_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t burnMaxPower_ = EMS_VALUE_UINT_NOTSET;
|
||||
int8_t boilHystOff_ = EMS_VALUE_INT_NOTSET;
|
||||
int8_t boilHystOn_ = EMS_VALUE_INT_NOTSET;
|
||||
uint8_t burnMinPeriod_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t pumpDelay_ = EMS_VALUE_UINT_NOTSET;
|
||||
|
||||
// UBASetPoint
|
||||
uint8_t setFlowTemp_ = EMS_VALUE_UINT_NOTSET; // boiler setpoint temp
|
||||
uint8_t setBurnPow_ = EMS_VALUE_UINT_NOTSET; // max output power in %
|
||||
uint8_t wWSetPumpPower_ = EMS_VALUE_UINT_NOTSET; // ww pump speed/power?
|
||||
|
||||
// other internal calculated params
|
||||
uint8_t tapwaterActive_ = EMS_VALUE_BOOL_NOTSET; // Hot tap water is on/off
|
||||
uint8_t heatingActive_ = EMS_VALUE_BOOL_NOTSET; // Central heating is on/off
|
||||
uint8_t pumpMod2_ = EMS_VALUE_UINT_NOTSET; // heatpump modulation from 0xE3 (heatpumps)
|
||||
|
||||
// UBAInformation
|
||||
uint32_t upTimeControl_ = EMS_VALUE_ULONG_NOTSET; // Operating time control
|
||||
uint32_t upTimeCompHeating_ = EMS_VALUE_ULONG_NOTSET; // Operating time compressor heating
|
||||
uint32_t upTimeCompCooling_ = EMS_VALUE_ULONG_NOTSET; // Operating time compressor cooling
|
||||
uint32_t upTimeCompWw_ = EMS_VALUE_ULONG_NOTSET; // Operating time compressor warm water
|
||||
uint32_t heatingStarts_ = EMS_VALUE_ULONG_NOTSET; // Heating starts (control)
|
||||
uint32_t coolingStarts_ = EMS_VALUE_ULONG_NOTSET; // Cooling starts (control)
|
||||
uint32_t wWStarts2_ = EMS_VALUE_ULONG_NOTSET; // Warm water starts (control)
|
||||
uint32_t nrgConsTotal_ = EMS_VALUE_ULONG_NOTSET; // Energy consumption total
|
||||
uint32_t auxElecHeatNrgConsTotal_ = EMS_VALUE_ULONG_NOTSET; // Auxiliary electrical heater energy consumption total
|
||||
uint32_t auxElecHeatNrgConsHeating_ = EMS_VALUE_ULONG_NOTSET; // Auxiliary electrical heater energy consumption heating
|
||||
uint32_t auxElecHeatNrgConsDHW_ = EMS_VALUE_ULONG_NOTSET; // Auxiliary electrical heater energ consumption DHW
|
||||
uint32_t nrgConsCompTotal_ = EMS_VALUE_ULONG_NOTSET; // Energy consumption compressor total
|
||||
uint32_t nrgConsCompHeating_ = EMS_VALUE_ULONG_NOTSET; // Energy consumption compressor heating
|
||||
uint32_t nrgConsCompWw_ = EMS_VALUE_ULONG_NOTSET; // Energy consumption compressor warm water
|
||||
uint32_t nrgConsCompCooling_ = EMS_VALUE_ULONG_NOTSET; // Energy consumption compressor cooling
|
||||
|
||||
// UBAEnergySupplied
|
||||
uint32_t nrgSuppTotal_ = EMS_VALUE_ULONG_NOTSET; // Energy supplied total
|
||||
uint32_t nrgSuppHeating_ = EMS_VALUE_ULONG_NOTSET; // Energy supplied heating
|
||||
uint32_t nrgSuppWw_ = EMS_VALUE_ULONG_NOTSET; // Energy supplied warm water
|
||||
uint32_t nrgSuppCooling_ = EMS_VALUE_ULONG_NOTSET; // Energy supplied cooling
|
||||
|
||||
// _UBAMaintenanceData
|
||||
uint8_t maintenanceMessage_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t maintenanceType_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t maintenanceTime_ = EMS_VALUE_UINT_NOTSET;
|
||||
char maintenanceDate_[12] = {'\0'};
|
||||
// main
|
||||
uint8_t heatingActive_; // Central heating is on/off
|
||||
uint8_t tapwaterActive_; // Hot tap water is on/off
|
||||
uint8_t selFlowTemp_; // Selected flow temperature
|
||||
uint8_t selBurnPow_; // Burner max power %
|
||||
uint8_t pumpMod2_; // heatpump modulation from 0xE3 (heatpumps)
|
||||
uint8_t pumpMod_; // Pump modulation %
|
||||
int16_t outdoorTemp_; // Outside temperature
|
||||
uint16_t curFlowTemp_; // Current flow temperature
|
||||
uint16_t retTemp_; // Return temperature
|
||||
uint16_t switchTemp_; // Switch temperature
|
||||
uint8_t sysPress_; // System pressure
|
||||
uint16_t boilTemp_; // Boiler temperature
|
||||
uint16_t exhaustTemp_; // Exhaust temperature
|
||||
uint8_t burnGas_; // Gas on/off
|
||||
uint16_t flameCurr_; // Flame current in micro amps
|
||||
uint8_t heatPump_; // Boiler pump on/off
|
||||
uint8_t fanWork_; // Fan on/off
|
||||
uint8_t ignWork_; // Ignition on/off
|
||||
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 %
|
||||
uint8_t pumpModMin_; // Boiler circuit pump modulation min. power
|
||||
uint8_t pumpDelay_;
|
||||
uint8_t burnMinPeriod_;
|
||||
uint8_t burnMinPower_;
|
||||
uint8_t burnMaxPower_;
|
||||
int8_t boilHystOn_;
|
||||
int8_t boilHystOff_;
|
||||
uint8_t setFlowTemp_; // boiler setpoint temp
|
||||
uint8_t curBurnPow_; // Burner current power %
|
||||
uint8_t setBurnPow_; // max output power in %
|
||||
uint32_t burnStarts_; // # burner restarts
|
||||
uint32_t burnWorkMin_; // Total burner operating time
|
||||
uint32_t heatWorkMin_; // Total heat operating time
|
||||
uint32_t UBAuptime_; // Total UBA working hours
|
||||
char lastCode_[30]; // last error code
|
||||
char serviceCode_[4]; // 3 character status/service code
|
||||
uint16_t serviceCodeNumber_; // error/service code
|
||||
|
||||
// info
|
||||
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 heatingStarts_; // Heating starts (control)
|
||||
uint32_t coolingStarts_; // Cooling starts (control)
|
||||
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 nrgConsCompCooling_; // Energy consumption compressor cooling
|
||||
uint32_t nrgSuppTotal_; // Energy supplied total
|
||||
uint32_t nrgSuppHeating_; // Energy supplied heating
|
||||
uint32_t nrgSuppWw_; // Energy supplied warm water
|
||||
uint32_t nrgSuppCooling_; // Energy supplied cooling
|
||||
uint32_t auxElecHeatNrgConsTotal_; // Auxiliary electrical heater energy consumption total
|
||||
uint32_t auxElecHeatNrgConsHeating_; // Auxiliary electrical heater energy consumption heating
|
||||
uint32_t auxElecHeatNrgConsDHW_; // Auxiliary electrical heater energy consumption DHW
|
||||
char maintenanceMessage_[4];
|
||||
char maintenanceDate_[12];
|
||||
uint8_t maintenanceType_;
|
||||
uint8_t maintenanceTime_;
|
||||
|
||||
void process_UBAParameterWW(std::shared_ptr<const Telegram> telegram);
|
||||
void process_UBAMonitorFast(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
@@ -28,21 +28,9 @@ Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
}
|
||||
|
||||
void Connect::device_info_web(JsonArray & root) {
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
void Connect::publish_values(JsonObject & json, bool force) {
|
||||
}
|
||||
|
||||
// export values to JSON
|
||||
bool Connect::export_values(JsonObject & json) {
|
||||
// publish HA config
|
||||
bool Connect::publish_ha_config() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check to see if values have been updated
|
||||
bool Connect::updated_values() {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -35,10 +35,7 @@ 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 void publish_values(JsonObject & json, bool force);
|
||||
virtual bool export_values(JsonObject & json);
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual bool publish_ha_config();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
@@ -28,21 +28,9 @@ Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
}
|
||||
|
||||
void Controller::device_info_web(JsonArray & root) {
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
void Controller::publish_values(JsonObject & json, bool force) {
|
||||
}
|
||||
|
||||
// export values to JSON
|
||||
bool Controller::export_values(JsonObject & json) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check to see if values have been updated
|
||||
bool Controller::updated_values() {
|
||||
return false;
|
||||
// publish HA config
|
||||
bool Controller::publish_ha_config() {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -35,10 +35,7 @@ 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 void publish_values(JsonObject & json, bool force);
|
||||
virtual bool export_values(JsonObject & json);
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual bool publish_ha_config();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
@@ -28,21 +28,9 @@ Gateway::Gateway(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
}
|
||||
|
||||
void Gateway::device_info_web(JsonArray & root) {
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
void Gateway::publish_values(JsonObject & json, bool force) {
|
||||
}
|
||||
|
||||
// export values to JSON
|
||||
bool Gateway::export_values(JsonObject & json) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check to see if values have been updated
|
||||
bool Gateway::updated_values() {
|
||||
return false;
|
||||
// publish HA config
|
||||
bool Gateway::publish_ha_config() {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -35,10 +35,7 @@ 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 void publish_values(JsonObject & json, bool force);
|
||||
virtual bool export_values(JsonObject & json);
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual bool publish_ha_config();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
@@ -28,21 +28,9 @@ Generic::Generic(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
}
|
||||
|
||||
void Generic::device_info_web(JsonArray & root) {
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
void Generic::publish_values(JsonObject & json, bool force) {
|
||||
}
|
||||
|
||||
// export values to JSON
|
||||
bool Generic::export_values(JsonObject & json) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check to see if values have been updated
|
||||
bool Generic::updated_values() {
|
||||
return false;
|
||||
// publish HA config
|
||||
bool Generic::publish_ha_config() {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -35,10 +35,7 @@ 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 void publish_values(JsonObject & json, bool force);
|
||||
virtual bool export_values(JsonObject & json);
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual bool publish_ha_config();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
@@ -31,66 +31,23 @@ Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, c
|
||||
// telegram handlers
|
||||
register_telegram_type(0x042B, F("HP1"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor1(t); });
|
||||
register_telegram_type(0x047B, F("HP2"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor2(t); });
|
||||
|
||||
std::string empty("");
|
||||
register_device_value(empty, &airHumidity_, DeviceValueType::UINT, flash_string_vector{F("2")}, F("airHumidity"), F("Relative air humidity"), DeviceValueUOM::NONE);
|
||||
register_device_value(empty, &dewTemperature_, DeviceValueType::UINT, {}, F("dewTemperature"), F("Dew point temperature"), DeviceValueUOM::NONE);
|
||||
}
|
||||
|
||||
// creates JSON doc from values
|
||||
// returns false if empty
|
||||
bool Heatpump::export_values(JsonObject & json) {
|
||||
if (Helpers::hasValue(airHumidity_)) {
|
||||
json["airHumidity"] = (float)airHumidity_ / 2;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(dewTemperature_)) {
|
||||
json["dewTemperature"] = dewTemperature_;
|
||||
}
|
||||
|
||||
return json.size();
|
||||
}
|
||||
|
||||
void Heatpump::device_info_web(JsonArray & root) {
|
||||
// fetch the values into a JSON document
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_SMALL> doc;
|
||||
JsonObject json = doc.to<JsonObject>();
|
||||
if (!export_values(json)) {
|
||||
return; // empty
|
||||
}
|
||||
|
||||
create_value_json(root, F("airHumidity"), nullptr, F_(airHumidity), F_(percent), json);
|
||||
create_value_json(root, F("dewTemperature"), nullptr, F_(dewTemperature), F_(degrees), json);
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
void Heatpump::publish_values(JsonObject & json, bool force) {
|
||||
// handle HA first
|
||||
if (Mqtt::mqtt_format() == Mqtt::Format::HA) {
|
||||
if (!mqtt_ha_config_ || force) {
|
||||
register_mqtt_ha_config();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_SMALL> doc;
|
||||
JsonObject json_data = doc.to<JsonObject>();
|
||||
if (export_values(json_data)) {
|
||||
Mqtt::publish(F("heatpump_data"), doc.as<JsonObject>());
|
||||
}
|
||||
}
|
||||
|
||||
void Heatpump::register_mqtt_ha_config() {
|
||||
if (!Mqtt::connected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the Master device
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_HA_CONFIG> doc;
|
||||
doc["name"] = F_(EMSESP);
|
||||
// publish HA config
|
||||
bool Heatpump::publish_ha_config() {
|
||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||
doc["uniq_id"] = F_(heatpump);
|
||||
doc["ic"] = F_(iconheatpump);
|
||||
doc["ic"] = F_(iconvalve);
|
||||
|
||||
char stat_t[50];
|
||||
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/heatpump_data"), System::hostname().c_str());
|
||||
doc["stat_t"] = stat_t;
|
||||
|
||||
doc["name"] = FJSON("Humidity");
|
||||
doc["val_tpl"] = FJSON("{{value_json.airHumidity}}");
|
||||
|
||||
JsonObject dev = doc.createNestedObject("dev");
|
||||
@@ -100,21 +57,12 @@ void Heatpump::register_mqtt_ha_config() {
|
||||
dev["mdl"] = this->name();
|
||||
JsonArray ids = dev.createNestedArray("ids");
|
||||
ids.add("ems-esp-heatpump");
|
||||
Mqtt::publish_ha(F("homeassistant/sensor/ems-esp/heatpump/config"), doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(airHumidity), device_type(), "airHumidity", F_(percent), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(dewTemperature), device_type(), "dewTemperature", F_(degrees), nullptr);
|
||||
char topic[100];
|
||||
snprintf_P(topic, sizeof(topic), PSTR("homeassistant/sensor/%s/heatpump/config"), System::hostname().c_str());
|
||||
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
|
||||
mqtt_ha_config_ = true; // done
|
||||
}
|
||||
|
||||
// check to see if values have been updated
|
||||
bool Heatpump::updated_values() {
|
||||
if (changed_) {
|
||||
changed_ = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -122,8 +70,8 @@ bool Heatpump::updated_values() {
|
||||
* e.g. "38 10 FF 00 03 7B 08 24 00 4B"
|
||||
*/
|
||||
void Heatpump::process_HPMonitor2(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(dewTemperature_, 0);
|
||||
changed_ |= telegram->read_value(airHumidity_, 1);
|
||||
has_update(telegram->read_value(dewTemperature_, 0));
|
||||
has_update(telegram->read_value(airHumidity_, 1));
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
|
||||
@@ -36,21 +36,13 @@ 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 void publish_values(JsonObject & json, bool force);
|
||||
virtual bool export_values(JsonObject & json);
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual bool publish_ha_config();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void register_mqtt_ha_config();
|
||||
|
||||
uint8_t airHumidity_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t dewTemperature_ = EMS_VALUE_UINT_NOTSET;
|
||||
|
||||
bool changed_ = false;
|
||||
bool mqtt_ha_config_ = false; // for HA MQTT Discovery
|
||||
uint8_t airHumidity_;
|
||||
uint8_t dewTemperature_;
|
||||
|
||||
void process_HPMonitor1(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPMonitor2(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
@@ -55,103 +55,50 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
}
|
||||
}
|
||||
|
||||
// output json to web UI
|
||||
void Mixer::device_info_web(JsonArray & root) {
|
||||
if (type() == Type::NONE) {
|
||||
return; // don't have any values yet
|
||||
|
||||
// register values, depending on type (hc or wwc)
|
||||
void Mixer::register_values(const Type type, uint16_t hc) {
|
||||
if (type == Type::NONE) {
|
||||
return; // already done
|
||||
}
|
||||
|
||||
// fetch the values into a JSON document
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_SMALL> doc;
|
||||
JsonObject json = doc.to<JsonObject>();
|
||||
// store the heating circuit and type
|
||||
hc_ = hc + 1;
|
||||
type_ = type;
|
||||
|
||||
if (!export_values_format(Mqtt::Format::SINGLE, json)) {
|
||||
return; // empty
|
||||
}
|
||||
std::string prefix(10, '\0');
|
||||
snprintf_P(&prefix[0], sizeof(prefix), PSTR("%s%d"), (type_ == Type::HC) ? "hc" : "wwc", hc + 1);
|
||||
|
||||
char prefix_str[10];
|
||||
if (type() == Type::HC) {
|
||||
snprintf_P(prefix_str, sizeof(prefix_str), PSTR("(hc %d) "), hc_);
|
||||
create_value_json(root, F("flowTemp"), FPSTR(prefix_str), F_(flowTemp), F_(degrees), json);
|
||||
create_value_json(root, F("flowSetTemp"), FPSTR(prefix_str), F_(flowSetTemp), F_(degrees), json);
|
||||
create_value_json(root, F("pumpStatus"), FPSTR(prefix_str), F_(pumpStatus), nullptr, json);
|
||||
create_value_json(root, F("valveStatus"), FPSTR(prefix_str), F_(valveStatus), F_(percent), json);
|
||||
} else {
|
||||
snprintf_P(prefix_str, sizeof(prefix_str), PSTR("(wwc %d) "), hc_);
|
||||
create_value_json(root, F("wwTemp"), FPSTR(prefix_str), F_(wwTemp), F_(degrees), json);
|
||||
create_value_json(root, F("pumpStatus"), FPSTR(prefix_str), F_(pumpStatus), nullptr, json);
|
||||
create_value_json(root, F("tempStatus"), FPSTR(prefix_str), F_(tempStatus), nullptr, json);
|
||||
}
|
||||
register_device_value(
|
||||
prefix, &flowTemp_, DeviceValueType::USHORT, flash_string_vector{F("10")}, F("flowTemp"), F("Current flow temperature"), DeviceValueUOM::DEGREES);
|
||||
register_device_value(prefix, &flowSetTemp_, DeviceValueType::UINT, {}, F("flowSetTemp"), F("Setpoint flow temperature"), DeviceValueUOM::DEGREES);
|
||||
register_device_value(prefix, &pumpStatus_, DeviceValueType::BOOL, {}, F("pumpStatus"), F("Pump/Valve status"), DeviceValueUOM::NONE);
|
||||
register_device_value(prefix, &status_, DeviceValueType::INT, {}, F("status"), F("Current status"), DeviceValueUOM::NONE);
|
||||
}
|
||||
|
||||
// check to see if values have been updated
|
||||
bool Mixer::updated_values() {
|
||||
if (changed_) {
|
||||
changed_ = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
// topic is mixer_data<id>
|
||||
void Mixer::publish_values(JsonObject & json, bool force) {
|
||||
// handle HA first
|
||||
if (Mqtt::mqtt_format() == Mqtt::Format::HA) {
|
||||
if (!mqtt_ha_config_ || force) {
|
||||
register_mqtt_ha_config();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Mqtt::mqtt_format() == Mqtt::Format::SINGLE) {
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_SMALL> doc;
|
||||
JsonObject json_data = doc.to<JsonObject>();
|
||||
if (export_values_format(Mqtt::mqtt_format(), json_data)) {
|
||||
char topic[30];
|
||||
if (type() == Type::HC) {
|
||||
snprintf_P(topic, 30, PSTR("mixer_data_hc%d"), hc_);
|
||||
} else {
|
||||
snprintf_P(topic, 30, PSTR("mixer_data_wwc%d"), hc_);
|
||||
}
|
||||
Mqtt::publish(topic, doc.as<JsonObject>());
|
||||
}
|
||||
} else {
|
||||
// format is HA or Nested. This is bundled together and sent in emsesp.cpp
|
||||
export_values_format(Mqtt::mqtt_format(), json);
|
||||
}
|
||||
}
|
||||
|
||||
// publish config topic for HA MQTT Discovery
|
||||
void Mixer::register_mqtt_ha_config() {
|
||||
if (!Mqtt::connected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// publish HA config
|
||||
bool Mixer::publish_ha_config() {
|
||||
// if we don't have valid values for this HC don't add it ever again
|
||||
if (!Helpers::hasValue(pumpStatus_)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the Master device
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_HA_CONFIG> doc;
|
||||
|
||||
char name[20];
|
||||
snprintf_P(name, sizeof(name), PSTR("Mixer %02X"), device_id() - 0x20 + 1);
|
||||
doc["name"] = name;
|
||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||
|
||||
char uniq_id[20];
|
||||
snprintf_P(uniq_id, sizeof(uniq_id), PSTR("mixer%02X"), device_id() - 0x20 + 1);
|
||||
snprintf_P(uniq_id, sizeof(uniq_id), PSTR("Mixer%02X"), device_id() - 0x20 + 1);
|
||||
doc["uniq_id"] = uniq_id;
|
||||
|
||||
doc["ic"] = FJSON("mdi:home-thermometer-outline");
|
||||
|
||||
char stat_t[50];
|
||||
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/mixer_data"), System::hostname().c_str());
|
||||
doc["stat_t"] = stat_t;
|
||||
|
||||
doc["val_tpl"] = FJSON("{{value_json.type}}"); // HA needs a single value. We take the type which is wwc or hc
|
||||
char name[20];
|
||||
snprintf_P(name, sizeof(name), PSTR("Mixer %02X Type"), device_id() - 0x20 + 1);
|
||||
doc["name"] = name;
|
||||
|
||||
doc["val_tpl"] = FJSON("{{value_json.type}}"); // HA needs a single value. We take the type which is wwc or hc
|
||||
JsonObject dev = doc.createNestedObject("dev");
|
||||
dev["name"] = FJSON("EMS-ESP Mixer");
|
||||
dev["sw"] = EMSESP_APP_VERSION;
|
||||
@@ -160,127 +107,45 @@ void Mixer::register_mqtt_ha_config() {
|
||||
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(100, '\0');
|
||||
if (type() == Type::HC) {
|
||||
snprintf_P(&topic[0], topic.capacity() + 1, PSTR("homeassistant/sensor/ems-esp/mixer_hc%d/config"), hc_);
|
||||
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
char hc_name[10];
|
||||
snprintf_P(hc_name, sizeof(hc_name), PSTR("hc%d"), hc_);
|
||||
Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(flowTemp), device_type(), "flowTemp", F_(degrees), F_(icontemperature));
|
||||
Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(flowSetTemp), device_type(), "flowSetTemp", F_(degrees), F_(icontemperature));
|
||||
Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(pumpStatus), device_type(), "pumpStatus", nullptr, nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(hc_name, nullptr, F_(valveStatus), device_type(), "valveStatus", F_(percent), F_(iconpercent));
|
||||
if (type_ == Type::HC) {
|
||||
snprintf_P(&topic[0], topic.capacity() + 1, PSTR("homeassistant/sensor/%s/mixer_hc%d/config"), System::hostname().c_str(), hc_);
|
||||
} else {
|
||||
// WWC
|
||||
snprintf_P(&topic[0], topic.capacity() + 1, PSTR("homeassistant/sensor/ems-esp/mixer_wwc%d/config"), hc_);
|
||||
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
char wwc_name[10];
|
||||
snprintf_P(wwc_name, sizeof(wwc_name), PSTR("wwc%d"), hc_);
|
||||
Mqtt::register_mqtt_ha_sensor(wwc_name, nullptr, F_(wwTemp), device_type(), "wwTemp", F_(degrees), F_(icontemperature));
|
||||
Mqtt::register_mqtt_ha_sensor(wwc_name, nullptr, F_(pumpStatus), device_type(), "pumpStatus", nullptr, nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(wwc_name, nullptr, F_(tempStatus), device_type(), "tempStatus", nullptr, nullptr);
|
||||
snprintf_P(&topic[0], topic.capacity() + 1, PSTR("homeassistant/sensor/%s/mixer_wwc%d/config"), System::hostname().c_str(), hc_); // WWC
|
||||
}
|
||||
|
||||
mqtt_ha_config_ = true; // done
|
||||
}
|
||||
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
|
||||
bool Mixer::export_values(JsonObject & json) {
|
||||
return export_values_format(Mqtt::Format::NESTED, json);
|
||||
}
|
||||
|
||||
// creates JSON doc from values
|
||||
// returns false if empty
|
||||
bool Mixer::export_values_format(uint8_t mqtt_format, JsonObject & json) {
|
||||
// check if there is data for the mixer unit
|
||||
if (type() == Type::NONE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
JsonObject json_hc;
|
||||
char hc_name[10]; // hc{1-4}
|
||||
|
||||
if (type() == Type::HC) {
|
||||
snprintf_P(hc_name, sizeof(hc_name), PSTR("hc%d"), hc_);
|
||||
if (mqtt_format == Mqtt::Format::SINGLE) {
|
||||
json_hc = json;
|
||||
json["type"] = FJSON("hc");
|
||||
} else if (mqtt_format == Mqtt::Format::HA) {
|
||||
json_hc = json.createNestedObject(hc_name);
|
||||
json_hc["type"] = FJSON("hc");
|
||||
} else {
|
||||
json_hc = json.createNestedObject(hc_name);
|
||||
}
|
||||
if (Helpers::hasValue(flowTemp_)) {
|
||||
json_hc["flowTemp"] = (float)flowTemp_ / 10;
|
||||
}
|
||||
if (Helpers::hasValue(flowSetTemp_)) {
|
||||
json_hc["flowSetTemp"] = flowSetTemp_;
|
||||
}
|
||||
if (Helpers::hasValue(pumpStatus_)) {
|
||||
char s[7];
|
||||
json_hc["pumpStatus"] = Helpers::render_value(s, pumpStatus_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(status_)) {
|
||||
json_hc["valveStatus"] = status_;
|
||||
}
|
||||
|
||||
return json_hc.size();
|
||||
}
|
||||
|
||||
// WWC
|
||||
snprintf_P(hc_name, sizeof(hc_name), PSTR("wwc%d"), hc_);
|
||||
if (mqtt_format == Mqtt::Format::SINGLE) {
|
||||
json_hc = json;
|
||||
json["type"] = FJSON("wwc");
|
||||
} else if (mqtt_format == Mqtt::Format::HA) {
|
||||
json_hc = json.createNestedObject(hc_name);
|
||||
json_hc["type"] = FJSON("wwc");
|
||||
} else {
|
||||
json_hc = json.createNestedObject(hc_name);
|
||||
}
|
||||
if (Helpers::hasValue(flowTemp_)) {
|
||||
json_hc["wwTemp"] = (float)flowTemp_ / 10;
|
||||
}
|
||||
if (Helpers::hasValue(pumpStatus_)) {
|
||||
char s[7];
|
||||
json_hc["pumpStatus"] = Helpers::render_value(s, pumpStatus_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(status_)) {
|
||||
json_hc["tempStatus"] = status_;
|
||||
}
|
||||
|
||||
return json_hc.size();
|
||||
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) {
|
||||
type(Type::HC);
|
||||
hc_ = telegram->type_id - 0x02D7 + 1; // determine which circuit this is
|
||||
changed_ |= telegram->read_value(flowTemp_, 3); // is * 10
|
||||
changed_ |= telegram->read_value(flowSetTemp_, 5);
|
||||
changed_ |= telegram->read_bitvalue(pumpStatus_, 0, 0);
|
||||
changed_ |= telegram->read_value(status_, 2); // valve status
|
||||
register_values(Type::HC, telegram->type_id - 0x02D7);
|
||||
has_update(telegram->read_value(flowTemp_, 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
|
||||
}
|
||||
|
||||
// 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) {
|
||||
type(Type::WWC);
|
||||
hc_ = telegram->type_id - 0x0331 + 1; // determine which circuit this is. There are max 2.
|
||||
changed_ |= telegram->read_value(flowTemp_, 0); // is * 10
|
||||
changed_ |= telegram->read_bitvalue(pumpStatus_, 2, 0);
|
||||
changed_ |= telegram->read_value(status_, 11); // temp status
|
||||
register_values(Type::WWC, telegram->type_id - 0x0331);
|
||||
has_update(telegram->read_value(flowTemp_, 0)); // is * 10
|
||||
has_update(telegram->read_bitvalue(pumpStatus_, 2, 0));
|
||||
has_update(telegram->read_value(status_, 11)); // temp status
|
||||
}
|
||||
|
||||
// Mixer IMP - 0x010C
|
||||
// e.g. A0 00 FF 00 00 0C 01 00 00 00 00 00 54
|
||||
// A1 00 FF 00 00 0C 02 04 00 01 1D 00 82
|
||||
void Mixer::process_IPMStatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
type(Type::HC);
|
||||
hc_ = device_id() - 0x20 + 1;
|
||||
register_values(Type::HC, device_id() - 0x20);
|
||||
|
||||
// check if circuit is active, 0-off, 1-unmixed, 2-mixed
|
||||
uint8_t ismixed = 0;
|
||||
@@ -291,28 +156,27 @@ void Mixer::process_IPMStatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// do we have a mixed circuit
|
||||
if (ismixed == 2) {
|
||||
changed_ |= telegram->read_value(flowTemp_, 3); // is * 10
|
||||
changed_ |= telegram->read_value(flowSetTemp_, 5);
|
||||
changed_ |= telegram->read_value(status_, 2); // valve status
|
||||
has_update(telegram->read_value(flowTemp_, 3)); // is * 10
|
||||
has_update(telegram->read_value(flowSetTemp_, 5));
|
||||
has_update(telegram->read_value(status_, 2)); // valve status
|
||||
}
|
||||
|
||||
changed_ |= telegram->read_bitvalue(pumpStatus_, 1, 0); // pump is also in unmixed circuits
|
||||
has_update(telegram->read_bitvalue(pumpStatus_, 1, 0)); // pump is also in unmixed circuits
|
||||
}
|
||||
|
||||
// Mixer on a MM10 - 0xAB
|
||||
// e.g. Mixer Module -> All, type 0xAB, telegram: 21 00 AB 00 2D 01 BE 64 04 01 00 (CRC=15) #data=7
|
||||
// see also https://github.com/proddy/EMS-ESP/issues/386
|
||||
void Mixer::process_MMStatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
type(Type::HC);
|
||||
|
||||
// the heating circuit is determine by which device_id it is, 0x20 - 0x23
|
||||
// 0x21 is position 2. 0x20 is typically reserved for the WM10 switch module
|
||||
// see https://github.com/proddy/EMS-ESP/issues/270 and https://github.com/proddy/EMS-ESP/issues/386#issuecomment-629610918
|
||||
hc_ = device_id() - 0x20 + 1;
|
||||
changed_ |= telegram->read_value(flowTemp_, 1); // is * 10
|
||||
changed_ |= telegram->read_bitvalue(pumpStatus_, 3, 2); // is 0 or 0x64 (100%), check only bit 2
|
||||
changed_ |= telegram->read_value(flowSetTemp_, 0);
|
||||
changed_ |= telegram->read_value(status_, 4); // valve status -100 to 100
|
||||
register_values(Type::HC, device_id() - 0x20);
|
||||
|
||||
has_update(telegram->read_value(flowTemp_, 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
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
@@ -321,7 +185,7 @@ void Mixer::process_MMStatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
// 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) {
|
||||
hc_ = device_id() - 0x20 + 1;
|
||||
register_values(Type::HC, device_id() - 0x20);
|
||||
// pos 0: active FF = on
|
||||
// pos 1: valve runtime 0C = 120 sec in units of 10 sec
|
||||
}
|
||||
@@ -329,7 +193,7 @@ void Mixer::process_MMConfigMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
// 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) {
|
||||
hc_ = device_id() - 0x20 + 1;
|
||||
register_values(Type::HC, device_id() - 0x20);
|
||||
// pos 0: flowtemp setpoint 1E = 30°C
|
||||
// pos 1: position in %
|
||||
}
|
||||
|
||||
@@ -36,17 +36,11 @@ 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 void publish_values(JsonObject & json, bool force);
|
||||
virtual bool export_values(JsonObject & json);
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual bool publish_ha_config();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
bool export_values_format(uint8_t mqtt_format, JsonObject & doc);
|
||||
void register_mqtt_ha_config();
|
||||
|
||||
void process_MMPLUSStatusMessage_HC(std::shared_ptr<const Telegram> telegram);
|
||||
void process_MMPLUSStatusMessage_WWC(std::shared_ptr<const Telegram> telegram);
|
||||
void process_IPMStatusMessage(std::shared_ptr<const Telegram> telegram);
|
||||
@@ -60,25 +54,15 @@ class Mixer : public EMSdevice {
|
||||
WWC // warm water circuit
|
||||
};
|
||||
|
||||
Type type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
void type(Type new_type) {
|
||||
type_ = new_type;
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t hc_ = EMS_VALUE_USHORT_NOTSET;
|
||||
uint16_t flowTemp_ = EMS_VALUE_USHORT_NOTSET;
|
||||
uint8_t pumpStatus_ = EMS_VALUE_UINT_NOTSET;
|
||||
int8_t status_ = EMS_VALUE_INT_NOTSET;
|
||||
uint8_t flowSetTemp_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint16_t flowTemp_;
|
||||
uint8_t pumpStatus_;
|
||||
int8_t status_;
|
||||
uint8_t flowSetTemp_;
|
||||
|
||||
Type type_ = Type::NONE;
|
||||
|
||||
bool changed_ = false;
|
||||
bool mqtt_ha_config_ = false; // for HA MQTT Discovery
|
||||
void register_values(const Type type, const uint16_t hc);
|
||||
Type type_ = Type::NONE;
|
||||
uint16_t hc_ = EMS_VALUE_USHORT_NOTSET;
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -59,67 +59,62 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
register_telegram_type(0x0103, F("ISM1StatusMessage"), true, [&](std::shared_ptr<const Telegram> t) { process_ISM1StatusMessage(t); });
|
||||
register_telegram_type(0x0101, F("ISM1Set"), false, [&](std::shared_ptr<const Telegram> t) { process_ISM1Set(t); });
|
||||
}
|
||||
|
||||
std::string empty("");
|
||||
|
||||
// special case for a device_id with 0x2A where it's not actual a solar module
|
||||
if (device_id == 0x2A) {
|
||||
register_device_value(empty, &type_, DeviceValueType::TEXT, {}, F("type"), F("Type"), DeviceValueUOM::NONE);
|
||||
strncpy(type_, "warm water circuit", sizeof(type_));
|
||||
}
|
||||
|
||||
register_device_value(empty,
|
||||
&collectorTemp_,
|
||||
DeviceValueType::SHORT,
|
||||
flash_string_vector{F("10")},
|
||||
F("collectorTemp"),
|
||||
F("Collector temperature (TS1)"),
|
||||
DeviceValueUOM::DEGREES);
|
||||
register_device_value(empty,
|
||||
&tankBottomTemp_,
|
||||
DeviceValueType::SHORT,
|
||||
flash_string_vector{F("10")},
|
||||
F("tankBottomTemp"),
|
||||
F("Bottom temperature (TS2)"),
|
||||
DeviceValueUOM::DEGREES);
|
||||
register_device_value(empty,
|
||||
&tankBottomTemp2_,
|
||||
DeviceValueType::SHORT,
|
||||
flash_string_vector{F("10")},
|
||||
F("tankBottomTemp2"),
|
||||
F("Bottom temperature (TS5)"),
|
||||
DeviceValueUOM::DEGREES);
|
||||
register_device_value(
|
||||
empty, &heatExchangerTemp_, DeviceValueType::SHORT, {F("10")}, F("heatExchangerTemp"), F("Heat exchanger temperature (TS6)"), DeviceValueUOM::DEGREES);
|
||||
|
||||
register_device_value(empty, &tank1MaxTempCurrent_, DeviceValueType::UINT, {}, F("tank1MaxTempCurrent"), F("Maximum Tank temperature"), DeviceValueUOM::NONE);
|
||||
register_device_value(empty, &solarPumpModulation_, DeviceValueType::UINT, {}, F("solarPumpModulation"), F("Solar pump modulation (PS1)"), DeviceValueUOM::PERCENT);
|
||||
register_device_value(
|
||||
empty, &cylinderPumpModulation_, DeviceValueType::UINT, {}, F("cylinderPumpModulation"), F("Cylinder pump modulation (PS5)"), DeviceValueUOM::PERCENT);
|
||||
|
||||
register_device_value(empty, &solarPump_, DeviceValueType::BOOL, {}, F("solarPump"), F("Solar pump (PS1) active"), DeviceValueUOM::NONE);
|
||||
register_device_value(empty, &valveStatus_, DeviceValueType::BOOL, {}, F("valveStatus"), F("Valve status"), DeviceValueUOM::NONE);
|
||||
register_device_value(empty, &tankHeated_, DeviceValueType::BOOL, {}, F("tankHeated"), F("Tank heated"), DeviceValueUOM::NONE);
|
||||
register_device_value(empty, &collectorShutdown_, DeviceValueType::BOOL, {}, F("collectorShutdown"), F("Collector shutdown"), DeviceValueUOM::NONE);
|
||||
|
||||
register_device_value(empty, &pumpWorkMin_, DeviceValueType::TIME, {}, F("pumpWorkMin"), F("Pump working time"), DeviceValueUOM::MINUTES);
|
||||
|
||||
register_device_value(
|
||||
empty, &energyLastHour_, DeviceValueType::ULONG, flash_string_vector{F("10")}, F("energyLastHour"), F("Energy last hour"), DeviceValueUOM::WH);
|
||||
register_device_value(empty, &energyTotal_, DeviceValueType::ULONG, flash_string_vector{F("10")}, F("energyTotal"), F("Energy total"), DeviceValueUOM::KWH);
|
||||
register_device_value(empty, &energyToday_, DeviceValueType::ULONG, {}, F("energyToday"), F("Energy today"), DeviceValueUOM::WH);
|
||||
}
|
||||
|
||||
// print to web
|
||||
void Solar::device_info_web(JsonArray & root) {
|
||||
// fetch the values into a JSON document
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
|
||||
JsonObject json = doc.to<JsonObject>();
|
||||
if (!export_values(json)) {
|
||||
return; // empty
|
||||
}
|
||||
|
||||
create_value_json(root, F("collectorTemp"), nullptr, F_(collectorTemp), F_(degrees), json);
|
||||
create_value_json(root, F("tankBottomTemp"), nullptr, F_(tankBottomTemp), F_(degrees), json);
|
||||
create_value_json(root, F("tankBottomTemp2"), nullptr, F_(tankBottomTemp2), F_(degrees), json);
|
||||
create_value_json(root, F("tank1MaxTempCurrent"), nullptr, F_(tank1MaxTempCurrent), F_(degrees), json);
|
||||
create_value_json(root, F("heatExchangerTemp"), nullptr, F_(heatExchangerTemp), F_(degrees), json);
|
||||
create_value_json(root, F("solarPumpModulation"), nullptr, F_(solarPumpModulation), F_(percent), json);
|
||||
create_value_json(root, F("cylinderPumpModulation"), nullptr, F_(cylinderPumpModulation), F_(percent), json);
|
||||
create_value_json(root, F("valveStatus"), nullptr, F_(valveStatus), nullptr, json);
|
||||
create_value_json(root, F("solarPump"), nullptr, F_(solarPump), nullptr, json);
|
||||
create_value_json(root, F("tankHeated"), nullptr, F_(tankHeated), nullptr, json);
|
||||
create_value_json(root, F("collectorShutdown"), nullptr, F_(collectorShutdown), nullptr, json);
|
||||
create_value_json(root, F("energyLastHour"), nullptr, F_(energyLastHour), F_(wh), json);
|
||||
create_value_json(root, F("energyToday"), nullptr, F_(energyToday), F_(wh), json);
|
||||
create_value_json(root, F("energyTotal"), nullptr, F_(energyTotal), F_(kwh), json);
|
||||
create_value_json(root, F("pumpWorkMin"), nullptr, F_(pumpWorkMin), F_(min), json);
|
||||
create_value_json(root, F("pumpWorkMintxt"), nullptr, F_(pumpWorkMintxt), F_(min), json);
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
void Solar::publish_values(JsonObject & json, bool force) {
|
||||
// handle HA first
|
||||
if (Mqtt::mqtt_format() == Mqtt::Format::HA) {
|
||||
if ((!mqtt_ha_config_ || force)) {
|
||||
register_mqtt_ha_config();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
|
||||
JsonObject json_payload = doc.to<JsonObject>();
|
||||
if (export_values(json_payload)) {
|
||||
if (device_id() == 0x2A) {
|
||||
Mqtt::publish(F("ww_data"), doc.as<JsonObject>());
|
||||
} else {
|
||||
Mqtt::publish(F("solar_data"), doc.as<JsonObject>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// publish config topic for HA MQTT Discovery
|
||||
void Solar::register_mqtt_ha_config() {
|
||||
if (!Mqtt::connected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the Master device
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_HA_CONFIG> doc;
|
||||
doc["name"] = F_(EMSESP);
|
||||
// publish HA config
|
||||
bool Solar::publish_ha_config() {
|
||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||
doc["name"] = FJSON("Solar Status");
|
||||
doc["uniq_id"] = F_(solar);
|
||||
doc["ic"] = F_(iconthermostat);
|
||||
|
||||
char stat_t[50];
|
||||
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/solar_data"), System::hostname().c_str());
|
||||
@@ -133,113 +128,21 @@ void Solar::register_mqtt_ha_config() {
|
||||
dev["mdl"] = name();
|
||||
JsonArray ids = dev.createNestedArray("ids");
|
||||
ids.add("ems-esp-solar");
|
||||
Mqtt::publish_ha(F("homeassistant/sensor/ems-esp/solar/config"), doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(collectorTemp), device_type(), "collectorTemp", F_(degrees), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(tankBottomTemp), device_type(), "tankBottomTemp", F_(degrees), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(tankBottomTemp2), device_type(), "tankBottomTemp2", F_(degrees), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(tank1MaxTempCurrent), device_type(), "tank1MaxTempCurrent", F_(degrees), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(heatExchangerTemp), device_type(), "heatExchangerTemp", F_(degrees), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(solarPumpModulation), device_type(), "solarPumpModulation", F_(percent), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(cylinderPumpModulation), device_type(), "cylinderPumpModulation", F_(percent), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(pumpWorkMin), device_type(), "pumpWorkMin", F_(min), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(energyLastHour), device_type(), "energyLastHour", F_(wh), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(energyToday), device_type(), "energyToday", F_(wh), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(energyTotal), device_type(), "energyTotal", F_(kwh), nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(solarPump), device_type(), "solarPump", nullptr, nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(valveStatus), device_type(), "valveStatus", nullptr, nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(tankHeated), device_type(), "tankHeated", nullptr, nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(collectorShutdown), device_type(), "collectorShutdown", nullptr, nullptr);
|
||||
char topic[100];
|
||||
snprintf_P(topic, sizeof(topic), PSTR("homeassistant/sensor/%s/solar/config"), System::hostname().c_str());
|
||||
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
|
||||
mqtt_ha_config_ = true; // done
|
||||
}
|
||||
|
||||
// creates JSON doc from values
|
||||
// returns false if empty
|
||||
bool Solar::export_values(JsonObject & json) {
|
||||
char s[10]; // for formatting strings
|
||||
|
||||
if (Helpers::hasValue(collectorTemp_)) {
|
||||
json["collectorTemp"] = (float)collectorTemp_ / 10;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(tankBottomTemp_)) {
|
||||
json["tankBottomTemp"] = (float)tankBottomTemp_ / 10;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(tankBottomTemp2_)) {
|
||||
json["tankBottomTemp2"] = (float)tankBottomTemp2_ / 10;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(tank1MaxTempCurrent_)) {
|
||||
json["tank1MaxTempCurrent"] = tank1MaxTempCurrent_;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(heatExchangerTemp_)) {
|
||||
json["heatExchangerTemp"] = (float)heatExchangerTemp_ / 10;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(solarPumpModulation_)) {
|
||||
json["solarPumpModulation"] = solarPumpModulation_;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(cylinderPumpModulation_)) {
|
||||
json["cylinderPumpModulation"] = cylinderPumpModulation_;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(solarPump_, EMS_VALUE_BOOL)) {
|
||||
json["solarPump"] = Helpers::render_value(s, solarPump_, EMS_VALUE_BOOL);
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(valveStatus_, EMS_VALUE_BOOL)) {
|
||||
json["valveStatus"] = Helpers::render_value(s, valveStatus_, EMS_VALUE_BOOL);
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(pumpWorkMin_)) {
|
||||
json["pumpWorkMin"] = pumpWorkMin_;
|
||||
char slong[40];
|
||||
json["pumpWorkMintxt"] = Helpers::render_value(slong, pumpWorkMin_, EMS_VALUE_TIME);
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(tankHeated_, EMS_VALUE_BOOL)) {
|
||||
json["tankHeated"] = Helpers::render_value(s, tankHeated_, EMS_VALUE_BOOL);
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(collectorShutdown_, EMS_VALUE_BOOL)) {
|
||||
json["collectorShutdown"] = Helpers::render_value(s, collectorShutdown_, EMS_VALUE_BOOL);
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(energyLastHour_)) {
|
||||
json["energyLastHour"] = (float)energyLastHour_ / 10;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(energyToday_)) {
|
||||
json["energyToday"] = energyToday_;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(energyTotal_)) {
|
||||
json["energyTotal"] = (float)energyTotal_ / 10;
|
||||
}
|
||||
|
||||
return json.size();
|
||||
}
|
||||
|
||||
// check to see if values have been updated
|
||||
bool Solar::updated_values() {
|
||||
if (changed_) {
|
||||
changed_ = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// SM10Monitor - type 0x97
|
||||
void Solar::process_SM10Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(collectorTemp_, 2); // collector temp from SM10, is *10
|
||||
changed_ |= telegram->read_value(tankBottomTemp_, 5); // bottom temp from SM10, is *10
|
||||
changed_ |= telegram->read_value(solarPumpModulation_, 4); // modulation solar pump
|
||||
changed_ |= telegram->read_bitvalue(solarPump_, 7, 1);
|
||||
changed_ |= telegram->read_value(pumpWorkMin_, 8, 3);
|
||||
has_update(telegram->read_value(collectorTemp_, 2)); // collector temp from SM10, is *10
|
||||
has_update(telegram->read_value(tankBottomTemp_, 5)); // bottom temp from SM10, is *10
|
||||
has_update(telegram->read_value(solarPumpModulation_, 4)); // modulation solar pump
|
||||
has_update(telegram->read_bitvalue(solarPump_, 7, 1));
|
||||
has_update(telegram->read_value(pumpWorkMin_, 8, 3));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -247,11 +150,11 @@ void Solar::process_SM10Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
* e.g. B0 0B FF 00 02 58 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00 FF 01 00 00
|
||||
*/
|
||||
void Solar::process_SM100SystemConfig(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(heatTransferSystem_, 5, 1);
|
||||
changed_ |= telegram->read_value(externalTank_, 9, 1);
|
||||
changed_ |= telegram->read_value(thermalDisinfect_, 10, 1);
|
||||
changed_ |= telegram->read_value(heatMetering_, 14, 1);
|
||||
changed_ |= telegram->read_value(solarIsEnabled_, 19, 1);
|
||||
has_update(telegram->read_value(heatTransferSystem_, 5, 1));
|
||||
has_update(telegram->read_value(externalTank_, 9, 1));
|
||||
has_update(telegram->read_value(thermalDisinfect_, 10, 1));
|
||||
has_update(telegram->read_value(heatMetering_, 14, 1));
|
||||
has_update(telegram->read_value(solarIsEnabled_, 19, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -259,16 +162,16 @@ void Solar::process_SM100SystemConfig(std::shared_ptr<const Telegram> telegram)
|
||||
* e.g. B0 0B FF 00 02 5A 64 05 00 58 14 01 01 32 64 00 00 00 5A 0C
|
||||
*/
|
||||
void Solar::process_SM100SolarCircuitConfig(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(collectorTempMax_, 0, 1);
|
||||
changed_ |= telegram->read_value(tank1MaxTempCurrent_, 3, 1);
|
||||
changed_ |= telegram->read_value(collectorTempMin_, 4, 1);
|
||||
changed_ |= telegram->read_value(solarPumpMode_, 5, 1);
|
||||
changed_ |= telegram->read_value(solarPumpMinRPM_, 6, 1);
|
||||
changed_ |= telegram->read_value(solarPumpTurnoffDiff_, 7, 1);
|
||||
changed_ |= telegram->read_value(solarPumpTurnonDiff_, 8, 1);
|
||||
changed_ |= telegram->read_value(solarPumpKick_, 9, 1);
|
||||
changed_ |= telegram->read_value(plainWaterMode_, 10, 1);
|
||||
changed_ |= telegram->read_value(doubleMatchFlow_, 11, 1);
|
||||
has_update(telegram->read_value(collectorTempMax_, 0, 1));
|
||||
has_update(telegram->read_value(tank1MaxTempCurrent_, 3, 1));
|
||||
has_update(telegram->read_value(collectorTempMin_, 4, 1));
|
||||
has_update(telegram->read_value(solarPumpMode_, 5, 1));
|
||||
has_update(telegram->read_value(solarPumpMinRPM_, 6, 1));
|
||||
has_update(telegram->read_value(solarPumpTurnoffDiff_, 7, 1));
|
||||
has_update(telegram->read_value(solarPumpTurnonDiff_, 8, 1));
|
||||
has_update(telegram->read_value(solarPumpKick_, 9, 1));
|
||||
has_update(telegram->read_value(plainWaterMode_, 10, 1));
|
||||
has_update(telegram->read_value(doubleMatchFlow_, 11, 1));
|
||||
}
|
||||
|
||||
/* process_SM100ParamCfg - type 0xF9 EMS 1.0
|
||||
@@ -290,14 +193,14 @@ void Solar::process_SM100ParamCfg(std::shared_ptr<const Telegram> telegram) {
|
||||
uint16_t t_id;
|
||||
uint8_t of;
|
||||
int32_t min, def, max, cur;
|
||||
telegram->read_value(t_id, 1);
|
||||
telegram->read_value(of, 3);
|
||||
telegram->read_value(min, 5);
|
||||
telegram->read_value(def, 9);
|
||||
telegram->read_value(max, 13);
|
||||
telegram->read_value(cur, 17);
|
||||
has_update(telegram->read_value(t_id, 1));
|
||||
has_update(telegram->read_value(of, 3));
|
||||
has_update(telegram->read_value(min, 5));
|
||||
has_update(telegram->read_value(def, 9));
|
||||
has_update(telegram->read_value(max, 13));
|
||||
has_update(telegram->read_value(cur, 17));
|
||||
|
||||
// LOG_DEBUG(F("SM100ParamCfg param=0x%04X, offset=%d, min=%d, default=%d, max=%d, current=%d"), t_id, of, min, def, max, cur);
|
||||
// LOG_DEBUG(F("SM100ParamCfg param=0x%04X, offset=%d, min=%d, default=%d, max=%d, current=%d"), t_id, of, min, def, max, cur));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -312,10 +215,10 @@ void Solar::process_SM100ParamCfg(std::shared_ptr<const Telegram> telegram) {
|
||||
* bytes 20+21 = TS6 Temperature sensor external heat exchanger
|
||||
*/
|
||||
void Solar::process_SM100Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(collectorTemp_, 0); // is *10 - TS1: Temperature sensor for collector array 1
|
||||
changed_ |= telegram->read_value(tankBottomTemp_, 2); // is *10 - TS2: Temperature sensor 1 cylinder, bottom
|
||||
changed_ |= telegram->read_value(tankBottomTemp2_, 16); // is *10 - TS5: Temperature sensor 2 cylinder, bottom, or swimming pool
|
||||
changed_ |= telegram->read_value(heatExchangerTemp_, 20); // is *10 - TS6: Heat exchanger temperature sensor
|
||||
has_update(telegram->read_value(collectorTemp_, 0)); // is *10 - TS1: Temperature sensor for collector array 1
|
||||
has_update(telegram->read_value(tankBottomTemp_, 2)); // is *10 - TS2: Temperature sensor 1 cylinder, bottom
|
||||
has_update(telegram->read_value(tankBottomTemp2_, 16)); // is *10 - TS5: Temperature sensor 2 cylinder, bottom, or swimming pool
|
||||
has_update(telegram->read_value(heatExchangerTemp_, 20)); // is *10 - TS6: Heat exchanger temperature sensor
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
@@ -330,17 +233,17 @@ void Solar::process_SM100Monitor2(std::shared_ptr<const Telegram> telegram) {
|
||||
// SM100wwTemperatur - 0x07D6
|
||||
// Solar Module(0x2A) -> (0x00), (0x7D6), data: 01 C1 00 00 02 5B 01 AF 01 AD 80 00 01 90
|
||||
void Solar::process_SM100wwTemperature(std::shared_ptr<const Telegram> telegram) {
|
||||
// changed_ |= telegram->read_value(wwTemp_1_, 0);
|
||||
// changed_ |= telegram->read_value(wwTemp_3_, 4);
|
||||
// changed_ |= telegram->read_value(wwTemp_4_, 6);
|
||||
// changed_ |= telegram->read_value(wwTemp_5_, 8);
|
||||
// changed_ |= telegram->read_value(wwTemp_7_, 12);
|
||||
// has_update(telegram->read_value(wwTemp_1_, 0));
|
||||
// has_update(telegram->read_value(wwTemp_3_, 4));
|
||||
// has_update(telegram->read_value(wwTemp_4_, 6));
|
||||
// has_update(telegram->read_value(wwTemp_5_, 8));
|
||||
// has_update(telegram->read_value(wwTemp_7_, 12));
|
||||
}
|
||||
|
||||
// SM100wwStatus - 0x07AA
|
||||
// Solar Module(0x2A) -> (0x00), (0x7AA), data: 64 00 04 00 03 00 28 01 0F
|
||||
void Solar::process_SM100wwStatus(std::shared_ptr<const Telegram> telegram) {
|
||||
// changed_ |= telegram->read_value(wwPump_, 0);
|
||||
// has_update(telegram->read_value(wwPump_, 0));
|
||||
}
|
||||
|
||||
// SM100wwCommand - 0x07AB
|
||||
@@ -349,15 +252,14 @@ void Solar::process_SM100wwCommand(std::shared_ptr<const Telegram> telegram) {
|
||||
// not implemented yet
|
||||
}
|
||||
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// SM100Config - 0x0366
|
||||
// e.g. B0 00 FF 00 02 66 01 62 00 13 40 14
|
||||
void Solar::process_SM100Config(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(availabilityFlag_, 0);
|
||||
changed_ |= telegram->read_value(configFlag_, 1);
|
||||
changed_ |= telegram->read_value(userFlag_, 2);
|
||||
has_update(telegram->read_value(availabilityFlag_, 0));
|
||||
has_update(telegram->read_value(configFlag_, 1));
|
||||
has_update(telegram->read_value(userFlag_, 2));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -369,8 +271,8 @@ void Solar::process_SM100Config(std::shared_ptr<const Telegram> telegram) {
|
||||
void Solar::process_SM100Status(std::shared_ptr<const Telegram> telegram) {
|
||||
uint8_t solarpumpmod = solarPumpModulation_;
|
||||
uint8_t cylinderpumpmod = cylinderPumpModulation_;
|
||||
changed_ |= telegram->read_value(cylinderPumpModulation_, 8);
|
||||
changed_ |= telegram->read_value(solarPumpModulation_, 9);
|
||||
has_update(telegram->read_value(cylinderPumpModulation_, 8));
|
||||
has_update(telegram->read_value(solarPumpModulation_, 9));
|
||||
|
||||
if (solarpumpmod == 0 && solarPumpModulation_ == 100) { // mask out boosts
|
||||
solarPumpModulation_ = 15; // set to minimum
|
||||
@@ -379,8 +281,8 @@ void Solar::process_SM100Status(std::shared_ptr<const Telegram> telegram) {
|
||||
if (cylinderpumpmod == 0 && cylinderPumpModulation_ == 100) { // mask out boosts
|
||||
cylinderPumpModulation_ = 15; // set to minimum
|
||||
}
|
||||
changed_ |= telegram->read_bitvalue(tankHeated_, 3, 1); // issue #422
|
||||
changed_ |= telegram->read_bitvalue(collectorShutdown_, 3, 0); // collector shutdown
|
||||
has_update(telegram->read_bitvalue(tankHeated_, 3, 1)); // issue #422
|
||||
has_update(telegram->read_bitvalue(collectorShutdown_, 3, 0)); // collector shutdown
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -390,8 +292,8 @@ void Solar::process_SM100Status(std::shared_ptr<const Telegram> telegram) {
|
||||
* byte 10 = PS1 Solar circuit pump for collector array 1: test=b0001(1), on=b0100(4) and off=b0011(3)
|
||||
*/
|
||||
void Solar::process_SM100Status2(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_bitvalue(valveStatus_, 4, 2); // on if bit 2 set
|
||||
changed_ |= telegram->read_bitvalue(solarPump_, 10, 2); // on if bit 2 set
|
||||
has_update(telegram->read_bitvalue(valveStatus_, 4, 2)); // on if bit 2 set
|
||||
has_update(telegram->read_bitvalue(solarPump_, 10, 2)); // on if bit 2 set
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -399,9 +301,9 @@ void Solar::process_SM100Status2(std::shared_ptr<const Telegram> telegram) {
|
||||
* e.g. B0 0B FF 00 02 80 50 64 00 00 29 01 00 00 01
|
||||
*/
|
||||
void Solar::process_SM100CollectorConfig(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(climateZone_, 0, 1);
|
||||
changed_ |= telegram->read_value(collector1Area_, 3, 2);
|
||||
changed_ |= telegram->read_value(collector1Type_, 5, 1);
|
||||
has_update(telegram->read_value(climateZone_, 0, 1));
|
||||
has_update(telegram->read_value(collector1Area_, 3, 2));
|
||||
has_update(telegram->read_value(collector1Type_, 5, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -409,16 +311,16 @@ void Solar::process_SM100CollectorConfig(std::shared_ptr<const Telegram> telegra
|
||||
* e.g. 30 00 FF 00 02 8E 00 00 00 00 00 00 06 C5 00 00 76 35
|
||||
*/
|
||||
void Solar::process_SM100Energy(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(energyLastHour_, 0); // last hour / 10 in Wh
|
||||
changed_ |= telegram->read_value(energyToday_, 4); // todays in Wh
|
||||
changed_ |= telegram->read_value(energyTotal_, 8); // total / 10 in kWh
|
||||
has_update(telegram->read_value(energyLastHour_, 0)); // last hour / 10 in Wh
|
||||
has_update(telegram->read_value(energyToday_, 4)); // todays in Wh
|
||||
has_update(telegram->read_value(energyTotal_, 8)); // total / 10 in kWh
|
||||
}
|
||||
|
||||
/*
|
||||
* SM100Time - type 0x0391 EMS+ for pump working time
|
||||
*/
|
||||
void Solar::process_SM100Time(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(pumpWorkMin_, 1, 3);
|
||||
has_update(telegram->read_value(pumpWorkMin_, 1, 3));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -426,26 +328,26 @@ void Solar::process_SM100Time(std::shared_ptr<const Telegram> telegram) {
|
||||
* e.g. B0 00 FF 00 00 03 32 00 00 00 00 13 00 D6 00 00 00 FB D0 F0
|
||||
*/
|
||||
void Solar::process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(collectorTemp_, 4); // Collector Temperature
|
||||
changed_ |= telegram->read_value(tankBottomTemp_, 6); // Temperature Bottom of Solar Boiler
|
||||
has_update(telegram->read_value(collectorTemp_, 4)); // Collector Temperature
|
||||
has_update(telegram->read_value(tankBottomTemp_, 6)); // Temperature Bottom of Solar Boiler
|
||||
uint16_t Wh = 0xFFFF;
|
||||
changed_ |= telegram->read_value(Wh, 2); // Solar Energy produced in last hour only ushort, is not * 10
|
||||
has_update(telegram->read_value(Wh, 2)); // Solar Energy produced in last hour only ushort, is not * 10
|
||||
|
||||
if (Wh != 0xFFFF) {
|
||||
energyLastHour_ = Wh * 10; // set to *10
|
||||
}
|
||||
|
||||
changed_ |= telegram->read_bitvalue(solarPump_, 8, 0); // PS1 Solar pump on (1) or off (0)
|
||||
changed_ |= telegram->read_value(pumpWorkMin_, 10, 3); // force to 3 bytes
|
||||
changed_ |= telegram->read_bitvalue(collectorShutdown_, 9, 0); // collector shutdown on/off
|
||||
changed_ |= telegram->read_bitvalue(tankHeated_, 9, 2); // tank full
|
||||
has_update(telegram->read_bitvalue(solarPump_, 8, 0)); // PS1 Solar pump on (1) or off (0)
|
||||
has_update(telegram->read_value(pumpWorkMin_, 10, 3)); // force to 3 bytes
|
||||
has_update(telegram->read_bitvalue(collectorShutdown_, 9, 0)); // collector shutdown on/off
|
||||
has_update(telegram->read_bitvalue(tankHeated_, 9, 2)); // tank full
|
||||
}
|
||||
|
||||
/*
|
||||
* Junkers ISM1 Solar Module - type 0x0101 EMS+ for setting values
|
||||
*/
|
||||
void Solar::process_ISM1Set(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(setpoint_maxBottomTemp_, 6);
|
||||
has_update(telegram->read_value(setpoint_maxBottomTemp_, 6));
|
||||
}
|
||||
|
||||
// set temperature for tank
|
||||
|
||||
@@ -36,61 +36,56 @@ 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 void publish_values(JsonObject & json, bool force);
|
||||
virtual bool export_values(JsonObject & json);
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual bool publish_ha_config();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
void register_mqtt_ha_config();
|
||||
|
||||
int16_t collectorTemp_ = EMS_VALUE_SHORT_NOTSET; // TS1: Temperature sensor for collector array 1
|
||||
int16_t tankBottomTemp_ = EMS_VALUE_SHORT_NOTSET; // TS2: Temperature sensor 1 cylinder, bottom (solar thermal system)
|
||||
int16_t tankBottomTemp2_ = EMS_VALUE_SHORT_NOTSET; // TS5: Temperature sensor 2 cylinder, bottom, or swimming pool (solar thermal system)
|
||||
int16_t heatExchangerTemp_ = EMS_VALUE_SHORT_NOTSET; // TS6: Heat exchanger temperature sensor
|
||||
uint8_t solarPumpModulation_ = EMS_VALUE_UINT_NOTSET; // PS1: modulation solar pump
|
||||
uint8_t cylinderPumpModulation_ = EMS_VALUE_UINT_NOTSET; // PS5: modulation cylinder pump
|
||||
uint8_t solarPump_ = EMS_VALUE_BOOL_NOTSET; // PS1: solar pump active
|
||||
uint8_t valveStatus_ = EMS_VALUE_BOOL_NOTSET; // VS2: status 3-way valve for cylinder 2 (solar thermal system) with valve
|
||||
int16_t setpoint_maxBottomTemp_ = EMS_VALUE_SHORT_NOTSET; // setpoint for maximum collector temp
|
||||
uint32_t energyLastHour_ = EMS_VALUE_ULONG_NOTSET;
|
||||
uint32_t energyToday_ = EMS_VALUE_ULONG_NOTSET;
|
||||
uint32_t energyTotal_ = EMS_VALUE_ULONG_NOTSET;
|
||||
uint32_t pumpWorkMin_ = EMS_VALUE_ULONG_NOTSET; // Total solar pump operating time
|
||||
uint8_t tankHeated_ = EMS_VALUE_BOOL_NOTSET;
|
||||
uint8_t collectorShutdown_ = EMS_VALUE_BOOL_NOTSET; // Collector shutdown on/off
|
||||
int16_t collectorTemp_; // TS1: Temperature sensor for collector array 1
|
||||
int16_t tankBottomTemp_; // TS2: Temperature sensor 1 cylinder, bottom (solar thermal system)
|
||||
int16_t tankBottomTemp2_; // TS5: Temperature sensor 2 cylinder, bottom, 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 setpoint_maxBottomTemp_; // setpoint for maximum collector temp
|
||||
uint32_t energyLastHour_;
|
||||
uint32_t energyToday_;
|
||||
uint32_t energyTotal_;
|
||||
uint32_t pumpWorkMin_; // Total solar pump operating time
|
||||
uint8_t tankHeated_;
|
||||
uint8_t collectorShutdown_; // Collector shutdown on/off
|
||||
|
||||
uint8_t availabilityFlag_ = EMS_VALUE_BOOL_NOTSET;
|
||||
uint8_t configFlag_ = EMS_VALUE_BOOL_NOTSET;
|
||||
uint8_t userFlag_ = EMS_VALUE_BOOL_NOTSET;
|
||||
uint8_t availabilityFlag_;
|
||||
uint8_t configFlag_;
|
||||
uint8_t userFlag_;
|
||||
|
||||
// telegram 0x0358
|
||||
uint8_t heatTransferSystem_ = EMS_VALUE_UINT_NOTSET; // Umladesystem, 00=no
|
||||
uint8_t externalTank_ = EMS_VALUE_UINT_NOTSET; // Heat exchanger, 00=no
|
||||
uint8_t thermalDisinfect_ = EMS_VALUE_UINT_NOTSET; // Daily heatup for disinfection, 00=no
|
||||
uint8_t heatMetering_ = EMS_VALUE_UINT_NOTSET; // Wärmemengenzählung, 00=no
|
||||
uint8_t solarIsEnabled_ = EMS_VALUE_UINT_NOTSET; // System enable, 00=no
|
||||
uint8_t heatTransferSystem_; // Umladesystem, 00=no
|
||||
uint8_t externalTank_; // Heat exchanger, 00=no
|
||||
uint8_t thermalDisinfect_; // Daily heatup for disinfection, 00=no
|
||||
uint8_t heatMetering_; // Wärmemengenzählung, 00=no
|
||||
uint8_t solarIsEnabled_; // System enable, 00=no
|
||||
|
||||
// telegram 0x035A
|
||||
uint8_t collectorTempMax_ = EMS_VALUE_UINT_NOTSET; // maximum allowable temperature for collector
|
||||
uint8_t tank1MaxTempCurrent_ = EMS_VALUE_UINT_NOTSET; // Current value for max tank temp
|
||||
uint8_t collectorTempMin_ = EMS_VALUE_UINT_NOTSET; // minimum allowable temperature for collector
|
||||
uint8_t solarPumpMode_ = EMS_VALUE_UINT_NOTSET; // 00=off, 01=PWM, 02=10V
|
||||
uint8_t solarPumpMinRPM_ = EMS_VALUE_UINT_NOTSET; // minimum RPM setting, *5 %
|
||||
uint8_t solarPumpTurnoffDiff_ = EMS_VALUE_UINT_NOTSET; // solar pump turnoff collector/tank diff
|
||||
uint8_t solarPumpTurnonDiff_ = EMS_VALUE_UINT_NOTSET; // solar pump turnon collector/tank diff
|
||||
uint8_t solarPumpKick_ = EMS_VALUE_UINT_NOTSET; // pump kick for vacuum collector, 00=off
|
||||
uint8_t plainWaterMode_ = EMS_VALUE_UINT_NOTSET; // system does not use antifreeze, 00=off
|
||||
uint8_t doubleMatchFlow_ = EMS_VALUE_UINT_NOTSET; // double Match Flow, 00=off
|
||||
uint8_t collectorTempMax_; // maximum allowable temperature for collector
|
||||
uint8_t tank1MaxTempCurrent_; // Current value for max tank temp
|
||||
uint8_t collectorTempMin_; // minimum allowable temperature for collector
|
||||
uint8_t solarPumpMode_; // 00=off, 01=PWM, 02=10V
|
||||
uint8_t solarPumpMinRPM_; // minimum RPM setting, *5 %
|
||||
uint8_t solarPumpTurnoffDiff_; // solar pump turnoff collector/tank diff
|
||||
uint8_t solarPumpTurnonDiff_; // solar pump turnon collector/tank 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 0x380
|
||||
uint8_t climateZone_ = EMS_VALUE_UINT_NOTSET; // climate zone identifier
|
||||
uint16_t collector1Area_ = EMS_VALUE_USHORT_NOTSET; // Area of collector field 1
|
||||
uint8_t collector1Type_ = EMS_VALUE_UINT_NOTSET; // Type of collector field 1, 01=flat, 02=vacuum
|
||||
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
|
||||
|
||||
bool changed_ = false;
|
||||
bool mqtt_ha_config_ = false; // for HA MQTT Discovery
|
||||
char type_[20]; // Solar of WWC
|
||||
|
||||
void process_SM10Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100SystemConfig(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
@@ -32,92 +32,30 @@ Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const
|
||||
|
||||
register_telegram_type(0x9C, F("WM10MonitorMessage"), false, [&](std::shared_ptr<const Telegram> t) { process_WM10MonitorMessage(t); });
|
||||
register_telegram_type(0x9B, F("WM10SetMessage"), false, [&](std::shared_ptr<const Telegram> t) { process_WM10SetMessage(t); });
|
||||
|
||||
std::string empty("");
|
||||
register_device_value(empty, &activated_, DeviceValueType::BOOL, {}, F("activated"), F("Activated"), DeviceValueUOM::NONE);
|
||||
register_device_value(
|
||||
empty, &flowTemp_, DeviceValueType::USHORT, flash_string_vector{F("10")}, F("flowTemp"), F("Current flow temperature"), DeviceValueUOM::DEGREES);
|
||||
register_device_value(empty, &status_, DeviceValueType::INT, {}, F("status"), F("Status"), DeviceValueUOM::NONE);
|
||||
}
|
||||
|
||||
// fetch the values into a JSON document for display in the web
|
||||
void Switch::device_info_web(JsonArray & root) {
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_SMALL> doc;
|
||||
JsonObject json = doc.to<JsonObject>();
|
||||
if (export_values(json)) {
|
||||
create_value_json(root, F("activated"), nullptr, F_(activated), nullptr, json);
|
||||
create_value_json(root, F("flowTemp"), nullptr, F_(flowTemp), F_(degrees), json);
|
||||
create_value_json(root, F("status"), nullptr, F_(status), nullptr, json);
|
||||
}
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
void Switch::publish_values(JsonObject & json, bool force) {
|
||||
if (Mqtt::mqtt_format() == Mqtt::Format::HA) {
|
||||
if (!mqtt_ha_config_ || force) {
|
||||
register_mqtt_ha_config();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_SMALL> doc;
|
||||
JsonObject json_data = doc.to<JsonObject>();
|
||||
if (export_values(json_data)) {
|
||||
Mqtt::publish(F("switch_data"), doc.as<JsonObject>());
|
||||
}
|
||||
}
|
||||
|
||||
// export values to JSON
|
||||
bool Switch::export_values(JsonObject & json) {
|
||||
if (Helpers::hasValue(flowTemp_)) {
|
||||
char s[7];
|
||||
json["activated"] = Helpers::render_value(s, activated_, EMS_VALUE_BOOL);
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(flowTemp_)) {
|
||||
json["flowTemp"] = (float)flowTemp_ / 10;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(flowTemp_)) {
|
||||
json["status"] = status_;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// check to see if values have been updated
|
||||
bool Switch::updated_values() {
|
||||
if (changed_) {
|
||||
changed_ = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// publish config topic for HA MQTT Discovery
|
||||
void Switch::register_mqtt_ha_config() {
|
||||
if (!Mqtt::connected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we don't have valid values for this HC don't add it ever again
|
||||
// publish HA config
|
||||
bool Switch::publish_ha_config() {
|
||||
// if we don't have valid values don't add it ever again
|
||||
if (!Helpers::hasValue(flowTemp_)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the Master device
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_HA_CONFIG> doc;
|
||||
|
||||
char name[10];
|
||||
snprintf_P(name, sizeof(name), PSTR("Switch"));
|
||||
doc["name"] = name;
|
||||
|
||||
char uniq_id[10];
|
||||
snprintf_P(uniq_id, sizeof(uniq_id), PSTR("switch"));
|
||||
doc["uniq_id"] = uniq_id;
|
||||
|
||||
doc["ic"] = FJSON("mdi:home-thermometer-outline");
|
||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||
doc["uniq_id"] = F_(switch);
|
||||
|
||||
char stat_t[50];
|
||||
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/switch_data"), System::hostname().c_str());
|
||||
doc["stat_t"] = stat_t;
|
||||
|
||||
doc["name"] = FJSON("Type");
|
||||
doc["val_tpl"] = FJSON("{{value_json.type}}"); // HA needs a single value. We take the type which is wwc or hc
|
||||
|
||||
JsonObject dev = doc.createNestedObject("dev");
|
||||
dev["name"] = FJSON("EMS-ESP Switch");
|
||||
dev["sw"] = EMSESP_APP_VERSION;
|
||||
@@ -126,24 +64,22 @@ void Switch::register_mqtt_ha_config() {
|
||||
JsonArray ids = dev.createNestedArray("ids");
|
||||
ids.add("ems-esp-switch");
|
||||
|
||||
Mqtt::publish_ha(F("homeassistant/sensor/ems-esp/switch/config"), doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
char topic[100];
|
||||
snprintf_P(topic, sizeof(topic), PSTR("homeassistant/sensor/%s/switch/config"), System::hostname().c_str());
|
||||
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(activated), device_type(), "activated", nullptr, nullptr);
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(flowTemp), device_type(), "flowTemp", F_(degrees), F_(icontemperature));
|
||||
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(status), device_type(), "status", nullptr, nullptr);
|
||||
|
||||
mqtt_ha_config_ = true; // done
|
||||
return true;
|
||||
}
|
||||
|
||||
// message 0x9B switch on/off
|
||||
void Switch::process_WM10SetMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(activated_, 0);
|
||||
has_update(telegram->read_value(activated_, 0));
|
||||
}
|
||||
|
||||
// message 0x9C holds flowtemp and unknown status value
|
||||
void Switch::process_WM10MonitorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(flowTemp_, 0); // is * 10
|
||||
changed_ |= telegram->read_value(status_, 2);
|
||||
has_update(telegram->read_value(flowTemp_, 0)); // is * 10
|
||||
has_update(telegram->read_value(status_, 2));
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -36,23 +36,17 @@ 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 void publish_values(JsonObject & json, bool force);
|
||||
virtual bool export_values(JsonObject & json);
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual bool publish_ha_config();
|
||||
|
||||
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 register_mqtt_ha_config();
|
||||
|
||||
uint16_t flowTemp_ = EMS_VALUE_USHORT_NOTSET;
|
||||
uint8_t status_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t activated_ = EMS_VALUE_BOOL_NOTSET;
|
||||
bool changed_ = false;
|
||||
bool mqtt_ha_config_ = false; // for HA MQTT Discovery
|
||||
uint16_t flowTemp_;
|
||||
uint8_t status_;
|
||||
uint8_t activated_;
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,44 +40,43 @@ class Thermostat : public EMSdevice {
|
||||
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);
|
||||
class HeatingCircuit {
|
||||
public:
|
||||
HeatingCircuit(const uint8_t hc_num)
|
||||
HeatingCircuit(const uint8_t hc_num, const uint8_t model)
|
||||
: hc_num_(hc_num)
|
||||
, ha_registered_(false) {
|
||||
, model_(model) {
|
||||
}
|
||||
~HeatingCircuit() = default;
|
||||
|
||||
int16_t setpoint_roomTemp = EMS_VALUE_SHORT_NOTSET;
|
||||
int16_t curr_roomTemp = EMS_VALUE_SHORT_NOTSET;
|
||||
uint8_t mode = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t mode_type = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t summer_mode = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t holiday_mode = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t daytemp = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t nighttemp = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t holidaytemp = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t heatingtype = EMS_VALUE_UINT_NOTSET; // type of heating: 1 radiator, 2 convectors, 3 floors, 4 room supply
|
||||
uint8_t targetflowtemp = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t summertemp = EMS_VALUE_UINT_NOTSET;
|
||||
int8_t nofrosttemp = EMS_VALUE_INT_NOTSET; // signed -20°C to +10°C
|
||||
uint8_t designtemp = EMS_VALUE_UINT_NOTSET; // heating curve design temp at MinExtTemp
|
||||
int8_t offsettemp = EMS_VALUE_INT_NOTSET; // heating curve offest temp at roomtemp signed!
|
||||
uint8_t manualtemp = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t summer_setmode = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t roominfluence = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t flowtempoffset = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t minflowtemp = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t maxflowtemp = EMS_VALUE_UINT_NOTSET;
|
||||
int16_t setpoint_roomTemp;
|
||||
int16_t curr_roomTemp;
|
||||
uint8_t mode;
|
||||
uint8_t modetype;
|
||||
uint8_t summermode;
|
||||
uint8_t holidaymode;
|
||||
uint8_t daytemp;
|
||||
uint8_t nighttemp;
|
||||
uint8_t holidaytemp;
|
||||
uint8_t heatingtype; // type of heating: 1 radiator, 2 convectors, 3 floors, 4 room supply
|
||||
uint8_t targetflowtemp;
|
||||
uint8_t summertemp;
|
||||
int8_t nofrosttemp; // signed -20°C to +10°C
|
||||
uint8_t designtemp; // heating curve design temp at MinExtTemp
|
||||
int8_t offsettemp; // heating curve offest temp at roomtemp signed!
|
||||
uint8_t manualtemp;
|
||||
uint8_t summer_setmode;
|
||||
uint8_t roominfluence;
|
||||
uint8_t flowtempoffset;
|
||||
uint8_t minflowtemp;
|
||||
uint8_t maxflowtemp;
|
||||
uint8_t reducemode;
|
||||
uint8_t program;
|
||||
uint8_t controlmode;
|
||||
|
||||
uint8_t hc_num() const {
|
||||
return hc_num_;
|
||||
}
|
||||
|
||||
bool ha_registered() const {
|
||||
return ha_registered_;
|
||||
}
|
||||
|
||||
void ha_registered(bool b) {
|
||||
ha_registered_ = b;
|
||||
uint8_t get_model() const {
|
||||
return model_;
|
||||
}
|
||||
|
||||
// determines if the heating circuit is actually present and has data
|
||||
@@ -85,11 +84,10 @@ class Thermostat : public EMSdevice {
|
||||
return Helpers::hasValue(setpoint_roomTemp);
|
||||
}
|
||||
|
||||
uint8_t get_mode(uint8_t model) const;
|
||||
uint8_t get_mode_type(uint8_t model) const;
|
||||
uint8_t get_mode() const;
|
||||
uint8_t get_mode_type() const;
|
||||
|
||||
enum Mode : uint8_t {
|
||||
UNKNOWN,
|
||||
OFF,
|
||||
MANUAL,
|
||||
AUTO,
|
||||
@@ -106,7 +104,8 @@ class Thermostat : public EMSdevice {
|
||||
FLOWOFFSET,
|
||||
MINFLOW,
|
||||
MAXFLOW,
|
||||
ROOMINFLUENCE
|
||||
ROOMINFLUENCE,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
// for sorting based on hc number
|
||||
@@ -115,31 +114,21 @@ class Thermostat : public EMSdevice {
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t hc_num_; // heating circuit number 1..10
|
||||
bool ha_registered_; // whether it has been registered for HA MQTT Discovery
|
||||
uint8_t hc_num_; // heating circuit number 1..10
|
||||
uint8_t model_; // the model type
|
||||
};
|
||||
|
||||
static std::string mode_tostring(uint8_t mode);
|
||||
|
||||
virtual void publish_values(JsonObject & json, bool force);
|
||||
virtual bool export_values(JsonObject & json);
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual bool publish_ha_config();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void add_commands();
|
||||
bool export_values_main(JsonObject & doc);
|
||||
bool export_values_hc(uint8_t mqtt_format, JsonObject & doc);
|
||||
|
||||
bool ha_registered() const {
|
||||
return ha_registered_;
|
||||
}
|
||||
|
||||
void ha_registered(bool b) {
|
||||
ha_registered_ = b;
|
||||
}
|
||||
void register_device_values();
|
||||
void register_device_values(uint8_t hc_num);
|
||||
|
||||
// specific thermostat characteristics, stripping the top 4 bits
|
||||
inline uint8_t model() const {
|
||||
@@ -153,40 +142,38 @@ class Thermostat : public EMSdevice {
|
||||
std::vector<uint16_t> summer_typeids;
|
||||
std::vector<uint16_t> curve_typeids;
|
||||
|
||||
std::string datetime_; // date and time stamp
|
||||
std::string errorCode_; // code from 0xA2 as string i.e. "A22(816)"
|
||||
|
||||
bool changed_ = false;
|
||||
bool ha_registered_ = false;
|
||||
char dateTime_[25]; // date and time stamp
|
||||
char errorCode_[15]; // code from 0xA2 as string i.e. "A22(816)"
|
||||
|
||||
// Installation parameters
|
||||
uint8_t ibaMainDisplay_ =
|
||||
EMS_VALUE_UINT_NOTSET; // 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
|
||||
uint8_t ibaLanguage_ = EMS_VALUE_UINT_NOTSET; // language on Thermostat: 0 german, 1 dutch, 2 french, 3 italian
|
||||
int8_t ibaCalIntTemperature_ = EMS_VALUE_INT_NOTSET; // offset int. temperature sensor, by * 0.1 Kelvin (-5.0 to 5.0K)
|
||||
int8_t ibaMinExtTemperature_ = EMS_VALUE_INT_NOTSET; // min ext temp for heating curve, in deg., 0xF6=-10, 0x0 = 0, 0xFF=-1
|
||||
uint8_t ibaBuildingType_ = EMS_VALUE_UINT_NOTSET; // building type: 0 = light, 1 = medium, 2 = heavy
|
||||
uint8_t ibaClockOffset_ = EMS_VALUE_UINT_NOTSET; // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
|
||||
uint8_t 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
|
||||
uint8_t ibaLanguage_; // language on Thermostat: 0 german, 1 dutch, 2 french, 3 italian
|
||||
int8_t ibaCalIntTemperature_; // offset int. temperature sensor, by * 0.1 Kelvin (-5.0 to 5.0K)
|
||||
int8_t ibaMinExtTemperature_; // min ext temp for heating curve, in deg., 0xF6=-10, 0x0 = 0, 0xFF=-1
|
||||
uint8_t ibaBuildingType_; // building type: 0 = light, 1 = medium, 2 = heavy
|
||||
uint8_t ibaClockOffset_; // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
|
||||
|
||||
uint16_t errorNumber_ = EMS_VALUE_USHORT_NOTSET;
|
||||
char lastCode_[30] = {'\0'};
|
||||
int8_t dampedoutdoortemp_ = EMS_VALUE_INT_NOTSET;
|
||||
uint16_t tempsensor1_ = EMS_VALUE_USHORT_NOTSET;
|
||||
uint16_t tempsensor2_ = EMS_VALUE_USHORT_NOTSET;
|
||||
int16_t dampedoutdoortemp2_ = EMS_VALUE_SHORT_NOTSET;
|
||||
uint8_t floordrystatus_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t floordrytemp_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint16_t errorNumber_;
|
||||
char lastCode_[30];
|
||||
int8_t dampedoutdoortemp_;
|
||||
uint16_t tempsensor1_;
|
||||
uint16_t tempsensor2_;
|
||||
int16_t dampedoutdoortemp2_;
|
||||
uint8_t floordrystatus_;
|
||||
uint8_t floordrytemp_;
|
||||
|
||||
uint8_t wwExtra1_ = EMS_VALUE_UINT_NOTSET; // wwExtra active for wwSystem 1
|
||||
uint8_t wwExtra2_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t wwMode_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t wwCircPump_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t wwCircMode_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t wwTemp_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t wwTempLow_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t wwExtra1_; // wwExtra active for wwSystem 1
|
||||
uint8_t wwExtra2_;
|
||||
uint8_t wwMode_;
|
||||
uint8_t wwCircPump_;
|
||||
uint8_t wwCircMode_;
|
||||
uint8_t wwTemp_;
|
||||
uint8_t wwTempLow_;
|
||||
|
||||
std::vector<std::shared_ptr<HeatingCircuit>> heating_circuits_; // each thermostat can have multiple heating circuits
|
||||
|
||||
uint8_t zero_value_ = 0; // for fixing current room temperature to 0 for HA
|
||||
|
||||
// Generic Types
|
||||
static constexpr uint16_t EMS_TYPE_RCTime = 0x06; // time
|
||||
static constexpr uint16_t EMS_TYPE_RCOutdoorTemp = 0xA3; // is an automatic thermostat broadcast, outdoor external temp
|
||||
@@ -266,9 +253,9 @@ class Thermostat : public EMSdevice {
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> heating_circuit(std::shared_ptr<const Telegram> telegram);
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> heating_circuit(const uint8_t hc_num);
|
||||
|
||||
void register_mqtt_ha_config();
|
||||
void register_mqtt_ha_config(uint8_t hc_num);
|
||||
bool ha_config(bool force = false);
|
||||
void register_mqtt_ha_config_hc(uint8_t hc_num);
|
||||
void register_device_values_hc(std::shared_ptr<emsesp::Thermostat::HeatingCircuit> hc);
|
||||
|
||||
bool thermostat_ha_cmd(const char * message, uint8_t hc_num);
|
||||
|
||||
void process_RCOutdoorTemp(std::shared_ptr<const Telegram> telegram);
|
||||
@@ -279,6 +266,7 @@ class Thermostat : public EMSdevice {
|
||||
void process_RC35wwSettings(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);
|
||||
void process_RC30Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC30Set(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC20Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
@@ -335,6 +323,9 @@ class Thermostat : public EMSdevice {
|
||||
bool set_flowtempoffset(const char * value, const int8_t id);
|
||||
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_program(const char * value, const int8_t id);
|
||||
bool set_controlmode(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);
|
||||
@@ -353,4 +344,4 @@ class Thermostat : public EMSdevice {
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user