tidy up commands for temperature sensor

This commit is contained in:
proddy
2024-01-28 16:36:18 +01:00
parent eec0051997
commit 040954bb70
10 changed files with 119 additions and 133 deletions

View File

@@ -364,10 +364,10 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
// report back. If not OK show output from error, other return the HTTP code
if (return_code != CommandRet::OK) {
if (value == nullptr) {
if ((value == nullptr) || (strlen(value) == 0)) {
LOG_ERROR("Command '%s' failed with code: %d", cmd, return_code);
} else {
LOG_ERROR("Command '%s:%s' failed with code: %d", cmd, value, return_code);
LOG_ERROR("Command '%s/%s' failed with code: %d", cmd, value, return_code);
}
return message(return_code, "callback function failed", output);
}
@@ -442,7 +442,7 @@ bool Command::list(const uint8_t device_type, JsonObject output) {
return false;
}
// create a list of commands, sort them
// create a list of commands we have registered, and sort them
std::list<std::string> sorted_cmds;
for (const auto & cf : cmdfunctions_) {
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN)) {
@@ -451,6 +451,12 @@ bool Command::list(const uint8_t device_type, JsonObject output) {
}
sorted_cmds.sort();
// force add info and commands for those non-EMS devices
if (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR) {
output[F_(info)] = Helpers::translated_word(FL_(info_cmd));
output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd));
}
for (const auto & cl : sorted_cmds) {
for (const auto & cf : cmdfunctions_) {
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == std::string(cf.cmd_))) {
@@ -475,14 +481,24 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo
return;
}
// create list of command, and sort
// create list of commands we have registered
std::list<std::string> sorted_cmds;
for (const auto & cf : cmdfunctions_) {
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN)) {
sorted_cmds.push_back((cf.cmd_));
}
}
sorted_cmds.sort();
// non EMS devices always have an info and commands command
bool show_info = (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR || device_type == EMSdevice::DeviceType::ANALOGSENSOR
|| device_type == EMSdevice::DeviceType::SCHEDULER || device_type == EMSdevice::DeviceType::CUSTOM);
if (!verbose && show_info) {
sorted_cmds.push_back(F_(info));
sorted_cmds.push_back(F_(commands));
}
sorted_cmds.sort(); // sort them
// if not in verbose mode, just print them on a single line and exit
if (!verbose) {
@@ -495,7 +511,16 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo
}
// verbose mode
shell.println();
shell.printfln("\n%s%s %s:%s", COLOR_BOLD_ON, COLOR_YELLOW, EMSdevice::device_type_2_device_name(device_type), COLOR_RESET);
// we hard code 'info' and 'commmands' commands so print them first
if (show_info) {
shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN);
shell.println(COLOR_RESET);
shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN);
shell.println(COLOR_RESET);
}
for (const auto & cl : sorted_cmds) {
// find and print the description
for (const auto & cf : cmdfunctions_) {
@@ -530,8 +555,6 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo
}
shell.println();
}
shell.println();
}
// see if a device_type is active and has associated commands
@@ -599,69 +622,32 @@ void Command::show_devices(uuid::console::Shell & shell) {
shell.println();
}
// output list of all commands to console
// 'show commmands' : output list of all commands to console
// calls show with verbose mode set
void Command::show_all(uuid::console::Shell & shell) {
shell.printfln("Showing all available commands (%s*%s=authentication not required):", COLOR_BRIGHT_GREEN, COLOR_RESET);
// show system first
shell.print(COLOR_BOLD_ON);
shell.print(COLOR_YELLOW);
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM));
shell.print(COLOR_RESET);
// show system ones first
show(shell, EMSdevice::DeviceType::SYSTEM, true);
// show Custom Entities
shell.print(COLOR_BOLD_ON);
shell.print(COLOR_YELLOW);
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::CUSTOM));
shell.println(COLOR_RESET);
// TODO to remove later?
shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN);
shell.println(COLOR_RESET);
shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN);
shell.print(COLOR_RESET);
show(shell, EMSdevice::DeviceType::CUSTOM, true);
// show scheduler
shell.print(COLOR_BOLD_ON);
shell.print(COLOR_YELLOW);
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SCHEDULER));
shell.println(COLOR_RESET);
// TODO to remove later?
shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN);
shell.println(COLOR_RESET);
shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN);
shell.print(COLOR_RESET);
show(shell, EMSdevice::DeviceType::SCHEDULER, true);
// show sensors
// then sensors
if (EMSESP::sensor_enabled()) {
shell.print(COLOR_BOLD_ON);
shell.print(COLOR_YELLOW);
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::TEMPERATURESENSOR));
shell.print(COLOR_RESET);
show(shell, EMSdevice::DeviceType::TEMPERATURESENSOR, true);
}
if (EMSESP::analog_enabled()) {
shell.print(COLOR_BOLD_ON);
shell.print(COLOR_YELLOW);
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR));
shell.print(COLOR_RESET);
show(shell, EMSdevice::DeviceType::ANALOGSENSOR, true);
}
// do this in the order of factory classes to keep a consistent order when displaying
// now EMS devices, do this in the order of factory classes to keep a consistent order when displaying
for (const auto & device_class : EMSFactory::device_handlers()) {
if (Command::device_has_commands(device_class.first)) {
shell.print(COLOR_BOLD_ON);
shell.print(COLOR_YELLOW);
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(device_class.first));
shell.print(COLOR_RESET);
show(shell, device_class.first, true);
}
}
shell.println();
}
// Extract only the path component from the passed URI and normalized it

