From 7bad0e04b1091d7073df2564fc81a92772a9427d Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 29 Nov 2022 17:04:05 +0100 Subject: [PATCH 01/52] allow raw telegram sending with other src-id --- src/emsesp.cpp | 2 +- src/telegram.cpp | 25 +++++++++++++++++++++---- src/telegram.h | 1 + 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 5690fc264..769103a79 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -1255,7 +1255,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) { } #endif // check for poll to us, if so send top message from Tx queue immediately and quit - if (poll_id == txservice_.ems_bus_id()) { + if (poll_id == txservice_.get_send_id()) { txservice_.send(); } // send remote room temperature if active diff --git a/src/telegram.cpp b/src/telegram.cpp index 45e86a4f9..c7d2869c9 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -268,6 +268,21 @@ void TxService::send_poll() const { } } +// get src id from next telegram to check poll in emsesp::incoming_telegram +uint8_t TxService::get_send_id() { + static uint32_t count = 0; + if (!tx_telegrams_.empty() && tx_telegrams_.front().telegram_->src != ems_bus_id()) { + if (++count > 500) { // after 500 polls (~3-10 sec) there will be no master poll for this id + tx_telegrams_.pop_front(); + count = 0; + return tx_telegrams_.empty() ? ems_bus_id() : tx_telegrams_.front().telegram_->src; + } + return tx_telegrams_.front().telegram_->src; + } + count = 0; + return ems_bus_id(); +} + // Process the next telegram on the Tx queue // This is sent when we receive a poll request void TxService::send() { @@ -463,7 +478,7 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt } // build header. src, dest and offset have fixed positions - uint8_t src = ems_bus_id(); // data[0]; we can only send data with own bus_id. + uint8_t src = operation == Telegram::Operation::TX_RAW ? data[0] : ems_bus_id(); uint8_t dest = data[1]; uint8_t offset = data[3]; @@ -499,7 +514,9 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt } if (operation == Telegram::Operation::TX_RAW) { - if (dest & 0x80) { + if (src != ems_bus_id()) { + operation = Telegram::Operation::NONE; // do not check reply/ack for other ids + } else if (dest & 0x80) { operation = Telegram::Operation::TX_READ; } else { operation = Telegram::Operation::TX_WRITE; @@ -585,8 +602,8 @@ bool TxService::send_raw(const char * telegram_data) { } } - // check valid length and src - if ((count < 4) || ((data[0] & 0x7F) != ems_bus_id())) { + // check valid length + if (count < 4) { return false; } diff --git a/src/telegram.h b/src/telegram.h index 710558f57..452edcb8b 100644 --- a/src/telegram.h +++ b/src/telegram.h @@ -290,6 +290,7 @@ class TxService : public EMSbus { void start(); void send(); + uint8_t get_send_id(); void add(const uint8_t operation, const uint8_t dest, const uint16_t type_id, From bc31d5402857e4b2734a80c2c1dcd676c8d5bc8a Mon Sep 17 00:00:00 2001 From: Proddy Date: Tue, 29 Nov 2022 21:13:15 +0100 Subject: [PATCH 02/52] package update --- interface/package-lock.json | 14 +++++++------- interface/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/package-lock.json b/interface/package-lock.json index 9bd895607..e49b8950d 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -30,7 +30,7 @@ "react-app-rewired": "^2.2.1", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", - "react-icons": "^4.6.0", + "react-icons": "^4.7.1", "react-router-dom": "^6.4.3", "react-scripts": "5.0.1", "sockette": "^2.0.6", @@ -14540,9 +14540,9 @@ "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, "node_modules/react-icons": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.6.0.tgz", - "integrity": "sha512-rR/L9m9340yO8yv1QT1QurxWQvWpbNHqVX0fzMln2HEb9TEIrQRGsqiNFQfiv9/JEUbyHmHPlNTB2LWm2Ttz0g==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.7.1.tgz", + "integrity": "sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==", "peerDependencies": { "react": "*" } @@ -27705,9 +27705,9 @@ "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, "react-icons": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.6.0.tgz", - "integrity": "sha512-rR/L9m9340yO8yv1QT1QurxWQvWpbNHqVX0fzMln2HEb9TEIrQRGsqiNFQfiv9/JEUbyHmHPlNTB2LWm2Ttz0g==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.7.1.tgz", + "integrity": "sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==", "requires": {} }, "react-is": { diff --git a/interface/package.json b/interface/package.json index 42e2ad379..1886c19e6 100644 --- a/interface/package.json +++ b/interface/package.json @@ -26,7 +26,7 @@ "react-app-rewired": "^2.2.1", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", - "react-icons": "^4.6.0", + "react-icons": "^4.7.1", "react-router-dom": "^6.4.3", "react-scripts": "5.0.1", "sockette": "^2.0.6", From 6b978759caf3530f2c19f50420885d3b9cca7895 Mon Sep 17 00:00:00 2001 From: Proddy Date: Tue, 29 Nov 2022 21:13:26 +0100 Subject: [PATCH 03/52] update --- CHANGELOG_LATEST.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index d0b5685c1..73b2939e3 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -4,7 +4,7 @@ ## Added -- Translations in Web UI and all device entity names (DE, NL, SE, PL, NO, ...) [#22](https://github.com/emsesp/EMS-ESP32/issues/22) +- Translations in Web UI and all device entity names (DE, NL, SE, PL, NO) [#22](https://github.com/emsesp/EMS-ESP32/issues/22) - Add support for Lolin C3 mini [#620](https://github.com/emsesp/EMS-ESP32/pull/620) - Add support for ESP32-S2 [#667](https://github.com/emsesp/EMS-ESP32/pull/667) - Add devices: Greenstar 30Ri boiler, Junkers FW500 thermostat, Buderus BC30 controller @@ -17,8 +17,9 @@ - Add min/max to customization table [#686](https://github.com/emsesp/EMS-ESP32/issues/686) - Add MD5 check [#637](https://github.com/emsesp/EMS-ESP32/issues/637) - Add more bus-ids [#673](https://github.com/emsesp/EMS-ESP32/issues/673) -- Use HA connectivity device class for Status [#751](https://github.com/emsesp/EMS-ESP32/issues/751) +- Use HA connectivity device class for Status, added boot time [#751](https://github.com/emsesp/EMS-ESP32/issues/751) - Add commands for analog sensors outputs +- Support for multiple EMS-ESPs with MQTT and HA [[#759](https://github.com/emsesp/EMS-ESP32/issues/759)] ## Fixed @@ -29,11 +30,13 @@ - Discovery in HomeAssistant don't work with custom base topic. [#596](https://github.com/emsesp/EMS-ESP32/issues/596) Base topic containing `/` are changed to `_` - RF room temperature sensor are shown as thermostat - render mqtt float json values with trailing zero -- removed flash strings +- removed flash strings, to increase available heap memory - reload page after restart button is pressed - analog/dallas values command as list like ems-devices - analog/dallas HA-entities based on id +- MQTT Base is a mandatory field. Removed MQTT topic length from settings. ## **BREAKING CHANGES:** -- When upgrading from 3.4.x you may need to erase the flash on the ESP32 before uploading the firmware. Make sure you make a backup of the settings and customizations via the WebUI (System->Upload/Download) +- When upgrading for the first time from 3.4.x on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases). Make sure you make a backup of the settings and customizations via the WebUI (System->Upload/Download). +- Because of #759 the Home Assistant entity IDs have been renamed From c9ef0bcd7b81763e0e0af51af42a661c62fcbf45 Mon Sep 17 00:00:00 2001 From: Proddy Date: Tue, 29 Nov 2022 21:14:08 +0100 Subject: [PATCH 04/52] remove max_topic_length, make base mandatory --- interface/src/project/validators.ts | 4 ++-- interface/src/types/mqtt.ts | 1 - interface/src/validators/mqtt.ts | 7 ++----- lib/framework/MqttSettingsService.cpp | 2 -- mock-api/server.js | 1 - 5 files changed, 4 insertions(+), 11 deletions(-) diff --git a/interface/src/project/validators.ts b/interface/src/project/validators.ts index 6000e0769..73991f5ac 100644 --- a/interface/src/project/validators.ts +++ b/interface/src/project/validators.ts @@ -72,11 +72,11 @@ export const createSettingsValidator = (settings: Settings) => syslog_host: [{ required: true, message: 'Host is required' }, IP_OR_HOSTNAME_VALIDATOR], syslog_port: [ { required: true, message: 'Port is required' }, - { type: 'number', min: 0, max: 65535, message: 'Port must be between 0 and 65535' } + { type: 'number', min: 0, max: 65535, message: 'Invalid Port' } ], syslog_mark_interval: [ { required: true, message: 'Mark interval is required' }, - { type: 'number', min: 0, max: 10, message: 'Port must be between 0 and 10' } + { type: 'number', min: 0, max: 10, message: ' must be between 0 and 10' } ] }), ...(settings.shower_alert && { diff --git a/interface/src/types/mqtt.ts b/interface/src/types/mqtt.ts index 0e8a10eec..7ecf694ca 100644 --- a/interface/src/types/mqtt.ts +++ b/interface/src/types/mqtt.ts @@ -29,7 +29,6 @@ export interface MqttSettings { client_id: string; keep_alive: number; clean_session: boolean; - max_topic_length: number; publish_time_boiler: number; publish_time_thermostat: number; publish_time_solar: number; diff --git a/interface/src/validators/mqtt.ts b/interface/src/validators/mqtt.ts index b26619e82..362c66ca9 100644 --- a/interface/src/validators/mqtt.ts +++ b/interface/src/validators/mqtt.ts @@ -3,16 +3,13 @@ import { IP_OR_HOSTNAME_VALIDATOR } from './shared'; export const MQTT_SETTINGS_VALIDATOR = new Schema({ host: [{ required: true, message: 'Host is required' }, IP_OR_HOSTNAME_VALIDATOR], + base: { required: true, message: 'Base is required' }, port: [ { required: true, message: 'Port is required' }, - { type: 'number', min: 0, max: 65535, message: 'Port must be between 0 and 65535' } + { type: 'number', min: 0, max: 65535, message: 'Invalid Port' } ], keep_alive: [ { required: true, message: 'Keep alive is required' }, { type: 'number', min: 1, max: 86400, message: 'Keep alive must be between 1 and 86400' } - ], - max_topic_length: [ - { required: true, message: 'Max topic length is required' }, - { type: 'number', min: 16, max: 1024, message: 'Max topic length must be between 16 and 1024' } ] }); diff --git a/lib/framework/MqttSettingsService.cpp b/lib/framework/MqttSettingsService.cpp index 6a2c13413..8ea106423 100644 --- a/lib/framework/MqttSettingsService.cpp +++ b/lib/framework/MqttSettingsService.cpp @@ -154,7 +154,6 @@ void MqttSettings::read(MqttSettings & settings, JsonObject & root) { root["client_id"] = settings.clientId; root["keep_alive"] = settings.keepAlive; root["clean_session"] = settings.cleanSession; - root["max_topic_length"] = settings.maxTopicLength; // added by proddy for EMS-ESP root["publish_time_boiler"] = settings.publish_time_boiler; @@ -186,7 +185,6 @@ StateUpdateResult MqttSettings::update(JsonObject & root, MqttSettings & setting newSettings.clientId = root["client_id"] | FACTORY_MQTT_CLIENT_ID; newSettings.keepAlive = root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE; newSettings.cleanSession = root["clean_session"] | FACTORY_MQTT_CLEAN_SESSION; - newSettings.maxTopicLength = root["max_topic_length"] | FACTORY_MQTT_MAX_TOPIC_LENGTH; newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS; newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN; diff --git a/mock-api/server.js b/mock-api/server.js index 248257958..f37697551 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -219,7 +219,6 @@ mqtt_settings = { client_id: 'ems-esp', keep_alive: 60, clean_session: true, - max_topic_length: 128, publish_time_boiler: 10, publish_time_thermostat: 10, publish_time_solar: 10, From d6a8563cc75e0fc55c16afb8022cd242f280889c Mon Sep 17 00:00:00 2001 From: Proddy Date: Tue, 29 Nov 2022 21:14:31 +0100 Subject: [PATCH 05/52] fixes for #751 --- lib/framework/NTPSettingsService.cpp | 1 - src/system.cpp | 11 ++++++----- src/system.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/framework/NTPSettingsService.cpp b/lib/framework/NTPSettingsService.cpp index 3df0d3118..f20bd8d6a 100644 --- a/lib/framework/NTPSettingsService.cpp +++ b/lib/framework/NTPSettingsService.cpp @@ -83,5 +83,4 @@ void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVari void NTPSettingsService::ntp_received(struct timeval * tv) { // emsesp::EMSESP::logger().info("NTP sync to %d sec", tv->tv_sec); emsesp::EMSESP::system_.ntp_connected(true); - emsesp::EMSESP::system_.send_info_mqtt("connected"); } diff --git a/src/system.cpp b/src/system.cpp index cdeba2322..a8a521ae0 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -536,17 +536,17 @@ void System::loop() { } // send MQTT info topic appended with the version information as JSON, as a retained flag -void System::send_info_mqtt(const char * event_str) { +void System::send_info_mqtt(const char * event_str, bool send_ntp) { StaticJsonDocument doc; doc["event"] = event_str; doc["version"] = EMSESP_APP_VERSION; // if NTP is enabled send the boot_time in local time in ISO 8601 format (eg: 2022-11-15 20:46:38) // https://github.com/emsesp/EMS-ESP32/issues/751 - if (ntp_connected()) { + if (send_ntp) { char time_string[25]; - time_t now = time(nullptr); // grab the current instant in unix seconds - strftime(time_string, 25, "%F %T", localtime(&now)); + time_t now = time(nullptr) - uuid::get_uptime_sec(); + strftime(time_string, 25, "%FT%T%z", localtime(&now)); doc["boot_time"] = time_string; } @@ -1414,7 +1414,8 @@ std::string System::reset_reason(uint8_t cpu) const { // set NTP status void System::ntp_connected(bool b) { if (b != ntp_connected_) { - LOG_INFO(b ? "NTP connected" : "NTP disconnected"); // if changed report it + LOG_INFO(b ? "NTP connected" : "NTP disconnected"); // if changed report it + emsesp::EMSESP::system_.send_info_mqtt("connected", true); // send info topic, but only once } ntp_connected_ = b; ntp_last_check_ = b ? uuid::get_uptime_sec() : 0; diff --git a/src/system.h b/src/system.h index e13efd3a8..f8ee51dc2 100644 --- a/src/system.h +++ b/src/system.h @@ -77,7 +77,7 @@ class System { bool check_upgrade(); bool heartbeat_json(JsonObject & output); void send_heartbeat(); - void send_info_mqtt(const char * event_str); + void send_info_mqtt(const char * event_str, bool send_ntp = false); bool syslog_enabled() { return syslog_enabled_; From 4103bad8de6222da5ca962277e76d182b07eabec Mon Sep 17 00:00:00 2001 From: Proddy Date: Tue, 29 Nov 2022 21:14:40 +0100 Subject: [PATCH 06/52] bump b11 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 76199a5b4..1a4fba9ca 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define EMSESP_APP_VERSION "3.5.0b10" +#define EMSESP_APP_VERSION "3.5.0b11" #if CONFIG_IDF_TARGET_ESP32C3 #define EMSESP_PLATFORM "ESP32-C3"; From 5b5dc6a8cc8dbd5010179c118f51aec87afe8b25 Mon Sep 17 00:00:00 2001 From: Proddy Date: Tue, 29 Nov 2022 21:15:46 +0100 Subject: [PATCH 07/52] #759 use b ase in HA unique_id and object_id --- src/analogsensor.cpp | 4 +-- src/dallassensor.cpp | 7 ++-- src/mqtt.cpp | 85 ++++++++++++++++++++------------------------ 3 files changed, 43 insertions(+), 53 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index cd4b09d7c..38f01fbe8 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -454,13 +454,11 @@ void AnalogSensor::publish_values(const bool force) { // snprintf(str, sizeof(str), "%s_analog_sensor_%s", Mqtt::basename().c_str(), sensor.name().c_str()); snprintf(str, sizeof(str), "analog_sensor_%d", sensor.gpio()); config["object_id"] = str; + config["uniq_id"] = str; // same as object_id snprintf(str, sizeof(str), "%s", sensor.name().c_str()); config["name"] = str; - snprintf(str, sizeof(str), "analogsensor_%d", sensor.gpio()); - config["uniq_id"] = str; - if (sensor.uom() != DeviceValueUOM::NONE) { config["unit_of_meas"] = EMSdevice::uom_to_string(sensor.uom()); } diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index 116a43090..9d933b7d0 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -521,15 +521,14 @@ void DallasSensor::publish_values(const bool force) { // snprintf(str, sizeof(str), "%s_temperature_sensor_%s", Mqtt::basename().c_str(), sensor.id().c_str()); snprintf(str, sizeof(str), "temperature_sensor_%s", sensor.id().c_str()); config["object_id"] = str; + config["uniq_id"] = str; // same as object_id snprintf(str, sizeof(str), "%s", sensor.name().c_str()); config["name"] = str; - snprintf(str, sizeof(str), "dallasensor_%s", sensor.id().c_str()); config["uniq_id"] = str; - - JsonObject dev = config.createNestedObject("dev"); - JsonArray ids = dev.createNestedArray("ids"); + JsonObject dev = config.createNestedObject("dev"); + JsonArray ids = dev.createNestedArray("ids"); ids.add("ems-esp"); char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 2e8b4de4a..b4fe2b7a4 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -591,12 +591,12 @@ void Mqtt::on_connect() { void Mqtt::ha_status() { StaticJsonDocument doc; - doc["uniq_id"] = "ems-esp-system"; - doc["~"] = mqtt_base_; // default ems-esp + doc["uniq_id"] = "ems-esp-system"; + doc["object_id"] = "ems_esp_status"; + doc["~"] = mqtt_base_; // default ems-esp // doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes // doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes doc["stat_t"] = "~/status"; - doc["object_id"] = "ems_esp_status"; doc["name"] = "EMS-ESP status"; doc["payload_on"] = "online"; doc["payload_off"] = "offline"; @@ -950,21 +950,29 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev return; } + + // create the device name auto device_name = EMSdevice::device_type_2_device_name(device_type); // create entity by add the hc/wwc tag if present, separating with a . - char new_entity[50]; + char entity_with_tag[50]; if (tag >= DeviceValueTAG::TAG_HC1) { - snprintf(new_entity, sizeof(new_entity), "%s.%s", EMSdevice::tag_to_mqtt(tag).c_str(), entity); + snprintf(entity_with_tag, sizeof(entity_with_tag), "%s.%s", EMSdevice::tag_to_mqtt(tag).c_str(), entity); } else { - snprintf(new_entity, sizeof(new_entity), "%s", entity); + snprintf(entity_with_tag, sizeof(entity_with_tag), "%s", entity); } - // build unique identifier which will be used in the topic, replacing all . with _ as not to break HA - char uniq[101]; - snprintf(uniq, sizeof(uniq), "%s_%s", device_name, new_entity); - Helpers::replace_char(uniq, '.', '_'); + // build unique identifier which will be used in the topic, also used as object_id + char uniq_id[70]; + snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag); + Helpers::replace_char(uniq_id, '.', '_'); // replacing all . with _ as not to break HA + + // build a config topic that will be prefix onto a HA type (e.g. number, switch) + // e.g. homeassistant/number/ems-esp/thermostat_hc1_manualtemp + char config_topic[70]; + snprintf(config_topic, sizeof(config_topic), "%s/%s_%s/config", mqtt_basename_.c_str(), device_name, entity_with_tag); + Helpers::replace_char(config_topic, '.', '_'); // replacing all . with _ as not to break HA bool set_ha_classes = false; // set to true if we want to set the state class and device class @@ -981,19 +989,19 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev case DeviceValueType::ULONG: // number - https://www.home-assistant.io/integrations/number.mqtt // https://developers.home-assistant.io/docs/core/entity/number - snprintf(topic, sizeof(topic), "number/%s/%s/config", mqtt_basename_.c_str(), uniq); + snprintf(topic, sizeof(topic), "number/%s", config_topic); break; case DeviceValueType::BOOL: // switch - https://www.home-assistant.io/integrations/switch.mqtt - snprintf(topic, sizeof(topic), "switch/%s/%s/config", mqtt_basename_.c_str(), uniq); + snprintf(topic, sizeof(topic), "switch/%s", config_topic); break; case DeviceValueType::ENUM: // select - https://www.home-assistant.io/integrations/select.mqtt - snprintf(topic, sizeof(topic), "select/%s/%s/config", mqtt_basename_.c_str(), uniq); + snprintf(topic, sizeof(topic), "select/%s", config_topic); break; default: // plain old sensor - snprintf(topic, sizeof(topic), "sensor/%s/%s/config", mqtt_basename_.c_str(), uniq); + snprintf(topic, sizeof(topic), "sensor/%s", config_topic); break; } } else { @@ -1001,26 +1009,25 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev set_ha_classes = true; // plain old read only device entity if (type == DeviceValueType::BOOL) { - snprintf(topic, sizeof(topic), "binary_sensor/%s/%s/config", mqtt_basename_.c_str(), uniq); // binary sensor (for booleans) + snprintf(topic, sizeof(topic), "binary_sensor/%s", config_topic); // binary sensor (for booleans) } else { - snprintf(topic, sizeof(topic), "sensor/%s/%s/config", mqtt_basename_.c_str(), uniq); // normal HA sensor + snprintf(topic, sizeof(topic), "sensor/%s", config_topic); // normal HA sensor } } // if we're asking to remove this topic, send an empty payload and exit // https://github.com/emsesp/EMS-ESP32/issues/196 if (remove) { - LOG_DEBUG("Removing HA config for %s", uniq); + LOG_DEBUG("Removing HA config for %s", uniq_id); publish_ha(topic); return; } - bool have_tag = !EMSdevice::tag_to_string(tag).empty(); - // build the payload DynamicJsonDocument doc(EMSESP_JSON_SIZE_HA_CONFIG); - doc["~"] = mqtt_base_; - doc["uniq_id"] = uniq; + doc["~"] = mqtt_base_; + doc["uniq_id"] = uniq_id; + doc["object_id"] = uniq_id; // same as unique_id const char * ic_ha = "ic"; // icon - only set this if there is no device class const char * sc_ha = "state_class"; // state class @@ -1031,8 +1038,8 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev // note: there is no way to handle strings in HA so datetimes (e.g. set_datetime, set_holiday, set_wwswitchtime etc) are excluded if (has_cmd) { // command topic back to EMS-ESP - char command_topic[105]; - snprintf(command_topic, sizeof(command_topic), "~/%s", uniq); + char command_topic[MQTT_TOPIC_MAX_SIZE]; + snprintf(command_topic, sizeof(command_topic), "~/%s", uniq_id); Helpers::replace_char(command_topic, '_', '/'); doc["command_topic"] = command_topic; @@ -1082,31 +1089,19 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev char ha_name[70]; char * F_name = strdup(fullname); F_name[0] = toupper(F_name[0]); // capitalize first letter - if (have_tag) { - snprintf(ha_name, sizeof(ha_name), "%s %s", EMSdevice::tag_to_string(tag).c_str(), F_name); - } else { + if (EMSdevice::tag_to_string(tag).empty()) { snprintf(ha_name, sizeof(ha_name), "%s", F_name); - } - free(F_name); - doc["name"] = ha_name; - - // entity id is generated from the name, see https://www.home-assistant.io/docs/mqtt/discovery/#use-object_id-to-influence-the-entity-id - // so we override it to make it unique using entity_id - // See https://github.com/emsesp/EMS-ESP32/issues/596 - // keep it compatible to v3.4, use english fullname, no prefix (basename prefix commented out) - char object_id[130]; - if (have_tag) { - snprintf(object_id, sizeof(object_id), "%s_%s_%s", device_name, EMSdevice::tag_to_string(tag, false).c_str(), en_name); } else { - snprintf(object_id, sizeof(object_id), "%s_%s", device_name, en_name); + snprintf(ha_name, sizeof(ha_name), "%s %s", EMSdevice::tag_to_string(tag).c_str(), F_name); } - doc["object_id"] = object_id; + free(F_name); // very important! + doc["name"] = ha_name; // value template // if its nested mqtt format then use the appended entity name, otherwise take the original char val_tpl[75]; if (is_nested()) { - snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", new_entity); + snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity_with_tag); } else { snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity); } @@ -1230,8 +1225,7 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, char currtemp_s[30]; char mode_str_tpl[400]; char name_s[10]; - char id_s[20]; - char uniq_id_s[30]; + char uniq_id_s[60]; char temp_cmd_s[30]; char mode_cmd_s[30]; char min_s[10]; @@ -1269,18 +1263,17 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, hc_mode_s, hc_mode_s); - snprintf(id_s, sizeof(id_s), "thermostat_hc%d", hc_num); snprintf(name_s, sizeof(name_s), "Hc%d", hc_num); - snprintf(uniq_id_s, sizeof(uniq_id_s), "thermostat_hc%d", hc_num); + snprintf(uniq_id_s, sizeof(uniq_id_s), "%s_thermostat_hc%d", mqtt_basename_.c_str(), hc_num); // add basename snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num); snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num); StaticJsonDocument doc; doc["~"] = mqtt_base_; - doc["object_id"] = id_s; - doc["name"] = name_s; doc["uniq_id"] = uniq_id_s; + doc["object_id"] = uniq_id_s; // same as uniq_id + doc["name"] = name_s; doc["mode_stat_t"] = topic_t; doc["mode_stat_tpl"] = mode_str_tpl; doc["temp_cmd_t"] = temp_cmd_s; From 085f5ff22fcbd50f31e43e0967b126f0c2fc82ed Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Wed, 30 Nov 2022 14:00:19 +0100 Subject: [PATCH 08/52] change GH tagged_release to web language 'en' #754 --- .github/workflows/tagged_release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tagged_release.yml b/.github/workflows/tagged_release.yml index 8e169e249..9818be2af 100644 --- a/.github/workflows/tagged_release.yml +++ b/.github/workflows/tagged_release.yml @@ -31,6 +31,7 @@ jobs: cd interface npm ci npx typesafe-i18n --no-watch + sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts npm run build - name: Build firmware From 996063d76d4aa9504aecc54d7ea0485a40a90f15 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Wed, 30 Nov 2022 16:06:06 +0100 Subject: [PATCH 09/52] show received (ignored) handlers for devices without registered telegrams. --- src/emsdevice.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 90dac5a49..0fe91f565 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -350,14 +350,8 @@ void EMSdevice::show_telegram_handlers(uuid::console::Shell & shell) const { // list all the telegram type IDs for this device, outputting to a string (max size 200) char * EMSdevice::show_telegram_handlers(char * result, const size_t len, const uint8_t handlers) { - uint8_t size = telegram_functions_.size(); - strlcpy(result, "", len); - if (!size) { - return result; - } - uint8_t i = 0; for (const auto & tf : telegram_functions_) { if (handlers == Handlers::ALL || (handlers == Handlers::RECEIVED && tf.received_ && !tf.fetch_) From 4168a08276c99738bb2246d3b0d6031c1f1b64e3 Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:16:41 +0100 Subject: [PATCH 10/52] #751 move ntp sending info topic back --- lib/framework/NTPSettingsService.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/framework/NTPSettingsService.cpp b/lib/framework/NTPSettingsService.cpp index f20bd8d6a..1697ad3d1 100644 --- a/lib/framework/NTPSettingsService.cpp +++ b/lib/framework/NTPSettingsService.cpp @@ -83,4 +83,5 @@ void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVari void NTPSettingsService::ntp_received(struct timeval * tv) { // emsesp::EMSESP::logger().info("NTP sync to %d sec", tv->tv_sec); emsesp::EMSESP::system_.ntp_connected(true); + emsesp::EMSESP::system_.send_info_mqtt("connected", true); // send info topic with NTP time } From 424234ec489aa903915a9be2da2344893d892b27 Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:16:57 +0100 Subject: [PATCH 11/52] default send_response is false for standalone testing --- lib_standalone/ESP8266React.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_standalone/ESP8266React.h b/lib_standalone/ESP8266React.h index 4c17cc4aa..96590bef2 100644 --- a/lib_standalone/ESP8266React.h +++ b/lib_standalone/ESP8266React.h @@ -74,7 +74,7 @@ class DummySettings { String base = "ems-esp"; bool publish_single = false; bool publish_single2cmd = false; - bool send_response = true; + bool send_response = false; // don't send response String host = "192.168.1.4"; uint16_t port = 1883; String clientId = "ems-esp"; From 7f18dd942fc7fc776bc0cd735102878a0690ac61 Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:17:41 +0100 Subject: [PATCH 12/52] add mqtt base to topic - #759 --- src/analogsensor.cpp | 3 +-- src/dallassensor.cpp | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 38f01fbe8..69cd7e8a6 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -451,8 +451,7 @@ void AnalogSensor::publish_values(const bool force) { } config["val_tpl"] = str; - // snprintf(str, sizeof(str), "%s_analog_sensor_%s", Mqtt::basename().c_str(), sensor.name().c_str()); - snprintf(str, sizeof(str), "analog_sensor_%d", sensor.gpio()); + snprintf(str, sizeof(str), "%s_analog_sensor_%s", Mqtt::basename().c_str(), sensor.name().c_str()); config["object_id"] = str; config["uniq_id"] = str; // same as object_id diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index 9d933b7d0..ccfc7438c 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -518,15 +518,13 @@ void DallasSensor::publish_values(const bool force) { } config["val_tpl"] = str; - // snprintf(str, sizeof(str), "%s_temperature_sensor_%s", Mqtt::basename().c_str(), sensor.id().c_str()); - snprintf(str, sizeof(str), "temperature_sensor_%s", sensor.id().c_str()); + snprintf(str, sizeof(str), "%s_temperature_sensor_%s", Mqtt::basename().c_str(), sensor.id().c_str()); config["object_id"] = str; config["uniq_id"] = str; // same as object_id snprintf(str, sizeof(str), "%s", sensor.name().c_str()); config["name"] = str; - config["uniq_id"] = str; JsonObject dev = config.createNestedObject("dev"); JsonArray ids = dev.createNestedArray("ids"); ids.add("ems-esp"); From 048bd877da5f7d37955c5df6a2519655ff924427 Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:17:55 +0100 Subject: [PATCH 13/52] fix tests for MQTT --- src/test/test.cpp | 51 ++++++++++++++++++++++++++++++++--------------- src/test/test.h | 4 ++-- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/test/test.cpp b/src/test/test.cpp index 3135f6ba4..44fce64f1 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -1397,9 +1397,21 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // add a boiler add_device(0x08, 123); // Nefit Trendline - // add a thermostat - add_device(0x18, 157); // Bosch CR100 - https://github.com/emsesp/EMS-ESP/issues/355 + // add some boiler data + // Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25) + uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A, + 0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00}); + // Boiler -> Thermostat, UBAParameterWW(0x33), telegram: 08 97 33 00 23 24 (#data=2) + uart_telegram({0x08, 0x98, 0x33, 0x00, 0x23, 0x24}); + + // Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13) + uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00}); + + // add a thermostat + add_device(0x18, 157); // Bosch CR100 + + // add some thermostat data // RCPLUSStatusMessage_HC1(0x01A5) - HC1 uart_telegram({0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24, 0x03, 0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03}); @@ -1412,11 +1424,13 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const char boiler_topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; char thermostat_topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; + char thermostat_topic_hc1[Mqtt::MQTT_TOPIC_MAX_SIZE]; char system_topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; Mqtt::show_mqtt(shell); // show queue strlcpy(boiler_topic, "ems-esp/boiler", sizeof(boiler_topic)); strlcpy(thermostat_topic, "ems-esp/thermostat", sizeof(thermostat_topic)); + strlcpy(thermostat_topic_hc1, "ems-esp/thermostat/hc1", sizeof(thermostat_topic)); strlcpy(system_topic, "ems-esp/system", sizeof(system_topic)); // test publishing @@ -1425,11 +1439,13 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // test receiving EMSESP::mqtt_.incoming(boiler_topic, ""); // test if ignore empty payloads, should return values - EMSESP::mqtt_.incoming(boiler_topic, "12345"); // error: invalid format - EMSESP::mqtt_.incoming("bad_topic", "123456"); // error: no matching topic - EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"garbage\",\"data\":22.52}"); // error: should report error + // these all should fail + EMSESP::mqtt_.incoming(boiler_topic, "12345"); // error: invalid format + EMSESP::mqtt_.incoming("bad_topic", "123456"); // error: no matching topic + EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"garbage\",\"data\":22.52}"); // error: should report error + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"control\",\"data\":\"1\"}"); // RC35 only, should error - EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"comfort\",\"data\":\"eco\"}"); + // these all should pass EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"wwactivated\",\"data\":\"1\"}"); // with quotes EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"wwactivated\",\"data\":1}"); // without quotes EMSESP::mqtt_.incoming(boiler_topic, "{\"cmd\":\"selflowtemp\",\"data\":55}"); @@ -1437,20 +1453,23 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // test direct commands EMSESP::mqtt_.incoming("ems-esp/boiler/selflowtemp", "56"); - EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"send\",\"data\":\"01 02 03 04 05\"}"); - EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"pin\",\"id\":12,\"data\":\"1\"}"); + EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"send\",\"data\":\"01 02 03 04 05\"}"); // TODO check if works + // EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"pin\",\"id\":12,\"data\":\"1\"}"); EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"wwmode\",\"data\":\"auto\"}"); - EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"control\",\"data\":\"1\"}"); // RC35 only, should error EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"typo\",\"id\":2}"); // invalid mode EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"id\":2}"); - EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"hc\":2}"); // hc as number - EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":19.5,\"hc\":1}"); // data as number - EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"hc\":\"2\"}"); // hc as string. should error as no hc2 - EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":22.56}"); - EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":22}"); - EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"data\":\"22.56\"}"); - EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"temp\",\"id\":2,\"data\":22}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"mode\",\"data\":\"auto\",\"hc\":2}"); // hc as number + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"data\":19.5,\"hc\":1}"); // data as number + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"data\":\"auto\",\"hc\":\"2\"}"); // hc as string. should error as no hc2 + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"data\":22.56}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"data\":22}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"data\":\"22.56\"}"); + EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"seltemp\",\"id\":2,\"data\":22}"); + + // test with hc + EMSESP::mqtt_.incoming("ems-esp/thermostat/hc1/seltemp", "30"); + EMSESP::mqtt_.incoming("ems-esp/thermostat/hc2/seltemp", "32"); // test single commands EMSESP::mqtt_.incoming(thermostat_topic, "auto"); diff --git a/src/test/test.h b/src/test/test.h index af16002f3..e8d7a287e 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -30,8 +30,8 @@ namespace emsesp { // #define EMSESP_DEBUG_DEFAULT "solar" // #define EMSESP_DEBUG_DEFAULT "mixer" // #define EMSESP_DEBUG_DEFAULT "web" -// #define EMSESP_DEBUG_DEFAULT "mqtt" -#define EMSESP_DEBUG_DEFAULT "general" +#define EMSESP_DEBUG_DEFAULT "mqtt" +// #define EMSESP_DEBUG_DEFAULT "general" // #define EMSESP_DEBUG_DEFAULT "boiler" // #define EMSESP_DEBUG_DEFAULT "mqtt2" // #define EMSESP_DEBUG_DEFAULT "mqtt_nested" From eafe358deb379df5f9f18da44f88745c559d7e3f Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:18:15 +0100 Subject: [PATCH 14/52] shower uses mqtt base - #759 --- src/shower.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/shower.cpp b/src/shower.cpp index d2cb1c678..01fa187cb 100644 --- a/src/shower.cpp +++ b/src/shower.cpp @@ -151,10 +151,13 @@ void Shower::set_shower_state(bool state, bool force) { ha_configdone_ = true; StaticJsonDocument doc; - doc["name"] = "Shower Active"; - doc["uniq_id"] = "shower_active"; - doc["~"] = Mqtt::base(); - doc["stat_t"] = "~/shower_active"; + doc["name"] = "Shower Active"; + char str[70]; + snprintf(str, sizeof(str), "%s_shower_active", Mqtt::basename().c_str()); + doc["uniq_id"] = str; + doc["object_id"] = str; + doc["~"] = Mqtt::base(); + doc["stat_t"] = "~/shower_active"; // always render boolean as strings for HA char result[12]; From 5d10b284335125919d0933cb30b7a1d847faf59e Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:19:21 +0100 Subject: [PATCH 15/52] rename boot time, free mem, free app, add web buffer to info command output --- src/system.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/system.cpp b/src/system.cpp index a8a521ae0..1b91c93dc 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -547,7 +547,7 @@ void System::send_info_mqtt(const char * event_str, bool send_ntp) { char time_string[25]; time_t now = time(nullptr) - uuid::get_uptime_sec(); strftime(time_string, 25, "%FT%T%z", localtime(&now)); - doc["boot_time"] = time_string; + doc["boot time"] = time_string; } #ifndef EMSESP_STANDALONE @@ -1071,9 +1071,9 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3); // node["uptime (seconds)"] = uuid::get_uptime_sec(); #ifndef EMSESP_STANDALONE - node["freemem"] = ESP.getFreeHeap() / 1024; // kilobytes + node["free mem"] = ESP.getFreeHeap() / 1024; // kilobytes node["maxalloc"] = ESP.getMaxAllocHeap() / 1024; // kilobytes - node["free_app"] = EMSESP::system_.appFree(); // kilobytes + node["free app"] = EMSESP::system_.appFree(); // kilobytes #endif node["reset reason"] = EMSESP::system_.reset_reason(0) + " / " + EMSESP::system_.reset_reason(1); @@ -1264,6 +1264,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp node["enum format"] = settings.enum_format; node["analog enabled"] = settings.analog_enabled; node["telnet enabled"] = settings.telnet_enabled; + node["web log buffer"] = settings.weblog_buffer; }); // Devices - show EMS devices if we have any @@ -1414,9 +1415,9 @@ std::string System::reset_reason(uint8_t cpu) const { // set NTP status void System::ntp_connected(bool b) { if (b != ntp_connected_) { - LOG_INFO(b ? "NTP connected" : "NTP disconnected"); // if changed report it - emsesp::EMSESP::system_.send_info_mqtt("connected", true); // send info topic, but only once + LOG_INFO(b ? "NTP connected" : "NTP disconnected"); // if changed report it } + ntp_connected_ = b; ntp_last_check_ = b ? uuid::get_uptime_sec() : 0; } @@ -1427,6 +1428,7 @@ bool System::ntp_connected() { if ((uuid::get_uptime_sec() - ntp_last_check_ > 7201) && ntp_connected_) { ntp_connected(false); } + return ntp_connected_; } From d450464a1ab3ef7053c0ad591e9b8aa3c72bd796 Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:19:57 +0100 Subject: [PATCH 16/52] hardcode "response" topic --- src/emsesp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 5690fc264..16cc4e0e9 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -589,7 +589,7 @@ void EMSESP::publish_response(std::shared_ptr telegram) { doc["value"] = value; } - Mqtt::publish(F_(response), doc.as()); + Mqtt::publish("response", doc.as()); } // builds json with the detail of each value, for a specific EMS device type or the dallas sensor From 557b532f740058f5d379b2e60fc662fa2f8cca97 Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:20:08 +0100 Subject: [PATCH 17/52] added comment --- src/emsdevice.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 90dac5a49..17c99a0ca 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -623,6 +623,7 @@ bool EMSdevice::is_readable(const void * value_p) const { } // check if value/command is readonly +// matches valid tags too bool EMSdevice::is_readonly(const std::string & cmd, const int8_t id) const { uint8_t tag = id > 0 ? DeviceValueTAG::TAG_HC1 + id - 1 : DeviceValueTAG::TAG_NONE; for (const auto & dv : devicevalues_) { From bcd8992abc56ac0a35c6ae59e54a4b26378de7f8 Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:20:47 +0100 Subject: [PATCH 18/52] added INVALID command return err, so detects when incorrect hc given in a command --- src/command.cpp | 31 +++++++++++++++++++++---------- src/command.h | 12 ++++++------ 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index 8c6cd7019..6c8936976 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -179,6 +179,8 @@ std::string Command::return_code_string(const uint8_t return_code) { return "Not Authorized"; case CommandRet::FAIL: return "Failed"; + case CommandRet::INVALID: + return "Invalid"; default: break; } @@ -270,18 +272,22 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * } auto description = Helpers::translated_word(cf->description_); + char info_s[100]; + if (strlen(description)) { + snprintf(info_s, sizeof(info_s), "'%s/%s' (%s)", dname, cmd, description); + } else { + snprintf(info_s, sizeof(info_s), "'%s/%s'", dname, cmd); + } + + std::string ro = EMSESP::system_.readonly_mode() ? "[readonly] " : ""; if ((value == nullptr) || (strlen(value) == 0)) { - if (EMSESP::system_.readonly_mode()) { - LOG_INFO(("[readonly] Calling command '%s/%s' (%s)"), dname, cmd, description); - } else { - LOG_DEBUG(("Calling command '%s/%s' (%s)"), dname, cmd, description); - } + LOG_INFO(("%sCalling command %s"), ro.c_str(), info_s); } else { - if (EMSESP::system_.readonly_mode()) { - LOG_INFO(("[readonly] Calling command '%s/%s' (%s) with value %s"), dname, cmd, description, value); + if (id > 0) { + LOG_INFO(("%sCalling command %s with value %s and id %d"), ro.c_str(), info_s, value, id); } else { - LOG_DEBUG(("Calling command '%s/%s' (%s) with value %s"), dname, cmd, description, value); + LOG_INFO(("%sCalling command %s with value %s"), ro.c_str(), info_s, value); } } @@ -290,8 +296,13 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * return_code = ((cf->cmdfunction_json_)(value, id, output)) ? CommandRet::OK : CommandRet::ERROR; } - if (cf->cmdfunction_ && !EMSESP::cmd_is_readonly(device_type, cmd, id)) { - return_code = ((cf->cmdfunction_)(value, id)) ? CommandRet::OK : CommandRet::ERROR; + // check if read-only. This also checks for valid tags (e.g. heating circuits) + if (cf->cmdfunction_) { + if (EMSESP::cmd_is_readonly(device_type, cmd, id)) { + return_code = CommandRet::INVALID; // readonly or invalid hc + } else { + return_code = ((cf->cmdfunction_)(value, id)) ? CommandRet::OK : CommandRet::ERROR; + } } // report back diff --git a/src/command.h b/src/command.h index d131f0574..187a213d7 100644 --- a/src/command.h +++ b/src/command.h @@ -40,12 +40,12 @@ enum CommandFlag : uint8_t { // return status after calling a Command enum CommandRet : uint8_t { - FAIL = 0, // 0 or FALSE - OK, // 1 or TRUE - NOT_FOUND, // 2 - ERROR, // 3 - NOT_ALLOWED // needs authentication - + FAIL = 0, // 0 or FALSE + OK, // 1 or TRUE + NOT_FOUND, // 2 + ERROR, // 3 + NOT_ALLOWED, // 4 - needs authentication + INVALID // 5 - invalid (tag) }; using cmd_function_p = std::function; From ba1813c7674e2cc1b313fd77124d977f24739aa4 Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:21:03 +0100 Subject: [PATCH 19/52] removed en_name --- src/mqtt.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mqtt.h b/src/mqtt.h index 406752fa8..65e4fcad7 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -94,7 +94,6 @@ class Mqtt { static void publish_ha_sensor_config(uint8_t type, uint8_t tag, const char * const fullname, - const char * const en_name, const uint8_t device_type, const char * const entity, const uint8_t uom, From e8d6c4d4513af1e31080e2edec994d54baac31dd Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:21:19 +0100 Subject: [PATCH 20/52] add new ReturnCmd error called INVALID --- src/web/WebAPIService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index 085aec367..0b4de5c36 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -136,7 +136,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) { // send the json that came back from the command call // FAIL, OK, NOT_FOUND, ERROR, NOT_ALLOWED = 400 (bad request), 200 (OK), 400 (not found), 400 (bad request), 401 (unauthorized) - int ret_codes[5] = {400, 200, 400, 400, 401}; + int ret_codes[6] = {400, 200, 400, 400, 401, 400}; response->setCode(ret_codes[return_code]); response->setLength(); response->setContentType("application/json; charset=utf-8"); From e3c94cc1f74ed3310865658104b3116294f80cb8 Mon Sep 17 00:00:00 2001 From: Proddy Date: Wed, 30 Nov 2022 21:21:32 +0100 Subject: [PATCH 21/52] updates for #759 --- src/mqtt.cpp | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/mqtt.cpp b/src/mqtt.cpp index b4fe2b7a4..43f0c8d3c 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -280,6 +280,7 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) cons } return; } + // for misconfigured mqtt servers and publish2command ignore echos if (publish_single_ && publish_single2cmd_ && lasttopic_ == topic && lastpayload_ == message) { LOG_DEBUG("Received echo message %s: %s", topic, message); @@ -291,11 +292,12 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) cons // 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)) && (mf.mqtt_subfunction_)) { if (!(mf.mqtt_subfunction_)(message)) { LOG_ERROR("error: invalid payload %s for this topic %s", message, topic); if (send_response_) { - Mqtt::publish(F_(response), "error: invalid data"); + Mqtt::publish("response", "error: invalid data"); } } return; @@ -330,12 +332,12 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) cons } LOG_ERROR(error); if (send_response_) { - Mqtt::publish(F_(response), error); + Mqtt::publish("response", error); } } else { // all good, send back json output from call if (send_response_) { - Mqtt::publish(F_(response), output); + Mqtt::publish("response", output); } } } @@ -904,7 +906,6 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model, publish_ha_sensor_config(dv.type, dv.tag, dv.get_fullname().c_str(), - (dv.fullname ? dv.fullname[0] : nullptr), // EN name dv.device_type, dv.short_name, dv.uom, @@ -925,7 +926,7 @@ void Mqtt::publish_system_ha_sensor_config(uint8_t type, const char * name, cons JsonArray ids = dev_json.createNestedArray("ids"); ids.add("ems-esp"); - publish_ha_sensor_config(type, DeviceValueTAG::TAG_HEARTBEAT, name, name, EMSdevice::DeviceType::SYSTEM, entity, uom, false, false, nullptr, 0, 0, 0, dev_json); + publish_ha_sensor_config(type, DeviceValueTAG::TAG_HEARTBEAT, name, EMSdevice::DeviceType::SYSTEM, entity, uom, false, false, nullptr, 0, 0, 0, dev_json); } // MQTT discovery configs @@ -934,7 +935,6 @@ void Mqtt::publish_system_ha_sensor_config(uint8_t type, const char * name, cons void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdevice::DeviceValueType uint8_t tag, // EMSdevice::DeviceValueTAG const char * const fullname, // fullname, already translated - const char * const en_name, // original name const uint8_t device_type, // EMSdevice::DeviceType const char * const entity, // same as shortname const uint8_t uom, // EMSdevice::DeviceValueUOM (0=NONE) @@ -946,19 +946,17 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev const int16_t dv_set_max, const JsonObject & dev_json) { // ignore if name (fullname) is empty - if (fullname == nullptr || en_name == nullptr) { + if (!fullname) { return; } - - // create the device name auto device_name = EMSdevice::device_type_2_device_name(device_type); - // create entity by add the hc/wwc tag if present, separating with a . + // create entity by add the hc/wwc tag if present, separating with a _ char entity_with_tag[50]; if (tag >= DeviceValueTAG::TAG_HC1) { - snprintf(entity_with_tag, sizeof(entity_with_tag), "%s.%s", EMSdevice::tag_to_mqtt(tag).c_str(), entity); + snprintf(entity_with_tag, sizeof(entity_with_tag), "%s_%s", EMSdevice::tag_to_mqtt(tag).c_str(), entity); } else { snprintf(entity_with_tag, sizeof(entity_with_tag), "%s", entity); } @@ -966,13 +964,11 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev // build unique identifier which will be used in the topic, also used as object_id char uniq_id[70]; snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag); - Helpers::replace_char(uniq_id, '.', '_'); // replacing all . with _ as not to break HA // build a config topic that will be prefix onto a HA type (e.g. number, switch) // e.g. homeassistant/number/ems-esp/thermostat_hc1_manualtemp char config_topic[70]; snprintf(config_topic, sizeof(config_topic), "%s/%s_%s/config", mqtt_basename_.c_str(), device_name, entity_with_tag); - Helpers::replace_char(config_topic, '.', '_'); // replacing all . with _ as not to break HA bool set_ha_classes = false; // set to true if we want to set the state class and device class @@ -1005,8 +1001,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev break; } } else { - // these are Read only sensors. We can set the device class and state class - set_ha_classes = true; + set_ha_classes = true; // these are Read only sensors. We can set the device class and state class // plain old read only device entity if (type == DeviceValueType::BOOL) { snprintf(topic, sizeof(topic), "binary_sensor/%s", config_topic); // binary sensor (for booleans) @@ -1025,7 +1020,6 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev // build the payload DynamicJsonDocument doc(EMSESP_JSON_SIZE_HA_CONFIG); - doc["~"] = mqtt_base_; doc["uniq_id"] = uniq_id; doc["object_id"] = uniq_id; // same as unique_id @@ -1039,8 +1033,11 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev if (has_cmd) { // command topic back to EMS-ESP char command_topic[MQTT_TOPIC_MAX_SIZE]; - snprintf(command_topic, sizeof(command_topic), "~/%s", uniq_id); - Helpers::replace_char(command_topic, '_', '/'); + if (tag >= DeviceValueTAG::TAG_HC1) { + snprintf(command_topic, sizeof(command_topic), "%s/%s/%s/%s", mqtt_basename_.c_str(), device_name, EMSdevice::tag_to_mqtt(tag).c_str(), entity); + } else { + snprintf(command_topic, sizeof(command_topic), "%s/%s/%s", mqtt_basename_.c_str(), device_name, entity); + } doc["command_topic"] = command_topic; // for enums, add options @@ -1082,7 +1079,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev // state topic char stat_t[MQTT_TOPIC_MAX_SIZE]; - snprintf(stat_t, sizeof(stat_t), "~/%s", tag_to_topic(device_type, tag).c_str()); + snprintf(stat_t, sizeof(stat_t), "%s/%s", mqtt_basename_.c_str(), tag_to_topic(device_type, tag).c_str()); doc["stat_t"] = stat_t; // friendly name = @@ -1090,7 +1087,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev char * F_name = strdup(fullname); F_name[0] = toupper(F_name[0]); // capitalize first letter if (EMSdevice::tag_to_string(tag).empty()) { - snprintf(ha_name, sizeof(ha_name), "%s", F_name); + snprintf(ha_name, sizeof(ha_name), "%s", F_name); // no tag } else { snprintf(ha_name, sizeof(ha_name), "%s %s", EMSdevice::tag_to_string(tag).c_str(), F_name); } @@ -1098,10 +1095,14 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev doc["name"] = ha_name; // value template - // if its nested mqtt format then use the appended entity name, otherwise take the original + // if its nested mqtt format then use the appended entity name, otherwise take the original name char val_tpl[75]; if (is_nested()) { - snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity_with_tag); + if (tag >= DeviceValueTAG::TAG_HC1) { + snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s.%s}}", EMSdevice::tag_to_mqtt(tag).c_str(), entity); + } else { + snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity); + } } else { snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity); } From 9053e7ac88c86f4a97736e42c4a4d5e5ae34f350 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 4 Dec 2022 10:32:37 +0100 Subject: [PATCH 22/52] minor renaming --- src/system.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/system.cpp b/src/system.cpp index 1b91c93dc..1fbfe9aa9 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -552,7 +552,7 @@ void System::send_info_mqtt(const char * event_str, bool send_ntp) { #ifndef EMSESP_STANDALONE if (EMSESP::system_.ethernet_connected()) { - doc["connection"] = "ethernet"; + doc["network"] = "ethernet"; doc["hostname"] = ETH.getHostname(); doc["MAC"] = ETH.macAddress(); doc["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask()); @@ -562,7 +562,7 @@ void System::send_info_mqtt(const char * event_str, bool send_ntp) { doc["IPv6 address"] = uuid::printable_to_string(ETH.localIPv6()); } } else if (WiFi.status() == WL_CONNECTED) { - doc["connection"] = "wifi"; + doc["network"] = "wifi"; doc["hostname"] = WiFi.getHostname(); doc["SSID"] = WiFi.SSID(); doc["BSSID"] = WiFi.BSSIDstr(); @@ -896,19 +896,19 @@ void System::show_system(uuid::console::Shell & shell) { shell.println("Network:"); switch (WiFi.status()) { case WL_IDLE_STATUS: - shell.printfln(" Network: Idle"); + shell.printfln(" Status: Idle"); break; case WL_NO_SSID_AVAIL: - shell.printfln(" Network: Network not found"); + shell.printfln(" Status: Network not found"); break; case WL_SCAN_COMPLETED: - shell.printfln(" Network: Network scan complete"); + shell.printfln(" Status: Network scan complete"); break; case WL_CONNECTED: - shell.printfln(" Network: connected"); + shell.printfln(" Status: connected"); shell.printfln(" SSID: %s", WiFi.SSID().c_str()); shell.printfln(" BSSID: %s", WiFi.BSSIDstr().c_str()); shell.printfln(" RSSI: %d dBm (%d %%)", WiFi.RSSI(), wifi_quality(WiFi.RSSI())); @@ -943,7 +943,7 @@ void System::show_system(uuid::console::Shell & shell) { // show Ethernet if connected if (ethernet_connected_) { shell.println(); - shell.printfln(" Ethernet Network: connected"); + shell.printfln(" Status: Ethernet connected"); shell.printfln(" MAC address: %s", ETH.macAddress().c_str()); shell.printfln(" Hostname: %s", ETH.getHostname()); shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str()); @@ -1071,9 +1071,9 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3); // node["uptime (seconds)"] = uuid::get_uptime_sec(); #ifndef EMSESP_STANDALONE - node["free mem"] = ESP.getFreeHeap() / 1024; // kilobytes - node["maxalloc"] = ESP.getMaxAllocHeap() / 1024; // kilobytes - node["free app"] = EMSESP::system_.appFree(); // kilobytes + node["free mem"] = ESP.getFreeHeap() / 1024; // kilobytes + node["max alloc"] = ESP.getMaxAllocHeap() / 1024; // kilobytes + node["free app"] = EMSESP::system_.appFree(); // kilobytes #endif node["reset reason"] = EMSESP::system_.reset_reason(0) + " / " + EMSESP::system_.reset_reason(1); @@ -1081,7 +1081,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp // Network Status node = output.createNestedObject("Network Info"); if (EMSESP::system_.ethernet_connected()) { - node["connection"] = "Ethernet"; + node["network"] = "Ethernet"; node["hostname"] = ETH.getHostname(); node["MAC"] = ETH.macAddress(); node["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask()); @@ -1091,8 +1091,8 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp node["IPv6 address"] = uuid::printable_to_string(ETH.localIPv6()); } } else if (WiFi.status() == WL_CONNECTED) { - node["connection"] = "WiFi"; - node["hostname"] = WiFi.getHostname(); + node["network"] = "WiFi"; + node["hostname"] = WiFi.getHostname(); // node["SSID"] = WiFi.SSID(); // node["BSSID"] = WiFi.BSSIDstr(); node["RSSI"] = WiFi.RSSI(); @@ -1150,7 +1150,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp } EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & settings) { node["enabled"] = settings.enabled; - node["client_id"] = settings.clientId; + node["client id"] = settings.clientId; node["keep alive"] = settings.keepAlive; node["clean session"] = settings.cleanSession; node["base"] = settings.base; @@ -1245,7 +1245,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp node["phy type"] = settings.phy_type; if (settings.phy_type != PHY_type::PHY_TYPE_NONE) { node["eth power"] = settings.eth_power; - node["eth phy_addr"] = settings.eth_phy_addr; + node["eth phy addr"] = settings.eth_phy_addr; node["eth clock_mode"] = settings.eth_clock_mode; } node["rx gpio"] = settings.rx_gpio; From 7fbeed88a97cc4ce522a95108b2aeec08c0ab7a7 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 4 Dec 2022 10:32:50 +0100 Subject: [PATCH 23/52] package updates --- interface/package-lock.json | 92 ++++++++++++++++++------------------- interface/package.json | 8 ++-- package-lock.json | 6 +++ 3 files changed, 56 insertions(+), 50 deletions(-) create mode 100644 package-lock.json diff --git a/interface/package-lock.json b/interface/package-lock.json index e49b8950d..a29315980 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -14,9 +14,9 @@ "@mui/icons-material": "^5.10.16", "@mui/material": "^5.10.16", "@table-library/react-table-library": "4.0.23", - "@types/lodash": "^4.14.190", - "@types/node": "^18.11.9", - "@types/react": "^18.0.25", + "@types/lodash": "^4.14.191", + "@types/node": "^18.11.10", + "@types/react": "^18.0.26", "@types/react-dom": "^18.0.9", "@types/react-router-dom": "^5.3.3", "async-validator": "^4.2.5", @@ -31,7 +31,7 @@ "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-icons": "^4.7.1", - "react-router-dom": "^6.4.3", + "react-router-dom": "^6.4.4", "react-scripts": "5.0.1", "sockette": "^2.0.6", "typesafe-i18n": "^5.17.1", @@ -3458,9 +3458,9 @@ } }, "node_modules/@remix-run/router": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz", - "integrity": "sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.4.tgz", + "integrity": "sha512-gTL8H5USTAKOyVA4xczzDJnC3HMssdFa3tRlwBicXynx9XfiXwneHnYQogwSKpdCkjXISrEKSTtX62rLpNEVQg==", "engines": { "node": ">=14" } @@ -4007,9 +4007,9 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, "node_modules/@types/lodash": { - "version": "4.14.190", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.190.tgz", - "integrity": "sha512-5iJ3FBJBvQHQ8sFhEhJfjUP+G+LalhavTkYyrAYqz5MEJG+erSv0k9KJLb6q7++17Lafk1scaTIFXcMJlwK8Mw==" + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" }, "node_modules/@types/mime": { "version": "3.0.1", @@ -4017,9 +4017,9 @@ "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, "node_modules/@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" + "version": "18.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", + "integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -4052,9 +4052,9 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "node_modules/@types/react": { - "version": "18.0.25", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.25.tgz", - "integrity": "sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==", + "version": "18.0.26", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz", + "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -14561,11 +14561,11 @@ } }, "node_modules/react-router": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.3.tgz", - "integrity": "sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.4.tgz", + "integrity": "sha512-SA6tSrUCRfuLWeYsTJDuriRqfFIsrSvuH7SqAJHegx9ZgxadE119rU8oOX/rG5FYEthpdEaEljdjDlnBxvfr+Q==", "dependencies": { - "@remix-run/router": "1.0.3" + "@remix-run/router": "1.0.4" }, "engines": { "node": ">=14" @@ -14575,12 +14575,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.3.tgz", - "integrity": "sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.4.tgz", + "integrity": "sha512-0Axverhw5d+4SBhLqLpzPhNkmv7gahUwlUVIOrRLGJ4/uwt30JVajVJXqv2Qr/LCwyvHhQc7YyK1Do8a9Jj7qA==", "dependencies": { - "@remix-run/router": "1.0.3", - "react-router": "6.4.3" + "@remix-run/router": "1.0.4", + "react-router": "6.4.4" }, "engines": { "node": ">=14" @@ -19816,9 +19816,9 @@ "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" }, "@remix-run/router": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz", - "integrity": "sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.4.tgz", + "integrity": "sha512-gTL8H5USTAKOyVA4xczzDJnC3HMssdFa3tRlwBicXynx9XfiXwneHnYQogwSKpdCkjXISrEKSTtX62rLpNEVQg==" }, "@rollup/plugin-babel": { "version": "5.3.1", @@ -20220,9 +20220,9 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, "@types/lodash": { - "version": "4.14.190", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.190.tgz", - "integrity": "sha512-5iJ3FBJBvQHQ8sFhEhJfjUP+G+LalhavTkYyrAYqz5MEJG+erSv0k9KJLb6q7++17Lafk1scaTIFXcMJlwK8Mw==" + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" }, "@types/mime": { "version": "3.0.1", @@ -20230,9 +20230,9 @@ "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, "@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" + "version": "18.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", + "integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" }, "@types/parse-json": { "version": "4.0.0", @@ -20265,9 +20265,9 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "@types/react": { - "version": "18.0.25", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.25.tgz", - "integrity": "sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==", + "version": "18.0.26", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz", + "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -27721,20 +27721,20 @@ "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, "react-router": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.3.tgz", - "integrity": "sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.4.tgz", + "integrity": "sha512-SA6tSrUCRfuLWeYsTJDuriRqfFIsrSvuH7SqAJHegx9ZgxadE119rU8oOX/rG5FYEthpdEaEljdjDlnBxvfr+Q==", "requires": { - "@remix-run/router": "1.0.3" + "@remix-run/router": "1.0.4" } }, "react-router-dom": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.3.tgz", - "integrity": "sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.4.tgz", + "integrity": "sha512-0Axverhw5d+4SBhLqLpzPhNkmv7gahUwlUVIOrRLGJ4/uwt30JVajVJXqv2Qr/LCwyvHhQc7YyK1Do8a9Jj7qA==", "requires": { - "@remix-run/router": "1.0.3", - "react-router": "6.4.3" + "@remix-run/router": "1.0.4", + "react-router": "6.4.4" } }, "react-scripts": { diff --git a/interface/package.json b/interface/package.json index 1886c19e6..c727c1dc4 100644 --- a/interface/package.json +++ b/interface/package.json @@ -10,9 +10,9 @@ "@mui/icons-material": "^5.10.16", "@mui/material": "^5.10.16", "@table-library/react-table-library": "4.0.23", - "@types/lodash": "^4.14.190", - "@types/node": "^18.11.9", - "@types/react": "^18.0.25", + "@types/lodash": "^4.14.191", + "@types/node": "^18.11.10", + "@types/react": "^18.0.26", "@types/react-dom": "^18.0.9", "@types/react-router-dom": "^5.3.3", "async-validator": "^4.2.5", @@ -27,7 +27,7 @@ "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-icons": "^4.7.1", - "react-router-dom": "^6.4.3", + "react-router-dom": "^6.4.4", "react-scripts": "5.0.1", "sockette": "^2.0.6", "typesafe-i18n": "^5.17.1", diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..2442bf511 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "EMS-ESP32", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} From 67e07813cbce4cf4f9a2acd31566eacff6828b73 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 4 Dec 2022 10:33:13 +0100 Subject: [PATCH 24/52] adding missing translations for Value (single/plural) --- interface/src/i18n/de/index.ts | 2 +- interface/src/i18n/en/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index 09d3e3f7c..5837fac56 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -37,7 +37,7 @@ const de: Translation = { PRODUCT: 'Produkt', VERSION: 'Version', ENTITY_NAME: 'Entitätsname', - VALUE: 'Wert', + VALUE: '{{Wert|wert}}', SHOW_FAV: 'nur Favoriten anzeigen', DEVICE_SENSOR_DATA: 'Geräte- und Sensordaten', DEVICES_SENSORS: 'Geräte & Sensoren', diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts index 2e949f2e8..4cd5e69ec 100644 --- a/interface/src/i18n/en/index.ts +++ b/interface/src/i18n/en/index.ts @@ -37,7 +37,7 @@ const en: Translation = { VERSION: 'Version', BRAND: 'Brand', ENTITY_NAME: 'Entity Name', - VALUE: 'Value', + VALUE: '{{Value|value}}', SHOW_FAV: 'only show favorites', DEVICE_SENSOR_DATA: 'Device and Sensor Data', DEVICES_SENSORS: 'Devices & Sensors', From 1c48aa844435416a0d491aeb5f8939e4471fac0d Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 4 Dec 2022 12:44:44 +0100 Subject: [PATCH 25/52] fixes #787 --- interface/src/i18n/nl/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/i18n/nl/index.ts b/interface/src/i18n/nl/index.ts index 496ea4a35..75897d27d 100644 --- a/interface/src/i18n/nl/index.ts +++ b/interface/src/i18n/nl/index.ts @@ -100,8 +100,8 @@ const nl: Translation = { NUM_ANALOG_SENSORS: '{num} Analoge sensor{{en}}', NUM_DAYS: '{num} dag{{en}}', NUM_SECONDS: '{num} second{{en}}', - NUM_HOURS: '{num} uur{{en}}', - NUM_MINUTES: '{num} minuut{{en}}', + NUM_HOURS: '{num} {{uur|uren}}', + NUM_MINUTES: '{num} minute{{n}}', APPLICATION_SETTINGS: 'Applicatieinstellingen', CUSTOMIZATION: 'Custom aanpassingen', APPLICATION_RESTARTING: 'EMS-ESP herstarten', From 990d75d42acd61c850a6b0903255aa72c4190373 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 4 Dec 2022 12:44:57 +0100 Subject: [PATCH 26/52] debug comments --- lib/framework/UploadFileService.cpp | 3 +++ src/command.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/lib/framework/UploadFileService.cpp b/lib/framework/UploadFileService.cpp index e2d07d83b..b876a195b 100644 --- a/lib/framework/UploadFileService.cpp +++ b/lib/framework/UploadFileService.cpp @@ -29,9 +29,12 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri std::string extension = fname.substr(position + 1); size_t fsize = request->contentLength(); +#ifdef EMSESP_DEBUG #if defined(EMSESP_USE_SERIAL) + Serial.println(); Serial.printf("Received filename: %s, len: %d, index: %d, ext: %s, fsize: %d", filename.c_str(), len, index, extension.c_str(), fsize); Serial.println(); +#endif #endif is_firmware = false; diff --git a/src/command.cpp b/src/command.cpp index 6c8936976..a8fea507a 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -52,8 +52,10 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec } } +#ifdef EMSESP_DEBUG #if defined(EMSESP_USE_SERIAL) // Serial.println(p.path().c_str()); // dump paths, for debugging +#endif #endif // re-calculate new path From 132ca9d106b746b6b81dde7aebb438fd64ee7533 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 4 Dec 2022 12:45:23 +0100 Subject: [PATCH 27/52] fix mqtt topic length which broke PR #781 --- lib/framework/MqttSettingsService.cpp | 42 ++++++++++++++------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/lib/framework/MqttSettingsService.cpp b/lib/framework/MqttSettingsService.cpp index 8ea106423..be23b107d 100644 --- a/lib/framework/MqttSettingsService.cpp +++ b/lib/framework/MqttSettingsService.cpp @@ -145,15 +145,15 @@ void MqttSettingsService::configureMqtt() { } void MqttSettings::read(MqttSettings & settings, JsonObject & root) { - root["enabled"] = settings.enabled; - root["host"] = settings.host; - root["port"] = settings.port; - root["base"] = settings.base; - root["username"] = settings.username; - root["password"] = settings.password; - root["client_id"] = settings.clientId; - root["keep_alive"] = settings.keepAlive; - root["clean_session"] = settings.cleanSession; + root["enabled"] = settings.enabled; + root["host"] = settings.host; + root["port"] = settings.port; + root["base"] = settings.base; + root["username"] = settings.username; + root["password"] = settings.password; + root["client_id"] = settings.clientId; + root["keep_alive"] = settings.keepAlive; + root["clean_session"] = settings.cleanSession; // added by proddy for EMS-ESP root["publish_time_boiler"] = settings.publish_time_boiler; @@ -176,17 +176,19 @@ StateUpdateResult MqttSettings::update(JsonObject & root, MqttSettings & setting MqttSettings newSettings = {}; bool changed = false; - newSettings.enabled = root["enabled"] | FACTORY_MQTT_ENABLED; - newSettings.host = root["host"] | FACTORY_MQTT_HOST; - newSettings.port = root["port"] | FACTORY_MQTT_PORT; - newSettings.base = root["base"] | FACTORY_MQTT_BASE; - newSettings.username = root["username"] | FACTORY_MQTT_USERNAME; - newSettings.password = root["password"] | FACTORY_MQTT_PASSWORD; - newSettings.clientId = root["client_id"] | FACTORY_MQTT_CLIENT_ID; - newSettings.keepAlive = root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE; - newSettings.cleanSession = root["clean_session"] | FACTORY_MQTT_CLEAN_SESSION; - newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS; - newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN; + newSettings.enabled = root["enabled"] | FACTORY_MQTT_ENABLED; + newSettings.host = root["host"] | FACTORY_MQTT_HOST; + newSettings.port = root["port"] | FACTORY_MQTT_PORT; + newSettings.base = root["base"] | FACTORY_MQTT_BASE; + newSettings.username = root["username"] | FACTORY_MQTT_USERNAME; + newSettings.password = root["password"] | FACTORY_MQTT_PASSWORD; + newSettings.clientId = root["client_id"] | FACTORY_MQTT_CLIENT_ID; + newSettings.keepAlive = root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE; + newSettings.cleanSession = root["clean_session"] | FACTORY_MQTT_CLEAN_SESSION; + newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS; + newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN; + + newSettings.maxTopicLength = FACTORY_MQTT_MAX_TOPIC_LENGTH; // hardcode. We don't take this from the settings anymore. newSettings.publish_time_boiler = root["publish_time_boiler"] | EMSESP_DEFAULT_PUBLISH_TIME; newSettings.publish_time_thermostat = root["publish_time_thermostat"] | EMSESP_DEFAULT_PUBLISH_TIME; From 5029a1625e4cc4b79ba27c182fec61873c882513 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 4 Dec 2022 15:51:56 +0100 Subject: [PATCH 28/52] remove TODO --- src/test/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/test.cpp b/src/test/test.cpp index 44fce64f1..d4ab3fe8e 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -1453,7 +1453,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // test direct commands EMSESP::mqtt_.incoming("ems-esp/boiler/selflowtemp", "56"); - EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"send\",\"data\":\"01 02 03 04 05\"}"); // TODO check if works + EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"send\",\"data\":\"01 02 03 04 05\"}"); // EMSESP::mqtt_.incoming(system_topic, "{\"cmd\":\"pin\",\"id\":12,\"data\":\"1\"}"); EMSESP::mqtt_.incoming(thermostat_topic, "{\"cmd\":\"wwmode\",\"data\":\"auto\"}"); From d080f5db0f317bfe521781fbbcedb6f69c6c5e4b Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 4 Dec 2022 15:52:31 +0100 Subject: [PATCH 29/52] fix dutch NUM_MINUTES #787 --- interface/src/i18n/nl/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/i18n/nl/index.ts b/interface/src/i18n/nl/index.ts index 75897d27d..cbd1cd400 100644 --- a/interface/src/i18n/nl/index.ts +++ b/interface/src/i18n/nl/index.ts @@ -101,7 +101,7 @@ const nl: Translation = { NUM_DAYS: '{num} dag{{en}}', NUM_SECONDS: '{num} second{{en}}', NUM_HOURS: '{num} {{uur|uren}}', - NUM_MINUTES: '{num} minute{{n}}', + NUM_MINUTES: '{num} {{minuut|minuten}}', APPLICATION_SETTINGS: 'Applicatieinstellingen', CUSTOMIZATION: 'Custom aanpassingen', APPLICATION_RESTARTING: 'EMS-ESP herstarten', From 0903b31fcfe7110b618bebd5b1d0982518a5284e Mon Sep 17 00:00:00 2001 From: Proddy Date: Mon, 5 Dec 2022 10:06:50 +0100 Subject: [PATCH 30/52] highlight breaking changes --- CHANGELOG_LATEST.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 73b2939e3..5eeeaa02b 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -2,6 +2,11 @@ # [3.5.0] +## **IMPORTANT! BREAKING CHANGES** + +- When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade. +- Since 3.5.0b11 we added support for multiple EMS-ESPs [#759] so they can co-exist with MQTT Discovery. The mqtt base is now included in each of the entity names to make them unique. Unfortunately this means in Home Assistant the entity IDs have also been renamed (for example from `number.boiler_burnminperiod` to `number.ems_esp_boiler_burnminperiod`) and any dashboards and automation scripts need to be adjusted accordingly. + ## Added - Translations in Web UI and all device entity names (DE, NL, SE, PL, NO) [#22](https://github.com/emsesp/EMS-ESP32/issues/22) @@ -35,8 +40,3 @@ - analog/dallas values command as list like ems-devices - analog/dallas HA-entities based on id - MQTT Base is a mandatory field. Removed MQTT topic length from settings. - -## **BREAKING CHANGES:** - -- When upgrading for the first time from 3.4.x on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases). Make sure you make a backup of the settings and customizations via the WebUI (System->Upload/Download). -- Because of #759 the Home Assistant entity IDs have been renamed From b900932574b135ccfaf178a87f2efbcca297bd38 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 5 Dec 2022 14:09:25 +0100 Subject: [PATCH 31/52] hardcode maxTopicLength to settingfunction --- lib/framework/MqttSettingsService.cpp | 4 +--- lib/framework/MqttSettingsService.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/framework/MqttSettingsService.cpp b/lib/framework/MqttSettingsService.cpp index be23b107d..952724606 100644 --- a/lib/framework/MqttSettingsService.cpp +++ b/lib/framework/MqttSettingsService.cpp @@ -137,7 +137,7 @@ void MqttSettingsService::configureMqtt() { _mqttClient.setClientId(retainCstr(_state.clientId.c_str(), &_retainedClientId)); _mqttClient.setKeepAlive(_state.keepAlive); _mqttClient.setCleanSession(_state.cleanSession); - _mqttClient.setMaxTopicLength(_state.maxTopicLength); + _mqttClient.setMaxTopicLength(FACTORY_MQTT_MAX_TOPIC_LENGTH); // hardcode. We don't take this from the settings anymore. _mqttClient.connect(); // } else { // emsesp::EMSESP::logger().info("Error configuring Mqtt client"); @@ -188,8 +188,6 @@ StateUpdateResult MqttSettings::update(JsonObject & root, MqttSettings & setting newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS; newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN; - newSettings.maxTopicLength = FACTORY_MQTT_MAX_TOPIC_LENGTH; // hardcode. We don't take this from the settings anymore. - newSettings.publish_time_boiler = root["publish_time_boiler"] | EMSESP_DEFAULT_PUBLISH_TIME; newSettings.publish_time_thermostat = root["publish_time_thermostat"] | EMSESP_DEFAULT_PUBLISH_TIME; newSettings.publish_time_solar = root["publish_time_solar"] | EMSESP_DEFAULT_PUBLISH_TIME; diff --git a/lib/framework/MqttSettingsService.h b/lib/framework/MqttSettingsService.h index 473c130ac..199c7379b 100644 --- a/lib/framework/MqttSettingsService.h +++ b/lib/framework/MqttSettingsService.h @@ -74,7 +74,6 @@ class MqttSettings { // connection settings uint16_t keepAlive; bool cleanSession; - uint16_t maxTopicLength; // proddy EMS-ESP specific String base; From 6f27253441f0b048587c28a536706467da1de8cb Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 5 Dec 2022 14:10:05 +0100 Subject: [PATCH 32/52] log calling command in debug level --- src/command.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index a8fea507a..eebbd7730 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -284,12 +284,12 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * std::string ro = EMSESP::system_.readonly_mode() ? "[readonly] " : ""; if ((value == nullptr) || (strlen(value) == 0)) { - LOG_INFO(("%sCalling command %s"), ro.c_str(), info_s); + LOG_DEBUG(("%sCalling command %s"), ro.c_str(), info_s); } else { if (id > 0) { - LOG_INFO(("%sCalling command %s with value %s and id %d"), ro.c_str(), info_s, value, id); + LOG_DEBUG(("%sCalling command %s with value %s and id %d"), ro.c_str(), info_s, value, id); } else { - LOG_INFO(("%sCalling command %s with value %s"), ro.c_str(), info_s, value); + LOG_DEBUG(("%sCalling command %s with value %s"), ro.c_str(), info_s, value); } } From 739c007c95654eeefe1cb52022e953c98adbcd30 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 5 Dec 2022 14:13:25 +0100 Subject: [PATCH 33/52] sync sensors and status to same entitiy in path, uniq_id, objdect_id --- src/analogsensor.cpp | 2 +- src/dallassensor.cpp | 2 +- src/mqtt.cpp | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 69cd7e8a6..1b805b460 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -451,7 +451,7 @@ void AnalogSensor::publish_values(const bool force) { } config["val_tpl"] = str; - snprintf(str, sizeof(str), "%s_analog_sensor_%s", Mqtt::basename().c_str(), sensor.name().c_str()); + snprintf(str, sizeof(str), "%s_analogsensor_%d", Mqtt::basename().c_str(), sensor.gpio()); config["object_id"] = str; config["uniq_id"] = str; // same as object_id diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index ccfc7438c..eb1aeab74 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -518,7 +518,7 @@ void DallasSensor::publish_values(const bool force) { } config["val_tpl"] = str; - snprintf(str, sizeof(str), "%s_temperature_sensor_%s", Mqtt::basename().c_str(), sensor.id().c_str()); + snprintf(str, sizeof(str), "%s_dallassensor_%s", Mqtt::basename().c_str(), sensor.id().c_str()); config["object_id"] = str; config["uniq_id"] = str; // same as object_id diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 43f0c8d3c..404b8878b 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -593,8 +593,10 @@ void Mqtt::on_connect() { void Mqtt::ha_status() { StaticJsonDocument doc; - doc["uniq_id"] = "ems-esp-system"; - doc["object_id"] = "ems_esp_status"; + char uniq[70]; + snprintf(uniq, sizeof(uniq), "%s_status", mqtt_basename_.c_str()); + doc["uniq_id"] = uniq; + doc["object_id"] = uniq; doc["~"] = mqtt_base_; // default ems-esp // doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes // doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes @@ -614,7 +616,7 @@ void Mqtt::ha_status() { ids.add("ems-esp"); char topic[MQTT_TOPIC_MAX_SIZE]; - snprintf(topic, sizeof(topic), "binary_sensor/%s/system/config", mqtt_basename_.c_str()); + snprintf(topic, sizeof(topic), "binary_sensor/%s/status/config", mqtt_basename_.c_str()); Mqtt::publish_ha(topic, doc.as()); // publish the config payload with retain flag // create the sensors - must match the MQTT payload keys From 0c9d0a4d152beaefd4f2f95191d25b52aab01b54 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 5 Dec 2022 14:19:41 +0100 Subject: [PATCH 34/52] show mqtt payload in debug log --- src/mqtt.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 404b8878b..572e44065 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -845,6 +845,7 @@ void Mqtt::process_queue() { mqtt_message.retry_count_ + 1, message->payload.size(), packet_id); + LOG_DEBUG("Payload:%s", message->payload.c_str()); if (packet_id == 0) { // it failed. if we retried n times, give up. remove from queue From 3878a3ee0baf2531a5e9176d62a2e96f75051635 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 5 Dec 2022 18:26:18 +0100 Subject: [PATCH 35/52] analogsensor float->double #789 --- CHANGELOG_LATEST.md | 10 +++++----- src/analogsensor.cpp | 8 ++++---- src/analogsensor.h | 24 ++++++++++++------------ src/helpers.cpp | 2 +- src/helpers.h | 2 +- src/web/WebCustomizationService.h | 4 ++-- src/web/WebDataService.cpp | 4 ++-- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 73b2939e3..5eeeaa02b 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -2,6 +2,11 @@ # [3.5.0] +## **IMPORTANT! BREAKING CHANGES** + +- When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade. +- Since 3.5.0b11 we added support for multiple EMS-ESPs [#759] so they can co-exist with MQTT Discovery. The mqtt base is now included in each of the entity names to make them unique. Unfortunately this means in Home Assistant the entity IDs have also been renamed (for example from `number.boiler_burnminperiod` to `number.ems_esp_boiler_burnminperiod`) and any dashboards and automation scripts need to be adjusted accordingly. + ## Added - Translations in Web UI and all device entity names (DE, NL, SE, PL, NO) [#22](https://github.com/emsesp/EMS-ESP32/issues/22) @@ -35,8 +40,3 @@ - analog/dallas values command as list like ems-devices - analog/dallas HA-entities based on id - MQTT Base is a mandatory field. Removed MQTT topic length from settings. - -## **BREAKING CHANGES:** - -- When upgrading for the first time from 3.4.x on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases). Make sure you make a backup of the settings and customizations via the WebUI (System->Upload/Download). -- Because of #759 the Home Assistant entity IDs have been renamed diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 1b805b460..ff9d83801 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -296,7 +296,7 @@ void AnalogSensor::loop() { } // update analog information name and offset -bool AnalogSensor::update(uint8_t gpio, const std::string & name, float offset, float factor, uint8_t uom, int8_t type) { +bool AnalogSensor::update(uint8_t gpio, const std::string & name, double offset, double factor, uint8_t uom, int8_t type) { boolean found_sensor = false; // see if we can find the sensor in our customization list EMSESP::webCustomizationService.update( @@ -375,7 +375,7 @@ void AnalogSensor::publish_sensor(const Sensor & sensor) const { snprintf(topic, sizeof(topic), "%s%s/%s", F_(analogsensor), "_data", sensor.name().c_str()); } char payload[10]; - Mqtt::publish(topic, Helpers::render_value(payload, sensor.value(), 2)); // always publish as floats + Mqtt::publish(topic, Helpers::render_value(payload, sensor.value(), 2)); // always publish as doubles } } @@ -422,7 +422,7 @@ void AnalogSensor::publish_values(const bool force) { case AnalogType::PWM_0: case AnalogType::PWM_1: case AnalogType::PWM_2: - dataSensor["value"] = serialized(Helpers::render_value(s, sensor.value(), 2)); // float + dataSensor["value"] = serialized(Helpers::render_value(s, sensor.value(), 2)); // double break; default: dataSensor["value"] = (uint8_t)sensor.value(); // convert to char for 1 or 0 @@ -581,7 +581,7 @@ bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject } // this creates the sensor, initializing everything -AnalogSensor::Sensor::Sensor(const uint8_t gpio, const std::string & name, const float offset, const float factor, const uint8_t uom, const int8_t type) +AnalogSensor::Sensor::Sensor(const uint8_t gpio, const std::string & name, const double offset, const double factor, const uint8_t uom, const int8_t type) : gpio_(gpio) , name_(name) , offset_(offset) diff --git a/src/analogsensor.h b/src/analogsensor.h index 9a00061cf..9b3d2f6c9 100644 --- a/src/analogsensor.h +++ b/src/analogsensor.h @@ -35,10 +35,10 @@ class AnalogSensor { public: class Sensor { public: - Sensor(const uint8_t gpio, const std::string & name, const float offset, const float factor, const uint8_t uom, const int8_t type); + Sensor(const uint8_t gpio, const std::string & name, const double offset, const double factor, const uint8_t uom, const int8_t type); ~Sensor() = default; - void set_offset(const float offset) { + void set_offset(const double offset) { offset_ = offset; } @@ -52,23 +52,23 @@ class AnalogSensor { return gpio_; } - float value() const { + double value() const { return value_; } - void set_value(float value) { + void set_value(const double value) { value_ = value; } - float factor() const { + double factor() const { return factor_; } - void set_factor(float factor) { + void set_factor(const double factor) { factor_ = factor; } - float offset() const { + double offset() const { return offset_; } @@ -84,7 +84,7 @@ class AnalogSensor { return type_; } - void set_type(int8_t type) { + void set_type(const int8_t type) { type_ = type; } @@ -101,10 +101,10 @@ class AnalogSensor { private: uint8_t gpio_; std::string name_; - float offset_; - float factor_; + double offset_; + double factor_; uint8_t uom_; - float value_; // float because of the factor is a float + double value_; // double because of the factor is a double int8_t type_; }; @@ -157,7 +157,7 @@ class AnalogSensor { return sensors_.size(); } - bool update(uint8_t gpio, const std::string & name, float offset, float factor, uint8_t uom, int8_t type); + bool update(uint8_t gpio, const std::string & name, double offset, double factor, uint8_t uom, int8_t type); bool get_value_info(JsonObject & output, const char * cmd, const int8_t id) const; #ifdef EMSESP_DEBUG diff --git a/src/helpers.cpp b/src/helpers.cpp index c2b99638d..6865f9081 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -244,7 +244,7 @@ char * Helpers::render_value(char * result, uint8_t value, int8_t format, const // float: convert float to char // format is the precision, 0 to 8 -char * Helpers::render_value(char * result, const float value, const int8_t format) { +char * Helpers::render_value(char * result, const double value, const int8_t format) { if (format > 8) { return nullptr; } diff --git a/src/helpers.h b/src/helpers.h index 95fa7a5db..cc153079b 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -27,7 +27,7 @@ namespace emsesp { class Helpers { public: - static char * render_value(char * result, const float value, const int8_t format); // format is the precision + static char * render_value(char * result, const double value, const int8_t format); // format is the precision static char * render_value(char * result, const uint8_t value, const int8_t format, const uint8_t fahrenheit = 0); static char * render_value(char * result, const int8_t value, const int8_t format, const uint8_t fahrenheit = 0); static char * render_value(char * result, const uint16_t value, const int8_t format, const uint8_t fahrenheit = 0); diff --git a/src/web/WebCustomizationService.h b/src/web/WebCustomizationService.h index e5d7a9512..d0a979807 100644 --- a/src/web/WebCustomizationService.h +++ b/src/web/WebCustomizationService.h @@ -44,8 +44,8 @@ class AnalogCustomization { public: uint8_t gpio; std::string name; - float offset; - float factor; + double offset; + double factor; uint8_t uom; // 0 is none int8_t type; // -1 is for deletion diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 81e6d0ae7..bb886f790 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -284,8 +284,8 @@ void WebDataService::write_analog(AsyncWebServerRequest * request, JsonVariant & uint8_t gpio = analog["gpio"]; // this is the unique key, the GPIO std::string name = analog["name"]; - float factor = analog["factor"]; - float offset = analog["offset"]; + double factor = analog["factor"]; + double offset = analog["offset"]; uint8_t uom = analog["uom"]; int8_t type = analog["type"]; ok = EMSESP::analogsensor_.update(gpio, name, offset, factor, uom, type); From 9e23710c6d36536f7df4f00bf43b6668f0e289ca Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 5 Dec 2022 19:27:56 +0100 Subject: [PATCH 36/52] add heartbeat interval to mqtt settings --- .../src/framework/mqtt/MqttSettingsForm.tsx | 16 ++++++++++++++++ interface/src/i18n/de/index.ts | 1 + interface/src/i18n/en/index.ts | 1 + interface/src/i18n/nl/index.ts | 1 + interface/src/i18n/no/index.ts | 1 + interface/src/i18n/pl/index.ts | 1 + interface/src/i18n/se/index.ts | 1 + interface/src/types/mqtt.ts | 1 + interface/src/validators/mqtt.ts | 4 ++++ lib/framework/MqttSettingsService.cpp | 7 +++++++ lib/framework/MqttSettingsService.h | 1 + src/default_settings.h | 4 ++++ src/mqtt.cpp | 12 ++++++++++++ src/mqtt.h | 3 +++ src/system.cpp | 6 ------ src/system.h | 2 -- 16 files changed, 54 insertions(+), 8 deletions(-) diff --git a/interface/src/framework/mqtt/MqttSettingsForm.tsx b/interface/src/framework/mqtt/MqttSettingsForm.tsx index b5956b034..5e6cdbeca 100644 --- a/interface/src/framework/mqtt/MqttSettingsForm.tsx +++ b/interface/src/framework/mqtt/MqttSettingsForm.tsx @@ -238,6 +238,22 @@ const MqttSettingsForm: FC = () => { {LL.MQTT_PUBLISH_INTERVALS()} (0=auto) + + {LL.SECONDS()} + }} + fullWidth + variant="outlined" + value={numberValue(data.publish_time_heartbeat)} + type="number" + onChange={updateFormValue} + margin="normal" + /> + publish_time_heartbeat_)) { + last_publish_heartbeat_ = currentMillis; + EMSESP::system_.send_heartbeat(); // send heartbeat + } + // dallas publish on change if (!publish_time_sensor_) { EMSESP::publish_sensor_values(false); @@ -430,6 +437,7 @@ void Mqtt::load_settings() { publish_time_mixer_ = mqttSettings.publish_time_mixer * 1000; publish_time_other_ = mqttSettings.publish_time_other * 1000; publish_time_sensor_ = mqttSettings.publish_time_sensor * 1000; + publish_time_heartbeat_ = mqttSettings.publish_time_heartbeat * 1000; }); // create basename from base @@ -512,6 +520,10 @@ void Mqtt::set_publish_time_sensor(uint16_t publish_time) { publish_time_sensor_ = publish_time * 1000; // convert to milliseconds } +void Mqtt::set_publish_time_heartbeat(uint16_t publish_time) { + publish_time_heartbeat_ = publish_time * 1000; // convert to milliseconds +} + bool Mqtt::get_publish_onchange(uint8_t device_type) { if (publish_single_ && !ha_enabled_) { return false; diff --git a/src/mqtt.h b/src/mqtt.h index 65e4fcad7..848c87989 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -65,6 +65,7 @@ class Mqtt { void set_publish_time_mixer(uint16_t publish_time); void set_publish_time_other(uint16_t publish_time); void set_publish_time_sensor(uint16_t publish_time); + void set_publish_time_heartbeat(uint16_t publish_time); bool get_publish_onchange(uint8_t device_type); enum Operation : uint8_t { PUBLISH, SUBSCRIBE, UNSUBSCRIBE }; @@ -288,6 +289,7 @@ class Mqtt { uint32_t last_publish_mixer_ = 0; uint32_t last_publish_other_ = 0; uint32_t last_publish_sensor_ = 0; + uint32_t last_publish_heartbeat_ = 0; uint32_t last_publish_queue_ = 0; static bool connecting_; @@ -311,6 +313,7 @@ class Mqtt { static uint32_t publish_time_mixer_; static uint32_t publish_time_other_; static uint32_t publish_time_sensor_; + static uint32_t publish_time_heartbeat_; static bool mqtt_enabled_; static bool ha_enabled_; static uint8_t nested_format_; diff --git a/src/system.cpp b/src/system.cpp index 1fbfe9aa9..2b6ab7440 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -512,12 +512,6 @@ void System::loop() { led_monitor(); // check status and report back using the LED system_check(); // check system health - // send out heartbeat - uint32_t currentMillis = uuid::get_uptime(); - if (!last_heartbeat_ || (currentMillis - last_heartbeat_ > SYSTEM_HEARTBEAT_INTERVAL)) { - last_heartbeat_ = currentMillis; - send_heartbeat(); - } #ifndef EMSESP_STANDALONE #if defined(EMSESP_DEBUG) diff --git a/src/system.h b/src/system.h index f8ee51dc2..3f4169306 100644 --- a/src/system.h +++ b/src/system.h @@ -250,7 +250,6 @@ class System { static constexpr uint32_t HEALTHCHECK_LED_FLASH_DUARATION = 150; static constexpr uint8_t HEALTHCHECK_NO_BUS = (1 << 0); // 1 static constexpr uint8_t HEALTHCHECK_NO_NETWORK = (1 << 1); // 2 - static constexpr uint32_t SYSTEM_HEARTBEAT_INTERVAL = 60000; // in milliseconds, how often the MQTT heartbeat is sent (1 min) static constexpr uint8_t LED_ON = HIGH; // LED on #ifndef EMSESP_STANDALONE @@ -263,7 +262,6 @@ class System { int8_t wifi_quality(int8_t dBm); uint8_t healthcheck_ = HEALTHCHECK_NO_NETWORK | HEALTHCHECK_NO_BUS; // start with all flags set, no wifi and no ems bus connection - uint32_t last_heartbeat_ = 0; uint32_t last_system_check_ = 0; bool upload_status_ = false; // true if we're in the middle of a OTA firmware upload From fd04f8be5ad96316e102af7fb2b26339d389678c Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 5 Dec 2022 20:35:04 +0100 Subject: [PATCH 37/52] add multiple_sessions --- .../src/framework/mqtt/MqttSettingsForm.tsx | 4 ++ interface/src/i18n/de/index.ts | 1 + interface/src/i18n/en/index.ts | 1 + interface/src/i18n/nl/index.ts | 1 + interface/src/i18n/no/index.ts | 1 + interface/src/i18n/pl/index.ts | 1 + interface/src/i18n/se/index.ts | 1 + interface/src/types/mqtt.ts | 1 + lib/framework/MqttSettingsService.cpp | 43 ++++++++++--------- lib/framework/MqttSettingsService.h | 7 +++ lib_standalone/ESP8266React.h | 1 + mock-api/server.js | 1 + src/system.cpp | 1 + 13 files changed, 44 insertions(+), 20 deletions(-) diff --git a/interface/src/framework/mqtt/MqttSettingsForm.tsx b/interface/src/framework/mqtt/MqttSettingsForm.tsx index b5956b034..984f23e7d 100644 --- a/interface/src/framework/mqtt/MqttSettingsForm.tsx +++ b/interface/src/framework/mqtt/MqttSettingsForm.tsx @@ -162,6 +162,10 @@ const MqttSettingsForm: FC = () => { + } + label={LL.MQTT_MULTIPLE_INSTANCES()} + /> } label={LL.MQTT_CLEAN_SESSION()} diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index 5837fac56..fe6c05740 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -247,6 +247,7 @@ const de: Translation = { MQTT_INT_MIXER: 'Mischermodule', MQTT_QUEUE: 'MQTT Queue', DEFAULT: 'Standard', + MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP', MQTT_CLEAN_SESSION: 'Setze `Clean Session`', MQTT_RETAIN_FLAG: 'Setze `Retain flag` immer', INACTIVE: 'Inaktiv', diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts index 4cd5e69ec..0abaf6d97 100644 --- a/interface/src/i18n/en/index.ts +++ b/interface/src/i18n/en/index.ts @@ -247,6 +247,7 @@ const en: Translation = { MQTT_INT_MIXER: 'Mixer Modules', MQTT_QUEUE: 'MQTT Queue', DEFAULT: 'Default', + MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP', MQTT_CLEAN_SESSION: 'Set Clean Session', MQTT_RETAIN_FLAG: 'Always set Retain flag', INACTIVE: 'Inactive', diff --git a/interface/src/i18n/nl/index.ts b/interface/src/i18n/nl/index.ts index cbd1cd400..5363adcbf 100644 --- a/interface/src/i18n/nl/index.ts +++ b/interface/src/i18n/nl/index.ts @@ -247,6 +247,7 @@ const nl: Translation = { MQTT_INT_MIXER: 'Mixer Modules', MQTT_QUEUE: 'MQTT Queue', DEFAULT: 'Default', + MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP', MQTT_CLEAN_SESSION: 'Clean Session aan', MQTT_RETAIN_FLAG: 'Retain flag aan', INACTIVE: 'Inactief', diff --git a/interface/src/i18n/no/index.ts b/interface/src/i18n/no/index.ts index 851876219..04df90fc2 100644 --- a/interface/src/i18n/no/index.ts +++ b/interface/src/i18n/no/index.ts @@ -247,6 +247,7 @@ const no: Translation = { MQTT_INT_MIXER: 'Blandeventil', MQTT_QUEUE: 'MQTT Queue', DEFAULT: 'Standard', + MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP', MQTT_CLEAN_SESSION: 'Benytt Clean Session', MQTT_RETAIN_FLAG: 'Alltid sett Retain flag', INACTIVE: 'Innaktiv', diff --git a/interface/src/i18n/pl/index.ts b/interface/src/i18n/pl/index.ts index 413d21c66..06f58bbd9 100644 --- a/interface/src/i18n/pl/index.ts +++ b/interface/src/i18n/pl/index.ts @@ -247,6 +247,7 @@ const pl: BaseTranslation = { MQTT_INT_MIXER: 'Mieszacze', MQTT_QUEUE: 'Kolejka MQTT', DEFAULT: '{{Pozostałe|Domyślna|}}', + MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP', MQTT_CLEAN_SESSION: 'Ustawiaj flagę "Clean session"', MQTT_RETAIN_FLAG: 'Ustawiaj flagę "Retain"', INACTIVE: 'nieaktywny', diff --git a/interface/src/i18n/se/index.ts b/interface/src/i18n/se/index.ts index 923c9617e..cddcc243d 100644 --- a/interface/src/i18n/se/index.ts +++ b/interface/src/i18n/se/index.ts @@ -247,6 +247,7 @@ const se: Translation = { MQTT_INT_MIXER: 'Blandarventiler', MQTT_QUEUE: 'MQTT Queue', DEFAULT: 'Standard', + MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP', MQTT_CLEAN_SESSION: 'Använd "Clean Session"-flaggan', MQTT_RETAIN_FLAG: 'Använd "Always Retain"-flaggan', INACTIVE: 'Inaktiv', diff --git a/interface/src/types/mqtt.ts b/interface/src/types/mqtt.ts index 7ecf694ca..65d0a444a 100644 --- a/interface/src/types/mqtt.ts +++ b/interface/src/types/mqtt.ts @@ -29,6 +29,7 @@ export interface MqttSettings { client_id: string; keep_alive: number; clean_session: boolean; + multiple_instances: boolean; publish_time_boiler: number; publish_time_thermostat: number; publish_time_solar: number; diff --git a/lib/framework/MqttSettingsService.cpp b/lib/framework/MqttSettingsService.cpp index 952724606..9a9bfa487 100644 --- a/lib/framework/MqttSettingsService.cpp +++ b/lib/framework/MqttSettingsService.cpp @@ -145,15 +145,16 @@ void MqttSettingsService::configureMqtt() { } void MqttSettings::read(MqttSettings & settings, JsonObject & root) { - root["enabled"] = settings.enabled; - root["host"] = settings.host; - root["port"] = settings.port; - root["base"] = settings.base; - root["username"] = settings.username; - root["password"] = settings.password; - root["client_id"] = settings.clientId; - root["keep_alive"] = settings.keepAlive; - root["clean_session"] = settings.cleanSession; + root["enabled"] = settings.enabled; + root["host"] = settings.host; + root["port"] = settings.port; + root["base"] = settings.base; + root["username"] = settings.username; + root["password"] = settings.password; + root["client_id"] = settings.clientId; + root["keep_alive"] = settings.keepAlive; + root["clean_session"] = settings.cleanSession; + root["multiple_instances"] = settings.multiple_instances; // added by proddy for EMS-ESP root["publish_time_boiler"] = settings.publish_time_boiler; @@ -176,17 +177,19 @@ StateUpdateResult MqttSettings::update(JsonObject & root, MqttSettings & setting MqttSettings newSettings = {}; bool changed = false; - newSettings.enabled = root["enabled"] | FACTORY_MQTT_ENABLED; - newSettings.host = root["host"] | FACTORY_MQTT_HOST; - newSettings.port = root["port"] | FACTORY_MQTT_PORT; - newSettings.base = root["base"] | FACTORY_MQTT_BASE; - newSettings.username = root["username"] | FACTORY_MQTT_USERNAME; - newSettings.password = root["password"] | FACTORY_MQTT_PASSWORD; - newSettings.clientId = root["client_id"] | FACTORY_MQTT_CLIENT_ID; - newSettings.keepAlive = root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE; - newSettings.cleanSession = root["clean_session"] | FACTORY_MQTT_CLEAN_SESSION; - newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS; - newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN; + newSettings.enabled = root["enabled"] | FACTORY_MQTT_ENABLED; + newSettings.host = root["host"] | FACTORY_MQTT_HOST; + newSettings.port = root["port"] | FACTORY_MQTT_PORT; + newSettings.base = root["base"] | FACTORY_MQTT_BASE; + newSettings.username = root["username"] | FACTORY_MQTT_USERNAME; + newSettings.password = root["password"] | FACTORY_MQTT_PASSWORD; + newSettings.clientId = root["client_id"] | FACTORY_MQTT_CLIENT_ID; + newSettings.keepAlive = root["keep_alive"] | FACTORY_MQTT_KEEP_ALIVE; + newSettings.cleanSession = root["clean_session"] | FACTORY_MQTT_CLEAN_SESSION; + newSettings.multiple_instances = root["multiple_instances"] | FACTORY_MQTT_MULTIPLE_INSTANCES; + + newSettings.mqtt_qos = root["mqtt_qos"] | EMSESP_DEFAULT_MQTT_QOS; + newSettings.mqtt_retain = root["mqtt_retain"] | EMSESP_DEFAULT_MQTT_RETAIN; newSettings.publish_time_boiler = root["publish_time_boiler"] | EMSESP_DEFAULT_PUBLISH_TIME; newSettings.publish_time_thermostat = root["publish_time_thermostat"] | EMSESP_DEFAULT_PUBLISH_TIME; diff --git a/lib/framework/MqttSettingsService.h b/lib/framework/MqttSettingsService.h index 199c7379b..0a976ac21 100644 --- a/lib/framework/MqttSettingsService.h +++ b/lib/framework/MqttSettingsService.h @@ -57,6 +57,10 @@ static String generateClientId() { #define FACTORY_MQTT_MAX_TOPIC_LENGTH 128 #endif +#ifndef FACTORY_MQTT_MULTIPLE_INSTANCES +#define FACTORY_MQTT_MULTIPLE_INSTANCES false +#endif + class MqttSettings { public: // host and port - if enabled @@ -75,6 +79,9 @@ class MqttSettings { uint16_t keepAlive; bool cleanSession; + // multiple instances + bool multiple_instances; + // proddy EMS-ESP specific String base; uint16_t publish_time_boiler; diff --git a/lib_standalone/ESP8266React.h b/lib_standalone/ESP8266React.h index 96590bef2..4587c8817 100644 --- a/lib_standalone/ESP8266React.h +++ b/lib_standalone/ESP8266React.h @@ -81,6 +81,7 @@ class DummySettings { String username = ""; uint16_t keepAlive = 60; bool cleanSession = false; + bool multiple_instances = false; uint16_t publish_time_boiler = 10; uint16_t publish_time_thermostat = 10; diff --git a/mock-api/server.js b/mock-api/server.js index f37697551..28315dfbc 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -219,6 +219,7 @@ mqtt_settings = { client_id: 'ems-esp', keep_alive: 60, clean_session: true, + multiple_instances: false, publish_time_boiler: 10, publish_time_thermostat: 10, publish_time_solar: 10, diff --git a/src/system.cpp b/src/system.cpp index 1fbfe9aa9..47b439759 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1153,6 +1153,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp node["client id"] = settings.clientId; node["keep alive"] = settings.keepAlive; node["clean session"] = settings.cleanSession; + node["multiple instances"] = settings.multiple_instances; node["base"] = settings.base; node["discovery prefix"] = settings.discovery_prefix; node["nested format"] = settings.nested_format; From 1af1a1863a4b848fceb634017ff4f47b710c1c13 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 5 Dec 2022 21:33:10 +0100 Subject: [PATCH 38/52] #759 add option to enable multiple instances to keep backward compatibllity with v3.4 --- interface/package-lock.json | 28 ++++++++++++++-------------- interface/package.json | 4 ++-- src/analogsensor.cpp | 7 ++++++- src/dallassensor.cpp | 11 ++++++++--- src/mqtt.cpp | 22 ++++++++++++++++++---- src/mqtt.h | 5 +++++ 6 files changed, 53 insertions(+), 24 deletions(-) diff --git a/interface/package-lock.json b/interface/package-lock.json index a29315980..9b1f3f369 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -15,12 +15,12 @@ "@mui/material": "^5.10.16", "@table-library/react-table-library": "4.0.23", "@types/lodash": "^4.14.191", - "@types/node": "^18.11.10", + "@types/node": "^18.11.11", "@types/react": "^18.0.26", "@types/react-dom": "^18.0.9", "@types/react-router-dom": "^5.3.3", "async-validator": "^4.2.5", - "axios": "^1.2.0", + "axios": "^1.2.1", "http-proxy-middleware": "^2.0.6", "jwt-decode": "^3.1.2", "lodash": "^4.17.21", @@ -4017,9 +4017,9 @@ "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, "node_modules/@types/node": { - "version": "18.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", - "integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" + "version": "18.11.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz", + "integrity": "sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -5030,9 +5030,9 @@ } }, "node_modules/axios": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.0.tgz", - "integrity": "sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz", + "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -20230,9 +20230,9 @@ "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, "@types/node": { - "version": "18.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", - "integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" + "version": "18.11.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz", + "integrity": "sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g==" }, "@types/parse-json": { "version": "4.0.0", @@ -20998,9 +20998,9 @@ "integrity": "sha512-u2MVsXfew5HBvjsczCv+xlwdNnB1oQR9HlAcsejZttNjKKSkeDNVwB1vMThIUIFI9GoT57Vtk8iQLwqOfAkboA==" }, "axios": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.0.tgz", - "integrity": "sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz", + "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==", "requires": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", diff --git a/interface/package.json b/interface/package.json index c727c1dc4..91afdb57e 100644 --- a/interface/package.json +++ b/interface/package.json @@ -11,12 +11,12 @@ "@mui/material": "^5.10.16", "@table-library/react-table-library": "4.0.23", "@types/lodash": "^4.14.191", - "@types/node": "^18.11.10", + "@types/node": "^18.11.11", "@types/react": "^18.0.26", "@types/react-dom": "^18.0.9", "@types/react-router-dom": "^5.3.3", "async-validator": "^4.2.5", - "axios": "^1.2.0", + "axios": "^1.2.1", "http-proxy-middleware": "^2.0.6", "jwt-decode": "^3.1.2", "lodash": "^4.17.21", diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 1b805b460..a90e7219f 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -451,7 +451,12 @@ void AnalogSensor::publish_values(const bool force) { } config["val_tpl"] = str; - snprintf(str, sizeof(str), "%s_analogsensor_%d", Mqtt::basename().c_str(), sensor.gpio()); + if (Mqtt::multiple_instances()) { + snprintf(str, sizeof(str), "%s_analogsensor_%d", Mqtt::basename().c_str(), sensor.gpio()); + } else { + snprintf(str, sizeof(str), "analogsensor_%d", sensor.gpio()); + } + config["object_id"] = str; config["uniq_id"] = str; // same as object_id diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index eb1aeab74..15b55ddad 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -518,15 +518,20 @@ void DallasSensor::publish_values(const bool force) { } config["val_tpl"] = str; - snprintf(str, sizeof(str), "%s_dallassensor_%s", Mqtt::basename().c_str(), sensor.id().c_str()); + if (Mqtt::multiple_instances()) { + snprintf(str, sizeof(str), "%s_dallassensor_%s", Mqtt::basename().c_str(), sensor.id().c_str()); + } else { + snprintf(str, sizeof(str), "dallassensor_%s", sensor.id().c_str()); + } + config["object_id"] = str; config["uniq_id"] = str; // same as object_id snprintf(str, sizeof(str), "%s", sensor.name().c_str()); config["name"] = str; - JsonObject dev = config.createNestedObject("dev"); - JsonArray ids = dev.createNestedArray("ids"); + JsonObject dev = config.createNestedObject("dev"); + JsonArray ids = dev.createNestedArray("ids"); ids.add("ems-esp"); char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 404b8878b..bc11f6a10 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -37,6 +37,7 @@ uint32_t Mqtt::publish_time_mixer_; uint32_t Mqtt::publish_time_sensor_; uint32_t Mqtt::publish_time_other_; bool Mqtt::mqtt_enabled_; +bool Mqtt::multiple_instances_; bool Mqtt::ha_enabled_; uint8_t Mqtt::nested_format_; std::string Mqtt::discovery_prefix_; @@ -422,6 +423,7 @@ void Mqtt::load_settings() { publish_single2cmd_ = mqttSettings.publish_single2cmd; send_response_ = mqttSettings.send_response; discovery_prefix_ = mqttSettings.discovery_prefix.c_str(); + multiple_instances_ = mqttSettings.multiple_instances; // convert to milliseconds publish_time_boiler_ = mqttSettings.publish_time_boiler * 1000; @@ -594,10 +596,10 @@ void Mqtt::ha_status() { StaticJsonDocument doc; char uniq[70]; - snprintf(uniq, sizeof(uniq), "%s_status", mqtt_basename_.c_str()); + snprintf(uniq, sizeof(uniq), "%s_status", mqtt_basename_.c_str()); // always use basename doc["uniq_id"] = uniq; doc["object_id"] = uniq; - doc["~"] = mqtt_base_; // default ems-esp + doc["~"] = mqtt_base_; // doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes // doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes doc["stat_t"] = "~/status"; @@ -784,6 +786,7 @@ void Mqtt::process_queue() { if (message->topic.find(discovery_prefix_) == 0) { strlcpy(topic, message->topic.c_str(), sizeof(topic)); // leave topic as it is } else { + // it's a discovery topic, added the mqtt base to the topic path snprintf(topic, MQTT_TOPIC_MAX_SIZE, "%s/%s", mqtt_base_.c_str(), message->topic.c_str()); // uses base } @@ -965,7 +968,12 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev // build unique identifier which will be used in the topic, also used as object_id char uniq_id[70]; - snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag); + if (multiple_instances_) { + // prefix base name to each uniq_id + snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag); + } else { + snprintf(uniq_id, sizeof(uniq_id), "%s_%s", device_name, entity_with_tag); + } // build a config topic that will be prefix onto a HA type (e.g. number, switch) // e.g. homeassistant/number/ems-esp/thermostat_hc1_manualtemp @@ -1267,7 +1275,13 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, hc_mode_s); snprintf(name_s, sizeof(name_s), "Hc%d", hc_num); - snprintf(uniq_id_s, sizeof(uniq_id_s), "%s_thermostat_hc%d", mqtt_basename_.c_str(), hc_num); // add basename + + if (Mqtt::multiple_instances()) { + snprintf(uniq_id_s, sizeof(uniq_id_s), "%s_thermostat_hc%d", mqtt_basename_.c_str(), hc_num); // add basename + } else { + snprintf(uniq_id_s, sizeof(uniq_id_s), "thermostat_hc%d", hc_num); // backward compatible with v3.4 + } + snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num); snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num); diff --git a/src/mqtt.h b/src/mqtt.h index 65e4fcad7..1fcebb217 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -179,6 +179,10 @@ class Mqtt { return nested_format_ == NestedFormat::NESTED; } + static bool multiple_instances() { + return multiple_instances_; + } + static void nested_format(uint8_t nested_format) { nested_format_ = nested_format; } @@ -314,6 +318,7 @@ class Mqtt { static bool mqtt_enabled_; static bool ha_enabled_; static uint8_t nested_format_; + static bool multiple_instances_; static std::string discovery_prefix_; static bool publish_single_; static bool publish_single2cmd_; From 995420354e04d6db1dc2600f09eededab54693d8 Mon Sep 17 00:00:00 2001 From: Proddy Date: Tue, 6 Dec 2022 11:15:14 +0100 Subject: [PATCH 39/52] remove breaking change note about MQTT discovery --- CHANGELOG_LATEST.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 5eeeaa02b..64ecba199 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -5,7 +5,6 @@ ## **IMPORTANT! BREAKING CHANGES** - When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade. -- Since 3.5.0b11 we added support for multiple EMS-ESPs [#759] so they can co-exist with MQTT Discovery. The mqtt base is now included in each of the entity names to make them unique. Unfortunately this means in Home Assistant the entity IDs have also been renamed (for example from `number.boiler_burnminperiod` to `number.ems_esp_boiler_burnminperiod`) and any dashboards and automation scripts need to be adjusted accordingly. ## Added From fa703db41e3fe425730c103b8133672da3f2a910 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Wed, 7 Dec 2022 07:42:47 +0100 Subject: [PATCH 40/52] heartbeat time in standalone --- interface/package.json | 2 +- interface/src/i18n/de/index.ts | 2 +- lib_standalone/ESP8266React.h | 1 + mock-api/server.js | 1 + src/system.cpp | 1 + 5 files changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/package.json b/interface/package.json index 91afdb57e..4dbd7f5e9 100644 --- a/interface/package.json +++ b/interface/package.json @@ -8,7 +8,7 @@ "@emotion/styled": "^11.10.5", "@msgpack/msgpack": "^2.8.0", "@mui/icons-material": "^5.10.16", - "@mui/material": "^5.10.16", + "@mui/material": "^5.10.17", "@table-library/react-table-library": "4.0.23", "@types/lodash": "^4.14.191", "@types/node": "^18.11.11", diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index 3a4f450fd..dde8b25f4 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -248,7 +248,7 @@ const de: Translation = { MQTT_INT_HEARTBEAT: 'Heartbeat', MQTT_QUEUE: 'MQTT Queue', DEFAULT: 'Standard', - MQTT_MULTIPLE_INSTANCES: 'Enable Multiple Instances of EMS-ESP', + MQTT_MULTIPLE_INSTANCES: 'Erlaube EMS-ESP Mehrfachinstanzen', MQTT_CLEAN_SESSION: 'Setze `Clean Session`', MQTT_RETAIN_FLAG: 'Setze `Retain flag` immer', INACTIVE: 'Inaktiv', diff --git a/lib_standalone/ESP8266React.h b/lib_standalone/ESP8266React.h index 4587c8817..25973a224 100644 --- a/lib_standalone/ESP8266React.h +++ b/lib_standalone/ESP8266React.h @@ -89,6 +89,7 @@ class DummySettings { uint16_t publish_time_mixer = 10; uint16_t publish_time_other = 10; uint16_t publish_time_sensor = 10; + uint16_t publish_time_heartbeat = 60; String hostname = "ems-esp"; String jwtSecret = "ems-esp"; diff --git a/mock-api/server.js b/mock-api/server.js index 28315dfbc..ecf2f7927 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -226,6 +226,7 @@ mqtt_settings = { publish_time_mixer: 10, publish_time_other: 10, publish_time_sensor: 10, + publish_time_heartbeat: 60, mqtt_qos: 0, mqtt_retain: false, ha_enabled: true, diff --git a/src/system.cpp b/src/system.cpp index fe0ce91a9..1f9ccac9e 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1154,6 +1154,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp node["ha enabled"] = settings.ha_enabled; node["mqtt qos"] = settings.mqtt_qos; node["mqtt retain"] = settings.mqtt_retain; + node["publish time heartbeat"] = settings.publish_time_heartbeat; node["publish time boiler"] = settings.publish_time_boiler; node["publish time thermostat"] = settings.publish_time_thermostat; node["publish time solar"] = settings.publish_time_solar; From 1735c036ccb9e7ff2a7562238236aafca974397d Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Wed, 7 Dec 2022 13:10:31 +0100 Subject: [PATCH 41/52] move multiple instances setting to HA section --- .../src/framework/mqtt/MqttSettingsForm.tsx | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/interface/src/framework/mqtt/MqttSettingsForm.tsx b/interface/src/framework/mqtt/MqttSettingsForm.tsx index 41ed3d8fe..013799b09 100644 --- a/interface/src/framework/mqtt/MqttSettingsForm.tsx +++ b/interface/src/framework/mqtt/MqttSettingsForm.tsx @@ -162,10 +162,6 @@ const MqttSettingsForm: FC = () => { - } - label={LL.MQTT_MULTIPLE_INSTANCES()} - /> } label={LL.MQTT_CLEAN_SESSION()} @@ -224,17 +220,25 @@ const MqttSettingsForm: FC = () => { /> {data.ha_enabled && ( - - - + <> + + } + label={LL.MQTT_MULTIPLE_INSTANCES()} + /> + + + + + )} )} From 5061ddf38efe0d01d9a7a4e7fd2dd69c7d238b4e Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Wed, 7 Dec 2022 13:11:48 +0100 Subject: [PATCH 42/52] add CORS option to network --- interface/package-lock.json | 722 +++++++++--------- .../framework/network/NetworkSettingsForm.tsx | 31 +- interface/src/i18n/de/index.ts | 7 +- interface/src/i18n/en/index.ts | 2 + interface/src/i18n/nl/index.ts | 2 + interface/src/i18n/no/index.ts | 2 + interface/src/i18n/pl/index.ts | 2 + interface/src/i18n/se/index.ts | 2 + interface/src/types/network.ts | 2 + lib/framework/ESP8266React.cpp | 7 + lib/framework/NetworkSettingsService.h | 6 + lib_standalone/ESP8266React.h | 2 + mock-api/server.js | 4 + src/system.cpp | 5 + 14 files changed, 428 insertions(+), 368 deletions(-) diff --git a/interface/package-lock.json b/interface/package-lock.json index 9b1f3f369..36f95d85d 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -12,7 +12,7 @@ "@emotion/styled": "^11.10.5", "@msgpack/msgpack": "^2.8.0", "@mui/icons-material": "^5.10.16", - "@mui/material": "^5.10.16", + "@mui/material": "^5.10.17", "@table-library/react-table-library": "4.0.23", "@types/lodash": "^4.14.191", "@types/node": "^18.11.11", @@ -66,28 +66,28 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.1.tgz", - "integrity": "sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz", + "integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.2.tgz", - "integrity": "sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz", + "integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.2", + "@babel/generator": "^7.20.5", "@babel/helper-compilation-targets": "^7.20.0", "@babel/helper-module-transforms": "^7.20.2", - "@babel/helpers": "^7.20.1", - "@babel/parser": "^7.20.2", + "@babel/helpers": "^7.20.5", + "@babel/parser": "^7.20.5", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2", + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -128,11 +128,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.20.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.4.tgz", - "integrity": "sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", + "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", "dependencies": { - "@babel/types": "^7.20.2", + "@babel/types": "^7.20.5", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -194,9 +194,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.2.tgz", - "integrity": "sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.5.tgz", + "integrity": "sha512-3RCdA/EmEaikrhayahwToF0fpweU/8o2p8vhc1c/1kftHOdTKuC65kik/TLc+qfbS8JKw4qqJbne4ovICDhmww==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-environment-visitor": "^7.18.9", @@ -214,12 +214,12 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz", - "integrity": "sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz", + "integrity": "sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.1.0" + "regexpu-core": "^5.2.1" }, "engines": { "node": ">=6.9.0" @@ -435,27 +435,27 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz", - "integrity": "sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", + "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", "dependencies": { "@babel/helper-function-name": "^7.19.0", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.1.tgz", - "integrity": "sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz", + "integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==", "dependencies": { "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.0" + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" }, "engines": { "node": ">=6.9.0" @@ -475,9 +475,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.3.tgz", - "integrity": "sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", + "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -564,11 +564,11 @@ } }, "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.20.2.tgz", - "integrity": "sha512-nkBH96IBmgKnbHQ5gXFrcmez+Z9S2EIDKDQGp005ROqBigc88Tky4rzCnlP/lnlj245dCEQl4/YyV0V1kYh5dw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.20.5.tgz", + "integrity": "sha512-Lac7PpRJXcC3s9cKsBfl+uc+DYXU5FD06BrTFunQO6QIQT+DwyzDPURAowI3bcvD1dZF/ank1Z5rstUJn3Hn4Q==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.20.2", + "@babel/helper-create-class-features-plugin": "^7.20.5", "@babel/helper-plugin-utils": "^7.20.2", "@babel/helper-replace-supers": "^7.19.1", "@babel/helper-split-export-declaration": "^7.18.6", @@ -736,13 +736,13 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", - "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz", + "integrity": "sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1067,9 +1067,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.2.tgz", - "integrity": "sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.5.tgz", + "integrity": "sha512-WvpEIW9Cbj9ApF3yJCjIEEf1EiNJLtXagOrL5LNWEZOo3jv8pmPoYTSNJQvqej8OavVlgOoOPw6/htGZro6IkA==", "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" }, @@ -1311,12 +1311,12 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz", - "integrity": "sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", + "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-create-regexp-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1355,9 +1355,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.3.tgz", - "integrity": "sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.5.tgz", + "integrity": "sha512-h7plkOmcndIUWXZFLgpbrh2+fXAi47zcUX7IrOQuZdLD0I0KvjJ6cvo3BEcAOsDOcZhVKGJqv07mkSqK0y2isQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" }, @@ -1458,12 +1458,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", - "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", + "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "regenerator-transform": "^0.15.0" + "@babel/helper-plugin-utils": "^7.20.2", + "regenerator-transform": "^0.15.1" }, "engines": { "node": ">=6.9.0" @@ -1760,23 +1760,23 @@ } }, "node_modules/@babel/runtime": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.1.tgz", - "integrity": "sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", + "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", "dependencies": { - "regenerator-runtime": "^0.13.10" + "regenerator-runtime": "^0.13.11" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.20.1.tgz", - "integrity": "sha512-CGulbEDcg/ND1Im7fUNRZdGXmX2MTWVVZacQi/6DiKE5HNwZ3aVTm5PV4lO8HHz0B2h8WQyvKKjbX5XgTtydsg==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.20.6.tgz", + "integrity": "sha512-tqeujPiuEfcH067mx+7otTQWROVMKHXEaOQcAeNV5dDdbPWvPcFA8/W9LXw2NfjNmOetqLl03dfnG2WALPlsRQ==", "dependencies": { "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.10" + "regenerator-runtime": "^0.13.11" }, "engines": { "node": ">=6.9.0" @@ -1796,18 +1796,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.1.tgz", - "integrity": "sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", + "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.1", + "@babel/generator": "^7.20.5", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.1", - "@babel/types": "^7.20.0", + "@babel/parser": "^7.20.5", + "@babel/types": "^7.20.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1816,9 +1816,9 @@ } }, "node_modules/@babel/types": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.2.tgz", - "integrity": "sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", + "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -3091,9 +3091,9 @@ } }, "node_modules/@mui/base": { - "version": "5.0.0-alpha.108", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.108.tgz", - "integrity": "sha512-KjzRUts2i/ODlMfywhFTqTzQl+Cr9nlDSZxJcnYjrbOV/iRyQNBTDoiFJt+XEdRi0fZBHnk74AFbnP56ehybsA==", + "version": "5.0.0-alpha.109", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.109.tgz", + "integrity": "sha512-UQxoONPI3ntzxcD/cbFHl+Lp2xsVj6HpKmU9QhUZ2kZ2K2yej2QJyU1gnADoWl/Hu94VrvwSSRnjTjR3HvXO/g==", "dependencies": { "@babel/runtime": "^7.20.1", "@emotion/is-prop-valid": "^1.2.0", @@ -3123,9 +3123,9 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.10.16", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.16.tgz", - "integrity": "sha512-eK9+olw2ZbXX+vGrtKnN01/vLP1aX0Lq0xok35bqWM1aB93Dcmky/xPNf8h31oJ/C+IzJBjZaZMEDzVZg4Qc0A==", + "version": "5.10.17", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.17.tgz", + "integrity": "sha512-iNwUuMA30nrN0tiEkeD3zaczv7Tk2jlZIDbXRnijAsYXkZtl/xEzQsVRIPYRDuyEz6D18vQJhV8h7gPUXEubTg==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui" @@ -3157,14 +3157,14 @@ } }, "node_modules/@mui/material": { - "version": "5.10.16", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.16.tgz", - "integrity": "sha512-JSHcDQQ+k30NKkCM/0KX6jq4F5LOrbFKZpS+cEl7scZWOCJpUPH5ccAT5a7O8wzrgNZ8Y9PnwzNvWBrfShpJFw==", + "version": "5.10.17", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.17.tgz", + "integrity": "sha512-Kuqgv1qI5HXnc/Xu426xhCGYBSKzplb+xFNLitbnIb92Qx8jmcpfNpFlDJa2kD2H6qP66rr/m4c/zMUfGX/xBQ==", "dependencies": { "@babel/runtime": "^7.20.1", - "@mui/base": "5.0.0-alpha.108", - "@mui/core-downloads-tracker": "^5.10.16", - "@mui/system": "^5.10.16", + "@mui/base": "5.0.0-alpha.109", + "@mui/core-downloads-tracker": "^5.10.17", + "@mui/system": "^5.10.17", "@mui/types": "^7.2.2", "@mui/utils": "^5.10.16", "@types/react-transition-group": "^4.4.5", @@ -3258,9 +3258,9 @@ } }, "node_modules/@mui/system": { - "version": "5.10.16", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.16.tgz", - "integrity": "sha512-OqI9B1jZ9zQ/dmoqseku4CzdEs9DbLiiMOaWxC3WeAJxM1UavlCgXz0encqm93LIlmSL7TjuHN1/rW8BJCnU8A==", + "version": "5.10.17", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.17.tgz", + "integrity": "sha512-UYzAOSK7uxkMsUssqrIUW3lnOuQpU8vqh4hLwfSw+GYAnQo3qjK4m4NhlDx+pFpsjjiGnr3K+vrSH+aIAMbcLg==", "dependencies": { "@babel/runtime": "^7.20.1", "@mui/private-theming": "^5.10.16", @@ -3550,9 +3550,9 @@ "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" }, "node_modules/@sinonjs/commons": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.5.tgz", - "integrity": "sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dependencies": { "type-detect": "4.0.8" } @@ -3864,9 +3864,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", - "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", + "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", "dependencies": { "@babel/types": "^7.3.0" } @@ -4184,13 +4184,13 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.44.0.tgz", - "integrity": "sha512-j5ULd7FmmekcyWeArx+i8x7sdRHzAtXTkmDPthE4amxZOWKFK7bomoJ4r7PJ8K7PoMzD16U8MmuZFAonr1ERvw==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.45.1.tgz", + "integrity": "sha512-cOizjPlKEh0bXdFrBLTrI/J6B/QMlhwE9auOov53tgB+qMukH6/h8YAK/qw+QJGct/PTbdh2lytGyipxCcEtAw==", "dependencies": { - "@typescript-eslint/scope-manager": "5.44.0", - "@typescript-eslint/type-utils": "5.44.0", - "@typescript-eslint/utils": "5.44.0", + "@typescript-eslint/scope-manager": "5.45.1", + "@typescript-eslint/type-utils": "5.45.1", + "@typescript-eslint/utils": "5.45.1", "debug": "^4.3.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", @@ -4230,11 +4230,11 @@ } }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.44.0.tgz", - "integrity": "sha512-j8GLemAySe8oUCgILdUaT66pemdWSYcwUYG2Pb71O119hCdvkU+4q8sUTbnDg8NhlZEzSWG2N1v4IxT1kEZrGg==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.45.1.tgz", + "integrity": "sha512-WlXwY9dbmc0Lzu6xQOZ3yN8u/ws/1R8zPC16O217LMZJCbV2hJezqkWMUB+jMwguOJW+cukCDe92vcwwf8zwjQ==", "dependencies": { - "@typescript-eslint/utils": "5.44.0" + "@typescript-eslint/utils": "5.45.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4248,13 +4248,13 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.44.0.tgz", - "integrity": "sha512-H7LCqbZnKqkkgQHaKLGC6KUjt3pjJDx8ETDqmwncyb6PuoigYajyAwBGz08VU/l86dZWZgI4zm5k2VaKqayYyA==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.45.1.tgz", + "integrity": "sha512-JQ3Ep8bEOXu16q0ztsatp/iQfDCtvap7sp/DKo7DWltUquj5AfCOpX2zSzJ8YkAVnrQNqQ5R62PBz2UtrfmCkA==", "dependencies": { - "@typescript-eslint/scope-manager": "5.44.0", - "@typescript-eslint/types": "5.44.0", - "@typescript-eslint/typescript-estree": "5.44.0", + "@typescript-eslint/scope-manager": "5.45.1", + "@typescript-eslint/types": "5.45.1", + "@typescript-eslint/typescript-estree": "5.45.1", "debug": "^4.3.4" }, "engines": { @@ -4274,12 +4274,12 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.44.0.tgz", - "integrity": "sha512-2pKml57KusI0LAhgLKae9kwWeITZ7IsZs77YxyNyIVOwQ1kToyXRaJLl+uDEXzMN5hnobKUOo2gKntK9H1YL8g==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.45.1.tgz", + "integrity": "sha512-D6fCileR6Iai7E35Eb4Kp+k0iW7F1wxXYrOhX/3dywsOJpJAQ20Fwgcf+P/TDtvQ7zcsWsrJaglaQWDhOMsspQ==", "dependencies": { - "@typescript-eslint/types": "5.44.0", - "@typescript-eslint/visitor-keys": "5.44.0" + "@typescript-eslint/types": "5.45.1", + "@typescript-eslint/visitor-keys": "5.45.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4290,12 +4290,12 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.44.0.tgz", - "integrity": "sha512-A1u0Yo5wZxkXPQ7/noGkRhV4J9opcymcr31XQtOzcc5nO/IHN2E2TPMECKWYpM3e6olWEM63fq/BaL1wEYnt/w==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.45.1.tgz", + "integrity": "sha512-aosxFa+0CoYgYEl3aptLe1svP910DJq68nwEJzyQcrtRhC4BN0tJAvZGAe+D0tzjJmFXe+h4leSsiZhwBa2vrA==", "dependencies": { - "@typescript-eslint/typescript-estree": "5.44.0", - "@typescript-eslint/utils": "5.44.0", + "@typescript-eslint/typescript-estree": "5.45.1", + "@typescript-eslint/utils": "5.45.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -4316,9 +4316,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.44.0.tgz", - "integrity": "sha512-Tp+zDnHmGk4qKR1l+Y1rBvpjpm5tGXX339eAlRBDg+kgZkz9Bw+pqi4dyseOZMsGuSH69fYfPJCBKBrbPCxYFQ==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.45.1.tgz", + "integrity": "sha512-HEW3U0E5dLjUT+nk7b4lLbOherS1U4ap+b9pfu2oGsW3oPu7genRaY9dDv3nMczC1rbnRY2W/D7SN05wYoGImg==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -4328,12 +4328,12 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.44.0.tgz", - "integrity": "sha512-M6Jr+RM7M5zeRj2maSfsZK2660HKAJawv4Ud0xT+yauyvgrsHu276VtXlKDFnEmhG+nVEd0fYZNXGoAgxwDWJw==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.45.1.tgz", + "integrity": "sha512-76NZpmpCzWVrrb0XmYEpbwOz/FENBi+5W7ipVXAsG3OoFrQKJMiaqsBMbvGRyLtPotGqUfcY7Ur8j0dksDJDng==", "dependencies": { - "@typescript-eslint/types": "5.44.0", - "@typescript-eslint/visitor-keys": "5.44.0", + "@typescript-eslint/types": "5.45.1", + "@typescript-eslint/visitor-keys": "5.45.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -4368,15 +4368,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.44.0.tgz", - "integrity": "sha512-fMzA8LLQ189gaBjS0MZszw5HBdZgVwxVFShCO3QN+ws3GlPkcy9YuS3U4wkT6su0w+Byjq3mS3uamy9HE4Yfjw==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.45.1.tgz", + "integrity": "sha512-rlbC5VZz68+yjAzQBc4I7KDYVzWG2X/OrqoZrMahYq3u8FFtmQYc+9rovo/7wlJH5kugJ+jQXV5pJMnofGmPRw==", "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.44.0", - "@typescript-eslint/types": "5.44.0", - "@typescript-eslint/typescript-estree": "5.44.0", + "@typescript-eslint/scope-manager": "5.45.1", + "@typescript-eslint/types": "5.45.1", + "@typescript-eslint/typescript-estree": "5.45.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -4427,11 +4427,11 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.44.0.tgz", - "integrity": "sha512-a48tLG8/4m62gPFbJ27FxwCOqPKxsb8KC3HkmYoq2As/4YyjQl1jDbRr1s63+g4FS/iIehjmN3L5UjmKva1HzQ==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.1.tgz", + "integrity": "sha512-cy9ln+6rmthYWjH9fmx+5FU/JDpjQb586++x2FZlveq7GdGuLLW9a2Jcst2TGekH82bXpfmRNSwP9tyEs6RjvQ==", "dependencies": { - "@typescript-eslint/types": "5.44.0", + "@typescript-eslint/types": "5.45.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -5576,9 +5576,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001434", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz", - "integrity": "sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA==", + "version": "1.0.30001436", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001436.tgz", + "integrity": "sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg==", "funding": [ { "type": "opencollective", @@ -6233,9 +6233,9 @@ } }, "node_modules/cssdb": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.1.0.tgz", - "integrity": "sha512-Sd99PrFgx28ez4GHu8yoQIufc/70h9oYowDf4EjeIKi8mac9whxRjhM3IaMr6EllP6KKKWtJrMfN6C7T9tIWvQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.2.0.tgz", + "integrity": "sha512-JYlIsE7eKHSi0UNuCyo96YuIDFqvhGgHw4Ck6lsN+DP0Tp8M64UTDT2trGbkMDqnCoEjks7CkS0XcjU0rkvBdg==", "funding": { "type": "opencollective", "url": "https://opencollective.com/csstools" @@ -6422,9 +6422,9 @@ } }, "node_modules/decimal.js": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", - "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==" + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" }, "node_modules/dedent": { "version": "0.7.0", @@ -7004,9 +7004,9 @@ } }, "node_modules/eslint": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz", - "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", + "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", "dependencies": { "@eslint/eslintrc": "^1.3.3", "@humanwhocodes/config-array": "^0.11.6", @@ -7925,9 +7925,9 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dependencies": { "reusify": "^1.0.4" } @@ -8009,9 +8009,9 @@ } }, "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", + "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -8955,9 +8955,9 @@ } }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", + "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", "engines": { "node": ">= 4" } @@ -11054,9 +11054,9 @@ } }, "node_modules/jest-watch-typeahead/node_modules/@types/yargs": { - "version": "17.0.14", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.14.tgz", - "integrity": "sha512-9Pj7abXoW1RSTcZaL2Hk6G2XyLMlp5ECdVC/Zf2p/KBjC3srijLGgRAXOBjtFrJoIrvxdTKyKDA14bEcbxBaWw==", + "version": "17.0.16", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.16.tgz", + "integrity": "sha512-Mh3OP0oh8X7O7F9m5AplC+XHYLBWuPKNkGVD3gIZFLFebBnuFI2Nz5Sf8WLvwGxECJ8YjifQvFdh79ubODkdug==", "dependencies": { "@types/yargs-parser": "*" } @@ -11626,11 +11626,11 @@ "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" }, "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.6.tgz", + "integrity": "sha512-HNkaCgM8wZgE/BZACeotAAgpL9FUjEnhgF0FVQMIgH//zqTPreLYMb3rWYkYAqPoF75Jwuycp1da7uz66cfFQg==", "dependencies": { - "language-subtag-registry": "~0.3.2" + "language-subtag-registry": "^0.3.20" } }, "node_modules/leven": { @@ -11943,9 +11943,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz", - "integrity": "sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.2.tgz", + "integrity": "sha512-EdlUizq13o0Pd+uCp+WO/JpkLvHRVGt97RqfeGhXqAcorYo1ypJSpkV+WDT0vY/kmh/p7wRdJNJtuyK540PXDw==", "dependencies": { "schema-utils": "^4.0.0" }, @@ -13047,9 +13047,9 @@ } }, "node_modules/postcss-custom-properties": { - "version": "12.1.10", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.10.tgz", - "integrity": "sha512-U3BHdgrYhCrwTVcByFHs9EOBoqcKq4Lf3kXwbTi4hhq0qWhl/pDWq2THbv/ICX/Fl9KqeHBb8OVrTf2OaYF07A==", + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", + "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -15082,6 +15082,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", "dependencies": { "@babel/code-frame": "^7.10.4", "jest-worker": "^26.2.1", @@ -15593,7 +15594,8 @@ "node_modules/sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" }, "node_modules/spdx-correct": { "version": "3.1.1", @@ -16155,9 +16157,9 @@ } }, "node_modules/terser": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.0.tgz", - "integrity": "sha512-KjTV81QKStSfwbNiwlBXfcgMcOloyuRdb62/iLFPGBcVNF4EXjhdYBhYHmbJpiBrVxZhDvltE11j+LBQUxEEJg==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", "dependencies": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", @@ -17600,25 +17602,25 @@ } }, "@babel/compat-data": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.1.tgz", - "integrity": "sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==" + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz", + "integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==" }, "@babel/core": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.2.tgz", - "integrity": "sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz", + "integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==", "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.2", + "@babel/generator": "^7.20.5", "@babel/helper-compilation-targets": "^7.20.0", "@babel/helper-module-transforms": "^7.20.2", - "@babel/helpers": "^7.20.1", - "@babel/parser": "^7.20.2", + "@babel/helpers": "^7.20.5", + "@babel/parser": "^7.20.5", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.2", + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -17644,11 +17646,11 @@ } }, "@babel/generator": { - "version": "7.20.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.4.tgz", - "integrity": "sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", + "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", "requires": { - "@babel/types": "^7.20.2", + "@babel/types": "^7.20.5", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -17694,9 +17696,9 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.2.tgz", - "integrity": "sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.5.tgz", + "integrity": "sha512-3RCdA/EmEaikrhayahwToF0fpweU/8o2p8vhc1c/1kftHOdTKuC65kik/TLc+qfbS8JKw4qqJbne4ovICDhmww==", "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-environment-visitor": "^7.18.9", @@ -17708,12 +17710,12 @@ } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz", - "integrity": "sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz", + "integrity": "sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w==", "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.1.0" + "regexpu-core": "^5.2.1" } }, "@babel/helper-define-polyfill-provider": { @@ -17866,24 +17868,24 @@ "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==" }, "@babel/helper-wrap-function": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz", - "integrity": "sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", + "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", "requires": { "@babel/helper-function-name": "^7.19.0", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" } }, "@babel/helpers": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.1.tgz", - "integrity": "sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz", + "integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==", "requires": { "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.1", - "@babel/types": "^7.20.0" + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" } }, "@babel/highlight": { @@ -17897,9 +17899,9 @@ } }, "@babel/parser": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.3.tgz", - "integrity": "sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==" + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", + "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", @@ -17950,11 +17952,11 @@ } }, "@babel/plugin-proposal-decorators": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.20.2.tgz", - "integrity": "sha512-nkBH96IBmgKnbHQ5gXFrcmez+Z9S2EIDKDQGp005ROqBigc88Tky4rzCnlP/lnlj245dCEQl4/YyV0V1kYh5dw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.20.5.tgz", + "integrity": "sha512-Lac7PpRJXcC3s9cKsBfl+uc+DYXU5FD06BrTFunQO6QIQT+DwyzDPURAowI3bcvD1dZF/ank1Z5rstUJn3Hn4Q==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.20.2", + "@babel/helper-create-class-features-plugin": "^7.20.5", "@babel/helper-plugin-utils": "^7.20.2", "@babel/helper-replace-supers": "^7.19.1", "@babel/helper-split-export-declaration": "^7.18.6", @@ -18056,13 +18058,13 @@ } }, "@babel/plugin-proposal-private-property-in-object": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", - "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz", + "integrity": "sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ==", "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, @@ -18270,9 +18272,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.2.tgz", - "integrity": "sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.5.tgz", + "integrity": "sha512-WvpEIW9Cbj9ApF3yJCjIEEf1EiNJLtXagOrL5LNWEZOo3jv8pmPoYTSNJQvqej8OavVlgOoOPw6/htGZro6IkA==", "requires": { "@babel/helper-plugin-utils": "^7.20.2" } @@ -18418,12 +18420,12 @@ } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz", - "integrity": "sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", + "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-create-regexp-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-transform-new-target": { @@ -18444,9 +18446,9 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.3.tgz", - "integrity": "sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.5.tgz", + "integrity": "sha512-h7plkOmcndIUWXZFLgpbrh2+fXAi47zcUX7IrOQuZdLD0I0KvjJ6cvo3BEcAOsDOcZhVKGJqv07mkSqK0y2isQ==", "requires": { "@babel/helper-plugin-utils": "^7.20.2" } @@ -18505,12 +18507,12 @@ } }, "@babel/plugin-transform-regenerator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", - "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", + "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "regenerator-transform": "^0.15.0" + "@babel/helper-plugin-utils": "^7.20.2", + "regenerator-transform": "^0.15.1" } }, "@babel/plugin-transform-reserved-words": { @@ -18720,20 +18722,20 @@ } }, "@babel/runtime": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.1.tgz", - "integrity": "sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", + "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", "requires": { - "regenerator-runtime": "^0.13.10" + "regenerator-runtime": "^0.13.11" } }, "@babel/runtime-corejs3": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.20.1.tgz", - "integrity": "sha512-CGulbEDcg/ND1Im7fUNRZdGXmX2MTWVVZacQi/6DiKE5HNwZ3aVTm5PV4lO8HHz0B2h8WQyvKKjbX5XgTtydsg==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.20.6.tgz", + "integrity": "sha512-tqeujPiuEfcH067mx+7otTQWROVMKHXEaOQcAeNV5dDdbPWvPcFA8/W9LXw2NfjNmOetqLl03dfnG2WALPlsRQ==", "requires": { "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.10" + "regenerator-runtime": "^0.13.11" } }, "@babel/template": { @@ -18747,26 +18749,26 @@ } }, "@babel/traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.1.tgz", - "integrity": "sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", + "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", "requires": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.1", + "@babel/generator": "^7.20.5", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.1", - "@babel/types": "^7.20.0", + "@babel/parser": "^7.20.5", + "@babel/types": "^7.20.5", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.2.tgz", - "integrity": "sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", + "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", "requires": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", @@ -19640,9 +19642,9 @@ "integrity": "sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==" }, "@mui/base": { - "version": "5.0.0-alpha.108", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.108.tgz", - "integrity": "sha512-KjzRUts2i/ODlMfywhFTqTzQl+Cr9nlDSZxJcnYjrbOV/iRyQNBTDoiFJt+XEdRi0fZBHnk74AFbnP56ehybsA==", + "version": "5.0.0-alpha.109", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.109.tgz", + "integrity": "sha512-UQxoONPI3ntzxcD/cbFHl+Lp2xsVj6HpKmU9QhUZ2kZ2K2yej2QJyU1gnADoWl/Hu94VrvwSSRnjTjR3HvXO/g==", "requires": { "@babel/runtime": "^7.20.1", "@emotion/is-prop-valid": "^1.2.0", @@ -19655,9 +19657,9 @@ } }, "@mui/core-downloads-tracker": { - "version": "5.10.16", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.16.tgz", - "integrity": "sha512-eK9+olw2ZbXX+vGrtKnN01/vLP1aX0Lq0xok35bqWM1aB93Dcmky/xPNf8h31oJ/C+IzJBjZaZMEDzVZg4Qc0A==" + "version": "5.10.17", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.17.tgz", + "integrity": "sha512-iNwUuMA30nrN0tiEkeD3zaczv7Tk2jlZIDbXRnijAsYXkZtl/xEzQsVRIPYRDuyEz6D18vQJhV8h7gPUXEubTg==" }, "@mui/icons-material": { "version": "5.10.16", @@ -19668,14 +19670,14 @@ } }, "@mui/material": { - "version": "5.10.16", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.16.tgz", - "integrity": "sha512-JSHcDQQ+k30NKkCM/0KX6jq4F5LOrbFKZpS+cEl7scZWOCJpUPH5ccAT5a7O8wzrgNZ8Y9PnwzNvWBrfShpJFw==", + "version": "5.10.17", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.17.tgz", + "integrity": "sha512-Kuqgv1qI5HXnc/Xu426xhCGYBSKzplb+xFNLitbnIb92Qx8jmcpfNpFlDJa2kD2H6qP66rr/m4c/zMUfGX/xBQ==", "requires": { "@babel/runtime": "^7.20.1", - "@mui/base": "5.0.0-alpha.108", - "@mui/core-downloads-tracker": "^5.10.16", - "@mui/system": "^5.10.16", + "@mui/base": "5.0.0-alpha.109", + "@mui/core-downloads-tracker": "^5.10.17", + "@mui/system": "^5.10.17", "@mui/types": "^7.2.2", "@mui/utils": "^5.10.16", "@types/react-transition-group": "^4.4.5", @@ -19708,9 +19710,9 @@ } }, "@mui/system": { - "version": "5.10.16", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.16.tgz", - "integrity": "sha512-OqI9B1jZ9zQ/dmoqseku4CzdEs9DbLiiMOaWxC3WeAJxM1UavlCgXz0encqm93LIlmSL7TjuHN1/rW8BJCnU8A==", + "version": "5.10.17", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.17.tgz", + "integrity": "sha512-UYzAOSK7uxkMsUssqrIUW3lnOuQpU8vqh4hLwfSw+GYAnQo3qjK4m4NhlDx+pFpsjjiGnr3K+vrSH+aIAMbcLg==", "requires": { "@babel/runtime": "^7.20.1", "@mui/private-theming": "^5.10.16", @@ -19879,9 +19881,9 @@ "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" }, "@sinonjs/commons": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.5.tgz", - "integrity": "sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "requires": { "type-detect": "4.0.8" } @@ -20077,9 +20079,9 @@ } }, "@types/babel__traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", - "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", + "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", "requires": { "@babel/types": "^7.3.0" } @@ -20397,13 +20399,13 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, "@typescript-eslint/eslint-plugin": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.44.0.tgz", - "integrity": "sha512-j5ULd7FmmekcyWeArx+i8x7sdRHzAtXTkmDPthE4amxZOWKFK7bomoJ4r7PJ8K7PoMzD16U8MmuZFAonr1ERvw==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.45.1.tgz", + "integrity": "sha512-cOizjPlKEh0bXdFrBLTrI/J6B/QMlhwE9auOov53tgB+qMukH6/h8YAK/qw+QJGct/PTbdh2lytGyipxCcEtAw==", "requires": { - "@typescript-eslint/scope-manager": "5.44.0", - "@typescript-eslint/type-utils": "5.44.0", - "@typescript-eslint/utils": "5.44.0", + "@typescript-eslint/scope-manager": "5.45.1", + "@typescript-eslint/type-utils": "5.45.1", + "@typescript-eslint/utils": "5.45.1", "debug": "^4.3.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", @@ -20423,56 +20425,56 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.44.0.tgz", - "integrity": "sha512-j8GLemAySe8oUCgILdUaT66pemdWSYcwUYG2Pb71O119hCdvkU+4q8sUTbnDg8NhlZEzSWG2N1v4IxT1kEZrGg==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.45.1.tgz", + "integrity": "sha512-WlXwY9dbmc0Lzu6xQOZ3yN8u/ws/1R8zPC16O217LMZJCbV2hJezqkWMUB+jMwguOJW+cukCDe92vcwwf8zwjQ==", "requires": { - "@typescript-eslint/utils": "5.44.0" + "@typescript-eslint/utils": "5.45.1" } }, "@typescript-eslint/parser": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.44.0.tgz", - "integrity": "sha512-H7LCqbZnKqkkgQHaKLGC6KUjt3pjJDx8ETDqmwncyb6PuoigYajyAwBGz08VU/l86dZWZgI4zm5k2VaKqayYyA==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.45.1.tgz", + "integrity": "sha512-JQ3Ep8bEOXu16q0ztsatp/iQfDCtvap7sp/DKo7DWltUquj5AfCOpX2zSzJ8YkAVnrQNqQ5R62PBz2UtrfmCkA==", "requires": { - "@typescript-eslint/scope-manager": "5.44.0", - "@typescript-eslint/types": "5.44.0", - "@typescript-eslint/typescript-estree": "5.44.0", + "@typescript-eslint/scope-manager": "5.45.1", + "@typescript-eslint/types": "5.45.1", + "@typescript-eslint/typescript-estree": "5.45.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.44.0.tgz", - "integrity": "sha512-2pKml57KusI0LAhgLKae9kwWeITZ7IsZs77YxyNyIVOwQ1kToyXRaJLl+uDEXzMN5hnobKUOo2gKntK9H1YL8g==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.45.1.tgz", + "integrity": "sha512-D6fCileR6Iai7E35Eb4Kp+k0iW7F1wxXYrOhX/3dywsOJpJAQ20Fwgcf+P/TDtvQ7zcsWsrJaglaQWDhOMsspQ==", "requires": { - "@typescript-eslint/types": "5.44.0", - "@typescript-eslint/visitor-keys": "5.44.0" + "@typescript-eslint/types": "5.45.1", + "@typescript-eslint/visitor-keys": "5.45.1" } }, "@typescript-eslint/type-utils": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.44.0.tgz", - "integrity": "sha512-A1u0Yo5wZxkXPQ7/noGkRhV4J9opcymcr31XQtOzcc5nO/IHN2E2TPMECKWYpM3e6olWEM63fq/BaL1wEYnt/w==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.45.1.tgz", + "integrity": "sha512-aosxFa+0CoYgYEl3aptLe1svP910DJq68nwEJzyQcrtRhC4BN0tJAvZGAe+D0tzjJmFXe+h4leSsiZhwBa2vrA==", "requires": { - "@typescript-eslint/typescript-estree": "5.44.0", - "@typescript-eslint/utils": "5.44.0", + "@typescript-eslint/typescript-estree": "5.45.1", + "@typescript-eslint/utils": "5.45.1", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.44.0.tgz", - "integrity": "sha512-Tp+zDnHmGk4qKR1l+Y1rBvpjpm5tGXX339eAlRBDg+kgZkz9Bw+pqi4dyseOZMsGuSH69fYfPJCBKBrbPCxYFQ==" + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.45.1.tgz", + "integrity": "sha512-HEW3U0E5dLjUT+nk7b4lLbOherS1U4ap+b9pfu2oGsW3oPu7genRaY9dDv3nMczC1rbnRY2W/D7SN05wYoGImg==" }, "@typescript-eslint/typescript-estree": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.44.0.tgz", - "integrity": "sha512-M6Jr+RM7M5zeRj2maSfsZK2660HKAJawv4Ud0xT+yauyvgrsHu276VtXlKDFnEmhG+nVEd0fYZNXGoAgxwDWJw==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.45.1.tgz", + "integrity": "sha512-76NZpmpCzWVrrb0XmYEpbwOz/FENBi+5W7ipVXAsG3OoFrQKJMiaqsBMbvGRyLtPotGqUfcY7Ur8j0dksDJDng==", "requires": { - "@typescript-eslint/types": "5.44.0", - "@typescript-eslint/visitor-keys": "5.44.0", + "@typescript-eslint/types": "5.45.1", + "@typescript-eslint/visitor-keys": "5.45.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -20491,15 +20493,15 @@ } }, "@typescript-eslint/utils": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.44.0.tgz", - "integrity": "sha512-fMzA8LLQ189gaBjS0MZszw5HBdZgVwxVFShCO3QN+ws3GlPkcy9YuS3U4wkT6su0w+Byjq3mS3uamy9HE4Yfjw==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.45.1.tgz", + "integrity": "sha512-rlbC5VZz68+yjAzQBc4I7KDYVzWG2X/OrqoZrMahYq3u8FFtmQYc+9rovo/7wlJH5kugJ+jQXV5pJMnofGmPRw==", "requires": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.44.0", - "@typescript-eslint/types": "5.44.0", - "@typescript-eslint/typescript-estree": "5.44.0", + "@typescript-eslint/scope-manager": "5.45.1", + "@typescript-eslint/types": "5.45.1", + "@typescript-eslint/typescript-estree": "5.45.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -20530,11 +20532,11 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.44.0.tgz", - "integrity": "sha512-a48tLG8/4m62gPFbJ27FxwCOqPKxsb8KC3HkmYoq2As/4YyjQl1jDbRr1s63+g4FS/iIehjmN3L5UjmKva1HzQ==", + "version": "5.45.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.1.tgz", + "integrity": "sha512-cy9ln+6rmthYWjH9fmx+5FU/JDpjQb586++x2FZlveq7GdGuLLW9a2Jcst2TGekH82bXpfmRNSwP9tyEs6RjvQ==", "requires": { - "@typescript-eslint/types": "5.44.0", + "@typescript-eslint/types": "5.45.1", "eslint-visitor-keys": "^3.3.0" } }, @@ -21417,9 +21419,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001434", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz", - "integrity": "sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA==" + "version": "1.0.30001436", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001436.tgz", + "integrity": "sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg==" }, "case-sensitive-paths-webpack-plugin": { "version": "2.4.0", @@ -21877,9 +21879,9 @@ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" }, "cssdb": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.1.0.tgz", - "integrity": "sha512-Sd99PrFgx28ez4GHu8yoQIufc/70h9oYowDf4EjeIKi8mac9whxRjhM3IaMr6EllP6KKKWtJrMfN6C7T9tIWvQ==" + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.2.0.tgz", + "integrity": "sha512-JYlIsE7eKHSi0UNuCyo96YuIDFqvhGgHw4Ck6lsN+DP0Tp8M64UTDT2trGbkMDqnCoEjks7CkS0XcjU0rkvBdg==" }, "cssesc": { "version": "3.0.0", @@ -22016,9 +22018,9 @@ } }, "decimal.js": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.2.tgz", - "integrity": "sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==" + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" }, "dedent": { "version": "0.7.0", @@ -22452,9 +22454,9 @@ } }, "eslint": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz", - "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", + "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", "requires": { "@eslint/eslintrc": "^1.3.3", "@humanwhocodes/config-array": "^0.11.6", @@ -23124,9 +23126,9 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "requires": { "reusify": "^1.0.4" } @@ -23189,9 +23191,9 @@ } }, "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", + "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", "requires": { "brace-expansion": "^2.0.1" } @@ -23861,9 +23863,9 @@ } }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", + "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==" }, "ignore-by-default": { "version": "1.0.1", @@ -25362,9 +25364,9 @@ } }, "@types/yargs": { - "version": "17.0.14", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.14.tgz", - "integrity": "sha512-9Pj7abXoW1RSTcZaL2Hk6G2XyLMlp5ECdVC/Zf2p/KBjC3srijLGgRAXOBjtFrJoIrvxdTKyKDA14bEcbxBaWw==", + "version": "17.0.16", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.16.tgz", + "integrity": "sha512-Mh3OP0oh8X7O7F9m5AplC+XHYLBWuPKNkGVD3gIZFLFebBnuFI2Nz5Sf8WLvwGxECJ8YjifQvFdh79ubODkdug==", "requires": { "@types/yargs-parser": "*" } @@ -25782,11 +25784,11 @@ "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" }, "language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.6.tgz", + "integrity": "sha512-HNkaCgM8wZgE/BZACeotAAgpL9FUjEnhgF0FVQMIgH//zqTPreLYMb3rWYkYAqPoF75Jwuycp1da7uz66cfFQg==", "requires": { - "language-subtag-registry": "~0.3.2" + "language-subtag-registry": "^0.3.20" } }, "leven": { @@ -26026,9 +26028,9 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, "mini-css-extract-plugin": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz", - "integrity": "sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.2.tgz", + "integrity": "sha512-EdlUizq13o0Pd+uCp+WO/JpkLvHRVGt97RqfeGhXqAcorYo1ypJSpkV+WDT0vY/kmh/p7wRdJNJtuyK540PXDw==", "requires": { "schema-utils": "^4.0.0" }, @@ -26766,9 +26768,9 @@ } }, "postcss-custom-properties": { - "version": "12.1.10", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.10.tgz", - "integrity": "sha512-U3BHdgrYhCrwTVcByFHs9EOBoqcKq4Lf3kXwbTi4hhq0qWhl/pDWq2THbv/ICX/Fl9KqeHBb8OVrTf2OaYF07A==", + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", + "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", "requires": { "postcss-value-parser": "^4.2.0" } @@ -28910,9 +28912,9 @@ } }, "terser": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.0.tgz", - "integrity": "sha512-KjTV81QKStSfwbNiwlBXfcgMcOloyuRdb62/iLFPGBcVNF4EXjhdYBhYHmbJpiBrVxZhDvltE11j+LBQUxEEJg==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", "requires": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", diff --git a/interface/src/framework/network/NetworkSettingsForm.tsx b/interface/src/framework/network/NetworkSettingsForm.tsx index d4a856146..41fa5895b 100644 --- a/interface/src/framework/network/NetworkSettingsForm.tsx +++ b/interface/src/framework/network/NetworkSettingsForm.tsx @@ -62,7 +62,9 @@ const WiFiSettingsForm: FC = () => { bandwidth20: false, tx_power: 20, nosleep: false, - enableMDNS: true + enableMDNS: true, + enableCORS: false, + CORSOrigin: '*' }); } setInitialized(true); @@ -162,11 +164,6 @@ const WiFiSettingsForm: FC = () => { label={LL.NETWORK_LOW_BAND()} /> - } - label={LL.NETWORK_USE_DNS()} - /> - {LL.GENERAL_OPTIONS()} @@ -182,6 +179,28 @@ const WiFiSettingsForm: FC = () => { margin="normal" /> + } + label={LL.NETWORK_USE_DNS()} + /> + + } + label={LL.NETWORK_ENABLE_CORS()} + /> + {data.enableCORS && ( + + )} + } label={LL.NETWORK_ENABLE_IPV6()} diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index dde8b25f4..5b55d8cb7 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -3,6 +3,7 @@ import type { Translation } from '../i18n-types'; /* eslint-disable */ const de: Translation = { +// ...en as Translation, LANGUAGE: 'Sprache', RETRY: 'Neuer Versuch', LOADING: 'Laden', @@ -190,8 +191,8 @@ const de: Translation = { SYSTEM_FACTORY_TEXT_DIALOG: 'Sind Sie sicher alle Einstellungen auf Werkseinstellung zu setzen?', VERSION_CHECK: 'Versionsprüfung', THE_LATEST: 'Die neueste', - OFFICIAL: 'official', - DEVELOPMENT: 'development', + OFFICIAL: 'offizielle', + DEVELOPMENT: 'Entwicklungs', VERSION_IS: 'Version ist', RELEASE_NOTES: 'Versionshinweise', EMS_ESP_VER: 'EMS-ESP Version', @@ -284,6 +285,8 @@ const de: Translation = { NETWORK_DISABLE_SLEEP: 'Deaktiviere WiFi Schlafmodus', NETWORK_LOW_BAND: 'Verwende niedrige WiFi Bandbreite', NETWORK_USE_DNS: 'Aktiviere mDNS Service', + NETWORK_ENABLE_CORS: 'Aktiviere CORS', + NETWORK_CORS_ORIGIN: 'CORS origin', NETWORK_ENABLE_IPV6: 'Aktiviere IPv6 Unterstützung', NETWORK_FIXED_IP: 'Feste IP Adresse', NETWORK_GATEWAY: 'Gateway', diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts index 173fb3fa1..e28a3bd4d 100644 --- a/interface/src/i18n/en/index.ts +++ b/interface/src/i18n/en/index.ts @@ -284,6 +284,8 @@ const en: Translation = { NETWORK_DISABLE_SLEEP: 'Disable WiFi Sleep Mode', NETWORK_LOW_BAND: 'Use Lower WiFi Bandwidth', NETWORK_USE_DNS: 'Enable mDNS Service', + NETWORK_ENABLE_CORS: 'Enable CORS', + NETWORK_CORS_ORIGIN: 'CORS origin', NETWORK_ENABLE_IPV6: 'Enable IPv6 support', NETWORK_FIXED_IP: 'Use Fixed IP address', NETWORK_GATEWAY: 'Gateway', diff --git a/interface/src/i18n/nl/index.ts b/interface/src/i18n/nl/index.ts index f34024f45..08553526f 100644 --- a/interface/src/i18n/nl/index.ts +++ b/interface/src/i18n/nl/index.ts @@ -284,6 +284,8 @@ const nl: Translation = { NETWORK_DISABLE_SLEEP: 'WiFi Sleep Mode uitzetten', NETWORK_LOW_BAND: 'Lagere WiFi bandbreedte gebruiken', NETWORK_USE_DNS: 'Activeer mDNS Service', + NETWORK_ENABLE_CORS: 'Activeer CORS', + NETWORK_CORS_ORIGIN: 'CORS origin', NETWORK_ENABLE_IPV6: 'Activeer IPv6 support', NETWORK_FIXED_IP: 'Gebruik vast IP addres', NETWORK_GATEWAY: 'Gateway', diff --git a/interface/src/i18n/no/index.ts b/interface/src/i18n/no/index.ts index 6a18f9700..d3474b5e6 100644 --- a/interface/src/i18n/no/index.ts +++ b/interface/src/i18n/no/index.ts @@ -284,6 +284,8 @@ const no: Translation = { NETWORK_DISABLE_SLEEP: 'Hindre at trådløst nettverk går i Sleep Mode', NETWORK_LOW_BAND: 'Benytt smalere båndbredde på trådløst nettverk', NETWORK_USE_DNS: 'Aktiviser mDNS Service', + NETWORK_ENABLE_CORS: 'Aktiviser CORS', + NETWORK_CORS_ORIGIN: 'CORS origin', NETWORK_ENABLE_IPV6: 'Aktiviser IPv6 støtte', NETWORK_FIXED_IP: 'Benytt statisk IP adresse', NETWORK_GATEWAY: 'Gateway', diff --git a/interface/src/i18n/pl/index.ts b/interface/src/i18n/pl/index.ts index d60523e35..dd4714de7 100644 --- a/interface/src/i18n/pl/index.ts +++ b/interface/src/i18n/pl/index.ts @@ -284,6 +284,8 @@ const pl: BaseTranslation = { NETWORK_DISABLE_SLEEP: 'Wyłącz tryb usypiania WiFi', NETWORK_LOW_BAND: 'Używaj zmniejszonej przepustowości WiFi', NETWORK_USE_DNS: 'Włącz wsparcie dla mDNS', + NETWORK_ENABLE_CORS: 'Włącz wsparcie dla CORS', + NETWORK_CORS_ORIGIN: 'CORS origin', NETWORK_ENABLE_IPV6: 'Włącz wsparcie dla IPv6', NETWORK_FIXED_IP: 'Użyj stałego adresu IP', NETWORK_GATEWAY: 'Brama', diff --git a/interface/src/i18n/se/index.ts b/interface/src/i18n/se/index.ts index 6ae2f4d13..e302363dc 100644 --- a/interface/src/i18n/se/index.ts +++ b/interface/src/i18n/se/index.ts @@ -284,6 +284,8 @@ const se: Translation = { NETWORK_DISABLE_SLEEP: 'Inaktivera sömnläge', NETWORK_LOW_BAND: 'Använd lägre bandbredd', NETWORK_USE_DNS: 'Aktivera mDNS-tjänsten', + NETWORK_ENABLE_CORS: 'Aktivera CORS', + NETWORK_CORS_ORIGIN: 'CORS origin', NETWORK_ENABLE_IPV6: 'Aktivera IPv6-support', NETWORK_FIXED_IP: 'Använd statiskt IP', NETWORK_GATEWAY: 'Gateway', diff --git a/interface/src/types/network.ts b/interface/src/types/network.ts index fb6b576ba..a0de253f0 100644 --- a/interface/src/types/network.ts +++ b/interface/src/types/network.ts @@ -48,6 +48,8 @@ export interface NetworkSettings { dns_ip_1?: string; dns_ip_2?: string; enableMDNS: boolean; + enableCORS: boolean; + CORSOrigin: string; } export interface WiFiNetworkList { diff --git a/lib/framework/ESP8266React.cpp b/lib/framework/ESP8266React.cpp index e83b284cf..e238ba54e 100644 --- a/lib/framework/ESP8266React.cpp +++ b/lib/framework/ESP8266React.cpp @@ -46,6 +46,13 @@ ESP8266React::ESP8266React(AsyncWebServer * server, FS * fs) void ESP8266React::begin() { _networkSettingsService.begin(); + _networkSettingsService.read([&](NetworkSettings & networkSettings) { + if (networkSettings.enableCORS) { + DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", networkSettings.CORSOrigin); + DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization"); + DefaultHeaders::Instance().addHeader("Access-Control-Allow-Credentials", "true"); + } + }); _apSettingsService.begin(); _ntpSettingsService.begin(); _otaSettingsService.begin(); diff --git a/lib/framework/NetworkSettingsService.h b/lib/framework/NetworkSettingsService.h index fe8ddd699..edaae7fa7 100644 --- a/lib/framework/NetworkSettingsService.h +++ b/lib/framework/NetworkSettingsService.h @@ -39,6 +39,8 @@ class NetworkSettings { int8_t tx_power; bool nosleep; bool enableMDNS; + bool enableCORS; + String CORSOrigin; // optional configuration for static IP address IPAddress localIP; @@ -58,6 +60,8 @@ class NetworkSettings { root["tx_power"] = settings.tx_power; root["nosleep"] = settings.nosleep; root["enableMDNS"] = settings.enableMDNS; + root["enableCORS"] = settings.enableCORS; + root["CORSOrigin"] = settings.CORSOrigin; // extended settings JsonUtils::writeIP(root, "local_ip", settings.localIP); @@ -77,6 +81,8 @@ class NetworkSettings { settings.tx_power = root["tx_power"] | 20; settings.nosleep = root["nosleep"] | false; settings.enableMDNS = root["enableMDNS"] | true; + settings.enableCORS = root["enableCORS"] | false; + settings.CORSOrigin = root["CORSOrigin"] | "*"; // extended settings JsonUtils::readIP(root, "local_ip", settings.localIP); diff --git a/lib_standalone/ESP8266React.h b/lib_standalone/ESP8266React.h index 25973a224..f0e8b3817 100644 --- a/lib_standalone/ESP8266React.h +++ b/lib_standalone/ESP8266React.h @@ -103,6 +103,8 @@ class DummySettings { String dnsIP2 = ""; bool enableIPv6 = false; bool enableMDNS = true; + bool enableCORS = false; + String CORSOrigin = "*"; uint8_t phy_type = 0; uint8_t eth_power = 0; // 0 means -1 diff --git a/mock-api/server.js b/mock-api/server.js index ecf2f7927..f73d04026 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -122,7 +122,11 @@ network_settings = { hostname: 'ems-esp', nosleep: true, tx_power: 20, + bandwidth20: false, static_ip_config: false, + enableMDNS: true, + enableCORS: false, + CORSOrigin: '*', } const network_status = { status: 3, diff --git a/src/system.cpp b/src/system.cpp index 1f9ccac9e..a66a5c8d1 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1104,6 +1104,11 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp node["enable IPv6"] = settings.enableIPv6; node["low bandwidth"] = settings.bandwidth20; node["disable sleep"] = settings.nosleep; + node["enable MDNS"] = settings.enableMDNS; + node["enable CORS"] = settings.enableCORS; + if (settings.enableCORS) { + node["CORS origin"] = settings.CORSOrigin; + } }); #ifndef EMSESP_STANDALONE EMSESP::esp8266React.getAPSettingsService()->read([&](APSettings & settings) { From a2730fb17c5318a56beb85816e348130c7c52df8 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Wed, 7 Dec 2022 19:13:43 +0100 Subject: [PATCH 43/52] extra debug message for payload only ifdef EMSESP_DEBUG Signed-off-by: MichaelDvP --- src/mqtt.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mqtt.cpp b/src/mqtt.cpp index a7c3a38d2..67367ed48 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -665,7 +665,7 @@ std::shared_ptr Mqtt::queue_message(const uint8_t operation, std::shared_ptr message; message = std::make_shared(operation, topic, payload, retain); -#ifdef EMSESP_DEBUG +#if defined(EMSESP_DEBUG) if (operation == Operation::PUBLISH) { if (message->payload.empty()) { LOG_INFO("[DEBUG] Adding to queue: (Publish) topic='%s' empty payload", message->topic.c_str()); @@ -860,8 +860,9 @@ void Mqtt::process_queue() { mqtt_message.retry_count_ + 1, message->payload.size(), packet_id); - LOG_DEBUG("Payload:%s", message->payload.c_str()); - +#if defined(EMSESP_DEBUG) + LOG_DEBUG("Payload:%s", message->payload.c_str()); // extra message for #784 +#endif if (packet_id == 0) { // it failed. if we retried n times, give up. remove from queue if (mqtt_message.retry_count_ == (MQTT_PUBLISH_MAX_RETRY - 1)) { From f71c62f167e82fde45ae8ba1520917cdad192f6c Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Thu, 8 Dec 2022 16:54:27 +0100 Subject: [PATCH 44/52] restart when changing CORS settings --- .../framework/network/NetworkSettingsForm.tsx | 31 +++++++++++++++++-- lib/framework/NetworkSettingsService.h | 5 +++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/interface/src/framework/network/NetworkSettingsForm.tsx b/interface/src/framework/network/NetworkSettingsForm.tsx index 41fa5895b..f1e528e94 100644 --- a/interface/src/framework/network/NetworkSettingsForm.tsx +++ b/interface/src/framework/network/NetworkSettingsForm.tsx @@ -1,4 +1,5 @@ import { FC, useContext, useEffect, useState } from 'react'; +import { useSnackbar } from 'notistack'; import { Avatar, @@ -18,6 +19,7 @@ import LockOpenIcon from '@mui/icons-material/LockOpen'; import DeleteIcon from '@mui/icons-material/Delete'; import SaveIcon from '@mui/icons-material/Save'; import LockIcon from '@mui/icons-material/Lock'; +import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew'; import { BlockFormControlLabel, @@ -25,11 +27,13 @@ import { FormLoader, SectionContent, ValidatedPasswordField, - ValidatedTextField + ValidatedTextField, + MessageBox } from '../../components'; import { NetworkSettings } from '../../types'; import * as NetworkApi from '../../api/network'; import { numberValue, updateValue, useRest } from '../../utils'; +import * as EMSESP from '../../project/api'; import { WiFiConnectionContext } from './WiFiConnectionContext'; import { isNetworkOpen, networkSecurityMode } from './WiFiNetworkSelector'; @@ -38,14 +42,17 @@ import { validate } from '../../validators'; import { createNetworkSettingsValidator } from '../../validators/network'; import { useI18nContext } from '../../i18n/i18n-react'; +import RestartMonitor from '../system/RestartMonitor'; const WiFiSettingsForm: FC = () => { const { LL } = useI18nContext(); + const { enqueueSnackbar } = useSnackbar(); const { selectedNetwork, deselectNetwork } = useContext(WiFiConnectionContext); const [initialized, setInitialized] = useState(false); - const { loadData, saving, data, setData, saveData, errorMessage } = useRest({ + const [restarting, setRestarting] = useState(false); + const { loadData, saving, data, setData, saveData, errorMessage, restartNeeded } = useRest({ read: NetworkApi.readNetworkSettings, update: NetworkApi.updateNetworkSettings }); @@ -92,6 +99,15 @@ const WiFiSettingsForm: FC = () => { } }; + const restart = async () => { + try { + await EMSESP.restart(); + setRestarting(true); + } catch (error) { + enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' }); + } + }; + return ( <> @@ -264,6 +280,14 @@ const WiFiSettingsForm: FC = () => { /> )} + {restartNeeded && ( + + + + )} + {!restartNeeded && ( + )} ); }; return ( - {content()} + {restarting ? : content()} ); }; diff --git a/lib/framework/NetworkSettingsService.h b/lib/framework/NetworkSettingsService.h index edaae7fa7..407282413 100644 --- a/lib/framework/NetworkSettingsService.h +++ b/lib/framework/NetworkSettingsService.h @@ -72,6 +72,8 @@ class NetworkSettings { } static StateUpdateResult update(JsonObject & root, NetworkSettings & settings) { + auto enableCORS = settings.enableCORS; + auto CORSOrigin = settings.CORSOrigin; settings.ssid = root["ssid"] | FACTORY_WIFI_SSID; settings.password = root["password"] | FACTORY_WIFI_PASSWORD; settings.hostname = root["hostname"] | FACTORY_WIFI_HOSTNAME; @@ -103,6 +105,9 @@ class NetworkSettings { if (settings.staticIPConfig && (IPUtils::isNotSet(settings.localIP) || IPUtils::isNotSet(settings.gatewayIP) || IPUtils::isNotSet(settings.subnetMask))) { settings.staticIPConfig = false; } + if (enableCORS != settings.enableCORS || CORSOrigin != settings.CORSOrigin) { + return StateUpdateResult::CHANGED_RESTART; // tell WebUI that a restart is needed + } return StateUpdateResult::CHANGED; } From 923494fdce18870bb00c8c16b7d378d151971629 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 10 Dec 2022 11:55:59 +0100 Subject: [PATCH 45/52] mention breaking change in HA entity names --- CHANGELOG_LATEST.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 64ecba199..92d278a2b 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -5,6 +5,7 @@ ## **IMPORTANT! BREAKING CHANGES** - When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade. +- Since 3.5.0b11 we have added support for multiple EMS-ESPs [#759] and also renamed the HA Entity IDs. For example what was previously `sensor.boiler_actual_boiler_temperature` is now using the shortname form `sensor.boiler_boiltemp` as opposed to the English description. Unfortunately this does means any HA dashboards, automation scripts and integrations (e.g. Grafana) need to be adjusted accordingly. ## Added From e67fde24f19f34c91f8ad3e78802df9da88729b1 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 10 Dec 2022 11:56:28 +0100 Subject: [PATCH 46/52] formatting --- interface/.typesafe-i18n.json | 8 +++---- .../src/framework/mqtt/MqttSettingsForm.tsx | 8 ++++++- .../framework/network/NetworkSettingsForm.tsx | 24 +++++++++---------- interface/src/project/DeviceIcon.tsx | 4 ++-- src/dallassensor.h | 2 +- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/interface/.typesafe-i18n.json b/interface/.typesafe-i18n.json index 38811b0eb..acc346bcc 100644 --- a/interface/.typesafe-i18n.json +++ b/interface/.typesafe-i18n.json @@ -1,5 +1,5 @@ { - "adapter": "react", - "baseLocale": "pl", - "$schema": "https://unpkg.com/typesafe-i18n@5.17.1/schema/typesafe-i18n.json" -} \ No newline at end of file + "adapter": "react", + "baseLocale": "pl", + "$schema": "https://unpkg.com/typesafe-i18n@5.17.1/schema/typesafe-i18n.json" +} diff --git a/interface/src/framework/mqtt/MqttSettingsForm.tsx b/interface/src/framework/mqtt/MqttSettingsForm.tsx index 013799b09..03f305508 100644 --- a/interface/src/framework/mqtt/MqttSettingsForm.tsx +++ b/interface/src/framework/mqtt/MqttSettingsForm.tsx @@ -223,7 +223,13 @@ const MqttSettingsForm: FC = () => { <> } + control={ + + } label={LL.MQTT_MULTIPLE_INSTANCES()} /> diff --git a/interface/src/framework/network/NetworkSettingsForm.tsx b/interface/src/framework/network/NetworkSettingsForm.tsx index f1e528e94..0fc9e4927 100644 --- a/interface/src/framework/network/NetworkSettingsForm.tsx +++ b/interface/src/framework/network/NetworkSettingsForm.tsx @@ -288,18 +288,18 @@ const WiFiSettingsForm: FC = () => { )} {!restartNeeded && ( - - - + + + )} ); diff --git a/interface/src/project/DeviceIcon.tsx b/interface/src/project/DeviceIcon.tsx index 347a1f1cd..ec8910487 100644 --- a/interface/src/project/DeviceIcon.tsx +++ b/interface/src/project/DeviceIcon.tsx @@ -37,9 +37,9 @@ const DeviceIcon: FC = ({ type }) => { case 'Gateway': return ; case 'Alert': - return ; + return ; case 'Pump': - return ; + return ; default: return null; } diff --git a/src/dallassensor.h b/src/dallassensor.h index 46d62a18b..78bc9e29d 100644 --- a/src/dallassensor.h +++ b/src/dallassensor.h @@ -57,7 +57,7 @@ class DallasSensor { std::string name() const; void set_name(const std::string & name) { - name_ = name; + name_ = name; } bool apply_customization(); From ccbc809ecf238233a0c4698ed694030f3a9ed4a8 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 10 Dec 2022 11:56:39 +0100 Subject: [PATCH 47/52] upgrade packages --- interface/package-lock.json | 78 ++++++++++++++++++------------------- interface/package.json | 6 +-- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/interface/package-lock.json b/interface/package-lock.json index 36f95d85d..59ff55056 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -15,7 +15,7 @@ "@mui/material": "^5.10.17", "@table-library/react-table-library": "4.0.23", "@types/lodash": "^4.14.191", - "@types/node": "^18.11.11", + "@types/node": "^18.11.12", "@types/react": "^18.0.26", "@types/react-dom": "^18.0.9", "@types/react-router-dom": "^5.3.3", @@ -31,11 +31,11 @@ "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-icons": "^4.7.1", - "react-router-dom": "^6.4.4", + "react-router-dom": "^6.4.5", "react-scripts": "5.0.1", "sockette": "^2.0.6", "typesafe-i18n": "^5.17.1", - "typescript": "^4.9.3" + "typescript": "^4.9.4" }, "devDependencies": { "nodemon": "^2.0.20", @@ -3458,9 +3458,9 @@ } }, "node_modules/@remix-run/router": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.4.tgz", - "integrity": "sha512-gTL8H5USTAKOyVA4xczzDJnC3HMssdFa3tRlwBicXynx9XfiXwneHnYQogwSKpdCkjXISrEKSTtX62rLpNEVQg==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.5.tgz", + "integrity": "sha512-my0Mycd+jruq/1lQuO5LBB6WTlL/e8DTCYWp44DfMTDcXz8DcTlgF0ISaLsGewt+ctHN+yA8xMq3q/N7uWJPug==", "engines": { "node": ">=14" } @@ -4017,9 +4017,9 @@ "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, "node_modules/@types/node": { - "version": "18.11.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz", - "integrity": "sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g==" + "version": "18.11.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.12.tgz", + "integrity": "sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -14561,11 +14561,11 @@ } }, "node_modules/react-router": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.4.tgz", - "integrity": "sha512-SA6tSrUCRfuLWeYsTJDuriRqfFIsrSvuH7SqAJHegx9ZgxadE119rU8oOX/rG5FYEthpdEaEljdjDlnBxvfr+Q==", + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.5.tgz", + "integrity": "sha512-1RQJ8bM70YEumHIlNUYc6mFfUDoWa5EgPDenK/fq0bxD8DYpQUi/S6Zoft+9DBrh2xmtg92N5HMAJgGWDhKJ5Q==", "dependencies": { - "@remix-run/router": "1.0.4" + "@remix-run/router": "1.0.5" }, "engines": { "node": ">=14" @@ -14575,12 +14575,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.4.tgz", - "integrity": "sha512-0Axverhw5d+4SBhLqLpzPhNkmv7gahUwlUVIOrRLGJ4/uwt30JVajVJXqv2Qr/LCwyvHhQc7YyK1Do8a9Jj7qA==", + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.5.tgz", + "integrity": "sha512-a7HsgikBR0wNfroBHcZUCd9+mLRqZS8R5U1Z1mzLWxFXEkUT3vR1XXmSIVoVpxVX8Bar0nQYYYc9Yipq8dWwAA==", "dependencies": { - "@remix-run/router": "1.0.4", - "react-router": "6.4.4" + "@remix-run/router": "1.0.5", + "react-router": "6.4.5" }, "engines": { "node": ">=14" @@ -16441,9 +16441,9 @@ } }, "node_modules/typescript": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", - "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -19818,9 +19818,9 @@ "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" }, "@remix-run/router": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.4.tgz", - "integrity": "sha512-gTL8H5USTAKOyVA4xczzDJnC3HMssdFa3tRlwBicXynx9XfiXwneHnYQogwSKpdCkjXISrEKSTtX62rLpNEVQg==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.5.tgz", + "integrity": "sha512-my0Mycd+jruq/1lQuO5LBB6WTlL/e8DTCYWp44DfMTDcXz8DcTlgF0ISaLsGewt+ctHN+yA8xMq3q/N7uWJPug==" }, "@rollup/plugin-babel": { "version": "5.3.1", @@ -20232,9 +20232,9 @@ "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, "@types/node": { - "version": "18.11.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz", - "integrity": "sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g==" + "version": "18.11.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.12.tgz", + "integrity": "sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg==" }, "@types/parse-json": { "version": "4.0.0", @@ -27723,20 +27723,20 @@ "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, "react-router": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.4.tgz", - "integrity": "sha512-SA6tSrUCRfuLWeYsTJDuriRqfFIsrSvuH7SqAJHegx9ZgxadE119rU8oOX/rG5FYEthpdEaEljdjDlnBxvfr+Q==", + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.5.tgz", + "integrity": "sha512-1RQJ8bM70YEumHIlNUYc6mFfUDoWa5EgPDenK/fq0bxD8DYpQUi/S6Zoft+9DBrh2xmtg92N5HMAJgGWDhKJ5Q==", "requires": { - "@remix-run/router": "1.0.4" + "@remix-run/router": "1.0.5" } }, "react-router-dom": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.4.tgz", - "integrity": "sha512-0Axverhw5d+4SBhLqLpzPhNkmv7gahUwlUVIOrRLGJ4/uwt30JVajVJXqv2Qr/LCwyvHhQc7YyK1Do8a9Jj7qA==", + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.5.tgz", + "integrity": "sha512-a7HsgikBR0wNfroBHcZUCd9+mLRqZS8R5U1Z1mzLWxFXEkUT3vR1XXmSIVoVpxVX8Bar0nQYYYc9Yipq8dWwAA==", "requires": { - "@remix-run/router": "1.0.4", - "react-router": "6.4.4" + "@remix-run/router": "1.0.5", + "react-router": "6.4.5" } }, "react-scripts": { @@ -29117,9 +29117,9 @@ "requires": {} }, "typescript": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", - "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==" + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" }, "unbox-primitive": { "version": "1.0.2", diff --git a/interface/package.json b/interface/package.json index 4dbd7f5e9..4238aba64 100644 --- a/interface/package.json +++ b/interface/package.json @@ -11,7 +11,7 @@ "@mui/material": "^5.10.17", "@table-library/react-table-library": "4.0.23", "@types/lodash": "^4.14.191", - "@types/node": "^18.11.11", + "@types/node": "^18.11.12", "@types/react": "^18.0.26", "@types/react-dom": "^18.0.9", "@types/react-router-dom": "^5.3.3", @@ -27,11 +27,11 @@ "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-icons": "^4.7.1", - "react-router-dom": "^6.4.4", + "react-router-dom": "^6.4.5", "react-scripts": "5.0.1", "sockette": "^2.0.6", "typesafe-i18n": "^5.17.1", - "typescript": "^4.9.3" + "typescript": "^4.9.4" }, "scripts": { "start": "react-app-rewired start", From 5f5e786c0e1fd48e65fb6f495e0fb2063976fa20 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 10 Dec 2022 11:57:17 +0100 Subject: [PATCH 48/52] added comments --- src/analogsensor.cpp | 2 +- src/dallassensor.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 0059c29a1..ffb02bb7c 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -440,7 +440,7 @@ void AnalogSensor::publish_values(const bool force) { StaticJsonDocument config; char stat_t[50]; - snprintf(stat_t, sizeof(stat_t), "%s/analogsensor_data", Mqtt::base().c_str()); + snprintf(stat_t, sizeof(stat_t), "%s/analogsensor_data", Mqtt::base().c_str()); // use base path config["stat_t"] = stat_t; char str[50]; diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index 15b55ddad..d58f22d7c 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -505,7 +505,7 @@ void DallasSensor::publish_values(const bool force) { config["dev_cla"] = "temperature"; char stat_t[50]; - snprintf(stat_t, sizeof(stat_t), "%s/dallassensor_data", Mqtt::base().c_str()); + snprintf(stat_t, sizeof(stat_t), "%s/dallassensor_data", Mqtt::base().c_str()); // use base path config["stat_t"] = stat_t; config["unit_of_meas"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES); From e96b5af0c8550f3ffd1c605d2ed35701a8a51d1b Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 10 Dec 2022 11:58:00 +0100 Subject: [PATCH 49/52] HA ems_esp status to system_status to be uniform with the other naming conventions --- src/mqtt.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 67367ed48..c29c1099d 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -443,6 +443,7 @@ void Mqtt::load_settings() { }); // create basename from base + // by taking the MQTT base path and replacing all / with underscores mqtt_basename_ = mqtt_base_; std::replace(mqtt_basename_.begin(), mqtt_basename_.end(), '/', '_'); } @@ -608,19 +609,25 @@ void Mqtt::ha_status() { StaticJsonDocument doc; char uniq[70]; - snprintf(uniq, sizeof(uniq), "%s_status", mqtt_basename_.c_str()); // always use basename + if (Mqtt::multiple_instances()) { + snprintf(uniq, sizeof(uniq), "%s_system_status", mqtt_basename_.c_str()); + } else { + strcpy(uniq, "system_status"); + } + doc["uniq_id"] = uniq; doc["object_id"] = uniq; - doc["~"] = mqtt_base_; - // doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes - // doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes - doc["stat_t"] = "~/status"; + + doc["stat_t"] = mqtt_base_ + "/status"; doc["name"] = "EMS-ESP status"; doc["payload_on"] = "online"; doc["payload_off"] = "offline"; doc["state_class"] = "measurement"; doc["device_class"] = "connectivity"; + // doc["avty_t"] = "~/status"; // commented out, as it causes errors in HA sometimes + // doc["json_attr_t"] = "~/heartbeat"; // store also as HA attributes + JsonObject dev = doc.createNestedObject("dev"); dev["name"] = "EMS-ESP"; dev["sw"] = "v" + std::string(EMSESP_APP_VERSION); @@ -630,7 +637,7 @@ void Mqtt::ha_status() { ids.add("ems-esp"); char topic[MQTT_TOPIC_MAX_SIZE]; - snprintf(topic, sizeof(topic), "binary_sensor/%s/status/config", mqtt_basename_.c_str()); + snprintf(topic, sizeof(topic), "binary_sensor/%s/system_status/config", mqtt_basename_.c_str()); Mqtt::publish_ha(topic, doc.as()); // publish the config payload with retain flag // create the sensors - must match the MQTT payload keys @@ -982,7 +989,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev // build unique identifier which will be used in the topic, also used as object_id char uniq_id[70]; - if (multiple_instances_) { + if (Mqtt::multiple_instances()) { // prefix base name to each uniq_id snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag); } else { From bba70ce852b310d3f00fc08b700f41e76d6bd01b Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 10 Dec 2022 11:58:32 +0100 Subject: [PATCH 50/52] replace HA ~ with hardcoded base name --- src/shower.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/shower.cpp b/src/shower.cpp index 01fa187cb..fa43a6f05 100644 --- a/src/shower.cpp +++ b/src/shower.cpp @@ -151,13 +151,17 @@ void Shower::set_shower_state(bool state, bool force) { ha_configdone_ = true; StaticJsonDocument doc; + doc["name"] = "Shower Active"; + char str[70]; snprintf(str, sizeof(str), "%s_shower_active", Mqtt::basename().c_str()); doc["uniq_id"] = str; doc["object_id"] = str; - doc["~"] = Mqtt::base(); - doc["stat_t"] = "~/shower_active"; + + char stat_t[50]; + snprintf(stat_t, sizeof(stat_t), "%s/shower_active", Mqtt::base().c_str()); // use base path + doc["stat_t"] = stat_t; // always render boolean as strings for HA char result[12]; @@ -169,7 +173,7 @@ void Shower::set_shower_state(bool state, bool force) { ids.add("ems-esp"); char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; - snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::base().c_str()); + snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::basename().c_str()); Mqtt::publish_ha(topic, doc.as()); // publish the config payload with retain flag } } From 7e888f6408fd8537ad52cb09e07142edca963123 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sat, 10 Dec 2022 16:09:47 +0100 Subject: [PATCH 51/52] Avoid blank page (NULL) as response --- src/web/WebAPIService.cpp | 11 +++++++++-- src/web/WebCustomizationService.cpp | 7 +++++++ src/web/WebDataService.cpp | 8 ++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index 0b4de5c36..a50b7148a 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -101,8 +101,15 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) { } // output json buffer - auto * response = new PrettyAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE_DYN); - JsonObject output = response->getRoot(); + auto * response = new PrettyAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE_DYN); + if (!response->getSize()) { + response = new PrettyAsyncJsonResponse(false, 256); + response->setCode(507); + response->setLength(); + request->send(response); // Insufficient Storage + return; + } + 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 5a641e91a..d7b1d3c7e 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -201,6 +201,13 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) { void WebCustomizationService::device_entities(AsyncWebServerRequest * request, JsonVariant & json) { if (json.is()) { auto * response = new MsgpackAsyncJsonResponse(true, EMSESP_JSON_SIZE_XXXLARGE_DYN); + if (!response->getSize()) { + response = new MsgpackAsyncJsonResponse(true, 256); + response->setCode(507); + response->setLength(); + request->send(response); // Insufficient Storage + return; + } for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice->unique_id() == json["id"]) { #ifndef EMSESP_STANDALONE diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index bb886f790..c82855338 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -166,6 +166,14 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) { void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant & json) { if (json.is()) { auto * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXXLARGE_DYN); + if (!response->getSize()) { + // EMSESP::logger().err("Insufficient storage"); + response = new MsgpackAsyncJsonResponse(false, 256); + response->setCode(507); + response->setLength(); + request->send(response); // Insufficient Storage (507) + return; + } for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice->unique_id() == json["id"]) { // wait max 2.5 sec for updated data (post_send_delay is 2 sec) From 11fd833cdb0e6347c3dc3b098a5254c67aa9092f Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 11 Dec 2022 11:13:56 +0100 Subject: [PATCH 52/52] delete empty response --- src/web/WebAPIService.cpp | 5 +++-- src/web/WebCustomizationService.cpp | 5 +++-- src/web/WebDataService.cpp | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index a50b7148a..5fe1a40d2 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -103,10 +103,11 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) { // output json buffer auto * response = new PrettyAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE_DYN); if (!response->getSize()) { + delete response; response = new PrettyAsyncJsonResponse(false, 256); - response->setCode(507); + response->setCode(507); // Insufficient Storage response->setLength(); - request->send(response); // Insufficient Storage + request->send(response); return; } JsonObject output = response->getRoot(); diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index d7b1d3c7e..0dffaf843 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -202,10 +202,11 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J if (json.is()) { auto * response = new MsgpackAsyncJsonResponse(true, EMSESP_JSON_SIZE_XXXLARGE_DYN); if (!response->getSize()) { + delete response; response = new MsgpackAsyncJsonResponse(true, 256); - response->setCode(507); + response->setCode(507); // Insufficient Storage response->setLength(); - request->send(response); // Insufficient Storage + request->send(response); return; } for (const auto & emsdevice : EMSESP::emsdevices) { diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index c82855338..f708b8528 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -167,11 +167,11 @@ void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant & if (json.is()) { auto * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_XXXLARGE_DYN); if (!response->getSize()) { - // EMSESP::logger().err("Insufficient storage"); + delete response; response = new MsgpackAsyncJsonResponse(false, 256); - response->setCode(507); + response->setCode(507); // Insufficient Storage response->setLength(); - request->send(response); // Insufficient Storage (507) + request->send(response); return; } for (const auto & emsdevice : EMSESP::emsdevices) {