diff --git a/.github/workflows/sonar_check.yml b/.github/workflows/sonar_check.yml new file mode 100644 index 000000000..c0ea0e1bb --- /dev/null +++ b/.github/workflows/sonar_check.yml @@ -0,0 +1,56 @@ +name: Sonar Check +on: + push: + branches: + - dev + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: Build + runs-on: ubuntu-latest + env: + # https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/ + # SONAR_SCANNER_VERSION: 4.6.1.2450 + SONAR_SCANNER_VERSION: 4.7.0.2747 + SONAR_SERVER_URL: "https://sonarcloud.io" + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Download and set up sonar-scanner + env: + SONAR_SCANNER_DOWNLOAD_URL: https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${{ env.SONAR_SCANNER_VERSION }}-linux.zip + run: | + mkdir -p $HOME/.sonar + curl -sSLo $HOME/.sonar/sonar-scanner.zip ${{ env.SONAR_SCANNER_DOWNLOAD_URL }} + unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/ + echo "$HOME/.sonar/sonar-scanner-${{ env.SONAR_SCANNER_VERSION }}-linux/bin" >> $GITHUB_PATH + - name: Download and set up build-wrapper + env: + BUILD_WRAPPER_DOWNLOAD_URL: ${{ env.SONAR_SERVER_URL }}/static/cpp/build-wrapper-linux-x86.zip + run: | + curl -sSLo $HOME/.sonar/build-wrapper-linux-x86.zip ${{ env.BUILD_WRAPPER_DOWNLOAD_URL }} + unzip -o $HOME/.sonar/build-wrapper-linux-x86.zip -d $HOME/.sonar/ + echo "$HOME/.sonar/build-wrapper-linux-x86" >> $GITHUB_PATH + - name: Run build-wrapper + run: | + make clean + build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make clean all + - name: Run sonar-scanner + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + sonar-scanner diff --git a/.gitignore b/.gitignore index 1f342b86d..ed0708caf 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,8 @@ node_modules test.sh scripts/__pycache__ .temp + +# sonar +.scannerwork/ +sonar/ +build_wrapper_output_directory/ diff --git a/Makefile b/Makefile index 88cac6bc0..9baf49005 100644 --- a/Makefile +++ b/Makefile @@ -113,6 +113,7 @@ COMPILE.cpp = $(CXX) $(CXX_STANDARD) $(CXXFLAGS) $(DEPFLAGS) -c $< -o $@ #---------------------------------------------------------------------- # Targets #---------------------------------------------------------------------- +.PHONY: all all: $(OUTPUT) $(OUTPUT): $(OBJS) @@ -138,6 +139,7 @@ cppcheck: $(SOURCES) run: $(OUTPUT) @$< +.PHONY: clean clean: @$(RM) -r $(BUILD) $(OUTPUT) diff --git a/interface/package-lock.json b/interface/package-lock.json index 7554f981a..99b007d19 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -16,7 +16,7 @@ "@types/lodash": "^4.14.179", "@types/node": "^17.0.21", "@types/react": "^17.0.39", - "@types/react-dom": "^17.0.11", + "@types/react-dom": "^17.0.13", "@types/react-router-dom": "^5.3.3", "async-validator": "^4.0.7", "axios": "^0.26.0", @@ -3793,9 +3793,9 @@ } }, "node_modules/@types/react-dom": { - "version": "17.0.11", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", - "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.13.tgz", + "integrity": "sha512-wEP+B8hzvy6ORDv1QBhcQia4j6ea4SFIBttHYpXKPFZRviBvknq0FRh3VrIxeXUmsPkwuXVZrVGG7KUVONmXCQ==", "dependencies": { "@types/react": "*" } @@ -20246,9 +20246,9 @@ } }, "@types/react-dom": { - "version": "17.0.11", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", - "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.13.tgz", + "integrity": "sha512-wEP+B8hzvy6ORDv1QBhcQia4j6ea4SFIBttHYpXKPFZRviBvknq0FRh3VrIxeXUmsPkwuXVZrVGG7KUVONmXCQ==", "requires": { "@types/react": "*" } diff --git a/interface/package.json b/interface/package.json index 2c81307d2..e6c94e445 100644 --- a/interface/package.json +++ b/interface/package.json @@ -12,7 +12,7 @@ "@types/lodash": "^4.14.179", "@types/node": "^17.0.21", "@types/react": "^17.0.39", - "@types/react-dom": "^17.0.11", + "@types/react-dom": "^17.0.13", "@types/react-router-dom": "^5.3.3", "async-validator": "^4.0.7", "axios": "^0.26.0", diff --git a/scripts/run_sonar.sh b/scripts/run_sonar.sh new file mode 100755 index 000000000..713fbaa9f --- /dev/null +++ b/scripts/run_sonar.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# make sure you add the soanr token here +# export SONAR_TOKEN="" + +make clean +build-wrapper-linux-x86-64 --out-dir build_wrapper_output_directory make all +sonar-scanner diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 000000000..cd8e24393 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,11 @@ +sonar.organization=emsesp +sonar.projectKey=emsesp_EMS-ESP32 +sonar.projectName=EMS-ESP32 +sonar.projectVersion=3.4 +sonar.sources=./src +sonar.cfamily.build-wrapper-output=build_wrapper_output_directory +sonar.sourceEncoding=UTF-8 +sonar.host.url=https://sonarcloud.io +sonar.cfamily.threads=8 +sonar.cfamily.cache.enabled=false +; sonar.cfamily.cache.path=./sonar/cache diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 0fb66a6e8..8c42fdd55 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -64,12 +64,11 @@ void AnalogSensor::reload() { // load the list of analog sensors from the customization service // and store them locally and then activate them EMSESP::webCustomizationService.read([&](WebCustomization & settings) { - auto sensors = settings.analogCustomizations; - auto it = sensors_.begin(); + auto it = sensors_.begin(); for (auto & sensor_ : sensors_) { // update existing sensors bool found = false; - for (auto & sensor : sensors) { //search customlist + for (const auto & sensor : settings.analogCustomizations) { //search customlist if (sensor_.id() == sensor.id) { // for output sensors set value to new start-value if ((sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) @@ -90,10 +89,11 @@ void AnalogSensor::reload() { } it++; } + // add new sensors from list - for (auto & sensor : sensors) { + for (const auto & sensor : settings.analogCustomizations) { bool found = false; - for (auto & sensor_ : sensors_) { + for (const auto & sensor_ : sensors_) { if (sensor_.id() == sensor.id) { found = true; } @@ -295,13 +295,13 @@ bool AnalogSensor::update(uint8_t id, const std::string & name, float offset, fl if (!found_sensor) { EMSESP::webCustomizationService.update( [&](WebCustomization & settings) { - AnalogCustomization newSensor = AnalogCustomization(); - newSensor.id = id; - newSensor.name = name; - newSensor.offset = offset; - newSensor.factor = factor; - newSensor.uom = uom; - newSensor.type = type; + auto newSensor = AnalogCustomization(); + newSensor.id = id; + newSensor.name = name; + newSensor.offset = offset; + newSensor.factor = factor; + newSensor.uom = uom; + newSensor.type = type; settings.analogCustomizations.push_back(newSensor); LOG_DEBUG(F("Adding new customization for analog sensor ID %d"), id); return StateUpdateResult::CHANGED; // persist the change @@ -325,7 +325,7 @@ bool AnalogSensor::updated_values() { } // publish a single sensor to MQTT -void AnalogSensor::publish_sensor(const Sensor & sensor) { +void AnalogSensor::publish_sensor(const Sensor & sensor) const { if (Mqtt::publish_single()) { char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; if (Mqtt::publish_single2cmd()) { @@ -339,7 +339,7 @@ void AnalogSensor::publish_sensor(const Sensor & sensor) { } // send empty config topic to remove the entry from HA -void AnalogSensor::remove_ha_topic(const uint8_t id) { +void AnalogSensor::remove_ha_topic(const uint8_t id) const { if (!Mqtt::ha_enabled()) { return; } @@ -363,7 +363,6 @@ void AnalogSensor::publish_values(const bool force) { for (const auto & sensor : sensors_) { publish_sensor(sensor); } - // return; } DynamicJsonDocument doc(120 * num_sensors); @@ -383,61 +382,59 @@ void AnalogSensor::publish_values(const bool force) { case AnalogType::PWM_0: case AnalogType::PWM_1: case AnalogType::PWM_2: - dataSensor["value"] = (float)sensor.value(); // float + dataSensor["value"] = sensor.value(); // float break; - case AnalogType::DIGITAL_IN: - case AnalogType::DIGITAL_OUT: default: dataSensor["value"] = (uint8_t)sensor.value(); // convert to char for 1 or 0 break; } // create HA config - if (Mqtt::ha_enabled()) { - if (!sensor.ha_registered || force) { - LOG_DEBUG(F("Recreating HA config for analog sensor ID %d"), sensor.id()); + if (Mqtt::ha_enabled() && (!sensor.ha_registered || force)) { + LOG_DEBUG(F("Recreating HA config for analog sensor ID %d"), sensor.id()); - StaticJsonDocument config; + StaticJsonDocument config; - char stat_t[50]; - snprintf(stat_t, sizeof(stat_t), "%s/analogsensor_data", Mqtt::base().c_str()); - config["stat_t"] = stat_t; + char stat_t[50]; + snprintf(stat_t, sizeof(stat_t), "%s/analogsensor_data", Mqtt::base().c_str()); + config["stat_t"] = stat_t; - char str[50]; - snprintf(str, sizeof(str), "{{value_json['%d'].value}}", sensor.id()); - config["val_tpl"] = str; + char str[50]; + snprintf(str, sizeof(str), "{{value_json['%d'].value}}", sensor.id()); + config["val_tpl"] = str; - snprintf(str, sizeof(str), "Analog Sensor %s", sensor.name().c_str()); - config["name"] = str; + snprintf(str, sizeof(str), "Analog Sensor %s", sensor.name().c_str()); + config["name"] = str; - snprintf(str, sizeof(str), "analogsensor_%d", sensor.id()); - config["uniq_id"] = str; + snprintf(str, sizeof(str), "analogsensor_%d", sensor.id()); + config["uniq_id"] = str; - JsonObject dev = config.createNestedObject("dev"); - JsonArray ids = dev.createNestedArray("ids"); - ids.add("ems-esp"); + JsonObject dev = config.createNestedObject("dev"); + JsonArray ids = dev.createNestedArray("ids"); + ids.add("ems-esp"); - char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; - snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%d/config", Mqtt::base().c_str(), sensor.id()); + char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; + snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%d/config", Mqtt::base().c_str(), sensor.id()); - Mqtt::publish_ha(topic, config.as()); + Mqtt::publish_ha(topic, config.as()); - sensor.ha_registered = true; - } + sensor.ha_registered = true; } + } else { // not nested doc[sensor.name()] = sensor.value(); } } } + Mqtt::publish(F("analogsensor_data"), doc.as()); } // called from emsesp.cpp, similar to the emsdevice->get_value_info // searches by name -bool AnalogSensor::get_value_info(JsonObject & output, const char * cmd, const int8_t id) { +bool AnalogSensor::get_value_info(JsonObject & output, const char * cmd, const int8_t id) const { for (const auto & sensor : sensors_) { if (strcmp(cmd, sensor.name().c_str()) == 0) { output["id"] = sensor.id(); @@ -455,8 +452,8 @@ bool AnalogSensor::get_value_info(JsonObject & output, const char * cmd, const i // creates JSON doc from values // returns false if there are no sensors -bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject & output) { - if (sensors_.size() == 0) { +bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject & output) const { + if (sensors_.empty()) { return false; } @@ -532,7 +529,7 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t id) { return true; } else if (sensor.type() == AnalogType::DIGITAL_OUT) { uint8_t v = val; - if ((sensor.id() == 25 || sensor.id() == 26)) { + if (sensor.id() == 25 || sensor.id() == 26) { sensor.set_offset(v); sensor.set_value(v); pinMode(sensor.id(), OUTPUT); @@ -573,7 +570,6 @@ bool AnalogSensor::command_commands(const char * value, const int8_t id, JsonObj // hard coded tests #ifdef EMSESP_DEBUG void AnalogSensor::test() { - // Sensor(const uint8_t id, const std::string & name, const float offset, const float factor, const uint8_t uom, const int8_t type); sensors_.emplace_back(36, "test12", 0, 0.1, 17, AnalogType::ADC); sensors_.back().set_value(12.4); diff --git a/src/analogsensor.h b/src/analogsensor.h index e48acd7e9..fc7f72ea6 100644 --- a/src/analogsensor.h +++ b/src/analogsensor.h @@ -127,38 +127,38 @@ class AnalogSensor { void start(); void loop(); - void publish_sensor(const Sensor & sensor); + void publish_sensor(const Sensor & sensor) const; void publish_values(const bool force); void reload(); bool updated_values(); // return back reference to the sensor list, used by other classes - const std::vector sensors() const { + std::vector sensors() const { return sensors_; } - uint32_t reads() { + uint32_t reads() const { return sensorreads_; } - uint32_t fails() { + uint32_t fails() const { return sensorfails_; } - bool analog_enabled() { + bool analog_enabled() const { return (analog_enabled_); } - bool have_sensors() { - return (sensors_.size() > 0); + bool have_sensors() const { + return (!sensors_.empty()); } - size_t no_sensors() { + size_t no_sensors() const { return sensors_.size(); } bool update(uint8_t id, const std::string & name, float offset, float factor, uint8_t uom, int8_t type); - 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) const; #ifdef EMSESP_DEBUG void test(); @@ -170,10 +170,10 @@ class AnalogSensor { static uuid::log::Logger logger_; - void remove_ha_topic(const uint8_t id); + void remove_ha_topic(const uint8_t id) const; bool command_setvalue(const char * value, const int8_t id); void measure(); - bool command_info(const char * value, const int8_t id, JsonObject & output); + bool command_info(const char * value, const int8_t id, JsonObject & output) const; bool command_commands(const char * value, const int8_t id, JsonObject & output); std::vector sensors_; // our list of sensors diff --git a/src/command.cpp b/src/command.cpp index 0efece5cd..75ee3ccc1 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -39,13 +39,13 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec } // check first if it's from API, if so strip the "api/" - if ((p.paths().front() == "api")) { + if (p.paths().front() == "api") { p.paths().erase(p.paths().begin()); } else { // not /api, so must be MQTT path. Check for base and remove it. if (!strncmp(path, Mqtt::base().c_str(), Mqtt::base().length())) { char new_path[Mqtt::MQTT_TOPIC_MAX_SIZE]; - strncpy(new_path, path, sizeof(new_path)); + strlcpy(new_path, path, sizeof(new_path)); p.parse(new_path + Mqtt::base().length() + 1); // re-parse the stripped path } else { return message(CommandRet::ERROR, "unrecognized path", output); // error @@ -151,7 +151,7 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec return_code = Command::call(device_type, command_p, Helpers::itoa((int16_t)data.as(), data_str), is_admin, id_n, output); } else if (data.is()) { char data_str[10]; - return_code = Command::call(device_type, command_p, Helpers::render_value(data_str, (float)data.as(), 2), is_admin, id_n, output); + return_code = Command::call(device_type, command_p, Helpers::render_value(data_str, data.as(), 2), is_admin, id_n, output); } else if (data.isNull()) { return_code = Command::call(device_type, command_p, "", is_admin, id_n, output); // empty, will do a query instead } else { @@ -160,22 +160,19 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec return return_code; } -const std::string Command::return_code_string(const uint8_t return_code) { +std::string Command::return_code_string(const uint8_t return_code) { switch (return_code) { case CommandRet::ERROR: return read_flash_string(F("Error")); - break; case CommandRet::OK: return read_flash_string(F("OK")); - break; case CommandRet::NOT_FOUND: return read_flash_string(F("Not Found")); - break; case CommandRet::NOT_ALLOWED: return read_flash_string(F("Not Authorized")); - break; case CommandRet::FAIL: return read_flash_string(F("Failed")); + default: break; } char s[4]; @@ -191,7 +188,7 @@ const char * Command::parse_command_string(const char * command, int8_t & id) { // make a copy of the string command for parsing char command_s[100]; - strncpy(command_s, command, sizeof(command_s)); + strlcpy(command_s, command, sizeof(command_s)); // look for a delimeter and split the string char * p = command_s; @@ -365,7 +362,7 @@ bool Command::list(const uint8_t device_type, JsonObject & output) { } sorted_cmds.sort(); - for (auto & cl : sorted_cmds) { + 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 == read_flash_string(cf.cmd_))) { output[cl] = cf.description_; @@ -394,7 +391,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo // if not in verbose mode, just print them on a single line if (!verbose) { - for (auto & cl : sorted_cmds) { + for (const auto & cl : sorted_cmds) { shell.print(cl); shell.print(" "); } @@ -404,7 +401,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo // verbose mode shell.println(); - for (auto & cl : sorted_cmds) { + for (const auto & cl : sorted_cmds) { // find and print the description for (const auto & cf : cmdfunctions_) { if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == read_flash_string(cf.cmd_))) { @@ -462,7 +459,7 @@ bool Command::device_has_commands(const uint8_t device_type) { } for (const auto & emsdevice : EMSESP::emsdevices) { - if ((emsdevice) && (emsdevice->device_type() == device_type)) { + if (emsdevice && (emsdevice->device_type() == device_type)) { // device found, now see if it has any commands for (const auto & cf : cmdfunctions_) { if (cf.device_type_ == device_type) { @@ -488,7 +485,7 @@ void Command::show_devices(uuid::console::Shell & shell) { for (const auto & device_class : EMSFactory::device_handlers()) { for (const auto & emsdevice : EMSESP::emsdevices) { - if ((emsdevice) && (emsdevice->device_type() == device_class.first) && (device_has_commands(device_class.first))) { + if (emsdevice && (emsdevice->device_type() == device_class.first) && (device_has_commands(device_class.first))) { shell.printf("%s ", EMSdevice::device_type_2_device_name(device_class.first).c_str()); break; // we only want to show one (not multiple of the same device types) } @@ -541,7 +538,7 @@ void Command::show_all(uuid::console::Shell & shell) { // e.g. //one/two////three/// becomes /one/two/three std::string SUrlParser::path() { std::string s = "/"; // set up the beginning slash - for (std::string & f : m_folders) { + for (const std::string & f : m_folders) { s += f; s += "/"; } @@ -554,6 +551,14 @@ SUrlParser::SUrlParser(const char * uri) { } bool SUrlParser::parse(const char * uri) { + if (uri == nullptr) { + return false; + } + + if (*uri == '\0') { + return false; + } + m_folders.clear(); m_keysvalues.clear(); enum Type { begin, folder, param, value }; @@ -563,54 +568,53 @@ bool SUrlParser::parse(const char * uri) { enum Type t = Type::begin; std::string last_param; - if (c != nullptr || *c != '\0') { - do { - if (*c == '/') { - if (s.length() > 0) { - m_folders.push_back(s); - s.clear(); - } - t = Type::folder; - } else if (*c == '?' && (t == Type::folder || t == Type::begin)) { - if (s.length() > 0) { - m_folders.push_back(s); - s.clear(); - } - t = Type::param; - } else if (*c == '=' && (t == Type::param || t == Type::begin)) { + do { + if (*c == '/') { + if (s.length() > 0) { + m_folders.push_back(s); + s.clear(); + } + t = Type::folder; + } else if (*c == '?' && (t == Type::folder || t == Type::begin)) { + if (s.length() > 0) { + m_folders.push_back(s); + s.clear(); + } + t = Type::param; + } else if (*c == '=' && (t == Type::param || t == Type::begin)) { + m_keysvalues[s] = ""; + last_param = s; + s.clear(); + t = Type::value; + } else if (*c == '&' && (t == Type::value || t == Type::param || t == Type::begin)) { + if (t == Type::value) { + m_keysvalues[last_param] = s; + } else if ((t == Type::param || t == Type::begin) && (s.length() > 0)) { m_keysvalues[s] = ""; last_param = s; - s.clear(); - t = Type::value; - } else if (*c == '&' && (t == Type::value || t == Type::param || t == Type::begin)) { - if (t == Type::value) { - m_keysvalues[last_param] = s; - } else if ((t == Type::param || t == Type::begin) && (s.length() > 0)) { - m_keysvalues[s] = ""; - last_param = s; - } - t = Type::param; - s.clear(); - } else if (*c == '\0' && s.length() > 0) { - if (t == Type::value) { - m_keysvalues[last_param] = s; - } else if (t == Type::folder || t == Type::begin) { - m_folders.push_back(s); - } else if (t == Type::param) { - m_keysvalues[s] = ""; - last_param = s; - } - s.clear(); - } else if (*c == '\0' && s.length() == 0) { - if (t == Type::param && last_param.length() > 0) { - m_keysvalues[last_param] = ""; - } - s.clear(); - } else { - s += *c; } - } while (*c++ != '\0'); - } + t = Type::param; + s.clear(); + } else if (*c == '\0' && s.length() > 0) { + if (t == Type::value) { + m_keysvalues[last_param] = s; + } else if (t == Type::folder || t == Type::begin) { + m_folders.push_back(s); + } else if (t == Type::param) { + m_keysvalues[s] = ""; + last_param = s; + } + s.clear(); + } else if (*c == '\0' && s.length() == 0) { + if (t == Type::param && last_param.length() > 0) { + m_keysvalues[last_param] = ""; + } + s.clear(); + } else { + s += *c; + } + } while (*c++ != '\0'); + return true; } diff --git a/src/command.h b/src/command.h index bc1bf7e7c..3ff3c3c38 100644 --- a/src/command.h +++ b/src/command.h @@ -125,22 +125,22 @@ class Command { static const char * parse_command_string(const char * command, int8_t & id); - static const std::string return_code_string(const uint8_t return_code); + static std::string return_code_string(const uint8_t return_code); private: static uuid::log::Logger logger_; static std::vector cmdfunctions_; // the list of commands - inline static uint8_t message(uint8_t error_code, const char * message, JsonObject & output) { + inline static uint8_t message(uint8_t error_code, const char * message, const JsonObject & output) { output.clear(); - output["message"] = (const char *)message; + output["message"] = message; return error_code; } }; -typedef std::unordered_map KeyValueMap_t; -typedef std::vector Folder_t; +using KeyValueMap_t = std::unordered_map; +using Folder_t = std::vector; class SUrlParser { private: @@ -148,7 +148,7 @@ class SUrlParser { Folder_t m_folders; public: - SUrlParser(){}; + SUrlParser() = default; SUrlParser(const char * url); bool parse(const char * url); diff --git a/src/console.cpp b/src/console.cpp index e17f357f1..096052954 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -31,9 +31,8 @@ std::shared_ptr EMSESPShell::commands = [] { return commands; }(); -static std::shared_ptr shell; - -std::vector EMSESPStreamConsole::ptys_; +std::shared_ptr shell; +std::vector EMSESPStreamConsole::ptys_; #ifndef EMSESP_STANDALONE uuid::telnet::TelnetService telnet_([](Stream & stream, const IPAddress & addr, uint16_t port) -> std::shared_ptr { @@ -447,7 +446,7 @@ void Console::load_standard_commands(unsigned int context) { flash_string_vector{F("test")}, flash_string_vector{F_(name_optional), F_(data_optional)}, [](Shell & shell, const std::vector & arguments) { - if (arguments.size() == 0) { + if (arguments.empty()) { Test::run_test(shell, "default"); } else if (arguments.size() == 1) { Test::run_test(shell, arguments.front()); @@ -467,7 +466,7 @@ void Console::load_standard_commands(unsigned int context) { flash_string_vector{F_(debug)}, flash_string_vector{F_(name_optional)}, [](Shell & shell, const std::vector & arguments) { - if (arguments.size() == 0) { + if (arguments.empty()) { Test::debug(shell, "default"); } else { Test::debug(shell, arguments.front()); @@ -515,10 +514,7 @@ void Console::load_standard_commands(unsigned int context) { EMSESPShell::commands->add_command(context, CommandFlags::USER, flash_string_vector{F_(exit)}, - [=](Shell & shell, const std::vector & arguments __attribute__((unused))) { - shell.stop(); - // shell.exit_context(); - }); + [=](Shell & shell, const std::vector & arguments __attribute__((unused))) { shell.stop(); }); EMSESPShell::commands->add_command(context, CommandFlags::USER, diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index 0a69b6f17..a71c79a3d 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -354,7 +354,7 @@ bool DallasSensor::command_commands(const char * value, const int8_t id, JsonObj // creates JSON doc from values // returns false if there are no sensors bool DallasSensor::command_info(const char * value, const int8_t id, JsonObject & output) { - if (sensors_.size() == 0) { + if (sensors_.empty()) { return false; } @@ -435,7 +435,6 @@ void DallasSensor::publish_values(const bool force) { for (const auto & sensor : sensors_) { publish_sensor(sensor); } - // return; } DynamicJsonDocument doc(120 * num_sensors); @@ -536,8 +535,8 @@ std::string DallasSensor::Sensor::name() const { bool DallasSensor::Sensor::apply_customization() { EMSESP::webCustomizationService.read([&](WebCustomization & settings) { auto sensors = settings.sensorCustomizations; - if (sensors.size() != 0) { - for (auto & sensor : sensors) { + if (sensors.empty()) { + for (const auto & sensor : sensors) { #if defined(EMSESP_DEBUG) LOG_DEBUG(F("Loading customization for dallas sensor %s"), sensor.id_str.c_str()); #endif diff --git a/src/dallassensor.h b/src/dallassensor.h index f6add0adf..c9567e32f 100644 --- a/src/dallassensor.h +++ b/src/dallassensor.h @@ -85,7 +85,7 @@ class DallasSensor { bool get_value_info(JsonObject & output, const char * cmd, const int8_t id); // return back reference to the sensor list, used by other classes - const std::vector sensors() const { + std::vector sensors() const { return sensors_; } @@ -102,7 +102,7 @@ class DallasSensor { } bool have_sensors() { - return (sensors_.size() > 0); + return (!sensors_.empty()); } size_t no_sensors() { diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 4bc65ecb0..00189f703 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -532,7 +532,7 @@ void Boiler::process_UBAParameterWW(std::shared_ptr telegram) { has_update(telegram, wwDisinfectionTemp_, 8); has_bitupdate(telegram, wwChargeType_, 10, 0); // 0 = charge pump, 0xff = 3-way valve - uint8_t wwComfort; + uint8_t wwComfort = EMS_VALUE_UINT_NOTSET; telegram->read_value(wwComfort, 9); if (wwComfort == 0) { wwComfort = 0; // Hot @@ -594,7 +594,7 @@ void Boiler::process_UBAMonitorFastPlus(std::shared_ptr telegram // read 3 char service code / installation status as appears on the display if ((telegram->message_length > 3) && (telegram->offset == 0)) { - char serviceCode[4]; + char serviceCode[4] = {0}; telegram->read_value(serviceCode[0], 1); serviceCode[0] = (serviceCode[0] == (char)0xF0) ? '~' : serviceCode[0]; telegram->read_value(serviceCode[1], 2); @@ -878,19 +878,19 @@ void Boiler::process_UBAErrorMessage(std::shared_ptr telegram) { if (telegram->message_data[4] & 0x80) { // valid date static uint32_t lastCodeDate_ = 0; // last code date - char code[3]; - uint16_t codeNo; - code[0] = telegram->message_data[0]; - code[1] = telegram->message_data[1]; - code[2] = 0; + char code[3] = {0}; + uint16_t codeNo = EMS_VALUE_SHORT_NOTSET; + code[0] = telegram->message_data[0]; + code[1] = telegram->message_data[1]; + code[2] = 0; telegram->read_value(codeNo, 2); - uint16_t year = (telegram->message_data[4] & 0x7F) + 2000; - uint8_t month = telegram->message_data[5]; - uint8_t day = telegram->message_data[7]; - uint8_t hour = telegram->message_data[6]; - uint8_t min = telegram->message_data[8]; - uint32_t date = (year - 2000) * 535680UL + month * 44640UL + day * 1440UL + hour * 60 + min; - uint16_t duration; + uint16_t year = (telegram->message_data[4] & 0x7F) + 2000; + uint8_t month = telegram->message_data[5]; + uint8_t day = telegram->message_data[7]; + uint8_t hour = telegram->message_data[6]; + uint8_t min = telegram->message_data[8]; + uint32_t date = (year - 2000) * 535680UL + month * 44640UL + day * 1440UL + hour * 60 + min; + uint16_t duration = EMS_VALUE_SHORT_NOTSET; telegram->read_value(duration, 9); // store only the newest code from telegrams 10 and 11 if (date > lastCodeDate_) { @@ -908,12 +908,12 @@ void Boiler::process_UBAErrorMessage2(std::shared_ptr telegram) return; } - char code[sizeof(lastCode_)]; - uint16_t codeNo; - code[0] = telegram->message_data[5]; - code[1] = telegram->message_data[6]; - code[2] = telegram->message_data[7]; - code[3] = 0; + char code[sizeof(lastCode_)] = {0}; + uint16_t codeNo = EMS_VALUE_SHORT_NOTSET; + code[0] = telegram->message_data[5]; + code[1] = telegram->message_data[6]; + code[2] = telegram->message_data[7]; + code[3] = 0; telegram->read_value(codeNo, 8); // check for valid date, https://github.com/emsesp/EMS-ESP32/issues/204 @@ -1486,8 +1486,12 @@ bool Boiler::set_reset(const char * value, const int8_t id) { return false; } -//maintenance +// maintenance bool Boiler::set_maintenance(const char * value, const int8_t id) { + if (value == nullptr) { + return false; + } + std::string s; if (Helpers::value2string(value, s)) { if (s == Helpers::toLower(read_flash_string(F_(reset)))) { @@ -1549,7 +1553,7 @@ bool Boiler::set_maintenancetime(const char * value, const int8_t id) { //maintenance bool Boiler::set_maintenancedate(const char * value, const int8_t id) { - if (strlen(value) == 10) { // date + if ((value != nullptr) && strlen(value) == 10) { // date uint8_t day = (value[0] - '0') * 10 + (value[1] - '0'); uint8_t month = (value[3] - '0') * 10 + (value[4] - '0'); uint8_t year = (uint8_t)(Helpers::atoint(&value[6]) - 2000); diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index f8f505aa5..35a8fa3b6 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -293,7 +293,7 @@ std::shared_ptr Thermostat::heating_circuit(std::sha */ // if it's the first set the status flag - if (heating_circuits_.size() == 0) { + if (heating_circuits_.empty()) { strlcpy(status_, "online", sizeof(status_)); } @@ -333,7 +333,7 @@ std::shared_ptr Thermostat::heating_circuit(std::sha } // add the HVAC/Climate HA component for the HC -void Thermostat::add_ha_climate(std::shared_ptr hc) { +void Thermostat::add_ha_climate(std::shared_ptr hc) const { if (!Mqtt::ha_enabled()) { hc->climate = EMS_VALUE_UINT_NOTSET; return; @@ -452,65 +452,44 @@ std::string Thermostat::mode_tostring(uint8_t mode) { switch (mode) { case HeatingCircuit::Mode::OFF: return read_flash_string(F_(off)); - break; case HeatingCircuit::Mode::MANUAL: return read_flash_string(F_(manual)); - break; case HeatingCircuit::Mode::DAY: return read_flash_string(F_(day)); - break; case HeatingCircuit::Mode::NIGHT: return read_flash_string(F_(night)); - break; case HeatingCircuit::Mode::ECO: return read_flash_string(F_(eco)); - break; case HeatingCircuit::Mode::COMFORT: return read_flash_string(F_(comfort)); - break; case HeatingCircuit::Mode::HEAT: return read_flash_string(F_(heat)); - break; case HeatingCircuit::Mode::HOLIDAY: return read_flash_string(F_(holiday)); - break; case HeatingCircuit::Mode::NOFROST: return read_flash_string(F_(nofrost)); - break; case HeatingCircuit::Mode::AUTO: return read_flash_string(F_(auto)); - break; case HeatingCircuit::Mode::SUMMER: return read_flash_string(F_(summer)); - break; case HeatingCircuit::Mode::OFFSET: return read_flash_string(F_(offset)); - break; case HeatingCircuit::Mode::DESIGN: return read_flash_string(F_(design)); - break; case HeatingCircuit::Mode::MINFLOW: return read_flash_string(F_(minflow)); - break; case HeatingCircuit::Mode::MAXFLOW: return read_flash_string(F_(maxflow)); - break; case HeatingCircuit::Mode::ROOMINFLUENCE: return read_flash_string(F_(roominfluence[0])); - break; case HeatingCircuit::Mode::FLOWOFFSET: return read_flash_string(F_(flowtempoffset[0])); - break; case HeatingCircuit::Mode::TEMPAUTO: return read_flash_string(F_(tempauto)); - break; case HeatingCircuit::Mode::NOREDUCE: return read_flash_string(F_(noreduce)); - break; default: - case HeatingCircuit::Mode::UNKNOWN: return read_flash_string(F_(unknown)); - break; } } @@ -1237,18 +1216,18 @@ void Thermostat::process_RCErrorMessage(std::shared_ptr telegram // data: displaycode(2), errornumber(2), year, month, hour, day, minute, duration(2), src-addr if (telegram->message_data[4] & 0x80) { // valid date - char code[sizeof(lastCode_)]; - uint16_t codeNo = EMS_VALUE_USHORT_NOTSET; - code[0] = telegram->message_data[0]; - code[1] = telegram->message_data[1]; - code[2] = 0; + char code[sizeof(lastCode_)] = {0}; + uint16_t codeNo = EMS_VALUE_USHORT_NOTSET; + code[0] = telegram->message_data[0]; + code[1] = telegram->message_data[1]; + code[2] = 0; telegram->read_value(codeNo, 2); - uint16_t year = (telegram->message_data[4] & 0x7F) + 2000; - uint8_t month = telegram->message_data[5]; - uint8_t day = telegram->message_data[7]; - uint8_t hour = telegram->message_data[6]; - uint8_t min = telegram->message_data[8]; - uint16_t duration; + uint16_t year = (telegram->message_data[4] & 0x7F) + 2000; + uint8_t month = telegram->message_data[5]; + uint8_t day = telegram->message_data[7]; + uint8_t hour = telegram->message_data[6]; + uint8_t min = telegram->message_data[8]; + uint16_t duration = EMS_VALUE_SHORT_NOTSET; telegram->read_value(duration, 9); snprintf(&code[2], sizeof(code) - 2, "(%d) %02d.%02d.%d %02d:%02d (%d min)", codeNo, day, month, year, hour, min, duration); has_update(lastCode_, code, sizeof(lastCode_)); @@ -1292,7 +1271,7 @@ bool Thermostat::set_calinttemp(const char * value, const int8_t id) { return false; } - int8_t t = (int8_t)(ct * 10); + auto t = (int8_t)(ct * 10); LOG_DEBUG(F("Calibrating internal temperature to %d.%d C"), t / 10, t < 0 ? -t % 10 : t % 10); if (model() == EMS_DEVICE_FLAG_RC10) { @@ -1658,9 +1637,11 @@ bool Thermostat::set_wwCircProg(const char * value, const int8_t id) { bool Thermostat::set_holiday(const char * value, const int8_t id, const bool vacation) { uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; std::shared_ptr hc = heating_circuit(hc_num); - if (hc == nullptr) { + + if ((hc == nullptr) || (value == nullptr)) { return false; } + if (strlen(value) != 21) { return false; } @@ -1805,7 +1786,7 @@ bool Thermostat::set_roominfl_factor(const char * value, const int8_t id) { // sets the thermostat working mode, where mode is a string // converts string mode to HeatingCircuit::Mode bool Thermostat::set_mode(const char * value, const int8_t id) { - if (strlen(value) >= 20) { + if ((value == nullptr) || (strlen(value) >= 20)) { return false; } @@ -1907,9 +1888,7 @@ bool Thermostat::set_mode_n(const uint8_t mode, const uint8_t hc_num) { set_mode_value = 1; break; - default: - case HeatingCircuit::Mode::AUTO: - case HeatingCircuit::Mode::ECO: + default: // AUTO & ECO set_mode_value = 2; break; } @@ -2133,7 +2112,7 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char } const char * s_mode = doc["mode"]; const char * s_time = doc["time"]; - if ((model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N)) { + if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) { bool b; if (Helpers::value2bool(s_mode, b)) { on = b ? 1 : 0; @@ -2348,6 +2327,8 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co offset = 4; } break; + default: + break; } } else if (model == EMS_DEVICE_FLAG_RC20) { switch (mode) { @@ -2381,6 +2362,8 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co offset = EMS_OFFSET_RC20Set_temp_auto; } break; + default: + break; } } else if (model == EMS_DEVICE_FLAG_RC30) { @@ -2460,7 +2443,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co factor = 1; break; default: - case HeatingCircuit::Mode::AUTO: + // HeatingCircuit::Mode::AUTO: uint8_t mode_ = hc->get_mode(); if (mode_ == HeatingCircuit::Mode::MANUAL) { offset = 0x0A; // manual offset @@ -2499,7 +2482,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co offset = EMS_OFFSET_RC20_2_Set_temp_day; break; default: - case HeatingCircuit::Mode::AUTO: // automatic selection, if no type is defined, we use the standard code + // automatic selection, if no type is defined, we use the standard code uint8_t mode_ = hc->get_mode(); if (mode_ == HeatingCircuit::Mode::NIGHT) { offset = EMS_OFFSET_RC20_2_Set_temp_night; @@ -2570,7 +2553,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co factor = 1; break; default: - case HeatingCircuit::Mode::AUTO: // automatic selection, if no type is defined, we use the standard code + // automatic selection, if no type is defined, we use the standard code validate_typeid = monitor_typeids[hc->hc()]; //get setpoint roomtemp back if (model == EMS_DEVICE_FLAG_RC35) { uint8_t mode_ = hc->get_mode(); @@ -2606,7 +2589,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co offset = EMS_OFFSET_JunkersSetMessage_day_temp; break; default: - case HeatingCircuit::Mode::AUTO: // automatic selection, if no type is defined, we use the standard code + // automatic selection, if no type is defined, we use the standard code uint8_t modetype = hc->get_mode_type(); if (modetype == HeatingCircuit::Mode::NIGHT || modetype == HeatingCircuit::Mode::ECO) { offset = EMS_OFFSET_JunkersSetMessage_night_temp; @@ -2633,7 +2616,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co offset = EMS_OFFSET_JunkersSetMessage2_heat_temp; break; default: - case HeatingCircuit::Mode::AUTO: // automatic selection, if no type is defined, we use the standard code + // automatic selection, if no type is defined, we use the standard code uint8_t modetype = hc->get_mode_type(); if (modetype == HeatingCircuit::Mode::NIGHT || modetype == HeatingCircuit::Mode::ECO) { offset = EMS_OFFSET_JunkersSetMessage2_eco_temp; @@ -2651,7 +2634,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co if (offset != -1) { // add the write command to the Tx queue. value is *2 // post validate is the corresponding monitor or set type IDs as they can differ per model - write_command(set_typeid, offset, (uint8_t)((float)temperature * (float)factor), validate_typeid); + write_command(set_typeid, offset, (uint8_t)(temperature * (float)factor), validate_typeid); return true; } @@ -3300,6 +3283,8 @@ void Thermostat::register_device_values_hc(std::shared_ptrprogram, DeviceValueType::ENUM, FL_(enum_progMode4), FL_(program), DeviceValueUOM::NONE, MAKE_CF_CB(set_program)); register_device_value(tag, &hc->remotetemp, DeviceValueType::SHORT, FL_(div10), FL_(remotetemp), DeviceValueUOM::DEGREES); break; + default: + break; } } diff --git a/src/devices/thermostat.h b/src/devices/thermostat.h index e10eccda8..8bd467b46 100644 --- a/src/devices/thermostat.h +++ b/src/devices/thermostat.h @@ -93,7 +93,7 @@ class Thermostat : public EMSdevice { } // determines if the heating circuit is actually present and has data - bool is_active() { + bool is_active() const { return Helpers::hasValue(selTemp); } @@ -292,7 +292,7 @@ class Thermostat : public EMSdevice { void register_device_values_hc(std::shared_ptr hc); - void add_ha_climate(std::shared_ptr hc); + void add_ha_climate(std::shared_ptr hc) const; void process_RCOutdoorTemp(std::shared_ptr telegram); void process_IBASettings(std::shared_ptr telegram); diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index db2c5586a..7aebfdb85 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -34,7 +34,7 @@ uint8_t EMSdevice::count_entities() { } // see if there are entities, excluding any commands -bool EMSdevice::has_entities() { +bool EMSdevice::has_entities() const { for (const auto & dv : devicevalues_) { if (dv.type != DeviceValueType::CMD) { return true; @@ -43,107 +43,71 @@ bool EMSdevice::has_entities() { return false; } -const std::string EMSdevice::tag_to_string(uint8_t tag) { +std::string EMSdevice::tag_to_string(uint8_t tag) { return read_flash_string(DeviceValue::DeviceValueTAG_s[tag]); } -const std::string EMSdevice::tag_to_mqtt(uint8_t tag) { +std::string EMSdevice::tag_to_mqtt(uint8_t tag) { return read_flash_string(DeviceValue::DeviceValueTAG_mqtt[tag]); } -const std::string EMSdevice::uom_to_string(uint8_t uom) { +std::string EMSdevice::uom_to_string(uint8_t uom) { if (EMSESP::system_.fahrenheit() && (uom == DeviceValueUOM::DEGREES || uom == DeviceValueUOM::DEGREES_R)) { return read_flash_string(DeviceValue::DeviceValueUOM_s[DeviceValueUOM::FAHRENHEIT]); } return read_flash_string(DeviceValue::DeviceValueUOM_s[uom]); } -const std::string EMSdevice::brand_to_string() const { +std::string EMSdevice::brand_to_string() const { switch (brand_) { case EMSdevice::Brand::BOSCH: return read_flash_string(F("Bosch")); - break; case EMSdevice::Brand::JUNKERS: return read_flash_string(F("Junkers")); - break; case EMSdevice::Brand::BUDERUS: return read_flash_string(F("Buderus")); - break; case EMSdevice::Brand::NEFIT: return read_flash_string(F("Nefit")); - break; case EMSdevice::Brand::SIEGER: return read_flash_string(F("Sieger")); - break; case EMSdevice::Brand::WORCESTER: return read_flash_string(F("Worcester")); - break; case EMSdevice::Brand::IVT: return read_flash_string(F("IVT")); - break; - case EMSdevice::Brand::NO_BRAND: default: return read_flash_string(F("")); - break; } - - return std::string{}; } // returns the name of the MQTT topic to use for a specific device, without the base -const std::string EMSdevice::device_type_2_device_name(const uint8_t device_type) { +std::string EMSdevice::device_type_2_device_name(const uint8_t device_type) { switch (device_type) { case DeviceType::SYSTEM: return read_flash_string(F_(system)); - break; - case DeviceType::BOILER: return read_flash_string(F_(boiler)); - break; - case DeviceType::THERMOSTAT: return read_flash_string(F_(thermostat)); - break; - case DeviceType::HEATPUMP: return read_flash_string(F_(heatpump)); - break; - case DeviceType::SOLAR: return read_flash_string(F_(solar)); - break; - case DeviceType::CONNECT: return read_flash_string(F_(connect)); - break; - case DeviceType::MIXER: return read_flash_string(F_(mixer)); - break; - case DeviceType::DALLASSENSOR: return read_flash_string(F_(dallassensor)); - break; - case DeviceType::ANALOGSENSOR: return read_flash_string(F_(analogsensor)); - break; - case DeviceType::CONTROLLER: return read_flash_string(F_(controller)); - break; - case DeviceType::SWITCH: return read_flash_string(F_(switch)); - break; - case DeviceType::GATEWAY: return read_flash_string(F_(gateway)); - break; - default: return read_flash_string(F_(unknown)); - break; } } @@ -196,7 +160,7 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) { } // return name of the device type, capitalized -const std::string EMSdevice::device_type_name() const { +std::string EMSdevice::device_type_name() const { std::string s = device_type_2_device_name(device_type_); s[0] = toupper(s[0]); return s; @@ -207,34 +171,25 @@ uint8_t EMSdevice::decode_brand(uint8_t value) { switch (value) { case 1: return EMSdevice::Brand::BOSCH; - break; case 2: return EMSdevice::Brand::JUNKERS; - break; case 3: return EMSdevice::Brand::BUDERUS; - break; case 4: return EMSdevice::Brand::NEFIT; - break; case 5: return EMSdevice::Brand::SIEGER; - break; case 11: return EMSdevice::Brand::WORCESTER; - break; case 13: return EMSdevice::Brand::IVT; - break; - case 0: default: return EMSdevice::Brand::NO_BRAND; - break; } } // returns string of a human friendly description of the EMS device -const std::string EMSdevice::to_string() const { +std::string EMSdevice::to_string() const { // for devices that haven't been lookup yet, don't show all details if (product_id_ == 0) { return name_ + " (DeviceID:" + Helpers::hextoa(device_id_) + ")"; @@ -249,7 +204,7 @@ const std::string EMSdevice::to_string() const { } // returns out brand + device name -const std::string EMSdevice::to_string_short() const { +std::string EMSdevice::to_string_short() const { if (brand_ == Brand::NO_BRAND) { return device_type_name() + ": " + name_; } @@ -280,8 +235,8 @@ void EMSdevice::toggle_fetch(uint16_t telegram_id, bool toggle) { } // get status of automatic fetch for a telegramID -bool EMSdevice::is_fetch(uint16_t telegram_id) { - for (auto & tf : telegram_functions_) { +bool EMSdevice::is_fetch(uint16_t telegram_id) const { + for (const auto & tf : telegram_functions_) { if (tf.telegram_type_id_ == telegram_id) { return tf.fetch_; } @@ -301,7 +256,7 @@ bool EMSdevice::has_tag(const uint8_t tag) { // list of registered device entries // called from the command 'entities' -void EMSdevice::list_device_entries(JsonObject & output) { +void EMSdevice::list_device_entries(JsonObject & output) const { for (const auto & dv : devicevalues_) { if (dv.has_state(DeviceValueState::DV_VISIBLE) && dv.type != DeviceValueType::CMD && dv.full_name) { // if we have a tag prefix it @@ -326,8 +281,8 @@ void EMSdevice::list_device_entries(JsonObject & output) { } // list all the telegram type IDs for this device -void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) { - if (telegram_functions_.size() == 0) { +void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) const { + if (telegram_functions_.empty()) { return; } /* @@ -393,7 +348,7 @@ char * EMSdevice::show_telegram_handlers(char * result, uint8_t handlers) { } // list all the mqtt handlers for this device -void EMSdevice::show_mqtt_handlers(uuid::console::Shell & shell) { +void EMSdevice::show_mqtt_handlers(uuid::console::Shell & shell) const { Mqtt::show_topic_handlers(shell, device_type_); } @@ -426,7 +381,7 @@ void EMSdevice::register_device_value(uint8_t tag, uint16_t max) { // initialize the device value depending on it's type if (type == DeviceValueType::STRING) { - *(char *)(value_p) = {'\0'}; + *(char *)(value_p) = {'\0'}; // this is important for string functions like strlen() to work later } else if (type == DeviceValueType::INT) { *(int8_t *)(value_p) = EMS_VALUE_INT_NOTSET; } else if (type == DeviceValueType::SHORT) { @@ -447,7 +402,7 @@ void EMSdevice::register_device_value(uint8_t tag, uint8_t i = 0; while (options[i++]) { options_size++; - }; + } } // this is the unique id set for the device entity. it's a simple sequence number @@ -456,9 +411,6 @@ void EMSdevice::register_device_value(uint8_t tag, // determine state uint8_t state = DeviceValueState::DV_VISIBLE; // default to visible - // if (!full_name) { - // state = DeviceValueState::DV_DEFAULT; // don't show if the full_name is empty - // } else { // scan through customizations to see if it's on the exclusion list by matching the productID and deviceID EMSESP::webCustomizationService.read([&](WebCustomization & settings) { for (EntityCustomization entityCustomization : settings.entityCustomizations) { @@ -472,7 +424,6 @@ void EMSdevice::register_device_value(uint8_t tag, } } }); - // } // add the device devicevalues_.emplace_back(device_type_, tag, value_p, type, options, options_size, short_name, full_name, uom, 0, has_cmd, min, max, state, dv_id); @@ -536,7 +487,7 @@ void EMSdevice::register_device_value(uint8_t tag, } // check if value is visible -bool EMSdevice::is_visible(void * value_p) { +bool EMSdevice::is_visible(const void * value_p) const { for (const auto & dv : devicevalues_) { if (dv.value_p == value_p) { return dv.has_state(DeviceValueState::DV_VISIBLE); @@ -546,10 +497,11 @@ bool EMSdevice::is_visible(void * value_p) { } // publish a single value on change -void EMSdevice::publish_value(void * value_p) { +void EMSdevice::publish_value(void * value_p) const { if (!Mqtt::publish_single() || value_p == nullptr) { return; } + for (const auto & dv : devicevalues_) { if (dv.value_p == value_p && dv.has_state(DeviceValueState::DV_VISIBLE)) { char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; @@ -593,7 +545,6 @@ void EMSdevice::publish_value(void * value_p) { } break; } - case DeviceValueType::USHORT: Helpers::render_value(payload, *(uint16_t *)(value_p), divider, fahrenheit); break; @@ -617,11 +568,12 @@ void EMSdevice::publish_value(void * value_p) { Helpers::render_value(payload, *(uint32_t *)(value_p), divider); break; case DeviceValueType::STRING: - default: if (Helpers::hasValue((char *)(value_p))) { strlcpy(payload, (char *)(value_p), sizeof(payload)); } break; + default: + break; } if (payload[0] != '\0') { @@ -632,7 +584,7 @@ void EMSdevice::publish_value(void * value_p) { } // looks up the UOM for a given key from the device value table -const std::string EMSdevice::get_value_uom(const char * key) { +std::string EMSdevice::get_value_uom(const char * key) const { // the key may have a TAG string prefixed at the beginning. If so, remove it char new_key[80]; strlcpy(new_key, key, sizeof(new_key)); @@ -651,14 +603,12 @@ const std::string EMSdevice::get_value_uom(const char * key) { // look up key in our device value list for (const auto & dv : devicevalues_) { - if (dv.has_state(DeviceValueState::DV_VISIBLE) && dv.full_name) { - if (read_flash_string(dv.full_name) == key_p) { - // ignore TIME since "minutes" is already added to the string value - if ((dv.uom == DeviceValueUOM::NONE) || (dv.uom == DeviceValueUOM::MINUTES)) { - break; - } - return EMSdevice::uom_to_string(dv.uom); + if ((dv.has_state(DeviceValueState::DV_VISIBLE) && dv.full_name) && (read_flash_string(dv.full_name) == key_p)) { + // ignore TIME since "minutes" is already added to the string value + if ((dv.uom == DeviceValueUOM::NONE) || (dv.uom == DeviceValueUOM::MINUTES)) { + break; } + return EMSdevice::uom_to_string(dv.uom); } } @@ -685,9 +635,9 @@ void EMSdevice::generate_values_web(JsonObject & output) { // handle Booleans (true, false) if (dv.type == DeviceValueType::BOOL) { bool value_b = *(bool *)(dv.value_p); - if ((EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE)) { + if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { obj["v"] = value_b ? "true" : "false"; - } else if ((EMSESP::system_.bool_format() == BOOL_FORMAT_10)) { + } else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) { obj["v"] = value_b ? 1 : 0; } else { char s[7]; @@ -816,9 +766,9 @@ void EMSdevice::generate_values_web_all(JsonArray & output) { // handle Booleans (true, false) if (dv.type == DeviceValueType::BOOL) { bool value_b = *(bool *)(dv.value_p); - if ((EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE)) { + if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { obj["v"] = value_b; - } else if ((EMSESP::system_.bool_format() == BOOL_FORMAT_10)) { + } else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) { obj["v"] = value_b ? 1 : 0; } else { char s[7]; @@ -844,7 +794,8 @@ void EMSdevice::generate_values_web_all(JsonArray & output) { uint8_t divider = 0; uint8_t factor = 1; if (dv.options_size == 1) { - const char * s = read_flash_string(dv.options[0]).c_str(); + auto s_str = read_flash_string(dv.options[0]); // prevent object backing the pointer will be destroyed at the end of the full-expression + const char * s = s_str.c_str(); if (s[0] == '*') { factor = Helpers::atoint(&s[1]); } else { @@ -853,13 +804,13 @@ void EMSdevice::generate_values_web_all(JsonArray & output) { } if (dv.type == DeviceValueType::INT) { - obj["v"] = (divider) ? Helpers::round2(*(int8_t *)(dv.value_p), divider) : *(int8_t *)(dv.value_p) * factor; + obj["v"] = divider ? Helpers::round2(*(int8_t *)(dv.value_p), divider) : *(int8_t *)(dv.value_p) * factor; } else if (dv.type == DeviceValueType::UINT) { - obj["v"] = (divider) ? Helpers::round2(*(uint8_t *)(dv.value_p), divider) : *(uint8_t *)(dv.value_p) * factor; + obj["v"] = divider ? Helpers::round2(*(uint8_t *)(dv.value_p), divider) : *(uint8_t *)(dv.value_p) * factor; } else if (dv.type == DeviceValueType::SHORT) { - obj["v"] = (divider) ? Helpers::round2(*(int16_t *)(dv.value_p), divider) : *(int16_t *)(dv.value_p) * factor; + obj["v"] = divider ? Helpers::round2(*(int16_t *)(dv.value_p), divider) : *(int16_t *)(dv.value_p) * factor; } else if (dv.type == DeviceValueType::USHORT) { - obj["v"] = (divider) ? Helpers::round2(*(uint16_t *)(dv.value_p), divider) : *(uint16_t *)(dv.value_p) * factor; + obj["v"] = divider ? Helpers::round2(*(uint16_t *)(dv.value_p), divider) : *(uint16_t *)(dv.value_p) * factor; } else if (dv.type == DeviceValueType::ULONG) { obj["v"] = divider ? Helpers::round2(*(uint32_t *)(dv.value_p), divider) : *(uint32_t *)(dv.value_p) * factor; } else if (dv.type == DeviceValueType::TIME) { @@ -988,10 +939,10 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8 case DeviceValueType::BOOL: if (Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) { - bool value_b = (bool)(*(uint8_t *)(dv.value_p)); - if ((EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE)) { + auto value_b = (bool)(*(uint8_t *)(dv.value_p)); + if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { json[value] = value_b; - } else if ((EMSESP::system_.bool_format() == BOOL_FORMAT_10)) { + } else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) { json[value] = value_b ? 1 : 0; } else { char s[7]; @@ -1106,10 +1057,10 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c if (have_tag) { snprintf(name, 80, "%s %s", tag_to_string(dv.tag).c_str(), read_flash_string(dv.full_name).c_str()); // prefix the tag } else { - strcpy(name, read_flash_string(dv.full_name).c_str()); // use full name + strlcpy(name, read_flash_string(dv.full_name).c_str(), sizeof(name)); // use full name } } else { - strcpy(name, read_flash_string(dv.short_name).c_str()); // use short name + strlcpy(name, read_flash_string(dv.short_name).c_str(), sizeof(name)); // use short name // if we have a tag, and its different to the last one create a nested object. only for hc, wwc and hs if (dv.tag != old_tag) { @@ -1123,14 +1074,14 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c // handle Booleans if (dv.type == DeviceValueType::BOOL && Helpers::hasValue(*(uint8_t *)(dv.value_p), EMS_VALUE_BOOL)) { // see how to render the value depending on the setting - bool value_b = (bool)*(uint8_t *)(dv.value_p); + auto value_b = (bool)*(uint8_t *)(dv.value_p); if (Mqtt::ha_enabled() && (output_target == OUTPUT_TARGET::MQTT)) { char s[7]; json[name] = Helpers::render_boolean(s, value_b); // for HA always render as string } else { - if ((EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE)) { + if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { json[name] = value_b; - } else if ((EMSESP::system_.bool_format() == BOOL_FORMAT_10)) { + } else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) { json[name] = value_b ? 1 : 0; } else { char s[7]; @@ -1147,7 +1098,7 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c // handle ENUMs else if ((dv.type == DeviceValueType::ENUM) && (*(uint8_t *)(dv.value_p) < dv.options_size)) { // check for numeric enum-format - if ((EMSESP::system_.enum_format() == ENUM_FORMAT_INDEX)) { + if (EMSESP::system_.enum_format() == ENUM_FORMAT_INDEX) { json[name] = (uint8_t)(*(uint8_t *)(dv.value_p)); } else { json[name] = dv.options[*(uint8_t *)(dv.value_p)]; @@ -1164,7 +1115,8 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c uint8_t divider = 0; uint8_t factor = 1; if (dv.options_size == 1) { - const char * s = read_flash_string(dv.options[0]).c_str(); + auto s_str = read_flash_string(dv.options[0]); // prevent object backing the pointer will be destroyed at the end of the full-expression + const char * s = s_str.c_str(); if (s[0] == '*') { factor = Helpers::atoint(&s[1]); } else { @@ -1300,7 +1252,7 @@ void EMSdevice::ha_config_clear() { ha_config_done(false); // this will force the recreation of the main HA device config } -bool EMSdevice::has_telegram_id(uint16_t id) { +bool EMSdevice::has_telegram_id(uint16_t id) const { for (const auto & tf : telegram_functions_) { if (tf.telegram_type_id_ == id) { return true; @@ -1310,7 +1262,7 @@ bool EMSdevice::has_telegram_id(uint16_t id) { } // return the name of the telegram type -const std::string EMSdevice::telegram_type_name(std::shared_ptr telegram) { +std::string EMSdevice::telegram_type_name(std::shared_ptr telegram) const { // see if it's one of the common ones, like Version if (telegram->type_id == EMS_TYPE_VERSION) { return read_flash_string(F("Version")); @@ -1351,22 +1303,22 @@ bool EMSdevice::handle_telegram(std::shared_ptr telegram) { } // send Tx write with a data block -void EMSdevice::write_command(const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid) { +void EMSdevice::write_command(const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid) const { EMSESP::send_write_request(type_id, device_id(), offset, message_data, message_length, validate_typeid); } // send Tx write with a single value -void EMSdevice::write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid) { +void EMSdevice::write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid) const { EMSESP::send_write_request(type_id, device_id(), offset, value, validate_typeid); } // send Tx write with a single value, with no post validation -void EMSdevice::write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value) { +void EMSdevice::write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value) const { EMSESP::send_write_request(type_id, device_id(), offset, value, 0); } // send Tx read command to the device -void EMSdevice::read_command(const uint16_t type_id, const uint8_t offset, const uint8_t length) { +void EMSdevice::read_command(const uint16_t type_id, const uint8_t offset, const uint8_t length) const { EMSESP::send_read_request(type_id, device_id(), offset, length); } diff --git a/src/emsdevice.h b/src/emsdevice.h index 92467ff77..d81d1492e 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -44,13 +44,13 @@ class EMSdevice { strlcpy(version_, version, sizeof(version_)); } - const std::string device_type_name() const; + std::string device_type_name() const; - static const std::string device_type_2_device_name(const uint8_t device_type); - static uint8_t device_name_2_device_type(const char * topic); - static const std::string uom_to_string(uint8_t uom); - static const std::string tag_to_string(uint8_t tag); - static const std::string tag_to_mqtt(uint8_t tag); + static std::string device_type_2_device_name(const uint8_t device_type); + static uint8_t device_name_2_device_type(const char * topic); + static std::string uom_to_string(uint8_t uom); + static std::string tag_to_string(uint8_t tag); + static std::string tag_to_mqtt(uint8_t tag); bool has_tag(const uint8_t tag); @@ -66,7 +66,7 @@ class EMSdevice { product_id_ = product_id; } - inline bool is_device_id(uint8_t device_id) { + inline bool is_device_id(uint8_t device_id) const { return ((device_id & 0x7F) == (device_id_ & 0x7F)); } @@ -92,7 +92,7 @@ class EMSdevice { strlcpy(version_, version, sizeof(version_)); } - inline const char * version() { + inline const char * version() const { return version_; } @@ -134,7 +134,7 @@ class EMSdevice { publish_value(value); } - inline void has_update(char * value, char * newvalue, size_t len) { + inline void has_update(char * value, const char * newvalue, size_t len) { if (strcmp(value, newvalue) != 0) { strlcpy(value, newvalue, len); has_update_ = true; @@ -173,18 +173,18 @@ class EMSdevice { } } - const std::string brand_to_string() const; - static uint8_t decode_brand(uint8_t value); + std::string brand_to_string() const; + static uint8_t decode_brand(uint8_t value); - const std::string to_string() const; - const std::string to_string_short() const; + std::string to_string() const; + std::string to_string_short() const; enum Handlers : uint8_t { ALL, RECEIVED, FETCHED, PENDING }; - void show_telegram_handlers(uuid::console::Shell & shell); + void show_telegram_handlers(uuid::console::Shell & shell) const; char * show_telegram_handlers(char * result, uint8_t handlers); - void show_mqtt_handlers(uuid::console::Shell & shell); - void list_device_entries(JsonObject & output); + void show_mqtt_handlers(uuid::console::Shell & shell) const; + void list_device_entries(JsonObject & output) const; void exclude_entity(uint8_t entity_id); void reset_exclude_entities(); @@ -193,9 +193,9 @@ class EMSdevice { void register_telegram_type(const uint16_t telegram_type_id, const __FlashStringHelper * telegram_type_name, bool fetch, const process_function_p cb); bool handle_telegram(std::shared_ptr telegram); - const std::string get_value_uom(const char * key); - bool get_value_info(JsonObject & root, const char * cmd, const int8_t id); - void get_dv_info(JsonObject & json); + std::string get_value_uom(const char * key) const; + bool get_value_info(JsonObject & root, const char * cmd, const int8_t id); + void get_dv_info(JsonObject & json); enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT }; bool generate_values(JsonObject & output, const uint8_t tag_filter, const bool nested, const uint8_t output_target); @@ -238,25 +238,25 @@ class EMSdevice { const __FlashStringHelper * const * name, uint8_t uom); - void write_command(const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid); - void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid); - void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value); + void write_command(const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid) const; + void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid) const; + void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value) const; - void read_command(const uint16_t type_id, uint8_t offset = 0, uint8_t length = 0); + void read_command(const uint16_t type_id, uint8_t offset = 0, uint8_t length = 0) const; - bool is_visible(void * value_p); - void publish_value(void * value_p); + bool is_visible(const void * value_p) const; + void publish_value(void * value_p) const; void publish_all_values(); void mqtt_ha_entity_config_create(); void mqtt_ha_entity_config_remove(); - const std::string telegram_type_name(std::shared_ptr telegram); + std::string telegram_type_name(std::shared_ptr telegram) const; void fetch_values(); void toggle_fetch(uint16_t telegram_id, bool toggle); - bool is_fetch(uint16_t telegram_id); - bool has_telegram_id(uint16_t id); + bool is_fetch(uint16_t telegram_id) const; + bool has_telegram_id(uint16_t id) const; void ha_config_clear(); bool ha_config_done() const { @@ -347,7 +347,7 @@ class EMSdevice { static constexpr uint8_t EMS_DEVICE_FLAG_CRF = 12; // CRF200 only monitor uint8_t count_entities(); - bool has_entities(); + bool has_entities() const; private: uint8_t unique_id_; diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 401ebc48d..9e8ab31f1 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -77,12 +77,10 @@ bool EMSESP::wait_km_ = true; // or if device_id is 0 it will fetch from all our known and active devices void EMSESP::fetch_device_values(const uint8_t device_id) { for (const auto & emsdevice : emsdevices) { - if (emsdevice) { - if ((device_id == 0) || emsdevice->is_device_id(device_id)) { - emsdevice->fetch_values(); - if (device_id != 0) { - return; // quit, we only want to return the selected device - } + if ((device_id == 0) || emsdevice->is_device_id(device_id)) { + emsdevice->fetch_values(); + if (device_id != 0) { + return; // quit, we only want to return the selected device } } } @@ -91,10 +89,8 @@ void EMSESP::fetch_device_values(const uint8_t device_id) { // see if the deviceID exists bool EMSESP::valid_device(const uint8_t device_id) { for (const auto & emsdevice : emsdevices) { - if (emsdevice) { - if (emsdevice->is_device_id(device_id)) { - return true; - } + if (emsdevice && emsdevice->is_device_id(device_id)) { + return true; } } return false; // can't find it @@ -103,7 +99,7 @@ bool EMSESP::valid_device(const uint8_t device_id) { // for a specific EMS device type go and request data values void EMSESP::fetch_device_values_type(const uint8_t device_type) { for (const auto & emsdevice : emsdevices) { - if ((emsdevice) && (emsdevice->device_type() == device_type)) { + if (emsdevice && (emsdevice->device_type() == device_type)) { emsdevice->fetch_values(); } } @@ -170,9 +166,9 @@ void EMSESP::watch_id(uint16_t watch_id) { // resets all counters and bumps the UART // this is called when the tx_mode is persisted in the FS either via Web UI or the console void EMSESP::uart_init() { - uint8_t tx_mode; - uint8_t rx_gpio; - uint8_t tx_gpio; + uint8_t tx_mode = 0; + uint8_t rx_gpio = 0; + uint8_t tx_gpio = 0; EMSESP::webSettingsService.read([&](WebSettings & settings) { tx_mode = settings.tx_mode; rx_gpio = settings.rx_gpio; @@ -217,10 +213,8 @@ uint8_t EMSESP::bus_status() { } // Tx Failure rate > 10% - if (total_fail < total_sent) { - if (((total_fail * 100) / total_sent) > EMSbus::EMS_TX_ERROR_LIMIT) { - return BUS_STATUS_TX_ERRORS; - } + if ((total_fail < total_sent) && (((total_fail * 100) / total_sent) > EMSbus::EMS_TX_ERROR_LIMIT)) { + return BUS_STATUS_TX_ERRORS; } return BUS_STATUS_CONNECTED; @@ -236,7 +230,6 @@ void EMSESP::show_ems(uuid::console::Shell & shell) { case BUS_STATUS_TX_ERRORS: shell.printfln(F("EMS Bus is connected, but Tx is not stable.")); break; - case BUS_STATUS_CONNECTED: default: shell.printfln(F("EMS Bus is connected.")); break; @@ -248,7 +241,7 @@ void EMSESP::show_ems(uuid::console::Shell & shell) { shell.printfln(F("EMS Bus info:")); EMSESP::webSettingsService.read([&](WebSettings & settings) { shell.printfln(F(" Tx mode: %d"), settings.tx_mode); }); shell.printfln(F(" Bus protocol: %s"), EMSbus::is_ht3() ? F("HT3") : F("Buderus")); - shell.printfln(F(" #recognized EMS devices: %d"), (EMSESP::emsdevices).size()); + shell.printfln(F(" #recognized EMS devices: %d"), EMSESP::emsdevices.size()); shell.printfln(F(" #telegrams received: %d"), rxservice_.telegram_count()); shell.printfln(F(" #read requests sent: %d"), txservice_.telegram_read_count()); shell.printfln(F(" #write requests sent: %d"), txservice_.telegram_write_count()); @@ -308,7 +301,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) { // 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 : emsdevices) { - if ((emsdevice) && (emsdevice->device_type() == device_class.first)) { + if (emsdevice && (emsdevice->device_type() == device_class.first)) { // print header shell.printfln(F("%s: %s (%d)"), emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str(), emsdevice->count_entities()); @@ -330,7 +323,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) { shell.print(data.as()); } else if (data.is()) { char s[10]; - shell.print(Helpers::render_value(s, (float)data.as(), 1)); + shell.print(Helpers::render_value(s, data.as(), 1)); } else if (data.is()) { shell.print(data.as() ? F_(on) : F_(off)); } @@ -400,8 +393,8 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) { sensor.offset()); break; default: - case AnalogSensor::AnalogType::DIGITAL_IN: - case AnalogSensor::AnalogType::COUNTER: + // case AnalogSensor::AnalogType::DIGITAL_IN: + // case AnalogSensor::AnalogType::COUNTER: shell.printfln(F(" %s: %s%d%s (Type: %s)"), sensor.name().c_str(), COLOR_BRIGHT_GREEN, @@ -582,7 +575,7 @@ void EMSESP::publish_response(std::shared_ptr telegram) { doc["dest"] = Helpers::hextoa(buffer, telegram->dest); doc["type"] = Helpers::hextoa(buffer, telegram->type_id); doc["offset"] = Helpers::hextoa(buffer, telegram->offset); - strcpy(buffer, Helpers::data_to_hex(telegram->message_data, telegram->message_length).c_str()); // telegram is without crc + strlcpy(buffer, Helpers::data_to_hex(telegram->message_data, telegram->message_length).c_str(), sizeof(buffer)); // telegram is without crc doc["data"] = buffer; if (telegram->message_length <= 4) { @@ -830,31 +823,29 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { bool found = false; bool knowndevice = false; for (const auto & emsdevice : emsdevices) { - if (emsdevice) { - if (emsdevice->is_device_id(telegram->src) || emsdevice->is_device_id(telegram->dest)) { - knowndevice = true; - found = emsdevice->handle_telegram(telegram); - if (found && emsdevice->is_device_id(telegram->dest)) { - LOG_DEBUG(F("Process setting 0x%02X for device 0x%02X"), telegram->type_id, telegram->dest); - } - // if we correctly processed the telegram then follow up with sending it via MQTT (if enabled) - if (found && Mqtt::connected()) { - if ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update()) - || (telegram->type_id == publish_id_ && telegram->dest == txservice_.ems_bus_id())) { - if (telegram->type_id == publish_id_) { - publish_id_ = 0; - } - emsdevice->has_update(false); // reset flag - if (!Mqtt::publish_single()) { - publish_device_values(emsdevice->device_type()); // publish to MQTT if we explicitly have too - } + if (emsdevice->is_device_id(telegram->src) || emsdevice->is_device_id(telegram->dest)) { + knowndevice = true; + found = emsdevice->handle_telegram(telegram); + if (found && emsdevice->is_device_id(telegram->dest)) { + LOG_DEBUG(F("Process setting 0x%02X for device 0x%02X"), telegram->type_id, telegram->dest); + } + // if we correctly processed the telegram then follow up with sending it via MQTT (if enabled) + if (found && Mqtt::connected()) { + if ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update()) + || (telegram->type_id == publish_id_ && telegram->dest == txservice_.ems_bus_id())) { + if (telegram->type_id == publish_id_) { + publish_id_ = 0; + } + emsdevice->has_update(false); // reset flag + if (!Mqtt::publish_single()) { + publish_device_values(emsdevice->device_type()); // publish to MQTT if we explicitly have too } } - if (wait_validate_ == telegram->type_id) { - wait_validate_ = 0; - } - break; } + if (wait_validate_ == telegram->type_id) { + wait_validate_ = 0; + } + break; } } @@ -874,10 +865,8 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { // return true if we have this device already registered bool EMSESP::device_exists(const uint8_t device_id) { for (const auto & emsdevice : emsdevices) { - if (emsdevice) { - if (emsdevice->is_device_id(device_id)) { - return true; - } + if (emsdevice && emsdevice->is_device_id(device_id)) { + return true; } } @@ -898,7 +887,7 @@ void EMSESP::show_devices(uuid::console::Shell & shell) { // count the number of thermostats uint8_t num_thermostats = 0; for (const auto & emsdevice : emsdevices) { - if ((emsdevice) && (emsdevice->device_type() == DeviceType::THERMOSTAT)) { + if (emsdevice && (emsdevice->device_type() == DeviceType::THERMOSTAT)) { num_thermostats++; } } @@ -907,7 +896,7 @@ void EMSESP::show_devices(uuid::console::Shell & shell) { // so we keep a consistent order for (const auto & device_class : EMSFactory::device_handlers()) { for (const auto & emsdevice : emsdevices) { - if ((emsdevice) && (emsdevice->device_type() == device_class.first)) { + if (emsdevice && (emsdevice->device_type() == device_class.first)) { shell.printf(F("%s: %s"), emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str()); shell.println(); emsdevice->show_telegram_handlers(shell); @@ -931,25 +920,23 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const // first check to see if we already have it, if so update the record for (const auto & emsdevice : emsdevices) { - if (emsdevice) { - if (emsdevice->is_device_id(device_id)) { - LOG_DEBUG(F("Updating details for already active deviceID 0x%02X"), device_id); - emsdevice->product_id(product_id); - emsdevice->version(version); - // only set brand if it doesn't already exist - if (emsdevice->brand() == EMSdevice::Brand::NO_BRAND) { - emsdevice->brand(brand); - } - // find the name and flags in our database - for (const auto & device : device_library_) { - if (device.product_id == product_id && device.device_type == emsdevice->device_type()) { - emsdevice->name(std::move(read_flash_string(device.name))); - emsdevice->add_flags(device.flags); - } - } - - return true; // finish up + if (emsdevice && emsdevice->is_device_id(device_id)) { + LOG_DEBUG(F("Updating details for already active deviceID 0x%02X"), device_id); + emsdevice->product_id(product_id); + emsdevice->version(version); + // only set brand if it doesn't already exist + if (emsdevice->brand() == EMSdevice::Brand::NO_BRAND) { + emsdevice->brand(brand); } + // find the name and flags in our database + for (const auto & device : device_library_) { + if (device.product_id == product_id && device.device_type == emsdevice->device_type()) { + emsdevice->name(std::move(read_flash_string(device.name))); + emsdevice->add_flags(device.flags); + } + } + + return true; // finish up } } @@ -1085,7 +1072,7 @@ bool EMSESP::command_entities(uint8_t device_type, JsonObject & output, const in JsonObject node; for (const auto & emsdevice : emsdevices) { - if ((emsdevice) && (emsdevice->device_type() == device_type)) { + if (emsdevice && (emsdevice->device_type() == device_type)) { emsdevice->list_device_entries(output); return true; } @@ -1213,11 +1200,10 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) { txservice_.send_poll(); // close the bus txservice_.reset_retry_count(); tx_successful = true; + // if telegram is longer read next part with offset +25 for ems+ or +27 for ems1.0 - if (length == 32) { - if (txservice_.read_next_tx(data[3]) == read_id_) { - read_next_ = true; - } + if ((length == 32) && (txservice_.read_next_tx(data[3]) == read_id_)) { + read_next_ = true; } } } @@ -1341,7 +1327,7 @@ void EMSESP::scheduled_fetch_values() { if (txservice_.tx_queue_empty()) { uint8_t i = 0; for (const auto & emsdevice : emsdevices) { - if (emsdevice && ++i >= no) { + if (++i >= no) { emsdevice->fetch_values(); no++; return; diff --git a/src/helpers.cpp b/src/helpers.cpp index c405630ef..97a954207 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -64,8 +64,8 @@ std::string Helpers::hextoa(const uint16_t value, bool prefix) { #ifdef EMSESP_STANDALONE // special function to work outside of ESP's libraries char * Helpers::ultostr(char * ptr, uint32_t value, const uint8_t base) { - if (NULL == ptr) { - return NULL; + if (nullptr == ptr) { + return nullptr; } unsigned long t = 0; @@ -191,7 +191,7 @@ char * Helpers::render_boolean(char * result, bool value) { // render for native char strings char * Helpers::render_value(char * result, const char * value, const int8_t format __attribute__((unused))) { - strcpy(result, value); + strcpy(result, value); // un-safe but we don't care return result; } @@ -256,8 +256,8 @@ char * Helpers::render_value(char * result, const float value, const int8_t form uint32_t p[] = {0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000}; - char * ret = result; - int32_t whole = (int32_t)value; + char * ret = result; + auto whole = (int32_t)value; itoa(whole, result, 10); @@ -356,12 +356,11 @@ char * Helpers::render_value(char * result, const uint32_t value, const int8_t f } else { strlcpy(result, ltoa(new_value * format * -1, s, 10), sizeof(s)); } - #else if (!format) { strlcpy(result, ultostr(s, new_value, 10), sizeof(s)); // format is 0 } else { - strncpy(result, ultostr(s, new_value / format, 10), sizeof(s)); + strlcpy(result, ultostr(s, new_value / format, 10), sizeof(s)); strlcat(result, ".", sizeof(s)); strncat(result, ultostr(s, new_value % format, 10), sizeof(s)); } @@ -481,7 +480,7 @@ bool Helpers::hasValue(const int8_t & v) { return (v != EMS_VALUE_INT_NOTSET); } -bool Helpers::hasValue(char * v) { +bool Helpers::hasValue(const char * v) { if ((v == nullptr) || (strlen(v) == 0)) { return false; } @@ -508,7 +507,8 @@ bool Helpers::value2number(const char * v, int & value, const int min, const int value = 0; return false; } - value = atoi((char *)v); + + value = atoi(v); if (value >= min && value <= max) { return true; } @@ -521,12 +521,14 @@ bool Helpers::value2float(const char * v, float & value) { if ((v == nullptr) || (strlen(v) == 0)) { return false; } + if (v[0] == '-' || v[0] == '.' || (v[0] >= '0' && v[0] <= '9')) { - value = atof((char *)v); + value = atof(v); return true; } + if (v[0] == '+' && (v[1] == '.' || (v[1] >= '0' && v[1] <= '9'))) { - value = atof((char *)(v + 1)); + value = atof(v + 1); return true; } return false; @@ -584,12 +586,12 @@ bool Helpers::value2bool(const char * v, bool & value) { std::string bool_str = toLower(v); // convert to lower case - if ((bool_str == read_flash_string(F_(on))) || (bool_str == "1") or (bool_str == "true")) { + if ((bool_str == read_flash_string(F_(on))) || (bool_str == "1") || (bool_str == "true")) { value = true; return true; // is a bool } - if ((bool_str == read_flash_string(F_(off))) || (bool_str == "0") or (bool_str == "false")) { + if ((bool_str == read_flash_string(F_(off))) || (bool_str == "0") || (bool_str == "false")) { value = false; return true; // is a bool } diff --git a/src/helpers.h b/src/helpers.h index f7ab36ada..2aa33ae68 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -63,7 +63,7 @@ class Helpers { static bool hasValue(const int16_t & v); static bool hasValue(const uint16_t & v); static bool hasValue(const uint32_t & v); - static bool hasValue(char * v); + static bool hasValue(const char * v); static bool value2number(const char * v, int & value, const int min = -2147483648, const int max = 2147483647); static bool value2float(const char * v, float & value); diff --git a/src/locale_DE.h b/src/locale_DE.h index ec577247e..295d9b18e 100644 --- a/src/locale_DE.h +++ b/src/locale_DE.h @@ -379,7 +379,18 @@ MAKE_PSTR_LIST(enum_j_control, F_(off), F("fb10"), F("fb110")) MAKE_PSTR_LIST(enum_wwProgMode, F("std Prog"), F_(own_prog)) MAKE_PSTR_LIST(enum_dayOfWeek, F("Mo"), F("Di"), F("Mi"), F("Do"), F("Fr"), F("Sa"), F("So"), F("Alle")) MAKE_PSTR_LIST(enum_progMode, F("Prog_1"), F("Prog_2")) -MAKE_PSTR_LIST(enum_progMode2, F("Eigen_1"), F("Familie"), F("Morgends"), F("Abends"), F("Vormittag"), F("Nachmittag"), F("Mittag"), F("Singles"), F("Senioren"), F("Neu"), F("Eigen_2")) +MAKE_PSTR_LIST(enum_progMode2, + F("Eigen_1"), + F("Familie"), + F("Morgends"), + F("Abends"), + F("Vormittag"), + F("Nachmittag"), + F("Mittag"), + F("Singles"), + F("Senioren"), + F("Neu"), + F("Eigen_2")) MAKE_PSTR_LIST(enum_progMode3, F("Familie"), F("Morgends"), F("Abends"), F("Vormittag"), F("Nachmittag"), F("Mittag"), F("Singles"), F("Senioren")) MAKE_PSTR_LIST(enum_progMode4, F("prog_a"), F("prog_b"), F("prog_c"), F("prog_d"), F("prog_e"), F("prog_f")) diff --git a/src/mqtt.cpp b/src/mqtt.cpp index e1b56dfdb..e39df2699 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -244,14 +244,16 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) { #if defined(EMSESP_DEBUG) // simulate receiving a MQTT message, used only for testing void Mqtt::incoming(const char * topic, const char * payload) { - on_message(topic, payload, strlen(payload)); + if (payload != nullptr) { + on_message(topic, payload, strlen(payload)); + } } #endif // received an MQTT message that we subscribed too // topic is the full path // payload is json or a single string and converted to a json with key 'value' -void Mqtt::on_message(const char * topic, const char * payload, size_t len) { +void Mqtt::on_message(const char * topic, const char * payload, size_t len) const { // sometimes the payload is not terminated correctly, so make a copy // convert payload to a null-terminated char string char message[len + 2]; @@ -280,16 +282,14 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) { // add the base back char full_topic[MQTT_TOPIC_MAX_SIZE]; snprintf(full_topic, sizeof(full_topic), "%s/%s", mqtt_base_.c_str(), mf.topic_.c_str()); - if (!strcmp(topic, full_topic)) { - if (mf.mqtt_subfunction_) { - if (!(mf.mqtt_subfunction_)(message)) { - LOG_ERROR(F("error: invalid payload %s for this topic %s"), message, topic); - if (send_response_) { - Mqtt::publish(F_(response), "error: invalid data"); - } + if ((!strcmp(topic, full_topic)) && (mf.mqtt_subfunction_)) { + if (!(mf.mqtt_subfunction_)(message)) { + LOG_ERROR(F("error: invalid payload %s for this topic %s"), message, topic); + if (send_response_) { + Mqtt::publish(F_(response), "error: invalid data"); } - return; } + return; } } @@ -353,7 +353,7 @@ void Mqtt::show_topic_handlers(uuid::console::Shell & shell, const uint8_t devic // its a poor man's QOS we assume the ACK represents the last Publish sent // check if ACK matches the last Publish we sent, if not report an error. Only if qos is 1 or 2 // and always remove from queue -void Mqtt::on_publish(uint16_t packetId) { +void Mqtt::on_publish(uint16_t packetId) const { // find the MQTT message in the queue and remove it if (mqtt_messages_.empty()) { #if defined(EMSESP_DEBUG) @@ -462,7 +462,7 @@ void Mqtt::start() { snprintf(will_topic, MQTT_TOPIC_MAX_SIZE, "%s/status", mqtt_base_.c_str()); mqttClient_->setWill(will_topic, 1, true, "offline"); // with qos 1, retain true - mqttClient_->onMessage([this](char * topic, char * payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { + mqttClient_->onMessage([this](const char * topic, const char * payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { on_message(topic, payload, len); // receiving mqtt }); @@ -804,7 +804,7 @@ void Mqtt::process_queue() { char topic[MQTT_TOPIC_MAX_SIZE]; if (message->topic.find(discovery_prefix_) == 0) { - strcpy(topic, message->topic.c_str()); // leave topic as it is + strlcpy(topic, message->topic.c_str(), sizeof(topic)); // leave topic as it is } else { snprintf(topic, MQTT_TOPIC_MAX_SIZE, "%s/%s", mqtt_base_.c_str(), message->topic.c_str()); } @@ -1313,7 +1313,7 @@ void Mqtt::publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove // based on the device and tag, create the MQTT topic name (without the basename) // differs based on whether MQTT nested is enabled // tag = EMSdevice::DeviceValueTAG -const std::string Mqtt::tag_to_topic(uint8_t device_type, uint8_t tag) { +std::string Mqtt::tag_to_topic(uint8_t device_type, uint8_t tag) { // the system device is treated differently. The topic is 'heartbeat' and doesn't follow the usual convention if (device_type == EMSdevice::DeviceType::SYSTEM) { return EMSdevice::tag_to_mqtt(tag); diff --git a/src/mqtt.h b/src/mqtt.h index ebe8bac78..743870251 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -30,7 +30,7 @@ using uuid::console::Shell; // size of queue -#define MAX_MQTT_MESSAGES 300 +static constexpr uint16_t MAX_MQTT_MESSAGES = 300; namespace emsesp { @@ -208,11 +208,11 @@ class Mqtt { send_response_ = send_response; } - void set_qos(uint8_t mqtt_qos) { + void set_qos(uint8_t mqtt_qos) const { mqtt_qos_ = mqtt_qos; } - void set_retain(bool mqtt_retain) { + void set_retain(bool mqtt_retain) const { mqtt_retain_ = mqtt_retain; } @@ -220,20 +220,18 @@ class Mqtt { return mqtt_messages_.empty(); } - static const std::string tag_to_topic(uint8_t device_type, uint8_t tag); + static std::string tag_to_topic(uint8_t device_type, uint8_t tag); struct QueuedMqttMessage { const uint32_t id_; const std::shared_ptr content_; - uint8_t retry_count_; - uint16_t packet_id_; + uint8_t retry_count_ = 0; + uint16_t packet_id_ = 0; ~QueuedMqttMessage() = default; QueuedMqttMessage(uint32_t id, std::shared_ptr && content) : id_(id) , content_(std::move(content)) { - retry_count_ = 0; - packet_id_ = 0; } }; static std::deque mqtt_messages_; @@ -253,8 +251,8 @@ class Mqtt { static std::shared_ptr queue_subscribe_message(const std::string & topic); static std::shared_ptr queue_unsubscribe_message(const std::string & topic); - void on_publish(uint16_t packetId); - void on_message(const char * topic, const char * payload, size_t len); + void on_publish(uint16_t packetId) const; + void on_message(const char * topic, const char * payload, size_t len) const; void process_queue(); // function handlers for MQTT subscriptions diff --git a/src/shower.cpp b/src/shower.cpp index 0d4af6718..f9c8a2e8e 100644 --- a/src/shower.cpp +++ b/src/shower.cpp @@ -65,12 +65,12 @@ void Shower::loop() { } } else { // hot water is off // if it just turned off, record the time as it could be a short pause - if ((timer_start_) && (timer_pause_ == 0)) { + if (timer_start_ && (timer_pause_ == 0)) { timer_pause_ = time_now; } // if shower has been off for longer than the wait time - if ((timer_pause_) && ((time_now - timer_pause_) > SHOWER_PAUSE_TIME)) { + if (timer_pause_ && ((time_now - timer_pause_) > SHOWER_PAUSE_TIME)) { // it is over the wait period, so assume that the shower has finished and calculate the total time and publish // because its unsigned long, can't have negative so check if length is less than OFFSET_TIME if ((timer_pause_ - timer_start_) > SHOWER_OFFSET_TIME) { @@ -121,7 +121,7 @@ void Shower::shower_alert_start() { // Publish to the shower_data topic // showing whether the shower timer and alert are enabled or disabled // and the duration of the last shower -void Shower::publish_shower_data() { +void Shower::publish_shower_data() const { StaticJsonDocument doc; if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { diff --git a/src/shower.h b/src/shower.h index a9705923c..dc9dafda4 100644 --- a/src/shower.h +++ b/src/shower.h @@ -55,7 +55,7 @@ class Shower { static constexpr uint32_t SHOWER_COLDSHOT_DURATION = 10000; // 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 publish_shower_data(); + void publish_shower_data() const; void shower_alert_start(); void shower_alert_stop(); diff --git a/src/system.cpp b/src/system.cpp index f92d740b7..09f16ec1a 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -484,7 +484,7 @@ bool System::upload_status() { void System::upload_status(bool in_progress) { // if we've just started an upload - if ((!upload_status_) && (in_progress)) { + if (!upload_status_ && in_progress) { EMSuart::stop(); } upload_status_ = in_progress; @@ -615,7 +615,7 @@ void System::network_init(bool refresh) { // ETH_CLOCK_GPIO0_OUT = 1 RMII clock output from GPIO0 // ETH_CLOCK_GPIO16_OUT = 2 RMII clock output from GPIO16 // ETH_CLOCK_GPIO17_OUT = 3 RMII clock output from GPIO17, for 50hz inverted clock - eth_clock_mode_t clock_mode = (eth_clock_mode_t)eth_clock_mode_; + auto clock_mode = (eth_clock_mode_t)eth_clock_mode_; ETH.begin(phy_addr, power, mdc, mdio, type, clock_mode); } @@ -1133,9 +1133,11 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp node["bus status"] = (F("connected, tx issues - try a different tx-mode")); break; case EMSESP::BUS_STATUS_CONNECTED: - default: node["bus status"] = (F("connected")); break; + default: + node["bus status"] = (F("unknown")); + break; } if (EMSESP::bus_status() != EMSESP::BUS_STATUS_OFFLINE) { @@ -1180,7 +1182,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp JsonArray devices = output.createNestedArray("Devices"); for (const auto & device_class : EMSFactory::device_handlers()) { for (const auto & emsdevice : EMSESP::emsdevices) { - if ((emsdevice) && (emsdevice->device_type() == device_class.first)) { + if (emsdevice && (emsdevice->device_type() == device_class.first)) { JsonObject obj = devices.createNestedObject(); obj["type"] = emsdevice->device_type_name(); // obj["name"] = emsdevice->to_string(); @@ -1278,7 +1280,7 @@ bool System::command_restart(const char * value, const int8_t id) { return true; } -const std::string System::reset_reason(uint8_t cpu) { +std::string System::reset_reason(uint8_t cpu) const { #ifndef EMSESP_STANDALONE switch (rtc_get_reset_reason(cpu)) { case 1: diff --git a/src/system.h b/src/system.h index d87e6e737..970b77731 100644 --- a/src/system.h +++ b/src/system.h @@ -65,7 +65,7 @@ class System { static bool command_customizations(const char * value, const int8_t id, JsonObject & output); static bool command_commands(const char * value, const int8_t id, JsonObject & output); - const std::string reset_reason(uint8_t cpu); + std::string reset_reason(uint8_t cpu) const; void system_restart(); void format(uuid::console::Shell & shell); diff --git a/src/telegram.cpp b/src/telegram.cpp index 97c3cb541..5624ead2a 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -261,7 +261,7 @@ void TxService::start() { } // sends a 1 byte poll which is our own deviceID -void TxService::send_poll() { +void TxService::send_poll() const { //LOG_DEBUG(F("Ack %02X"),ems_bus_id() ^ ems_mask()); if (tx_mode()) { EMSuart::send_poll(ems_bus_id() ^ ems_mask()); @@ -568,7 +568,7 @@ void TxService::send_raw(const char * telegram_data) { while (p != 0) { if ((p = strtok(nullptr, " ,"))) { strlcpy(value, p, sizeof(value)); - uint8_t val = (uint8_t)strtol(value, 0, 16); + auto val = (uint8_t)strtol(value, 0, 16); data[++count] = val; } } diff --git a/src/telegram.h b/src/telegram.h index e75f53008..cf05e5076 100644 --- a/src/telegram.h +++ b/src/telegram.h @@ -87,11 +87,12 @@ class Telegram { // reads a bit value from a given telegram position bool read_bitvalue(uint8_t & value, const uint8_t index, const uint8_t bit) const { uint8_t abs_index = (index - this->offset); - if (abs_index >= this->message_length) { + if ((abs_index >= this->message_length) || (abs_index > EMS_MAX_TELEGRAM_MESSAGE_LENGTH)) { return false; // out of bounds } + uint8_t val = value; - value = (uint8_t)(((this->message_data[abs_index]) >> (bit)) & 0x01); + value = (uint8_t)(((this->message_data[abs_index]) >> bit) & 0x01); return (val != value); } @@ -105,14 +106,17 @@ class Telegram { bool read_value(Value & value, const uint8_t index, uint8_t s = 0) const { uint8_t num_bytes = (!s) ? sizeof(Value) : s; // check for out of bounds, if so don't modify the value - if ((index < this->offset) || ((index - this->offset + num_bytes - 1) >= this->message_length)) { + auto msg_size = (index - this->offset + num_bytes - 1); + if ((index < this->offset) || (msg_size >= this->message_length) || (msg_size > EMS_MAX_TELEGRAM_MESSAGE_LENGTH)) { return false; } - auto val = value; - value = 0; + + Value val = value; + value = 0; for (uint8_t i = 0; i < num_bytes; i++) { value = (value << 8) + this->message_data[index - this->offset + i]; // shift by byte } + return (val != value); } @@ -120,6 +124,7 @@ class Telegram { if ((index < this->offset) || ((index - this->offset) >= this->message_length)) { return false; } + uint8_t val = value; value = this->message_data[index - this->offset] - start; return (val != value); @@ -265,7 +270,7 @@ class RxService : public EMSbus { } }; - const std::deque queue() const { + std::deque queue() const { return rx_telegrams_; } @@ -300,7 +305,7 @@ class TxService : public EMSbus { void add(const uint8_t operation, const uint8_t * data, const uint8_t length, const uint16_t validateid, const bool front = false); void read_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset = 0, const uint8_t length = 0); void send_raw(const char * telegram_data); - void send_poll(); + void send_poll() const; void retry_tx(const uint8_t operation, const uint8_t * data, const uint8_t length); bool is_last_tx(const uint8_t src, const uint8_t dest) const; uint16_t post_send_query(); @@ -318,7 +323,7 @@ class TxService : public EMSbus { telegram_last_post_send_query_ = type_id; } - uint16_t get_post_send_query() { + uint16_t get_post_send_query() const { return telegram_last_post_send_query_; } @@ -362,14 +367,14 @@ class TxService : public EMSbus { if (telegram_read_fail_count_ == 0) { return 100; // all good, 100% } - return (100 - (uint8_t)((telegram_read_fail_count_ * 100 / (telegram_read_fail_count_ + telegram_read_count_)))); + return (100 - (uint8_t)(telegram_read_fail_count_ * 100 / (telegram_read_fail_count_ + telegram_read_count_))); } uint8_t write_quality() const { if (telegram_write_fail_count_ == 0) { return 100; // all good, 100% } - return (100 - (uint8_t)((telegram_write_fail_count_ * 100 / (telegram_write_fail_count_ + telegram_write_count_)))); + return (100 - (uint8_t)(telegram_write_fail_count_ * 100 / (telegram_write_fail_count_ + telegram_write_count_))); } void increment_telegram_read_fail_count() { @@ -395,12 +400,12 @@ class TxService : public EMSbus { } }; - const std::deque queue() const { + std::deque queue() const { return tx_telegrams_; } - bool tx_queue_empty() { - return tx_telegrams_.size() == 0; + bool tx_queue_empty() const { + return tx_telegrams_.empty(); } #if defined(EMSESP_DEBUG) diff --git a/src/test/test.cpp b/src/test/test.cpp index 70d32ce92..a9ec54c4f 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -804,28 +804,28 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // test command parse int8_t id_n; - const char * cmd; + const char * ncmd; char command_s[100]; id_n = -1; - strcpy(command_s, "hc2/seltemp"); - cmd = Command::parse_command_string(command_s, id_n); - shell.printfln("test cmd parse cmd=%s id=%d", cmd, id_n); + strlcpy(command_s, "hc2/seltemp", sizeof(command_s)); + ncmd = Command::parse_command_string(command_s, id_n); + shell.printfln("test cmd parse cmd=%s id=%d", ncmd, id_n); id_n = -1; - strcpy(command_s, "seltemp"); - cmd = Command::parse_command_string(command_s, id_n); - shell.printfln("test cmd parse cmd=%s id=%d", cmd, id_n); + strlcpy(command_s, "seltemp", sizeof(command_s)); + ncmd = Command::parse_command_string(command_s, id_n); + shell.printfln("test cmd parse cmd=%s id=%d", ncmd, id_n); id_n = -1; - strcpy(command_s, "xyz/seltemp"); - cmd = Command::parse_command_string(command_s, id_n); - shell.printfln("test cmd parse cmd=%s id=%d", cmd, id_n); + strlcpy(command_s, "xyz/seltemp", sizeof(command_s)); + ncmd = Command::parse_command_string(command_s, id_n); + shell.printfln("test cmd parse cmd=%s id=%d", ncmd, id_n); id_n = -1; - strcpy(command_s, "wwc4/seltemp"); - cmd = Command::parse_command_string(command_s, id_n); - shell.printfln("test cmd parse cmd=%s id=%d", cmd, id_n); + strlcpy(command_s, "wwc4/seltemp", sizeof(command_s)); + ncmd = Command::parse_command_string(command_s, id_n); + shell.printfln("test cmd parse cmd=%s id=%d", ncmd, id_n); id_n = -1; - strcpy(command_s, "hc3_seltemp"); - cmd = Command::parse_command_string(command_s, id_n); - shell.printfln("test cmd parse cmd=%s id=%d", cmd, id_n); + strlcpy(command_s, "hc3_seltemp", sizeof(command_s)); + ncmd = Command::parse_command_string(command_s, id_n); + shell.printfln("test cmd parse cmd=%s id=%d", ncmd, id_n); #endif @@ -1335,12 +1335,12 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const char system_topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; Mqtt::show_mqtt(shell); // show queue - strcpy(boiler_topic, "ems-esp/boiler"); - strcpy(thermostat_topic, "ems-esp/thermostat"); - strcpy(system_topic, "ems-esp/system"); + strlcpy(boiler_topic, "ems-esp/boiler", sizeof(boiler_topic)); + strlcpy(thermostat_topic, "ems-esp/thermostat", sizeof(thermostat_topic)); + strlcpy(system_topic, "ems-esp/system", sizeof(system_topic)); // test publishing - EMSESP::EMSESP::mqtt_.publish(boiler_topic, "test me"); + EMSESP::mqtt_.publish(boiler_topic, "test me"); // test receiving EMSESP::mqtt_.incoming(boiler_topic, ""); // test if ignore empty payloads, should return values diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index ab4c0d202..3ade88792 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -49,7 +49,7 @@ void WebAPIService::webAPIService_get(AsyncWebServerRequest * request) { // POST /{device}[/{hc|id}][/{name}] void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVariant & json) { // if no body then treat it as a secure GET - if (not json.is()) { + if (!json.is()) { webAPIService_get(request); return; } @@ -63,10 +63,10 @@ void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVari // reporting back any errors void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) { // check if the user has admin privileges (token is included and authorized) - bool is_admin; + bool is_admin = false; EMSESP::webSettingsService.read([&](WebSettings & settings) { Authentication authentication = _securityManager->authenticateRequest(request); - is_admin = settings.notoken_api | AuthenticationPredicates::IS_ADMIN(authentication); + is_admin = settings.notoken_api || AuthenticationPredicates::IS_ADMIN(authentication); }); // check for query parameters first, the old style from v2 @@ -97,8 +97,8 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) { } // output json buffer - PrettyAsyncJsonResponse * response = new PrettyAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE_DYN); - JsonObject output = response->getRoot(); + auto * response = new PrettyAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE_DYN); + JsonObject output = response->getRoot(); // call command uint8_t return_code = Command::process(request->url().c_str(), is_admin, input, output); diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index 08a11e778..7564de6e5 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -99,10 +99,10 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & if (root["sensors"].is()) { for (const JsonObject sensorJson : root["sensors"].as()) { // create each of the sensor, overwritting any previous settings - SensorCustomization sensor = SensorCustomization(); - sensor.id_str = sensorJson["id_str"].as(); - sensor.name = sensorJson["name"].as(); - sensor.offset = sensorJson["offset"]; + auto sensor = SensorCustomization(); + sensor.id_str = sensorJson["id_str"].as(); + sensor.name = sensorJson["name"].as(); + sensor.offset = sensorJson["offset"]; settings.sensorCustomizations.push_back(sensor); // add to list } } @@ -112,13 +112,13 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & if (root["analogs"].is()) { for (const JsonObject analogJson : root["analogs"].as()) { // create each of the sensor, overwritting any previous settings - AnalogCustomization sensor = AnalogCustomization(); - sensor.id = analogJson["id"]; - sensor.name = analogJson["name"].as(); - sensor.offset = analogJson["offset"]; - sensor.factor = analogJson["factor"]; - sensor.uom = analogJson["uom"]; - sensor.type = analogJson["type"]; + auto sensor = AnalogCustomization(); + sensor.id = analogJson["id"]; + sensor.name = analogJson["name"].as(); + sensor.offset = analogJson["offset"]; + sensor.factor = analogJson["factor"]; + sensor.uom = analogJson["uom"]; + sensor.type = analogJson["type"]; settings.analogCustomizations.push_back(sensor); // add to list } } @@ -127,9 +127,9 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & settings.entityCustomizations.clear(); if (root["exclude_entities"].is()) { for (const JsonObject exclude_entities : root["exclude_entities"].as()) { - EntityCustomization new_entry = EntityCustomization(); - new_entry.product_id = exclude_entities["product_id"]; - new_entry.device_id = exclude_entities["device_id"]; + auto new_entry = EntityCustomization(); + new_entry.product_id = exclude_entities["product_id"]; + new_entry.device_id = exclude_entities["device_id"]; for (const JsonVariant exclude_entity_id : exclude_entities["entity_ids"].as()) { new_entry.entity_ids.push_back(exclude_entity_id.as()); // add entity list @@ -158,11 +158,11 @@ void WebCustomizationService::reset_customization(AsyncWebServerRequest * reques // send back a short list devices used in the customization page void WebCustomizationService::devices(AsyncWebServerRequest * request) { - AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN); + JsonObject root = response->getRoot(); JsonArray devices = root.createNestedArray("devices"); - for (auto & emsdevice : EMSESP::emsdevices) { + for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice->has_entities()) { JsonObject obj = devices.createNestedObject(); obj["i"] = emsdevice->unique_id(); // a unique id @@ -185,18 +185,16 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) { // send back list device entities void WebCustomizationService::device_entities(AsyncWebServerRequest * request, JsonVariant & json) { if (json.is()) { - MsgpackAsyncJsonResponse * response = new MsgpackAsyncJsonResponse(true, EMSESP_JSON_SIZE_XXLARGE_DYN); + auto * response = new MsgpackAsyncJsonResponse(true, EMSESP_JSON_SIZE_XXLARGE_DYN); for (const auto & emsdevice : EMSESP::emsdevices) { - if (emsdevice) { - if (emsdevice->unique_id() == json["id"]) { + if (emsdevice->unique_id() == json["id"]) { #ifndef EMSESP_STANDALONE - JsonArray output = response->getRoot(); - emsdevice->generate_values_web_all(output); + JsonArray output = response->getRoot(); + emsdevice->generate_values_web_all(output); #endif - response->setLength(); - request->send(response); - return; - } + response->setLength(); + request->send(response); + return; } } } diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 85989b9c7..7f331c9c5 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -70,13 +70,13 @@ void WebDataService::scan_devices(AsyncWebServerRequest * request) { // this is used in the dashboard and contains all ems device information // /coreData endpoint void WebDataService::core_data(AsyncWebServerRequest * request) { - AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE_DYN); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE_DYN); + JsonObject root = response->getRoot(); // list is already sorted by device type // Ignore Contoller JsonArray devices = root.createNestedArray("devices"); - for (auto & emsdevice : EMSESP::emsdevices) { + for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice && emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER) { JsonObject obj = devices.createNestedObject(); obj["i"] = emsdevice->unique_id(); // a unique id @@ -102,8 +102,8 @@ void WebDataService::core_data(AsyncWebServerRequest * request) { // /sensorData endpoint // the "sensors" and "analogs" are arrays and must exist void WebDataService::sensor_data(AsyncWebServerRequest * request) { - AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE_DYN); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE_DYN); + JsonObject root = response->getRoot(); // dallas sensors JsonArray sensors = root.createNestedArray("sensors"); @@ -158,23 +158,21 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) { // Compresses the JSON using MsgPack https://msgpack.org/index.html void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant & json) { if (json.is()) { - MsgpackAsyncJsonResponse * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXXLARGE_DYN); + auto * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXXLARGE_DYN); for (const auto & emsdevice : EMSESP::emsdevices) { - if (emsdevice) { - if (emsdevice->unique_id() == json["id"]) { - // wait max 2.5 sec for updated data (post_send_delay is 2 sec) - for (uint16_t i = 0; i < (emsesp::TxService::POST_SEND_DELAY + 500) && EMSESP::wait_validate(); i++) { - delay(1); - } - EMSESP::wait_validate(0); // reset in case of timeout -#ifndef EMSESP_STANDALONE - JsonObject output = response->getRoot(); - emsdevice->generate_values_web(output); -#endif - response->setLength(); - request->send(response); - return; + if (emsdevice->unique_id() == json["id"]) { + // wait max 2.5 sec for updated data (post_send_delay is 2 sec) + for (uint16_t i = 0; i < (emsesp::TxService::POST_SEND_DELAY + 500) && EMSESP::wait_validate(); i++) { + delay(1); } + EMSESP::wait_validate(0); // reset in case of timeout +#ifndef EMSESP_STANDALONE + JsonObject output = response->getRoot(); + emsdevice->generate_values_web(output); +#endif + response->setLength(); + request->send(response); + return; } } } @@ -195,46 +193,44 @@ void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant & // using the unique ID from the web find the real device type // id is the selected device for (const auto & emsdevice : EMSESP::emsdevices) { - if (emsdevice) { - if (emsdevice->unique_id() == unique_id) { - // parse the command as it could have a hc or wwc prefixed, e.g. hc2/seltemp - const char * cmd = dv["c"]; // the command - int8_t id = -1; // default - cmd = Command::parse_command_string(cmd, id); // extract hc or wwc + if (emsdevice->unique_id() == unique_id) { + // parse the command as it could have a hc or wwc prefixed, e.g. hc2/seltemp + const char * cmd = dv["c"]; // the command + int8_t id = -1; // default + cmd = Command::parse_command_string(cmd, id); // extract hc or wwc - // create JSON for output - AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL); - JsonObject output = response->getRoot(); + // create JSON for output + auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL); + JsonObject output = response->getRoot(); - // the data could be in any format, but we need string - // authenticated is always true - JsonVariant data = dv["v"]; // the value in any format - uint8_t return_code = CommandRet::OK; - uint8_t device_type = emsdevice->device_type(); - if (data.is()) { - return_code = Command::call(device_type, cmd, data.as(), true, id, output); - } else if (data.is()) { - char s[10]; - return_code = Command::call(device_type, cmd, Helpers::render_value(s, data.as(), 0), true, id, output); - } else if (data.is()) { - char s[10]; - return_code = Command::call(device_type, cmd, Helpers::render_value(s, (float)data.as(), 1), true, id, output); - } else if (data.is()) { - return_code = Command::call(device_type, cmd, data.as() ? "true" : "false", true, id, output); - } - - // write debug - if (return_code != CommandRet::OK) { - EMSESP::logger().err(F("Write command failed %s (%s)"), (const char *)output["message"], Command::return_code_string(return_code).c_str()); - } else { - EMSESP::logger().debug(F("Write command successful")); - } - - response->setCode((return_code == CommandRet::OK) ? 200 : 204); - response->setLength(); - request->send(response); - return; + // the data could be in any format, but we need string + // authenticated is always true + JsonVariant data = dv["v"]; // the value in any format + uint8_t return_code = CommandRet::OK; + uint8_t device_type = emsdevice->device_type(); + if (data.is()) { + return_code = Command::call(device_type, cmd, data.as(), true, id, output); + } else if (data.is()) { + char s[10]; + return_code = Command::call(device_type, cmd, Helpers::render_value(s, data.as(), 0), true, id, output); + } else if (data.is()) { + char s[10]; + return_code = Command::call(device_type, cmd, Helpers::render_value(s, data.as(), 1), true, id, output); + } else if (data.is()) { + return_code = Command::call(device_type, cmd, data.as() ? "true" : "false", true, id, output); } + + // write debug + if (return_code != CommandRet::OK) { + EMSESP::logger().err(F("Write command failed %s (%s)"), (const char *)output["message"], Command::return_code_string(return_code).c_str()); + } else { + EMSESP::logger().debug(F("Write command successful")); + } + + response->setCode((return_code == CommandRet::OK) ? 200 : 204); + response->setLength(); + request->send(response); + return; } } } diff --git a/src/web/WebLogService.cpp b/src/web/WebLogService.cpp index 133986d9d..357ae03f3 100644 --- a/src/web/WebLogService.cpp +++ b/src/web/WebLogService.cpp @@ -90,7 +90,7 @@ void WebLogService::maximum_log_messages(size_t count) { "local"); } -bool WebLogService::compact() { +bool WebLogService::compact() const { return compact_; } @@ -156,24 +156,24 @@ void WebLogService::loop() { } // convert time to real offset -char * WebLogService::messagetime(char * out, const uint64_t t) { +char * WebLogService::messagetime(char * out, const uint64_t t, const size_t bufsize) { if (!time_offset_) { - strcpy(out, uuid::log::format_timestamp_ms(t, 3).c_str()); + strlcpy(out, uuid::log::format_timestamp_ms(t, 3).c_str(), bufsize); } else { time_t t1 = time_offset_ + t / 1000ULL; - strftime(out, 25, "%F %T", localtime(&t1)); - snprintf(out, 25, "%s.%03d", out, (uint16_t)(t % 1000)); + strftime(out, bufsize, "%F %T", localtime(&t1)); + snprintf(out, bufsize, "%s.%03d", out, (uint16_t)(t % 1000)); } return out; } // send to web eventsource void WebLogService::transmit(const QueuedLogMessage & message) { - DynamicJsonDocument jsonDocument = DynamicJsonDocument(EMSESP_JSON_SIZE_MEDIUM); - JsonObject logEvent = jsonDocument.to(); - char time_string[25]; + auto jsonDocument = DynamicJsonDocument(EMSESP_JSON_SIZE_MEDIUM); + JsonObject logEvent = jsonDocument.to(); + char time_string[25]; - logEvent["t"] = messagetime(time_string, message.content_->uptime_ms); + logEvent["t"] = messagetime(time_string, message.content_->uptime_ms, sizeof(time_string)); logEvent["l"] = message.content_->level; logEvent["i"] = message.id_; logEvent["n"] = message.content_->name; @@ -190,9 +190,9 @@ void WebLogService::transmit(const QueuedLogMessage & message) { // send the complete log buffer to the API, not filtering on log level void WebLogService::fetchLog(AsyncWebServerRequest * request) { - MsgpackAsyncJsonResponse * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN + 192 * log_messages_.size()); - JsonObject root = response->getRoot(); - JsonArray log = root.createNestedArray("events"); + auto * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN + 192 * log_messages_.size()); + JsonObject root = response->getRoot(); + JsonArray log = root.createNestedArray("events"); log_message_id_tail_ = log_messages_.back().id_; last_transmit_ = uuid::get_uptime_ms(); @@ -200,7 +200,7 @@ void WebLogService::fetchLog(AsyncWebServerRequest * request) { JsonObject logEvent = log.createNestedObject(); char time_string[25]; - logEvent["t"] = messagetime(time_string, message.content_->uptime_ms); + logEvent["t"] = messagetime(time_string, message.content_->uptime_ms, sizeof(time_string)); logEvent["l"] = message.content_->level; logEvent["i"] = message.id_; logEvent["n"] = message.content_->name; @@ -213,7 +213,7 @@ void WebLogService::fetchLog(AsyncWebServerRequest * request) { // sets the values like level after a POST void WebLogService::setValues(AsyncWebServerRequest * request, JsonVariant & json) { - if (not json.is()) { + if (!json.is()) { return; } @@ -233,11 +233,11 @@ void WebLogService::setValues(AsyncWebServerRequest * request, JsonVariant & jso // return the current value settings after a GET void WebLogService::getValues(AsyncWebServerRequest * request) { - AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL); - JsonObject root = response->getRoot(); - root["level"] = log_level(); - root["max_messages"] = maximum_log_messages(); - root["compact"] = compact(); + auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL); + JsonObject root = response->getRoot(); + root["level"] = log_level(); + root["max_messages"] = maximum_log_messages(); + root["compact"] = compact(); response->setLength(); request->send(response); } diff --git a/src/web/WebLogService.h b/src/web/WebLogService.h index 5e3ae234f..55ca039f7 100644 --- a/src/web/WebLogService.h +++ b/src/web/WebLogService.h @@ -38,7 +38,7 @@ class WebLogService : public uuid::log::Handler { void log_level(uuid::log::Level level); size_t maximum_log_messages() const; void maximum_log_messages(size_t count); - bool compact(); + bool compact() const; void compact(bool compact); void loop(); @@ -62,9 +62,10 @@ class WebLogService : public uuid::log::Handler { void fetchLog(AsyncWebServerRequest * request); void getValues(AsyncWebServerRequest * request); - char * messagetime(char * out, const uint64_t t); + char * messagetime(char * out, const uint64_t t, const size_t bufsize); + + void setValues(AsyncWebServerRequest * request, JsonVariant & json); - void setValues(AsyncWebServerRequest * request, JsonVariant & json); AsyncCallbackJsonWebHandler setValues_; // for POSTs uint64_t last_transmit_ = 0; // Last transmit time diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp index 6cef7485e..35f7e9897 100644 --- a/src/web/WebSettingsService.cpp +++ b/src/web/WebSettingsService.cpp @@ -271,8 +271,8 @@ void WebSettingsService::save() { // build the json profile to send back void WebSettingsService::board_profile(AsyncWebServerRequest * request, JsonVariant & json) { if (json.is()) { - AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_MEDIUM); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_MEDIUM); + JsonObject root = response->getRoot(); if (json.containsKey("board_profile")) { String board_profile = json["board_profile"]; diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 6cf10c22d..bb9dd3050 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -126,8 +126,8 @@ void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) { } void WebStatusService::webStatusService(AsyncWebServerRequest * request) { - AsyncJsonResponse * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_MEDIUM_DYN); - JsonObject root = response->getRoot(); + auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_MEDIUM_DYN); + JsonObject root = response->getRoot(); root["status"] = EMSESP::bus_status(); // 0, 1 or 2 root["num_devices"] = EMSESP::count_devices(); // excluding Controller @@ -163,7 +163,7 @@ void WebStatusService::webStatusService(AsyncWebServerRequest * request) { } // start the multicast UDP service so EMS-ESP is discoverable via .local -void WebStatusService::mDNS_start() { +void WebStatusService::mDNS_start() const { #ifndef EMSESP_STANDALONE MDNS.end(); if (!MDNS.begin(EMSESP::system_.hostname().c_str())) { diff --git a/src/web/WebStatusService.h b/src/web/WebStatusService.h index 332533ed9..938bcfa32 100644 --- a/src/web/WebStatusService.h +++ b/src/web/WebStatusService.h @@ -32,7 +32,7 @@ class WebStatusService { private: void webStatusService(AsyncWebServerRequest * request); void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info); - void mDNS_start(); + void mDNS_start() const; }; } // namespace emsesp