This commit is contained in:
Paul
2020-05-23 14:00:14 +02:00
parent 1ceef8afd5
commit b2bb8e2b5a
24 changed files with 391 additions and 304 deletions

View File

@@ -55,14 +55,14 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_telegram_type(0x1C, F("UBAMaintenanceStatus"), false, std::bind(&Boiler::process_UBAMaintenanceStatus, this, _1));
register_telegram_type(0x2A, F("MC10Status"), false, std::bind(&Boiler::process_MC10Status, this, _1));
register_telegram_type(0x33, F("UBAParameterWW"), true, std::bind(&Boiler::process_UBAParameterWW, this, _1));
register_telegram_type(0x14, F("UBATotalUptime"), true, std::bind(&Boiler::process_UBATotalUptime, this, _1));
register_telegram_type(0x14, F("UBATotalUptime"), false, std::bind(&Boiler::process_UBATotalUptime, this, _1));
register_telegram_type(0x35, F("UBAFlags"), false, std::bind(&Boiler::process_UBAFlags, this, _1));
register_telegram_type(0x15, F("UBAMaintenanceSettings"), false, std::bind(&Boiler::process_UBAMaintenanceSettings, this, _1));
register_telegram_type(0x16, F("UBAParameters"), true, std::bind(&Boiler::process_UBAParameters, this, _1));
register_telegram_type(0x1A, F("UBASetPoints"), false, std::bind(&Boiler::process_UBASetPoints, this, _1));
register_telegram_type(0xD1, F("UBAOutdoorTemp"), false, std::bind(&Boiler::process_UBAOutdoorTemp, 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(0xE4, F("UBAMonitorFastPlus"), true, std::bind(&Boiler::process_UBAMonitorFastPlus, this, _1));
register_telegram_type(0xE5, F("UBAMonitorSlowPlus"), true, std::bind(&Boiler::process_UBAMonitorSlowPlus, this, _1));
register_telegram_type(0xE9, F("UBADHWStatus"), false, std::bind(&Boiler::process_UBADHWStatus, this, _1));
register_telegram_type(0xE3, F("HeatPumpMonitor1"), true, std::bind(&Boiler::process_HPMonitor1, this, _1));
@@ -82,8 +82,7 @@ void Boiler::add_context_menu() {
CommandFlags::USER,
flash_string_vector{F_(boiler)},
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
dynamic_cast<EMSESPShell &>(shell).enter_custom_context(ShellContext::BOILER);
console_commands();
Boiler::console_commands(shell, ShellContext::BOILER);
});
}
@@ -316,7 +315,10 @@ void Boiler::publish_values() {
DEBUG_LOG(F("[DEBUG] Performing a boiler publish"));
#endif
Mqtt::publish("boiler_data", doc);
// if we have data, publish it
if (!doc.isNull()) {
Mqtt::publish("boiler_data", doc);
}
}
// called after a process command is called, to check values and see if we need to force an MQTT publish
@@ -330,22 +332,22 @@ void Boiler::show_values(uuid::console::Shell & shell) {
char buffer[10]; // used for formatting
print_value(shell, F("Selected flow temperature"), F_(degrees), Helpers::render_value(buffer, selFlowTemp_, 1));
print_value(shell, F("Warm Water selected temperature"), F_(degrees), Helpers::render_value(buffer, wWSelTemp_, 1));
print_value(shell, 2, F("Selected flow temperature"), F_(degrees), Helpers::render_value(buffer, selFlowTemp_, 1));
print_value(shell, 2, F("Warm Water selected temperature"), F_(degrees), Helpers::render_value(buffer, wWSelTemp_, 1));
if (tap_water_active_ != EMS_VALUE_BOOL_NOTSET) {
print_value(shell, F("Hot tap water"), tap_water_active_ ? "running" : "off");
print_value(shell, 2, F("Hot tap water"), tap_water_active_ ? "running" : "off");
}
if (heating_active_ != EMS_VALUE_BOOL_NOTSET) {
print_value(shell, F("Central heating"), heating_active_ ? "active" : "off");
print_value(shell, 2, F("Central heating"), heating_active_ ? "active" : "off");
}
print_value(shell, F("Warm Water activated"), Helpers::render_value(buffer, wWActivated_, EMS_VALUE_BOOL));
print_value(shell, F("Warm Water circulation pump available"), Helpers::render_value(buffer, wWCircPump_, EMS_VALUE_BOOL));
print_value(shell, F("Warm Water circulation pump type"), wWCircPumpType_ ? "3-way pump" : "charge pump");
print_value(shell, 2, F("Warm Water activated"), Helpers::render_value(buffer, wWActivated_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Warm Water circulation pump available"), Helpers::render_value(buffer, wWCircPump_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Warm Water circulation pump type"), wWCircPumpType_ ? "3-way pump" : "charge pump");
if (wWCircPumpMode_ == 7) {
print_value(shell, F("Warm Water circulation pump freq"), "continuous");
print_value(shell, 2, F("Warm Water circulation pump freq"), "continuous");
} else {
char s[7];
char buffer[2];
@@ -353,64 +355,64 @@ void Boiler::show_values(uuid::console::Shell & shell) {
buffer[1] = '\0';
strlcpy(s, buffer, 7);
strlcat(s, "x3min", 7);
print_value(shell, F("Warm Water circulation pump freq"), s);
print_value(shell, 2, F("Warm Water circulation pump freq"), s);
}
if (wWComfort_ == 0x00) {
print_value(shell, F("Warm Water comfort setting"), "Hot");
print_value(shell, 2, F("Warm Water comfort setting"), "Hot");
} else if (wWComfort_ == 0xD8) {
print_value(shell, F("Warm Water comfort setting"), "Eco");
print_value(shell, 2, F("Warm Water comfort setting"), "Eco");
} else if (wWComfort_ == 0xEC) {
print_value(shell, F("Warm Water comfort setting"), "Intelligent");
print_value(shell, 2, F("Warm Water comfort setting"), "Intelligent");
}
print_value(shell, F("Warm Water selected temperature"), F_(degrees), Helpers::render_value(buffer, wWSelTemp_, 1));
print_value(shell, F("Warm Water disinfection temperature"), F_(degrees), Helpers::render_value(buffer, wWDisinfectTemp_, 1));
print_value(shell, F("Warm Water circulation active"), F_(degrees), Helpers::render_value(buffer, wWCirc_, EMS_VALUE_BOOL));
print_value(shell, F("Warm Water set temperature"), F_(degrees), Helpers::render_value(buffer, wWSetTmp_, 1));
print_value(shell, F("Warm Water current temperature"), F_(degrees), Helpers::render_value(buffer, wWCurTmp_, 10));
print_value(shell, F("Warm water temperature (intern)"), F_(degrees), Helpers::render_value(buffer, wwStorageTemp1_, 10));
print_value(shell, F("Warm water temperature (extern)"), F_(degrees), Helpers::render_value(buffer, wwStorageTemp2_, 10));
print_value(shell, F("Warm Water current temperature (extern)"), F_(degrees), Helpers::render_value(buffer, wWCurTmp2_, 10));
print_value(shell, F("Warm Water current tap water flow"), F("l/min"), Helpers::render_value(buffer, wWCurFlow_, 10));
print_value(shell, F("Warm Water # starts"), Helpers::render_value(buffer, wWStarts_, 1));
print_value(shell, 2, F("Warm Water selected temperature"), F_(degrees), Helpers::render_value(buffer, wWSelTemp_, 1));
print_value(shell, 2, F("Warm Water disinfection temperature"), F_(degrees), Helpers::render_value(buffer, wWDisinfectTemp_, 1));
print_value(shell, 2, F("Warm Water circulation active"), F_(degrees), Helpers::render_value(buffer, wWCirc_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Warm Water set temperature"), F_(degrees), Helpers::render_value(buffer, wWSetTmp_, 1));
print_value(shell, 2, F("Warm Water current temperature"), F_(degrees), Helpers::render_value(buffer, wWCurTmp_, 10));
print_value(shell, 2, F("Warm water temperature (intern)"), F_(degrees), Helpers::render_value(buffer, wwStorageTemp1_, 10));
print_value(shell, 2, F("Warm water temperature (extern)"), F_(degrees), Helpers::render_value(buffer, wwStorageTemp2_, 10));
print_value(shell, 2, F("Warm Water current temperature (extern)"), F_(degrees), Helpers::render_value(buffer, wWCurTmp2_, 10));
print_value(shell, 2, F("Warm Water current tap water flow"), F("l/min"), Helpers::render_value(buffer, wWCurFlow_, 10));
print_value(shell, 2, F("Warm Water # starts"), Helpers::render_value(buffer, wWStarts_, 1));
if (wWWorkM_ != EMS_VALUE_ULONG_NOTSET) {
shell.printfln(F(" Warm Water active time: %d days %d hours %d minutes"), wWWorkM_ / 1440, (wWWorkM_ % 1440) / 60, wWWorkM_ % 60);
}
print_value(shell, F("Warm Water 3-way valve"), Helpers::render_value(buffer, wWHeat_, EMS_VALUE_BOOL));
print_value(shell, F("Selected flow temperature"), F_(degrees), Helpers::render_value(buffer, selFlowTemp_, 1));
print_value(shell, F("Current flow temperature"), F_(degrees), Helpers::render_value(buffer, curFlowTemp_, 10));
print_value(shell, F("Max boiler temperature"), F_(degrees), Helpers::render_value(buffer, boilTemp_, 10));
print_value(shell, F("Return temperature"), F_(degrees), Helpers::render_value(buffer, retTemp_, 10));
print_value(shell, F("Gas"), Helpers::render_value(buffer, burnGas_, EMS_VALUE_BOOL));
print_value(shell, F("Boiler pump"), Helpers::render_value(buffer, heatPmp_, EMS_VALUE_BOOL));
print_value(shell, F("Fan"), Helpers::render_value(buffer, fanWork_, EMS_VALUE_BOOL));
print_value(shell, F("Ignition"), Helpers::render_value(buffer, ignWork_, EMS_VALUE_BOOL));
print_value(shell, F("Circulation pump"), Helpers::render_value(buffer, wWCirc_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Warm Water 3-way valve"), Helpers::render_value(buffer, wWHeat_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Selected flow temperature"), F_(degrees), Helpers::render_value(buffer, selFlowTemp_, 1));
print_value(shell, 2, F("Current flow temperature"), F_(degrees), Helpers::render_value(buffer, curFlowTemp_, 10));
print_value(shell, 2, F("Max boiler temperature"), F_(degrees), Helpers::render_value(buffer, boilTemp_, 10));
print_value(shell, 2, F("Return temperature"), F_(degrees), Helpers::render_value(buffer, retTemp_, 10));
print_value(shell, 2, F("Gas"), Helpers::render_value(buffer, burnGas_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Boiler pump"), Helpers::render_value(buffer, heatPmp_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Fan"), Helpers::render_value(buffer, fanWork_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Ignition"), Helpers::render_value(buffer, ignWork_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Circulation pump"), Helpers::render_value(buffer, wWCirc_, EMS_VALUE_BOOL));
print_value(shell, F("Burner selected max power"), F_(percent), Helpers::render_value(buffer, selBurnPow_, 1));
print_value(shell, F("Burner current power"), F_(percent), Helpers::render_value(buffer, curBurnPow_, 1));
print_value(shell, F("Flame current"), F("uA"), Helpers::render_value(buffer, flameCurr_, 10));
print_value(shell, F("System pressure"), F("bar"), Helpers::render_value(buffer, sysPress_, 10));
if (serviceCode_ == EMS_VALUE_USHORT_NOTSET) {
shell.printfln(F(" System service code: %s"), serviceCodeChar_);
} else {
print_value(shell, 2, F("Burner selected max power"), F_(percent), Helpers::render_value(buffer, selBurnPow_, 1));
print_value(shell, 2, F("Burner current power"), F_(percent), Helpers::render_value(buffer, curBurnPow_, 1));
print_value(shell, 2, F("Flame current"), F("uA"), Helpers::render_value(buffer, flameCurr_, 10));
print_value(shell, 2, F("System pressure"), F("bar"), Helpers::render_value(buffer, sysPress_, 10));
if (serviceCode_ != EMS_VALUE_USHORT_NOTSET) {
shell.printfln(F(" System service code: %s (%d)"), serviceCodeChar_, serviceCode_);
} else if (serviceCodeChar_[0] != '\0') {
shell.printfln(F(" System service code: %s"), serviceCodeChar_);
}
// UBAParameters
print_value(shell, F("Heating temperature setting on the boiler"), F_(degrees), Helpers::render_value(buffer, heating_temp_, 1));
print_value(shell, F("Boiler circuit pump modulation max power"), F_(percent), Helpers::render_value(buffer, pump_mod_max_, 1));
print_value(shell, F("Boiler circuit pump modulation min power"), F_(percent), Helpers::render_value(buffer, pump_mod_min_, 1));
print_value(shell, 2, F("Heating temperature setting on the boiler"), F_(degrees), Helpers::render_value(buffer, heating_temp_, 1));
print_value(shell, 2, F("Boiler circuit pump modulation max power"), F_(percent), Helpers::render_value(buffer, pump_mod_max_, 1));
print_value(shell, 2, F("Boiler circuit pump modulation min power"), F_(percent), Helpers::render_value(buffer, pump_mod_min_, 1));
// UBAMonitorSlow
if (extTemp_ != EMS_VALUE_SHORT_NOTSET) {
print_value(shell, F("Outside temperature"), F_(degrees), Helpers::render_value(buffer, extTemp_, 10));
print_value(shell, 2, F("Outside temperature"), F_(degrees), Helpers::render_value(buffer, extTemp_, 10));
}
print_value(shell, F("Exhaust temperature"), F_(degrees), Helpers::render_value(buffer, exhaustTemp_, 10));
print_value(shell, F("Pump modulation"), F_(percent), Helpers::render_value(buffer, pumpMod_, 1));
print_value(shell, F("Burner # starts"), Helpers::render_value(buffer, burnStarts_, 1));
print_value(shell, 2, F("Exhaust temperature"), F_(degrees), Helpers::render_value(buffer, exhaustTemp_, 10));
print_value(shell, 2, F("Pump modulation"), F_(percent), Helpers::render_value(buffer, pumpMod_, 1));
print_value(shell, 2, F("Burner # starts"), Helpers::render_value(buffer, burnStarts_, 1));
if (burnWorkMin_ != EMS_VALUE_ULONG_NOTSET) {
shell.printfln(F(" Total burner operating time: %d days %d hours %d minutes"), burnWorkMin_ / 1440, (burnWorkMin_ % 1440) / 60, burnWorkMin_ % 60);
}
@@ -422,11 +424,11 @@ void Boiler::show_values(uuid::console::Shell & shell) {
}
if (hpModulation_ != EMS_VALUE_UINT_NOTSET) {
print_value(shell, F("Heat Pump modulation"), F_(percent), Helpers::render_value(buffer, hpModulation_, 1));
print_value(shell, 2, F("Heat Pump modulation"), F_(percent), Helpers::render_value(buffer, hpModulation_, 1));
}
if (hpSpeed_ != EMS_VALUE_UINT_NOTSET) {
print_value(shell, F("Heat Pump speed"), F_(percent), Helpers::render_value(buffer, hpSpeed_, 1));
print_value(shell, 2, F("Heat Pump speed"), F_(percent), Helpers::render_value(buffer, hpSpeed_, 1));
}
}
@@ -545,6 +547,7 @@ void Boiler::process_UBAMonitorWW(std::shared_ptr<const Telegram> telegram) {
/*
* UBAMonitorFastPlus - type 0xE4 - central heating monitor EMS+
* Still to figure out are: serviceCode, retTemp, sysPress
*/
void Boiler::process_UBAMonitorFastPlus(std::shared_ptr<const Telegram> telegram) {
telegram->read_value(selFlowTemp_, 6);
@@ -562,8 +565,6 @@ void Boiler::process_UBAMonitorFastPlus(std::shared_ptr<const Telegram> telegram
serviceCodeChar_[2] = '\0';
}
// still to figure out: serviceCode, retTemp, sysPress
// at this point do a quick check to see if the hot water or heating is active
check_active();
}
@@ -754,7 +755,7 @@ void Boiler::set_warmwater_circulation(const bool activated) {
}
// add console commands
void Boiler::console_commands() {
void Boiler::console_commands(Shell & shell, unsigned int context) {
EMSESPShell::commands->add_command(ShellContext::BOILER,
CommandFlags::ADMIN,
flash_string_vector{F_(read)},
@@ -920,6 +921,10 @@ void Boiler::console_commands() {
shell.printfln(F_(shower_alert_fmt), settings.shower_alert() ? F_(enabled) : F_(disabled));
shell.println();
});
// enter the context
Console::enter_custom_context(shell, context);
}
} // namespace emsesp

View File

@@ -46,7 +46,7 @@ class Boiler : public EMSdevice {
private:
static uuid::log::Logger logger_;
void console_commands();
void console_commands(Shell & shell, unsigned int context);
uint8_t last_boilerState = 0xFF; // remember last state of heating and warm water on/off
@@ -67,23 +67,23 @@ class Boiler : public EMSdevice {
uint8_t wWComfort_ = EMS_VALUE_UINT_NOTSET; // WW comfort mode
// UBAMonitorFast - 0x18 on EMS1
uint8_t selFlowTemp_ = EMS_VALUE_UINT_NOTSET; // Selected flow temperature
uint16_t curFlowTemp_ = EMS_VALUE_USHORT_NOTSET; // Current flow temperature
uint16_t wwStorageTemp1_ = EMS_VALUE_USHORT_NOTSET; // warm water storage temp 1
uint16_t wwStorageTemp2_ = EMS_VALUE_USHORT_NOTSET; // warm water storage temp 2
uint16_t retTemp_ = EMS_VALUE_USHORT_NOTSET; // Return temperature
uint8_t burnGas_ = EMS_VALUE_BOOL_NOTSET; // Gas on/off
uint8_t fanWork_ = EMS_VALUE_BOOL_NOTSET; // Fan on/off
uint8_t ignWork_ = EMS_VALUE_BOOL_NOTSET; // Ignition on/off
uint8_t heatPmp_ = EMS_VALUE_BOOL_NOTSET; // Boiler pump on/off
uint8_t wWHeat_ = EMS_VALUE_BOOL_NOTSET; // 3-way valve on WW
uint8_t wWCirc_ = EMS_VALUE_BOOL_NOTSET; // Circulation on/off
uint8_t selBurnPow_ = EMS_VALUE_UINT_NOTSET; // Burner max power %
uint8_t curBurnPow_ = EMS_VALUE_UINT_NOTSET; // Burner current power %
uint16_t flameCurr_ = EMS_VALUE_USHORT_NOTSET; // Flame current in micro amps
uint8_t sysPress_ = EMS_VALUE_UINT_NOTSET; // System pressure
char serviceCodeChar_[3]; // 2 character status/service code
uint16_t serviceCode_ = EMS_VALUE_USHORT_NOTSET; // error/service code
uint8_t selFlowTemp_ = EMS_VALUE_UINT_NOTSET; // Selected flow temperature
uint16_t curFlowTemp_ = EMS_VALUE_USHORT_NOTSET; // Current flow temperature
uint16_t wwStorageTemp1_ = EMS_VALUE_USHORT_NOTSET; // warm water storage temp 1
uint16_t wwStorageTemp2_ = EMS_VALUE_USHORT_NOTSET; // warm water storage temp 2
uint16_t retTemp_ = EMS_VALUE_USHORT_NOTSET; // Return temperature
uint8_t burnGas_ = EMS_VALUE_BOOL_NOTSET; // Gas on/off
uint8_t fanWork_ = EMS_VALUE_BOOL_NOTSET; // Fan on/off
uint8_t ignWork_ = EMS_VALUE_BOOL_NOTSET; // Ignition on/off
uint8_t heatPmp_ = EMS_VALUE_BOOL_NOTSET; // Boiler pump on/off
uint8_t wWHeat_ = EMS_VALUE_BOOL_NOTSET; // 3-way valve on WW
uint8_t wWCirc_ = EMS_VALUE_BOOL_NOTSET; // Circulation on/off
uint8_t selBurnPow_ = EMS_VALUE_UINT_NOTSET; // Burner max power %
uint8_t curBurnPow_ = EMS_VALUE_UINT_NOTSET; // Burner current power %
uint16_t flameCurr_ = EMS_VALUE_USHORT_NOTSET; // Flame current in micro amps
uint8_t sysPress_ = EMS_VALUE_UINT_NOTSET; // System pressure
char serviceCodeChar_[3] = {'\0'}; // 2 character status/service code
uint16_t serviceCode_ = EMS_VALUE_USHORT_NOTSET; // error/service code
// UBAMonitorSlow - 0x19 on EMS1
int16_t extTemp_ = EMS_VALUE_SHORT_NOTSET; // Outside temperature

View File

@@ -21,7 +21,11 @@
namespace emsesp {
static std::shared_ptr<Commands> commands = std::make_shared<Commands>();
std::shared_ptr<Commands> EMSESPShell::commands = [] {
std::shared_ptr<Commands> commands = std::make_shared<Commands>();
return commands;
}();
static std::shared_ptr<EMSESPShell> shell;
std::vector<bool> EMSESPStreamConsole::ptys_;
@@ -32,11 +36,6 @@ uuid::telnet::TelnetService telnet_([](Stream & stream, const IPAddress & addr,
});
#endif
std::shared_ptr<Commands> EMSESPShell::commands = [] {
std::shared_ptr<Commands> commands = std::make_shared<Commands>();
return commands;
}();
EMSESPShell::EMSESPShell()
: Shell() {
}
@@ -125,7 +124,7 @@ void EMSESPShell::add_console_commands() {
});
/*
* add the submenu contexts...
* add all the submenu contexts...
*/
// MQTT
@@ -133,8 +132,7 @@ void EMSESPShell::add_console_commands() {
CommandFlags::USER,
flash_string_vector{F_(mqtt)},
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
dynamic_cast<EMSESPShell &>(shell).enter_custom_context(ShellContext::MQTT);
Mqtt::console_commands();
Mqtt::console_commands(shell, ShellContext::MQTT);
});
// EMS
@@ -142,8 +140,7 @@ void EMSESPShell::add_console_commands() {
CommandFlags::USER,
flash_string_vector{F_(ems)},
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
dynamic_cast<EMSESPShell &>(shell).enter_custom_context(ShellContext::EMS);
EMSESP::console_commands();
EMSESP::console_commands(shell, ShellContext::EMS);
});
// System
@@ -151,15 +148,14 @@ void EMSESPShell::add_console_commands() {
CommandFlags::USER,
flash_string_vector{F_(system)},
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
dynamic_cast<EMSESPShell &>(shell).enter_custom_context(ShellContext::SYSTEM);
System::console_commands();
System::console_commands(shell, ShellContext::SYSTEM);
});
// add all the context menus for the connected devices
// this assumes they devices have been detected and registered
EMSESP::add_context_menu();
// this assumes they devices have been detected and pre-registered
EMSESP::add_context_menus();
enter_custom_context(ShellContext::MAIN); // add su, exit and help
Console::load_standard_commands(ShellContext::MAIN);
_console_commands_loaded = true;
}
@@ -199,17 +195,29 @@ bool EMSESPShell::exit_context() {
return Shell::exit_context();
}
// enter a custom context (sub-menu)
void Console::enter_custom_context(Shell & shell, unsigned int context) {
load_standard_commands(context);
// don't enter context if we're already at the root
if (context != ShellContext::MAIN) {
shell.enter_context(context);
}
}
// each custom context has the common commands like log, help, exit, su etc
void EMSESPShell::enter_custom_context(unsigned int context) {
void Console::load_standard_commands(unsigned int context) {
#ifdef EMSESP_DEBUG
commands->add_command(context,
CommandFlags::ADMIN,
flash_string_vector{F_(test)},
flash_string_vector{F_(name_mandatory)},
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { EMSESP::run_test(shell, arguments.front()); });
EMSESPShell::commands->add_command(context,
CommandFlags::ADMIN,
flash_string_vector{F_(test)},
flash_string_vector{F_(name_mandatory)},
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
EMSESP::run_test(shell, arguments.front());
});
#endif
commands->add_command(
EMSESPShell::commands->add_command(
context,
CommandFlags::USER,
flash_string_vector{F_(log)},
@@ -229,7 +237,7 @@ void EMSESPShell::enter_custom_context(unsigned int context) {
uint16_t watch_id = 0; // no watch ID set
if ((arguments.size() == 2) && (level == uuid::log::Level::TRACE)) {
watch_id = Helpers::hextoint(arguments[1].c_str());
shell.printfln(("Tracing only telegrams that match a device ID/telegram type ID of 0x%02X"), watch_id);
shell.printfln(("Tracing only telegrams that match a device ID or telegram type of 0x%02X"), watch_id);
}
emsesp::EMSESP::trace_watch_id(watch_id);
}
@@ -239,68 +247,61 @@ void EMSESPShell::enter_custom_context(unsigned int context) {
return uuid::log::levels_lowercase();
});
commands->add_command(context,
CommandFlags::USER,
flash_string_vector{F_(help)},
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { shell.print_all_available_commands(); });
EMSESPShell::commands->add_command(context,
CommandFlags::USER,
flash_string_vector{F_(help)},
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
shell.print_all_available_commands();
});
commands->add_command(context,
CommandFlags::USER,
flash_string_vector{F_(exit)},
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { shell.exit_context(); });
EMSESPShell::commands->add_command(context,
CommandFlags::USER,
flash_string_vector{F_(exit)},
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
// delete MAIN console stuff first to save memory
EMSESPShell::commands->remove_context_commands(context);
shell.exit_context();
});
commands->add_command(context,
CommandFlags::USER,
flash_string_vector{F_(su)},
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
auto become_admin = [](Shell & shell) {
shell.logger().log(LogLevel::NOTICE,
LogFacility::AUTH,
F("Admin session opened on console %s"),
dynamic_cast<EMSESPShell &>(shell).console_name().c_str());
shell.add_flags(CommandFlags::ADMIN);
};
EMSESPShell::commands->add_command(context,
CommandFlags::USER,
flash_string_vector{F_(su)},
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
auto become_admin = [](Shell & shell) {
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, F("Admin session opened on console"));
shell.add_flags(CommandFlags::ADMIN);
};
if (shell.has_flags(CommandFlags::LOCAL)) {
become_admin(shell);
} else {
shell.enter_password(F_(password_prompt), [=](Shell & shell, bool completed, const std::string & password) {
if (completed) {
uint64_t now = uuid::get_uptime_ms();
if (shell.has_flags(CommandFlags::LOCAL)) {
become_admin(shell);
} else {
shell.enter_password(F_(password_prompt), [=](Shell & shell, bool completed, const std::string & password) {
if (completed) {
uint64_t now = uuid::get_uptime_ms();
if (!password.empty() && password == Settings().admin_password()) {
become_admin(shell);
} else {
shell.delay_until(now + INVALID_PASSWORD_DELAY_MS, [](Shell & shell) {
shell.logger().log(LogLevel::NOTICE,
LogFacility::AUTH,
F("Invalid admin password on console %s"),
dynamic_cast<EMSESPShell &>(shell).console_name().c_str());
shell.println(F("su: incorrect password"));
});
}
}
});
}
});
if (!password.empty() && password == Settings().admin_password()) {
become_admin(shell);
} else {
shell.delay_until(now + INVALID_PASSWORD_DELAY_MS, [](Shell & shell) {
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, F("Invalid admin password on console"));
shell.println(F("su: incorrect password"));
});
}
}
});
}
});
#ifdef EMSESP_DEBUG
commands->add_command(context,
CommandFlags::ADMIN,
flash_string_vector{F_(debug)},
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
shell.printfln(F("%s%sEMS-ESP version %s%s"), COLOR_BRIGHT_GREEN, COLOR_BOLD_ON, Settings().app_version().c_str(), COLOR_RESET);
Settings settings;
settings.commit();
settings.show_settings(shell);
shell.println();
});
EMSESPShell::commands->add_command(
context, CommandFlags::ADMIN, flash_string_vector{F_(debug)}, [&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
shell.printfln(F("%s%sEMS-ESP version %s%s"), COLOR_BRIGHT_GREEN, COLOR_BOLD_ON, Settings().app_version().c_str(), COLOR_RESET);
Settings settings;
settings.commit();
settings.show_settings(shell);
shell.println();
});
#endif
// don't enter context if we're at the root
if (context != ShellContext::MAIN) {
Shell::enter_context(context);
}
}
// prompt, change per context
@@ -339,8 +340,6 @@ std::string EMSESPShell::prompt_suffix() {
}
void EMSESPShell::end_of_transmission() {
// delete MAIN console stuff
commands->remove_context_commands(ShellContext::MAIN);
invoke_command(uuid::read_flash_string(F_(exit)));
}
@@ -415,7 +414,7 @@ void Console::start() {
// note, this must be started after the network/wifi for ESP32 otherwise it'll crash
#ifndef EMSESP_STANDALONE
telnet_.start();
// telnet_.default_write_timeout(1000); // in ms, socket timeout 1 second
telnet_.default_write_timeout(1000); // in ms, socket timeout 1 second
#endif
}
@@ -428,8 +427,6 @@ void Console::loop() {
#endif
Shell::loop_all();
// delay(0); // in EMS-ESP 1.9.5 this helped with stability
}
} // namespace emsesp