View File

@@ -659,9 +659,10 @@ void EMSESP::publish_response(std::shared_ptr<const Telegram> telegram) {
buffer = nullptr;
}
// builds json with the detail of each value,
// for a specific EMS device type or the sensors, scheduler and custom entities
// builds json with the detail of each value, for an EMS device
// for other types like sensors, scheduler, custom entities it will process single commands like 'info', 'values', 'commands'...
bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8_t id, const uint8_t devicetype) {
// check first for EMS devices
for (const auto & emsdevice : emsdevices) {
if (emsdevice->device_type() == devicetype) {
if (emsdevice->get_value_info(root, cmd, id)) {
@@ -670,24 +671,24 @@ bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8
}
}
// specific for the temperaturesensor
// temperaturesensor
if (devicetype == DeviceType::TEMPERATURESENSOR) {
return EMSESP::temperaturesensor_.get_value_info(root, cmd, id);
return temperaturesensor_.get_value_info(root, cmd, id);
}
// analog sensor
if (devicetype == DeviceType::ANALOGSENSOR) {
return EMSESP::analogsensor_.get_value_info(root, cmd, id);
return analogsensor_.get_value_info(root, cmd, id);
}
// scheduler
if (devicetype == DeviceType::SCHEDULER) {
return EMSESP::webSchedulerService.get_value_info(root, cmd);
return webSchedulerService.get_value_info(root, cmd);
}
// custom entities
if (devicetype == DeviceType::CUSTOM) {
return EMSESP::webCustomEntityService.get_value_info(root, cmd);
return webCustomEntityService.get_value_info(root, cmd);
}
char error[100];
@@ -1165,7 +1166,9 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
// Print to LOG showing we've added a new device
LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type), device_id);
// add command commands for all devices, except for connect, controller and gateway
// add commands 'info', 'commands', 'values', 'entities' for all EMS devices
// and register the MQTT subscribe topic for this device
// except for connect, controller and gateway
if ((device_type == DeviceType::CONNECT) || (device_type == DeviceType::CONTROLLER) || (device_type == DeviceType::GATEWAY)) {
return true;
}

View File

@@ -125,9 +125,10 @@ bool System::command_allvalues(const char * value, const int8_t id, JsonObject o
// Sensors
device_output = output["Analog Sensors"].to<JsonObject>();
// TODO fix this also for analogsensor
EMSESP::analogsensor_.command_info(nullptr, 0, device_output);
device_output = output["Temperature Sensors"].to<JsonObject>();
EMSESP::temperaturesensor_.command_info(nullptr, 0, device_output);
EMSESP::temperaturesensor_.get_value_info(device_output, nullptr);
return true;
}

View File

