Merge pull request #2091 from MichaelDvP/dev

S3-Temperature, Thermostat dhw circuits
This commit is contained in:
Proddy
2024-10-14 16:41:52 +01:00
committed by GitHub
16 changed files with 212 additions and 72 deletions

View File

@@ -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' : '')
}
/>
</ListItem>

View File

@@ -41,6 +41,7 @@ export interface SystemStatus {
has_loader: boolean;
has_partition: boolean;
status: string;
temperature?: number;
}
export enum LogLevel {

View File

@@ -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());
}

View File

@@ -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<const Telegram> 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<const Telegram> 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)) {

View File

@@ -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);

View File

@@ -557,10 +557,10 @@ uint8_t Thermostat::HeatingCircuit::get_mode_type() const {
return HeatingCircuit::Mode::DAY;
}
std::shared_ptr<Thermostat::DhwCircuit> Thermostat::dhw_circuit(const uint8_t offset, const uint8_t dhw_num, const bool create) {
std::shared_ptr<Thermostat::DhwCircuit> 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::DhwCircuit> 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<Thermostat::DhwCircuit>(offset, dhw_num);
auto new_dhw = std::make_shared<Thermostat::DhwCircuit>(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<const Telegram> 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<const Telegram> telegram) {
// Settings WW 0x37 - RC35
void Thermostat::process_RC35wwSettings(std::shared_ptr<const Telegram> 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<const Telegram> telegram
// Settings WW 0x3A - RC30
void Thermostat::process_RC30wwSettings(std::shared_ptr<const Telegram> 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<const Telegram> telegram
// type 0x38 (ww) and 0x39 (circ)
void Thermostat::process_RC35wwTimer(std::shared_ptr<const Telegram> 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<const Telegram> telegra
}
void Thermostat::process_JunkersWW(std::shared_ptr<const Telegram> 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<const Telegram> telegram) {
// types 0x31B
void Thermostat::process_RC300WWtemp(std::shared_ptr<const Telegram> 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<const Telegram> 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<const Telegram> 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,7 +2192,10 @@ 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);
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);
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,18 +2328,24 @@ 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);
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);
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);
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);
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<Thermostat::DhwCircuit>(0, 1); // offset 0, dhw num 1
auto new_dhw = std::make_shared<Thermostat::DhwCircuit>(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<Thermostat::HeatingCi
// registers the values for a heating circuit
void Thermostat::register_device_values_dhw(std::shared_ptr<Thermostat::DhwCircuit> 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:

View File

@@ -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<Thermostat::HeatingCircuit> heating_circuit(std::shared_ptr<const Telegram> telegram);
std::shared_ptr<Thermostat::HeatingCircuit> heating_circuit(const int8_t id);
std::shared_ptr<Thermostat::DhwCircuit> dhw_circuit(const uint8_t offset = 0, const uint8_t dhw_num = 255, const bool create = false);
std::shared_ptr<Thermostat::DhwCircuit> dhw_circuit(const uint8_t offset, const bool create = false);
void register_device_values_hc(std::shared_ptr<Thermostat::HeatingCircuit> hc);
void register_device_values_dhw(std::shared_ptr<Thermostat::DhwCircuit> dhw);

View File

@@ -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

View File

@@ -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;

View File

@@ -56,7 +56,7 @@ WebLogService EMSESP::webLogService = WebLogService(&webServer, EMSESP
using DeviceFlags = EMSdevice;
using DeviceType = EMSdevice::DeviceType;
std::vector<std::unique_ptr<EMSdevice>> EMSESP::emsdevices; // array of all the detected EMS devices
std::deque<std::unique_ptr<EMSdevice>> EMSESP::emsdevices; // array of all the detected EMS devices
std::vector<EMSESP::Device_record> EMSESP::device_library_; // library of all our known EMS devices, in heap
uuid::log::Logger EMSESP::logger_{F_(emsesp), uuid::log::Facility::KERN};
@@ -943,11 +943,10 @@ void EMSESP::process_UBADevices(std::shared_ptr<const Telegram> 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;
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))) {
@@ -959,7 +958,6 @@ void EMSESP::process_UBADevices(std::shared_ptr<const Telegram> telegram) {
}
}
}
}
// process the Version telegram (type 0x02), which is a common type
// e.g. 09 0B 02 00 PP V1 V2
@@ -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()) {

View File

@@ -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<std::unique_ptr<EMSdevice>> emsdevices;
static std::deque<std::unique_ptr<EMSdevice>> emsdevices;
// services
static Mqtt mqtt_;

View File

@@ -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)")

View File

@@ -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

View File

@@ -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

View File

@@ -39,6 +39,14 @@
#include <uuid/log.h>
#include <PButton.h>
#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

View File

@@ -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);