View File

@@ -125,7 +125,13 @@ namespace emsesp {
using LogLevel = ::uuid::log::Level;
using LogFacility = ::uuid::log::Facility;
enum CommandFlags : uint8_t { USER = 0, ADMIN = (1 << 0), LOCAL = (1 << 1) };
enum CommandFlags : uint8_t {
USER = 0,
ADMIN = (1 << 0),
LOCAL = (1 << 1)
};
enum ShellContext : uint8_t {
@@ -147,8 +153,6 @@ class EMSESPShell : virtual public uuid::console::Shell {
static std::shared_ptr<uuid::console::Commands> commands;
static std::shared_ptr<EMSESPShell> shell;
void enter_custom_context(unsigned int context);
protected:
EMSESPShell();
@@ -191,6 +195,9 @@ class Console {
uuid::log::Level log_level();
static void enter_custom_context(Shell & shell, unsigned int context);
static void load_standard_commands(unsigned int context);
private:
static constexpr unsigned long SERIAL_CONSOLE_BAUD_RATE = 115200;
static constexpr auto & serial_console_ = Serial;

View File

@@ -27,7 +27,6 @@
{115, DeviceType::BOILER, F("Topline/GB162"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{123, DeviceType::BOILER, F("GBx72/Trendline/Cerapur/Greenstar Si/27i"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{133, DeviceType::BOILER, F("GB125/Logamatic MC110"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{115, DeviceType::BOILER, F("Topline/GB162"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{203, DeviceType::BOILER, F("Logamax U122/Cerapur"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{208, DeviceType::BOILER, F("Logamax plus/GB192/Condens GC9000"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{ 64, DeviceType::BOILER, F("BK13,BK15/Smartline/GB1x2"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
@@ -37,6 +36,7 @@
{122, DeviceType::BOILER, F("Proline"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{170, DeviceType::BOILER, F("Logano GB212"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{172, DeviceType::BOILER, F("Enviline/Compress 6000AW"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
{ 72, DeviceType::BOILER, F("MC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
// Solar Modules - 0x30
{ 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10},
@@ -56,29 +56,30 @@
{200, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
// Switches - 0x11
{ 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x11
{ 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x11
// Controllers - 0x09 / 0x10
{ 68, DeviceType::CONTROLLER, F("BC10/RFM20"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{ 68, DeviceType::CONTROLLER, F("BC10/RFM20"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{ 89, DeviceType::CONTROLLER, F("BC"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{218, DeviceType::CONTROLLER, F("M200/RFM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x50
{190, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},// 0x09
{114, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},// 0x09
{125, DeviceType::CONTROLLER, F("BC25"), DeviceFlags::EMS_DEVICE_FLAG_NONE},// 0x09
{169, DeviceType::CONTROLLER, F("BC40"), DeviceFlags::EMS_DEVICE_FLAG_NONE},// 0x09
{152, DeviceType::CONTROLLER, F("Controller"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{ 95, DeviceType::CONTROLLER, F("HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{209, DeviceType::CONTROLLER, F("ErP"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{190, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{114, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{125, DeviceType::CONTROLLER, F("BC25"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{169, DeviceType::CONTROLLER, F("BC40"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{152, DeviceType::CONTROLLER, F("Controller"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{ 95, DeviceType::CONTROLLER, F("HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{209, DeviceType::CONTROLLER, F("ErP"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
{207, DeviceType::CONTROLLER, F("Sense II/CS200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x10
// Connect devices - 0x02
{205, DeviceType::CONNECT, F("Moduline Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x02
{206, DeviceType::CONNECT, F("Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x02
{171, DeviceType::CONNECT, F("OpenTherm Converter"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x02
{171, DeviceType::CONNECT, F("OpenTherm Converter"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x02
// Gateways - 0x48 / 0x18
{189, DeviceType::GATEWAY, F("KM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x48
{ 94, DeviceType::GATEWAY, F("RC"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x18
{ 94, DeviceType::GATEWAY, F("RC"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x18
// Thermostat - not currently supporting write operations, like the Easy/100 types - 0x18
{202, DeviceType::THERMOSTAT, F("Logamatic TC100/Moduline Easy"), DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write

View File

@@ -138,7 +138,7 @@ std::string EMSdevice::to_string() const {
}
if (brand_ == Brand::NO_BRAND) {
snprintf_P(&str[0], str.capacity() + 1, PSTR("%s (DeviceID:0x%02X ProductID:%d, Version:%s)"), name_.c_str(), device_id_, product_id_, version_.c_str());
snprintf_P(&str[0], str.capacity() + 1, PSTR("%s (DeviceID:0x%02X, ProductID:%d, Version:%s)"), name_.c_str(), device_id_, product_id_, version_.c_str());
} else {
snprintf_P(&str[0],
str.capacity() + 1,
@@ -161,6 +161,7 @@ void EMSdevice::show_values(uuid::console::Shell & shell) {
// for each telegram that has the fetch value set (true) do a read request
void EMSdevice::fetch_values() {
DEBUG_LOG(F("Fetching values for device ID 0x%02X"), device_id());
for (const auto & tf : telegram_functions_) {
if (tf.fetch_) {
read_command(tf.telegram_type_id_);
@@ -260,13 +261,21 @@ void EMSdevice::read_command(const uint16_t type_id) {
}
// prints a value to the console
void EMSdevice::print_value(uuid::console::Shell & shell, const __FlashStringHelper * name, const __FlashStringHelper * prefix, const char * value) {
shell.printfln(PSTR(" %s: %s%s"), uuid::read_flash_string(name).c_str(), value, uuid::read_flash_string(prefix).c_str());
void EMSdevice::print_value(uuid::console::Shell & shell, uint8_t padding, const __FlashStringHelper * name, const __FlashStringHelper * suffix, const char * value) {
uint8_t i = padding;
while (i-- > 0) {
shell.print(F(" "));
}
shell.printf(PSTR("%s: %s"), uuid::read_flash_string(name).c_str(), value);
if (suffix != nullptr) {
shell.print(uuid::read_flash_string(suffix).c_str());
}
shell.println();
}
// prints a value to the console - no prefix
void EMSdevice::print_value(uuid::console::Shell & shell, const __FlashStringHelper * name, const char * value) {
shell.printfln(PSTR(" %s: %s"), uuid::read_flash_string(name).c_str(), value);
// prints a value to the console - with no prefix
void EMSdevice::print_value(uuid::console::Shell & shell, uint8_t padding, const __FlashStringHelper * name, const char * value) {
print_value(shell, padding, name, nullptr, value);
}
} // namespace emsesp

View File

@@ -119,8 +119,8 @@ class EMSdevice {
void fetch_values();
void print_value(uuid::console::Shell & shell, const __FlashStringHelper * name, const __FlashStringHelper * prefix, const char * value);
void print_value(uuid::console::Shell & shell, const __FlashStringHelper * name, const char * value);
void print_value(uuid::console::Shell & shell, uint8_t padding, const __FlashStringHelper * name, const __FlashStringHelper * prefix, const char * value);
void print_value(uuid::console::Shell & shell, uint8_t padding, const __FlashStringHelper * name, const char * value);
enum Brand : uint8_t {
NO_BRAND, // 0
@@ -195,9 +195,8 @@ class EMSdevice {
uint16_t telegram_type_id_; // it's type_id
const __FlashStringHelper * telegram_type_name_; // e.g. RC20Message
// std::string telegram_type_name_; // e.g. RC20Message
bool fetch_; // should this type_id be queried automatically?
process_function_p process_function_;
bool fetch_; // if this type_id be queried automatically
process_function_p process_function_;
};
std::vector<TelegramFunction> telegram_functions_; // each EMS device has its own set of registered telegram types
};

View File

@@ -59,14 +59,15 @@ uint8_t EMSESP::actual_master_thermostat_ = EMSESP_DEFAULT_MASTER_THERMOSTAT; /
uint16_t EMSESP::trace_watch_id_ = 0; // for when log is TRACE
bool EMSESP::tap_water_active_ = false; // for when Boiler states we having running warm water. used in Shower()
bool EMSESP::ems_read_only_;
uint32_t EMSESP::last_fetch_ = 0;
#ifdef EMSESP_DEBUG
#include "test/test_data.h" // used with the 'test' command, under su/admin
#endif
// for each associated EMS device go and request data values
// for each associated EMS device go and request its data values
void EMSESP::fetch_device_values() {
fetch_device_values(0); // fetch all
fetch_device_values(0); // 0 = fetch all
}
// for a specific EMS device go and request data values
@@ -76,7 +77,9 @@ void EMSESP::fetch_device_values(const uint8_t device_id) {
if (emsdevice) {
if ((device_id == 0) || emsdevice->is_device_id(device_id)) {
emsdevice->fetch_values();
return;
if (device_id != 0) {
return; // quit, we only want to return the selected device
}
}
}
}
@@ -177,6 +180,14 @@ void EMSESP::show_values(uuid::console::Shell & shell) {
return;
}
// show EMS device values
for (const auto & emsdevice : emsdevices) {
if (emsdevice) {
emsdevice->show_values(shell);
shell.println();
}
}
// Dallas sensors (if available)
char valuestr[8] = {0}; // for formatting temp
if (!sensor_devices().empty()) {
@@ -187,14 +198,6 @@ void EMSESP::show_values(uuid::console::Shell & shell) {
shell.println();
}
// show EMS device values
for (const auto & emsdevice : emsdevices) {
if (emsdevice) {
emsdevice->show_values(shell);
shell.println();
}
}
shell.println();
}
@@ -340,6 +343,7 @@ void EMSESP::process_UBADevices(std::shared_ptr<const Telegram> telegram) {
}
// process the Version telegram (type 0x02), which is a common type
// e.g. 09 0B 02 00 PP V1 V2
void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
// check for valid telegram, just in case
if (telegram->message_length < 3) {
@@ -447,7 +451,7 @@ bool EMSESP::device_exists(const uint8_t device_id) {
}
// for each device add its context menu for the console
void EMSESP::add_context_menu() {
void EMSESP::add_context_menus() {
for (const auto & emsdevice : emsdevices) {
if (emsdevice) {
emsdevice->add_context_menu();
@@ -531,10 +535,10 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, std::
// if we don't recognize the product ID report it, but don't add it.
if (!found) {
DEBUG_LOG(F("Cannot add device. Unknown device ID 0x%02X, product ID %d. Ignoring it."), device_id, product_id);
logger_.notice(F("Unrecognized EMS device with device ID 0x%02X with product ID %d. Please report on GitHub."), device_id, product_id);
return false; // not found
} else {
DEBUG_LOG(F("Adding new device with device ID 0x%02X, product ID %d"), device_id, product_id);
DEBUG_LOG(F("Adding new device with device ID 0x%02X with product ID %d"), device_id, product_id);
// go and fetch its data, including asking for the version
send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id);
fetch_device_values(device_id);
@@ -634,7 +638,7 @@ void EMSESP::set_ems_read_only() {
}
// console commands to add
void EMSESP::console_commands() {
void EMSESP::console_commands(Shell & shell, unsigned int context) {
EMSESPShell::commands->add_command(ShellContext::EMS,
CommandFlags::USER,
flash_string_vector{F_(show), F_(devices)},
@@ -775,6 +779,9 @@ void EMSESP::console_commands() {
shell.printfln(F_(bus_id_fmt), settings.ems_bus_id());
shell.printfln(F_(read_only_fmt), settings.ems_read_only() ? F_(enabled) : F_(disabled));
});
// enter the context
Console::enter_custom_context(shell, context);
}
// kick off the party, start all the services
@@ -805,6 +812,13 @@ void EMSESP::loop() {
rxservice_.loop(); // process what ever is in the rx queue
shower_.loop(); // check for shower on/off
sensors_.loop(); // this will also send out via MQTT
// force a query on the EMS devices to fetch latest data
uint32_t currentMillis = millis();
if ((currentMillis - last_fetch_ > EMS_FETCH_FREQUENCY)) {
last_fetch_ = currentMillis;
fetch_device_values();
}
}
}

View File

@@ -85,7 +85,7 @@ class EMSESP {
static void show_devices(uuid::console::Shell & shell);
static void show_emsbus(uuid::console::Shell & shell);
static void add_context_menu();
static void add_context_menus();
static void incoming_telegram(uint8_t * data, const uint8_t length);
@@ -111,7 +111,7 @@ class EMSESP {
return ems_read_only_;
}
static void console_commands();
static void console_commands(Shell & shell, unsigned int context);
static void fetch_device_values(const uint8_t device_id);
static void fetch_device_values();
@@ -136,6 +136,9 @@ class EMSESP {
static RxService rxservice_;
static TxService txservice_;
static constexpr uint32_t EMS_FETCH_FREQUENCY = 60000; // check every minute
static uint32_t last_fetch_;
struct Device_record {
uint8_t product_id;
EMSdevice::DeviceType device_type;

View File

@@ -65,10 +65,10 @@ void Mixing::show_values(uuid::console::Shell & shell) {
} else {
shell.printfln(F(" Heating Circuit #: %d"), hc_);
}
print_value(shell, F("Current flow temperature"), F_(degrees), Helpers::render_value(buffer, flowTemp_, 10));
print_value(shell, F("Setpoint flow temperature"), F_(degrees), Helpers::render_value(buffer, flowSetTemp_, 1));
print_value(shell, F("Current pump modulation"), Helpers::render_value(buffer, pumpMod_, 1));
print_value(shell, F("Current valve status"), Helpers::render_value(buffer, status_, 1));
print_value(shell, 2, F("Current flow temperature"), F_(degrees), Helpers::render_value(buffer, flowTemp_, 10));
print_value(shell, 2, F("Setpoint flow temperature"), F_(degrees), Helpers::render_value(buffer, flowSetTemp_, 1));
print_value(shell, 2, F("Current pump modulation"), Helpers::render_value(buffer, pumpMod_, 1));
print_value(shell, 2, F("Current valve status"), Helpers::render_value(buffer, status_, 1));
}
// publish values via MQTT
@@ -151,9 +151,9 @@ void Mixing::process_MMStatusMessage(std::shared_ptr<const Telegram> telegram) {
type_ = Type::HC;
// the heating circuit is determine by which device_id it is, 0x20 - 0x23
// 0x21 is position 2. 0x20 is typically reserved for the WM10 switch module
// 0x21 is position 2. 0x20 is typically reserved for the WM10 switch module
// see https://github.com/proddy/EMS-ESP/issues/270 and https://github.com/proddy/EMS-ESP/issues/386#issuecomment-629610918
hc_ = 0x22 - device_id();
hc_ = 0x22 - device_id();
telegram->read_value(flowTemp_, 1); // is * 10
telegram->read_value(pumpMod_, 3);
telegram->read_value(flowSetTemp_, 0);

View File

@@ -40,7 +40,7 @@ MAKE_PSTR(mqtt_enabled_fmt, "MQTT is %s")
MAKE_PSTR(mqtt_base_fmt, "Base = %s")
MAKE_PSTR(mqtt_qos_fmt, "QOS = %ld")
MAKE_PSTR(mqtt_retain_fmt, "Retain Flag = %s")
MAKE_PSTR(mqtt_format_fmt, "JSON format = %s")
MAKE_PSTR(mqtt_format_fmt, "Format for JSON = %s")
MAKE_PSTR(mqtt_heartbeat_fmt, "Heartbeat = %s")
MAKE_PSTR(mqtt_publish_time_fmt, "Publish time = %d seconds")
@@ -52,6 +52,7 @@ namespace emsesp {
#ifndef EMSESP_STANDALONE
AsyncMqttClient Mqtt::mqttClient_;
#endif
std::vector<Mqtt::MQTTFunction> Mqtt::mqtt_functions_;
bool Mqtt::mqtt_retain_;
uint8_t Mqtt::mqtt_qos_;
@@ -463,17 +464,20 @@ void Mqtt::send_heartbeat() {
// add MQTT message to queue, payload is a JSON doc.
// NOTE this only prints first 255 chars
void Mqtt::queue_publish_message(const char * topic, const JsonDocument & payload, const bool retain) {
if (strlen(topic) == 0) {
void Mqtt::queue_publish_message(const std::string & topic, const JsonDocument & payload, const bool retain) {
// can't have bogus topics, but empty payloads are ok
if (topic.empty()) {
return;
}
/*
// check for empty JSON doc - we don't like those
size_t capacity = measureJson(payload);
if (capacity <= 3) {
// DEBUG_LOG(("Empty JSON for topic %s. Skipping"), topic);
// DEBUG_LOG(("Empty JSON payload for topic %s. Skipping"), topic);
return;
}
*/
std::string payload_text;
serializeJson(payload, payload_text);
@@ -491,9 +495,9 @@ void Mqtt::queue_publish_message(const char * topic, const JsonDocument & payloa
}
// add MQTT message to queue, payload is a string
void Mqtt::queue_publish_message(const char * topic, const std::string & payload, const bool retain) {
void Mqtt::queue_publish_message(const std::string & topic, const std::string & payload, const bool retain) {
// can't have bogus topics, but empty payloads are ok
if (strlen(topic) == 0) {
if (topic.empty()) {
return;
}
@@ -525,29 +529,29 @@ void Mqtt::queue_subscribe_message(const std::string & topic) {
}
// MQTT Publish, using a specific retain flag
void Mqtt::publish(const char * topic, const char * payload, bool retain) {
void Mqtt::publish(const std::string & topic, const std::string & payload, bool retain) {
queue_publish_message(topic, payload, retain);
}
// Publish using the user's custom retain flag
void Mqtt::publish(const char * topic, const char * payload) {
void Mqtt::publish(const std::string & topic, const std::string & payload) {
publish(topic, payload, mqtt_retain_);
}
void Mqtt::publish(const char * topic, const JsonDocument & payload) {
void Mqtt::publish(const std::string & topic, const JsonDocument & payload) {
publish(topic, payload, mqtt_retain_);
}
void Mqtt::publish(const char * topic, const JsonDocument & payload, bool retain) {
void Mqtt::publish(const std::string & topic, const JsonDocument & payload, bool retain) {
queue_publish_message(topic, payload, retain);
}
void Mqtt::publish(const char * topic, const bool value) {
void Mqtt::publish(const std::string & topic, const bool value) {
queue_publish_message(topic, value ? "1" : "0", mqtt_retain_);
}
// no payload
void Mqtt::publish(const char * topic) {
void Mqtt::publish(const std::string & topic) {
queue_publish_message(topic, "", mqtt_retain_);
}
@@ -634,10 +638,10 @@ void Mqtt::process_queue() {
}
mqtt_messages_.pop_front(); // remove the message from the queue
} // namespace emsesp
}
// add console commands
void Mqtt::console_commands() {
void Mqtt::console_commands(Shell & shell, unsigned int context) {
EMSESPShell::commands->add_command(
ShellContext::MQTT,
CommandFlags::ADMIN,
@@ -853,6 +857,9 @@ void Mqtt::console_commands() {
shell.printfln(F_(mqtt_publish_time_fmt), settings.mqtt_publish_time());
shell.println();
});
} // namespace emsesp
// enter the context
Console::enter_custom_context(shell, context);
}
} // namespace emsesp

View File

@@ -39,6 +39,8 @@
#include <uuid/log.h>
using uuid::console::Shell;
#define EMSESP_MAX_JSON_SIZE_SMALL 200 // for smaller json docs
#define EMSESP_MAX_JSON_SIZE_MEDIUM 800 // for smaller json docs from ems devices
#define EMSESP_MAX_JSON_SIZE_LARGE 1500 // for large json docs from ems devices, like boiler or thermostat data
@@ -69,16 +71,16 @@ class Mqtt {
static void subscribe(const uint8_t device_id, const std::string & topic, mqtt_function_p cb);
static void subscribe(const std::string & topic, mqtt_function_p cb);
static void publish(const char * topic, const char * payload);
static void publish(const char * topic, const char * payload, bool retain);
static void publish(const char * topic, const JsonDocument & payload);
static void publish(const char * topic, const JsonDocument & payload, bool retain);
static void publish(const char * topic, const bool value);
static void publish(const char * topic);
static void publish(const std::string & topic, const std::string & payload);
static void publish(const std::string & topic, const std::string & payload, bool retain);
static void publish(const std::string & topic, const JsonDocument & payload);
static void publish(const std::string & topic, const JsonDocument & payload, bool retain);
static void publish(const std::string & topic, const bool value);
static void publish(const std::string & topic);
static void show_topic_handlers(uuid::console::Shell & shell, const uint8_t device_id);
static void console_commands();
static void console_commands(Shell & shell, unsigned int context);
void incoming(char * topic, char * payload); // for testing
@@ -130,8 +132,8 @@ class Mqtt {
static bool mqtt_retain_;
static void queue_publish_message(const char * topic, const JsonDocument & payload, const bool retain);
static void queue_publish_message(const char * topic, const std::string & payload, const bool retain);
static void queue_publish_message(const std::string & topic, const JsonDocument & payload, const bool retain);
static void queue_publish_message(const std::string & topic, const std::string & payload, const bool retain);
static void queue_subscribe_message(const std::string & topic);

View File

@@ -346,6 +346,7 @@ void Network::show_network(uuid::console::Shell & shell) {
shell.printfln(F("WiFi: unknown"));
break;
}
shell.println();
#endif
}

View File

@@ -54,20 +54,20 @@ void Solar::show_values(uuid::console::Shell & shell) {
char buffer[10]; // used for formatting
print_value(shell, F("Collector temperature (TS1)"), F_(degrees), Helpers::render_value(buffer, collectorTemp_, 10));
print_value(shell, F("Bottom temperature (TS2)"), F_(degrees), Helpers::render_value(buffer, bottomTemp_, 10));
print_value(shell, F("Bottom temperature (TS5)"), F_(degrees), Helpers::render_value(buffer, bottomTemp2_, 10));
print_value(shell, F("Pump modulation"), F_(percent), Helpers::render_value(buffer, pumpModulation_, 1));
print_value(shell, F("Valve (VS2) status"), Helpers::render_value(buffer, valveStatus_, EMS_VALUE_BOOL));
print_value(shell, F("Pump (PS1) active"), Helpers::render_value(buffer, pump_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Collector temperature (TS1)"), F_(degrees), Helpers::render_value(buffer, collectorTemp_, 10));
print_value(shell, 2, F("Bottom temperature (TS2)"), F_(degrees), Helpers::render_value(buffer, bottomTemp_, 10));
print_value(shell, 2, F("Bottom temperature (TS5)"), F_(degrees), Helpers::render_value(buffer, bottomTemp2_, 10));
print_value(shell, 2, F("Pump modulation"), F_(percent), Helpers::render_value(buffer, pumpModulation_, 1));
print_value(shell, 2, F("Valve (VS2) status"), Helpers::render_value(buffer, valveStatus_, EMS_VALUE_BOOL));
print_value(shell, 2, F("Pump (PS1) active"), Helpers::render_value(buffer, pump_, EMS_VALUE_BOOL));
if (pumpWorkMin_ != EMS_VALUE_ULONG_NOTSET) {
shell.printfln(F(" Pump working time: %d days %d hours %d minutes"), pumpWorkMin_ / 1440, (pumpWorkMin_ % 1440) / 60, pumpWorkMin_ % 60);
}
print_value(shell, F("Energy last hour"), F_(wh), Helpers::render_value(buffer, energyLastHour_, 10));
print_value(shell, F("Energy today"), F_(wh), Helpers::render_value(buffer, energyToday_, 0)); // no division
print_value(shell, F("Energy total"), F_(kwh), Helpers::render_value(buffer, energyTotal_, 10));
print_value(shell, 2, F("Energy last hour"), F_(wh), Helpers::render_value(buffer, energyLastHour_, 10));
print_value(shell, 2, F("Energy today"), F_(wh), Helpers::render_value(buffer, energyToday_, 0)); // no division
print_value(shell, 2, F("Energy total"), F_(kwh), Helpers::render_value(buffer, energyTotal_, 10));
}
// publish values via MQTT

View File

@@ -334,7 +334,7 @@ void System::show_system(uuid::console::Shell & shell) {
}
// console commands to add
void System::console_commands() {
void System::console_commands(Shell & shell, unsigned int context) {
EMSESPShell::commands->add_command(ShellContext::SYSTEM,
CommandFlags::ADMIN,
flash_string_vector{F_(set), F_(hostname)},
@@ -509,7 +509,6 @@ void System::console_commands() {
flash_string_vector{F_(show)},
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
Network::show_network(shell);
shell.println();
show_system(shell);
shell.println();
});
@@ -522,7 +521,7 @@ void System::console_commands() {
shell.printfln(F_(hostname_fmt),
settings.hostname().empty() ? uuid::read_flash_string(F_(unset)).c_str() : settings.hostname().c_str());
if (shell.has_flags(CommandFlags::ADMIN | CommandFlags::LOCAL)) {
if (shell.has_flags(CommandFlags::ADMIN)) {
shell.printfln("Wifi:");
shell.print(" ");
shell.printfln(F_(wifi_ssid_fmt),
@@ -540,6 +539,9 @@ void System::console_commands() {
shell.printfln(F_(mark_interval_fmt), settings.syslog_mark_interval());
}
});
// enter the context
Console::enter_custom_context(shell, context);
}

View File

@@ -43,6 +43,8 @@
#include <uuid/log.h>
using uuid::console::Shell;
namespace emsesp {
class System {
@@ -63,7 +65,7 @@ class System {
static void show_mem(const char * text);
static void console_commands();
static void console_commands(Shell & shell, unsigned int context);
private:
static uuid::log::Logger logger_;

View File

@@ -1,12 +1,12 @@
// create some fake test data
// used with the 'test' command, under su/admin
void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command) {
// A fake response - UBADevices(0x07) - only for testing offline
if (command == "devices") {
rxservice_.ems_mask(EMSbus::EMS_MASK_BUDERUS); // this is important otherwise nothing will be picked up!
emsdevices.push_back(EMSFactory::add(EMSdevice::DeviceType::BOILER, EMSdevice::EMS_DEVICE_ID_BOILER, 0, "", "My Boiler", 0, 0));
// A fake response - UBADevices(0x07)
uint8_t t0[] = {0x08, 0x00, 0x07, 0x00, 0x0B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47};
rxservice_.add(t0, sizeof(t0));
@@ -21,6 +21,20 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
return;
}
if (command == "unknown") {
// question: do we need to set the mask?
std::string version("1.2.3");
add_device(0x09, 89, version, EMSdevice::Brand::BUDERUS);
rxservice_.loop();
// simulate getting version information back from an unknown device
uint8_t u1[] = {0x09, 0x0B, 0x02, 0x00, 0x59, 0x01, 0x02, 0x56};
rxservice_.add(u1, sizeof(u1));
rxservice_.loop();
return;
}
if (command == "thermostats") {
shell.printfln(F("Testing adding devices on the EMS bus..."));

View File

@@ -39,6 +39,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(EMS_TYPE_RCOutdoorTemp, F("RCOutdoorTemp"), false, std::bind(&Thermostat::process_RCOutdoorTemp, this, _1));
register_telegram_type(EMS_TYPE_RCTime, F("RCTime"), true, std::bind(&Thermostat::process_RCTime, this, _1)); // 0x06
// RC10
if (flags == EMSdevice::EMS_DEVICE_FLAG_RC10) {
monitor_typeids = {0xB1};
set_typeids = {0xB0};
@@ -47,6 +48,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(set_typeids[i], F("RC10Set"), true, std::bind(&Thermostat::process_RC10Set, this, _1));
}
// RC35
} else if ((flags == EMSdevice::EMS_DEVICE_FLAG_RC35) || (flags == EMSdevice::EMS_DEVICE_FLAG_RC30_1)) {
monitor_typeids = {0x3E, 0x48, 0x52, 0x5C};
set_typeids = {0x3D, 0x47, 0x51, 0x5B};
@@ -56,6 +58,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
}
register_telegram_type(EMS_TYPE_IBASettings, F("IBASettings"), true, std::bind(&Thermostat::process_IBASettings, this, _1));
// RC20
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20) {
monitor_typeids = {0x91};
set_typeids = {0xA8};
@@ -64,6 +67,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(set_typeids[i], F("RC20Set"), true, std::bind(&Thermostat::process_RC20Set, this, _1));
}
// RC20 newer
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20_2) {
monitor_typeids = {0xAE};
set_typeids = {0xAD};
@@ -72,6 +76,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(set_typeids[i], F("RC20Set"), true, std::bind(&Thermostat::process_RC20Set_2, this, _1));
}
// RC30
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC30) {
monitor_typeids = {0x41};
set_typeids = {0xA7};
@@ -80,11 +85,13 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(set_typeids[i], F("RC30Set"), true, std::bind(&Thermostat::process_RC30Set, this, _1));
}
// EASY
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_EASY) {
monitor_typeids = {0x0A};
set_typeids = {};
register_telegram_type(monitor_typeids[0], F("EasyMonitor"), true, std::bind(&Thermostat::process_EasyMonitor, this, _1));
// RC300/RC100
} else if ((flags == EMSdevice::EMS_DEVICE_FLAG_RC300) || (flags == EMSdevice::EMS_DEVICE_FLAG_RC100)) {
monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8};
set_typeids = {0x02B9, 0x02BA, 0x02BB, 0x02BC};
@@ -93,6 +100,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
register_telegram_type(set_typeids[i], F("RC300Set"), true, std::bind(&Thermostat::process_RC300Set, this, _1));
}
// JUNKERS/HT3
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
monitor_typeids = {0x6F, 0x70, 0x71, 0x72};
set_typeids = {0x65, 0x66, 0x67, 0x68};
@@ -194,8 +202,7 @@ void Thermostat::add_context_menu() {
CommandFlags::USER,
flash_string_vector{F_(thermostat)},
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
dynamic_cast<EMSESPShell &>(shell).enter_custom_context(ShellContext::THERMOSTAT);
console_commands();
Thermostat::console_commands(shell, ShellContext::THERMOSTAT);
});
}
@@ -326,7 +333,7 @@ bool Thermostat::updated_values() {
}
return false;
} // namespace emsesp
}
// publish values via MQTT
void Thermostat::publish_values() {
@@ -337,7 +344,7 @@ void Thermostat::publish_values() {
DEBUG_LOG(F("Performing a thermostat publish (device ID 0x%02X)"), device_id());
uint8_t flags = (this->flags() & 0x0F); // specific thermostat characteristics, strip the option bits
uint8_t flags = (this->flags() & 0x0F); // specific thermostat characteristics, stripping the option bits
bool has_data = false;
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
@@ -364,6 +371,7 @@ void Thermostat::publish_values() {
}
has_data = true;
// if the MQTT format is 'nested' then create the parent object hc<n>
if (mqtt_format_ == Settings::MQTT_format::NESTED) {
// create nested json for each HC
char hc_name[10]; // hc{1-4}
@@ -533,6 +541,10 @@ std::shared_ptr<Thermostat::HeatingCircuit> Thermostat::heating_circuit(std::sha
// decodes the thermostat mode for the heating circuit based on the thermostat type
// modes are off, manual, auto, day and night
uint8_t Thermostat::HeatingCircuit::get_mode(uint8_t flags) const {
if (mode == EMS_VALUE_UINT_NOTSET) {
return HeatingCircuit::Mode::UNKNOWN;
}
flags &= 0x0F; // strip top 4 bits
if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20) {
@@ -565,7 +577,7 @@ uint8_t Thermostat::HeatingCircuit::get_mode(uint8_t flags) const {
}
}
return HeatingCircuit::Mode::OFF;
return HeatingCircuit::Mode::UNKNOWN;
}
// figures out the thermostat day/night mode depending on the thermostat type
@@ -629,10 +641,13 @@ std::string Thermostat::mode_tostring(uint8_t mode) const {
case HeatingCircuit::Mode::NOFROST:
return read_flash_string(F("nofrost"));
break;
default:
case HeatingCircuit::Mode::AUTO:
return read_flash_string(F("auto"));
break;
default:
case HeatingCircuit::Mode::UNKNOWN:
return read_flash_string(F("unknown"));
break;
}
}
@@ -643,22 +658,22 @@ void Thermostat::show_values(uuid::console::Shell & shell) {
char buffer[10]; // for formatting only
if (datetime_.size()) {
shell.printfln(F("Clock: %s"), datetime_.c_str());
shell.printfln(F(" Clock: %s"), datetime_.c_str());
if (ibaClockOffset != EMS_VALUE_UINT_NOTSET) {
print_value(shell, F("Offset clock"), Helpers::render_value(buffer, ibaClockOffset, 1)); // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
print_value(shell, 1, F("Offset clock"), Helpers::render_value(buffer, ibaClockOffset, 1)); // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
}
}
uint8_t flags = (this->flags() & 0x0F); // specific thermostat characteristics, strip the option bits
if (flags == EMS_DEVICE_FLAG_RC35) {
print_value(shell, F("Damped Outdoor temperature"), F_(degrees), Helpers::render_value(buffer, dampedoutdoortemp, 1));
print_value(shell, F("Tempsensor 1"), F_(degrees), Helpers::render_value(buffer, tempsensor1, 10));
print_value(shell, F("Tempsensor 2"), F_(degrees), Helpers::render_value(buffer, tempsensor2, 10));
print_value(shell, 1, F("Damped Outdoor temperature"), F_(degrees), Helpers::render_value(buffer, dampedoutdoortemp, 1));
print_value(shell, 1, F("Tempsensor 1"), F_(degrees), Helpers::render_value(buffer, tempsensor1, 10));
print_value(shell, 1, F("Tempsensor 2"), F_(degrees), Helpers::render_value(buffer, tempsensor2, 10));
}
for (const auto & hc : heating_circuits_) {
shell.printfln(F("Heating Circuit %d:"), hc->hc_num());
shell.printfln(F(" Heating Circuit %d:"), hc->hc_num());
// different thermostat types store their temperature values differently
uint8_t format_setpoint, format_curr;
@@ -677,83 +692,87 @@ void Thermostat::show_values(uuid::console::Shell & shell) {
break;
}
print_value(shell, F("Current room temperature"), F_(degrees), Helpers::render_value(buffer, hc->curr_roomTemp, format_curr));
print_value(shell, F("Setpoint room temperature"), F_(degrees), Helpers::render_value(buffer, hc->setpoint_roomTemp, format_setpoint));
print_value(shell, F("Mode"), mode_tostring(hc->get_mode(flags)).c_str());
print_value(shell, F("Mode Type"), mode_tostring(hc->get_mode_type(flags)).c_str());
print_value(shell, 2, F("Current room temperature"), F_(degrees), Helpers::render_value(buffer, hc->curr_roomTemp, format_curr));
print_value(shell, 2, F("Setpoint room temperature"), F_(degrees), Helpers::render_value(buffer, hc->setpoint_roomTemp, format_setpoint));
if (hc->mode != EMS_VALUE_UINT_NOTSET) {
print_value(shell, 2, F("Mode"), mode_tostring(hc->get_mode(flags)).c_str());
}
if (hc->mode_type != EMS_VALUE_UINT_NOTSET) {
print_value(shell, 2, F("Mode Type"), mode_tostring(hc->get_mode_type(flags)).c_str());
}
if ((flags == EMS_DEVICE_FLAG_RC35) || (flags == EMS_DEVICE_FLAG_RC30_1)) {
if (hc->summer_mode) {
shell.printfln(F(" Program is set to Summer mode"));
shell.printfln(F(" Program is set to Summer mode"));
} else if (hc->holiday_mode) {
shell.printfln(F(" Program is set to Holiday mode"));
shell.printfln(F(" Program is set to Holiday mode"));
}
print_value(shell, F("Day temperature"), F_(degrees), Helpers::render_value(buffer, hc->daytemp, 2));
print_value(shell, F("Night temperature"), F_(degrees), Helpers::render_value(buffer, hc->nighttemp, 2));
print_value(shell, F("Vacation temperature"), F_(degrees), Helpers::render_value(buffer, hc->holidaytemp, 2));
print_value(shell, 2, F("Day temperature"), F_(degrees), Helpers::render_value(buffer, hc->daytemp, 2));
print_value(shell, 2, F("Night temperature"), F_(degrees), Helpers::render_value(buffer, hc->nighttemp, 2));
print_value(shell, 2, F("Vacation temperature"), F_(degrees), Helpers::render_value(buffer, hc->holidaytemp, 2));
if (hc->offsettemp < 100) {
print_value(shell, F("Offset temperature"), F_(degrees), Helpers::render_value(buffer, hc->offsettemp, 2));
print_value(shell, 2, F("Offset temperature"), F_(degrees), Helpers::render_value(buffer, hc->offsettemp, 2));
}
print_value(shell, F("Design temperature"), F_(degrees), Helpers::render_value(buffer, hc->designtemp, 2));
print_value(shell, 2, F("Design temperature"), F_(degrees), Helpers::render_value(buffer, hc->designtemp, 2));
}
// show flow temp if we have it
if (hc->circuitcalctemp != EMS_VALUE_UINT_NOTSET) {
print_value(shell, F("Calculated flow temperature"), F_(degrees), Helpers::render_value(buffer, hc->circuitcalctemp, 1));
print_value(shell, 2, F("Calculated flow temperature"), F_(degrees), Helpers::render_value(buffer, hc->circuitcalctemp, 1));
}
// settings parameters
if (ibaMainDisplay != EMS_VALUE_UINT_NOTSET) {
if (ibaMainDisplay == 0) {
shell.printfln(F(" Display: internal temperature"));
shell.printfln(F(" Display: internal temperature"));
} else if (ibaMainDisplay == 1) {
shell.printfln(F(" Display: internal setpoint"));
shell.printfln(F(" Display: internal setpoint"));
} else if (ibaMainDisplay == 2) {
shell.printfln(F(" Display: external temperature"));
shell.printfln(F(" Display: external temperature"));
} else if (ibaMainDisplay == 3) {
shell.printfln(F(" Display: burner temperature"));
shell.printfln(F(" Display: burner temperature"));
} else if (ibaMainDisplay == 4) {
shell.printfln(F(" Display: WW temperature"));
shell.printfln(F(" Display: WW temperature"));
} else if (ibaMainDisplay == 5) {
shell.printfln(F(" Display: functioning mode"));
shell.printfln(F(" Display: functioning mode"));
} else if (ibaMainDisplay == 6) {
shell.printfln(F(" Display: time"));
shell.printfln(F(" Display: time"));
} else if (ibaMainDisplay == 7) {
shell.printfln(F(" Display: date"));
shell.printfln(F(" Display: date"));
} else if (ibaMainDisplay == 9) {
shell.printfln(F(" Display: smoke temperature"));
shell.printfln(F(" Display: smoke temperature"));
}
}
if (ibaLanguage != EMS_VALUE_UINT_NOTSET) {
if (ibaLanguage == 0) {
shell.printfln(F(" Language: German"));
shell.printfln(F(" Language: German"));
} else if (ibaLanguage == 1) {
shell.printfln(F(" Language: Dutch"));
shell.printfln(F(" Language: Dutch"));
} else if (ibaLanguage == 2) {
shell.printfln(F(" Language: French"));
shell.printfln(F(" Language: French"));
} else if (ibaLanguage == 3) {
shell.printfln(F(" Language: Italian"));
shell.printfln(F(" Language: Italian"));
}
}
if (ibaCalIntTemperature != EMS_VALUE_INT_NOTSET) {
print_value(shell, F("Offset int. temperature"), F_(degrees), Helpers::render_value(buffer, ibaCalIntTemperature, 2));
print_value(shell, 2, F("Offset int. temperature"), F_(degrees), Helpers::render_value(buffer, ibaCalIntTemperature, 2));
}
if (ibaMinExtTemperature != EMS_VALUE_INT_NOTSET) {
print_value(shell, F("Min ext. temperature"), F_(degrees), Helpers::render_value(buffer, ibaMinExtTemperature, 10)); // min ext temp for heating curve, in deg.
print_value(shell, 2, F("Min ext. temperature"), F_(degrees), Helpers::render_value(buffer, ibaMinExtTemperature, 10)); // min ext temp for heating curve, in deg.
}
if (ibaBuildingType != EMS_VALUE_UINT_NOTSET) {
if (ibaBuildingType == 0) {
shell.printfln(F(" Building: light"));
shell.printfln(F(" Building: light"));
} else if (ibaBuildingType == 1) {
shell.printfln(F(" Building: medium"));
shell.printfln(F(" Building: medium"));
} else if (ibaBuildingType == 2) {
shell.printfln(F(" Building: heavy"));
shell.printfln(F(" Building: heavy"));
}
}
}
@@ -1238,7 +1257,7 @@ void Thermostat::set_temperature(const float temperature, const uint8_t mode, co
}
// add console commands
void Thermostat::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)},
@@ -1318,6 +1337,9 @@ void Thermostat::console_commands() {
: Helpers::hextoa(buffer, settings.master_thermostat()));
shell.println();
});
// enter the context
Console::enter_custom_context(shell, context);
}
} // namespace emsesp

View File

@@ -76,7 +76,7 @@ class Thermostat : public EMSdevice {
return set_typeid_;
}
enum Mode : uint8_t { OFF, MANUAL, AUTO, DAY, NIGHT, HEAT, NOFROST, ECO, HOLIDAY, COMFORT, OFFSET, DESIGN };
enum Mode : uint8_t { UNKNOWN, OFF, MANUAL, AUTO, DAY, NIGHT, HEAT, NOFROST, ECO, HOLIDAY, COMFORT, OFFSET, DESIGN };
private:
uint8_t hc_num_;
@@ -103,7 +103,7 @@ class Thermostat : public EMSdevice {
private:
static uuid::log::Logger logger_;
void console_commands();
void console_commands(Shell & shell, unsigned int context);
void init_mqtt();
std::string datetime_; // date and time stamp

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "2.0.0a4"
#define EMSESP_APP_VERSION "2.0.0a6"