diff --git a/interface/package.json b/interface/package.json
index 2fd14b079..00152873d 100644
--- a/interface/package.json
+++ b/interface/package.json
@@ -41,17 +41,17 @@
"typescript": "^5.7.3"
},
"devDependencies": {
- "@babel/core": "^7.26.0",
- "@eslint/js": "^9.18.0",
+ "@babel/core": "^7.26.7",
+ "@eslint/js": "^9.19.0",
"@preact/compat": "^18.3.1",
"@preact/preset-vite": "^2.10.0",
"@trivago/prettier-plugin-sort-imports": "^5.2.1",
"@types/formidable": "^3",
- "@types/node": "^22.10.7",
- "@types/react": "^19.0.7",
+ "@types/node": "^22.10.10",
+ "@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"concurrently": "^9.1.2",
- "eslint": "^9.18.0",
+ "eslint": "^9.19.0",
"eslint-config-prettier": "^10.0.1",
"formidable": "^3.5.2",
"prettier": "^3.4.2",
diff --git a/interface/src/app/settings/ApplicationSettings.tsx b/interface/src/app/settings/ApplicationSettings.tsx
index 7ff37415c..7cda3cb2b 100644
--- a/interface/src/app/settings/ApplicationSettings.tsx
+++ b/interface/src/app/settings/ApplicationSettings.tsx
@@ -552,19 +552,19 @@ const ApplicationSettings = () => {
{data.led_gpio !== 0 && (
-
-
-
-
+
+
+
+
)}
diff --git a/interface/src/app/status/SystemMonitor.tsx b/interface/src/app/status/SystemMonitor.tsx
index 85dbd6c61..eb5faea23 100644
--- a/interface/src/app/status/SystemMonitor.tsx
+++ b/interface/src/app/status/SystemMonitor.tsx
@@ -56,7 +56,7 @@ const SystemMonitor = () => {
useInterval(() => {
void send();
- }, 1000); // check every second
+ }, 1000); // check every 1 second
const onCancel = async () => {
setErrorMessage(undefined);
@@ -78,7 +78,7 @@ const SystemMonitor = () => {
>
{data?.status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING
? LL.WAIT_FIRMWARE()
- : data?.status === SystemStatusCodes.SYSTEM_STATUS_RESTART_REQUESTED
+ : data?.status === SystemStatusCodes.SYSTEM_STATUS_PENDING_RESTART
? LL.APPLICATION_RESTARTING()
: data?.status === SystemStatusCodes.SYSTEM_STATUS_NORMAL
? LL.RESTARTING_PRE()
@@ -105,7 +105,7 @@ const SystemMonitor = () => {
{LL.PLEASE_WAIT()}…
- {data && data.status > SystemStatusCodes.SYSTEM_STATUS_UPLOADING && (
+ {data && data.status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING && (
void;
}
-const FormLoader = ({
- errorMessage,
- onRetry,
- message = 'Loading…'
-}: FormLoaderProps) => {
+const FormLoader = ({ errorMessage, onRetry }: FormLoaderProps) => {
const { LL } = useI18nContext();
if (errorMessage) {
@@ -38,9 +33,6 @@ const FormLoader = ({
-
- {message}
-
);
};
diff --git a/interface/src/components/loading/LoadingSpinner.tsx b/interface/src/components/loading/LoadingSpinner.tsx
index 46e07af4c..8b61b056c 100644
--- a/interface/src/components/loading/LoadingSpinner.tsx
+++ b/interface/src/components/loading/LoadingSpinner.tsx
@@ -1,15 +1,11 @@
-import { Box, CircularProgress, Typography } from '@mui/material';
+import { Box, CircularProgress } from '@mui/material';
import type { Theme } from '@mui/material';
-import { useI18nContext } from 'i18n/i18n-react';
-
interface LoadingSpinnerProps {
height?: number | string;
}
const LoadingSpinner = ({ height = '100%' }: LoadingSpinnerProps) => {
- const { LL } = useI18nContext();
-
return (
{
})}
size={100}
/>
-
- {LL.LOADING()}…
-
);
};
diff --git a/interface/yarn.lock b/interface/yarn.lock
index 8ad89b4a6..bbd835c2e 100644
--- a/interface/yarn.lock
+++ b/interface/yarn.lock
@@ -51,7 +51,7 @@ __metadata:
languageName: node
linkType: hard
-"@babel/core@npm:^7.22.1, @babel/core@npm:^7.26.0":
+"@babel/core@npm:^7.22.1":
version: 7.26.0
resolution: "@babel/core@npm:7.26.0"
dependencies:
@@ -74,6 +74,29 @@ __metadata:
languageName: node
linkType: hard
+"@babel/core@npm:^7.26.7":
+ version: 7.26.7
+ resolution: "@babel/core@npm:7.26.7"
+ dependencies:
+ "@ampproject/remapping": "npm:^2.2.0"
+ "@babel/code-frame": "npm:^7.26.2"
+ "@babel/generator": "npm:^7.26.5"
+ "@babel/helper-compilation-targets": "npm:^7.26.5"
+ "@babel/helper-module-transforms": "npm:^7.26.0"
+ "@babel/helpers": "npm:^7.26.7"
+ "@babel/parser": "npm:^7.26.7"
+ "@babel/template": "npm:^7.25.9"
+ "@babel/traverse": "npm:^7.26.7"
+ "@babel/types": "npm:^7.26.7"
+ convert-source-map: "npm:^2.0.0"
+ debug: "npm:^4.1.0"
+ gensync: "npm:^1.0.0-beta.2"
+ json5: "npm:^2.2.3"
+ semver: "npm:^6.3.1"
+ checksum: 10c0/fbd2cd9fc23280bdcaca556e558f715c0a42d940b9913c52582e8e3d24e391d269cb8a9cd6589172593983569021c379e28bba6b19ea2ee08674f6068c210a9d
+ languageName: node
+ linkType: hard
+
"@babel/generator@npm:^7.26.0, @babel/generator@npm:^7.26.2, @babel/generator@npm:^7.26.5":
version: 7.26.5
resolution: "@babel/generator@npm:7.26.5"
@@ -96,7 +119,7 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-compilation-targets@npm:^7.25.9":
+"@babel/helper-compilation-targets@npm:^7.25.9, @babel/helper-compilation-targets@npm:^7.26.5":
version: 7.26.5
resolution: "@babel/helper-compilation-targets@npm:7.26.5"
dependencies:
@@ -170,6 +193,16 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helpers@npm:^7.26.7":
+ version: 7.26.7
+ resolution: "@babel/helpers@npm:7.26.7"
+ dependencies:
+ "@babel/template": "npm:^7.25.9"
+ "@babel/types": "npm:^7.26.7"
+ checksum: 10c0/37fec398e53a2dbbf24bc2a025c4d571b2556cef18d8116d05d04b153f13ef659cdfbaab96c8eed875e629d39bdf9b3ea5d099ccf80544537de224e2d94f9b11
+ languageName: node
+ linkType: hard
+
"@babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.2, @babel/parser@npm:^7.26.5":
version: 7.26.5
resolution: "@babel/parser@npm:7.26.5"
@@ -181,6 +214,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/parser@npm:^7.26.7":
+ version: 7.26.7
+ resolution: "@babel/parser@npm:7.26.7"
+ dependencies:
+ "@babel/types": "npm:^7.26.7"
+ bin:
+ parser: ./bin/babel-parser.js
+ checksum: 10c0/dcb08a4f2878ece33caffefe43b71488d753324bae7ca58d64bca3bc4af34dcfa1b58abdf9972516d76af760fceb25bb9294ca33461d56b31c5059ccfe32001f
+ languageName: node
+ linkType: hard
+
"@babel/plugin-syntax-jsx@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/plugin-syntax-jsx@npm:7.25.9"
@@ -253,6 +297,21 @@ __metadata:
languageName: node
linkType: hard
+"@babel/traverse@npm:^7.26.7":
+ version: 7.26.7
+ resolution: "@babel/traverse@npm:7.26.7"
+ dependencies:
+ "@babel/code-frame": "npm:^7.26.2"
+ "@babel/generator": "npm:^7.26.5"
+ "@babel/parser": "npm:^7.26.7"
+ "@babel/template": "npm:^7.25.9"
+ "@babel/types": "npm:^7.26.7"
+ debug: "npm:^4.3.1"
+ globals: "npm:^11.1.0"
+ checksum: 10c0/b23a36ce40d2e4970741431c45d4f92e3f4c2895c0a421456516b2729bd9e17278846e01ee3d9039b0adf5fc5a071768061c17fcad040e74a5c3e39517449d5b
+ languageName: node
+ linkType: hard
+
"@babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.26.5":
version: 7.26.5
resolution: "@babel/types@npm:7.26.5"
@@ -263,6 +322,16 @@ __metadata:
languageName: node
linkType: hard
+"@babel/types@npm:^7.26.7":
+ version: 7.26.7
+ resolution: "@babel/types@npm:7.26.7"
+ dependencies:
+ "@babel/helper-string-parser": "npm:^7.25.9"
+ "@babel/helper-validator-identifier": "npm:^7.25.9"
+ checksum: 10c0/7810a2bca97b13c253f07a0863a628d33dbe76ee3c163367f24be93bfaf4c8c0a325f73208abaaa050a6b36059efc2950c2e4b71fb109c0f07fa62221d8473d4
+ languageName: node
+ linkType: hard
+
"@emotion/babel-plugin@npm:^11.13.5":
version: 11.13.5
resolution: "@emotion/babel-plugin@npm:11.13.5"
@@ -646,10 +715,10 @@ __metadata:
languageName: node
linkType: hard
-"@eslint/js@npm:9.18.0, @eslint/js@npm:^9.18.0":
- version: 9.18.0
- resolution: "@eslint/js@npm:9.18.0"
- checksum: 10c0/3938344c5ac7feef4b73fcb30f3c3e753570cea74c24904bb5d07e9c42fcd34fcbc40f545b081356a299e11f360c9c274b348c05fb0113fc3d492e5175eee140
+"@eslint/js@npm:9.19.0, @eslint/js@npm:^9.19.0":
+ version: 9.19.0
+ resolution: "@eslint/js@npm:9.19.0"
+ checksum: 10c0/45dc544c8803984f80a438b47a8e578fae4f6e15bc8478a703827aaf05e21380b42a43560374ce4dad0d5cb6349e17430fc9ce1686fed2efe5d1ff117939ff90
languageName: node
linkType: hard
@@ -1399,7 +1468,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/node@npm:*, @types/node@npm:^22.10.7":
+"@types/node@npm:*":
version: 22.10.7
resolution: "@types/node@npm:22.10.7"
dependencies:
@@ -1408,6 +1477,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/node@npm:^22.10.10":
+ version: 22.10.10
+ resolution: "@types/node@npm:22.10.10"
+ dependencies:
+ undici-types: "npm:~6.20.0"
+ checksum: 10c0/3425772d4513cd5dbdd87c00acda088113c03a97445f84f6a89744c60a66990b56c9d3a7213d09d57b6b944ae8ff45f985565e0c1846726112588e33a22dd12b
+ languageName: node
+ linkType: hard
+
"@types/parse-json@npm:^4.0.0":
version: 4.0.2
resolution: "@types/parse-json@npm:4.0.2"
@@ -1440,12 +1518,12 @@ __metadata:
languageName: node
linkType: hard
-"@types/react@npm:^19.0.7":
- version: 19.0.7
- resolution: "@types/react@npm:19.0.7"
+"@types/react@npm:^19.0.8":
+ version: 19.0.8
+ resolution: "@types/react@npm:19.0.8"
dependencies:
csstype: "npm:^3.0.2"
- checksum: 10c0/818e546fa03a2a65ac2652fc472891ac96684211e8967bc25e1da6a8a09e2301ad972b1b038d128f8b4cbbd7691f6f57fee274db568169e9b6b01556abbb5bee
+ checksum: 10c0/5fa7236356b1476de03519c66ef65d4fd904826956105619e2ad60cb0b55ae7b251dd5fff02234076225b5e15333d0d936bf9dbe1d461406f8a2ba01c197ddcd
languageName: node
linkType: hard
@@ -1584,10 +1662,10 @@ __metadata:
resolution: "EMS-ESP@workspace:."
dependencies:
"@alova/adapter-xhr": "npm:2.1.1"
- "@babel/core": "npm:^7.26.0"
+ "@babel/core": "npm:^7.26.7"
"@emotion/react": "npm:^11.14.0"
"@emotion/styled": "npm:^11.14.0"
- "@eslint/js": "npm:^9.18.0"
+ "@eslint/js": "npm:^9.19.0"
"@mui/icons-material": "npm:^6.4.1"
"@mui/material": "npm:^6.4.1"
"@preact/compat": "npm:^18.3.1"
@@ -1595,13 +1673,13 @@ __metadata:
"@table-library/react-table-library": "npm:4.1.7"
"@trivago/prettier-plugin-sort-imports": "npm:^5.2.1"
"@types/formidable": "npm:^3"
- "@types/node": "npm:^22.10.7"
- "@types/react": "npm:^19.0.7"
+ "@types/node": "npm:^22.10.10"
+ "@types/react": "npm:^19.0.8"
"@types/react-dom": "npm:^19.0.3"
alova: "npm:3.2.8"
async-validator: "npm:^4.2.5"
concurrently: "npm:^9.1.2"
- eslint: "npm:^9.18.0"
+ eslint: "npm:^9.19.0"
eslint-config-prettier: "npm:^10.0.1"
formidable: "npm:^3.5.2"
jwt-decode: "npm:^4.0.0"
@@ -3046,16 +3124,16 @@ __metadata:
languageName: node
linkType: hard
-"eslint@npm:^9.18.0":
- version: 9.18.0
- resolution: "eslint@npm:9.18.0"
+"eslint@npm:^9.19.0":
+ version: 9.19.0
+ resolution: "eslint@npm:9.19.0"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.2.0"
"@eslint-community/regexpp": "npm:^4.12.1"
"@eslint/config-array": "npm:^0.19.0"
"@eslint/core": "npm:^0.10.0"
"@eslint/eslintrc": "npm:^3.2.0"
- "@eslint/js": "npm:9.18.0"
+ "@eslint/js": "npm:9.19.0"
"@eslint/plugin-kit": "npm:^0.2.5"
"@humanfs/node": "npm:^0.16.6"
"@humanwhocodes/module-importer": "npm:^1.0.1"
@@ -3091,7 +3169,7 @@ __metadata:
optional: true
bin:
eslint: bin/eslint.js
- checksum: 10c0/7f592ad228b9bd627a24870fdc875bacdab7bf535d4b67316c4cb791e90d0125130a74769f3c407b0c4b7027b3082ef33864a63ee1024552a60a17db60493f15
+ checksum: 10c0/3b0dfaeff6a831de086884a3e2432f18468fe37c69f35e1a0a9a2833d9994a65b6dd2a524aaee28f361c849035ad9d15e3841029b67d261d0abd62c7de6d51f5
languageName: node
linkType: hard
diff --git a/lib_standalone/Arduino.cpp b/lib_standalone/Arduino.cpp
index 1f136fbd4..69cb01aef 100644
--- a/lib_standalone/Arduino.cpp
+++ b/lib_standalone/Arduino.cpp
@@ -146,5 +146,6 @@ double ledcSetup(uint8_t chan, double freq, uint8_t bit_num) {
};
void ledcAttachPin(uint8_t pin, uint8_t chan) {};
void ledcWrite(uint8_t chan, uint32_t duty) {};
+void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val) {};
#endif
\ No newline at end of file
diff --git a/lib_standalone/Arduino.h b/lib_standalone/Arduino.h
index 12a294793..adecdc7d0 100644
--- a/lib_standalone/Arduino.h
+++ b/lib_standalone/Arduino.h
@@ -71,6 +71,7 @@ void dacWrite(uint8_t pin, uint8_t value);
double ledcSetup(uint8_t chan, double freq, uint8_t bit_num);
void ledcAttachPin(uint8_t pin, uint8_t chan);
void ledcWrite(uint8_t chan, uint32_t duty);
+void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val);
#define PROGMEM
#define PGM_P const char *
diff --git a/platformio.ini b/platformio.ini
index e02248eb9..a58abd811 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -53,6 +53,7 @@ unbuild_flags =
framework = arduino
board_build.partitions = partitions/esp32_partition_16M.csv
board_upload.flash_size = 16MB
+board_build.app_partition_name = app0
platform = espressif32@6.9.0 ; Arduino Core 2.0.18 / IDF 4.4.8
; platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.11/platform-espressif32.zip ; Arduino Core 3.1.1 / IDF 5.3.2
;
@@ -87,6 +88,7 @@ platform = espressif32@6.9.0 ; Arduino Core 2.0.18 / IDF 4.4.8
framework = arduino
board_build.partitions = partitions/esp32_partition_32M.csv
board_upload.flash_size = 32MB
+board_build.app_partition_name = app0
platform = espressif32@6.9.0 ; Arduino Core 2.0.18 / IDF 4.4.8
; use Tasmota's library for 4MB Flash variants.
@@ -95,6 +97,7 @@ platform = espressif32@6.9.0 ; Arduino Core 2.0.18 / IDF 4.4.8
framework = arduino
board_build.partitions = partitions/esp32_partition_4M.csv
board_upload.flash_size = 4MB
+board_build.app_partition_name = app0
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.00/platform-espressif32.zip ; Arduino Core 2.0.18 with IPv6 support, based on IDF 4.4.8
; platform = https://github.com/tasmota/platform-espressif32/releases/download/2025.01.31/platform-espressif32.zip ; Arduino Core 3.1.1, based on IDF 5.3.2
@@ -104,6 +107,7 @@ platform = https://github.com/tasmota/platform-espressif32/releases/download/202
framework = arduino
board_build.partitions = partitions/esp32_partition_16M.csv
board_upload.flash_size = 16MB
+board_build.app_partition_name = app0
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.00/platform-espressif32.zip ; Arduino Core 2.0.18 with IPv6 support, based on IDF 4.4.8
; platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.12.30/platform-espressif32.zip ; Arduino Core 3.1.0.241206 based on IDF 5.3.2
@@ -122,8 +126,8 @@ build_type = release
board_build.filesystem = littlefs
lib_deps =
bblanchon/ArduinoJson @ 7.3.0
- mathieucarbou/AsyncTCP @ 3.3.2
- mathieucarbou/ESPAsyncWebServer @ 3.6.0
+ ESP32Async/AsyncTCP @ ^3.3.2
+ ESP32Async/ESPAsyncWebServer @ 3.6.2
https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.4
;
diff --git a/src/core/analogsensor.cpp b/src/core/analogsensor.cpp
index 54807e7cb..20c5bbbb5 100644
--- a/src/core/analogsensor.cpp
+++ b/src/core/analogsensor.cpp
@@ -668,6 +668,7 @@ bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int
return false; // not found
}
+// note we don't add the device and state classes here, as we do in the custom entity service
void AnalogSensor::get_value_json(JsonObject output, const Sensor & sensor) {
output["name"] = sensor.name();
output["fullname"] = sensor.name();
diff --git a/src/core/emsdevice.cpp b/src/core/emsdevice.cpp
index b208a1d20..203c51c4c 100644
--- a/src/core/emsdevice.cpp
+++ b/src/core/emsdevice.cpp
@@ -1670,10 +1670,8 @@ void EMSdevice::get_value_json(JsonObject json, DeviceValue & dv) {
}
}
- // add uom if it's not a " " (single space)
- if (dv.uom != DeviceValueUOM::NONE) {
- json["uom"] = uom_to_string(dv.uom);
- }
+ // add uom, state class and device class
+ Mqtt::add_ha_uom(json, dv.type, dv.uom, dv.short_name, false); // no icon
json["readable"] = !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE);
json["writeable"] = dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY);
diff --git a/src/core/emsesp.cpp b/src/core/emsesp.cpp
index c7c5e798a..216724341 100644
--- a/src/core/emsesp.cpp
+++ b/src/core/emsesp.cpp
@@ -1637,10 +1637,10 @@ void EMSESP::start() {
esp32React.begin();
#ifndef EMSESP_STANDALONE
- LOG_INFO("EMS-ESP version %s (%s partition)", EMSESP_APP_VERSION,
- esp_ota_get_running_partition()->label); // welcome message
+ LOG_INFO("EMS-ESP version %s", EMSESP_APP_VERSION);
+ LOG_DEBUG("Boot partition %s, Active partition %s", esp_ota_get_boot_partition()->label, esp_ota_get_running_partition()->label);
#else
- LOG_INFO("EMS-ESP version %s", EMSESP_APP_VERSION); // welcome message
+ LOG_INFO("EMS-ESP version %s", EMSESP_APP_VERSION);
#endif
LOG_DEBUG("System is running in Debug mode");
LOG_INFO("Last system reset reason Core0: %s, Core1: %s", system_.reset_reason(0).c_str(), system_.reset_reason(1).c_str());
diff --git a/src/core/mqtt.cpp b/src/core/mqtt.cpp
index 84f26a450..558a0f9d0 100644
--- a/src/core/mqtt.cpp
+++ b/src/core/mqtt.cpp
@@ -1117,15 +1117,16 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
return queue_ha(topic, doc.as());
}
-// Add the state class, device class and an optional icon based on the uom
-void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, const char * entity) {
- const char * dc_ha = "dev_cla"; // device class
- const char * sc_ha = "stat_cla"; // state class
-
- // set icon, except for booleans
- // using HA specific codes from https://github.com/home-assistant/core/blob/dev/homeassistant/const.py
+// Add the uom, state class, device class and an optional icon based on the uom
+void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, const char * entity, bool is_discovery) {
+ // for HA discovery we use different namings
+ const char * dc_ha = is_discovery ? "dev_cla" : "device_class"; // device class
+ const char * sc_ha = is_discovery ? "stat_cla" : "state_class"; // state class
+ const char * uom_ha = is_discovery ? "unit_of_meas" : "uom"; // unit of measure
+
+ // set uom, unless boolean
+ // using HA uom specific codes from https://github.com/home-assistant/core/blob/dev/homeassistant/const.py
if (type != DeviceValueType::BOOL) {
- const char * uom_ha = "unit_of_meas"; // unit of measure
if (uom == DeviceValueUOM::HOURS) {
doc[uom_ha] = "h";
} else if (uom == DeviceValueUOM::MINUTES) {
@@ -1133,7 +1134,7 @@ void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, con
} else if (uom == DeviceValueUOM::SECONDS) {
doc[uom_ha] = "s";
} else if (uom != DeviceValueUOM::NONE) {
- doc[uom_ha] = EMSdevice::uom_to_string(uom); // default
+ doc[uom_ha] = EMSdevice::uom_to_string(uom); // use default
} else if (discovery_type() != discoveryType::HOMEASSISTANT) {
// Domoticz use " " for a no-uom
doc[uom_ha] = " ";
@@ -1148,12 +1149,16 @@ void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, con
case DeviceValueUOM::K:
doc[sc_ha] = F_(measurement);
doc[dc_ha] = "temperature";
- doc["ic"] = F_(icondegrees); // icon
+ if (is_discovery)
+ doc["ic"] = F_(icondegrees); // icon // TODO check if still needed
+ // override uom if fahrenheit
+ doc[uom_ha] = EMSESP::system_.fahrenheit() ? DeviceValue::DeviceValueUOM_s[DeviceValueUOM::FAHRENHEIT] : DeviceValue::DeviceValueUOM_s[uom];
break;
case DeviceValueUOM::PERCENT:
doc[sc_ha] = F_(measurement);
doc[dc_ha] = "power_factor";
- doc["ic"] = F_(iconpercent); // icon
+ if (is_discovery)
+ doc["ic"] = F_(iconpercent); // icon // TODO check if still needed
break;
case DeviceValueUOM::SECONDS:
case DeviceValueUOM::MINUTES:
@@ -1166,11 +1171,13 @@ void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, con
doc[dc_ha] = "duration"; // https://github.com/emsesp/EMS-ESP32/issues/822
break;
case DeviceValueUOM::KB:
- doc["ic"] = F_(iconkb);
+ if (is_discovery)
+ doc["ic"] = F_(iconkb);
break;
case DeviceValueUOM::LMIN:
case DeviceValueUOM::LH:
- doc["ic"] = F_(iconlmin);
+ if (is_discovery)
+ doc["ic"] = F_(iconlmin);
doc[sc_ha] = F_(measurement);
break;
case DeviceValueUOM::WH:
@@ -1189,7 +1196,8 @@ void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, con
doc[dc_ha] = "energy";
break;
case DeviceValueUOM::UA:
- doc["ic"] = F_(iconua);
+ if (is_discovery)
+ doc["ic"] = F_(iconua);
doc[sc_ha] = F_(measurement);
break;
case DeviceValueUOM::BAR:
@@ -1214,7 +1222,8 @@ void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, con
if ((type != DeviceValueType::STRING)
&& (type == DeviceValueType::INT8 || type == DeviceValueType::UINT8 || type == DeviceValueType::INT16 || type == DeviceValueType::UINT16
|| type == DeviceValueType::UINT24 || type == DeviceValueType::UINT32)) {
- doc["ic"] = F_(iconnum); // set icon
+ if (is_discovery)
+ doc["ic"] = F_(iconnum); // set icon
// determine if its a measurement or total increasing
// most of the values are measurement. for example Tx Reads will increment but can be reset to 0 after a restart
// all the starts are increasing, and they are ULONGs
diff --git a/src/core/mqtt.h b/src/core/mqtt.h
index 61c096cd1..2a7fadf0f 100644
--- a/src/core/mqtt.h
+++ b/src/core/mqtt.h
@@ -232,7 +232,7 @@ class Mqtt {
static std::string tag_to_topic(uint8_t device_type, int8_t tag);
- static void add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, const char * entity = nullptr);
+ static void add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, const char * entity = nullptr, bool is_discovery = true);
static void add_ha_sections_to_doc(const char * name,
const char * state_t,
diff --git a/src/core/system.cpp b/src/core/system.cpp
index db717439e..603352e46 100644
--- a/src/core/system.cpp
+++ b/src/core/system.cpp
@@ -2076,7 +2076,7 @@ bool System::uploadFirmwareURL(const char * url) {
http.end();
saved_url.clear(); // prevent from downloading again
LOG_INFO("Firmware uploaded successfully. Restarting...");
- EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED);
+ EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_PENDING_RESTART);
#endif
return true; // OK
diff --git a/src/core/temperaturesensor.cpp b/src/core/temperaturesensor.cpp
index 0e67cf291..02769cdc8 100644
--- a/src/core/temperaturesensor.cpp
+++ b/src/core/temperaturesensor.cpp
@@ -379,6 +379,7 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons
return false; // not found
}
+// note we don't add the device and state classes here, as we do in the custom entity service
void TemperatureSensor::get_value_json(JsonObject output, const Sensor & sensor) {
output["id"] = sensor.id();
output["name"] = sensor.name();
@@ -395,7 +396,6 @@ void TemperatureSensor::get_value_json(JsonObject output, const Sensor & sensor)
output["visible"] = true;
}
-
// publish a single sensor to MQTT
void TemperatureSensor::publish_sensor(const Sensor & sensor) {
if (Mqtt::enabled() && Mqtt::publish_single()) {
diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp
index 0ac133207..1db89549b 100644
--- a/src/devices/boiler.cpp
+++ b/src/devices/boiler.cpp
@@ -112,7 +112,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatValve_, DeviceValueType::UINT8, FL_(heatValve), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_DHW1, &wwValve_, DeviceValueType::UINT8, FL_(wwValve), DeviceValueUOM::PERCENT);
- register_device_value(DeviceValueTAG::TAG_DHW1, &wwCurFlow_, DeviceValueType::UINT8, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwCurFlow), DeviceValueUOM::LMIN);
+ // register_device_value(DeviceValueTAG::TAG_DHW1, &wwCurFlow_, DeviceValueType::UINT8, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(wwCurFlow), DeviceValueUOM::LMIN);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&keepWarmTemp_,
DeviceValueType::UINT8,
diff --git a/src/test/test.h b/src/test/test.h
index 93dadbbe3..8e58e1b23 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -42,7 +42,7 @@ namespace emsesp {
// #define EMSESP_DEBUG_DEFAULT "render"
// #define EMSESP_DEBUG_DEFAULT "api"
// #define EMSESP_DEBUG_DEFAULT "api3"
-#define EMSESP_DEBUG_DEFAULT "api4"
+// #define EMSESP_DEBUG_DEFAULT "api4"
// #define EMSESP_DEBUG_DEFAULT "crash"
// #define EMSESP_DEBUG_DEFAULT "dv"
// #define EMSESP_DEBUG_DEFAULT "lastcode"
diff --git a/src/version.h b/src/version.h
index fb18d55c2..15ebda94d 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define EMSESP_APP_VERSION "3.7.2-dev.14"
+#define EMSESP_APP_VERSION "3.7.2-dev.15"
diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp
index 6ff441e39..985e21008 100644
--- a/src/web/WebCustomEntityService.cpp
+++ b/src/web/WebCustomEntityService.cpp
@@ -325,9 +325,8 @@ void WebCustomEntityService::get_value_json(JsonObject output, CustomEntityItem
output["fullname"] = entity.name;
output["storage"] = entity.ram ? "ram" : "ems";
output["type"] = entity.value_type == DeviceValueType::BOOL ? "boolean" : entity.value_type == DeviceValueType::STRING ? "string" : F_(number);
- if (entity.uom > 0) {
- output["uom"] = EMSdevice::uom_to_string(entity.uom);
- }
+ // add uom state class and device class
+ Mqtt::add_ha_uom(output, entity.value_type, entity.uom, nullptr, false);
output["readable"] = true;
output["writeable"] = entity.writeable;
output["visible"] = true;
diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp
index 7781bf0f4..ffd5cf0ab 100644
--- a/src/web/WebSettingsService.cpp
+++ b/src/web/WebSettingsService.cpp
@@ -139,7 +139,7 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
#if defined(ARDUINO_LOLIN_C3_MINI) && !defined(BOARD_C3_MINI_V1)
(int8_t)(root["led_type"] | 1)};
#else
- (int8_t)(root["led_type"] | 0)};
+ (int8_t)(root["led_type"] | 0)}; // 0 = LED, 1 = RGB-LED
#endif
}
// check valid pins in this board profile