diff --git a/interface/package.json b/interface/package.json
index ee37cbb80..a9dd511a4 100644
--- a/interface/package.json
+++ b/interface/package.json
@@ -35,7 +35,7 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-icons": "^5.4.0",
- "react-router": "^7.1.3",
+ "react-router": "^7.1.5",
"react-toastify": "^11.0.3",
"typesafe-i18n": "^5.26.2",
"typescript": "^5.7.3"
@@ -47,7 +47,7 @@
"@preact/preset-vite": "^2.10.0",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/formidable": "^3",
- "@types/node": "^22.12.0",
+ "@types/node": "^22.13.0",
"@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"concurrently": "^9.1.2",
diff --git a/interface/src/app/main/Dashboard.tsx b/interface/src/app/main/Dashboard.tsx
index 2bee49195..450727310 100644
--- a/interface/src/app/main/Dashboard.tsx
+++ b/interface/src/app/main/Dashboard.tsx
@@ -62,7 +62,7 @@ const Dashboard = () => {
send: fetchDashboard,
error
} = useRequest(readDashboard, {
- initialData: { connected: false, nodes: [] }
+ initialData: { connected: true, nodes: [] }
}).onSuccess((event) => {
if (event.data.nodes.length !== parentNodes) {
setParentNodes(event.data.nodes.length); // count number of parents/devices
@@ -238,7 +238,7 @@ const Dashboard = () => {
)}
- {data.connected && !hasFavEntities && (
+ {data.connected && data.nodes.length > 0 && !hasFavEntities && (
{LL.NO_DATA_1()}
diff --git a/interface/src/app/main/Help.tsx b/interface/src/app/main/Help.tsx
index 0fa7fe4c5..d7a06a431 100644
--- a/interface/src/app/main/Help.tsx
+++ b/interface/src/app/main/Help.tsx
@@ -51,20 +51,6 @@ const Help = () => {
}
});
- // const { send: sendExportAllValues } = useRequest(
- // () => callAction({ action: 'export', param: 'allvalues' }),
- // {
- // immediate: false
- // }
- // )
- // .onSuccess((event) => {
- // saveFile(event.data, 'allvalues', '.txt');
- // toast.info(LL.DOWNLOAD_SUCCESSFUL());
- // })
- // .onError((error) => {
- // toast.error(error.message);
- // });
-
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
immediate: false
})
@@ -165,16 +151,6 @@ const Help = () => {
- {/* }
- variant="outlined"
- color="primary"
- onClick={() => sendExportAllValues()}
- >
- {LL.DOWNLOAD(1)} {LL.ALLVALUES()}
- */}
-
diff --git a/interface/src/app/settings/DownloadUpload.tsx b/interface/src/app/settings/DownloadUpload.tsx
index b32850e1d..10c457a30 100644
--- a/interface/src/app/settings/DownloadUpload.tsx
+++ b/interface/src/app/settings/DownloadUpload.tsx
@@ -108,6 +108,15 @@ const DownloadUpload = () => {
{LL.SCHEDULE(0)}
+ }
+ variant="outlined"
+ color="primary"
+ onClick={() => sendExportData('allvalues')}
+ >
+ {LL.ALLVALUES()}
+
{LL.UPLOAD()}
diff --git a/interface/src/components/loading/FormLoader.tsx b/interface/src/components/loading/FormLoader.tsx
index 75e2f5c9f..b44cbdcea 100644
--- a/interface/src/components/loading/FormLoader.tsx
+++ b/interface/src/components/loading/FormLoader.tsx
@@ -17,6 +17,7 @@ const FormLoader = ({ errorMessage, onRetry }: FormLoaderProps) => {
{onRetry && (
}
variant="contained"
color="error"
diff --git a/interface/yarn.lock b/interface/yarn.lock
index edaefdc52..6326375a8 100644
--- a/interface/yarn.lock
+++ b/interface/yarn.lock
@@ -1408,12 +1408,12 @@ __metadata:
languageName: node
linkType: hard
-"@types/node@npm:^22.12.0":
- version: 22.12.0
- resolution: "@types/node@npm:22.12.0"
+"@types/node@npm:^22.13.0":
+ version: 22.13.0
+ resolution: "@types/node@npm:22.13.0"
dependencies:
undici-types: "npm:~6.20.0"
- checksum: 10c0/be220706732d95db2ed1c441c1e64cab90bf9a47519ce6f4c79cc5a9ec9d5c517131a149a9ac30afac1a30103e67e3a00d453ba7c1b0141608a3a7ba6397c303
+ checksum: 10c0/9cf6358b2863ae7bf9588ca1cc3d87f6a6289c3880e95a046a188760666870e2c12502df8b0a473bec8aa8ffee85e025d60382a6104b10f197120793235b2c22
languageName: node
linkType: hard
@@ -1604,7 +1604,7 @@ __metadata:
"@table-library/react-table-library": "npm:4.1.7"
"@trivago/prettier-plugin-sort-imports": "npm:^5.2.2"
"@types/formidable": "npm:^3"
- "@types/node": "npm:^22.12.0"
+ "@types/node": "npm:^22.13.0"
"@types/react": "npm:^19.0.8"
"@types/react-dom": "npm:^19.0.3"
alova: "npm:3.2.8"
@@ -1620,7 +1620,7 @@ __metadata:
react: "npm:^19.0.0"
react-dom: "npm:^19.0.0"
react-icons: "npm:^5.4.0"
- react-router: "npm:^7.1.3"
+ react-router: "npm:^7.1.5"
react-toastify: "npm:^11.0.3"
rollup-plugin-visualizer: "npm:^5.14.0"
terser: "npm:^5.37.0"
@@ -5612,9 +5612,9 @@ __metadata:
languageName: node
linkType: hard
-"react-router@npm:^7.1.3":
- version: 7.1.3
- resolution: "react-router@npm:7.1.3"
+"react-router@npm:^7.1.5":
+ version: 7.1.5
+ resolution: "react-router@npm:7.1.5"
dependencies:
"@types/cookie": "npm:^0.6.0"
cookie: "npm:^1.0.1"
@@ -5626,7 +5626,7 @@ __metadata:
peerDependenciesMeta:
react-dom:
optional: true
- checksum: 10c0/f42f7b245533d1adaa00779a0287993a836d5b56039d97a6643a8b3a721ffb92ff47c97cfb36409fec8794ac3c8a884339f588cf21fcd7f6dccdfc834520c76f
+ checksum: 10c0/c0013102c7a02d26cd2353fa3749bd229fbcfedd291710540be1765d703861f96a34ef0114dd5ee8d9a728e87f3a5698387058f9539b39604f331505f507d912
languageName: node
linkType: hard
diff --git a/pio_local.ini_example b/pio_local.ini_example
index 975fe8725..420f2e2a5 100644
--- a/pio_local.ini_example
+++ b/pio_local.ini_example
@@ -50,6 +50,13 @@ custom_password = admin
; upload_protocol = custom
; custom_emsesp_ip = 10.10.10.93
+; example override for lib_deps and using locally built modules
+;lib_deps =
+; bblanchon/ArduinoJson @ 7.3.0
+; ESP32Async/AsyncTCP @ 3.3.2
+; ESP32Async/ESPAsyncWebServer @ 3.6.2
+; file://${PROJECT_DIR}/../modules/EMS-ESP-Modules
+
; ** debug settings **
; to be used with esp-prog/JTAG hardware device like https://docs.espressif.com/projects/esp-dev-kits/en/latest/other/esp-prog/user_guide.html
; pio run -e debug
diff --git a/src/core/emsesp.cpp b/src/core/emsesp.cpp
index c6c2f125c..a188bc74c 100644
--- a/src/core/emsesp.cpp
+++ b/src/core/emsesp.cpp
@@ -43,7 +43,7 @@ uint8_t EMSESP::publish_all_idx_ = 0;
uint8_t EMSESP::unique_id_count_ = 0;
bool EMSESP::trace_raw_ = false;
uint16_t EMSESP::wait_validate_ = 0;
-bool EMSESP::wait_km_ = true;
+bool EMSESP::wait_km_ = false;
uint32_t EMSESP::last_fetch_ = 0;
AsyncWebServer webServer(80);
diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp
index 1a0d52df0..1ec43395a 100644
--- a/src/web/WebStatusService.cpp
+++ b/src/web/WebStatusService.cpp
@@ -204,12 +204,14 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json)
Serial.println(COLOR_RESET);
#endif
- // send response
+ // check for error
if (!ok) {
- request->send(400);
+ emsesp::EMSESP::logger().err("Action '%s' failed", action.c_str());
+ request->send(400); // bad request
return;
}
+ // send response
response->setLength();
request->send(response);
}
@@ -256,7 +258,7 @@ bool WebStatusService::checkUpgrade(JsonObject root, std::string & versions) {
}
// action = allvalues
-// output all the devices and the values
+// output all the devices and their values, including custom entities, scheduler and sensors
void WebStatusService::allvalues(JsonObject output) {
JsonObject device_output;
auto value = F_(values);
diff --git a/test/test_api/api_test.http b/test/test_api/api_test.http
index 5243da61d..4c7d6d33f 100755
--- a/test/test_api/api_test.http
+++ b/test/test_api/api_test.http
@@ -4,7 +4,7 @@
# The response will be shown in the right panel
# @host = http://ems-esp.local
-@host = http://192.168.1.206
+@host = http://192.168.1.225
@host_dev = http://10.10.10.175
@host_standalone = http://localhost:3080
@host_standalone2 = http://localhost:3082
diff --git a/test/test_api/api_test.sh b/test/test_api/api_test.sh
index cc50fcdd2..de182851d 100755
--- a/test/test_api/api_test.sh
+++ b/test/test_api/api_test.sh
@@ -4,14 +4,16 @@
# Command line test for the API
#
-# EMS_ESP API
+emsesp_url="http://192.168.1.225"
-emsesp_url="http://192.168.1.206"
+# get the token from the Security page. This is the token for the admin user, unless changed it'll always be the same
emsesp_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiYWRtaW4iOnRydWV9.2bHpWya2C7Q12WjNUBD6_7N3RCD7CMl-EGhyQVzFdDg"
+# This example will get the system info, via a GET request
curl -X GET ${emsesp_url}/api/system/info
echo "\n"
+# This example will execute a read command on product ID 8 and type ID 1
curl -X POST \
-H "Authorization: Bearer ${emsesp_token}" \
-H "Content-Type: application/json" \
@@ -20,12 +22,22 @@ curl -X POST \
echo "\n"
-# HA API
+# This example will export all values to a json file, including custom entities, sensors and schedules
+curl -X POST \
+ -H "Authorization: Bearer ${emsesp_token}" \
+ -H "Content-Type: application/json" \
+ -d '{"action":"export", "param":"allvalues"}' \
+ ${emsesp_url}/rest/action
+
+echo "\n"
+
+# This example is how to call a service in Home Assistant via the API
+# Which can be added to an EMS-EPS schedule
ha_url="http://192.168.1.42:8123"
ha_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIwMzMyZjU1MjhlZmM0NGIyOTgyMjIxNThiODU1NDkyNSIsImlhdCI6MTcyMTMwNDg2NSwiZXhwIjoyMDM2NjY0ODY1fQ.Q-Y7E_i7clH3ff4Ma-OMmhZfbN7aMi_CahKwmoar"
-# curl -X POST \
-# ${ha_url}/api/services/script/test_notify \
-# -H "Authorization: Bearer ${ha_token}" \
-# -H "Content-Type: application/json"
+curl -X POST \
+ ${ha_url}/api/services/script/test_notify \
+ -H "Authorization: Bearer ${ha_token}" \
+ -H "Content-Type: application/json"