From 5735ffd22204dd9bba2aa3d231a3d25acb089652 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 28 Jan 2024 18:28:26 +0100 Subject: [PATCH] tidied up commands --- src/analogsensor.cpp | 169 +++++++++++++++++--------------------- src/analogsensor.h | 6 +- src/emsdevice.cpp | 8 +- src/system.cpp | 7 +- src/temperaturesensor.cpp | 50 ++++++----- src/temperaturesensor.h | 1 + 6 files changed, 114 insertions(+), 127 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 993b964a0..46794b512 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -33,29 +33,13 @@ void AnalogSensor::start() { LOG_INFO("Starting Analog sensor service"); - // Add API call for /info - Command::add( - EMSdevice::DeviceType::ANALOGSENSOR, - F_(info), - [&](const char * value, const int8_t id, JsonObject output) { return command_info(value, id, output); }, - FL_(info_cmd)); - Command::add( - EMSdevice::DeviceType::ANALOGSENSOR, - F_(values), - [&](const char * value, const int8_t id, JsonObject output) { return command_info(value, 0, output); }, - nullptr, - CommandFlag::HIDDEN); // this command is hidden + // Add API calls Command::add( EMSdevice::DeviceType::ANALOGSENSOR, F_(setvalue), [&](const char * value, const int8_t id) { return command_setvalue(value, id); }, FL_(setiovalue_cmd), CommandFlag::ADMIN_ONLY); - Command::add( - EMSdevice::DeviceType::ANALOGSENSOR, - 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_(analogsensor)); @@ -636,48 +620,64 @@ void AnalogSensor::publish_values(const bool force) { Mqtt::queue_publish(topic, doc.as()); } -// called from emsesp.cpp, similar to the emsdevice->get_value_info -// searches by name -// TODO see if this can replace the command_info -bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) const { +// called from emsesp.cpp for commands +// searches sensor by name +bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) { if (sensors_.empty()) { + return true; // no sensors, return true + } + + uint8_t show_all = 0; + if (Helpers::hasValue(cmd)) { + show_all = (strncmp(cmd, F_(info), 4) == 0) ? 1 : (strncmp(cmd, F_(values), 6) == 0) ? 2 : 0; + } + + // see if we're showing all sensors + if (show_all) { + for (const auto & sensor : sensors_) { + if (show_all == 1) { + // info + JsonObject dataSensor = output[sensor.name()].to(); + addSensorJson(dataSensor, sensor); + } else { + // values, shortname version. Also used in 'system allvalues' + output[sensor.name()] = sensor.value(); + } + } 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 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 specific attribute to fetch instead of the complete record - char * breakp = strchr(command_s, '/'); + 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::atoint(command_s) == sensor.gpio()) { - output["gpio"] = sensor.gpio(); - output["name"] = sensor.name(); - output["type"] = F_(number); - output["analog"] = FL_(list_sensortype)[sensor.type()]; - output["uom"] = EMSdevice::uom_to_string(sensor.uom()); - output["offset"] = sensor.offset(); - output["factor"] = sensor.factor(); - output["value"] = sensor.value(); - output["writeable"] = sensor.type() == AnalogType::COUNTER || (sensor.type() >= AnalogType::DIGITAL_OUT && sensor.type() <= AnalogType::PWM_2); - // min/max for writeable analogs - if (sensor.type() == AnalogType::COUNTER) { - output["min"] = 0; - output["max"] = 4000000; - } else if (sensor.type() == AnalogType::DIGITAL_OUT) { - output["min"] = 0; - output["max"] = sensor.gpio() == 25 || sensor.gpio() == 26 ? 255 : 1; - } else if (sensor.type() >= AnalogType::PWM_0 && sensor.type() <= AnalogType::PWM_2) { - output["min"] = 0; - output["max"] = 100; - } + if (sensor_lowercase == Helpers::toLower(sensor.name().c_str()) || Helpers::atoint(sensor_name) == sensor.gpio()) { + // add the details + addSensorJson(output, sensor); + + /* + // if someone wants gpio numbers + char gpio_str[9]; + snprintf(gpio_str, sizeof(gpio_str), "gpio_%02d", sensor.gpio()); + output[gpio_str] = sensor.value(); + */ + // if we're filtering on an attribute, go find it if (attribute_s) { if (output.containsKey(attribute_s)) { @@ -687,57 +687,45 @@ bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int 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 } -// creates JSON doc from values -// returns true if there are no sensors -// TODO see if this can be merged with get_value_info so we can remove the commands (info, commands, etc...) -bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject output) const { - if (sensors_.empty()) { - return true; +void AnalogSensor::addSensorJson(JsonObject output, const Sensor & sensor) { + output["gpio"] = sensor.gpio(); + output["type"] = F_(number); + output["analog"] = FL_(list_sensortype)[sensor.type()]; + output["value"] = sensor.value(); + output["writeable"] = sensor.type() == AnalogType::COUNTER || (sensor.type() >= AnalogType::DIGITAL_OUT && sensor.type() <= AnalogType::PWM_2); + if (sensor.type() == AnalogType::COUNTER) { + output["min"] = 0; + output["max"] = 4000000; + output["start_value"] = sensor.offset(); + output["factor"] = sensor.factor(); + output["uom"] = EMSdevice::uom_to_string(sensor.uom()); + } else if (sensor.type() == AnalogType::ADC) { + output["offset"] = sensor.offset(); + output["factor"] = sensor.factor(); + output["uom"] = EMSdevice::uom_to_string(sensor.uom()); + } else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) { + output["factor"] = sensor.factor(); + } else if (sensor.type() >= AnalogType::PWM_0 && sensor.type() <= AnalogType::PWM_2) { + output["frequency"] = sensor.factor(); + output["min"] = 0; + output["max"] = 100; + output["uom"] = EMSdevice::uom_to_string(sensor.uom()); + } else if (sensor.type() == AnalogType::DIGITAL_OUT) { + output["min"] = 0; + output["max"] = sensor.gpio() == 25 || sensor.gpio() == 26 ? 255 : 1; } - - for (const auto & sensor : sensors_) { - if (id == -1) { // show number and id for info command - JsonObject dataSensor = output[sensor.name()].to(); - dataSensor["gpio"] = sensor.gpio(); - dataSensor["type"] = F_(number); - dataSensor["value"] = sensor.value(); - dataSensor["analog"] = FL_(list_sensortype)[sensor.type()]; - if (sensor.type() == AnalogType::ADC) { - dataSensor["uom"] = EMSdevice::uom_to_string(sensor.uom()); - dataSensor["offset"] = sensor.offset(); - dataSensor["factor"] = sensor.factor(); - } else if (sensor.type() == AnalogType::COUNTER) { - dataSensor["uom"] = EMSdevice::uom_to_string(sensor.uom()); - dataSensor["start_value"] = sensor.offset(); - dataSensor["factor"] = sensor.factor(); - } else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) { - dataSensor["factor"] = sensor.factor(); - } else if (sensor.type() >= AnalogType::PWM_0 && sensor.type() <= AnalogType::PWM_2) { - dataSensor["uom"] = EMSdevice::uom_to_string(sensor.uom()); - dataSensor["frequency"] = sensor.factor(); - } - } else if (id == 0) { // output values command - output[sensor.name()] = sensor.value(); - } else { // if someone wants gpio numbers - char gpio_str[9]; - snprintf(gpio_str, sizeof(gpio_str), "gpio_%02d", sensor.gpio()); - output[gpio_str] = sensor.value(); - } - } - - return (output.size() > 0); } // this creates the sensor, initializing everything @@ -853,9 +841,4 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) { return false; } -// list commands -bool AnalogSensor::command_commands(const char * value, const int8_t id, JsonObject output) { - return Command::list(EMSdevice::DeviceType::ANALOGSENSOR, output); -} - } // namespace emsesp \ No newline at end of file diff --git a/src/analogsensor.h b/src/analogsensor.h index 09c470397..8681106a4 100644 --- a/src/analogsensor.h +++ b/src/analogsensor.h @@ -153,11 +153,9 @@ class AnalogSensor { } bool update(uint8_t gpio, const std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted = false); - bool get_value_info(JsonObject output, const char * cmd, const int8_t id) const; + bool get_value_info(JsonObject output, const char * cmd, const int8_t id = -1); void store_counters(); - bool command_info(const char * value, const int8_t id, JsonObject output) const; - private: static constexpr uint8_t MAX_SENSORS = 20; static constexpr uint32_t MEASURE_ANALOG_INTERVAL = 500; @@ -167,7 +165,7 @@ class AnalogSensor { void remove_ha_topic(const int8_t type, const uint8_t id) const; bool command_setvalue(const char * value, const int8_t gpio); void measure(); - bool command_commands(const char * value, const int8_t id, JsonObject output); + void addSensorJson(JsonObject output, const Sensor & sensor); std::vector sensors_; // our list of sensors diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index d548734d4..f33e643ab 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -932,7 +932,7 @@ void EMSdevice::generate_values_web(JsonObject output) { // add name, prefixing the tag if it exists. This is the id used in the WebUI table and must be unique obj["id"] = dv.has_tag() ? mask + tag_to_string(dv.tag) + " " + fullname : mask + fullname; // suffix tag - // TODO check TAG https://github.com/emsesp/EMS-ESP32/issues/1338 + // TAG https://github.com/emsesp/EMS-ESP32/issues/1338 // obj["id"] = dv.has_tag() ? mask + fullname + " " + tag_to_string(dv.tag) : mask + fullname; // suffix tag // add commands and options @@ -1046,7 +1046,7 @@ void EMSdevice::generate_values_web_customization(JsonArray output) { if (fullname) { obj["n"] = dv.has_tag() ? std::string(tag_to_string(dv.tag)) + " " + fullname : fullname; // prefix tag - // TODO check TAG https://github.com/emsesp/EMS-ESP32/issues/1338 + // TAG https://github.com/emsesp/EMS-ESP32/issues/1338 // obj["n"] = (dv.has_tag()) ? fullname + " " + tag_to_string(dv.tag) : fullname; // suffix tag } @@ -1394,7 +1394,7 @@ bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t if (!fullname.empty()) { json["fullname"] = dv.has_tag() ? fullname + " " + tag_to_string(dv.tag) : fullname; // suffix tag - // TODO check TAG https://github.com/emsesp/EMS-ESP32/issues/1338 + // TAG https://github.com/emsesp/EMS-ESP32/issues/1338 json["fullname"] = dv.has_tag() ? std::string(tag_to_string(dv.tag)) + " " + fullname.c_str() : fullname; // prefix tag } @@ -1600,7 +1600,7 @@ bool EMSdevice::generate_values(JsonObject output, const uint8_t tag_filter, con // add tag if (have_tag) { snprintf(name, sizeof(name), "%s %s (%s)", tag_to_string(dv.tag), fullname.c_str(), dv.short_name); // prefix tag - // TODO check TAG https://github.com/emsesp/EMS-ESP32/issues/1338 + // TAG https://github.com/emsesp/EMS-ESP32/issues/1338 // snprintf(name, sizeof(name), "%s %s (%s)", fullname.c_str(), tag_to_string(dv.tag), dv.short_name); // sufix tag } else { snprintf(name, sizeof(name), "%s (%s)", fullname.c_str(), dv.short_name); diff --git a/src/system.cpp b/src/system.cpp index fc75fde48..a268aec16 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -119,16 +119,15 @@ bool System::command_allvalues(const char * value, const int8_t id, JsonObject o emsdevice->generate_values(device_output, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::API_VERBOSE); // use nested for id -1 and 0 } - // Custom entities + // Custom Entities device_output = output["Custom Entities"].to(); EMSESP::webCustomEntityService.get_value_info(device_output, ""); // Sensors device_output = output["Analog Sensors"].to(); - // TODO fix this also for analogsensor - EMSESP::analogsensor_.command_info(nullptr, 0, device_output); + EMSESP::analogsensor_.get_value_info(device_output, "values"); device_output = output["Temperature Sensors"].to(); - EMSESP::temperaturesensor_.get_value_info(device_output, nullptr); + EMSESP::temperaturesensor_.get_value_info(device_output, "values"); return true; } diff --git a/src/temperaturesensor.cpp b/src/temperaturesensor.cpp index ae77250b5..096bb6538 100644 --- a/src/temperaturesensor.cpp +++ b/src/temperaturesensor.cpp @@ -349,24 +349,25 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons return true; // no sensors, return true } - bool show_all = true; + uint8_t show_all = 0; if (Helpers::hasValue(cmd)) { - show_all = (strncmp(cmd, F_(info), 4) == 0); + show_all = (strncmp(cmd, F_(info), 4) == 0) ? 1 : (strncmp(cmd, F_(values), 6) == 0) ? 2 : 0; } // see if we're showing all sensors if (show_all) { for (const auto & sensor : sensors_) { - JsonObject dataSensor = output[sensor.name()].to(); - 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)); + if (show_all == 1) { + // info + JsonObject dataSensor = output[sensor.name()].to(); + addSensorJson(dataSensor, sensor); + } else { + // values, shortname version. Also used in 'system allvalues' + if (Helpers::hasValue(sensor.temperature_c)) { + char val[10]; + output[sensor.name()] = 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; } @@ -393,17 +394,8 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons for (const auto & sensor : sensors_) { // 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)) { - char val[10]; - output["value"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0)); - } - - output["type"] = F_(number); - output["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES); - output["writeable"] = false; - + // add values + addSensorJson(output, sensor); // if we're filtering on an attribute, go find it if (attribute_s) { if (output.containsKey(attribute_s)) { @@ -426,6 +418,20 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons return false; // not found } +void TemperatureSensor::addSensorJson(JsonObject output, const Sensor & sensor) { + output["id"] = sensor.id(); + output["name"] = sensor.name(); + if (Helpers::hasValue(sensor.temperature_c)) { + char val[10]; + output["value"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0)); + } + + output["type"] = F_(number); + output["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES); + output["writeable"] = false; +} + + // publish a single sensor to MQTT void TemperatureSensor::publish_sensor(const Sensor & sensor) { if (Mqtt::enabled() && Mqtt::publish_single()) { diff --git a/src/temperaturesensor.h b/src/temperaturesensor.h index 0c354d278..aad999e26 100644 --- a/src/temperaturesensor.h +++ b/src/temperaturesensor.h @@ -152,6 +152,7 @@ class TemperatureSensor { int16_t get_temperature_c(const uint8_t addr[]); uint64_t get_id(const uint8_t addr[]); void remove_ha_topic(const std::string & id); + void addSensorJson(JsonObject output, const Sensor & sensor); std::vector sensors_; // our list of active sensors