@@ -45,24 +45,6 @@ void TemperatureSensor::start() {
LOG_INFO("Starting Temperature sensor service");
#endif
// Add API calls
Command::add(
EMSdevice::DeviceType::TEMPERATURESENSOR,
F_(info),
[&](const char * value, const int8_t id, JsonObject output) { return command_info(value, id, output); },
FL_(info_cmd));
Command::add(
EMSdevice::DeviceType::TEMPERATURESENSOR,
F_(values),
[&](const char * value, const int8_t id, JsonObject output) { return command_info(value, 0, output); },
nullptr,
CommandFlag::HIDDEN); // this command is hidden
Command::add(
EMSdevice::DeviceType::TEMPERATURESENSOR,
F_(commands),
[&](const char * value, const int8_t id, JsonObject output) { return command_commands(value, id, output); },
FL_(commands_cmd));
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
snprintf(topic, sizeof(topic), "%s/#", F_(temperaturesensor));
Mqtt::subscribe(EMSdevice::DeviceType::TEMPERATURESENSOR, topic, nullptr); // use empty function callback
@@ -361,57 +343,56 @@ bool TemperatureSensor::updated_values() {
return false;
}
// list commands
bool TemperatureSensor::command_commands(const char * value, const int8_t id, JsonObject output) {
return Command::list(EMSdevice::DeviceType::TEMPERATURESENSOR, output);
}
// creates JSON doc from values
// returns true if there are no sensors
bool TemperatureSensor::command_info(const char * value, const int8_t id, JsonObject output) {
if (sensors_.empty()) {
return true;
}
for (const auto & sensor : sensors_) {
char val[10];
if (id == -1) { // show number and id, info command
JsonObject dataSensor = output[sensor.name()].to<JsonObject>();
dataSensor["id"] = sensor.id();
dataSensor["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
dataSensor["type"] = F_(number);
if (Helpers::hasValue(sensor.temperature_c)) {
dataSensor["temp"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
}
} else if (id == 0 && Helpers::hasValue(sensor.temperature_c)) { // values command
output[sensor.name()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
} else if (Helpers::hasValue(sensor.temperature_c)) {
output[sensor.id()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
}
}
return (output.size() > 0);
}
// called from emsesp.cpp, similar to the emsdevice->get_value_info
// called from emsesp.cpp for commands
bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) {
if (sensors_.empty()) {
return true; // no sensors, return true
}
bool show_all = true;
if (Helpers::hasValue(cmd)) {
show_all = (strncmp(cmd, F_(info), 4) == 0);
}
// see if we're showing all sensors
if (show_all) {
for (const auto & sensor : sensors_) {
JsonObject dataSensor = output[sensor.name()].to<JsonObject>();
dataSensor["id"] = sensor.id();
dataSensor["offset"] = sensor.offset();
if (Helpers::hasValue(sensor.temperature_c)) {
char val[10];
dataSensor["value"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
}
dataSensor["type"] = F_(number);
dataSensor["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
dataSensor["writeable"] = false;
}
return true;
}
// make a copy of the string command for parsing
char command_s[30];
strlcpy(command_s, cmd, sizeof(command_s));
char * attribute_s = nullptr;
// check specific attribute to fetch instead of the complete record
char * breakp = strchr(command_s, '/');
// check of it a 'commmands' command
if (Helpers::toLower(cmd) == F_(commands)) {
return Command::list(EMSdevice::DeviceType::TEMPERATURESENSOR, output);
}
// this is for a specific sensor
// make a copy of the string command for parsing, and lowercase it
char sensor_name[30] = {'\0'};
char * attribute_s = nullptr;
strlcpy(sensor_name, cmd, sizeof(sensor_name));
auto sensor_lowercase = Helpers::toLower(sensor_name);
// check for a specific attribute to fetch instead of the complete record
char * breakp = strchr(sensor_name, '/');
if (breakp) {
*breakp = '\0';
attribute_s = breakp + 1;
}
for (const auto & sensor : sensors_) {
if (Helpers::toLower(command_s) == Helpers::toLower(sensor.name().c_str()) || Helpers::toLower(command_s) == Helpers::toLower(sensor.id().c_str())) {
// match custom name or sensor ID
if (sensor_lowercase == Helpers::toLower(sensor.name().c_str()) || sensor_lowercase == Helpers::toLower(sensor.id().c_str())) {
output["id"] = sensor.id();
output["name"] = sensor.name();
if (Helpers::hasValue(sensor.temperature_c)) {
@@ -432,16 +413,17 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons
return true;
} else {
char error[100];
snprintf(error, sizeof(error), "cannot find attribute %s in entity %s", attribute_s, command_s);
snprintf(error, sizeof(error), "cannot find attribute %s in entity %s", attribute_s, sensor_name);
output.clear();
output["message"] = error;
return false;
}
}
return true;
return true; // found a match, exit
}
}
return false;
return false; // not found
}
// publish a single sensor to MQTT

View File

@@ -83,7 +83,7 @@ class TemperatureSensor {
void publish_values(const bool force);
void reload();
bool updated_values();
bool get_value_info(JsonObject output, const char * cmd, const int8_t id);
bool get_value_info(JsonObject output, const char * cmd, const int8_t id = -1);
// return back reference to the sensor list, used by other classes
std::vector<Sensor> sensors() const {
@@ -112,8 +112,6 @@ class TemperatureSensor {
bool update(const std::string & id, const std::string & name, int16_t offset);
bool command_info(const char * value, const int8_t id, JsonObject output);
#if defined(EMSESP_TEST)
void test();
#endif
@@ -155,8 +153,6 @@ class TemperatureSensor {
uint64_t get_id(const uint8_t addr[]);
void remove_ha_topic(const std::string & id);
bool command_commands(const char * value, const int8_t id, JsonObject output);
std::vector<Sensor> sensors_; // our list of active sensors
#ifndef EMSESP_STANDALONE

View File

@@ -757,8 +757,24 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
if (command == "temperature") {
shell.printfln("Testing adding Temperature sensor");
shell.invoke_command("show commands");
emsesp::EMSESP::temperaturesensor_.test();
shell.invoke_command("call temperaturesensor");
shell.invoke_command("show values");
shell.invoke_command("call system allvalues");
shell.invoke_command("call temperaturesensor info");
AsyncWebServerRequest request;
request.method(HTTP_GET);
request.url("/api/temperaturesensor/commands");
EMSESP::webAPIService.webAPIService_get(&request);
request.url("/api/temperaturesensor/info");
EMSESP::webAPIService.webAPIService_get(&request);
request.url("/api/temperaturesensor/01-0203-0405-0607");
EMSESP::webAPIService.webAPIService_get(&request);
ok = true;
}

View File

@@ -27,7 +27,7 @@
namespace emsesp {
#define EMSESP_DEBUG_DEFAULT "general"
// #define EMSESP_DEBUG_DEFAULT "general"
// #define EMSESP_DEBUG_DEFAULT "thermostat"
// #define EMSESP_DEBUG_DEFAULT "solar"
@@ -47,7 +47,7 @@ namespace emsesp {
// #define EMSESP_DEBUG_DEFAULT "dv"
// #define EMSESP_DEBUG_DEFAULT "lastcode"
// #define EMSESP_DEBUG_DEFAULT "2thermostats"
// #define EMSESP_DEBUG_DEFAULT "temperature"
#define EMSESP_DEBUG_DEFAULT "temperature"
// #define EMSESP_DEBUG_DEFAULT "analog"
// #define EMSESP_DEBUG_DEFAULT "api_values"
// #define EMSESP_DEBUG_DEFAULT "mqtt_post"

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.6.5-dev.10"
#define EMSESP_APP_VERSION "3.6.5-dev.11"

View File

@@ -152,12 +152,13 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject input) {
#if defined(EMSESP_STANDALONE)
Serial.print(COLOR_YELLOW);
Serial.print("web response code: ");
Serial.println(ret_codes[return_code]);
Serial.print("data: ");
if (output.size()) {
serializeJsonPretty(output, Serial);
serializeJson(output, Serial);
}
Serial.println();
Serial.print(" (response code ");
Serial.print(ret_codes[return_code]);
Serial.println(")");
Serial.print(COLOR_RESET);
#endif
}

View File

@@ -134,6 +134,7 @@ bool WebSchedulerService::command_setvalue(const char * value, const std::string
// process json output for info/commands and value_info
bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) {
// check of it a 'commmands' command
if (Helpers::toLower(cmd) == F_(commands)) {
output[F_(info)] = Helpers::translated_word(FL_(info_cmd));
output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd));