mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
a6
This commit is contained in:
@@ -10,12 +10,12 @@ Note: Version 2.0 is not backward compatible with v1.0. The File system structur
|
|||||||
|
|
||||||
### **Design & coding principles**
|
### **Design & coding principles**
|
||||||
|
|
||||||
- The code can be built and run without an ESP microcontroller, which is useful when testing and simulating handling of the different telegrams and devices. Make sure you have GNU make and g++ installed and use 'make' to build the image and execute the file `emsesp` (on linux).
|
- The code can be built and run without an ESP microcontroller, which is useful when testing and simulating handling of the different telegrams and devices. Make sure you have GNU make and g++ installed and use 'make' to build the image and execute the file `emsesp` (on linux).
|
||||||
- I used C++11 containers where I could (std::string, std::deque, std::list, std::multimap etc).
|
- I used C++11 containers where I could (std::string, std::deque, std::list, std::multimap etc).
|
||||||
- The core is based off the great libraries from @nomis' and I adopted his general design pattens such as making everything as asynchronous as possible so that no one operation should starve another operation of it's time to execute (https://isocpp.org/wiki/faq/ctors#static-init-order).
|
- The core is based off the great libraries from @nomis' and I adopted his general design pattens such as making everything as asynchronous as possible so that no one operation should starve another operation of it's time to execute (https://isocpp.org/wiki/faq/ctors#static-init-order).
|
||||||
- All EMS devices (e.g. boiler, thermostat, solar modules etc) are derived from a factory base class and each class handles its own registering of telegram and mqtt handlers. This makes the EMS device code easier to manage and extend with new telegrams types and features.
|
- All EMS devices (e.g. boiler, thermostat, solar modules etc) are derived from a factory base class and each class handles its own registering of telegram and mqtt handlers. This makes the EMS device code easier to manage and extend with new telegrams types and features.
|
||||||
- Built to work with both EMS8266 and ESP32.
|
- Built to work with both EMS8266 and ESP32.
|
||||||
- Extended MQTT to use MQTT discovery on Home Assistant, just for the thermostat
|
- Extended MQTT to use MQTT discovery on Home Assistant, just for the thermostat for now.
|
||||||
|
|
||||||
### **Features**
|
### **Features**
|
||||||
|
|
||||||
@@ -124,6 +124,7 @@ thermostat
|
|||||||
### **Known issues, bugs and improvements currently working on**
|
### **Known issues, bugs and improvements currently working on**
|
||||||
|
|
||||||
```
|
```
|
||||||
|
TODO when doing show, should we sort the ems devices?
|
||||||
TODO figure out why sometimes telnet on ESP32 (and sometimes ESP8266) has slow response times. After a manual reset it seems to fix itself. Perhaps the telnet service needs to start after the wifi is up & running.
|
TODO figure out why sometimes telnet on ESP32 (and sometimes ESP8266) has slow response times. After a manual reset it seems to fix itself. Perhaps the telnet service needs to start after the wifi is up & running.
|
||||||
TODO Get the ESP32 UART code working.
|
TODO Get the ESP32 UART code working.
|
||||||
TODO sometimes with tx_mode 0 there are a few CRC errors due to collision when waiting for a BRK signal.
|
TODO sometimes with tx_mode 0 there are a few CRC errors due to collision when waiting for a BRK signal.
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ Shell::~Shell() {
|
|||||||
|
|
||||||
void Shell::start() {
|
void Shell::start() {
|
||||||
#ifdef EMSESP_DEBUG
|
#ifdef EMSESP_DEBUG
|
||||||
uuid::log::Logger::register_handler(this, uuid::log::Level::DEBUG); // added by proddy
|
// uuid::log::Logger::register_handler(this, uuid::log::Level::DEBUG); // added by proddy
|
||||||
|
uuid::log::Logger::register_handler(this, uuid::log::Level::INFO); // added by proddy
|
||||||
#else
|
#else
|
||||||
uuid::log::Logger::register_handler(this, uuid::log::Level::NOTICE);
|
uuid::log::Logger::register_handler(this, uuid::log::Level::NOTICE);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ void Shell::output_logs() {
|
|||||||
auto message = std::move(log_messages_.front());
|
auto message = std::move(log_messages_.front());
|
||||||
log_messages_.pop_front();
|
log_messages_.pop_front();
|
||||||
|
|
||||||
|
|
||||||
print(uuid::log::format_timestamp_ms(message.content_->uptime_ms, 3));
|
print(uuid::log::format_timestamp_ms(message.content_->uptime_ms, 3));
|
||||||
printf(F(" %c %lu: [%S] "), uuid::log::format_level_char(message.content_->level), message.id_, message.content_->name);
|
printf(F(" %c %lu: [%S] "), uuid::log::format_level_char(message.content_->level), message.id_, message.content_->name);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
default_envs = esp8266
|
default_envs = esp8266
|
||||||
;default_envs = esp32
|
; default_envs = esp32
|
||||||
|
|
||||||
# override any settings with your own local ones in pio_local.ini
|
# override any settings with your own local ones in pio_local.ini
|
||||||
extra_configs = pio_local.ini
|
extra_configs = pio_local.ini
|
||||||
@@ -33,6 +33,7 @@ build_flags = -std=c++11 -Os -fno-exceptions
|
|||||||
-D ARDUINOJSON_USE_LONG_LONG=0
|
-D ARDUINOJSON_USE_LONG_LONG=0
|
||||||
-D BEARSSL_SSL_BASIC
|
-D BEARSSL_SSL_BASIC
|
||||||
-D PROGMEM_WWW
|
-D PROGMEM_WWW
|
||||||
|
-D UUID_TELNET_HAVE_WIFICLIENT_NODELAY=0
|
||||||
|
|
||||||
libs_core =
|
libs_core =
|
||||||
ArduinoJson
|
ArduinoJson
|
||||||
@@ -44,9 +45,8 @@ libs_esp8266 =
|
|||||||
libs_esp32 =
|
libs_esp32 =
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
build_unflags = -fno-rtti ; for dynamic_cast<>
|
;lib_ldf_mode = chain+
|
||||||
lib_ldf_mode = chain+
|
;lib_compat_mode = strict
|
||||||
lib_compat_mode = strict
|
|
||||||
extra_scripts = scripts/main_script.py
|
extra_scripts = scripts/main_script.py
|
||||||
framework = arduino
|
framework = arduino
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
@@ -57,13 +57,14 @@ check_flags =
|
|||||||
cppcheck: --std=c++11
|
cppcheck: --std=c++11
|
||||||
clangtidy: --checks=-*,clang-analyzer-*,performance-*
|
clangtidy: --checks=-*,clang-analyzer-*,performance-*
|
||||||
|
|
||||||
|
; USB upload
|
||||||
|
upload_protocol = esptool
|
||||||
; example ports for OSX
|
; example ports for OSX
|
||||||
;upload_port = /dev/cu.wchusbserial14403
|
;upload_port = /dev/cu.wchusbserial14403
|
||||||
;upload_port = /dev/cu.usbserial-1440
|
;upload_port = /dev/cu.usbserial-1440
|
||||||
;upload_port = /dev/cu.SLAB_USBtoUART
|
;upload_port = /dev/cu.SLAB_USBtoUART
|
||||||
|
|
||||||
; OTA
|
; OTA upload
|
||||||
upload_protocol = esptool
|
|
||||||
; upload_protocol = espota
|
; upload_protocol = espota
|
||||||
; upload_flags =
|
; upload_flags =
|
||||||
; --port=8266
|
; --port=8266
|
||||||
@@ -79,7 +80,7 @@ board = esp12e
|
|||||||
lib_deps = ${common.libs_core} ${common.libs_esp8266}
|
lib_deps = ${common.libs_core} ${common.libs_esp8266}
|
||||||
board_build.f_cpu = 160000000L ; 160MHz
|
board_build.f_cpu = 160000000L ; 160MHz
|
||||||
;board_build.ldscript = eagle.flash.4m1m.ld ; 1019 KB sketch, 1000 KB SPIFFS. 4KB EEPROM, 4KB RFCAL, 12KB WIFI stack, 2052 KB OTA & buffer
|
;board_build.ldscript = eagle.flash.4m1m.ld ; 1019 KB sketch, 1000 KB SPIFFS. 4KB EEPROM, 4KB RFCAL, 12KB WIFI stack, 2052 KB OTA & buffer
|
||||||
board_build.ldscript = eagle.flash.4m2m.ld ; same as above but with 2024 KB SPIFFS
|
board_build.ldscript = eagle.flash.4m2m.ld ; 1019 KB sketch, 2024 KB SPIFFS. 4KB EEPROM, 4KB RFCAL, 12KB WIFI stack, 1028 KB OTA & buffer
|
||||||
build_flags = ${common.build_flags} ${common.debug_flags} -flto -D PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
build_flags = ${common.build_flags} ${common.debug_flags} -flto -D PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||||
|
|
||||||
[env:esp32]
|
[env:esp32]
|
||||||
|
|||||||
119
src/boiler.cpp
119
src/boiler.cpp
@@ -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(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(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(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(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(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(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(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(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(0xE4, F("UBAMonitorFastPlus"), true, std::bind(&Boiler::process_UBAMonitorFastPlus, this, _1));
|
||||||
register_telegram_type(0xE5, F("UBAMonitorSlowPlus"), false, std::bind(&Boiler::process_UBAMonitorSlowPlus, 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(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));
|
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,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(boiler)},
|
flash_string_vector{F_(boiler)},
|
||||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
dynamic_cast<EMSESPShell &>(shell).enter_custom_context(ShellContext::BOILER);
|
Boiler::console_commands(shell, ShellContext::BOILER);
|
||||||
console_commands();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +315,10 @@ void Boiler::publish_values() {
|
|||||||
DEBUG_LOG(F("[DEBUG] Performing a boiler publish"));
|
DEBUG_LOG(F("[DEBUG] Performing a boiler publish"));
|
||||||
#endif
|
#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
|
// 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
|
char buffer[10]; // used for formatting
|
||||||
|
|
||||||
print_value(shell, F("Selected flow temperature"), F_(degrees), Helpers::render_value(buffer, selFlowTemp_, 1));
|
print_value(shell, 2, 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("Warm Water selected temperature"), F_(degrees), Helpers::render_value(buffer, wWSelTemp_, 1));
|
||||||
|
|
||||||
if (tap_water_active_ != EMS_VALUE_BOOL_NOTSET) {
|
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) {
|
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, 2, 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, 2, 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 circulation pump type"), wWCircPumpType_ ? "3-way pump" : "charge pump");
|
||||||
if (wWCircPumpMode_ == 7) {
|
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 {
|
} else {
|
||||||
char s[7];
|
char s[7];
|
||||||
char buffer[2];
|
char buffer[2];
|
||||||
@@ -353,64 +355,64 @@ void Boiler::show_values(uuid::console::Shell & shell) {
|
|||||||
buffer[1] = '\0';
|
buffer[1] = '\0';
|
||||||
strlcpy(s, buffer, 7);
|
strlcpy(s, buffer, 7);
|
||||||
strlcat(s, "x3min", 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) {
|
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) {
|
} 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) {
|
} 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, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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 # starts"), Helpers::render_value(buffer, wWStarts_, 1));
|
||||||
if (wWWorkM_ != EMS_VALUE_ULONG_NOTSET) {
|
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);
|
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, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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("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, 2, 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, 2, 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, 2, 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));
|
print_value(shell, 2, F("System pressure"), F("bar"), Helpers::render_value(buffer, sysPress_, 10));
|
||||||
if (serviceCode_ == EMS_VALUE_USHORT_NOTSET) {
|
if (serviceCode_ != EMS_VALUE_USHORT_NOTSET) {
|
||||||
shell.printfln(F(" System service code: %s"), serviceCodeChar_);
|
|
||||||
} else {
|
|
||||||
shell.printfln(F(" System service code: %s (%d)"), serviceCodeChar_, serviceCode_);
|
shell.printfln(F(" System service code: %s (%d)"), serviceCodeChar_, serviceCode_);
|
||||||
|
} else if (serviceCodeChar_[0] != '\0') {
|
||||||
|
shell.printfln(F(" System service code: %s"), serviceCodeChar_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// UBAParameters
|
// UBAParameters
|
||||||
print_value(shell, F("Heating temperature setting on the boiler"), F_(degrees), Helpers::render_value(buffer, heating_temp_, 1));
|
print_value(shell, 2, 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, 2, 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("Boiler circuit pump modulation min power"), F_(percent), Helpers::render_value(buffer, pump_mod_min_, 1));
|
||||||
|
|
||||||
// UBAMonitorSlow
|
// UBAMonitorSlow
|
||||||
if (extTemp_ != EMS_VALUE_SHORT_NOTSET) {
|
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, 2, 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, 2, 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("Burner # starts"), Helpers::render_value(buffer, burnStarts_, 1));
|
||||||
if (burnWorkMin_ != EMS_VALUE_ULONG_NOTSET) {
|
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);
|
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) {
|
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) {
|
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+
|
* 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) {
|
void Boiler::process_UBAMonitorFastPlus(std::shared_ptr<const Telegram> telegram) {
|
||||||
telegram->read_value(selFlowTemp_, 6);
|
telegram->read_value(selFlowTemp_, 6);
|
||||||
@@ -562,8 +565,6 @@ void Boiler::process_UBAMonitorFastPlus(std::shared_ptr<const Telegram> telegram
|
|||||||
serviceCodeChar_[2] = '\0';
|
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
|
// at this point do a quick check to see if the hot water or heating is active
|
||||||
check_active();
|
check_active();
|
||||||
}
|
}
|
||||||
@@ -754,7 +755,7 @@ void Boiler::set_warmwater_circulation(const bool activated) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add console commands
|
// add console commands
|
||||||
void Boiler::console_commands() {
|
void Boiler::console_commands(Shell & shell, unsigned int context) {
|
||||||
EMSESPShell::commands->add_command(ShellContext::BOILER,
|
EMSESPShell::commands->add_command(ShellContext::BOILER,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(read)},
|
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.printfln(F_(shower_alert_fmt), settings.shower_alert() ? F_(enabled) : F_(disabled));
|
||||||
shell.println();
|
shell.println();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// enter the context
|
||||||
|
Console::enter_custom_context(shell, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
36
src/boiler.h
36
src/boiler.h
@@ -46,7 +46,7 @@ class Boiler : public EMSdevice {
|
|||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
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
|
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
|
uint8_t wWComfort_ = EMS_VALUE_UINT_NOTSET; // WW comfort mode
|
||||||
|
|
||||||
// UBAMonitorFast - 0x18 on EMS1
|
// UBAMonitorFast - 0x18 on EMS1
|
||||||
uint8_t selFlowTemp_ = EMS_VALUE_UINT_NOTSET; // Selected flow temperature
|
uint8_t selFlowTemp_ = EMS_VALUE_UINT_NOTSET; // Selected flow temperature
|
||||||
uint16_t curFlowTemp_ = EMS_VALUE_USHORT_NOTSET; // Current 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 wwStorageTemp1_ = EMS_VALUE_USHORT_NOTSET; // warm water storage temp 1
|
||||||
uint16_t wwStorageTemp2_ = EMS_VALUE_USHORT_NOTSET; // warm water storage temp 2
|
uint16_t wwStorageTemp2_ = EMS_VALUE_USHORT_NOTSET; // warm water storage temp 2
|
||||||
uint16_t retTemp_ = EMS_VALUE_USHORT_NOTSET; // Return temperature
|
uint16_t retTemp_ = EMS_VALUE_USHORT_NOTSET; // Return temperature
|
||||||
uint8_t burnGas_ = EMS_VALUE_BOOL_NOTSET; // Gas on/off
|
uint8_t burnGas_ = EMS_VALUE_BOOL_NOTSET; // Gas on/off
|
||||||
uint8_t fanWork_ = EMS_VALUE_BOOL_NOTSET; // Fan on/off
|
uint8_t fanWork_ = EMS_VALUE_BOOL_NOTSET; // Fan on/off
|
||||||
uint8_t ignWork_ = EMS_VALUE_BOOL_NOTSET; // Ignition 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 heatPmp_ = EMS_VALUE_BOOL_NOTSET; // Boiler pump on/off
|
||||||
uint8_t wWHeat_ = EMS_VALUE_BOOL_NOTSET; // 3-way valve on WW
|
uint8_t wWHeat_ = EMS_VALUE_BOOL_NOTSET; // 3-way valve on WW
|
||||||
uint8_t wWCirc_ = EMS_VALUE_BOOL_NOTSET; // Circulation on/off
|
uint8_t wWCirc_ = EMS_VALUE_BOOL_NOTSET; // Circulation on/off
|
||||||
uint8_t selBurnPow_ = EMS_VALUE_UINT_NOTSET; // Burner max power %
|
uint8_t selBurnPow_ = EMS_VALUE_UINT_NOTSET; // Burner max power %
|
||||||
uint8_t curBurnPow_ = EMS_VALUE_UINT_NOTSET; // Burner current power %
|
uint8_t curBurnPow_ = EMS_VALUE_UINT_NOTSET; // Burner current power %
|
||||||
uint16_t flameCurr_ = EMS_VALUE_USHORT_NOTSET; // Flame current in micro amps
|
uint16_t flameCurr_ = EMS_VALUE_USHORT_NOTSET; // Flame current in micro amps
|
||||||
uint8_t sysPress_ = EMS_VALUE_UINT_NOTSET; // System pressure
|
uint8_t sysPress_ = EMS_VALUE_UINT_NOTSET; // System pressure
|
||||||
char serviceCodeChar_[3]; // 2 character status/service code
|
char serviceCodeChar_[3] = {'\0'}; // 2 character status/service code
|
||||||
uint16_t serviceCode_ = EMS_VALUE_USHORT_NOTSET; // error/service code
|
uint16_t serviceCode_ = EMS_VALUE_USHORT_NOTSET; // error/service code
|
||||||
|
|
||||||
// UBAMonitorSlow - 0x19 on EMS1
|
// UBAMonitorSlow - 0x19 on EMS1
|
||||||
int16_t extTemp_ = EMS_VALUE_SHORT_NOTSET; // Outside temperature
|
int16_t extTemp_ = EMS_VALUE_SHORT_NOTSET; // Outside temperature
|
||||||
|
|||||||
165
src/console.cpp
165
src/console.cpp
@@ -21,7 +21,11 @@
|
|||||||
|
|
||||||
namespace emsesp {
|
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;
|
static std::shared_ptr<EMSESPShell> shell;
|
||||||
|
|
||||||
std::vector<bool> EMSESPStreamConsole::ptys_;
|
std::vector<bool> EMSESPStreamConsole::ptys_;
|
||||||
@@ -32,11 +36,6 @@ uuid::telnet::TelnetService telnet_([](Stream & stream, const IPAddress & addr,
|
|||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::shared_ptr<Commands> EMSESPShell::commands = [] {
|
|
||||||
std::shared_ptr<Commands> commands = std::make_shared<Commands>();
|
|
||||||
return commands;
|
|
||||||
}();
|
|
||||||
|
|
||||||
EMSESPShell::EMSESPShell()
|
EMSESPShell::EMSESPShell()
|
||||||
: Shell() {
|
: Shell() {
|
||||||
}
|
}
|
||||||
@@ -125,7 +124,7 @@ void EMSESPShell::add_console_commands() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add the submenu contexts...
|
* add all the submenu contexts...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// MQTT
|
// MQTT
|
||||||
@@ -133,8 +132,7 @@ void EMSESPShell::add_console_commands() {
|
|||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(mqtt)},
|
flash_string_vector{F_(mqtt)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
dynamic_cast<EMSESPShell &>(shell).enter_custom_context(ShellContext::MQTT);
|
Mqtt::console_commands(shell, ShellContext::MQTT);
|
||||||
Mqtt::console_commands();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// EMS
|
// EMS
|
||||||
@@ -142,8 +140,7 @@ void EMSESPShell::add_console_commands() {
|
|||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(ems)},
|
flash_string_vector{F_(ems)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
dynamic_cast<EMSESPShell &>(shell).enter_custom_context(ShellContext::EMS);
|
EMSESP::console_commands(shell, ShellContext::EMS);
|
||||||
EMSESP::console_commands();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// System
|
// System
|
||||||
@@ -151,15 +148,14 @@ void EMSESPShell::add_console_commands() {
|
|||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(system)},
|
flash_string_vector{F_(system)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
dynamic_cast<EMSESPShell &>(shell).enter_custom_context(ShellContext::SYSTEM);
|
System::console_commands(shell, ShellContext::SYSTEM);
|
||||||
System::console_commands();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// add all the context menus for the connected devices
|
// add all the context menus for the connected devices
|
||||||
// this assumes they devices have been detected and registered
|
// this assumes they devices have been detected and pre-registered
|
||||||
EMSESP::add_context_menu();
|
EMSESP::add_context_menus();
|
||||||
|
|
||||||
enter_custom_context(ShellContext::MAIN); // add su, exit and help
|
Console::load_standard_commands(ShellContext::MAIN);
|
||||||
|
|
||||||
_console_commands_loaded = true;
|
_console_commands_loaded = true;
|
||||||
}
|
}
|
||||||
@@ -199,17 +195,29 @@ bool EMSESPShell::exit_context() {
|
|||||||
return Shell::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
|
// 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
|
#ifdef EMSESP_DEBUG
|
||||||
commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(test)},
|
flash_string_vector{F_(test)},
|
||||||
flash_string_vector{F_(name_mandatory)},
|
flash_string_vector{F_(name_mandatory)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { EMSESP::run_test(shell, arguments.front()); });
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
|
EMSESP::run_test(shell, arguments.front());
|
||||||
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
commands->add_command(
|
EMSESPShell::commands->add_command(
|
||||||
context,
|
context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(log)},
|
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
|
uint16_t watch_id = 0; // no watch ID set
|
||||||
if ((arguments.size() == 2) && (level == uuid::log::Level::TRACE)) {
|
if ((arguments.size() == 2) && (level == uuid::log::Level::TRACE)) {
|
||||||
watch_id = Helpers::hextoint(arguments[1].c_str());
|
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);
|
emsesp::EMSESP::trace_watch_id(watch_id);
|
||||||
}
|
}
|
||||||
@@ -239,68 +247,61 @@ void EMSESPShell::enter_custom_context(unsigned int context) {
|
|||||||
return uuid::log::levels_lowercase();
|
return uuid::log::levels_lowercase();
|
||||||
});
|
});
|
||||||
|
|
||||||
commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(help)},
|
flash_string_vector{F_(help)},
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { shell.print_all_available_commands(); });
|
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
|
shell.print_all_available_commands();
|
||||||
|
});
|
||||||
|
|
||||||
commands->add_command(context,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(exit)},
|
flash_string_vector{F_(exit)},
|
||||||
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { shell.exit_context(); });
|
[=](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,
|
EMSESPShell::commands->add_command(context,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(su)},
|
flash_string_vector{F_(su)},
|
||||||
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
auto become_admin = [](Shell & shell) {
|
auto become_admin = [](Shell & shell) {
|
||||||
shell.logger().log(LogLevel::NOTICE,
|
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, F("Admin session opened on console"));
|
||||||
LogFacility::AUTH,
|
shell.add_flags(CommandFlags::ADMIN);
|
||||||
F("Admin session opened on console %s"),
|
};
|
||||||
dynamic_cast<EMSESPShell &>(shell).console_name().c_str());
|
|
||||||
shell.add_flags(CommandFlags::ADMIN);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (shell.has_flags(CommandFlags::LOCAL)) {
|
if (shell.has_flags(CommandFlags::LOCAL)) {
|
||||||
become_admin(shell);
|
become_admin(shell);
|
||||||
} else {
|
} else {
|
||||||
shell.enter_password(F_(password_prompt), [=](Shell & shell, bool completed, const std::string & password) {
|
shell.enter_password(F_(password_prompt), [=](Shell & shell, bool completed, const std::string & password) {
|
||||||
if (completed) {
|
if (completed) {
|
||||||
uint64_t now = uuid::get_uptime_ms();
|
uint64_t now = uuid::get_uptime_ms();
|
||||||
|
|
||||||
if (!password.empty() && password == Settings().admin_password()) {
|
if (!password.empty() && password == Settings().admin_password()) {
|
||||||
become_admin(shell);
|
become_admin(shell);
|
||||||
} else {
|
} else {
|
||||||
shell.delay_until(now + INVALID_PASSWORD_DELAY_MS, [](Shell & shell) {
|
shell.delay_until(now + INVALID_PASSWORD_DELAY_MS, [](Shell & shell) {
|
||||||
shell.logger().log(LogLevel::NOTICE,
|
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, F("Invalid admin password on console"));
|
||||||
LogFacility::AUTH,
|
shell.println(F("su: incorrect password"));
|
||||||
F("Invalid admin password on console %s"),
|
});
|
||||||
dynamic_cast<EMSESPShell &>(shell).console_name().c_str());
|
}
|
||||||
shell.println(F("su: incorrect password"));
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
#ifdef EMSESP_DEBUG
|
#ifdef EMSESP_DEBUG
|
||||||
commands->add_command(context,
|
EMSESPShell::commands->add_command(
|
||||||
CommandFlags::ADMIN,
|
context, CommandFlags::ADMIN, flash_string_vector{F_(debug)}, [&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
flash_string_vector{F_(debug)},
|
shell.printfln(F("%s%sEMS-ESP version %s%s"), COLOR_BRIGHT_GREEN, COLOR_BOLD_ON, Settings().app_version().c_str(), COLOR_RESET);
|
||||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
Settings settings;
|
||||||
shell.printfln(F("%s%sEMS-ESP version %s%s"), COLOR_BRIGHT_GREEN, COLOR_BOLD_ON, Settings().app_version().c_str(), COLOR_RESET);
|
settings.commit();
|
||||||
Settings settings;
|
settings.show_settings(shell);
|
||||||
settings.commit();
|
shell.println();
|
||||||
settings.show_settings(shell);
|
});
|
||||||
shell.println();
|
|
||||||
});
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// don't enter context if we're at the root
|
|
||||||
if (context != ShellContext::MAIN) {
|
|
||||||
Shell::enter_context(context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// prompt, change per context
|
// prompt, change per context
|
||||||
@@ -339,8 +340,6 @@ std::string EMSESPShell::prompt_suffix() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EMSESPShell::end_of_transmission() {
|
void EMSESPShell::end_of_transmission() {
|
||||||
// delete MAIN console stuff
|
|
||||||
commands->remove_context_commands(ShellContext::MAIN);
|
|
||||||
invoke_command(uuid::read_flash_string(F_(exit)));
|
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
|
// note, this must be started after the network/wifi for ESP32 otherwise it'll crash
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
telnet_.start();
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,8 +427,6 @@ void Console::loop() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Shell::loop_all();
|
Shell::loop_all();
|
||||||
|
|
||||||
// delay(0); // in EMS-ESP 1.9.5 this helped with stability
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -125,7 +125,13 @@ namespace emsesp {
|
|||||||
using LogLevel = ::uuid::log::Level;
|
using LogLevel = ::uuid::log::Level;
|
||||||
using LogFacility = ::uuid::log::Facility;
|
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 {
|
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<uuid::console::Commands> commands;
|
||||||
static std::shared_ptr<EMSESPShell> shell;
|
static std::shared_ptr<EMSESPShell> shell;
|
||||||
|
|
||||||
void enter_custom_context(unsigned int context);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EMSESPShell();
|
EMSESPShell();
|
||||||
|
|
||||||
@@ -191,6 +195,9 @@ class Console {
|
|||||||
|
|
||||||
uuid::log::Level log_level();
|
uuid::log::Level log_level();
|
||||||
|
|
||||||
|
static void enter_custom_context(Shell & shell, unsigned int context);
|
||||||
|
static void load_standard_commands(unsigned int context);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr unsigned long SERIAL_CONSOLE_BAUD_RATE = 115200;
|
static constexpr unsigned long SERIAL_CONSOLE_BAUD_RATE = 115200;
|
||||||
static constexpr auto & serial_console_ = Serial;
|
static constexpr auto & serial_console_ = Serial;
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
{115, DeviceType::BOILER, F("Topline/GB162"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{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},
|
{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},
|
{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},
|
{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},
|
{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},
|
{ 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},
|
{122, DeviceType::BOILER, F("Proline"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{170, DeviceType::BOILER, F("Logano GB212"), 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},
|
{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
|
// Solar Modules - 0x30
|
||||||
{ 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10},
|
{ 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},
|
{200, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Switches - 0x11
|
// 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
|
// 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
|
{218, DeviceType::CONTROLLER, F("M200/RFM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x50
|
||||||
{190, DeviceType::CONTROLLER, F("BC10"), 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
|
{114, DeviceType::CONTROLLER, F("BC10"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{125, DeviceType::CONTROLLER, F("BC25"), 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
|
{169, DeviceType::CONTROLLER, F("BC40"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{152, DeviceType::CONTROLLER, F("Controller"), 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
|
{ 95, DeviceType::CONTROLLER, F("HT3"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
{209, DeviceType::CONTROLLER, F("ErP"), 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
|
{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
|
{207, DeviceType::CONTROLLER, F("Sense II/CS200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x10
|
||||||
|
|
||||||
// Connect devices - 0x02
|
// Connect devices - 0x02
|
||||||
{205, DeviceType::CONNECT, F("Moduline Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 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
|
{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
|
// Gateways - 0x48 / 0x18
|
||||||
{189, DeviceType::GATEWAY, F("KM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x48
|
{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
|
// 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
|
{202, DeviceType::THERMOSTAT, F("Logamatic TC100/Moduline Easy"), DeviceFlags::EMS_DEVICE_FLAG_EASY | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18, cannot write
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ std::string EMSdevice::to_string() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (brand_ == Brand::NO_BRAND) {
|
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 {
|
} else {
|
||||||
snprintf_P(&str[0],
|
snprintf_P(&str[0],
|
||||||
str.capacity() + 1,
|
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
|
// for each telegram that has the fetch value set (true) do a read request
|
||||||
void EMSdevice::fetch_values() {
|
void EMSdevice::fetch_values() {
|
||||||
DEBUG_LOG(F("Fetching values for device ID 0x%02X"), device_id());
|
DEBUG_LOG(F("Fetching values for device ID 0x%02X"), device_id());
|
||||||
|
|
||||||
for (const auto & tf : telegram_functions_) {
|
for (const auto & tf : telegram_functions_) {
|
||||||
if (tf.fetch_) {
|
if (tf.fetch_) {
|
||||||
read_command(tf.telegram_type_id_);
|
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
|
// prints a value to the console
|
||||||
void EMSdevice::print_value(uuid::console::Shell & shell, const __FlashStringHelper * name, const __FlashStringHelper * prefix, const char * value) {
|
void EMSdevice::print_value(uuid::console::Shell & shell, uint8_t padding, const __FlashStringHelper * name, const __FlashStringHelper * suffix, const char * value) {
|
||||||
shell.printfln(PSTR(" %s: %s%s"), uuid::read_flash_string(name).c_str(), value, uuid::read_flash_string(prefix).c_str());
|
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
|
// prints a value to the console - with no prefix
|
||||||
void EMSdevice::print_value(uuid::console::Shell & shell, const __FlashStringHelper * name, const char * value) {
|
void EMSdevice::print_value(uuid::console::Shell & shell, uint8_t padding, const __FlashStringHelper * name, const char * value) {
|
||||||
shell.printfln(PSTR(" %s: %s"), uuid::read_flash_string(name).c_str(), value);
|
print_value(shell, padding, name, nullptr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -119,8 +119,8 @@ class EMSdevice {
|
|||||||
|
|
||||||
void fetch_values();
|
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, uint8_t padding, 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 char * value);
|
||||||
|
|
||||||
enum Brand : uint8_t {
|
enum Brand : uint8_t {
|
||||||
NO_BRAND, // 0
|
NO_BRAND, // 0
|
||||||
@@ -195,9 +195,8 @@ class EMSdevice {
|
|||||||
|
|
||||||
uint16_t telegram_type_id_; // it's type_id
|
uint16_t telegram_type_id_; // it's type_id
|
||||||
const __FlashStringHelper * telegram_type_name_; // e.g. RC20Message
|
const __FlashStringHelper * telegram_type_name_; // e.g. RC20Message
|
||||||
// std::string telegram_type_name_; // e.g. RC20Message
|
bool fetch_; // if this type_id be queried automatically
|
||||||
bool fetch_; // should this type_id be queried automatically?
|
process_function_p process_function_;
|
||||||
process_function_p process_function_;
|
|
||||||
};
|
};
|
||||||
std::vector<TelegramFunction> telegram_functions_; // each EMS device has its own set of registered telegram types
|
std::vector<TelegramFunction> telegram_functions_; // each EMS device has its own set of registered telegram types
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
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::tap_water_active_ = false; // for when Boiler states we having running warm water. used in Shower()
|
||||||
bool EMSESP::ems_read_only_;
|
bool EMSESP::ems_read_only_;
|
||||||
|
uint32_t EMSESP::last_fetch_ = 0;
|
||||||
|
|
||||||
#ifdef EMSESP_DEBUG
|
#ifdef EMSESP_DEBUG
|
||||||
#include "test/test_data.h" // used with the 'test' command, under su/admin
|
#include "test/test_data.h" // used with the 'test' command, under su/admin
|
||||||
#endif
|
#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() {
|
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
|
// 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 (emsdevice) {
|
||||||
if ((device_id == 0) || emsdevice->is_device_id(device_id)) {
|
if ((device_id == 0) || emsdevice->is_device_id(device_id)) {
|
||||||
emsdevice->fetch_values();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// show EMS device values
|
||||||
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
if (emsdevice) {
|
||||||
|
emsdevice->show_values(shell);
|
||||||
|
shell.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dallas sensors (if available)
|
// Dallas sensors (if available)
|
||||||
char valuestr[8] = {0}; // for formatting temp
|
char valuestr[8] = {0}; // for formatting temp
|
||||||
if (!sensor_devices().empty()) {
|
if (!sensor_devices().empty()) {
|
||||||
@@ -187,14 +198,6 @@ void EMSESP::show_values(uuid::console::Shell & shell) {
|
|||||||
shell.println();
|
shell.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
// show EMS device values
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
|
||||||
if (emsdevice) {
|
|
||||||
emsdevice->show_values(shell);
|
|
||||||
shell.println();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
// 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) {
|
void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
|
||||||
// check for valid telegram, just in case
|
// check for valid telegram, just in case
|
||||||
if (telegram->message_length < 3) {
|
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
|
// 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) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice) {
|
if (emsdevice) {
|
||||||
emsdevice->add_context_menu();
|
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 we don't recognize the product ID report it, but don't add it.
|
||||||
if (!found) {
|
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
|
return false; // not found
|
||||||
} else {
|
} 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
|
// go and fetch its data, including asking for the version
|
||||||
send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id);
|
send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id);
|
||||||
fetch_device_values(device_id);
|
fetch_device_values(device_id);
|
||||||
@@ -634,7 +638,7 @@ void EMSESP::set_ems_read_only() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// console commands to add
|
// console commands to add
|
||||||
void EMSESP::console_commands() {
|
void EMSESP::console_commands(Shell & shell, unsigned int context) {
|
||||||
EMSESPShell::commands->add_command(ShellContext::EMS,
|
EMSESPShell::commands->add_command(ShellContext::EMS,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(show), F_(devices)},
|
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_(bus_id_fmt), settings.ems_bus_id());
|
||||||
shell.printfln(F_(read_only_fmt), settings.ems_read_only() ? F_(enabled) : F_(disabled));
|
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
|
// 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
|
rxservice_.loop(); // process what ever is in the rx queue
|
||||||
shower_.loop(); // check for shower on/off
|
shower_.loop(); // check for shower on/off
|
||||||
sensors_.loop(); // this will also send out via MQTT
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class EMSESP {
|
|||||||
static void show_devices(uuid::console::Shell & shell);
|
static void show_devices(uuid::console::Shell & shell);
|
||||||
static void show_emsbus(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);
|
static void incoming_telegram(uint8_t * data, const uint8_t length);
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ class EMSESP {
|
|||||||
return ems_read_only_;
|
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(const uint8_t device_id);
|
||||||
static void fetch_device_values();
|
static void fetch_device_values();
|
||||||
@@ -136,6 +136,9 @@ class EMSESP {
|
|||||||
static RxService rxservice_;
|
static RxService rxservice_;
|
||||||
static TxService txservice_;
|
static TxService txservice_;
|
||||||
|
|
||||||
|
static constexpr uint32_t EMS_FETCH_FREQUENCY = 60000; // check every minute
|
||||||
|
static uint32_t last_fetch_;
|
||||||
|
|
||||||
struct Device_record {
|
struct Device_record {
|
||||||
uint8_t product_id;
|
uint8_t product_id;
|
||||||
EMSdevice::DeviceType device_type;
|
EMSdevice::DeviceType device_type;
|
||||||
|
|||||||
@@ -65,10 +65,10 @@ void Mixing::show_values(uuid::console::Shell & shell) {
|
|||||||
} else {
|
} else {
|
||||||
shell.printfln(F(" Heating Circuit #: %d"), hc_);
|
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, 2, 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, 2, 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, 2, 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 valve status"), Helpers::render_value(buffer, status_, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// publish values via MQTT
|
// publish values via MQTT
|
||||||
@@ -151,9 +151,9 @@ void Mixing::process_MMStatusMessage(std::shared_ptr<const Telegram> telegram) {
|
|||||||
type_ = Type::HC;
|
type_ = Type::HC;
|
||||||
|
|
||||||
// the heating circuit is determine by which device_id it is, 0x20 - 0x23
|
// 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
|
// 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(flowTemp_, 1); // is * 10
|
||||||
telegram->read_value(pumpMod_, 3);
|
telegram->read_value(pumpMod_, 3);
|
||||||
telegram->read_value(flowSetTemp_, 0);
|
telegram->read_value(flowSetTemp_, 0);
|
||||||
|
|||||||
37
src/mqtt.cpp
37
src/mqtt.cpp
@@ -40,7 +40,7 @@ MAKE_PSTR(mqtt_enabled_fmt, "MQTT is %s")
|
|||||||
MAKE_PSTR(mqtt_base_fmt, "Base = %s")
|
MAKE_PSTR(mqtt_base_fmt, "Base = %s")
|
||||||
MAKE_PSTR(mqtt_qos_fmt, "QOS = %ld")
|
MAKE_PSTR(mqtt_qos_fmt, "QOS = %ld")
|
||||||
MAKE_PSTR(mqtt_retain_fmt, "Retain Flag = %s")
|
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_heartbeat_fmt, "Heartbeat = %s")
|
||||||
MAKE_PSTR(mqtt_publish_time_fmt, "Publish time = %d seconds")
|
MAKE_PSTR(mqtt_publish_time_fmt, "Publish time = %d seconds")
|
||||||
|
|
||||||
@@ -52,6 +52,7 @@ namespace emsesp {
|
|||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
AsyncMqttClient Mqtt::mqttClient_;
|
AsyncMqttClient Mqtt::mqttClient_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<Mqtt::MQTTFunction> Mqtt::mqtt_functions_;
|
std::vector<Mqtt::MQTTFunction> Mqtt::mqtt_functions_;
|
||||||
bool Mqtt::mqtt_retain_;
|
bool Mqtt::mqtt_retain_;
|
||||||
uint8_t Mqtt::mqtt_qos_;
|
uint8_t Mqtt::mqtt_qos_;
|
||||||
@@ -463,17 +464,20 @@ void Mqtt::send_heartbeat() {
|
|||||||
|
|
||||||
// add MQTT message to queue, payload is a JSON doc.
|
// add MQTT message to queue, payload is a JSON doc.
|
||||||
// NOTE this only prints first 255 chars
|
// NOTE this only prints first 255 chars
|
||||||
void Mqtt::queue_publish_message(const char * topic, const JsonDocument & payload, const bool retain) {
|
void Mqtt::queue_publish_message(const std::string & topic, const JsonDocument & payload, const bool retain) {
|
||||||
if (strlen(topic) == 0) {
|
// can't have bogus topics, but empty payloads are ok
|
||||||
|
if (topic.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// check for empty JSON doc - we don't like those
|
// check for empty JSON doc - we don't like those
|
||||||
size_t capacity = measureJson(payload);
|
size_t capacity = measureJson(payload);
|
||||||
if (capacity <= 3) {
|
if (capacity <= 3) {
|
||||||
// DEBUG_LOG(("Empty JSON for topic %s. Skipping"), topic);
|
// DEBUG_LOG(("Empty JSON payload for topic %s. Skipping"), topic);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
std::string payload_text;
|
std::string payload_text;
|
||||||
serializeJson(payload, 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
|
// 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
|
// can't have bogus topics, but empty payloads are ok
|
||||||
if (strlen(topic) == 0) {
|
if (topic.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,29 +529,29 @@ void Mqtt::queue_subscribe_message(const std::string & topic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MQTT Publish, using a specific retain flag
|
// 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);
|
queue_publish_message(topic, payload, retain);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish using the user's custom retain flag
|
// 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_);
|
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_);
|
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);
|
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_);
|
queue_publish_message(topic, value ? "1" : "0", mqtt_retain_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no payload
|
// no payload
|
||||||
void Mqtt::publish(const char * topic) {
|
void Mqtt::publish(const std::string & topic) {
|
||||||
queue_publish_message(topic, "", mqtt_retain_);
|
queue_publish_message(topic, "", mqtt_retain_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,10 +638,10 @@ void Mqtt::process_queue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mqtt_messages_.pop_front(); // remove the message from the queue
|
mqtt_messages_.pop_front(); // remove the message from the queue
|
||||||
} // namespace emsesp
|
}
|
||||||
|
|
||||||
// add console commands
|
// add console commands
|
||||||
void Mqtt::console_commands() {
|
void Mqtt::console_commands(Shell & shell, unsigned int context) {
|
||||||
EMSESPShell::commands->add_command(
|
EMSESPShell::commands->add_command(
|
||||||
ShellContext::MQTT,
|
ShellContext::MQTT,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
@@ -853,6 +857,9 @@ void Mqtt::console_commands() {
|
|||||||
shell.printfln(F_(mqtt_publish_time_fmt), settings.mqtt_publish_time());
|
shell.printfln(F_(mqtt_publish_time_fmt), settings.mqtt_publish_time());
|
||||||
shell.println();
|
shell.println();
|
||||||
});
|
});
|
||||||
} // namespace emsesp
|
|
||||||
|
// enter the context
|
||||||
|
Console::enter_custom_context(shell, context);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
20
src/mqtt.h
20
src/mqtt.h
@@ -39,6 +39,8 @@
|
|||||||
|
|
||||||
#include <uuid/log.h>
|
#include <uuid/log.h>
|
||||||
|
|
||||||
|
using uuid::console::Shell;
|
||||||
|
|
||||||
#define EMSESP_MAX_JSON_SIZE_SMALL 200 // for smaller json docs
|
#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_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
|
#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 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 subscribe(const std::string & topic, mqtt_function_p cb);
|
||||||
|
|
||||||
static void publish(const char * topic, const char * payload);
|
static void publish(const std::string & topic, const std::string & payload);
|
||||||
static void publish(const char * topic, const char * payload, bool retain);
|
static void publish(const std::string & topic, const std::string & payload, bool retain);
|
||||||
static void publish(const char * topic, const JsonDocument & payload);
|
static void publish(const std::string & topic, const JsonDocument & payload);
|
||||||
static void publish(const char * topic, const JsonDocument & payload, bool retain);
|
static void publish(const std::string & topic, const JsonDocument & payload, bool retain);
|
||||||
static void publish(const char * topic, const bool value);
|
static void publish(const std::string & topic, const bool value);
|
||||||
static void publish(const char * topic);
|
static void publish(const std::string & topic);
|
||||||
|
|
||||||
static void show_topic_handlers(uuid::console::Shell & shell, const uint8_t device_id);
|
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
|
void incoming(char * topic, char * payload); // for testing
|
||||||
|
|
||||||
@@ -130,8 +132,8 @@ class Mqtt {
|
|||||||
|
|
||||||
static bool mqtt_retain_;
|
static bool mqtt_retain_;
|
||||||
|
|
||||||
static void queue_publish_message(const char * topic, const JsonDocument & 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 char * topic, const std::string & 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);
|
static void queue_subscribe_message(const std::string & topic);
|
||||||
|
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ void Network::show_network(uuid::console::Shell & shell) {
|
|||||||
shell.printfln(F("WiFi: unknown"));
|
shell.printfln(F("WiFi: unknown"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
shell.println();
|
shell.println();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,20 +54,20 @@ void Solar::show_values(uuid::console::Shell & shell) {
|
|||||||
|
|
||||||
char buffer[10]; // used for formatting
|
char buffer[10]; // used for formatting
|
||||||
|
|
||||||
print_value(shell, F("Collector temperature (TS1)"), F_(degrees), Helpers::render_value(buffer, collectorTemp_, 10));
|
print_value(shell, 2, 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, 2, 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, 2, 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, 2, 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, 2, 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("Pump (PS1) active"), Helpers::render_value(buffer, pump_, EMS_VALUE_BOOL));
|
||||||
|
|
||||||
if (pumpWorkMin_ != EMS_VALUE_ULONG_NOTSET) {
|
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);
|
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, 2, 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, 2, 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 total"), F_(kwh), Helpers::render_value(buffer, energyTotal_, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
// publish values via MQTT
|
// publish values via MQTT
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ void System::show_system(uuid::console::Shell & shell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// console commands to add
|
// console commands to add
|
||||||
void System::console_commands() {
|
void System::console_commands(Shell & shell, unsigned int context) {
|
||||||
EMSESPShell::commands->add_command(ShellContext::SYSTEM,
|
EMSESPShell::commands->add_command(ShellContext::SYSTEM,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(set), F_(hostname)},
|
flash_string_vector{F_(set), F_(hostname)},
|
||||||
@@ -509,7 +509,6 @@ void System::console_commands() {
|
|||||||
flash_string_vector{F_(show)},
|
flash_string_vector{F_(show)},
|
||||||
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
Network::show_network(shell);
|
Network::show_network(shell);
|
||||||
shell.println();
|
|
||||||
show_system(shell);
|
show_system(shell);
|
||||||
shell.println();
|
shell.println();
|
||||||
});
|
});
|
||||||
@@ -522,7 +521,7 @@ void System::console_commands() {
|
|||||||
shell.printfln(F_(hostname_fmt),
|
shell.printfln(F_(hostname_fmt),
|
||||||
settings.hostname().empty() ? uuid::read_flash_string(F_(unset)).c_str() : settings.hostname().c_str());
|
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.printfln("Wifi:");
|
||||||
shell.print(" ");
|
shell.print(" ");
|
||||||
shell.printfln(F_(wifi_ssid_fmt),
|
shell.printfln(F_(wifi_ssid_fmt),
|
||||||
@@ -540,6 +539,9 @@ void System::console_commands() {
|
|||||||
shell.printfln(F_(mark_interval_fmt), settings.syslog_mark_interval());
|
shell.printfln(F_(mark_interval_fmt), settings.syslog_mark_interval());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// enter the context
|
||||||
|
Console::enter_custom_context(shell, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,8 @@
|
|||||||
|
|
||||||
#include <uuid/log.h>
|
#include <uuid/log.h>
|
||||||
|
|
||||||
|
using uuid::console::Shell;
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
class System {
|
class System {
|
||||||
@@ -63,7 +65,7 @@ class System {
|
|||||||
|
|
||||||
static void show_mem(const char * text);
|
static void show_mem(const char * text);
|
||||||
|
|
||||||
static void console_commands();
|
static void console_commands(Shell & shell, unsigned int context);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
// create some fake test data
|
// create some fake test data
|
||||||
// used with the 'test' command, under su/admin
|
// used with the 'test' command, under su/admin
|
||||||
void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command) {
|
void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command) {
|
||||||
// A fake response - UBADevices(0x07) - only for testing offline
|
|
||||||
if (command == "devices") {
|
if (command == "devices") {
|
||||||
rxservice_.ems_mask(EMSbus::EMS_MASK_BUDERUS); // this is important otherwise nothing will be picked up!
|
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));
|
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};
|
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));
|
rxservice_.add(t0, sizeof(t0));
|
||||||
|
|
||||||
@@ -21,6 +21,20 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
|
|||||||
return;
|
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") {
|
if (command == "thermostats") {
|
||||||
shell.printfln(F("Testing adding devices on the EMS bus..."));
|
shell.printfln(F("Testing adding devices on the EMS bus..."));
|
||||||
|
|
||||||
|
|||||||
@@ -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_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
|
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) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_RC10) {
|
||||||
monitor_typeids = {0xB1};
|
monitor_typeids = {0xB1};
|
||||||
set_typeids = {0xB0};
|
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));
|
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)) {
|
} else if ((flags == EMSdevice::EMS_DEVICE_FLAG_RC35) || (flags == EMSdevice::EMS_DEVICE_FLAG_RC30_1)) {
|
||||||
monitor_typeids = {0x3E, 0x48, 0x52, 0x5C};
|
monitor_typeids = {0x3E, 0x48, 0x52, 0x5C};
|
||||||
set_typeids = {0x3D, 0x47, 0x51, 0x5B};
|
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));
|
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) {
|
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20) {
|
||||||
monitor_typeids = {0x91};
|
monitor_typeids = {0x91};
|
||||||
set_typeids = {0xA8};
|
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));
|
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) {
|
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20_2) {
|
||||||
monitor_typeids = {0xAE};
|
monitor_typeids = {0xAE};
|
||||||
set_typeids = {0xAD};
|
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));
|
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) {
|
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_RC30) {
|
||||||
monitor_typeids = {0x41};
|
monitor_typeids = {0x41};
|
||||||
set_typeids = {0xA7};
|
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));
|
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) {
|
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_EASY) {
|
||||||
monitor_typeids = {0x0A};
|
monitor_typeids = {0x0A};
|
||||||
set_typeids = {};
|
set_typeids = {};
|
||||||
register_telegram_type(monitor_typeids[0], F("EasyMonitor"), true, std::bind(&Thermostat::process_EasyMonitor, this, _1));
|
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)) {
|
} else if ((flags == EMSdevice::EMS_DEVICE_FLAG_RC300) || (flags == EMSdevice::EMS_DEVICE_FLAG_RC100)) {
|
||||||
monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8};
|
monitor_typeids = {0x02A5, 0x02A6, 0x02A7, 0x02A8};
|
||||||
set_typeids = {0x02B9, 0x02BA, 0x02BB, 0x02BC};
|
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));
|
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) {
|
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
|
||||||
monitor_typeids = {0x6F, 0x70, 0x71, 0x72};
|
monitor_typeids = {0x6F, 0x70, 0x71, 0x72};
|
||||||
set_typeids = {0x65, 0x66, 0x67, 0x68};
|
set_typeids = {0x65, 0x66, 0x67, 0x68};
|
||||||
@@ -194,8 +202,7 @@ void Thermostat::add_context_menu() {
|
|||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
flash_string_vector{F_(thermostat)},
|
flash_string_vector{F_(thermostat)},
|
||||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||||
dynamic_cast<EMSESPShell &>(shell).enter_custom_context(ShellContext::THERMOSTAT);
|
Thermostat::console_commands(shell, ShellContext::THERMOSTAT);
|
||||||
console_commands();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +333,7 @@ bool Thermostat::updated_values() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} // namespace emsesp
|
}
|
||||||
|
|
||||||
// publish values via MQTT
|
// publish values via MQTT
|
||||||
void Thermostat::publish_values() {
|
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());
|
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;
|
bool has_data = false;
|
||||||
|
|
||||||
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
|
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
|
||||||
@@ -364,6 +371,7 @@ void Thermostat::publish_values() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
has_data = true;
|
has_data = true;
|
||||||
|
// if the MQTT format is 'nested' then create the parent object hc<n>
|
||||||
if (mqtt_format_ == Settings::MQTT_format::NESTED) {
|
if (mqtt_format_ == Settings::MQTT_format::NESTED) {
|
||||||
// create nested json for each HC
|
// create nested json for each HC
|
||||||
char hc_name[10]; // hc{1-4}
|
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
|
// decodes the thermostat mode for the heating circuit based on the thermostat type
|
||||||
// modes are off, manual, auto, day and night
|
// modes are off, manual, auto, day and night
|
||||||
uint8_t Thermostat::HeatingCircuit::get_mode(uint8_t flags) const {
|
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
|
flags &= 0x0F; // strip top 4 bits
|
||||||
|
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_RC20) {
|
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
|
// 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:
|
case HeatingCircuit::Mode::NOFROST:
|
||||||
return read_flash_string(F("nofrost"));
|
return read_flash_string(F("nofrost"));
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
case HeatingCircuit::Mode::AUTO:
|
case HeatingCircuit::Mode::AUTO:
|
||||||
return read_flash_string(F("auto"));
|
return read_flash_string(F("auto"));
|
||||||
break;
|
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
|
char buffer[10]; // for formatting only
|
||||||
|
|
||||||
if (datetime_.size()) {
|
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) {
|
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
|
uint8_t flags = (this->flags() & 0x0F); // specific thermostat characteristics, strip the option bits
|
||||||
|
|
||||||
if (flags == EMS_DEVICE_FLAG_RC35) {
|
if (flags == EMS_DEVICE_FLAG_RC35) {
|
||||||
print_value(shell, F("Damped Outdoor temperature"), F_(degrees), Helpers::render_value(buffer, dampedoutdoortemp, 1));
|
print_value(shell, 1, 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, 1, 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("Tempsensor 2"), F_(degrees), Helpers::render_value(buffer, tempsensor2, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto & hc : heating_circuits_) {
|
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
|
// different thermostat types store their temperature values differently
|
||||||
uint8_t format_setpoint, format_curr;
|
uint8_t format_setpoint, format_curr;
|
||||||
@@ -677,83 +692,87 @@ void Thermostat::show_values(uuid::console::Shell & shell) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_value(shell, F("Current room temperature"), F_(degrees), Helpers::render_value(buffer, hc->curr_roomTemp, format_curr));
|
print_value(shell, 2, 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, 2, 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());
|
if (hc->mode != EMS_VALUE_UINT_NOTSET) {
|
||||||
print_value(shell, F("Mode Type"), mode_tostring(hc->get_mode_type(flags)).c_str());
|
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 ((flags == EMS_DEVICE_FLAG_RC35) || (flags == EMS_DEVICE_FLAG_RC30_1)) {
|
||||||
if (hc->summer_mode) {
|
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) {
|
} 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, 2, 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, 2, 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("Vacation temperature"), F_(degrees), Helpers::render_value(buffer, hc->holidaytemp, 2));
|
||||||
|
|
||||||
if (hc->offsettemp < 100) {
|
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
|
// show flow temp if we have it
|
||||||
if (hc->circuitcalctemp != EMS_VALUE_UINT_NOTSET) {
|
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
|
// settings parameters
|
||||||
if (ibaMainDisplay != EMS_VALUE_UINT_NOTSET) {
|
if (ibaMainDisplay != EMS_VALUE_UINT_NOTSET) {
|
||||||
if (ibaMainDisplay == 0) {
|
if (ibaMainDisplay == 0) {
|
||||||
shell.printfln(F(" Display: internal temperature"));
|
shell.printfln(F(" Display: internal temperature"));
|
||||||
} else if (ibaMainDisplay == 1) {
|
} else if (ibaMainDisplay == 1) {
|
||||||
shell.printfln(F(" Display: internal setpoint"));
|
shell.printfln(F(" Display: internal setpoint"));
|
||||||
} else if (ibaMainDisplay == 2) {
|
} else if (ibaMainDisplay == 2) {
|
||||||
shell.printfln(F(" Display: external temperature"));
|
shell.printfln(F(" Display: external temperature"));
|
||||||
} else if (ibaMainDisplay == 3) {
|
} else if (ibaMainDisplay == 3) {
|
||||||
shell.printfln(F(" Display: burner temperature"));
|
shell.printfln(F(" Display: burner temperature"));
|
||||||
} else if (ibaMainDisplay == 4) {
|
} else if (ibaMainDisplay == 4) {
|
||||||
shell.printfln(F(" Display: WW temperature"));
|
shell.printfln(F(" Display: WW temperature"));
|
||||||
} else if (ibaMainDisplay == 5) {
|
} else if (ibaMainDisplay == 5) {
|
||||||
shell.printfln(F(" Display: functioning mode"));
|
shell.printfln(F(" Display: functioning mode"));
|
||||||
} else if (ibaMainDisplay == 6) {
|
} else if (ibaMainDisplay == 6) {
|
||||||
shell.printfln(F(" Display: time"));
|
shell.printfln(F(" Display: time"));
|
||||||
} else if (ibaMainDisplay == 7) {
|
} else if (ibaMainDisplay == 7) {
|
||||||
shell.printfln(F(" Display: date"));
|
shell.printfln(F(" Display: date"));
|
||||||
} else if (ibaMainDisplay == 9) {
|
} else if (ibaMainDisplay == 9) {
|
||||||
shell.printfln(F(" Display: smoke temperature"));
|
shell.printfln(F(" Display: smoke temperature"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ibaLanguage != EMS_VALUE_UINT_NOTSET) {
|
if (ibaLanguage != EMS_VALUE_UINT_NOTSET) {
|
||||||
if (ibaLanguage == 0) {
|
if (ibaLanguage == 0) {
|
||||||
shell.printfln(F(" Language: German"));
|
shell.printfln(F(" Language: German"));
|
||||||
} else if (ibaLanguage == 1) {
|
} else if (ibaLanguage == 1) {
|
||||||
shell.printfln(F(" Language: Dutch"));
|
shell.printfln(F(" Language: Dutch"));
|
||||||
} else if (ibaLanguage == 2) {
|
} else if (ibaLanguage == 2) {
|
||||||
shell.printfln(F(" Language: French"));
|
shell.printfln(F(" Language: French"));
|
||||||
} else if (ibaLanguage == 3) {
|
} else if (ibaLanguage == 3) {
|
||||||
shell.printfln(F(" Language: Italian"));
|
shell.printfln(F(" Language: Italian"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ibaCalIntTemperature != EMS_VALUE_INT_NOTSET) {
|
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) {
|
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 != EMS_VALUE_UINT_NOTSET) {
|
||||||
if (ibaBuildingType == 0) {
|
if (ibaBuildingType == 0) {
|
||||||
shell.printfln(F(" Building: light"));
|
shell.printfln(F(" Building: light"));
|
||||||
} else if (ibaBuildingType == 1) {
|
} else if (ibaBuildingType == 1) {
|
||||||
shell.printfln(F(" Building: medium"));
|
shell.printfln(F(" Building: medium"));
|
||||||
} else if (ibaBuildingType == 2) {
|
} 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
|
// add console commands
|
||||||
void Thermostat::console_commands() {
|
void Thermostat::console_commands(Shell & shell, unsigned int context) {
|
||||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||||
CommandFlags::ADMIN,
|
CommandFlags::ADMIN,
|
||||||
flash_string_vector{F_(set), F_(master)},
|
flash_string_vector{F_(set), F_(master)},
|
||||||
@@ -1318,6 +1337,9 @@ void Thermostat::console_commands() {
|
|||||||
: Helpers::hextoa(buffer, settings.master_thermostat()));
|
: Helpers::hextoa(buffer, settings.master_thermostat()));
|
||||||
shell.println();
|
shell.println();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// enter the context
|
||||||
|
Console::enter_custom_context(shell, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
@@ -76,7 +76,7 @@ class Thermostat : public EMSdevice {
|
|||||||
return set_typeid_;
|
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:
|
private:
|
||||||
uint8_t hc_num_;
|
uint8_t hc_num_;
|
||||||
@@ -103,7 +103,7 @@ class Thermostat : public EMSdevice {
|
|||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|
||||||
void console_commands();
|
void console_commands(Shell & shell, unsigned int context);
|
||||||
void init_mqtt();
|
void init_mqtt();
|
||||||
|
|
||||||
std::string datetime_; // date and time stamp
|
std::string datetime_; // date and time stamp
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "2.0.0a4"
|
#define EMSESP_APP_VERSION "2.0.0a6"
|
||||||
|
|||||||
Reference in New Issue
Block a user