diff --git a/interface/src/app/status/HardwareStatus.tsx b/interface/src/app/status/HardwareStatus.tsx index 93f8f3d1a..6c872468e 100644 --- a/interface/src/app/status/HardwareStatus.tsx +++ b/interface/src/app/status/HardwareStatus.tsx @@ -97,7 +97,8 @@ const HardwareStatus = () => { (data.cpu_cores === 1 ? 'single-core)' : 'dual-core)') + ' @ ' + data.cpu_freq_mhz + - ' Mhz' + ' Mhz' + + (data.temperature ? ', T: ' + data.temperature + ' °C' : '') } /> diff --git a/interface/src/types/system.ts b/interface/src/types/system.ts index ca9d34555..b71586af3 100644 --- a/interface/src/types/system.ts +++ b/interface/src/types/system.ts @@ -41,6 +41,7 @@ export interface SystemStatus { has_loader: boolean; has_partition: boolean; status: string; + temperature?: number; } export enum LogLevel { diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 17a2b57c1..ac23b33ca 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -210,7 +210,7 @@ void AnalogSensor::reload(bool get_nvs) { sensor.set_offset(EMSESP::nvs_.getChar(sensor.name().c_str())); } } - digitalWrite(sensor.gpio(), (sensor.offset() == 0) ^ (sensor.factor() != 0)); + digitalWrite(sensor.gpio(), (sensor.offset() == 0) ^ (sensor.factor() > 0)); sensor.set_value(sensor.offset()); } publish_sensor(sensor); @@ -756,7 +756,7 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) { sensor.set_offset(v); sensor.set_value(v); pinMode(sensor.gpio(), OUTPUT); - digitalWrite(sensor.gpio(), (sensor.offset() == 0) ^ (sensor.factor() != 0)); + digitalWrite(sensor.gpio(), (sensor.offset() == 0) ^ (sensor.factor() > 0)); if (sensor.uom() == 0 && EMSESP::nvs_.getChar(sensor.name().c_str()) != (int8_t)sensor.offset()) { EMSESP::nvs_.putChar(sensor.name().c_str(), (int8_t)sensor.offset()); } diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 72dc39a69..ee6de8b03 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -286,6 +286,8 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const MAKE_CF_CB(set_pumpCharacter)); register_device_value( DeviceValueTAG::TAG_DEVICE_DATA, &pumpDelay_, DeviceValueType::UINT8, FL_(pumpDelay), DeviceValueUOM::MINUTES, MAKE_CF_CB(set_pump_delay), 0, 60); + register_device_value( + DeviceValueTAG::TAG_DEVICE_DATA, &pumpOnTemp_, DeviceValueType::UINT8, FL_(pumpOnTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_pumpOnTemp), 0, 60); register_device_value( DeviceValueTAG::TAG_DEVICE_DATA, &selBurnPow_, DeviceValueType::UINT8, FL_(selBurnPow), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_burn_power), 0, 254); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &curBurnPow_, DeviceValueType::UINT8, FL_(curBurnPow), DeviceValueUOM::PERCENT); @@ -546,6 +548,13 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const FL_(hpMaxPower), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_hpMaxPower)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &pvMaxComp_, + DeviceValueType::UINT8, + DeviceValueNumOp::DV_NUMOP_DIV10, + FL_(pvMaxComp), + DeviceValueUOM::KW, + MAKE_CF_CB(set_pvMaxComp)); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpSetDiffPress_, DeviceValueType::UINT8, @@ -1296,6 +1305,7 @@ void Boiler::process_UBAParameters(std::shared_ptr telegram) { has_update(telegram, pumpMode_, 11); has_update(telegram, boil2HystOff_, 12); has_update(telegram, boil2HystOn_, 13); + has_update(telegram, pumpOnTemp_, 23); // https://github.com/emsesp/EMS-ESP32/issues/2088 } /* @@ -1929,6 +1939,7 @@ void Boiler::process_HpSilentMode(std::shared_ptr telegram) { has_update(telegram, hpMaxPower_, 31); has_update(telegram, silentFrom_, 52); // in steps of 15 min has_update(telegram, silentTo_, 53); // in steps of 15 min + has_update(telegram, pvMaxComp_, 54); // #2062 has_update(telegram, hpshutdown_, 58); // 1 powers off } @@ -2559,6 +2570,17 @@ bool Boiler::set_pump_delay(const char * value, const int8_t id) { return false; } +// set pump logic temperature +bool Boiler::set_pumpOnTemp(const char * value, const int8_t id) { + int v; + if (!Helpers::value2temperature(value, v)) { + return false; + } + + write_command(EMS_TYPE_UBAParameters, 23, v, EMS_TYPE_UBAParameters); + return true; +} + // note some boilers do not have this setting, than it's done by thermostat // on a RC35 it's by EMSESP::send_write_request(0x37, 0x10, 2, &set, 1, 0); (set is 1,2,3) 1=hot, 2=eco, 3=intelligent // on a RC310 it's 1=high, 2=eco @@ -3104,6 +3126,15 @@ bool Boiler::set_hpMaxPower(const char * value, const int8_t id) { return false; } +bool Boiler::set_pvMaxComp(const char * value, const int8_t id) { + float v; + if (Helpers::value2float(value, v)) { + write_command(0x484, 54, (uint8_t)(v * 10), 0x484); + return true; + } + return false; +} + bool Boiler::set_hpDiffPress(const char * value, const int8_t id) { int v; if (Helpers::value2number(value, v)) { diff --git a/src/devices/boiler.h b/src/devices/boiler.h index 3a276985f..e9d56f3b0 100644 --- a/src/devices/boiler.h +++ b/src/devices/boiler.h @@ -131,6 +131,7 @@ class Boiler : public EMSdevice { uint8_t pumpMode_; // pump setting proportional/deltaP uint8_t pumpCharacter_; // pump setting proportional/deltaP uint8_t pumpDelay_; + uint8_t pumpOnTemp_; uint8_t burnMinPeriod_; uint8_t burnMinPower_; uint8_t burnMaxPower_; @@ -254,6 +255,7 @@ class Boiler : public EMSdevice { uint8_t maxHeatHeat_; uint8_t maxHeatDhw_; uint8_t hpMaxPower_; + uint8_t pvMaxComp_; uint8_t pvCooling_; uint8_t manDefrost_; @@ -419,6 +421,7 @@ class Boiler : public EMSdevice { bool set_max_pump(const char * value, const int8_t id); bool set_pumpMode(const char * value, const int8_t id); bool set_pumpCharacter(const char * value, const int8_t id); + bool set_pumpOnTemp(const char * value, const int8_t id); bool set_hyst_on(const char * value, const int8_t id); bool set_hyst_off(const char * value, const int8_t id); inline bool set_hyst2_on(const char * value, const int8_t id) { @@ -476,6 +479,7 @@ class Boiler : public EMSdevice { bool set_hpCircPumpWw(const char * value, const int8_t id); bool set_hpPumpMode(const char * value, const int8_t id); bool set_hpMaxPower(const char * value, const int8_t id); + bool set_pvMaxComp(const char * value, const int8_t id); bool set_hpDiffPress(const char * value, const int8_t id); bool set_hpPowerLimit(const char * value, const int8_t id); diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 8f721427a..71b6ccad7 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -557,10 +557,10 @@ uint8_t Thermostat::HeatingCircuit::get_mode_type() const { return HeatingCircuit::Mode::DAY; } -std::shared_ptr Thermostat::dhw_circuit(const uint8_t offset, const uint8_t dhw_num, const bool create) { +std::shared_ptr Thermostat::dhw_circuit(const uint8_t offset, const bool create) { // check for existing circuit for (const auto & dhw_circuit : dhw_circuits_) { - if (dhw_circuit->dhw() == dhw_num - 1 || dhw_circuit->offset() == offset) { + if (dhw_circuit->offset() == offset) { return dhw_circuit; } } @@ -568,7 +568,7 @@ std::shared_ptr Thermostat::dhw_circuit(const uint8_t of return nullptr; } // create a new circuit object and add to the list - auto new_dhw = std::make_shared(offset, dhw_num); + auto new_dhw = std::make_shared(offset); dhw_circuits_.push_back(new_dhw); // register the device values register_device_values_dhw(new_dhw); @@ -600,7 +600,7 @@ void Thermostat::process_RC10Set(std::shared_ptr telegram) { if (hc == nullptr) { return; } - auto dhw = dhw_circuit(0, 1, true); + auto dhw = dhw_circuit(0, true); has_update(telegram, ibaCalIntTemperature_, 0); has_update(telegram, backlight_, 1); has_update(telegram, dhw->wwMode_, 2); @@ -867,7 +867,7 @@ void Thermostat::process_IBASettings(std::shared_ptr telegram) { // Settings WW 0x37 - RC35 void Thermostat::process_RC35wwSettings(std::shared_ptr telegram) { - auto dhw = dhw_circuit(0, 1, true); + auto dhw = dhw_circuit(0, true); has_update(telegram, dhw->wwProgMode_, 0); // 0-like hc, 0xFF own prog has_update(telegram, dhw->wwCircProg_, 1); // 0-like hc, 0xFF own prog has_update(telegram, dhw->wwMode_, 2); // 0-off, 1-on, 2-auto @@ -881,7 +881,7 @@ void Thermostat::process_RC35wwSettings(std::shared_ptr telegram // Settings WW 0x3A - RC30 void Thermostat::process_RC30wwSettings(std::shared_ptr telegram) { - auto dhw = dhw_circuit(0, 1, true); + auto dhw = dhw_circuit(0, true); has_update(telegram, dhw->wwMode_, 0); // 0-on, 1-off, 2-auto has_update(telegram, dhw->wwWhenModeOff_, 1); // 0-off, 0xFF on has_update(telegram, dhw->wwDisinfecting_, 2); // 0-off, 0xFF on @@ -891,7 +891,7 @@ void Thermostat::process_RC30wwSettings(std::shared_ptr telegram // type 0x38 (ww) and 0x39 (circ) void Thermostat::process_RC35wwTimer(std::shared_ptr telegram) { - auto dhw = dhw_circuit(0, 1, true); + auto dhw = dhw_circuit(0, true); if ((telegram->message_length == 2 && telegram->offset < 83 && !(telegram->offset & 1)) || (!telegram->offset && telegram->type_id == 0x38 && !strlen(dhw->wwSwitchTime_) && telegram->message_length > 1) || (!telegram->offset && telegram->type_id == 0x39 && !strlen(dhw->wwCircSwitchTime_) && telegram->message_length > 1)) { @@ -1004,7 +1004,7 @@ void Thermostat::process_JunkersSetMixer(std::shared_ptr telegra } void Thermostat::process_JunkersWW(std::shared_ptr telegram) { - auto dhw = dhw_circuit(0, 1, true); + auto dhw = dhw_circuit(0, true); has_bitupdate(telegram, dhw->wwCharge_, 0, 3); } @@ -1185,7 +1185,7 @@ void Thermostat::process_RC300Curve(std::shared_ptr telegram) { // types 0x31B void Thermostat::process_RC300WWtemp(std::shared_ptr telegram) { - auto dhw = dhw_circuit(0, 1, true); + auto dhw = dhw_circuit(0, true); has_update(telegram, dhw->wwSetTemp_, 0); has_update(telegram, dhw->wwSetTempLow_, 1); } @@ -1195,8 +1195,8 @@ void Thermostat::process_RC300WWtemp(std::shared_ptr telegram) { // RC300WWmode(0x2F6), data: 02 FF 04 00 00 00 08 05 00 08 04 00 00 00 00 00 00 00 00 00 01 void Thermostat::process_RC300WWmode(std::shared_ptr telegram) { uint8_t circuit = 0; - telegram->read_value(circuit, 0); - auto dhw = dhw_circuit(telegram->type_id - 0x2F5, circuit, circuit != 0); + telegram->read_value(circuit, 0); // 00-no circuit, 01-boiler, 02-mixer + auto dhw = dhw_circuit(telegram->type_id - 0x2F5, circuit != 0); if (dhw == nullptr) { return; } @@ -2105,7 +2105,10 @@ bool Thermostat::set_roomsensor(const char * value, const int8_t id) { // sets the thermostat ww working mode, where mode is a string, ems and ems+ bool Thermostat::set_wwmode(const char * value, const int8_t id) { - uint8_t dhw = id2dhw(id); + auto dhw = dhw_circuit(id2dhw(id)); + if (dhw == nullptr) { + return false; + } uint8_t set; if (model() == EMSdevice::EMS_DEVICE_FLAG_RC10) { @@ -2118,24 +2121,24 @@ bool Thermostat::set_wwmode(const char * value, const int8_t id) { return false; } const uint8_t modes[] = {0, 5, 1, 2, 4}; - write_command(0x02F5 + dhw, 2, modes[set], 0x02F5 + dhw); + write_command(0x02F5 + dhw->offset(), 2, modes[set], 0x02F5 + dhw->offset()); } else if (model() == EMSdevice::EMS_DEVICE_FLAG_CR120) { if (!Helpers::value2enum(value, set, FL_(enum_wwMode6))) { // normal, comfort, auto return false; } const uint8_t modes[] = {0, 2, 4}; - write_command(0x02F5 + dhw, 2, modes[set], 0x02F5 + dhw); + write_command(0x02F5 + dhw->offset(), 2, modes[set], 0x02F5 + dhw->offset()); } else if (model() == EMSdevice::EMS_DEVICE_FLAG_R3000) { // Rego3000 - https://github.com/emsesp/EMS-ESP32/issues/1692 if (!Helpers::value2enum(value, set, FL_(enum_wwMode5))) { return false; } const uint8_t modes[] = {1, 2, 5}; - write_command(0x02F5 + dhw, 2, modes[set], 0x02F5 + dhw); + write_command(0x02F5 + dhw->offset(), 2, modes[set], 0x02F5 + dhw->offset()); } else if ((model() == EMSdevice::EMS_DEVICE_FLAG_RC300) || (model() == EMSdevice::EMS_DEVICE_FLAG_RC100)) { if (!Helpers::value2enum(value, set, FL_(enum_wwMode))) { return false; } - write_command(0x02F5 + dhw, 2, set, 0x02F5 + dhw); + write_command(0x02F5 + dhw->offset(), 2, set, 0x02F5 + dhw->offset()); } else if (model() == EMSdevice::EMS_DEVICE_FLAG_RC30) { if (!Helpers::value2enum(value, set, FL_(enum_wwMode3))) { return false; @@ -2189,8 +2192,11 @@ bool Thermostat::set_wwtemplow(const char * value, const int8_t id) { // Set ww charge RC300, ems+ bool Thermostat::set_wwcharge(const char * value, const int8_t id) { - uint8_t dhw = id2dhw(id); - bool b; + auto dhw = dhw_circuit(id2dhw(id)); + if (dhw == nullptr) { + return false; + } + bool b; if (!Helpers::value2bool(value, b)) { return false; } @@ -2198,7 +2204,7 @@ bool Thermostat::set_wwcharge(const char * value, const int8_t id) { if ((model() == EMSdevice::EMS_DEVICE_FLAG_JUNKERS)) { write_command(0x0115, 0, b ? 0xFF : 0x00, 0x01D3); } else { - write_command(0x02F5 + dhw, 11, b ? 0xFF : 0x00, 0x02F5 + dhw); + write_command(0x02F5 + dhw->offset(), 11, b ? 0xFF : 0x00, 0x02F5 + dhw->offset()); } return true; @@ -2206,14 +2212,17 @@ bool Thermostat::set_wwcharge(const char * value, const int8_t id) { // Set ww charge duration in steps of 15 min, ems+ bool Thermostat::set_wwchargeduration(const char * value, const int8_t id) { - uint8_t dhw = id2dhw(id); - int t; + auto dhw = dhw_circuit(id2dhw(id)); + if (dhw == nullptr) { + return false; + } + int t; if (!Helpers::value2number(value, t)) { return false; } t = (t + 8) / 15; - write_command(0x2F5 + dhw, 10, t, 0x02F5 + dhw); + write_command(0x2F5 + dhw->offset(), 10, t, 0x02F5 + dhw->offset()); return true; } @@ -2296,14 +2305,17 @@ bool Thermostat::set_switchProgMode(const char * value, const int8_t id) { // sets the thermostat ww circulation working mode, where mode is a string bool Thermostat::set_wwcircmode(const char * value, const int8_t id) { - uint8_t dhw = id2dhw(id); + auto dhw = dhw_circuit(id2dhw(id)); + if (dhw == nullptr) { + return false; + } uint8_t set; if (isRC300() || (model() == EMSdevice::EMS_DEVICE_FLAG_RC100)) { if (!Helpers::value2enum(value, set, FL_(enum_wwCircMode))) { return false; } - write_command(0x02F5 + dhw, 3, set, 0x02F5 + dhw); + write_command(0x02F5 + dhw->offset(), 3, set, 0x02F5 + dhw->offset()); return true; } if (!Helpers::value2enum(value, set, FL_(enum_wwMode2))) { @@ -2316,19 +2328,25 @@ bool Thermostat::set_wwcircmode(const char * value, const int8_t id) { } bool Thermostat::set_wwDailyHeating(const char * value, const int8_t id) { - uint8_t dhw = id2dhw(id); - bool b; + auto dhw = dhw_circuit(id2dhw(id)); + if (dhw == nullptr) { + return false; + } + bool b; if (!Helpers::value2bool(value, b)) { return false; } - write_command(0x2F5 + dhw, 8, b ? 0xFF : 0x00, 0x2F5 + dhw); + write_command(0x2F5 + dhw->offset(), 8, b ? 0xFF : 0x00, 0x2F5 + dhw->offset()); return true; } bool Thermostat::set_wwDailyHeatTime(const char * value, const int8_t id) { - uint8_t dhw = id2dhw(id); - int set; + auto dhw = dhw_circuit(id2dhw(id)); + if (dhw == nullptr) { + return false; + } + int set; if (!Helpers::value2number(value, set)) { return false; } @@ -2339,20 +2357,23 @@ bool Thermostat::set_wwDailyHeatTime(const char * value, const int8_t id) { return false; } - write_command(0x2F5 + dhw, 9, t, 0x2F5 + dhw); + write_command(0x2F5 + dhw->offset(), 9, t, 0x2F5 + dhw->offset()); } return true; } bool Thermostat::set_wwDisinfect(const char * value, const int8_t id) { - uint8_t dhw = id2dhw(id); - bool b; + auto dhw = dhw_circuit(id2dhw(id)); + if (dhw == nullptr) { + return false; + } + bool b; if (!Helpers::value2bool(value, b)) { return false; } if (isRC300() || (model() == EMSdevice::EMS_DEVICE_FLAG_RC100)) { - write_command(0x2F5 + dhw, 5, b ? 0xFF : 0x00, 0x2F5 + dhw); + write_command(0x2F5 + dhw->offset(), 5, b ? 0xFF : 0x00, 0x2F5 + dhw->offset()); } else if (model() == EMSdevice::EMS_DEVICE_FLAG_RC30) { write_command(EMS_TYPE_RC30wwSettings, 2, b ? 0xFF : 0x00, EMS_TYPE_RC30wwSettings); } else { @@ -2363,14 +2384,17 @@ bool Thermostat::set_wwDisinfect(const char * value, const int8_t id) { } bool Thermostat::set_wwDisinfectDay(const char * value, const int8_t id) { - uint8_t dhw = id2dhw(id); + auto dhw = dhw_circuit(id2dhw(id)); + if (dhw == nullptr) { + return false; + } uint8_t set; if (!Helpers::value2enum(value, set, FL_(enum_dayOfWeek))) { return false; } if (isRC300() || (model() == EMSdevice::EMS_DEVICE_FLAG_RC100)) { - write_command(0x2F5 + dhw, 7, set, 0x2F5 + dhw); + write_command(0x2F5 + dhw->offset(), 7, set, 0x2F5 + dhw->offset()); } else if (model() == EMSdevice::EMS_DEVICE_FLAG_RC30) { write_command(EMS_TYPE_RC30wwSettings, 3, set, EMS_TYPE_RC30wwSettings); } else { @@ -2381,13 +2405,16 @@ bool Thermostat::set_wwDisinfectDay(const char * value, const int8_t id) { } bool Thermostat::set_wwDisinfectHour(const char * value, const int8_t id) { - uint8_t dhw = id2dhw(id); - int set; + auto dhw = dhw_circuit( id2dhw(id)); + if (dhw == nullptr) { + return false; + } + int set; if (isRC300() || (model() == EMSdevice::EMS_DEVICE_FLAG_RC100)) { if (!Helpers::value2number(value, set, 0, 1431)) { return false; } - write_command(0x2F5 + dhw, 6, (set + 8) / 15, 0x2F5 + dhw); + write_command(0x2F5 + dhw->offset(), 6, (set + 8) / 15, 0x2F5 + dhw->offset()); } else if (model() == EMSdevice::EMS_DEVICE_FLAG_RC30) { if (!Helpers::value2number(value, set, 0, 23)) { return false; @@ -3401,7 +3428,7 @@ bool Thermostat::set_switchtime2(const char * value, const int8_t id) { } // sets a single switchtime in the thermostat dhw program for RC35 bool Thermostat::set_wwCircSwitchTime(const char * value, const int8_t id) { - auto dhw = dhw_circuit(255, id2dhw(id)); + auto dhw = dhw_circuit(id2dhw(id)); if (dhw == nullptr) { return false; } @@ -3418,7 +3445,7 @@ bool Thermostat::set_wwCircSwitchTime(const char * value, const int8_t id) { // sets a single switchtime in the thermostat circulation program for RC35 bool Thermostat::set_wwSwitchTime(const char * value, const int8_t id) { - auto dhw = dhw_circuit(255, id2dhw(id)); + auto dhw = dhw_circuit(id2dhw(id)); if (dhw != nullptr) { return false; } @@ -4366,7 +4393,7 @@ void Thermostat::register_device_values() { register_device_values_hc(new_hc); // also a dhw circuit... - auto new_dhw = std::make_shared(0, 1); // offset 0, dhw num 1 + auto new_dhw = std::make_shared(0); // offset 0, dhw num 1 dhw_circuits_.push_back(new_dhw); register_device_values_dhw(new_dhw); #endif @@ -4836,7 +4863,7 @@ void Thermostat::register_device_values_hc(std::shared_ptr dhw) { - int8_t tag = DeviceValueTAG::TAG_DHW1 + dhw->dhw(); + int8_t tag = dhw->id(); switch (this->model()) { case EMSdevice::EMS_DEVICE_FLAG_RC100: case EMSdevice::EMS_DEVICE_FLAG_RC300: diff --git a/src/devices/thermostat.h b/src/devices/thermostat.h index dc5ff593e..0b01687a9 100644 --- a/src/devices/thermostat.h +++ b/src/devices/thermostat.h @@ -173,9 +173,8 @@ class Thermostat : public EMSdevice { class DhwCircuit { public: - DhwCircuit(const uint8_t offset, const uint8_t dhw_num) - : offset_(offset) - , dhw_num_(dhw_num) { + DhwCircuit(const uint8_t offset) + : dhw_num_(offset) { } ~DhwCircuit() = default; uint8_t wwExtra_; @@ -201,16 +200,16 @@ class Thermostat : public EMSdevice { char wwHoliday_[22]; char wwVacation_[22]; - uint8_t dhw() const { - return dhw_num_ - 1; + uint8_t id() const { // returns TAG(id) + return DeviceValueTAG::TAG_DHW1 + dhw_num_; } - uint8_t offset() const { - return offset_; + + uint8_t offset() const { // returns telegram offset + return dhw_num_; } private: - uint8_t offset_; // telegram offset to base telegram - uint8_t dhw_num_; // dhw circuit number 1..10 + uint8_t dhw_num_; // dhw circuit number 0..10 }; private: @@ -230,7 +229,7 @@ class Thermostat : public EMSdevice { || (model() == EMSdevice::EMS_DEVICE_FLAG_CR120)); } - inline uint8_t id2dhw(const int8_t id) const { + inline uint8_t id2dhw(const int8_t id) const { // returns telegram offset for TAG(id) return id - DeviceValueTAG::TAG_DHW1; } @@ -394,7 +393,7 @@ class Thermostat : public EMSdevice { std::shared_ptr heating_circuit(std::shared_ptr telegram); std::shared_ptr heating_circuit(const int8_t id); - std::shared_ptr dhw_circuit(const uint8_t offset = 0, const uint8_t dhw_num = 255, const bool create = false); + std::shared_ptr dhw_circuit(const uint8_t offset, const bool create = false); void register_device_values_hc(std::shared_ptr hc); void register_device_values_dhw(std::shared_ptr dhw); diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index c87fd1f3d..b9f4ba0f4 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -332,6 +332,9 @@ std::string EMSdevice::to_string_short() { // for each telegram that has the fetch value set (true) do a read request void EMSdevice::fetch_values() { + if (!active_) { + return; + } #if defined(EMSESP_DEBUG) EMSESP::logger().debug("Fetching values for deviceID 0x%02X", device_id()); #endif diff --git a/src/emsdevice.h b/src/emsdevice.h index 0c801d443..448e41740 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -111,6 +111,10 @@ class EMSdevice { return brand_; } + inline void active(bool active) { + active_ = active; + } + // set custom device name inline void custom_name(std::string const & custom_name) { custom_name_ = custom_name; @@ -497,6 +501,7 @@ class EMSdevice { std::string custom_name_ = ""; // custom name uint8_t flags_ = 0; uint8_t brand_ = Brand::NO_BRAND; + bool active_ = true; bool ha_config_done_ = false; bool has_update_ = false; diff --git a/src/emsesp.cpp b/src/emsesp.cpp index b2b23c566..75aae0205 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -56,8 +56,8 @@ WebLogService EMSESP::webLogService = WebLogService(&webServer, EMSESP using DeviceFlags = EMSdevice; using DeviceType = EMSdevice::DeviceType; -std::vector> EMSESP::emsdevices; // array of all the detected EMS devices -std::vector EMSESP::device_library_; // library of all our known EMS devices, in heap +std::deque> EMSESP::emsdevices; // array of all the detected EMS devices +std::vector EMSESP::device_library_; // library of all our known EMS devices, in heap uuid::log::Logger EMSESP::logger_{F_(emsesp), uuid::log::Facility::KERN}; uuid::log::Logger EMSESP::logger() { @@ -943,20 +943,18 @@ void EMSESP::process_UBADevices(std::shared_ptr telegram) { // for each byte, check the bits and determine the device_id for (uint8_t data_byte = 0; data_byte < telegram->message_length; data_byte++) { uint8_t next_byte = telegram->message_data[data_byte]; - - if (next_byte) { - for (uint8_t bit = 0; bit < 8; bit++) { - if (next_byte & 0x01) { - uint8_t device_id = ((data_byte + 1) * 8) + bit; - // if we haven't already detected this device, request it's version details, unless its us (EMS-ESP) - // when the version info is received, it will automagically add the device - if ((device_id != EMSbus::ems_bus_id()) && !(EMSESP::device_exists(device_id))) { - LOG_DEBUG("New EMS device detected with ID 0x%02X. Requesting version information.", device_id); - send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id); - } + for (uint8_t bit = 0; bit < 8; bit++) { + uint8_t device_id = ((data_byte + 1) * 8) + bit; + EMSESP::device_active(device_id, next_byte & 0x01); + if (next_byte & 0x01) { + // if we haven't already detected this device, request it's version details, unless its us (EMS-ESP) + // when the version info is received, it will automagically add the device + if ((device_id != EMSbus::ems_bus_id()) && !(EMSESP::device_exists(device_id))) { + LOG_DEBUG("New EMS device detected with ID 0x%02X. Requesting version information.", device_id); + send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id); } - next_byte = next_byte >> 1; // advance 1 bit } + next_byte = next_byte >> 1; // advance 1 bit } } } @@ -1141,6 +1139,15 @@ bool EMSESP::device_exists(const uint8_t device_id) { return false; // not found } +void EMSESP::device_active(const uint8_t device_id, const bool active) { + for (auto & emsdevice : emsdevices) { + if (emsdevice && emsdevice->is_device_id(device_id)) { + emsdevice->active(active); + return; + } + } +} + // for each associated EMS device go and get its system information void EMSESP::show_devices(uuid::console::Shell & shell) { if (emsdevices.empty()) { diff --git a/src/emsesp.h b/src/emsesp.h index 9f1ba1efd..360642bff 100644 --- a/src/emsesp.h +++ b/src/emsesp.h @@ -125,6 +125,7 @@ class EMSESP { static void send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid); static bool device_exists(const uint8_t device_id); + static void device_active(const uint8_t device_id, const bool active); static bool cmd_is_readonly(const uint8_t device_type, const uint8_t device_id, const char * cmd, const int8_t id); static uint8_t device_id_from_cmd(const uint8_t device_type, const char * cmd, const int8_t id); @@ -219,7 +220,7 @@ class EMSESP { static bool return_not_found(JsonObject output, const char * msg, const char * cmd); - static std::vector> emsdevices; + static std::deque> emsdevices; // services static Mqtt mqtt_; diff --git a/src/locale_translations.h b/src/locale_translations.h index 55a49b86c..5312a1813 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -360,6 +360,7 @@ MAKE_TRANSLATION(emergencyOps, "emergencyops", "emergency operation", "Notbetrie MAKE_TRANSLATION(emergencyTemp, "emergencytemp", "emergency temperature", "Notfalltemperatur", "Noodtemperatuur", "Nöddrift temperatur", "temperatura w trybie awaryjnym", "nødtemperatur", "température d'urgence", "acil durum sıcaklığı", "temperatura di emergenza", "núdzová teplota") MAKE_TRANSLATION(pumpMode, "pumpmode", "boiler pump mode", "Kesselpumpenmodus", "Ketelpomp modus", "", "tryb pracy pompy kotła", "pumpemodus", "", "pompa modu", "modalità pompa caldaia", "režim kotlového čerpadla") // TODO translate MAKE_TRANSLATION(pumpCharacter, "pumpcharacter", "boiler pump characteristic", "Charakteristik der Kesselpumpe", "karakteristiek ketelpomp", "pannpumpsegenskaper", "charakterystyka pompy kotłowej", "kjelepumpekarakteristikk", "caractéristique de la pompe de la chaudière", "gazan nasosy", "caratteristica della pompa della caldaia", "charakteristika kotlového čerpadla") // TODO translate +MAKE_TRANSLATION(pumpOnTemp, "pumpontemp", "pump logic temperature", "Pumpenlogiktemperatur", "", "", "", "", "", "", "", "") // TODO translate MAKE_TRANSLATION(headertemp, "headertemp", "low loss header", "Hydr. Weiche", "open verdeler", "", "sprzęgło hydrauliczne", "", "bouteille de déc. hydr.", "isı bloğu gidiş suyu sıc.", "comp. idr.", "nízkostratová hlavica") // TODO translate MAKE_TRANSLATION(heatblock, "heatblock", "heating block", "Wärmezelle", "Aanvoertemp. warmtecel", "", "blok grzewczy", "", "départ corps de chauffe", "Hid.denge kabı sıcaklığı", "mandata scamb. pr.", "vykurovací blok") // TODO translate @@ -409,6 +410,7 @@ MAKE_TRANSLATION(hpSwitchValve, "hpswitchvalve", "switch valve", "Schaltventil", MAKE_TRANSLATION(hpActivity, "hpactivity", "compressor activity", "Kompressoraktivität", "Compressoractiviteit", "Kompressoraktivitet", "pompa ciepła, aktywność sprężarki", "kompressoraktivitet", "", "hp ısı pompası", "attività compressore", "činnosť kompresora") // TODO translate MAKE_TRANSLATION(hpMaxPower, "hpmaxpower", "compressor max power", "max. Kompressorleistung", "", "", "maksymalna wydajność sprężarki", "", "", "", "", "max výkon kompresora") // TODO translate +MAKE_TRANSLATION(pvMaxComp, "pvmaxcomp", "pv compressor max power", "PV max. Kompressorleistung", "", "", "maksymalna wydajność sprężarki", "", "", "", "", "pv max výkon kompresora") // TODO translate MAKE_TRANSLATION(hpPower, "hppower", "compressor power output", "Kompressorleistung", "Compressorvermogen", "Kompressoreffekt", "moc wyjściowa sprężarki", "kompressoreffekt", "puissance de sortie compresseur", "ısı pompası güç çıkışı", "potenza uscita compressore", "výkon kompresora") MAKE_TRANSLATION(hpTc0, "hptc0", "heat carrier return (TC0)", "Kältemittelrücklauf (TC0)", "Koudemiddel retour (TC0)", "Värmebärare Retur (TC0)", "temperatura nośnika ciepła na powrocie (TC0)", "kjølemiddel retur (TC0)", "retour caloporteur (TC0)", "sıcak su dönüşü (TC0)", "ritorno del refrigerante (TC0)", "návrat nosiča tepla (TC0)") MAKE_TRANSLATION(hpTc1, "hptc1", "heat carrier forward (TC1)", "Kältemittelvorlauf (TC1)", "Koudemiddel aanvoer (TC1)", "Värmebärare Framledning (TC1)", "temperatura nośnika ciepła pierwotna (TC1)", "kjølemiddel tur (TC1)", "avance caloporteur (TC1)", "sıcak su çıkışı (TC1)", "flusso di refrigerante (TC1)", "nosič tepla vpred (TC1)") diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 3bbdf2118..955248e8b 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -525,7 +525,7 @@ void Mqtt::on_connect() { resubscribe(); // publish to the last will topic (see Mqtt::start() function) to say we're alive - queue_publish_retain("status", "online", false); // with retain off + queue_publish_retain("status", "online", true); // retain: https://github.com/emsesp/EMS-ESP32/discussions/2086 } // Home Assistant Discovery - the main master Device called EMS-ESP diff --git a/src/system.cpp b/src/system.cpp index 531c7ff22..1c7d776cd 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -458,6 +458,21 @@ void System::start() { appused_ = ESP.getSketchSize() / 1024; appfree_ = esp_ota_get_running_partition()->size / 1024 - appused_; refreshHeapMem(); // refresh free heap and max alloc heap +#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 +#if ESP_IDF_VERSION_MAJOR < 5 + temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT(); + temp_sensor_get_config(&temp_sensor); + temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // DEFAULT: range:-10℃ ~ 80℃, error < 1℃. + temp_sensor_set_config(temp_sensor); + temp_sensor_start(); + temp_sensor_read_celsius(&temperature_); +#else + temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80); + temperature_sensor_install(&temp_sensor_config, &temperature_handle_); + temperature_sensor_enable(temperature_handle_); + temperature_sensor_get_celsius(temperature_handle_, &temperature_); +#endif +#endif #endif EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) { @@ -692,6 +707,9 @@ void System::heartbeat_json(JsonObject output) { #ifndef EMSESP_STANDALONE output["freemem"] = getHeapMem(); output["max_alloc"] = getMaxAllocMem(); +#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 + output["temperature"] = temperature_; +#endif #endif #ifndef EMSESP_STANDALONE @@ -770,6 +788,16 @@ void System::system_check() { if (!last_system_check_ || ((uint32_t)(uuid::get_uptime() - last_system_check_) >= SYSTEM_CHECK_FREQUENCY)) { last_system_check_ = uuid::get_uptime(); +#ifndef EMSESP_STANDALONE +#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 +#if ESP_IDF_VERSION_MAJOR < 5 + temp_sensor_read_celsius(&temperature_); +#else + temperature_sensor_get_celsius(temperature_handle_, &temperature_); +#endif +#endif +#endif + #ifdef EMSESP_PINGTEST static uint64_t ping_count = 0; LOG_NOTICE("Ping test, #%d", ping_count++); @@ -987,6 +1015,9 @@ void System::show_system(uuid::console::Shell & shell) { shell.printfln(" SDK version: %s", ESP.getSdkVersion()); shell.printfln(" CPU frequency: %lu MHz", ESP.getCpuFreqMHz()); +#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 + shell.printfln(" CPU temperature: %d °C", (int)temperature()); +#endif shell.printfln(" Free heap/Max alloc: %lu KB / %lu KB", getHeapMem(), getMaxAllocMem()); shell.printfln(" App used/free: %lu KB / %lu KB", appUsed(), appFree()); uint32_t FSused = LittleFS.usedBytes() / 1024; @@ -1444,6 +1475,10 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output node["freePsram"] = ESP.getFreePsram() / 1024; } node["model"] = EMSESP::system_.getBBQKeesGatewayDetails(); +#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 + node["temperature"] = EMSESP::system_.temperature(); +#endif + #endif // Network Status diff --git a/src/system.h b/src/system.h index 60b619195..3bf59eef7 100644 --- a/src/system.h +++ b/src/system.h @@ -39,6 +39,14 @@ #include #include +#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 +#if ESP_IDF_VERSION_MAJOR < 5 +#include "driver/temp_sensor.h" +#else +#include "driver/temperature_sensor.h" +#endif +#endif + using uuid::console::Shell; #define EMSESP_FS_CONFIG_DIRECTORY "/config" @@ -303,6 +311,12 @@ class System { test_set_all_active_ = n; } +#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 + float temperature() { + return temperature_; + } +#endif + private: static uuid::log::Logger logger_; static bool restart_requested_; @@ -395,6 +409,13 @@ class System { uint32_t psram_; uint32_t appused_; uint32_t appfree_; + +#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 +#if ESP_IDF_VERSION_MAJOR >= 5 + temperature_sensor_handle_t temperature_handle_ = NULL; +#endif + float temperature_ = 0; +#endif }; } // namespace emsesp diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 378e44cf1..1fffc5881 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -119,6 +119,9 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) { root["free_psram"] = ESP.getFreePsram() / 1024; } root["model"] = EMSESP::system_.getBBQKeesGatewayDetails(); +#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 + root["temperature"] = EMSESP::system_.temperature(); +#endif // check for a factory partition first const esp_partition_t * partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr);