mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-10 09:49:54 +03:00
initial commit with refactored mqtt commands
This commit is contained in:
@@ -18,37 +18,15 @@
|
||||
|
||||
#include "boiler.h"
|
||||
|
||||
MAKE_PSTR_WORD(boiler)
|
||||
MAKE_PSTR_WORD(wwtemp)
|
||||
MAKE_PSTR_WORD(flowtemp)
|
||||
MAKE_PSTR_WORD(wwactive)
|
||||
MAKE_PSTR_WORD(wwonetime)
|
||||
MAKE_PSTR_WORD(wwcirculation)
|
||||
MAKE_PSTR_WORD(comfort)
|
||||
MAKE_PSTR_WORD(eco)
|
||||
MAKE_PSTR_WORD(intelligent)
|
||||
MAKE_PSTR_WORD(hot)
|
||||
MAKE_PSTR_WORD(maxpower)
|
||||
MAKE_PSTR_WORD(minpower)
|
||||
|
||||
MAKE_PSTR(comfort_mandatory, "<hot | eco | intelligent>")
|
||||
|
||||
// shower
|
||||
MAKE_PSTR_WORD(shower)
|
||||
MAKE_PSTR_WORD(timer)
|
||||
MAKE_PSTR_WORD(alert)
|
||||
MAKE_PSTR(shower_timer_fmt, "Shower Timer is %s")
|
||||
MAKE_PSTR(shower_alert_fmt, "Shower Alert is %s")
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
REGISTER_FACTORY(Boiler, EMSdevice::DeviceType::BOILER)
|
||||
MAKE_PSTR(logger_name, "boiler")
|
||||
uuid::log::Logger Boiler::logger_{F_(logger_name), uuid::log::Facility::CONSOLE};
|
||||
|
||||
uuid::log::Logger Boiler::logger_{F_(boiler), uuid::log::Facility::CONSOLE};
|
||||
|
||||
Boiler::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)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
LOG_DEBUG(F("Registering new Boiler with device ID 0x%02X"), device_id);
|
||||
LOG_DEBUG(F("Adding new Boiler with device ID 0x%02X"), device_id);
|
||||
|
||||
// the telegram handlers...
|
||||
register_telegram_type(0x10, F("UBAErrorMessage1"), false, std::bind(&Boiler::process_UBAErrorMessage, this, _1));
|
||||
@@ -68,15 +46,22 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
||||
register_telegram_type(0xE3, F("UBAMonitorSlowPlus"), false, std::bind(&Boiler::process_UBAMonitorSlowPlus2, this, _1));
|
||||
register_telegram_type(0xE4, F("UBAMonitorFastPlus"), false, std::bind(&Boiler::process_UBAMonitorFastPlus, this, _1));
|
||||
register_telegram_type(0xE5, F("UBAMonitorSlowPlus"), false, std::bind(&Boiler::process_UBAMonitorSlowPlus, this, _1));
|
||||
|
||||
register_telegram_type(0xE9, F("UBADHWStatus"), false, std::bind(&Boiler::process_UBADHWStatus, this, _1));
|
||||
|
||||
// MQTT callbacks
|
||||
register_mqtt_topic("boiler_cmd", std::bind(&Boiler::boiler_cmd, this, _1));
|
||||
register_mqtt_topic("boiler_cmd_wwactivated", std::bind(&Boiler::boiler_cmd_wwactivated, this, _1));
|
||||
register_mqtt_topic("boiler_cmd_wwonetime", std::bind(&Boiler::boiler_cmd_wwonetime, this, _1));
|
||||
register_mqtt_topic("boiler_cmd_wwcirculation", std::bind(&Boiler::boiler_cmd_wwcirculation, this, _1));
|
||||
register_mqtt_topic("boiler_cmd_wwtemp", std::bind(&Boiler::boiler_cmd_wwtemp, this, _1));
|
||||
// MQTT commands for boiler_cmd topic
|
||||
register_mqtt_cmd(F("comfort"), std::bind(&Boiler::set_warmwater_mode, this, _1, _2));
|
||||
register_mqtt_cmd(F("wwactivated"), std::bind(&Boiler::set_warmwater_activated, this, _1, _2));
|
||||
register_mqtt_cmd(F("wwtapactivated"), std::bind(&Boiler::set_tapwarmwater_activated, this, _1, _2));
|
||||
register_mqtt_cmd(F("wwonetime"), std::bind(&Boiler::set_warmwater_onetime, this, _1, _2));
|
||||
register_mqtt_cmd(F("wwcirculation"), std::bind(&Boiler::set_warmwater_circulation, this, _1, _2));
|
||||
register_mqtt_cmd(F("flowtemp"), std::bind(&Boiler::set_flow_temp, this, _1, _2));
|
||||
register_mqtt_cmd(F("wwtemp"), std::bind(&Boiler::set_warmwater_temp, this, _1, _2));
|
||||
register_mqtt_cmd(F("burnmaxpower"), std::bind(&Boiler::set_max_power, this, _1, _2));
|
||||
register_mqtt_cmd(F("burnminpower"), std::bind(&Boiler::set_min_power, this, _1, _2));
|
||||
register_mqtt_cmd(F("boilhyston"), std::bind(&Boiler::set_hyst_on, this, _1, _2));
|
||||
register_mqtt_cmd(F("boilhystoff"), std::bind(&Boiler::set_hyst_off, this, _1, _2));
|
||||
register_mqtt_cmd(F("burnperiod"), std::bind(&Boiler::set_burn_period, this, _1, _2));
|
||||
register_mqtt_cmd(F("pumpdelay"), std::bind(&Boiler::set_pump_delay, this, _1, _2));
|
||||
}
|
||||
|
||||
// add submenu context
|
||||
@@ -86,156 +71,10 @@ void Boiler::add_context_menu() {
|
||||
flash_string_vector{F_(boiler)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
Boiler::console_commands(shell, ShellContext::BOILER);
|
||||
add_context_commands(ShellContext::BOILER);
|
||||
});
|
||||
}
|
||||
|
||||
// boiler_cmd topic
|
||||
void Boiler::boiler_cmd(const char * message) {
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_SMALL> doc;
|
||||
DeserializationError error = deserializeJson(doc, message);
|
||||
if (error) {
|
||||
LOG_DEBUG(F("MQTT error: payload %s, error %s"), message, error.c_str());
|
||||
return;
|
||||
}
|
||||
if (nullptr != doc["flowtemp"]) {
|
||||
uint8_t t = doc["flowtemp"];
|
||||
set_flow_temp(t);
|
||||
}
|
||||
if (nullptr != doc["wwtemp"]) {
|
||||
uint8_t t = doc["wwtemp"];
|
||||
set_warmwater_temp(t);
|
||||
}
|
||||
if (nullptr != doc["boilhyston"]) {
|
||||
int8_t t = doc["boilhyston"];
|
||||
set_hyst_on(t);
|
||||
}
|
||||
if (nullptr != doc["boilhystoff"]) {
|
||||
uint8_t t = doc["boilhystoff"];
|
||||
set_hyst_off(t);
|
||||
}
|
||||
if (nullptr != doc["burnperiod"]) {
|
||||
uint8_t t = doc["burnperiod"];
|
||||
set_burn_period(t);
|
||||
}
|
||||
if (nullptr != doc["burnminpower"]) {
|
||||
uint8_t p = doc["burnminpower"];
|
||||
set_min_power(p);
|
||||
}
|
||||
if (nullptr != doc["burnmaxpower"]) {
|
||||
uint8_t p = doc["burnmaxpower"];
|
||||
set_max_power(p);
|
||||
}
|
||||
if (nullptr != doc["pumpdelay"]) {
|
||||
uint8_t t = doc["pumpdelay"];
|
||||
set_pump_delay(t);
|
||||
}
|
||||
|
||||
if (nullptr != doc["comfort"]) {
|
||||
const char * data = doc["comfort"];
|
||||
if (strcmp((char *)data, "hot") == 0) {
|
||||
set_warmwater_mode(1);
|
||||
} else if (strcmp((char *)data, "eco") == 0) {
|
||||
set_warmwater_mode(2);
|
||||
} else if (strcmp((char *)data, "intelligent") == 0) {
|
||||
set_warmwater_mode(3);
|
||||
}
|
||||
}
|
||||
|
||||
const char * command = doc["cmd"];
|
||||
if (command == nullptr || doc["data"] == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// boiler ww comfort setting
|
||||
if (strcmp(command, "comfort") == 0) {
|
||||
const char * data = doc["data"];
|
||||
if (strcmp((char *)data, "hot") == 0) {
|
||||
set_warmwater_mode(1);
|
||||
} else if (strcmp((char *)data, "eco") == 0) {
|
||||
set_warmwater_mode(2);
|
||||
} else if (strcmp((char *)data, "intelligent") == 0) {
|
||||
set_warmwater_mode(3);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// boiler flowtemp setting
|
||||
if (strcmp(command, "flowtemp") == 0) {
|
||||
uint8_t t = doc["data"];
|
||||
set_flow_temp(t);
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "wwtemp") == 0) {
|
||||
uint8_t t = doc["data"];
|
||||
set_warmwater_temp(t);
|
||||
return;
|
||||
}
|
||||
// boiler max power setting
|
||||
if (strcmp(command, "burnmaxpower") == 0) {
|
||||
uint8_t p = doc["data"];
|
||||
set_max_power(p);
|
||||
return;
|
||||
}
|
||||
|
||||
// boiler min power setting
|
||||
if (strcmp(command, "burnminpower") == 0) {
|
||||
uint8_t p = doc["data"];
|
||||
set_min_power(p);
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "boilhyston") == 0) {
|
||||
int8_t t = doc["data"];
|
||||
set_hyst_on(t);
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "boilhystoff") == 0) {
|
||||
uint8_t t = doc["data"];
|
||||
set_hyst_off(t);
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "burnperiod") == 0) {
|
||||
uint8_t t = doc["data"];
|
||||
set_burn_period(t);
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "pumpdelay") == 0) {
|
||||
uint8_t t = doc["data"];
|
||||
set_pump_delay(t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Boiler::boiler_cmd_wwactivated(const char * message) {
|
||||
if ((message[0] == '1' || strcmp(message, "on") == 0) || (strcmp(message, "auto") == 0)) {
|
||||
set_warmwater_activated(true);
|
||||
} else if (message[0] == '0' || strcmp(message, "off") == 0) {
|
||||
set_warmwater_activated(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Boiler::boiler_cmd_wwonetime(const char * message) {
|
||||
if (message[0] == '1' || strcmp(message, "on") == 0) {
|
||||
set_warmwater_onetime(true);
|
||||
} else if (message[0] == '0' || strcmp(message, "off") == 0) {
|
||||
set_warmwater_onetime(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Boiler::boiler_cmd_wwcirculation(const char * message) {
|
||||
if (message[0] == '1' || strcmp(message, "on") == 0) {
|
||||
set_warmwater_circulation(true);
|
||||
} else if (message[0] == '0' || strcmp(message, "off") == 0) {
|
||||
set_warmwater_circulation(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Boiler::boiler_cmd_wwtemp(const char * message) {
|
||||
uint8_t t = atoi((char *)message);
|
||||
if (t) {
|
||||
set_warmwater_temp(t);
|
||||
}
|
||||
}
|
||||
|
||||
void Boiler::device_info(JsonArray & root) {
|
||||
JsonObject dataElement;
|
||||
|
||||
@@ -295,16 +134,16 @@ void Boiler::publish_values() {
|
||||
if (Helpers::hasValue(pumpMod2_)) {
|
||||
doc["pumpMod2"] = pumpMod2_;
|
||||
}
|
||||
if (Helpers::hasValue(wWCircPump_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWCircPump_, EMS_VALUE_BOOL)) {
|
||||
doc["wWCircPump"] = Helpers::render_value(s, wWCircPump_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(wWCircPumpType_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWCircPumpType_, EMS_VALUE_BOOL)) {
|
||||
doc["wWCiPuType"] = wWCircPumpType_ ? "valve" : "pump";
|
||||
}
|
||||
if (Helpers::hasValue(wWCircPumpMode_)) {
|
||||
doc["wWCiPuMode"] = wWCircPumpMode_;
|
||||
}
|
||||
if (Helpers::hasValue(wWCirc_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWCirc_, EMS_VALUE_BOOL)) {
|
||||
doc["wWCirc"] = Helpers::render_value(s, wWCirc_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(extTemp_)) {
|
||||
@@ -340,43 +179,43 @@ void Boiler::publish_values() {
|
||||
if (Helpers::hasValue(exhaustTemp_)) {
|
||||
doc["exhaustTemp"] = (float)exhaustTemp_ / 10;
|
||||
}
|
||||
if (Helpers::hasValue(wWActivated_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWActivated_, EMS_VALUE_BOOL)) {
|
||||
doc["wWActivated"] = Helpers::render_value(s, wWActivated_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(wWOneTime_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWOneTime_, EMS_VALUE_BOOL)) {
|
||||
doc["wWOnetime"] = Helpers::render_value(s, wWOneTime_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(wWDesinfecting_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWDesinfecting_, EMS_VALUE_BOOL)) {
|
||||
doc["wWDesinfecting"] = Helpers::render_value(s, wWDesinfecting_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(wWReadiness_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWReadiness_, EMS_VALUE_BOOL)) {
|
||||
doc["wWReady"] = Helpers::render_value(s, wWReadiness_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(wWRecharging_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWRecharging_, EMS_VALUE_BOOL)) {
|
||||
doc["wWRecharge"] = Helpers::render_value(s, wWRecharging_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(wWTemperatureOK_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWTemperatureOK_, EMS_VALUE_BOOL)) {
|
||||
doc["wWTempOK"] = Helpers::render_value(s, wWTemperatureOK_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(wWCirc_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWCirc_, EMS_VALUE_BOOL)) {
|
||||
doc["wWCirc"] = Helpers::render_value(s, wWCirc_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(burnGas_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(burnGas_, EMS_VALUE_BOOL)) {
|
||||
doc["burnGas"] = Helpers::render_value(s, burnGas_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(flameCurr_)) {
|
||||
doc["flameCurr"] = (float)(int16_t)flameCurr_ / 10;
|
||||
}
|
||||
if (Helpers::hasValue(heatPmp_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(heatPmp_, EMS_VALUE_BOOL)) {
|
||||
doc["heatPump"] = Helpers::render_value(s, heatPmp_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(fanWork_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(fanWork_, EMS_VALUE_BOOL)) {
|
||||
doc["fanWork"] = Helpers::render_value(s, fanWork_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(ignWork_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(ignWork_, EMS_VALUE_BOOL)) {
|
||||
doc["ignWork"] = Helpers::render_value(s, ignWork_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(wWHeat_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWHeat_, EMS_VALUE_BOOL)) {
|
||||
doc["wWHeat"] = Helpers::render_value(s, wWHeat_, EMS_VALUE_BOOL);
|
||||
}
|
||||
if (Helpers::hasValue(heating_temp_)) {
|
||||
@@ -450,16 +289,16 @@ bool Boiler::updated_values() {
|
||||
void Boiler::show_values(uuid::console::Shell & shell) {
|
||||
EMSdevice::show_values(shell); // for showing the header
|
||||
|
||||
if (Helpers::hasValue(tap_water_active_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(tap_water_active_, EMS_VALUE_BOOL)) {
|
||||
print_value(shell, 2, F("Hot tap water"), tap_water_active_ ? F("running") : F("off"));
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(heating_active_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(heating_active_, EMS_VALUE_BOOL)) {
|
||||
print_value(shell, 2, F("Central heating"), heating_active_ ? F("active") : F("off"));
|
||||
}
|
||||
|
||||
print_value(shell, 2, F("Warm Water activated"), wWActivated_, nullptr, EMS_VALUE_BOOL);
|
||||
if (Helpers::hasValue(wWCircPumpType_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(wWCircPumpType_, EMS_VALUE_BOOL)) {
|
||||
print_value(shell, 2, F("Warm Water charging type"), wWCircPumpType_ ? F("3-way valve") : F("charge pump"));
|
||||
}
|
||||
print_value(shell, 2, F("Warm Water circulation pump available"), wWCircPump_, nullptr, EMS_VALUE_BOOL);
|
||||
@@ -557,6 +396,8 @@ void Boiler::show_values(uuid::console::Shell & shell) {
|
||||
if (Helpers::hasValue(UBAuptime_)) {
|
||||
shell.printfln(F(" Total UBA working time: %d days %d hours %d minutes"), UBAuptime_ / 1440, (UBAuptime_ % 1440) / 60, UBAuptime_ % 60);
|
||||
}
|
||||
|
||||
shell.println();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -579,7 +420,7 @@ void Boiler::check_active() {
|
||||
|
||||
// see if the heating or hot tap water has changed, if so send
|
||||
// last_boilerActive stores heating in bit 1 and tap water in bit 2
|
||||
if (Helpers::hasValue(tap_water_active_, VALUE_BOOL) && Helpers::hasValue(heating_active_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(tap_water_active_, EMS_VALUE_BOOL) && Helpers::hasValue(heating_active_, EMS_VALUE_BOOL)) {
|
||||
uint8_t latest_boilerState = (tap_water_active_ << 1) + heating_active_;
|
||||
if (latest_boilerState != last_boilerState) {
|
||||
last_boilerState = latest_boilerState;
|
||||
@@ -650,12 +491,12 @@ void Boiler::process_UBATotalUptime(std::shared_ptr<const Telegram> telegram) {
|
||||
*/
|
||||
void Boiler::process_UBAParameters(std::shared_ptr<const Telegram> telegram) {
|
||||
telegram->read_value(heating_temp_, 1);
|
||||
telegram->read_value(burnPowermax_,2);
|
||||
telegram->read_value(burnPowermin_,3);
|
||||
telegram->read_value(boilTemp_off_,4);
|
||||
telegram->read_value(boilTemp_on_,5);
|
||||
telegram->read_value(burnPeriod_,6);
|
||||
telegram->read_value(pumpDelay_,8);
|
||||
telegram->read_value(burnPowermax_, 2);
|
||||
telegram->read_value(burnPowermin_, 3);
|
||||
telegram->read_value(boilTemp_off_, 4);
|
||||
telegram->read_value(boilTemp_on_, 5);
|
||||
telegram->read_value(burnPeriod_, 6);
|
||||
telegram->read_value(pumpDelay_, 8);
|
||||
telegram->read_value(pump_mod_max_, 9);
|
||||
telegram->read_value(pump_mod_min_, 10);
|
||||
}
|
||||
@@ -804,7 +645,7 @@ void Boiler::process_UBAMaintenanceStatus(std::shared_ptr<const Telegram> telegr
|
||||
// 0x10, 0x11, 0x12
|
||||
// not yet implemented
|
||||
void Boiler::process_UBAErrorMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
// data: displaycode(2), errornumner(2), year, month, hour, day, minute, duration(2), src-addr
|
||||
// data: displaycode(2), errornumber(2), year, month, hour, day, minute, duration(2), src-addr
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
@@ -818,67 +659,113 @@ void Boiler::process_UBAMaintenanceData(std::shared_ptr<const Telegram> telegram
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Commands
|
||||
*/
|
||||
|
||||
|
||||
// Set the warm water temperature 0x33
|
||||
void Boiler::set_warmwater_temp(const uint8_t temperature) {
|
||||
LOG_INFO(F("Setting boiler warm water temperature to %d C"), temperature);
|
||||
write_command(EMS_TYPE_UBAParameterWW, 2, temperature);
|
||||
write_command(EMS_TYPE_UBAFlags, 3, temperature); // for i9000, see #397
|
||||
void Boiler::set_warmwater_temp(const char * value, const int8_t id) {
|
||||
uint8_t v = 0;
|
||||
if (!Helpers::value2number(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting boiler warm water temperature to %d C"), v);
|
||||
write_command(EMS_TYPE_UBAParameterWW, 2, v);
|
||||
write_command(EMS_TYPE_UBAFlags, 3, v); // for i9000, see #397
|
||||
}
|
||||
|
||||
// flow temp
|
||||
void Boiler::set_flow_temp(const uint8_t temperature) {
|
||||
LOG_INFO(F("Setting boiler flow temperature to %d C"), temperature);
|
||||
write_command(EMS_TYPE_UBASetPoints, 0, temperature);
|
||||
void Boiler::set_flow_temp(const char * value, const int8_t id) {
|
||||
uint8_t v = 0;
|
||||
if (!Helpers::value2number(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting boiler flow temperature to %d C"), v);
|
||||
write_command(EMS_TYPE_UBASetPoints, 0, v);
|
||||
}
|
||||
|
||||
// set min boiler output
|
||||
void Boiler::set_min_power(const uint8_t power) {
|
||||
LOG_INFO(F("Setting boiler min power to "), power);
|
||||
write_command(EMS_TYPE_UBAParameters, 3, power);
|
||||
void Boiler::set_min_power(const char * value, const int8_t id) {
|
||||
uint8_t v = 0;
|
||||
if (!Helpers::value2number(value, v)) {
|
||||
return;
|
||||
}
|
||||
LOG_INFO(F("Setting boiler min power to "), v);
|
||||
write_command(EMS_TYPE_UBAParameters, 3, v);
|
||||
}
|
||||
|
||||
// set max temp
|
||||
void Boiler::set_max_power(const uint8_t power) {
|
||||
LOG_INFO(F("Setting boiler max power to %d C"), power);
|
||||
write_command(EMS_TYPE_UBAParameters, 2, power);
|
||||
void Boiler::set_max_power(const char * value, const int8_t id) {
|
||||
uint8_t v = 0;
|
||||
if (!Helpers::value2number(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting boiler max power to %d C"), v);
|
||||
write_command(EMS_TYPE_UBAParameters, 2, v);
|
||||
}
|
||||
|
||||
// set oiler on hysteresis
|
||||
void Boiler::set_hyst_on(const uint8_t temp) {
|
||||
LOG_INFO(F("Setting boiler hysteresis on to %d C"), temp);
|
||||
write_command(EMS_TYPE_UBAParameters, 5, temp);
|
||||
void Boiler::set_hyst_on(const char * value, const int8_t id) {
|
||||
uint8_t v = 0;
|
||||
if (!Helpers::value2number(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting boiler hysteresis on to %d C"), v);
|
||||
write_command(EMS_TYPE_UBAParameters, 5, v);
|
||||
}
|
||||
|
||||
// set boiler off hysteresis
|
||||
void Boiler::set_hyst_off(const uint8_t temp) {
|
||||
LOG_INFO(F("Setting boiler hysteresis off to %d C"), temp);
|
||||
write_command(EMS_TYPE_UBAParameters, 4, temp);
|
||||
void Boiler::set_hyst_off(const char * value, const int8_t id) {
|
||||
uint8_t v = 0;
|
||||
if (!Helpers::value2number(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting boiler hysteresis off to %d C"), v);
|
||||
write_command(EMS_TYPE_UBAParameters, 4, v);
|
||||
}
|
||||
|
||||
// set min burner period
|
||||
void Boiler::set_burn_period(const uint8_t t) {
|
||||
LOG_INFO(F("Setting burner min. period to %d min"), t);
|
||||
write_command(EMS_TYPE_UBAParameters, 6, t);
|
||||
void Boiler::set_burn_period(const char * value, const int8_t id) {
|
||||
uint8_t v = 0;
|
||||
if (!Helpers::value2number(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting burner min. period to %d min"), v);
|
||||
write_command(EMS_TYPE_UBAParameters, 6, v);
|
||||
}
|
||||
|
||||
// set pump delay
|
||||
void Boiler::set_pump_delay(const uint8_t t) {
|
||||
LOG_INFO(F("Setting boiler pump delay to %d min"), t);
|
||||
write_command(EMS_TYPE_UBAParameters, 8, t);
|
||||
void Boiler::set_pump_delay(const char * value, const int8_t id) {
|
||||
uint8_t v = 0;
|
||||
if (!Helpers::value2number(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting boiler pump delay to %d min"), v);
|
||||
write_command(EMS_TYPE_UBAParameters, 8, v);
|
||||
}
|
||||
|
||||
// 1=hot, 2=eco, 3=intelligent
|
||||
// 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)
|
||||
void Boiler::set_warmwater_mode(const uint8_t comfort) {
|
||||
// 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
|
||||
void Boiler::set_warmwater_mode(const char * value, const int8_t id) {
|
||||
if (value == nullptr) {
|
||||
return;
|
||||
}
|
||||
uint8_t set;
|
||||
if (comfort == 1) {
|
||||
if (strcmp(value, "hot") == 0) {
|
||||
LOG_INFO(F("Setting boiler warm water to Hot"));
|
||||
set = 0x00;
|
||||
} else if (comfort == 2) {
|
||||
} else if (strcmp(value, "eco") == 0) {
|
||||
LOG_INFO(F("Setting boiler warm water to Eco"));
|
||||
set = 0xD8;
|
||||
} else if (comfort == 3) {
|
||||
} else if (strcmp(value, "intelligent") == 0) {
|
||||
LOG_INFO(F("Setting boiler warm water to Intelligent"));
|
||||
set = 0xEC;
|
||||
} else {
|
||||
@@ -888,24 +775,33 @@ void Boiler::set_warmwater_mode(const uint8_t comfort) {
|
||||
}
|
||||
|
||||
// turn on/off warm water
|
||||
void Boiler::set_warmwater_activated(const bool activated) {
|
||||
LOG_INFO(F("Setting boiler warm water %s"), activated ? "on" : "off");
|
||||
uint8_t value;
|
||||
void Boiler::set_warmwater_activated(const char * value, const int8_t id) {
|
||||
bool v = false;
|
||||
if (!Helpers::value2bool(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting boiler warm water %s"), v ? "on" : "off");
|
||||
|
||||
// https://github.com/proddy/EMS-ESP/issues/268
|
||||
uint8_t n;
|
||||
if (EMSbus::is_ht3()) {
|
||||
value = (activated ? 0x08 : 0x00); // 0x08 is on, 0x00 is off
|
||||
n = (v ? 0x08 : 0x00); // 0x08 is on, 0x00 is off
|
||||
} else {
|
||||
value = (activated ? 0xFF : 0x00); // 0xFF is on, 0x00 is off
|
||||
n = (v ? 0xFF : 0x00); // 0xFF is on, 0x00 is off
|
||||
}
|
||||
write_command(EMS_TYPE_UBAParameterWW, 1, value);
|
||||
write_command(EMS_TYPE_UBAParameterWW, 1, n);
|
||||
}
|
||||
|
||||
// Activate / De-activate the Warm Tap Water
|
||||
// true = on, false = off
|
||||
// Note: Using the type 0x1D to put the boiler into Test mode. This may be shown on the boiler with a flashing 'T'
|
||||
void Boiler::set_tapwarmwater_activated(const bool activated) {
|
||||
LOG_INFO(F("Setting boiler warm tap water %s"), activated ? "on" : "off");
|
||||
void Boiler::set_tapwarmwater_activated(const char * value, const int8_t id) {
|
||||
bool v = false;
|
||||
if (!Helpers::value2bool(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting tap warm tap water %s"), v ? "on" : "off");
|
||||
uint8_t message_data[EMS_MAX_TELEGRAM_MESSAGE_LENGTH];
|
||||
for (uint8_t i = 0; i < sizeof(message_data); i++) {
|
||||
message_data[i] = 0x00;
|
||||
@@ -914,7 +810,7 @@ void Boiler::set_tapwarmwater_activated(const bool activated) {
|
||||
// we use the special test mode 0x1D for this. Setting the first data to 5A puts the system into test mode and
|
||||
// a setting of 0x00 puts it back into normal operating mode
|
||||
// when in test mode we're able to mess around with the 3-way valve settings
|
||||
if (!activated) {
|
||||
if (!v) {
|
||||
// on
|
||||
message_data[0] = 0x5A; // test mode on
|
||||
message_data[1] = 0x00; // burner output 0%
|
||||
@@ -932,16 +828,26 @@ void Boiler::set_tapwarmwater_activated(const bool activated) {
|
||||
// Activate / De-activate One Time warm water 0x35
|
||||
// true = on, false = off
|
||||
// See also https://github.com/proddy/EMS-ESP/issues/341#issuecomment-596245458 for Junkers
|
||||
void Boiler::set_warmwater_onetime(const bool activated) {
|
||||
LOG_INFO(F("Setting boiler warm water OneTime loading %s"), activated ? "on" : "off");
|
||||
write_command(EMS_TYPE_UBAFlags, 0, (activated ? 0x22 : 0x02));
|
||||
void Boiler::set_warmwater_onetime(const char * value, const int8_t id) {
|
||||
bool v = false;
|
||||
if (!Helpers::value2bool(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting boiler warm water OneTime loading %s"), v ? "on" : "off");
|
||||
write_command(EMS_TYPE_UBAFlags, 0, (v ? 0x22 : 0x02));
|
||||
}
|
||||
|
||||
// Activate / De-activate circulation of warm water 0x35
|
||||
// true = on, false = off
|
||||
void Boiler::set_warmwater_circulation(const bool activated) {
|
||||
LOG_INFO(F("Setting boiler warm water circulation %s"), activated ? "on" : "off");
|
||||
write_command(EMS_TYPE_UBAFlags, 1, (activated ? 0x22 : 0x02));
|
||||
void Boiler::set_warmwater_circulation(const char * value, const int8_t id) {
|
||||
bool v = false;
|
||||
if (!Helpers::value2bool(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(F("Setting boiler warm water circulation %s"), v ? "on" : "off");
|
||||
write_command(EMS_TYPE_UBAFlags, 1, (v ? 0x22 : 0x02));
|
||||
}
|
||||
|
||||
// add console commands
|
||||
@@ -955,115 +861,6 @@ void Boiler::console_commands(Shell & shell, unsigned int context) {
|
||||
EMSESP::send_read_request(type_id, device_id());
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::BOILER,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(wwtemp)},
|
||||
flash_string_vector{F_(degrees_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
set_warmwater_temp(Helpers::atoint(arguments.front().c_str()));
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::BOILER,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(flowtemp)},
|
||||
flash_string_vector{F_(degrees_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
set_flow_temp(Helpers::atoint(arguments.front().c_str()));
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::BOILER,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(maxpower)},
|
||||
flash_string_vector{F_(n_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
set_max_power(Helpers::atoint(arguments.front().c_str()));
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::BOILER,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(minpower)},
|
||||
flash_string_vector{F_(n_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
set_min_power(Helpers::atoint(arguments.front().c_str()));
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(
|
||||
ShellContext::BOILER,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(wwactive)},
|
||||
flash_string_vector{F_(bool_mandatory)},
|
||||
[=](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
if (arguments[0] == read_flash_string(F_(on))) {
|
||||
set_warmwater_activated(true);
|
||||
} else if (arguments[0] == read_flash_string(F_(off))) {
|
||||
set_warmwater_activated(false);
|
||||
} else {
|
||||
shell.println(F("Must be on or off"));
|
||||
return;
|
||||
}
|
||||
},
|
||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
|
||||
return std::vector<std::string>{read_flash_string(F_(on)), read_flash_string(F_(off))};
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(
|
||||
ShellContext::BOILER,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(wwonetime)},
|
||||
flash_string_vector{F_(bool_mandatory)},
|
||||
[=](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
if (arguments[0] == read_flash_string(F_(on))) {
|
||||
set_warmwater_onetime(true);
|
||||
} else if (arguments[0] == read_flash_string(F_(off))) {
|
||||
set_warmwater_onetime(false);
|
||||
} else {
|
||||
shell.println(F("Must be on or off"));
|
||||
return;
|
||||
}
|
||||
},
|
||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
|
||||
return std::vector<std::string>{read_flash_string(F_(on)), read_flash_string(F_(off))};
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(
|
||||
ShellContext::BOILER,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(wwcirculation)},
|
||||
flash_string_vector{F_(bool_mandatory)},
|
||||
[=](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
if (arguments[0] == read_flash_string(F_(on))) {
|
||||
set_warmwater_circulation(true);
|
||||
} else if (arguments[0] == read_flash_string(F_(off))) {
|
||||
set_warmwater_circulation(false);
|
||||
} else {
|
||||
shell.println(F("Must be on or off"));
|
||||
return;
|
||||
}
|
||||
},
|
||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
|
||||
return std::vector<std::string>{read_flash_string(F_(on)), read_flash_string(F_(off))};
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(
|
||||
ShellContext::BOILER,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(comfort)},
|
||||
flash_string_vector{F_(comfort_mandatory)},
|
||||
[=](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
if (arguments[0] == read_flash_string(F_(hot))) {
|
||||
set_warmwater_mode(1);
|
||||
} else if (arguments[0] == read_flash_string(F_(eco))) {
|
||||
set_warmwater_mode(2);
|
||||
} else if (arguments[0] == read_flash_string(F_(intelligent))) {
|
||||
set_warmwater_mode(3);
|
||||
} else {
|
||||
shell.println(F("Invalid value. Must be hot, eco or intelligent"));
|
||||
}
|
||||
},
|
||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
|
||||
return std::vector<std::string>{read_flash_string(F_(hot)), read_flash_string(F_(eco)), read_flash_string(F_(intelligent))};
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::BOILER,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(show)},
|
||||
|
||||
@@ -124,7 +124,7 @@ class Boiler : public EMSdevice {
|
||||
uint8_t burnPowermin_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t burnPowermax_ = EMS_VALUE_UINT_NOTSET;
|
||||
int8_t boilTemp_off_ = EMS_VALUE_INT_NOTSET;
|
||||
int8_t boilTemp_on_ = EMS_VALUE_UINT_NOTSET;
|
||||
int8_t boilTemp_on_ = EMS_VALUE_INT_NOTSET;
|
||||
uint8_t burnPeriod_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t pumpDelay_ = EMS_VALUE_UINT_NOTSET;
|
||||
|
||||
@@ -160,27 +160,20 @@ class Boiler : public EMSdevice {
|
||||
|
||||
void check_active();
|
||||
|
||||
void set_warmwater_temp(const uint8_t temperature);
|
||||
void set_flow_temp(const uint8_t temperature);
|
||||
void set_warmwater_mode(const uint8_t comfort);
|
||||
void set_warmwater_activated(const bool activated);
|
||||
void set_tapwarmwater_activated(const bool activated);
|
||||
void set_warmwater_onetime(const bool activated);
|
||||
void set_warmwater_circulation(const bool activated);
|
||||
void set_min_power(const uint8_t power);
|
||||
void set_max_power(const uint8_t power);
|
||||
void set_hyst_on(const uint8_t temp);
|
||||
void set_hyst_off(const uint8_t temp);
|
||||
void set_burn_period(const uint8_t t);
|
||||
void set_pump_delay(const uint8_t t);
|
||||
|
||||
|
||||
// mqtt callbacks
|
||||
void boiler_cmd(const char * message);
|
||||
void boiler_cmd_wwactivated(const char * message);
|
||||
void boiler_cmd_wwonetime(const char * message);
|
||||
void boiler_cmd_wwcirculation(const char * message);
|
||||
void boiler_cmd_wwtemp(const char * message);
|
||||
// commands
|
||||
void set_warmwater_mode(const char * value, const int8_t id);
|
||||
void set_warmwater_activated(const char * value, const int8_t id);
|
||||
void set_tapwarmwater_activated(const char * value, const int8_t id);
|
||||
void set_warmwater_onetime(const char * value, const int8_t id);
|
||||
void set_warmwater_circulation(const char * value, const int8_t id);
|
||||
void set_warmwater_temp(const char * value, const int8_t id);
|
||||
void set_flow_temp(const char * value, const int8_t id);
|
||||
void set_min_power(const char * value, const int8_t id);
|
||||
void set_max_power(const char * value, const int8_t id);
|
||||
void set_hyst_on(const char * value, const int8_t id);
|
||||
void set_hyst_off(const char * value, const int8_t id);
|
||||
void set_burn_period(const char * value, const int8_t id);
|
||||
void set_pump_delay(const char * value, const int8_t id);
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -22,16 +22,10 @@ namespace emsesp {
|
||||
|
||||
REGISTER_FACTORY(Connect, EMSdevice::DeviceType::CONNECT);
|
||||
|
||||
MAKE_PSTR(logger_name, "connect")
|
||||
uuid::log::Logger Connect::logger_{F_(logger_name), uuid::log::Facility::CONSOLE};
|
||||
uuid::log::Logger Connect::logger_{F_(connect), uuid::log::Facility::CONSOLE};
|
||||
|
||||
Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
// telegram handlers
|
||||
// register_telegram_type(EMS_TYPE_XX, "XX", false, std::bind(&Controller::process_XX, this, _1));
|
||||
|
||||
// MQTT callbacks
|
||||
// register_mqtt_topic("topic", std::bind(&Connect::cmd, this, _1));
|
||||
}
|
||||
|
||||
void Connect::device_info(JsonArray & root) {
|
||||
@@ -42,7 +36,7 @@ void Connect::add_context_menu() {
|
||||
|
||||
// display all values into the shell console
|
||||
void Connect::show_values(uuid::console::Shell & shell) {
|
||||
EMSdevice::show_values(shell); // always call this to show header
|
||||
// EMSdevice::show_values(shell); // always call this to show header
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
|
||||
@@ -18,22 +18,14 @@
|
||||
|
||||
#include "controller.h"
|
||||
|
||||
// MAKE_PSTR_WORD(controller)
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
REGISTER_FACTORY(Controller, EMSdevice::DeviceType::CONTROLLER);
|
||||
|
||||
MAKE_PSTR(logger_name, "controller")
|
||||
uuid::log::Logger Controller::logger_{F_(logger_name), uuid::log::Facility::CONSOLE};
|
||||
uuid::log::Logger Controller::logger_{F_(controller), uuid::log::Facility::CONSOLE};
|
||||
|
||||
Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
// telegram handlers
|
||||
// register_telegram_type(EMS_TYPE_XX, "XX", false, std::bind(&Controller::process_XX, this, _1));
|
||||
|
||||
// MQTT callbacks
|
||||
// register_mqtt_topic("topic", std::bind(&Controller::cmd, this, _1));
|
||||
}
|
||||
|
||||
void Controller::add_context_menu() {
|
||||
@@ -44,7 +36,7 @@ void Controller::device_info(JsonArray & root) {
|
||||
|
||||
// display all values into the shell console
|
||||
void Controller::show_values(uuid::console::Shell & shell) {
|
||||
EMSdevice::show_values(shell); // always call this to show header
|
||||
// EMSdevice::show_values(shell); // always call this to show header
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
|
||||
@@ -18,22 +18,14 @@
|
||||
|
||||
#include "gateway.h"
|
||||
|
||||
// MAKE_PSTR_WORD(gateway)
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
REGISTER_FACTORY(Gateway, EMSdevice::DeviceType::GATEWAY);
|
||||
|
||||
MAKE_PSTR(logger_name, "gateway")
|
||||
uuid::log::Logger Gateway::logger_{F_(logger_name), uuid::log::Facility::CONSOLE};
|
||||
uuid::log::Logger Gateway::logger_{F_(gateway), uuid::log::Facility::CONSOLE};
|
||||
|
||||
Gateway::Gateway(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
// telegram handlers
|
||||
// register_telegram_type(EMS_TYPE_XX, "XX", false, std::bind(&Controller::process_XX, this, _1));
|
||||
|
||||
// MQTT callbacks
|
||||
// register_mqtt_topic("topic", std::bind(&Gateway::cmd, this, _1));
|
||||
}
|
||||
|
||||
void Gateway::add_context_menu() {
|
||||
|
||||
@@ -18,32 +18,19 @@
|
||||
|
||||
#include "heatpump.h"
|
||||
|
||||
// MAKE_PSTR_WORD(heatpump)
|
||||
|
||||
/*
|
||||
example telegrams 0x32B, 0x37B
|
||||
"38 10 FF 00 03 7B 08 24 00 4B",
|
||||
"38 10 FF 00 03 2B 00 C7 07 C3 01",
|
||||
"38 10 FF 00 03 2B 00 D1 08 2A 01",
|
||||
*/
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
REGISTER_FACTORY(Heatpump, EMSdevice::DeviceType::HEATPUMP);
|
||||
|
||||
MAKE_PSTR(logger_name, "heatpump")
|
||||
uuid::log::Logger Heatpump::logger_{F_(logger_name), uuid::log::Facility::CONSOLE};
|
||||
uuid::log::Logger Heatpump::logger_{F_(heatpump), uuid::log::Facility::CONSOLE};
|
||||
|
||||
Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
LOG_DEBUG(F("Registering new Heat Pump module with device ID 0x%02X"), device_id);
|
||||
LOG_DEBUG(F("Adding new Heat Pump module with device ID 0x%02X"), device_id);
|
||||
|
||||
// telegram handlers
|
||||
register_telegram_type(0x047B, F("HP1"), true, std::bind(&Heatpump::process_HPMonitor1, this, _1));
|
||||
register_telegram_type(0x042B, F("HP2"), true, std::bind(&Heatpump::process_HPMonitor2, this, _1));
|
||||
|
||||
// MQTT callbacks
|
||||
// register_mqtt_topic("topic", std::bind(&Heatpump::cmd, this, _1));
|
||||
}
|
||||
|
||||
// context submenu
|
||||
@@ -55,7 +42,7 @@ void Heatpump::device_info(JsonArray & root) {
|
||||
|
||||
// display all values into the shell console
|
||||
void Heatpump::show_values(uuid::console::Shell & shell) {
|
||||
EMSdevice::show_values(shell); // always call this to show header
|
||||
// EMSdevice::show_values(shell); // always call this to show header
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
|
||||
@@ -22,12 +22,11 @@ namespace emsesp {
|
||||
|
||||
REGISTER_FACTORY(Mixing, EMSdevice::DeviceType::MIXING);
|
||||
|
||||
MAKE_PSTR(logger_name, "mixing")
|
||||
uuid::log::Logger Mixing::logger_{F_(logger_name), uuid::log::Facility::CONSOLE};
|
||||
uuid::log::Logger Mixing::logger_{F_(mixing), uuid::log::Facility::CONSOLE};
|
||||
|
||||
Mixing::Mixing(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)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
LOG_DEBUG(F("Registering new Mixing module with device ID 0x%02X"), device_id);
|
||||
LOG_DEBUG(F("Adding new Mixing module with device ID 0x%02X"), device_id);
|
||||
|
||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) {
|
||||
if (device_id <= 0x27) {
|
||||
@@ -48,9 +47,6 @@ Mixing::Mixing(uint8_t device_type, uint8_t device_id, uint8_t product_id, const
|
||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_IPM) {
|
||||
register_telegram_type(0x010C, F("IPMSetMessage"), false, std::bind(&Mixing::process_IPMStatusMessage, this, _1));
|
||||
}
|
||||
|
||||
// MQTT callbacks
|
||||
// register_mqtt_topic("topic", std::bind(&Mixing::cmd, this, _1));
|
||||
}
|
||||
|
||||
// add context submenu
|
||||
@@ -72,7 +68,6 @@ void Mixing::device_info(JsonArray & root) {
|
||||
render_value_json(root, "", F("Setpoint flow temperature"), flowSetTemp_, F_(degrees));
|
||||
render_value_json(root, "", F("Current pump modulation"), pumpMod_, F_(percent));
|
||||
render_value_json(root, "", F("Current valve status"), status_, nullptr);
|
||||
|
||||
}
|
||||
|
||||
// check to see if values have been updated
|
||||
@@ -101,6 +96,8 @@ void Mixing::show_values(uuid::console::Shell & shell) {
|
||||
print_value(shell, 4, F("Setpoint flow temperature"), flowSetTemp_, F_(degrees));
|
||||
print_value(shell, 4, F("Current pump modulation"), pumpMod_, F_(percent));
|
||||
print_value(shell, 4, F("Current valve status"), status_, nullptr);
|
||||
|
||||
shell.println();
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
|
||||
@@ -18,19 +18,15 @@
|
||||
|
||||
#include "solar.h"
|
||||
|
||||
MAKE_PSTR(kwh, "kWh")
|
||||
MAKE_PSTR(wh, "Wh")
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
REGISTER_FACTORY(Solar, EMSdevice::DeviceType::SOLAR);
|
||||
|
||||
MAKE_PSTR(logger_name, "solar")
|
||||
uuid::log::Logger Solar::logger_{F_(logger_name), uuid::log::Facility::CONSOLE};
|
||||
uuid::log::Logger Solar::logger_{F_(solar), uuid::log::Facility::CONSOLE};
|
||||
|
||||
Solar::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)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
LOG_DEBUG(F("Registering new Solar module with device ID 0x%02X"), device_id);
|
||||
LOG_DEBUG(F("Adding new Solar module with device ID 0x%02X"), device_id);
|
||||
|
||||
// telegram handlers
|
||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
||||
@@ -49,9 +45,6 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
register_telegram_type(0x0103, F("ISM1StatusMessage"), true, std::bind(&Solar::process_ISM1StatusMessage, this, _1));
|
||||
register_telegram_type(0x0101, F("ISM1Set"), false, std::bind(&Solar::process_ISM1Set, this, _1));
|
||||
}
|
||||
|
||||
// MQTT callbacks
|
||||
// register_mqtt_topic("topic", std::bind(&Solar::cmd, this, _1));
|
||||
}
|
||||
|
||||
// context submenu
|
||||
@@ -105,6 +98,8 @@ void Solar::show_values(uuid::console::Shell & shell) {
|
||||
print_value(shell, 2, F("Energy last hour"), energyLastHour_, F_(wh), 10);
|
||||
print_value(shell, 2, F("Energy today"), energyToday_, F_(wh));
|
||||
print_value(shell, 2, F("Energy total"), energyTotal_, F_(kwh), 10);
|
||||
|
||||
shell.println();
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
@@ -129,11 +124,11 @@ void Solar::publish_values() {
|
||||
doc["pumpmodulation"] = pumpModulation_;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(pump_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(pump_, EMS_VALUE_BOOL)) {
|
||||
doc["pump"] = Helpers::render_value(s, pump_, EMS_VALUE_BOOL);
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(valveStatus_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(valveStatus_, EMS_VALUE_BOOL)) {
|
||||
doc["valvestatus"] = Helpers::render_value(s, valveStatus_, EMS_VALUE_BOOL);
|
||||
}
|
||||
|
||||
@@ -141,11 +136,11 @@ void Solar::publish_values() {
|
||||
doc["pumpWorkMin"] = (float)pumpWorkMin_;
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(tankHeated_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(tankHeated_, EMS_VALUE_BOOL)) {
|
||||
doc["tankHeated"] = Helpers::render_value(s, tankHeated_, EMS_VALUE_BOOL);
|
||||
}
|
||||
|
||||
if (Helpers::hasValue(collectorOnOff_, VALUE_BOOL)) {
|
||||
if (Helpers::hasValue(collectorOnOff_, EMS_VALUE_BOOL)) {
|
||||
doc["collectorOnOff"] = Helpers::render_value(s, collectorOnOff_, EMS_VALUE_BOOL);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,22 +18,14 @@
|
||||
|
||||
#include "switch.h"
|
||||
|
||||
// MAKE_PSTR_WORD(switch)
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
REGISTER_FACTORY(Switch, EMSdevice::DeviceType::SWITCH);
|
||||
|
||||
MAKE_PSTR(logger_name, "switch")
|
||||
uuid::log::Logger Switch::logger_{F_(logger_name), uuid::log::Facility::CONSOLE};
|
||||
uuid::log::Logger Switch::logger_{F_(switch), uuid::log::Facility::CONSOLE};
|
||||
|
||||
Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const std::string & version, const std::string & name, uint8_t flags, uint8_t brand)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
// telegram handlers
|
||||
// register_telegram_type(EMS_TYPE_XX, "XX", false, std::bind(&Controller::process_XX, this, _1));
|
||||
|
||||
// MQTT callbacks
|
||||
// register_mqtt_topic("topic", std::bind(&Switch::cmd, this, _1));
|
||||
}
|
||||
|
||||
void Switch::add_context_menu() {
|
||||
@@ -44,7 +36,7 @@ void Switch::device_info(JsonArray & root) {
|
||||
|
||||
// display all values into the shell console
|
||||
void Switch::show_values(uuid::console::Shell & shell) {
|
||||
EMSdevice::show_values(shell); // always call this to show header
|
||||
// EMSdevice::show_values(shell); // always call this to show header
|
||||
}
|
||||
|
||||
// publish values via MQTT
|
||||
|
||||
@@ -18,22 +18,11 @@
|
||||
|
||||
#include "thermostat.h"
|
||||
|
||||
MAKE_PSTR_WORD(thermostat)
|
||||
MAKE_PSTR_WORD(master)
|
||||
MAKE_PSTR_WORD(temp)
|
||||
MAKE_PSTR_WORD(mode)
|
||||
MAKE_PSTR_WORD(wwmode)
|
||||
|
||||
MAKE_PSTR(hc_optional, "[heating circuit]")
|
||||
MAKE_PSTR(mode_mandatory, "<mode>")
|
||||
MAKE_PSTR(mode_optional, "[mode]")
|
||||
MAKE_PSTR(master_thermostat_fmt, "Master Thermostat device ID = %s")
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
REGISTER_FACTORY(Thermostat, EMSdevice::DeviceType::THERMOSTAT);
|
||||
MAKE_PSTR(logger_name, "thermostat")
|
||||
uuid::log::Logger Thermostat::logger_{F_(logger_name), uuid::log::Facility::CONSOLE};
|
||||
|
||||
uuid::log::Logger Thermostat::logger_{F_(thermostat), uuid::log::Facility::CONSOLE};
|
||||
|
||||
Thermostat::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)
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
@@ -138,18 +127,17 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
||||
uint8_t actual_master_thermostat = EMSESP::actual_master_thermostat(); // what we're actually using
|
||||
uint8_t num_devices = EMSESP::count_devices(EMSdevice::DeviceType::THERMOSTAT) + 1; // including this thermostat
|
||||
|
||||
// if we're on auto mode, register this thermostat if it has a device id of 0x10 or 0x17
|
||||
// if we're on auto mode, register this thermostat if it has a device id of 0x10, 0x17 or 0x18
|
||||
// or if its the master thermostat we defined
|
||||
// see https://github.com/proddy/EMS-ESP/issues/362#issuecomment-629628161
|
||||
if (((num_devices == 1) && (actual_master_thermostat == EMSESP_DEFAULT_MASTER_THERMOSTAT)) || (master_thermostat == device_id)) {
|
||||
EMSESP::actual_master_thermostat(device_id);
|
||||
LOG_DEBUG(F("Registering new thermostat with device ID 0x%02X (as master)"), device_id);
|
||||
LOG_DEBUG(F("Adding new thermostat with device ID 0x%02X (as master)"), device_id);
|
||||
init_mqtt();
|
||||
} else {
|
||||
LOG_DEBUG(F("Registering new thermostat with device ID 0x%02X"), device_id);
|
||||
LOG_DEBUG(F("Adding new thermostat with device ID 0x%02X"), device_id);
|
||||
}
|
||||
|
||||
|
||||
// for the thermostat, go a query all the heating circuits. This is only done once. The automatic fetch will from now on
|
||||
// only update the active heating circuits
|
||||
for (uint8_t i = 0; i < monitor_typeids.size(); i++) {
|
||||
@@ -160,14 +148,6 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
||||
}
|
||||
}
|
||||
|
||||
// for the master thermostat initialize the MQTT subscribes
|
||||
// these will be prefixed with hostname
|
||||
void Thermostat::init_mqtt() {
|
||||
register_mqtt_topic("thermostat_cmd", std::bind(&Thermostat::thermostat_cmd, this, _1)); // generic commands
|
||||
register_mqtt_topic("thermostat_cmd_temp", std::bind(&Thermostat::thermostat_cmd_temp, this, _1));
|
||||
register_mqtt_topic("thermostat_cmd_mode", std::bind(&Thermostat::thermostat_cmd_mode, this, _1));
|
||||
}
|
||||
|
||||
// prepare data for Web UI
|
||||
void Thermostat::device_info(JsonArray & root) {
|
||||
uint8_t flags = (this->flags() & 0x0F); // specific thermostat characteristics, strip the option bits
|
||||
@@ -205,14 +185,18 @@ void Thermostat::device_info(JsonArray & root) {
|
||||
dataElement = root.createNestedObject();
|
||||
std::string mode_str(15, '\0');
|
||||
snprintf_P(&mode_str[0], mode_str.capacity() + 1, PSTR("%sMode"), hc_str.c_str());
|
||||
dataElement["name"] = mode_str;
|
||||
dataElement["name"] = mode_str;
|
||||
std::string modetype_str(20, '\0');
|
||||
if (Helpers::hasValue(hc->summer_mode) && hc->summer_mode) {
|
||||
snprintf_P(&modetype_str[0], modetype_str.capacity() + 1, PSTR("%s - summer"), mode_tostring(hc->get_mode(flags)).c_str());
|
||||
} else if (Helpers::hasValue(hc->holiday_mode) && hc->holiday_mode) {
|
||||
snprintf_P(&modetype_str[0], modetype_str.capacity() + 1, PSTR("%s - holiday"), mode_tostring(hc->get_mode(flags)).c_str());
|
||||
} else if (Helpers::hasValue(hc->mode_type)) {
|
||||
snprintf_P(&modetype_str[0], modetype_str.capacity() + 1, PSTR("%s - %s"), mode_tostring(hc->get_mode(flags)).c_str(), mode_tostring(hc->get_mode_type(flags)).c_str());
|
||||
snprintf_P(&modetype_str[0],
|
||||
modetype_str.capacity() + 1,
|
||||
PSTR("%s - %s"),
|
||||
mode_tostring(hc->get_mode(flags)).c_str(),
|
||||
mode_tostring(hc->get_mode_type(flags)).c_str());
|
||||
} else {
|
||||
snprintf_P(&modetype_str[0], modetype_str.capacity() + 1, mode_tostring(hc->get_mode(flags)).c_str());
|
||||
}
|
||||
@@ -221,8 +205,9 @@ void Thermostat::device_info(JsonArray & root) {
|
||||
}
|
||||
}
|
||||
|
||||
// only add the menu for the master thermostat
|
||||
// context menu "thermostat"
|
||||
void Thermostat::add_context_menu() {
|
||||
// only add it once, to prevent conflicts when there are multiple thermostats
|
||||
if (device_id() != EMSESP::actual_master_thermostat()) {
|
||||
return;
|
||||
}
|
||||
@@ -232,318 +217,10 @@ void Thermostat::add_context_menu() {
|
||||
flash_string_vector{F_(thermostat)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
Thermostat::console_commands(shell, ShellContext::THERMOSTAT);
|
||||
add_context_commands(ShellContext::THERMOSTAT);
|
||||
});
|
||||
}
|
||||
|
||||
// general MQTT command for controlling thermostat
|
||||
// e.g. { "hc": 1, "cmd":"daytemp", "data": 20 }
|
||||
// or { "hc": 1, "daytemp": 20 } or { "hc2": { "daytemp":20 }}
|
||||
void Thermostat::thermostat_cmd(const char * message) {
|
||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_SMALL> doc;
|
||||
DeserializationError error = deserializeJson(doc, message);
|
||||
if (error) {
|
||||
LOG_DEBUG(F("MQTT error: payload %s, error %s"), message, error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// check for nested commands like {"hc2":{"temp":21}}
|
||||
for (const auto & hc : heating_circuits_) {
|
||||
char hc_name[6], s[3]; // hc{1-4}
|
||||
strlcpy(hc_name, "hc", 6);
|
||||
uint8_t hc_num = hc->hc_num();
|
||||
strlcat(hc_name, Helpers::itoa(s, hc_num), 6);
|
||||
if (nullptr != doc[hc_name]["mode"]) {
|
||||
std::string mode = doc[hc_name]["mode"];
|
||||
set_mode(mode, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["temp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::AUTO, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["nighttemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::NIGHT, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["daytemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::DAY, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["nofrosttemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::NOFROST, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["ecotemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::ECO, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["heattemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::HEAT, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["summertemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::SUMMER, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["designtemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::DESIGN, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["offsettemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::OFFSET, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["holidaytemp"]) { //
|
||||
set_temperature(f, HeatingCircuit::Mode::HOLIDAY, hc_num);
|
||||
}
|
||||
if (float f = doc[hc_name]["remotetemp"]) {
|
||||
if (f > 100 || f < 0) {
|
||||
Roomctrl::set_remotetemp(hc_num - 1, EMS_VALUE_SHORT_NOTSET);
|
||||
} else {
|
||||
Roomctrl::set_remotetemp(hc_num - 1, (int16_t)(f * 10));
|
||||
}
|
||||
}
|
||||
if (nullptr != doc[hc_name]["control"]) {
|
||||
uint8_t ctrl = doc[hc_name]["control"];
|
||||
set_control(ctrl, hc_num);
|
||||
}
|
||||
if (nullptr != doc[hc_name]["pause"]) {
|
||||
uint8_t p = doc[hc_name]["pause"];
|
||||
set_pause(p, hc_num);
|
||||
}
|
||||
if (nullptr != doc[hc_name]["party"]) {
|
||||
uint8_t p = doc[hc_name]["party"];
|
||||
set_party(p, hc_num);
|
||||
}
|
||||
if (nullptr != doc[hc_name]["holiday"]) {
|
||||
std::string holiday = doc[hc_name]["holiday"];
|
||||
set_holiday(holiday.c_str(), hc_num);
|
||||
}
|
||||
}
|
||||
// commands without heatingcircuit
|
||||
if (nullptr != doc["wwmode"]) {
|
||||
std::string mode = doc["wwmode"];
|
||||
set_ww_mode(mode);
|
||||
}
|
||||
if (float ct = doc["calinttemp"]) {
|
||||
set_settings_calinttemp((int8_t)(ct * 10));
|
||||
}
|
||||
if (nullptr != doc["minexttemp"]) {
|
||||
int8_t mt = doc["minexttemp"];
|
||||
set_settings_minexttemp(mt);
|
||||
}
|
||||
if (nullptr != doc["building"]) {
|
||||
std::string bds = doc["building"];
|
||||
uint8_t bd = doc["building"];
|
||||
if (strcmp(bds.c_str(), "light") == 0) {
|
||||
bd = 0;
|
||||
} else if (strcmp(bds.c_str(), "medium") == 0) {
|
||||
bd = 1;
|
||||
} else if (strcmp(bds.c_str(), "heavy") == 0) {
|
||||
bd = 2;
|
||||
}
|
||||
set_settings_building(bd);
|
||||
}
|
||||
if (nullptr != doc["language"]) {
|
||||
uint8_t lg = doc["language"];
|
||||
set_settings_language(lg);
|
||||
}
|
||||
if (nullptr != doc["display"]) {
|
||||
uint8_t dp = doc["display"];
|
||||
set_settings_display(dp);
|
||||
}
|
||||
if (nullptr != doc["clockoffset"]) {
|
||||
int8_t co = doc["clockoffset"];
|
||||
set_settings_clockoffset(co);
|
||||
}
|
||||
|
||||
// get heating circuit if it exists
|
||||
uint8_t hc_num = doc["hc"] | AUTO_HEATING_CIRCUIT;
|
||||
|
||||
// check for unnested commands like {"temp":21} or {"hc":2,"temp":21,"mode":"auto"}
|
||||
if (nullptr != doc["mode"]) {
|
||||
std::string mode = doc["mode"];
|
||||
set_mode(mode, hc_num);
|
||||
}
|
||||
if (float f = doc["temp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::AUTO, hc_num);
|
||||
}
|
||||
if (float f = doc["nighttemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::NIGHT, hc_num);
|
||||
}
|
||||
if (float f = doc["daytemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::DAY, hc_num);
|
||||
}
|
||||
if (float f = doc["nofrosttemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::NOFROST, hc_num);
|
||||
}
|
||||
if (float f = doc["ecotemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::ECO, hc_num);
|
||||
}
|
||||
if (float f = doc["heattemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::HEAT, hc_num);
|
||||
}
|
||||
if (float f = doc["summertemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::SUMMER, hc_num);
|
||||
}
|
||||
if (float f = doc["designtemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::DESIGN, hc_num);
|
||||
}
|
||||
if (float f = doc["offsettemp"]) {
|
||||
set_temperature(f, HeatingCircuit::Mode::OFFSET, hc_num);
|
||||
}
|
||||
if (float f = doc["holidaytemp"]) { //
|
||||
set_temperature(f, HeatingCircuit::Mode::HOLIDAY, hc_num);
|
||||
}
|
||||
if (float f = doc["remotetemp"]) {
|
||||
if (f > 100 || f < 0) {
|
||||
Roomctrl::set_remotetemp(hc_num - 1, EMS_VALUE_SHORT_NOTSET);
|
||||
} else {
|
||||
Roomctrl::set_remotetemp(hc_num - 1, (int16_t)(f * 10));
|
||||
}
|
||||
}
|
||||
if (nullptr != doc["control"]) {
|
||||
uint8_t ctrl = doc["control"];
|
||||
set_control(ctrl, hc_num);
|
||||
}
|
||||
if (nullptr != doc["pause"]) {
|
||||
uint8_t p = doc["pause"];
|
||||
set_pause(p, hc_num);
|
||||
}
|
||||
if (nullptr != doc["party"]) {
|
||||
uint8_t p = doc["party"];
|
||||
set_party(p, hc_num);
|
||||
}
|
||||
if (nullptr != doc["holiday"]) {
|
||||
std::string holiday = doc["holiday"];
|
||||
set_holiday(holiday.c_str(), hc_num);
|
||||
}
|
||||
if (nullptr != doc["date"]) {
|
||||
std::string date = doc["date"];
|
||||
set_datetime(date.c_str());
|
||||
}
|
||||
|
||||
// check for commands like {"hc":2,"cmd":"temp","data":21}
|
||||
const char * command = doc["cmd"];
|
||||
if (command == nullptr || doc["data"] == nullptr) {
|
||||
return;
|
||||
}
|
||||
// ok, we have command and data
|
||||
if (strcmp(command, "temp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f) {
|
||||
set_temperature(f, HeatingCircuit::Mode::AUTO, hc_num);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "mode") == 0) {
|
||||
std::string mode = doc["data"];
|
||||
if (mode.empty()) {
|
||||
return;
|
||||
}
|
||||
set_mode(mode, hc_num);
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "nighttemp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f) {
|
||||
set_temperature(f, HeatingCircuit::Mode::NIGHT, hc_num);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "daytemp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f) {
|
||||
set_temperature(f, HeatingCircuit::Mode::DAY, hc_num);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "holidaytemp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f) {
|
||||
set_temperature(f, HeatingCircuit::Mode::HOLIDAY, hc_num);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "ecotemp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f) {
|
||||
set_temperature(f, HeatingCircuit::Mode::ECO, hc_num);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "heattemp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f) {
|
||||
set_temperature(f, HeatingCircuit::Mode::HEAT, hc_num);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "nofrosttemp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f) {
|
||||
set_temperature(f, HeatingCircuit::Mode::NOFROST, hc_num);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "summertemp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f) {
|
||||
set_temperature(f, HeatingCircuit::Mode::SUMMER, hc_num);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "designtemp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f) {
|
||||
set_temperature(f, HeatingCircuit::Mode::DESIGN, hc_num);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "offsettemp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f) {
|
||||
set_temperature(f, HeatingCircuit::Mode::OFFSET, hc_num);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "remotetemp") == 0) {
|
||||
float f = doc["data"];
|
||||
if (f > 100 || f < 0) {
|
||||
Roomctrl::set_remotetemp(hc_num - 1, EMS_VALUE_SHORT_NOTSET);
|
||||
} else {
|
||||
Roomctrl::set_remotetemp(hc_num - 1, (int16_t)(f * 10));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "control") == 0) {
|
||||
uint8_t ctrl = doc["data"];
|
||||
set_control(ctrl, hc_num);
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "pause") == 0) {
|
||||
uint8_t p = doc["data"];
|
||||
set_pause(p, hc_num);
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "party") == 0) {
|
||||
uint8_t p = doc["data"];
|
||||
set_party(p, hc_num);
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "holiday") == 0) {
|
||||
std::string holiday = doc["data"];
|
||||
set_holiday(holiday.c_str(), hc_num);
|
||||
return;
|
||||
}
|
||||
if (strcmp(command, "date") == 0) {
|
||||
std::string date = doc["data"];
|
||||
set_datetime(date.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Thermostat::thermostat_cmd_temp(const char * message) {
|
||||
float f = strtof((char *)message, 0);
|
||||
set_temperature(f, HeatingCircuit::Mode::AUTO, AUTO_HEATING_CIRCUIT);
|
||||
}
|
||||
|
||||
// message payload holds the text name of the mode e.g. "auto"
|
||||
void Thermostat::thermostat_cmd_mode(const char * message) {
|
||||
std::string s(message);
|
||||
set_mode(s, AUTO_HEATING_CIRCUIT);
|
||||
}
|
||||
|
||||
// this function is called post the telegram handler function has been executed
|
||||
// we check if any of the thermostat values have changed and then republish if necessary
|
||||
bool Thermostat::updated_values() {
|
||||
@@ -761,12 +438,14 @@ void Thermostat::publish_values() {
|
||||
// returns the heating circuit object based on the hc number
|
||||
// of nullptr if it doesn't exist yet
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(const uint8_t hc_num) {
|
||||
// if hc_num is 0 then return the first existing hc in the list
|
||||
if (hc_num == 0) {
|
||||
// return first existing hc
|
||||
for (const auto & heating_circuit : heating_circuits_) {
|
||||
return heating_circuit;
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise find a match
|
||||
for (const auto & heating_circuit : heating_circuits_) {
|
||||
if (heating_circuit->hc_num() == hc_num) {
|
||||
return heating_circuit;
|
||||
@@ -1161,6 +840,8 @@ void Thermostat::show_values(uuid::console::Shell & shell) {
|
||||
print_value(shell, 4, F("Target flow temperature"), hc->targetflowtemp, F_(degrees));
|
||||
}
|
||||
}
|
||||
|
||||
shell.println();
|
||||
}
|
||||
|
||||
// 0xA8 - for reading the mode from the RC20 thermostat (0x17)
|
||||
@@ -1360,8 +1041,7 @@ void Thermostat::process_RC35Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// type 0x3D (HC1), 0x47 (HC2), 0x51 (HC3), 0x5B (HC4) - Working Mode Heating - for reading the mode from the RC35 thermostat (0x10)
|
||||
void Thermostat::process_RC35Set(std::shared_ptr<const Telegram> telegram) {
|
||||
// check to see we have a valid type
|
||||
// heating: 1 radiator, 2 convectors, 3 floors, 4 room supply
|
||||
// check to see we have a valid type. heating: 1 radiator, 2 convectors, 3 floors, 4 room supply
|
||||
if (telegram->message_data[0] == 0x00) {
|
||||
return;
|
||||
}
|
||||
@@ -1389,7 +1069,7 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
||||
return;
|
||||
}
|
||||
if (telegram->message_data[7] & 0x0C) { // date and time not valid
|
||||
set_datetime("NTP"); // set from NTP
|
||||
set_datetime("ntp", -1); // set from NTP
|
||||
return;
|
||||
}
|
||||
if (datetime_.empty()) {
|
||||
@@ -1415,8 +1095,69 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
||||
);
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Thermostat::console_commands(Shell & shell, unsigned int context) {
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(set), F_(master)},
|
||||
flash_string_vector{F_(deviceid_optional)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
uint8_t value;
|
||||
if (arguments.empty()) {
|
||||
value = EMSESP_DEFAULT_MASTER_THERMOSTAT;
|
||||
} else {
|
||||
value = Helpers::hextoint(arguments.front().c_str());
|
||||
}
|
||||
|
||||
EMSESP::emsespSettingsService.update(
|
||||
[&](EMSESPSettings & settings) {
|
||||
settings.master_thermostat = value;
|
||||
EMSESP::actual_master_thermostat(value); // set the internal value too
|
||||
char buffer[5];
|
||||
shell.printfln(F_(master_thermostat_fmt),
|
||||
!value ? uuid::read_flash_string(F_(auto)).c_str() : Helpers::hextoa(buffer, value));
|
||||
return StateUpdateResult::CHANGED;
|
||||
},
|
||||
"local");
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(read)},
|
||||
flash_string_vector{F_(typeid_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
uint16_t type_id = Helpers::hextoint(arguments.front().c_str());
|
||||
EMSESP::send_read_request(type_id, device_id());
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(show)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { show_values(shell); });
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(set)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) {
|
||||
char buffer[4];
|
||||
shell.printfln(F_(master_thermostat_fmt),
|
||||
settings.master_thermostat == 0 ? uuid::read_flash_string(F_(auto)).c_str()
|
||||
: Helpers::hextoa(buffer, settings.master_thermostat));
|
||||
shell.println();
|
||||
});
|
||||
});
|
||||
|
||||
// enter the context
|
||||
Console::enter_custom_context(shell, context);
|
||||
}
|
||||
|
||||
// 0xA5 - Set minimum external temperature
|
||||
void Thermostat::set_settings_minexttemp(const int8_t mt) {
|
||||
void Thermostat::set_settings_minexttemp(const char * value, const int8_t id) {
|
||||
int8_t mt = 0;
|
||||
if (!Helpers::value2number(value, mt)) {
|
||||
return;
|
||||
}
|
||||
if (((flags() & 0x0F) == EMS_DEVICE_FLAG_RC30_1) || ((flags() & 0x0F) == EMS_DEVICE_FLAG_RC35)) {
|
||||
LOG_INFO(F("Setting min external temperature to %d"), mt);
|
||||
write_command(EMS_TYPE_IBASettings, 5, mt);
|
||||
@@ -1424,14 +1165,25 @@ void Thermostat::set_settings_minexttemp(const int8_t mt) {
|
||||
}
|
||||
|
||||
// 0xA5 - Clock offset
|
||||
void Thermostat::set_settings_clockoffset(const int8_t co) {
|
||||
void Thermostat::set_settings_clockoffset(const char * value, const int8_t id) {
|
||||
int8_t co = 0;
|
||||
if (!Helpers::value2number(value, co)) {
|
||||
return;
|
||||
}
|
||||
if ((flags() & 0x0F) == EMS_DEVICE_FLAG_RC30_1) {
|
||||
LOG_INFO(F("Setting clock offset to %d"), co);
|
||||
write_command(EMS_TYPE_IBASettings, 12, co);
|
||||
}
|
||||
}
|
||||
|
||||
// 0xA5 - Calibrate internal temperature
|
||||
void Thermostat::set_settings_calinttemp(const int8_t ct) {
|
||||
void Thermostat::set_settings_calinttemp(const char * value, const int8_t id) {
|
||||
int8_t ct = 0;
|
||||
if (!Helpers::value2number(value, ct)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Michael - does this value need to be multiple by 10?
|
||||
if (((flags() & 0x0F) == EMS_DEVICE_FLAG_RC30_1) || ((flags() & 0x0F) == EMS_DEVICE_FLAG_RC35)) {
|
||||
LOG_INFO(F("Calibrating internal temperature to %d.%d"), ct / 10, ct < 0 ? -ct % 10 : ct % 10);
|
||||
write_command(EMS_TYPE_IBASettings, 2, ct);
|
||||
@@ -1439,15 +1191,50 @@ void Thermostat::set_settings_calinttemp(const int8_t ct) {
|
||||
}
|
||||
|
||||
// 0xA5 - Set the display settings
|
||||
void Thermostat::set_settings_display(const uint8_t ds) {
|
||||
void Thermostat::set_settings_display(const char * value, const int8_t id) {
|
||||
uint8_t ds = 0;
|
||||
if (!Helpers::value2number(value, ds)) {
|
||||
return;
|
||||
}
|
||||
if ((flags() & 0x0F) == EMS_DEVICE_FLAG_RC30_1) {
|
||||
LOG_INFO(F("Setting display to %d"), ds);
|
||||
write_command(EMS_TYPE_IBASettings, 0, ds);
|
||||
}
|
||||
}
|
||||
|
||||
void Thermostat::set_remotetemp(const char * value, const int8_t id) {
|
||||
float f = 0;
|
||||
if (!Helpers::value2float(value, f)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t hc_num = (id == -1) ? DEFAULT_HEATING_CIRCUIT : id;
|
||||
|
||||
if (f > 100 || f < 0) {
|
||||
Roomctrl::set_remotetemp(hc_num - 1, EMS_VALUE_SHORT_NOTSET);
|
||||
} else {
|
||||
Roomctrl::set_remotetemp(hc_num - 1, (int16_t)(f * 10));
|
||||
}
|
||||
}
|
||||
|
||||
// 0xA5 - Set the building settings
|
||||
void Thermostat::set_settings_building(const uint8_t bg) {
|
||||
void Thermostat::set_settings_building(const char * value, const int8_t id) {
|
||||
std::string bd;
|
||||
if (!Helpers::value2string(value, bd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t bg = 0;
|
||||
if (bd == "light") {
|
||||
bg = 0;
|
||||
} else if (bd == "medium") {
|
||||
bg = 1;
|
||||
} else if (bd == "heavy") {
|
||||
bg = 2;
|
||||
} else {
|
||||
return; // invalid
|
||||
}
|
||||
|
||||
if (((flags() & 0x0F) == EMS_DEVICE_FLAG_RC30_1) || ((flags() & 0x0F) == EMS_DEVICE_FLAG_RC35)) {
|
||||
LOG_INFO(F("Setting building to %d"), bg);
|
||||
write_command(EMS_TYPE_IBASettings, 6, bg);
|
||||
@@ -1455,7 +1242,11 @@ void Thermostat::set_settings_building(const uint8_t bg) {
|
||||
}
|
||||
|
||||
// 0xA5 Set the language settings
|
||||
void Thermostat::set_settings_language(const uint8_t lg) {
|
||||
void Thermostat::set_settings_language(const char * value, const int8_t id) {
|
||||
uint8_t lg = 0;
|
||||
if (!Helpers::value2number(value, lg)) {
|
||||
return;
|
||||
}
|
||||
if ((flags() & 0x0F) == EMS_DEVICE_FLAG_RC30_1) {
|
||||
LOG_INFO(F("Setting language to %d"), lg);
|
||||
write_command(EMS_TYPE_IBASettings, 1, lg);
|
||||
@@ -1463,16 +1254,25 @@ void Thermostat::set_settings_language(const uint8_t lg) {
|
||||
}
|
||||
|
||||
// Set the control-mode for hc 0-off, 1-RC20, 2-RC3x
|
||||
void Thermostat::set_control(const uint8_t ctrl, const uint8_t hc_num) {
|
||||
void Thermostat::set_control(const char * value, const int8_t id) {
|
||||
uint8_t ctrl = 0;
|
||||
if (!Helpers::value2number(value, ctrl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t hc_num = (id == -1) ? DEFAULT_HEATING_CIRCUIT : id;
|
||||
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
|
||||
if (hc == nullptr) {
|
||||
LOG_WARNING(F("Set control: Heating Circuit %d not found or activated"), hc_num);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctrl > 2) {
|
||||
LOG_WARNING(F("Set control: Invalid control mode: %d"), ctrl);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((flags() & 0x0F) == EMS_DEVICE_FLAG_RC35 || (flags() & 0x0F) == EMS_DEVICE_FLAG_RC30_1) {
|
||||
LOG_INFO(F("Setting circuit-control for hc%d to %d"), hc_num, ctrl);
|
||||
write_command(set_typeids[hc->hc_num() - 1], 26, ctrl);
|
||||
@@ -1482,23 +1282,37 @@ void Thermostat::set_control(const uint8_t ctrl, const uint8_t hc_num) {
|
||||
}
|
||||
|
||||
// sets the thermostat ww working mode, where mode is a string
|
||||
void Thermostat::set_ww_mode(const std::string & mode) {
|
||||
if (strcasecmp("off", mode.c_str()) == 0) {
|
||||
LOG_INFO(F("Setting thermostat warm water mode to %s"), mode.c_str());
|
||||
write_command(EMS_TYPE_wwSettings, 2, 0);
|
||||
} else if (strcasecmp("on", mode.c_str()) == 0) {
|
||||
LOG_INFO(F("Setting thermostat warm water mode to %s"), mode.c_str());
|
||||
write_command(EMS_TYPE_wwSettings, 2, 1);
|
||||
} else if (strcasecmp("auto", mode.c_str()) == 0) {
|
||||
LOG_INFO(F("Setting thermostat warm water mode to %s"), mode.c_str());
|
||||
write_command(EMS_TYPE_wwSettings, 2, 2);
|
||||
void Thermostat::set_wwmode(const char * value, const int8_t id) {
|
||||
std::string v;
|
||||
if (!Helpers::value2string(value, v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t set = 0xFF; // some dummy value
|
||||
if (v == "off") {
|
||||
set = 0;
|
||||
} else if (v == "on") {
|
||||
set = 1;
|
||||
} else if (v == "auto") {
|
||||
set = 2;
|
||||
}
|
||||
|
||||
if (set != 0xFF) {
|
||||
LOG_INFO(F("Setting thermostat warm water mode to %s"), v.c_str());
|
||||
write_command(EMS_TYPE_wwSettings, 2, set);
|
||||
} else {
|
||||
LOG_WARNING(F("Set thermostat warm water mode: Invalid mode: %s"), mode.c_str());
|
||||
LOG_WARNING(F("Set thermostat warm water mode: Invalid mode: %s"), v.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// set the holiday as string dd.mm.yyyy-dd.mm.yyyy
|
||||
void Thermostat::set_holiday(const char * hd, const uint8_t hc_num) {
|
||||
void Thermostat::set_holiday(const char * value, const int8_t id) {
|
||||
std::string hd;
|
||||
if (!Helpers::value2string(value, hd)) {
|
||||
return;
|
||||
}
|
||||
uint8_t hc_num = (id == -1) ? DEFAULT_HEATING_CIRCUIT : id;
|
||||
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
|
||||
if (hc == nullptr) {
|
||||
LOG_WARNING(F("Set holiday: Heating Circuit %d not found or activated for device ID 0x%02X"), hc_num, device_id());
|
||||
@@ -1520,7 +1334,13 @@ void Thermostat::set_holiday(const char * hd, const uint8_t hc_num) {
|
||||
}
|
||||
|
||||
// set pause in hours
|
||||
void Thermostat::set_pause(const uint8_t hrs, const uint8_t hc_num) {
|
||||
void Thermostat::set_pause(const char * value, const int8_t id) {
|
||||
uint8_t hrs = 0;
|
||||
if (!Helpers::value2number(value, hrs)) {
|
||||
return;
|
||||
}
|
||||
uint8_t hc_num = (id == -1) ? DEFAULT_HEATING_CIRCUIT : id;
|
||||
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
|
||||
if (hc == nullptr) {
|
||||
LOG_WARNING(F("Set pause: Heating Circuit %d not found or activated for device ID 0x%02X"), hc_num, device_id());
|
||||
@@ -1535,7 +1355,13 @@ void Thermostat::set_pause(const uint8_t hrs, const uint8_t hc_num) {
|
||||
}
|
||||
|
||||
// set partymode in hours
|
||||
void Thermostat::set_party(const uint8_t hrs, const uint8_t hc_num) {
|
||||
void Thermostat::set_party(const char * value, const int8_t id) {
|
||||
uint8_t hrs = 0;
|
||||
if (!Helpers::value2number(value, hrs)) {
|
||||
return;
|
||||
}
|
||||
uint8_t hc_num = (id == -1) ? DEFAULT_HEATING_CIRCUIT : id;
|
||||
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);
|
||||
if (hc == nullptr) {
|
||||
LOG_WARNING(F("Set party: Heating Circuit %d not found or activated for device ID 0x%02X"), hc_num, device_id());
|
||||
@@ -1551,11 +1377,17 @@ void Thermostat::set_party(const uint8_t hrs, const uint8_t hc_num) {
|
||||
|
||||
// set date&time as string hh:mm:ss-dd.mm.yyyy-dw-dst or "NTP" for setting to internet-time
|
||||
// dw - day of week (0..6), dst- summertime (0/1)
|
||||
void Thermostat::set_datetime(const char * dt) {
|
||||
// id is ignored
|
||||
void Thermostat::set_datetime(const char * value, const int8_t id) {
|
||||
std::string dt;
|
||||
if (!Helpers::value2string(value, dt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t data[9];
|
||||
if (strcmp(dt,"NTP") == 0) {
|
||||
time_t now = time(nullptr);
|
||||
tm * tm_ = localtime(&now);
|
||||
if (dt == "ntp") {
|
||||
time_t now = time(nullptr);
|
||||
tm * tm_ = localtime(&now);
|
||||
if (tm_->tm_year < 110) { // no NTP time
|
||||
LOG_WARNING(F("No NTP time. Cannot set RCtime"));
|
||||
return;
|
||||
@@ -1590,34 +1422,43 @@ void Thermostat::set_datetime(const char * dt) {
|
||||
}
|
||||
|
||||
// sets the thermostat working mode, where mode is a string
|
||||
void Thermostat::set_mode(const std::string & mode, const uint8_t hc_num) {
|
||||
// converts string mode to HeatingCircuit::Mode
|
||||
void Thermostat::set_mode(const char * value, const int8_t id) {
|
||||
std::string mode;
|
||||
if (!Helpers::value2string(value, mode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t hc_num = (id == -1) ? DEFAULT_HEATING_CIRCUIT : id;
|
||||
|
||||
if (mode_tostring(HeatingCircuit::Mode::OFF) == mode) {
|
||||
set_mode(HeatingCircuit::Mode::OFF, hc_num);
|
||||
set_mode_n(HeatingCircuit::Mode::OFF, hc_num);
|
||||
} else if (mode_tostring(HeatingCircuit::Mode::MANUAL) == mode) {
|
||||
set_mode(HeatingCircuit::Mode::MANUAL, hc_num);
|
||||
set_mode_n(HeatingCircuit::Mode::MANUAL, hc_num);
|
||||
} else if (mode_tostring(HeatingCircuit::Mode::AUTO) == mode) {
|
||||
set_mode(HeatingCircuit::Mode::AUTO, hc_num);
|
||||
set_mode_n(HeatingCircuit::Mode::AUTO, hc_num);
|
||||
} else if (mode_tostring(HeatingCircuit::Mode::DAY) == mode) {
|
||||
set_mode(HeatingCircuit::Mode::DAY, hc_num);
|
||||
set_mode_n(HeatingCircuit::Mode::DAY, hc_num);
|
||||
} else if (mode_tostring(HeatingCircuit::Mode::NIGHT) == mode) {
|
||||
set_mode(HeatingCircuit::Mode::NIGHT, hc_num);
|
||||
set_mode_n(HeatingCircuit::Mode::NIGHT, hc_num);
|
||||
} else if (mode_tostring(HeatingCircuit::Mode::HEAT) == mode) {
|
||||
set_mode(HeatingCircuit::Mode::HEAT, hc_num);
|
||||
set_mode_n(HeatingCircuit::Mode::HEAT, hc_num);
|
||||
} else if (mode_tostring(HeatingCircuit::Mode::NOFROST) == mode) {
|
||||
set_mode(HeatingCircuit::Mode::NOFROST, hc_num);
|
||||
set_mode_n(HeatingCircuit::Mode::NOFROST, hc_num);
|
||||
} else if (mode_tostring(HeatingCircuit::Mode::ECO) == mode) {
|
||||
set_mode(HeatingCircuit::Mode::ECO, hc_num);
|
||||
set_mode_n(HeatingCircuit::Mode::ECO, hc_num);
|
||||
} else if (mode_tostring(HeatingCircuit::Mode::HOLIDAY) == mode) {
|
||||
set_mode(HeatingCircuit::Mode::HOLIDAY, hc_num);
|
||||
set_mode_n(HeatingCircuit::Mode::HOLIDAY, hc_num);
|
||||
} else if (mode_tostring(HeatingCircuit::Mode::COMFORT) == mode) {
|
||||
set_mode(HeatingCircuit::Mode::COMFORT, hc_num);
|
||||
set_mode_n(HeatingCircuit::Mode::COMFORT, hc_num);
|
||||
} else {
|
||||
LOG_WARNING(F("Invalid mode %s. Cannot set"), mode.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Set the thermostat working mode
|
||||
void Thermostat::set_mode(const uint8_t mode, const uint8_t hc_num) {
|
||||
// mode is HeatingCircuit::Mode
|
||||
void Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) {
|
||||
if (can_write()) {
|
||||
LOG_WARNING(F("Write not supported for this model Thermostat"));
|
||||
return;
|
||||
@@ -1893,109 +1734,93 @@ void Thermostat::set_temperature(const float temperature, const uint8_t mode, co
|
||||
}
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Thermostat::console_commands(Shell & shell, unsigned int context) {
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(set), F_(master)},
|
||||
flash_string_vector{F_(deviceid_optional)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
uint8_t value;
|
||||
if (arguments.empty()) {
|
||||
value = EMSESP_DEFAULT_MASTER_THERMOSTAT;
|
||||
} else {
|
||||
value = Helpers::hextoint(arguments.front().c_str());
|
||||
}
|
||||
|
||||
EMSESP::emsespSettingsService.update(
|
||||
[&](EMSESPSettings & settings) {
|
||||
settings.master_thermostat = value;
|
||||
EMSESP::actual_master_thermostat(value); // set the internal value too
|
||||
char buffer[5];
|
||||
shell.printfln(F_(master_thermostat_fmt),
|
||||
!value ? uuid::read_flash_string(F_(auto)).c_str() : Helpers::hextoa(buffer, value));
|
||||
return StateUpdateResult::CHANGED;
|
||||
},
|
||||
"local");
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(read)},
|
||||
flash_string_vector{F_(typeid_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
uint16_t type_id = Helpers::hextoint(arguments.front().c_str());
|
||||
EMSESP::send_read_request(type_id, device_id());
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(temp)},
|
||||
flash_string_vector{F_(degrees_mandatory), F_(hc_optional), F_(mode_optional)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
uint8_t hc = (arguments.size() >= 2) ? arguments[1].at(0) - '0' : AUTO_HEATING_CIRCUIT;
|
||||
if ((arguments.size() == 3)) {
|
||||
set_temperature(atof(arguments.front().c_str()), arguments.back().c_str(), hc);
|
||||
} else if (arguments[1].at(0) >= 'A') {
|
||||
set_temperature(atof(arguments.front().c_str()), arguments.back().c_str(), AUTO_HEATING_CIRCUIT);
|
||||
} else {
|
||||
set_temperature(atof(arguments.front().c_str()), HeatingCircuit::Mode::AUTO, hc);
|
||||
}
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(
|
||||
ShellContext::THERMOSTAT,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(mode)},
|
||||
flash_string_vector{F_(mode_mandatory), F_(hc_optional)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
uint8_t hc = (arguments.size() == 2) ? arguments[1].at(0) - '0' : AUTO_HEATING_CIRCUIT;
|
||||
set_mode(arguments.front(), hc);
|
||||
},
|
||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
|
||||
return std::vector<std::string>{read_flash_string(F("off")),
|
||||
read_flash_string(F("manual")),
|
||||
read_flash_string(F("day")),
|
||||
read_flash_string(F("night")),
|
||||
read_flash_string(F("eco")),
|
||||
read_flash_string(F("comfort")),
|
||||
read_flash_string(F("heat")),
|
||||
read_flash_string(F("nofrost")),
|
||||
read_flash_string(F("auto"))
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(
|
||||
ShellContext::THERMOSTAT,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(wwmode)},
|
||||
flash_string_vector{F_(mode_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) { set_ww_mode(arguments.front()); },
|
||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
|
||||
return std::vector<std::string>{read_flash_string(F("off")), read_flash_string(F("on")), read_flash_string(F("auto"))};
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(show)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { show_values(shell); });
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(set)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) {
|
||||
char buffer[4];
|
||||
shell.printfln(F_(master_thermostat_fmt),
|
||||
settings.master_thermostat == 0 ? uuid::read_flash_string(F_(auto)).c_str()
|
||||
: Helpers::hextoa(buffer, settings.master_thermostat));
|
||||
shell.println();
|
||||
});
|
||||
});
|
||||
|
||||
// enter the context
|
||||
Console::enter_custom_context(shell, context);
|
||||
// for HA specifically when receiving over MQTT
|
||||
void Thermostat::thermostat_cmd_temp(const char * message) {
|
||||
float f = strtof((char *)message, 0);
|
||||
set_temperature(f, HeatingCircuit::Mode::AUTO, AUTO_HEATING_CIRCUIT);
|
||||
}
|
||||
|
||||
// for HA specifically when receiving over MQTT
|
||||
// message payload holds the text name of the mode e.g. "auto"
|
||||
void Thermostat::thermostat_cmd_mode(const char * message) {
|
||||
set_mode(message, AUTO_HEATING_CIRCUIT);
|
||||
}
|
||||
|
||||
void Thermostat::set_temperature_value(const char * value, const uint8_t id, const uint8_t mode) {
|
||||
float f = 0;
|
||||
uint8_t hc_num = (id == -1) ? DEFAULT_HEATING_CIRCUIT : id;
|
||||
if (Helpers::value2float(value, f)) {
|
||||
set_temperature(f, mode, hc_num);
|
||||
}
|
||||
}
|
||||
|
||||
void Thermostat::set_temp(const char * value, const int8_t id) {
|
||||
set_temperature_value(value, id, HeatingCircuit::Mode::AUTO);
|
||||
}
|
||||
|
||||
void Thermostat::set_nighttemp(const char * value, const int8_t id) {
|
||||
set_temperature_value(value, id, HeatingCircuit::Mode::NIGHT);
|
||||
}
|
||||
|
||||
void Thermostat::set_daytemp(const char * value, const int8_t id) {
|
||||
set_temperature_value(value, id, HeatingCircuit::Mode::DAY);
|
||||
}
|
||||
|
||||
void Thermostat::set_nofrosttemp(const char * value, const int8_t id) {
|
||||
set_temperature_value(value, id, HeatingCircuit::Mode::NOFROST);
|
||||
}
|
||||
|
||||
void Thermostat::set_ecotemp(const char * value, const int8_t id) {
|
||||
set_temperature_value(value, id, HeatingCircuit::Mode::ECO);
|
||||
}
|
||||
|
||||
void Thermostat::set_heattemp(const char * value, const int8_t id) {
|
||||
set_temperature_value(value, id, HeatingCircuit::Mode::HEAT);
|
||||
}
|
||||
|
||||
void Thermostat::set_summertemp(const char * value, const int8_t id) {
|
||||
set_temperature_value(value, id, HeatingCircuit::Mode::SUMMER);
|
||||
}
|
||||
|
||||
void Thermostat::set_designtemp(const char * value, const int8_t id) {
|
||||
set_temperature_value(value, id, HeatingCircuit::Mode::DESIGN);
|
||||
}
|
||||
|
||||
void Thermostat::set_offsettemp(const char * value, const int8_t id) {
|
||||
set_temperature_value(value, id, HeatingCircuit::Mode::OFFSET);
|
||||
}
|
||||
|
||||
void Thermostat::set_holidaytemp(const char * value, const int8_t id) {
|
||||
set_temperature_value(value, id, HeatingCircuit::Mode::HOLIDAY);
|
||||
}
|
||||
|
||||
// commands for MQTT and Console
|
||||
void Thermostat::init_mqtt() {
|
||||
register_mqtt_cmd(F("wwmode"), std::bind(&Thermostat::set_wwmode, this, _1, _2));
|
||||
register_mqtt_cmd(F("control"), std::bind(&Thermostat::set_control, this, _1, _2));
|
||||
register_mqtt_cmd(F("mode"), std::bind(&Thermostat::set_mode, this, _1, _2));
|
||||
register_mqtt_cmd(F("holiday"), std::bind(&Thermostat::set_holiday, this, _1, _2));
|
||||
register_mqtt_cmd(F("pause"), std::bind(&Thermostat::set_pause, this, _1, _2));
|
||||
register_mqtt_cmd(F("party"), std::bind(&Thermostat::set_party, this, _1, _2));
|
||||
register_mqtt_cmd(F("datetime"), std::bind(&Thermostat::set_datetime, this, _1, _2));
|
||||
register_mqtt_cmd(F("minexttemp"), std::bind(&Thermostat::set_settings_minexttemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("clockoffset"), std::bind(&Thermostat::set_settings_clockoffset, this, _1, _2));
|
||||
register_mqtt_cmd(F("calinttemp"), std::bind(&Thermostat::set_settings_calinttemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("display"), std::bind(&Thermostat::set_settings_display, this, _1, _2));
|
||||
register_mqtt_cmd(F("building"), std::bind(&Thermostat::set_settings_building, this, _1, _2));
|
||||
register_mqtt_cmd(F("language"), std::bind(&Thermostat::set_settings_language, this, _1, _2));
|
||||
register_mqtt_cmd(F("remotetemp"), std::bind(&Thermostat::set_remotetemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("temp"), std::bind(&Thermostat::set_temp, this, _1, _2));
|
||||
register_mqtt_cmd(F("nighttemp"), std::bind(&Thermostat::set_nighttemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("daytemp"), std::bind(&Thermostat::set_daytemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("nofrosttemp"), std::bind(&Thermostat::set_nofrosttemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("ecotemp"), std::bind(&Thermostat::set_ecotemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("heattemp"), std::bind(&Thermostat::set_heattemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("summertemp"), std::bind(&Thermostat::set_summertemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("designtemp"), std::bind(&Thermostat::set_designtemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("offsettemp"), std::bind(&Thermostat::set_offsettemp, this, _1, _2));
|
||||
register_mqtt_cmd(F("holidaytemp"), std::bind(&Thermostat::set_holidaytemp, this, _1, _2));
|
||||
}
|
||||
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -220,55 +220,61 @@ class Thermostat : public EMSdevice {
|
||||
void process_IBASettings(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RCTime(std::shared_ptr<const Telegram> telegram);
|
||||
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_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);
|
||||
void process_RC20Set(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC20Remote(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
void process_RC20Monitor_2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC20Set_2(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
void process_RC10Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC10Set(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
void process_RC300Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC300Set(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
void process_JunkersMonitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_JunkersSet(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
void process_EasyMonitor(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
void process_RC300WWmode(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
// set functions
|
||||
void set_settings_minexttemp(const int8_t mt);
|
||||
void set_settings_calinttemp(const int8_t ct);
|
||||
void set_settings_clockoffset(const int8_t co);
|
||||
void set_settings_display(const uint8_t ds);
|
||||
void set_settings_building(const uint8_t bg);
|
||||
void set_settings_language(const uint8_t lg);
|
||||
void set_control(const uint8_t ctrl, const uint8_t hc_num);
|
||||
void set_ww_mode(const std::string & mode);
|
||||
void set_holiday(const char * hd, const uint8_t hc_num);
|
||||
void set_datetime(const char * dt);
|
||||
void set_pause(const uint8_t hrs, const uint8_t hc_num);
|
||||
void set_party(const uint8_t hrs, const uint8_t hc_num);
|
||||
void set_mode(const uint8_t mode, const uint8_t hc_num);
|
||||
void set_mode(const std::string & mode, const uint8_t hc_num);
|
||||
// internal helper functions
|
||||
void set_mode_n(const uint8_t mode, const uint8_t hc_num);
|
||||
void set_temperature_value(const char * value, const uint8_t hc, const uint8_t mode);
|
||||
void set_temperature(const float temperature, const std::string & mode, const uint8_t hc_num);
|
||||
void set_temperature(const float temperature, const uint8_t mode, const uint8_t hc_num);
|
||||
|
||||
// MQTT functions
|
||||
void thermostat_cmd(const char * message);
|
||||
// for HA specifically. MQTT functions.
|
||||
void thermostat_cmd_temp(const char * message);
|
||||
void thermostat_cmd_mode(const char * message);
|
||||
|
||||
// set functions - these use the id/hc
|
||||
void set_mode(const char * value, const int8_t id);
|
||||
void set_control(const char * value, const int8_t id);
|
||||
void set_holiday(const char * value, const int8_t id);
|
||||
void set_pause(const char * value, const int8_t id);
|
||||
void set_party(const char * value, const int8_t id);
|
||||
void set_temp(const char * value, const int8_t id);
|
||||
void set_nighttemp(const char * value, const int8_t id);
|
||||
void set_daytemp(const char * value, const int8_t id);
|
||||
void set_nofrosttemp(const char * value, const int8_t id);
|
||||
void set_ecotemp(const char * value, const int8_t id);
|
||||
void set_heattemp(const char * value, const int8_t id);
|
||||
void set_summertemp(const char * value, const int8_t id);
|
||||
void set_designtemp(const char * value, const int8_t id);
|
||||
void set_offsettemp(const char * value, const int8_t id);
|
||||
void set_holidaytemp(const char * value, const int8_t id);
|
||||
void set_remotetemp(const char * value, const int8_t id);
|
||||
|
||||
// set functions - these don't use the id/hc
|
||||
void set_wwmode(const char * value, const int8_t id);
|
||||
void set_datetime(const char * value, const int8_t id);
|
||||
void set_settings_minexttemp(const char * value, const int8_t id);
|
||||
void set_settings_clockoffset(const char * value, const int8_t id);
|
||||
void set_settings_calinttemp(const char * value, const int8_t id);
|
||||
void set_settings_display(const char * value, const int8_t id);
|
||||
void set_settings_building(const char * value, const int8_t id);
|
||||
void set_settings_language(const char * value, const int8_t id);
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
Reference in New Issue
Block a user