mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
refactor out console context menus - #510
This commit is contained in:
@@ -52,7 +52,7 @@ void EMSESPAPIService::emsespAPIService(AsyncWebServerRequest * request) {
|
||||
String cmd = request->getParam(F_(cmd))->value();
|
||||
|
||||
// look up command in our list
|
||||
if (!Command::find(device_type, cmd.c_str())) {
|
||||
if (!Command::find_command(device_type, cmd.c_str())) {
|
||||
request->send(400, "text/plain", F("Invalid cmd"));
|
||||
return;
|
||||
}
|
||||
|
||||
165
src/command.cpp
165
src/command.cpp
@@ -77,7 +77,7 @@ void Command::add_with_json(const uint8_t device_type, const __FlashStringHelper
|
||||
}
|
||||
|
||||
// see if a command exists for that device type
|
||||
bool Command::find(const uint8_t device_type, const char * cmd) {
|
||||
bool Command::find_command(const uint8_t device_type, const char * cmd) {
|
||||
for (const auto & cf : cmdfunctions_) {
|
||||
if (strcmp(cmd, uuid::read_flash_string(cf.cmd_).c_str()) == 0) {
|
||||
return true;
|
||||
@@ -88,6 +88,10 @@ bool Command::find(const uint8_t device_type, const char * cmd) {
|
||||
|
||||
// output list of all commands to console for a specific DeviceType
|
||||
void Command::show(uuid::console::Shell & shell, uint8_t device_type) {
|
||||
if (commands().empty()) {
|
||||
shell.println(F("No commands"));
|
||||
}
|
||||
|
||||
for (const auto & cf : Command::commands()) {
|
||||
if (cf.device_type_ == device_type) {
|
||||
shell.printf("%s ", uuid::read_flash_string(cf.cmd_).c_str());
|
||||
@@ -96,128 +100,71 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type) {
|
||||
shell.println();
|
||||
}
|
||||
|
||||
// determines the device_type from the shell context we're in
|
||||
uint8_t Command::context_2_device_type(unsigned int context) {
|
||||
// if (context == ShellContext::MAIN) {
|
||||
// return EMSdevice::DeviceType::SERVICEKEY;
|
||||
// }
|
||||
if (context == ShellContext::BOILER) {
|
||||
return EMSdevice::DeviceType::BOILER;
|
||||
}
|
||||
if (context == ShellContext::MIXING) {
|
||||
return EMSdevice::DeviceType::MIXING;
|
||||
}
|
||||
if (context == ShellContext::SOLAR) {
|
||||
return EMSdevice::DeviceType::SOLAR;
|
||||
}
|
||||
if (context == ShellContext::SYSTEM) {
|
||||
return EMSdevice::DeviceType::SERVICEKEY;
|
||||
}
|
||||
if (context == ShellContext::THERMOSTAT) {
|
||||
return EMSdevice::DeviceType::THERMOSTAT;
|
||||
}
|
||||
if (context == ShellContext::SENSOR) {
|
||||
return EMSdevice::DeviceType::SENSOR;
|
||||
// see if a device_type is active and has associated commands
|
||||
bool Command::device_has_commands(const uint8_t device_type) {
|
||||
if (device_type == EMSdevice::DeviceType::UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return EMSdevice::DeviceType::UNKNOWN; // unknown type
|
||||
if (device_type == EMSdevice::DeviceType::SYSTEM) {
|
||||
return true; // we always have System
|
||||
}
|
||||
|
||||
if (device_type == EMSdevice::DeviceType::SENSOR) {
|
||||
return true; // we always have Sensor, but should check if there are actual sensors attached!
|
||||
}
|
||||
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if ((emsdevice) && (emsdevice->device_type() == device_type)) {
|
||||
// device found, now see if it has any commands
|
||||
for (const auto & cf : Command::commands()) {
|
||||
if (cf.device_type_ == device_type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// show command per current context
|
||||
void Command::show(uuid::console::Shell & shell) {
|
||||
show(shell, context_2_device_type(shell.context()));
|
||||
void Command::show_devices(uuid::console::Shell & shell) {
|
||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM).c_str());
|
||||
|
||||
if (EMSESP::have_sensors()) {
|
||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SENSOR).c_str());
|
||||
}
|
||||
|
||||
for (const auto & device_class : EMSFactory::device_handlers()) {
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if ((emsdevice) && (emsdevice->device_type() == device_class.first)) {
|
||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(device_class.first).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
shell.println();
|
||||
}
|
||||
|
||||
// output list of all commands to console
|
||||
void Command::show_all(uuid::console::Shell & shell) {
|
||||
shell.println(F("Available commands per device: "));
|
||||
|
||||
// show system first
|
||||
shell.printf("%s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SERVICEKEY).c_str());
|
||||
show(shell, EMSdevice::DeviceType::SERVICEKEY);
|
||||
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM).c_str());
|
||||
show(shell, EMSdevice::DeviceType::SYSTEM);
|
||||
|
||||
// show sensor
|
||||
if (EMSESP::have_sensors()) {
|
||||
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SENSOR).c_str());
|
||||
show(shell, EMSdevice::DeviceType::SENSOR);
|
||||
}
|
||||
|
||||
// do this in the order of factory classes to keep a consistent order when displaying
|
||||
for (const auto & device_class : EMSFactory::device_handlers()) {
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if ((emsdevice) && (emsdevice->device_type() == device_class.first)) {
|
||||
shell.printf("%s: ", EMSdevice::device_type_2_device_name(device_class.first).c_str());
|
||||
show(shell, device_class.first);
|
||||
}
|
||||
if (Command::device_has_commands(device_class.first)) {
|
||||
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(device_class.first).c_str());
|
||||
show(shell, device_class.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the console 'call' command to the given context
|
||||
void Command::add_context_commands(unsigned int context) {
|
||||
// if we're adding commands for a thermostat or mixing, then include an additional optional paramter called heating circuit
|
||||
flash_string_vector params;
|
||||
if ((context == ShellContext::THERMOSTAT) || (context == ShellContext::MIXING)) {
|
||||
params = flash_string_vector{F_(cmd_optional), F_(data_optional), F_(hc_optional)};
|
||||
} else if ((context == ShellContext::MAIN) || (context == ShellContext::SYSTEM)) {
|
||||
params = flash_string_vector{F_(cmd_optional), F_(data_optional), F_(n_optional)};
|
||||
} else {
|
||||
params = flash_string_vector{F_(cmd_optional), F_(data_optional)};
|
||||
}
|
||||
|
||||
EMSESPShell::commands->add_command(
|
||||
context,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(call)},
|
||||
params,
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
if (arguments.empty()) {
|
||||
// list options
|
||||
shell.print("Available commands: ");
|
||||
show(shell);
|
||||
shell.println();
|
||||
return;
|
||||
}
|
||||
|
||||
// determine the device_type from the shell context
|
||||
uint8_t device_type = context_2_device_type(shell.context());
|
||||
|
||||
// validate the command
|
||||
const char * cmd = arguments[0].c_str();
|
||||
if (!find(device_type, cmd)) {
|
||||
shell.print(F("Unknown command. Available commands are: "));
|
||||
show(shell);
|
||||
shell.println();
|
||||
return;
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc(EMSESP_MAX_JSON_SIZE_LARGE);
|
||||
JsonObject output = doc.to<JsonObject>();
|
||||
|
||||
bool ok = false;
|
||||
if (arguments.size() == 1) {
|
||||
// no value specified, just the cmd
|
||||
ok = Command::call(device_type, cmd, nullptr, -1, output);
|
||||
} else if (arguments.size() == 2) {
|
||||
// has a value but no id
|
||||
ok = Command::call(device_type, cmd, arguments.back().c_str(), -1, output);
|
||||
} else {
|
||||
// use value, which could be an id or hc
|
||||
ok = Command::call(device_type, cmd, arguments[1].c_str(), atoi(arguments[2].c_str()), output);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
shell.print(F("output: "));
|
||||
serializeJson(doc, shell);
|
||||
shell.println();
|
||||
shell.println();
|
||||
}
|
||||
},
|
||||
[&](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) -> std::vector<std::string> {
|
||||
if (arguments.size() > 0) {
|
||||
return {};
|
||||
}
|
||||
std::vector<std::string> commands;
|
||||
uint8_t device_type = context_2_device_type(shell.context());
|
||||
for (const auto & cf : Command::commands()) {
|
||||
if (cf.device_type_ == device_type) {
|
||||
commands.emplace_back(uuid::read_flash_string(cf.cmd_));
|
||||
}
|
||||
}
|
||||
return commands;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -61,17 +61,15 @@ class Command {
|
||||
static void add(const uint8_t device_type, const uint8_t device_id, const __FlashStringHelper * cmd, cmdfunction_p cb);
|
||||
static void add_with_json(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_json_p cb);
|
||||
static void show_all(uuid::console::Shell & shell);
|
||||
static void show(uuid::console::Shell & shell);
|
||||
static void add_context_commands(unsigned int context);
|
||||
static bool find(const uint8_t device_type, const char * cmd);
|
||||
static bool find_command(const uint8_t device_type, const char * cmd);
|
||||
static void show(uuid::console::Shell & shell, uint8_t device_type);
|
||||
static void show_devices(uuid::console::Shell & shell);
|
||||
static bool device_has_commands(const uint8_t device_type);
|
||||
|
||||
static std::vector<CmdFunction> cmdfunctions_; // list of commands
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
static void show(uuid::console::Shell & shell, uint8_t device_type);
|
||||
static uint8_t context_2_device_type(unsigned int context);
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
253
src/console.cpp
253
src/console.cpp
@@ -118,6 +118,15 @@ void EMSESPShell::add_console_commands() {
|
||||
EMSESP::fetch_device_values();
|
||||
});
|
||||
|
||||
commands->add_command(ShellContext::MAIN,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(publish)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
shell.printfln(F("Publishing all data to MQTT"));
|
||||
EMSESP::publish_all();
|
||||
});
|
||||
|
||||
|
||||
commands->add_command(ShellContext::MAIN,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(show)},
|
||||
@@ -247,6 +256,10 @@ void EMSESPShell::add_console_commands() {
|
||||
EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) {
|
||||
shell.printfln(F_(tx_mode_fmt), settings.tx_mode);
|
||||
shell.printfln(F_(bus_id_fmt), settings.ems_bus_id);
|
||||
char buffer[4];
|
||||
shell.printfln(F_(master_thermostat_fmt),
|
||||
settings.master_thermostat == 0 ? uuid::read_flash_string(F_(auto)).c_str()
|
||||
: Helpers::hextoa(buffer, settings.master_thermostat));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -261,6 +274,163 @@ void EMSESPShell::add_console_commands() {
|
||||
EMSESP::send_read_request(type_id, device_id);
|
||||
});
|
||||
|
||||
commands->add_command(ShellContext::MAIN,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(set), F_(master), F_(thermostat)},
|
||||
flash_string_vector{F_(deviceid_mandatory)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
uint8_t value = Helpers::hextoint(arguments.front().c_str());
|
||||
EMSESP::emsespSettingsService.update(
|
||||
[&](EMSESPSettings & settings) {
|
||||
settings.master_thermostat = value;
|
||||
EMSESP::actual_master_thermostat(value); // set the internal value too
|
||||
char buffer[5];
|
||||
shell.printfln(F_(master_thermostat_fmt),
|
||||
!value ? uuid::read_flash_string(F_(auto)).c_str() : Helpers::hextoa(buffer, value));
|
||||
return StateUpdateResult::CHANGED;
|
||||
},
|
||||
"local");
|
||||
});
|
||||
|
||||
commands->add_command(ShellContext::MAIN,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(send), F_(telegram)},
|
||||
flash_string_vector{F_(data_mandatory)},
|
||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
EMSESP::send_raw_telegram(arguments.front().c_str());
|
||||
});
|
||||
|
||||
commands->add_command(ShellContext::MAIN,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(watch)},
|
||||
flash_string_vector{F_(watch_format_optional), F_(watchid_optional)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
uint16_t watch_id = WATCH_ID_NONE;
|
||||
|
||||
if (!arguments.empty()) {
|
||||
// get raw/pretty
|
||||
if (arguments[0] == read_flash_string(F_(raw))) {
|
||||
emsesp::EMSESP::watch(EMSESP::WATCH_RAW); // raw
|
||||
} else if (arguments[0] == read_flash_string(F_(on))) {
|
||||
emsesp::EMSESP::watch(EMSESP::WATCH_ON); // on
|
||||
} else if (arguments[0] == read_flash_string(F_(off))) {
|
||||
emsesp::EMSESP::watch(EMSESP::WATCH_OFF); // off
|
||||
} else if (emsesp::EMSESP::watch() == EMSESP::WATCH_OFF) {
|
||||
shell.printfln(F_(invalid_watch));
|
||||
return;
|
||||
} else {
|
||||
watch_id = Helpers::hextoint(arguments[0].c_str());
|
||||
}
|
||||
|
||||
if (arguments.size() == 2) {
|
||||
// get the watch_id if its set
|
||||
watch_id = Helpers::hextoint(arguments[1].c_str());
|
||||
}
|
||||
|
||||
emsesp::EMSESP::watch_id(watch_id);
|
||||
}
|
||||
|
||||
uint8_t watch = emsesp::EMSESP::watch();
|
||||
if (watch == EMSESP::WATCH_OFF) {
|
||||
shell.printfln(F("Watching telegrams is off"));
|
||||
return;
|
||||
}
|
||||
|
||||
// if logging is off, the watch won't show anything, show force it back to NOTICE
|
||||
if (!shell.logger().enabled(Level::NOTICE)) {
|
||||
shell.log_level(Level::NOTICE);
|
||||
}
|
||||
|
||||
if (watch == EMSESP::WATCH_ON) {
|
||||
shell.printfln(F("Watching incoming telegrams, displayed in decoded format"));
|
||||
} else {
|
||||
shell.printfln(F("Watching incoming telegrams, displayed as raw bytes")); // WATCH_RAW
|
||||
}
|
||||
|
||||
watch_id = emsesp::EMSESP::watch_id();
|
||||
if (watch_id > 0x80) {
|
||||
shell.printfln(F("Filtering only telegrams that match a telegram type of 0x%02X"), watch_id);
|
||||
} else if (watch_id != WATCH_ID_NONE) {
|
||||
shell.printfln(F("Filtering only telegrams that match a device ID or telegram type of 0x%02X"), watch_id);
|
||||
}
|
||||
});
|
||||
|
||||
commands->add_command(
|
||||
ShellContext::MAIN,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(call)},
|
||||
flash_string_vector{F_(device_type_optional), F_(cmd_optional), F_(data_optional), F_(n_optional)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
if (arguments.empty()) {
|
||||
Command::show_all(shell); // list options
|
||||
return;
|
||||
}
|
||||
|
||||
// validate the device_type
|
||||
uint8_t device_type = EMSdevice::device_name_2_device_type(arguments[0].c_str());
|
||||
if (!Command::device_has_commands(device_type)) {
|
||||
shell.print(F("Invalid device. Available devices are: "));
|
||||
Command::show_devices(shell);
|
||||
return;
|
||||
}
|
||||
|
||||
// validate the command
|
||||
const char * cmd = arguments[1].c_str();
|
||||
if (!Command::find_command(device_type, cmd)) {
|
||||
shell.print(F("Unknown command. Available commands are: "));
|
||||
Command::show(shell, device_type);
|
||||
return;
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc(EMSESP_MAX_JSON_SIZE_LARGE);
|
||||
JsonObject output = doc.to<JsonObject>();
|
||||
|
||||
bool ok = false;
|
||||
if (arguments.size() == 2) {
|
||||
// no value specified, just the cmd
|
||||
ok = Command::call(device_type, cmd, nullptr, -1, output);
|
||||
} else if (arguments.size() == 3) {
|
||||
// has a value but no id
|
||||
ok = Command::call(device_type, cmd, arguments.back().c_str(), -1, output);
|
||||
} else {
|
||||
// use value, which could be an id or hc
|
||||
ok = Command::call(device_type, cmd, arguments[2].c_str(), atoi(arguments[3].c_str()), output);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
shell.print(F("output: "));
|
||||
serializeJson(doc, shell);
|
||||
shell.println();
|
||||
shell.println();
|
||||
}
|
||||
},
|
||||
[&](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) -> std::vector<std::string> {
|
||||
if (arguments.size() == 0) {
|
||||
std::vector<std::string> devices_list;
|
||||
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM));
|
||||
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SENSOR));
|
||||
for (const auto & device_class : EMSFactory::device_handlers()) {
|
||||
if (Command::device_has_commands(device_class.first)) {
|
||||
devices_list.emplace_back(EMSdevice::device_type_2_device_name(device_class.first));
|
||||
}
|
||||
}
|
||||
return devices_list;
|
||||
} else if (arguments.size() == 1) {
|
||||
std::vector<std::string> command_list;
|
||||
uint8_t device_type = EMSdevice::device_name_2_device_type(arguments[0].c_str());
|
||||
if (!Command::device_has_commands(device_type)) {
|
||||
for (const auto & cf : Command::commands()) {
|
||||
if (cf.device_type_ == device_type) {
|
||||
command_list.emplace_back(uuid::read_flash_string(cf.cmd_));
|
||||
}
|
||||
}
|
||||
return command_list;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
});
|
||||
|
||||
/*
|
||||
* add all the submenu contexts...
|
||||
*/
|
||||
@@ -273,10 +443,6 @@ void EMSESPShell::add_console_commands() {
|
||||
System::console_commands(shell, ShellContext::SYSTEM);
|
||||
});
|
||||
|
||||
// add all the context menus for the connected devices
|
||||
// this assumes they devices have been detected and pre-registered
|
||||
EMSESP::add_context_menus();
|
||||
|
||||
Console::load_standard_commands(ShellContext::MAIN);
|
||||
|
||||
console_commands_loaded_ = true;
|
||||
@@ -400,76 +566,6 @@ void Console::load_standard_commands(unsigned int context) {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(context,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(send), F_(telegram)},
|
||||
flash_string_vector{F_(data_mandatory)},
|
||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
EMSESP::send_raw_telegram(arguments.front().c_str());
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(context,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(watch)},
|
||||
flash_string_vector{F_(watch_format_optional), F_(watchid_optional)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
uint16_t watch_id = WATCH_ID_NONE;
|
||||
|
||||
if (!arguments.empty()) {
|
||||
// get raw/pretty
|
||||
if (arguments[0] == read_flash_string(F_(raw))) {
|
||||
emsesp::EMSESP::watch(EMSESP::WATCH_RAW); // raw
|
||||
} else if (arguments[0] == read_flash_string(F_(on))) {
|
||||
emsesp::EMSESP::watch(EMSESP::WATCH_ON); // on
|
||||
} else if (arguments[0] == read_flash_string(F_(off))) {
|
||||
emsesp::EMSESP::watch(EMSESP::WATCH_OFF); // off
|
||||
} else if (emsesp::EMSESP::watch() == EMSESP::WATCH_OFF) {
|
||||
shell.printfln(F_(invalid_watch));
|
||||
return;
|
||||
} else {
|
||||
watch_id = Helpers::hextoint(arguments[0].c_str());
|
||||
}
|
||||
|
||||
if (arguments.size() == 2) {
|
||||
// get the watch_id if its set
|
||||
watch_id = Helpers::hextoint(arguments[1].c_str());
|
||||
}
|
||||
|
||||
emsesp::EMSESP::watch_id(watch_id);
|
||||
}
|
||||
|
||||
uint8_t watch = emsesp::EMSESP::watch();
|
||||
if (watch == EMSESP::WATCH_OFF) {
|
||||
shell.printfln(F("Watching telegrams is off"));
|
||||
return;
|
||||
}
|
||||
|
||||
// if logging is off, the watch won't show anything, show force it back to NOTICE
|
||||
if (!shell.logger().enabled(Level::NOTICE)) {
|
||||
shell.log_level(Level::NOTICE);
|
||||
}
|
||||
|
||||
if (watch == EMSESP::WATCH_ON) {
|
||||
shell.printfln(F("Watching incoming telegrams, displayed in decoded format"));
|
||||
} else {
|
||||
shell.printfln(F("Watching incoming telegrams, displayed as raw bytes")); // WATCH_RAW
|
||||
}
|
||||
|
||||
watch_id = emsesp::EMSESP::watch_id();
|
||||
if (watch_id > 0x80) {
|
||||
shell.printfln(F("Filtering only telegrams that match a telegram type of 0x%02X"), watch_id);
|
||||
} else if (watch_id != WATCH_ID_NONE) {
|
||||
shell.printfln(F("Filtering only telegrams that match a device ID or telegram type of 0x%02X"), watch_id);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// load the commands (console & mqtt topics) for this specific context
|
||||
// unless it's main (the root)
|
||||
if (context != ShellContext::MAIN) {
|
||||
Command::add_context_commands(context);
|
||||
}
|
||||
}
|
||||
|
||||
// prompt, change per context
|
||||
@@ -478,18 +574,9 @@ std::string EMSESPShell::context_text() {
|
||||
case ShellContext::MAIN:
|
||||
return std::string{'/'};
|
||||
|
||||
case ShellContext::BOILER:
|
||||
return std::string{"/boiler"};
|
||||
|
||||
case ShellContext::SYSTEM:
|
||||
return std::string{"/system"};
|
||||
|
||||
case ShellContext::THERMOSTAT:
|
||||
return std::string{"/thermostat"};
|
||||
|
||||
case ShellContext::SENSOR:
|
||||
return std::string{"/sensor"};
|
||||
|
||||
default:
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
@@ -76,11 +76,6 @@ enum ShellContext : uint8_t {
|
||||
|
||||
MAIN = 0,
|
||||
SYSTEM,
|
||||
BOILER,
|
||||
THERMOSTAT,
|
||||
SOLAR,
|
||||
MIXING,
|
||||
SENSOR
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -84,16 +84,6 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
||||
});
|
||||
}
|
||||
|
||||
// add submenu context
|
||||
void Boiler::add_context_menu() {
|
||||
EMSESPShell::commands->add_command(ShellContext::MAIN,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(boiler)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
Boiler::console_commands(shell, ShellContext::BOILER);
|
||||
});
|
||||
}
|
||||
|
||||
// create the config topic for Home Assistant MQTT Discovery
|
||||
// homeassistant/sensor/ems-esp/boiler
|
||||
// state is /state
|
||||
@@ -1070,25 +1060,4 @@ bool Boiler::set_warmwater_circulation(const char * value, const int8_t id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Boiler::console_commands(Shell & shell, unsigned int context) {
|
||||
EMSESPShell::commands->add_command(ShellContext::BOILER,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(read)},
|
||||
flash_string_vector{F_(typeid_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
uint16_t type_id = Helpers::hextoint(arguments.front().c_str());
|
||||
EMSESP::set_read_id(type_id);
|
||||
EMSESP::send_read_request(type_id, device_id());
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::BOILER,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(show)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { show_values(shell); });
|
||||
|
||||
// enter the context
|
||||
Console::enter_custom_context(shell, context);
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -42,12 +42,10 @@ class Boiler : public EMSdevice {
|
||||
virtual void publish_values();
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual void add_context_menu();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void console_commands(Shell & shell, unsigned int context);
|
||||
void register_mqtt_ha_config();
|
||||
void check_active();
|
||||
bool export_values(JsonObject & doc);
|
||||
|
||||
@@ -31,9 +31,6 @@ Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
|
||||
void Connect::device_info_web(JsonArray & root) {
|
||||
}
|
||||
|
||||
void Connect::add_context_menu() {
|
||||
}
|
||||
|
||||
// display all values into the shell console
|
||||
void Connect::show_values(uuid::console::Shell & shell) {
|
||||
// EMSdevice::show_values(shell); // always call this to show header
|
||||
@@ -48,8 +45,4 @@ bool Connect::updated_values() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Connect::console_commands() {
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -39,12 +39,9 @@ class Connect : public EMSdevice {
|
||||
virtual void publish_values();
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual void add_context_menu();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void console_commands();
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -28,9 +28,6 @@ Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
}
|
||||
|
||||
void Controller::add_context_menu() {
|
||||
}
|
||||
|
||||
void Controller::device_info_web(JsonArray & root) {
|
||||
}
|
||||
|
||||
@@ -48,8 +45,4 @@ bool Controller::updated_values() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Controller::console_commands() {
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -39,12 +39,10 @@ class Controller : public EMSdevice {
|
||||
virtual void publish_values();
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual void add_context_menu();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void console_commands();
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -28,9 +28,6 @@ Gateway::Gateway(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
}
|
||||
|
||||
void Gateway::add_context_menu() {
|
||||
}
|
||||
|
||||
void Gateway::device_info_web(JsonArray & root) {
|
||||
}
|
||||
|
||||
@@ -48,8 +45,4 @@ bool Gateway::updated_values() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Gateway::console_commands() {
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -39,12 +39,10 @@ class Gateway : public EMSdevice {
|
||||
virtual void publish_values();
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual void add_context_menu();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void console_commands();
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -33,10 +33,6 @@ Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, c
|
||||
register_telegram_type(0x042B, F("HP2"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor2(t); });
|
||||
}
|
||||
|
||||
// context submenu
|
||||
void Heatpump::add_context_menu() {
|
||||
}
|
||||
|
||||
void Heatpump::device_info_web(JsonArray & root) {
|
||||
}
|
||||
|
||||
@@ -54,10 +50,6 @@ bool Heatpump::updated_values() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Heatpump::console_commands() {
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
|
||||
@@ -39,13 +39,10 @@ class Heatpump : public EMSdevice {
|
||||
virtual void publish_values();
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual void add_context_menu();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void console_commands();
|
||||
|
||||
void process_HPMonitor1(std::shared_ptr<const Telegram> telegram);
|
||||
void process_HPMonitor2(std::shared_ptr<const Telegram> telegram);
|
||||
};
|
||||
|
||||
@@ -60,19 +60,6 @@ Mixing::Mixing(uint8_t device_type, uint8_t device_id, uint8_t product_id, const
|
||||
});
|
||||
}
|
||||
|
||||
// add context submenu
|
||||
void Mixing::add_context_menu() {
|
||||
// TODO support for multiple mixing units from a single menu, similar to set master with thermostat
|
||||
/*
|
||||
EMSESPShell::commands->add_command(ShellContext::MAIN,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(mixing)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
Mixing::console_commands(shell, ShellContext::MIXING);
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
// output json to web UI
|
||||
void Mixing::device_info_web(JsonArray & root) {
|
||||
if (type_ == Type::NONE) {
|
||||
@@ -102,27 +89,6 @@ bool Mixing::updated_values() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Mixing::console_commands(Shell & shell, unsigned int context) {
|
||||
EMSESPShell::commands->add_command(ShellContext::MIXING,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(read)},
|
||||
flash_string_vector{F_(typeid_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
uint16_t type_id = Helpers::hextoint(arguments.front().c_str());
|
||||
EMSESP::set_read_id(type_id);
|
||||
EMSESP::send_read_request(type_id, device_id());
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::MIXING,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(show)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { show_values(shell); });
|
||||
|
||||
// enter the context
|
||||
Console::enter_custom_context(shell, context);
|
||||
}
|
||||
|
||||
// display all values into the shell console
|
||||
void Mixing::show_values(uuid::console::Shell & shell) {
|
||||
EMSdevice::show_values(shell); // always call this to show header
|
||||
|
||||
@@ -40,12 +40,10 @@ class Mixing : public EMSdevice {
|
||||
virtual void publish_values();
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual void add_context_menu();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void console_commands(Shell & shell, unsigned int context);
|
||||
bool export_values(JsonObject & doc);
|
||||
bool command_info(const char * value, const int8_t id, JsonObject & output);
|
||||
|
||||
|
||||
@@ -58,19 +58,6 @@ bool Solar::command_info(const char * value, const int8_t id, JsonObject & outpu
|
||||
return (export_values(output));
|
||||
}
|
||||
|
||||
// context submenu
|
||||
void Solar::add_context_menu() {
|
||||
// TODO support for multiple solar units from a single menu, similar to set master with thermostat
|
||||
/*
|
||||
EMSESPShell::commands->add_command(ShellContext::MAIN,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(solar)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
Solar::console_commands(shell, ShellContext::SOLAR);
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
// print to web
|
||||
void Solar::device_info_web(JsonArray & root) {
|
||||
render_value_json(root, "", F("Collector temperature (TS1)"), collectorTemp_, F_(degrees), 10);
|
||||
@@ -206,27 +193,6 @@ bool Solar::updated_values() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Solar::console_commands(Shell & shell, unsigned int context) {
|
||||
EMSESPShell::commands->add_command(ShellContext::SOLAR,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(read)},
|
||||
flash_string_vector{F_(typeid_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
uint16_t type_id = Helpers::hextoint(arguments.front().c_str());
|
||||
EMSESP::set_read_id(type_id);
|
||||
EMSESP::send_read_request(type_id, device_id());
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::SOLAR,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(show)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { show_values(shell); });
|
||||
|
||||
// enter the context
|
||||
Console::enter_custom_context(shell, context);
|
||||
}
|
||||
|
||||
// SM10Monitor - type 0x97
|
||||
void Solar::process_SM10Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
changed_ |= telegram->read_value(collectorTemp_, 2); // collector temp from SM10, is *10
|
||||
|
||||
@@ -40,12 +40,10 @@ class Solar : public EMSdevice {
|
||||
virtual void publish_values();
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual void add_context_menu();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void console_commands(Shell & shell, unsigned int context);
|
||||
bool export_values(JsonObject & doc);
|
||||
bool command_info(const char * value, const int8_t id, JsonObject & output);
|
||||
|
||||
|
||||
@@ -28,9 +28,6 @@ Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const
|
||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||
}
|
||||
|
||||
void Switch::add_context_menu() {
|
||||
}
|
||||
|
||||
void Switch::device_info_web(JsonArray & root) {
|
||||
}
|
||||
|
||||
@@ -48,8 +45,4 @@ bool Switch::updated_values() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Switch::console_commands() {
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -39,12 +39,10 @@ class Switch : public EMSdevice {
|
||||
virtual void publish_values();
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual void add_context_menu();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void console_commands();
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -219,21 +219,6 @@ void Thermostat::device_info_web(JsonArray & root) {
|
||||
}
|
||||
}
|
||||
|
||||
// context menu "thermostat"
|
||||
void Thermostat::add_context_menu() {
|
||||
// only add it once, to prevent conflicts when there are multiple thermostats
|
||||
if (this->device_id() != EMSESP::actual_master_thermostat()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::MAIN,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(thermostat)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
Thermostat::console_commands(shell, ShellContext::THERMOSTAT);
|
||||
});
|
||||
}
|
||||
|
||||
// this function is called post the telegram handler function has been executed
|
||||
// we check if any of the thermostat values have changed and then republish if necessary
|
||||
bool Thermostat::updated_values() {
|
||||
@@ -1167,58 +1152,6 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
}
|
||||
|
||||
// add console commands
|
||||
void Thermostat::console_commands(Shell & shell, unsigned int context) {
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(set), F_(master)},
|
||||
flash_string_vector{F_(deviceid_mandatory)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
uint8_t value = Helpers::hextoint(arguments.front().c_str());
|
||||
EMSESP::emsespSettingsService.update(
|
||||
[&](EMSESPSettings & settings) {
|
||||
settings.master_thermostat = value;
|
||||
EMSESP::actual_master_thermostat(value); // set the internal value too
|
||||
char buffer[5];
|
||||
shell.printfln(F_(master_thermostat_fmt),
|
||||
!value ? uuid::read_flash_string(F_(auto)).c_str() : Helpers::hextoa(buffer, value));
|
||||
return StateUpdateResult::CHANGED;
|
||||
},
|
||||
"local");
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::ADMIN,
|
||||
flash_string_vector{F_(read)},
|
||||
flash_string_vector{F_(typeid_mandatory)},
|
||||
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
|
||||
uint16_t type_id = Helpers::hextoint(arguments.front().c_str());
|
||||
EMSESP::set_read_id(type_id);
|
||||
EMSESP::send_read_request(type_id, this->device_id());
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(show)},
|
||||
[&](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) { show_values(shell); });
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::THERMOSTAT,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(set)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) {
|
||||
char buffer[4];
|
||||
shell.printfln(F_(master_thermostat_fmt),
|
||||
settings.master_thermostat == 0 ? uuid::read_flash_string(F_(auto)).c_str()
|
||||
: Helpers::hextoa(buffer, settings.master_thermostat));
|
||||
shell.println();
|
||||
});
|
||||
});
|
||||
|
||||
// enter the context
|
||||
Console::enter_custom_context(shell, context);
|
||||
}
|
||||
|
||||
// 0xA5 - Set minimum external temperature
|
||||
bool Thermostat::set_minexttemp(const char * value, const int8_t id) {
|
||||
int mt = 0;
|
||||
|
||||
@@ -101,12 +101,10 @@ class Thermostat : public EMSdevice {
|
||||
virtual void publish_values();
|
||||
virtual void device_info_web(JsonArray & root);
|
||||
virtual bool updated_values();
|
||||
virtual void add_context_menu();
|
||||
|
||||
private:
|
||||
static uuid::log::Logger logger_;
|
||||
|
||||
void console_commands(Shell & shell, unsigned int context);
|
||||
void add_commands();
|
||||
bool export_values(uint8_t mqtt_format, JsonObject & doc);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ std::string EMSdevice::brand_to_string() const {
|
||||
// returns the name of the MQTT topic to use for a specific device
|
||||
std::string EMSdevice::device_type_2_device_name(const uint8_t device_type) {
|
||||
switch (device_type) {
|
||||
case DeviceType::SERVICEKEY:
|
||||
case DeviceType::SYSTEM:
|
||||
return read_flash_string(F("system"));
|
||||
break;
|
||||
|
||||
@@ -79,6 +79,18 @@ std::string EMSdevice::device_type_2_device_name(const uint8_t device_type) {
|
||||
return read_flash_string(F("mixing"));
|
||||
break;
|
||||
|
||||
case DeviceType::SENSOR:
|
||||
return read_flash_string(F("sensor"));
|
||||
break;
|
||||
|
||||
case DeviceType::CONTROLLER:
|
||||
return read_flash_string(F("controller"));
|
||||
break;
|
||||
|
||||
case DeviceType::SWITCH:
|
||||
return read_flash_string(F("switch"));
|
||||
break;
|
||||
|
||||
default:
|
||||
return std::string{};
|
||||
break;
|
||||
@@ -96,7 +108,7 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) {
|
||||
}
|
||||
|
||||
if (strcmp(topic, "system") == 0) {
|
||||
return DeviceType::SERVICEKEY;
|
||||
return DeviceType::SYSTEM;
|
||||
}
|
||||
|
||||
if (strcmp(topic, "heatpump") == 0) {
|
||||
|
||||
@@ -137,7 +137,6 @@ class EMSdevice {
|
||||
virtual void show_values(uuid::console::Shell & shell) = 0;
|
||||
virtual void publish_values() = 0;
|
||||
virtual bool updated_values() = 0;
|
||||
virtual void add_context_menu() = 0;
|
||||
virtual void device_info_web(JsonArray & root) = 0;
|
||||
|
||||
std::string telegram_type_name(std::shared_ptr<const Telegram> telegram);
|
||||
@@ -228,8 +227,8 @@ class EMSdevice {
|
||||
};
|
||||
|
||||
enum DeviceType : uint8_t {
|
||||
SERVICEKEY = 0, // this is us (EMS-ESP)
|
||||
SENSOR, // for internal dallas sensors
|
||||
SYSTEM = 0, // this is us (EMS-ESP)
|
||||
SENSOR, // for internal dallas sensors
|
||||
BOILER,
|
||||
THERMOSTAT,
|
||||
MIXING,
|
||||
@@ -279,7 +278,7 @@ class EMSdevice {
|
||||
|
||||
private:
|
||||
uint8_t unique_id_;
|
||||
uint8_t device_type_ = DeviceType::SERVICEKEY;
|
||||
uint8_t device_type_ = DeviceType::SYSTEM;
|
||||
uint8_t device_id_ = 0;
|
||||
uint8_t product_id_ = 0;
|
||||
std::string version_;
|
||||
|
||||
@@ -276,7 +276,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
|
||||
|
||||
// show Dallas temperature sensors
|
||||
void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
||||
if (sensor_devices().empty()) {
|
||||
if (!have_sensors()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -288,6 +288,17 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
||||
shell.println();
|
||||
}
|
||||
|
||||
// MQTT publish everything, immediately
|
||||
void EMSESP::publish_all() {
|
||||
publish_device_values(EMSdevice::DeviceType::BOILER);
|
||||
publish_device_values(EMSdevice::DeviceType::THERMOSTAT);
|
||||
publish_device_values(EMSdevice::DeviceType::SOLAR);
|
||||
publish_device_values(EMSdevice::DeviceType::MIXING);
|
||||
publish_other_values();
|
||||
publish_sensor_values(true);
|
||||
system_.send_heartbeat();
|
||||
}
|
||||
|
||||
void EMSESP::publish_device_values(uint8_t device_type) {
|
||||
if (Mqtt::connected()) {
|
||||
for (const auto & emsdevice : emsdevices) {
|
||||
@@ -432,7 +443,9 @@ std::string EMSESP::pretty_telegram(std::shared_ptr<const Telegram> telegram) {
|
||||
* e.g. 08 00 07 00 0B 80 00 00 00 00 00 00 00 00 00 00 00
|
||||
* Junkers has 15 bytes of data
|
||||
* each byte is a bitmask for which devices are active
|
||||
* byte 1 = range 0x08 - 0x0F, byte 2=0x10 - 0x17 etc...
|
||||
* byte 1 = 0x08 - 0x0F, byte 2 = 0x10 - 0x17, etc...
|
||||
* e.g. in example above 1st byte = x0B = b1011 so we have device ids 0x08, 0x09, 0x011
|
||||
* and 2nd byte = x80 = b1000 b0000 = device id 0x17
|
||||
*/
|
||||
void EMSESP::process_UBADevices(std::shared_ptr<const Telegram> telegram) {
|
||||
// exit it length is incorrect (must be 13 or 15 bytes long)
|
||||
@@ -589,15 +602,6 @@ bool EMSESP::device_exists(const uint8_t device_id) {
|
||||
return false; // not found
|
||||
}
|
||||
|
||||
// for each device add its context menu for the console
|
||||
void EMSESP::add_context_menus() {
|
||||
for (const auto & emsdevice : emsdevices) {
|
||||
if (emsdevice) {
|
||||
emsdevice->add_context_menu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for each associated EMS device go and get its system information
|
||||
void EMSESP::show_devices(uuid::console::Shell & shell) {
|
||||
if (emsdevices.empty()) {
|
||||
@@ -609,7 +613,7 @@ void EMSESP::show_devices(uuid::console::Shell & shell) {
|
||||
shell.printfln(F("These EMS devices are currently active:"));
|
||||
shell.println();
|
||||
|
||||
// for all device objects from emsdevice.h (UNKNOWN, SERVICEKEY, BOILER, THERMOSTAT, MIXING, SOLAR, HEATPUMP, GATEWAY, SWITCH, CONTROLLER, CONNECT)
|
||||
// for all device objects from emsdevice.h (UNKNOWN, SYSTEM, BOILER, THERMOSTAT, MIXING, SOLAR, HEATPUMP, GATEWAY, SWITCH, CONTROLLER, CONNECT)
|
||||
// so we keep a consistent order
|
||||
for (const auto & device_class : EMSFactory::device_handlers()) {
|
||||
// shell.printf(F("[factory ID: %d] "), device_class.first);
|
||||
|
||||
@@ -64,6 +64,7 @@ class EMSESP {
|
||||
static void publish_device_values(uint8_t device_type);
|
||||
static void publish_other_values();
|
||||
static void publish_sensor_values(const bool force = false);
|
||||
static void publish_all();
|
||||
|
||||
#ifdef EMSESP_STANDALONE
|
||||
static void run_test(uuid::console::Shell & shell, const std::string & command); // only for testing
|
||||
@@ -102,8 +103,6 @@ class EMSESP {
|
||||
static void show_devices(uuid::console::Shell & shell);
|
||||
static void show_ems(uuid::console::Shell & shell);
|
||||
|
||||
static void add_context_menus();
|
||||
|
||||
static void init_tx();
|
||||
|
||||
static void incoming_telegram(uint8_t * data, const uint8_t length);
|
||||
@@ -112,6 +111,10 @@ class EMSESP {
|
||||
return sensor_.devices();
|
||||
}
|
||||
|
||||
static bool have_sensors() {
|
||||
return (!(sensor_.devices().empty()));
|
||||
}
|
||||
|
||||
enum Watch : uint8_t { WATCH_OFF, WATCH_ON, WATCH_RAW };
|
||||
static void watch_id(uint16_t id);
|
||||
static uint16_t watch_id() {
|
||||
|
||||
@@ -62,6 +62,7 @@ MAKE_PSTR_WORD(heartbeat)
|
||||
MAKE_PSTR_WORD(users)
|
||||
MAKE_PSTR_WORD(master)
|
||||
MAKE_PSTR_WORD(pin)
|
||||
MAKE_PSTR_WORD(publish)
|
||||
|
||||
#if defined(EMSESP_DEBUG)
|
||||
MAKE_PSTR_WORD(test)
|
||||
@@ -117,6 +118,7 @@ MAKE_PSTR(n_optional, "[n]")
|
||||
MAKE_PSTR(data_optional, "[data]")
|
||||
MAKE_PSTR(typeid_mandatory, "<type ID>")
|
||||
MAKE_PSTR(deviceid_mandatory, "<device ID>")
|
||||
MAKE_PSTR(device_type_optional, "[device]")
|
||||
MAKE_PSTR(invalid_log_level, "Invalid log level")
|
||||
MAKE_PSTR(log_level_fmt, "Log level = %s")
|
||||
MAKE_PSTR(log_level_optional, "[level]")
|
||||
|
||||
17
src/mqtt.cpp
17
src/mqtt.cpp
@@ -100,9 +100,7 @@ void Mqtt::resubscribe() {
|
||||
}
|
||||
}
|
||||
|
||||
// Main MQTT loop
|
||||
// Checks for connection, establishes a connection if not
|
||||
// sends out top item on publish queue
|
||||
// Main MQTT loop - sends out top item on publish queue
|
||||
void Mqtt::loop() {
|
||||
// exit if MQTT is not enabled or if there is no WIFI
|
||||
if (!connected()) {
|
||||
@@ -116,26 +114,32 @@ void Mqtt::loop() {
|
||||
last_publish_boiler_ = currentMillis;
|
||||
EMSESP::publish_device_values(EMSdevice::DeviceType::BOILER);
|
||||
}
|
||||
|
||||
if (publish_time_thermostat_ && (currentMillis - last_publish_thermostat_ > publish_time_thermostat_)) {
|
||||
last_publish_thermostat_ = currentMillis;
|
||||
EMSESP::publish_device_values(EMSdevice::DeviceType::THERMOSTAT);
|
||||
}
|
||||
|
||||
if (publish_time_solar_ && (currentMillis - last_publish_solar_ > publish_time_solar_)) {
|
||||
last_publish_solar_ = currentMillis;
|
||||
EMSESP::publish_device_values(EMSdevice::DeviceType::SOLAR);
|
||||
}
|
||||
|
||||
if (publish_time_mixing_ && (currentMillis - last_publish_mixing_ > publish_time_mixing_)) {
|
||||
last_publish_mixing_ = currentMillis;
|
||||
EMSESP::publish_device_values(EMSdevice::DeviceType::MIXING);
|
||||
}
|
||||
|
||||
if (publish_time_other_ && (currentMillis - last_publish_other_ > publish_time_other_)) {
|
||||
last_publish_other_ = currentMillis;
|
||||
EMSESP::publish_other_values();
|
||||
}
|
||||
|
||||
if (currentMillis - last_publish_sensor_ > publish_time_sensor_) {
|
||||
last_publish_sensor_ = currentMillis;
|
||||
EMSESP::publish_sensor_values(publish_time_sensor_ != 0);
|
||||
}
|
||||
|
||||
// publish top item from MQTT queue to stop flooding
|
||||
if ((uint32_t)(currentMillis - last_mqtt_poll_) > MQTT_PUBLISH_WAIT) {
|
||||
last_mqtt_poll_ = currentMillis;
|
||||
@@ -316,7 +320,7 @@ void Mqtt::on_publish(uint16_t packetId) {
|
||||
}
|
||||
|
||||
if (mqtt_message.packet_id_ != packetId) {
|
||||
LOG_DEBUG(F("Mismatch, expecting PID %d, got %d"), mqtt_message.packet_id_, packetId);
|
||||
LOG_ERROR(F("Mismatch, expecting PID %d, got %d"), mqtt_message.packet_id_, packetId);
|
||||
mqtt_publish_fails_++; // increment error count
|
||||
}
|
||||
|
||||
@@ -470,13 +474,14 @@ std::shared_ptr<const MqttMessage> Mqtt::queue_message(const uint8_t operation,
|
||||
if ((strncmp(topic.c_str(), "homeassistant/", 13) == 0)) {
|
||||
// leave topic as it is
|
||||
// message = std::make_shared<MqttMessage>(operation, topic, std::move(payload), retain);
|
||||
message = std::make_shared<MqttMessage>(operation, topic, payload, retain);
|
||||
message = std::make_shared<MqttMessage>(operation, topic, std::move(payload), retain);
|
||||
|
||||
} else {
|
||||
// prefix the hostname
|
||||
std::string full_topic(50, '\0');
|
||||
snprintf_P(&full_topic[0], full_topic.capacity() + 1, PSTR("%s/%s"), Mqtt::hostname_.c_str(), topic.c_str());
|
||||
message = std::make_shared<MqttMessage>(operation, full_topic, payload, retain);
|
||||
// message = std::make_shared<MqttMessage>(operation, full_topic, std::move(payload), retain);
|
||||
message = std::make_shared<MqttMessage>(operation, full_topic, std::move(payload), retain);
|
||||
}
|
||||
|
||||
// if the queue is full, make room but removing the last one
|
||||
|
||||
@@ -55,8 +55,8 @@ struct MqttMessage {
|
||||
const std::string payload;
|
||||
const bool retain;
|
||||
|
||||
// MqttMessage(const uint8_t operation, const std::string & topic, const std::string && payload, bool retain)
|
||||
MqttMessage(const uint8_t operation, const std::string & topic, const std::string & payload, bool retain)
|
||||
// MqttMessage(const uint8_t operation, const std::string & topic, const std::string & payload, bool retain)
|
||||
MqttMessage(const uint8_t operation, const std::string & topic, const std::string && payload, bool retain)
|
||||
: operation(operation)
|
||||
, topic(topic)
|
||||
, payload(payload)
|
||||
|
||||
@@ -62,8 +62,6 @@ class Shower {
|
||||
static constexpr uint32_t SHOWER_COLDSHOT_DURATION = 10; // in seconds. 10 seconds for cold water before turning back hot water
|
||||
static constexpr uint32_t SHOWER_MAX_DURATION = 420000; // in ms. 7 minutes, before trigger a shot of cold water
|
||||
|
||||
void console_commands();
|
||||
|
||||
void publish_values();
|
||||
void shower_alert_start();
|
||||
void shower_alert_stop();
|
||||
|
||||
@@ -157,9 +157,9 @@ void System::start() {
|
||||
|
||||
// these commands respond to the topic "system" and take a payload like {cmd:"", data:"", id:""}
|
||||
EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) {
|
||||
Command::add(EMSdevice::DeviceType::SERVICEKEY, settings.ems_bus_id, F("pin"), System::command_pin);
|
||||
Command::add(EMSdevice::DeviceType::SERVICEKEY, settings.ems_bus_id, F("send"), System::command_send);
|
||||
Command::add_with_json(EMSdevice::DeviceType::SERVICEKEY, F("info"), System::command_info);
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, settings.ems_bus_id, F("pin"), System::command_pin);
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, settings.ems_bus_id, F("send"), System::command_send);
|
||||
Command::add_with_json(EMSdevice::DeviceType::SYSTEM, F("info"), System::command_info);
|
||||
});
|
||||
|
||||
EMSESP::init_tx(); // start UART
|
||||
@@ -523,7 +523,7 @@ void System::console_commands(Shell & shell, unsigned int context) {
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::SYSTEM,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(show)},
|
||||
flash_string_vector{F_(show), F_(system)},
|
||||
[=](Shell & shell, const std::vector<std::string> & arguments __attribute__((unused))) {
|
||||
show_system(shell);
|
||||
shell.println();
|
||||
|
||||
@@ -206,8 +206,6 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
||||
0x03, 0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03});
|
||||
|
||||
shell.invoke_command("show");
|
||||
// shell.invoke_command("system");
|
||||
// shell.invoke_command("show mqtt");
|
||||
}
|
||||
|
||||
if (command == "thermostat") {
|
||||
@@ -409,11 +407,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
||||
shell.loop_all();
|
||||
EMSESP::show_device_values(shell);
|
||||
|
||||
shell.invoke_command("thermostat");
|
||||
shell.loop_all();
|
||||
|
||||
// shell.invoke_command("set temp 20");
|
||||
shell.invoke_command("set mode auto");
|
||||
shell.invoke_command("call thermostat mode auto");
|
||||
|
||||
shell.loop_all();
|
||||
EMSESP::show_ems(shell);
|
||||
@@ -576,12 +570,9 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
||||
return StateUpdateResult::CHANGED;
|
||||
});
|
||||
|
||||
EMSESP::add_context_menus(); // need to add this as it happens later in the code
|
||||
shell.invoke_command("su");
|
||||
shell.invoke_command("system");
|
||||
shell.invoke_command("call");
|
||||
shell.invoke_command("call info");
|
||||
shell.invoke_command("exit");
|
||||
shell.invoke_command("call system info");
|
||||
|
||||
char system_topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||
strcpy(system_topic, "ems-esp/system");
|
||||
@@ -595,24 +586,14 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
||||
uart_telegram({0x90, 0x00, 0xFF, 0x00, 0x00, 0x70, 0x00, 0xCF, 0x22, 0x2F, 0x10, 0x00, 0x2E, 0x24,
|
||||
0x03, 0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03}); // HC2
|
||||
uart_telegram({0x90, 0x00, 0xFF, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); // HC3
|
||||
EMSESP::add_context_menus(); // need to add this as it happens later in the code
|
||||
shell.invoke_command("thermostat");
|
||||
shell.invoke_command("show");
|
||||
shell.invoke_command("call");
|
||||
shell.invoke_command("call info");
|
||||
shell.invoke_command("exit");
|
||||
shell.invoke_command("show mqtt");
|
||||
}
|
||||
|
||||
if (command == "pin") {
|
||||
shell.printfln(F("Testing pin..."));
|
||||
|
||||
EMSESP::add_context_menus(); // need to add this as it happens later in the code
|
||||
shell.invoke_command("su");
|
||||
shell.invoke_command("system");
|
||||
shell.invoke_command("help");
|
||||
shell.invoke_command("pin");
|
||||
shell.invoke_command("pin 1 true");
|
||||
shell.invoke_command("call system pin");
|
||||
shell.invoke_command("call system pin 1 true");
|
||||
}
|
||||
|
||||
if (command == "mqtt") {
|
||||
@@ -678,14 +659,12 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
||||
// EMSESP::txservice_.show_tx_queue();
|
||||
// EMSESP::publish_all_values();
|
||||
|
||||
EMSESP::add_context_menus(); // need to add this as it happens later in the code
|
||||
shell.invoke_command("su");
|
||||
shell.invoke_command("thermostat");
|
||||
shell.invoke_command("help");
|
||||
shell.invoke_command("call");
|
||||
shell.invoke_command("call wwmode");
|
||||
shell.invoke_command("call mode auto 2");
|
||||
shell.invoke_command("call temp 22.56");
|
||||
shell.invoke_command("call thermostat wwmode");
|
||||
shell.invoke_command("call thermostat mode auto 2");
|
||||
shell.invoke_command("call thermostat temp 22.56");
|
||||
|
||||
Mqtt::resubscribe();
|
||||
Mqtt::show_mqtt(shell); // show queue
|
||||
@@ -745,7 +724,6 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
||||
// check for error "[emsesp] No telegram type handler found for ID 0x255 (src 0x20, dest 0x00)"
|
||||
rx_telegram({0xA0, 0x00, 0xFF, 0x00, 0x01, 0x55, 0x00, 0x1A});
|
||||
|
||||
EMSESP::add_context_menus(); // need to add this as it happens later in the code
|
||||
}
|
||||
|
||||
// finally dump to console
|
||||
|
||||
Reference in New Issue
Block a user