819 Commits

Author SHA1 Message Date
proddy
1487f30c43 Merge remote-tracking branch 'origin/dev' for 3.6.5 2024-03-23 17:56:05 +01:00
proddy
793021573a update packages for 3.6.5 release 2024-03-23 17:28:38 +01:00
Proddy
2739712c5b Merge pull request #1661 from MichaelDvP/dev
add telnet command to reboot to previous version #1657
2024-03-16 08:41:23 +01:00
MichaelDvP
9945b8d09f changelog, 3.6.5-dev.18 2024-03-15 14:50:01 +01:00
MichaelDvP
ee3fafa066 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2024-03-15 14:49:33 +01:00
MichaelDvP
eec3b3be7a restart option partitionname, console-command set service 2024-03-15 14:42:47 +01:00
MichaelDvP
77ad209ce1 stop fetching empty messages after 5 min 2024-03-15 13:59:20 +01:00
MichaelDvP
8a0152ebe6 log running partition on startup 2024-03-15 13:57:52 +01:00
MichaelDvP
ce8d8699c3 add 16M partitions with factory and two ota 2024-03-15 13:57:03 +01:00
Proddy
2efb9d18c9 Merge pull request #1662 from proddy/dev
small regression fixes from the last messy build I created (sorry!)
2024-03-13 18:51:50 +01:00
proddy
9af782c485 fix web log 2024-03-13 18:49:38 +01:00
proddy
bc232fcff2 added some debug log messages 2024-03-13 17:50:33 +01:00
proddy
287232be5c fix bug where changing wifi ssid/password was not persisted from console 2024-03-13 17:39:39 +01:00
proddy
c1058ba06c package update 2024-03-13 17:37:35 +01:00
proddy
9fe6d1092a add back monitor filters for colors in VSC 2024-03-13 17:37:27 +01:00
proddy
ada55ffaba package cleanup 2024-03-13 17:37:07 +01:00
proddy
c70b1c3bbd don't need to start mDNS for IPv6 as its already running 2024-03-13 17:36:58 +01:00
MichaelDvP
a5708e11ba update packages 2024-03-13 16:21:41 +01:00
MichaelDvP
8dfc84eac2 add restart other command to change partition #1657 2024-03-13 16:03:28 +01:00
Proddy
e00c30cd4f Merge pull request #1658 from proddy/dev
fix broken web - #1656
2024-03-12 23:15:14 +01:00
Proddy
be6bb1de6a fixes #1656 2024-03-12 23:08:57 +01:00
Proddy
0bd57973c5 remove duplicate wifi log message for ipv6 2024-03-12 23:08:24 +01:00
Proddy
39cfa3ab79 uri doesnt need to be a string 2024-03-12 23:08:06 +01:00
Proddy
d36fe1c0bf update yarn 2024-03-12 23:07:55 +01:00
Proddy
27aa57da3c Merge pull request #1655 from proddy/dev
fix compiling local test
2024-03-10 21:36:55 +01:00
Proddy
b7bd2be0a5 fix compiling local test 2024-03-10 21:36:22 +01:00
Proddy
9ad80fc74d Merge pull request #1653 from MichaelDvP/dev
CW100/RC100 controlmode, fix emsesp#1650
2024-03-10 21:17:34 +01:00
Proddy
7fc7c24a20 Merge pull request #1654 from proddy/dev
cleanup and making asyncWS cleaner
2024-03-10 21:17:21 +01:00
Proddy
c1ae0e76c8 autoformatting 2024-03-10 21:15:52 +01:00
Proddy
f1f9bacf76 ignore vscode 2024-03-10 21:15:42 +01:00
Proddy
4e3eb3aeaa asyncwebserver optimizations 2024-03-10 21:15:34 +01:00
Proddy
18c5aaf598 ignore local vsc files 2024-03-10 21:14:20 +01:00
Proddy
cff60f4ed8 update API tests 2024-03-10 21:14:09 +01:00
MichaelDvP
9fe54825f8 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2024-03-09 16:09:17 +01:00
Proddy
c5f2dba1ef Merge pull request #1651 from proddy/dev
minor text changes
2024-03-09 14:52:16 +01:00
proddy
b94b3e7e2e added comment to show test add example 2024-03-09 14:51:03 +01:00
proddy
c75f7b6c7d simulate hc's 2024-03-09 14:50:52 +01:00
proddy
d25ead5208 update version in standalone 2024-03-09 14:50:37 +01:00
proddy
68f09f03f8 formatting console 2024-03-09 14:50:23 +01:00
MichaelDvP
fc1e009f09 CW100/RC100 controlmode, fix #1650 2024-03-09 14:38:07 +01:00
Proddy
a5ef1d16d5 Merge pull request #1649 from proddy/dev
package updates
2024-03-09 00:58:53 -08:00
Proddy
e80c2b0814 package updates 2024-03-09 09:58:12 +01:00
Proddy
5bdf7978bf Merge pull request #1646 from MichaelDvP/dev
enable IPv6 for tasmota-arduino
2024-03-02 10:53:45 +01:00
MichaelDvP
9fc109eec1 update changelog, 3.6.5-dev.16 2024-02-29 18:54:49 +01:00
MichaelDvP
854f764b3c add esp32_s3_32M profile, 16M partitions with larger data space, packages 2024-02-29 14:28:58 +01:00
MichaelDvP
463c68d08c enable IPv6 for tasmota, add env:ci_16M for E32V2 2024-02-29 10:12:42 +01:00
MichaelDvP
2ddd2401eb add limits to entities #1642 2024-02-28 12:41:21 +01:00
MichaelDvP
ff045b1a01 back to platform 2024.01.01, show dns ipv6 in right format 2024-02-28 12:40:27 +01:00
MichaelDvP
7c73e70986 more weather compensation entities #1642 2024-02-28 07:46:22 +01:00
MichaelDvP
8699bd4eb0 update packages 2024-02-28 07:45:17 +01:00
MichaelDvP
626c32763f add weather compensation, #1642 2024-02-27 17:48:54 +01:00
MichaelDvP
56c958a141 back to tasmota 2024.01.00, fix dns issue 2024-02-27 16:58:24 +01:00
Proddy
fd1d4b97a0 Merge pull request #1638 from MichaelDvP/dev
fix command attribute #1637
2024-02-27 08:25:16 +01:00
MichaelDvP
82579869a4 fix command attribute #1637 2024-02-27 07:53:22 +01:00
MichaelDvP
12690eeaf4 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2024-02-27 07:27:44 +01:00
MichaelDvP
768bdcaaaa add platform to system info 2024-02-24 14:38:08 +01:00
Proddy
1db4a33a1d Merge pull request #1631 from MichaelDvP/dev
small fixes
2024-02-24 13:28:50 +01:00
MichaelDvP
61d11ce440 update packages 2024-02-24 10:04:09 +01:00
MichaelDvP
08918a7349 AsyncTCP stack and queue settings 2024-02-24 10:03:58 +01:00
Proddy
fb09386c22 Merge pull request #1633 from proddy/dev
fix issue with HA, removing availability check for online status as it may not have been published in time
2024-02-23 19:43:17 +01:00
Proddy
d42ae52aff fix issue with HA, removing availability check for online status as it may not have been published in time 2024-02-23 19:42:15 +01:00
Proddy
271d1fda92 package update 2024-02-23 19:41:44 +01:00
MichaelDvP
392015f3af Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2024-02-23 08:48:27 +01:00
Proddy
c769fd6d2c Merge pull request #1626 from proddy/dev
Expose EMS-ESP commands (like reset) via MQTT Discovery #1605
2024-02-22 21:29:21 +01:00
Proddy
0f06bfa91c 3.6.5-dev15 2024-02-22 21:29:04 +01:00
Proddy
dffc4a7c02 package update 2024-02-22 21:27:43 +01:00
Proddy
34201025c3 update with #1628 2024-02-21 23:10:56 +01:00
Proddy
189ea6b23d Send MQTT heartbeat immediately after connection 2024-02-21 23:04:32 +01:00
Proddy
24f2d86059 update packages 2024-02-21 23:04:18 +01:00
Proddy
1a08ab6a2b remove RSSI from info payload as its in the heartbeat 2024-02-21 23:04:10 +01:00
MichaelDvP
5e5e6ff053 fixed ip for ETH, setting order 2024-02-21 16:02:04 +01:00
MichaelDvP
08204a94d8 fix typo #1622 2024-02-21 16:01:35 +01:00
MichaelDvP
0eb3df704e Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2024-02-21 15:59:56 +01:00
Proddy
2eb77b5f97 package update 2024-02-20 23:28:06 +01:00
Proddy
33b6ece55b Expose EMS-ESP commands (like reset) via MQTT Discovery #1605 2024-02-20 23:27:56 +01:00
Proddy
5d3f8e5b69 updates 2024-02-14 22:19:11 +01:00
Proddy
8ebc552cac Merge pull request #1615 from proddy/dev
fix WiFi TxPower, plus a ton of other refactoring
2024-02-14 15:08:04 +01:00
proddy
944d86b644 removed unused _retained's 2024-02-14 15:07:35 +01:00
proddy
8bd2a39d4e update for 3.6.5-dev14 2024-02-14 15:07:17 +01:00
proddy
ed9cad6e39 hostname is multiline 2024-02-14 15:07:02 +01:00
proddy
e31330e931 200 char limit for hostnames 2024-02-14 15:06:51 +01:00
proddy
49d749e89f move generateClientId() 2024-02-14 14:47:29 +01:00
proddy
d3fadd7081 remove comment 2024-02-14 14:47:17 +01:00
proddy
31ff0f5aba add override 2024-02-14 14:47:09 +01:00
proddy
b24a63b992 add missing overrides 2024-02-14 14:46:59 +01:00
proddy
f5ec9e9602 remove unneeded file 2024-02-14 14:46:20 +01:00
proddy
b6accb8d02 add extra {} to SubscribeItem list[1] 2024-02-14 14:46:10 +01:00
Proddy
a35486ec24 remove bogus flags 2024-02-14 11:09:08 +01:00
Proddy
fdaa9a6188 tidy up standalone 2024-02-14 11:00:16 +01:00
Proddy
daf08e7bd9 support standalone 2024-02-14 11:00:03 +01:00
Proddy
994e1fc26b remove bogus include 2024-02-14 10:54:16 +01:00
Proddy
34b7dd61cf clean up standalone 2024-02-14 10:53:53 +01:00
Proddy
ce3c3e0b3e tidy up lambda's 2024-02-13 20:19:58 +01:00
Proddy
92a80c3aaf factoryReset only used with button in test mode 2024-02-13 20:19:41 +01:00
Proddy
df21c15972 code cleaning 2024-02-13 20:19:21 +01:00
Proddy
b683d1dd21 default mqtt will base off ESP32's chip code 2024-02-13 20:19:03 +01:00
Proddy
a7d0259b30 replace lambda [&] with [this] 2024-02-13 15:19:06 +01:00
Proddy
16779064f4 update 2024-02-13 15:17:47 +01:00
Proddy
732ad4bc6a remove retainStr 2024-02-13 15:17:34 +01:00
Proddy
f40a6f20c6 change log text 2024-02-13 15:16:58 +01:00
proddy
4bf22dd6a5 refresh sync to 30ms for faster display in web 2024-02-13 10:57:37 +01:00
proddy
62ae5332de use consistent log message format 2024-02-13 10:57:11 +01:00
proddy
12e65279ef package update 2024-02-13 10:56:56 +01:00
proddy
295b90f49c NTP log text 2024-02-13 10:56:50 +01:00
Proddy
644907e58b fix error in event log 2024-02-12 14:51:10 +01:00
Proddy
a8a875f9d5 add missing tx_power 2024-02-12 14:40:08 +01:00
Proddy
6cd9dfc685 fixes for #1615 2024-02-12 14:25:21 +01:00
Proddy
80a3007f8b refactoring 2024-02-12 14:21:30 +01:00
Proddy
ed5f0bc6d5 start logging service sooner so weblog captures setup like network, mqtt etc 2024-02-12 11:22:56 +01:00
Proddy
df1109ea39 remove wifi_tweak 2024-02-12 11:22:21 +01:00
Proddy
1f7c968d0d remove OriginID from state service 2024-02-12 11:22:07 +01:00
Proddy
65cf8005a4 fixes for txPower 2024-02-11 23:01:32 +01:00
proddy
7c97aaf735 try out etags instead of immutable cache 2024-02-11 21:54:31 +01:00
proddy
23cfdd9b34 remove cmd 2024-02-11 21:54:08 +01:00
Proddy
b454e87405 Merge branch 'emsesp:dev' into dev 2024-02-11 14:23:24 +01:00
Proddy
3d715c45e0 Wifi Tx Power not adjusted #1614 2024-02-11 14:21:51 +01:00
proddy
fea63b0d52 #1614 - WiFi Tx Power 2024-02-11 10:32:33 +01:00
Proddy
57296e55f2 Merge pull request #1610 from proddy/dev
memory optimizations
2024-02-10 16:43:34 +01:00
Proddy
12f0120afd fix standalone compiling 2024-02-10 16:17:40 +01:00
Proddy
303e86a5eb remove unused comments 2024-02-10 15:43:59 +01:00
Proddy
52479c408f added comment for refactor reminder 2024-02-10 15:43:49 +01:00
Proddy
fc8eea91eb scope optimization 2024-02-10 15:43:35 +01:00
Proddy
fe5a6fb568 added missing data points 2024-02-10 15:43:19 +01:00
Proddy
55672cc9de don't show bus scanning, so orange warning doesn't render on refresh 2024-02-10 15:43:03 +01:00
Proddy
6d6291e659 remove feature as its not used, and speed up web loading slightly 2024-02-10 15:42:14 +01:00
proddy
257b40c2e4 fix MQTT discovery of custom entity doesn't consider type of data #1587 2024-02-10 09:51:29 +01:00
proddy
e6b61b7a51 bump 3.6.5-dev.13 2024-02-10 09:50:58 +01:00
proddy
f167be37a1 ArduinoJson 7.0.3 2024-02-10 09:50:32 +01:00
proddy
4ac2d1a9a7 remove extra v 2024-02-10 09:50:13 +01:00
proddy
8c602cd058 default -O2 2024-02-10 09:50:04 +01:00
proddy
b8f6664176 rename msgpack 2024-02-10 09:49:53 +01:00
proddy
1024dbb61f refactoring 2024-02-09 18:23:55 +01:00
Proddy
253adfeb45 memory optimizations 2024-02-05 09:38:11 +01:00
MichaelDvP
99d7ff0dc7 async tcp formatting 2024-02-05 08:42:38 +01:00
Proddy
738d9b1d94 Merge pull request #1608 from xobed/dev
Fix Slovenian -> Slovak
2024-02-04 18:20:49 +01:00
xobed
4319d648aa Fix Slovenian -> Slovak 2024-02-04 17:52:05 +01:00
Proddy
2595b906a5 Merge pull request #1606 from proddy/dev
small updates
2024-02-04 15:10:06 +01:00
Proddy
c98e1a629b add type to device info, so we know if its a Ram variable or not 2024-02-04 14:52:35 +01:00
Proddy
ae7f0445a3 added DEBUG around logger().debug to prevent 'undefined' showing in log 2024-02-04 14:52:12 +01:00
Proddy
8406657906 text change 2024-02-04 14:51:44 +01:00
Proddy
9135635af2 auto-formatting 2024-02-04 14:51:35 +01:00
Proddy
25098409df text update 2024-02-04 14:51:22 +01:00
Proddy
8176120bf9 text update 2024-02-04 14:51:10 +01:00
Proddy
5cfb7b4548 default C++17 and added CONFIG_ASYNC_TCP_STACK_SIZE 2024-02-04 14:51:03 +01:00
Proddy
3f17d74bc6 update packages 2024-02-04 14:50:43 +01:00
Proddy
1694a0b41d use default test general 2024-02-04 14:50:28 +01:00
Proddy
ec8a182aa3 bump version 2024-02-04 14:50:14 +01:00
Proddy
22b70ac378 replace list with vector (makes no diff) 2024-02-04 14:49:59 +01:00
Proddy
40a685aeb2 remove cache 2024-02-04 14:49:23 +01:00
Proddy
a580998f25 update libraries 2024-02-04 14:49:11 +01:00
Proddy
afc34fc387 Merge branch 'emsesp:dev' into dev 2024-02-04 10:24:39 +01:00
Proddy
45335be4ed Merge pull request #1603 from MichaelDvP/dev
add diff for #1597, fix #1599
2024-02-04 10:23:20 +01:00
MichaelDvP
24162b7350 update packages 2024-02-03 18:37:26 +01:00
MichaelDvP
3bb7e3514f add #1597 temp diff 2024-02-03 18:14:31 +01:00
MichaelDvP
58b75ee203 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2024-02-03 15:00:01 +01:00
MichaelDvP
d32178480d fix #1599 2024-02-03 14:59:14 +01:00
MichaelDvP
38e08be752 button should always be input 2024-02-03 14:58:49 +01:00
MichaelDvP
9573c4ed94 pretty_telegram 2nd fallback for name 2024-02-03 14:58:07 +01:00
Proddy
56e5e87238 Merge branch 'emsesp:dev' into dev 2024-01-30 20:54:58 +01:00
Proddy
a9a2380287 Merge pull request #1591 from MichaelDvP/dev
fix #1590 and more checks for device-telegram mapping
2024-01-30 19:57:08 +01:00
MichaelDvP
5bd9ec963f update translations 2024-01-30 08:09:18 +01:00
MichaelDvP
427e8cf11c update packages 2024-01-30 08:09:03 +01:00
MichaelDvP
de9c224a23 show sensor command commands 2024-01-30 08:05:50 +01:00
MichaelDvP
0f799d5922 fix broadcast sending 2024-01-30 07:15:11 +01:00
MichaelDvP
3a8bed6976 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2024-01-29 10:20:15 +01:00
proddy
aadf4b7a53 package update 2024-01-28 21:58:25 +01:00
Proddy
ed7ba17bc7 Merge pull request #1575 from proddy/dev
small changes, optimizations and fixes
2024-01-28 18:30:19 +01:00
Proddy
526c36728f Merge branch 'emsesp:dev' into dev 2024-01-28 18:29:52 +01:00
Proddy
c7a35ebc58 updated with changes to sensor commands 2024-01-28 18:29:22 +01:00
Proddy
5735ffd222 tidied up commands 2024-01-28 18:28:26 +01:00
Proddy
d11508282f tidied up commands info, values etc 2024-01-28 18:28:12 +01:00
Proddy
30e11ad593 added comment 2024-01-28 18:27:51 +01:00
proddy
040954bb70 tidy up commands for temperature sensor 2024-01-28 16:36:18 +01:00
proddy
eec0051997 hide IP addresses 2024-01-28 14:09:42 +01:00
proddy
fab74a9061 package update 2024-01-28 13:21:52 +01:00
proddy
8e9edcb673 fixes #1583 2024-01-28 13:21:45 +01:00
MichaelDvP
2bd66bf4b6 reset wait_validate, typo 2024-01-28 12:16:35 +01:00
MichaelDvP
9e423d9769 Merge branch 'dev' of https://github.com/MichaelDvP/EMS-ESP32 into dev 2024-01-28 11:37:41 +01:00
MichaelDvP
6155645436 process telegram selection of device 2024-01-28 11:31:17 +01:00
MichaelDvP
85a839e86b Merge branch 'emsesp:dev' into dev 2024-01-28 11:21:47 +01:00
MichaelDvP
0760e6e021 hpPressure telegram 2024-01-28 09:07:49 +01:00
MichaelDvP
fbd3ebbd4e fetch mixer 0x2CC 2024-01-28 09:07:28 +01:00
MichaelDvP
24b8e004ec fix jsonvariant in command 2024-01-28 09:07:05 +01:00
proddy
34cafe0d4d minor refactor moving scheduler item list loading once 2024-01-26 23:01:44 +01:00
proddy
e319f5e270 package update 2024-01-26 23:01:17 +01:00
Proddy
133decf453 Merge pull request #1579 from myxor/myxor-patch-2
Add Buderus MX300 Internet Gateway
2024-01-24 23:41:48 +01:00
Marco H
541615d405 Add Buderus MX300 Internet Gateway 2024-01-24 20:02:02 +01:00
MichaelDvP
21de630f8e check telegrams for dest==thermostat 2024-01-22 16:13:23 +01:00
Proddy
8a0e037c60 change default version for testing 2024-01-22 10:03:02 +01:00
Proddy
326e7bcc2a add TODO comments so reminding me what to do next 2024-01-21 21:51:52 +01:00
Proddy
cc8839ab31 add tests in a consistent way 2024-01-21 21:49:39 +01:00
Proddy
fcffa3df5c add comment 2024-01-21 21:49:06 +01:00
Proddy
27d0ba0526 store custom files for testing 2024-01-21 21:48:36 +01:00
Proddy
18d329f3ee add analog test 2024-01-21 21:48:24 +01:00
Proddy
9e064eb564 remove comments 2024-01-21 21:48:04 +01:00
Proddy
2764185132 minor text changes 2024-01-21 18:28:07 +01:00
Proddy
79d7142e5f add test data 2024-01-21 18:27:58 +01:00
Proddy
2a3838771a cleanup tests 2024-01-21 18:27:22 +01:00
Proddy
8d712c47f0 package update 2024-01-21 18:26:47 +01:00
Proddy
a3ccc83cf3 change text for custom entities 2024-01-21 18:26:36 +01:00
proddy
fe30b8de8d work on muter/upload testing 2024-01-21 11:46:13 +01:00
proddy
d8671dd114 formatting 2024-01-21 11:45:40 +01:00
proddy
603036a5e9 formatting 2024-01-21 11:45:29 +01:00
proddy
9eb617bcb0 package update 2024-01-21 11:45:22 +01:00
proddy
82e1b069eb rename callback function 2024-01-21 11:45:00 +01:00
Proddy
1b27e1fd09 Merge pull request #1572 from proddy/dev
update web standalone with variable custom entity
2024-01-20 21:00:20 +01:00
Proddy
d99222450c minor code optimizations 2024-01-20 20:58:46 +01:00
Proddy
ef075787dc add ram to test data 2024-01-20 20:58:38 +01:00
Proddy
ec411a7dff Merge pull request #1570 from MichaelDvP/dev
custom variables #1423
2024-01-20 20:20:34 +01:00
Proddy
fd4f649db3 Merge pull request #1571 from proddy/dev
minor tweaks
2024-01-20 20:18:50 +01:00
Proddy
0c93f1daa5 update esptool files 2024-01-20 20:17:46 +01:00
Proddy
7da2806ab4 add missing security endpoint 2024-01-20 20:17:30 +01:00
Proddy
f88685833d fix endless loop with token 2024-01-20 20:17:17 +01:00
MichaelDvP
c0e77698aa Add custom variables #1423 2024-01-20 17:57:01 +01:00
MichaelDvP
9fd7b2553c set min/max for hpDiffPress 2024-01-20 17:24:47 +01:00
Proddy
bb5ca8a804 Merge pull request #1569 from MichaelDvP/dev
telegram mapping to device, add 0x2CC telegrams
2024-01-20 15:13:39 +01:00
MichaelDvP
cd8921e78e add hpSetDiffPressure #1563 2024-01-20 15:01:41 +01:00
MichaelDvP
9260db330e add mixer values #1554 2024-01-20 15:01:11 +01:00
MichaelDvP
3b32dcb407 Map telegrams as mentioned in #1563 2024-01-20 14:59:59 +01:00
Proddy
549a0302b7 Merge pull request #1568 from MichaelDvP/dev
fix #1565 and workaround for #1564
2024-01-20 12:22:31 +01:00
MichaelDvP
4d1a428acf fix #1565, use String for output a single api_data 2024-01-20 10:48:16 +01:00
MichaelDvP
cc83dab97b remove unused type 2024-01-20 10:46:10 +01:00
MichaelDvP
65ff765219 workaround for #1564 2024-01-20 10:45:52 +01:00
MichaelDvP
d5cb5c1c51 update packages 2024-01-20 10:45:01 +01:00
MichaelDvP
4974208a65 update arduinoJson 7.02 2024-01-20 08:36:06 +01:00
Proddy
2b6fd41d5a Merge pull request #1559 from proddy/dev
add tag after fullname instead of before
2024-01-17 11:58:55 +01:00
Proddy
e26208a5e9 package update 2024-01-17 11:58:33 +01:00
Proddy
12a545ddbf rollback #1338 2024-01-17 11:58:25 +01:00
Proddy
4ad5c7299e fixes #1338 2024-01-14 21:32:00 +01:00
Proddy
c04371dfae rename Discovery to lowercase so it looks consistent 2024-01-14 21:31:43 +01:00
Proddy
d810494211 update react-toastify 2024-01-14 21:31:20 +01:00
Proddy
18dd207d3c fixes #1338 2024-01-14 21:12:50 +01:00
Proddy
a34c8661bd optimize so easier to port to IDF later 2024-01-14 21:12:36 +01:00
Proddy
f9516860e3 remove comment 2024-01-14 21:12:15 +01:00
Proddy
ded7b547e1 Merge pull request #1558 from proddy/dev
renamed Web custom entity TSX class, remove bogus URI handler from Web customization, added icon to Custom table
2024-01-14 15:26:14 +01:00
Proddy
77607263a9 3.6.5-dev.9 2024-01-14 15:22:07 +01:00
Proddy
c55e05e7b2 remove redundant rest call to /rest/customization 2024-01-14 15:16:50 +01:00
Proddy
d529cbf269 package update 2024-01-14 15:15:48 +01:00
Proddy
c578154b5e tidy up custom entities, add writeable icon (inspired by #1557) 2024-01-14 15:15:40 +01:00
Proddy
bbfdb0ff0e Merge pull request #1555 from proddy/dev
routine updates
2024-01-13 22:24:02 +01:00
Proddy
48de155201 update example 2024-01-13 22:21:50 +01:00
Proddy
a2cfe00113 update tasmota lib 2024-01-13 22:21:43 +01:00
Proddy
e0c8557d5c package update 2024-01-13 22:21:12 +01:00
Proddy
d6aa1fb48b ArduinoJson 7.0.1 2024-01-13 11:37:37 +01:00
Proddy
2190db77ad package update 2024-01-13 11:37:19 +01:00
Proddy
8c2aba8eb1 Merge pull request #1552 from proddy/dev
new 'add' test
2024-01-12 08:50:55 +01:00
proddy
c834c5e43e debug formatting 2024-01-11 21:37:48 +01:00
proddy
94f268a62d add new 'add' test 2024-01-11 21:37:40 +01:00
proddy
1f81ccb686 remove comment 2024-01-11 21:36:58 +01:00
proddy
356180dbf9 package update 2024-01-11 21:36:52 +01:00
Proddy
1d025d5b97 Merge pull request #1548 from proddy/dev
also remove references from JsonObjectConst and JsonArray
2024-01-08 11:45:30 +01:00
Proddy
cf8c5430d1 also remove references from JsonObjectConst and JsonArray 2024-01-08 11:44:33 +01:00
Proddy
1dde495f61 Merge pull request #1546 from MichaelDvP/dev
fix typo #1521
2024-01-08 11:33:50 +01:00
Proddy
c3650817ef Merge pull request #1547 from proddy/dev
remove & reference to JsonVariant (prevent dangling references)
2024-01-08 11:33:37 +01:00
Proddy
3f10523e66 remove & reference to JsonVariant (prevent dangling references) 2024-01-08 11:32:58 +01:00
Proddy
ad9e463923 update package 2024-01-08 11:25:35 +01:00
MichaelDvP
5f2859fae2 fix typo #1521 2024-01-08 11:23:17 +01:00
Proddy
2b03d01a15 Merge pull request #1544 from proddy/dev
small changes, but many
2024-01-06 18:00:23 +01:00
Proddy
2366f6ba50 update licensing year to 2024 2024-01-06 17:58:11 +01:00
Proddy
10d6728c82 remove obsolete reference to JsonObject 2024-01-06 17:42:42 +01:00
Proddy
778cdaabb6 Merge branch 'emsesp:dev' into dev 2024-01-06 17:37:49 +01:00
Proddy
efa4f80b99 Merge pull request #1542 from MichaelDvP/dev
fix #1495 and #1536
2024-01-06 17:16:35 +01:00
MichaelDvP
ae15c7ccd0 add boiler C1200W, #1536 2024-01-06 16:50:37 +01:00
MichaelDvP
bf95205af6 fix #1495 wwComfort mode 2024-01-06 16:10:12 +01:00
Proddy
cb11305416 upper case Digital In 2024-01-06 10:48:49 +01:00
Proddy
5e0c6a527a fix test for device list 2024-01-06 10:48:27 +01:00
Proddy
8540e71145 add additional cache header 2024-01-06 10:48:15 +01:00
Proddy
cb2746b741 show total size in a comment in file 2024-01-06 10:48:03 +01:00
Proddy
209644d500 unused 2024-01-06 10:47:51 +01:00
Proddy
273dc4b83c fix case of Value (introduced by Polish translations) 2024-01-06 10:47:43 +01:00
Proddy
75574f663b uppercase Digital In/Out 2024-01-06 10:47:15 +01:00
Proddy
462870fe6b uppercase Value 2024-01-06 10:47:02 +01:00
Proddy
f365fe5317 Merge pull request #1539 from proddy/dev
ArduinoJson version 7.0.0 - #1538
2024-01-05 22:42:20 +01:00
Proddy
19eb755157 fix Arduino 7 (using to<> and not as<> 2024-01-05 22:39:35 +01:00
Proddy
26e4badc1b add sections for MQTT Discovery 2024-01-05 22:39:08 +01:00
Proddy
fb00f4eef9 update 3.6.5.dev-8 2024-01-05 22:37:24 +01:00
Proddy
2ef85bb9fa package update 2024-01-05 22:37:07 +01:00
Proddy
2dfba3f7d0 default GPIO is 21 (40 is invalid) 2024-01-05 22:36:53 +01:00
Proddy
5259d55f23 show Platform (taken from build) 2024-01-05 22:36:31 +01:00
Proddy
af237c4fc0 Arduino v7 2024-01-04 23:43:30 +01:00
Proddy
13a915e1f4 Merge pull request #1537 from proddy/dev
fixes #1360 (domoticz) and #1528 (HA dev name)
2024-01-04 18:12:43 +01:00
Proddy
df33a24951 fix add_ha_sections_to_doc calls 2024-01-04 18:11:08 +01:00
Proddy
e62fc14b6d support domoticz - MQTT autodiscovery in Domoticz not working #1360 2024-01-04 18:10:53 +01:00
Proddy
591b8afcb0 restructuring and added additional domoticz support 2024-01-04 18:10:16 +01:00
Proddy
35ee8c33b3 add comment 2024-01-04 18:09:42 +01:00
Proddy
9ca47627d2 updated example pio 2024-01-04 18:09:29 +01:00
Proddy
4c27cb831e update tests for temp sensors 2024-01-04 18:09:18 +01:00
Proddy
a3b6656be7 add additional Domoticz to discovery_type 2024-01-04 18:09:00 +01:00
Proddy
b0076cd5da change comments 2024-01-04 18:08:41 +01:00
Proddy
b6dbf93de2 add missing setContentType 2024-01-04 18:08:31 +01:00
Proddy
3f42c4d56b fix typo 2024-01-03 23:57:00 +01:00
Proddy
55ce551868 added hostname to network status 2024-01-03 23:56:52 +01:00
Proddy
d16e77bba3 updated example 2024-01-03 23:56:31 +01:00
Proddy
c9efd095e7 show network hostname in webui 2024-01-03 23:56:23 +01:00
Proddy
8384344c5a no need to pretty json output 2024-01-03 23:03:41 +01:00
Proddy
cb5f707b2d use add_ha_sections_to_doc(), add via_device, add check for domoticz 2024-01-03 23:00:07 +01:00
Proddy
e525552e10 wifi console help text 2024-01-03 22:58:21 +01:00
Proddy
78bd0a1b76 espressif 6.5.0 2024-01-03 22:57:59 +01:00
Proddy
1316fe9509 3.6.5-dev.8 2024-01-03 22:57:13 +01:00
Proddy
c45fd23227 package update 2024-01-03 22:56:26 +01:00
Proddy
d6856e8a23 optimized chunking 2024-01-03 22:56:16 +01:00
Proddy
5fcad37fb9 ok to show devices if no ems connection 2024-01-03 22:56:03 +01:00
Proddy
ab58a3dfd3 add spacing 2024-01-03 22:55:44 +01:00
Proddy
0fce450418 Merge pull request #1530 from proddy/dev
minor changes
2023-12-28 14:21:35 +01:00
Proddy
3a92d69c77 minor changes from https branch 2023-12-28 14:20:06 +01:00
Proddy
fa1a372468 https://github.com/emsesp/EMS-ESP32/pull/1517 2023-12-28 14:19:54 +01:00
Proddy
62b341a614 Merge pull request #1517 from arturzx/dev
fix: Fixed dev section in analog sensor HA discovery
2023-12-28 13:56:34 +01:00
Proddy
0058632d71 Merge pull request #1523 from pswid/dev
Polish translation update
2023-12-28 13:53:45 +01:00
Proddy
339408e12a Merge pull request #1529 from proddy/dev
fix HA modes from dev2 for #1525
2023-12-28 13:41:38 +01:00
Proddy
8bffa6b304 bump version 2023-12-28 13:40:45 +01:00
Proddy
7c80364bcf package update 2023-12-28 13:39:28 +01:00
Proddy
ac950e0e92 fix from dev2 for https://github.com/emsesp/EMS-ESP32/pull/1525 2023-12-28 13:39:14 +01:00
Proddy
8d33a89e39 Merge pull request #1524 from MichaelDvP/dev
add ES79 and fix german translation, fixes #1521, #1522
2023-12-22 16:18:04 +01:00
MichaelDvP
41260a4370 fix nompower warning 2023-12-22 14:46:23 +01:00
MichaelDvP
7d15a8010d update pkg 2023-12-22 12:32:10 +01:00
MichaelDvP
606a7e6eec add Sieger ES79, #1521 2023-12-22 12:27:39 +01:00
MichaelDvP
83e400fbe9 fix german translation from #1522 2023-12-22 12:25:07 +01:00
pswid
d3ae73e6b2 Restored Polish characters in the font file
Polish characters disappeared from the re.woff2 file sometime between April and August this year. I assume it was unintentional.
2023-12-22 11:15:17 +01:00
pswid
b4b2531e33 Polish translation update 2023-12-22 10:45:37 +01:00
Proddy
225e482814 Merge pull request #1519 from MichaelDvP/dev_1
compile with tasmota arduino 2.14 and 3.0
2023-12-20 22:06:39 +01:00
MichaelDvP
446601c6e0 update mqttClient, works with tasmota-arduino 2.14 / 3.0 without WiFiSecure 2023-12-19 13:47:10 +01:00
MichaelDvP
9f3e2dbcd3 merge PR#1497 from pswid, add partiton, resort system status 2023-12-19 13:44:15 +01:00
Artur Zabroński
3163a142a9 fix: Fixed dev section in analog sensor HA discovery 2023-12-19 08:51:56 +01:00
MichaelDvP
dcb0d5087f Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-12-18 18:18:10 +01:00
MichaelDvP
19743da558 translation cold water 2023-12-18 09:48:25 +01:00
Proddy
08c5fd8f64 Merge pull request #1514 from MichaelDvP/dev
ethernet with arduino_3.0, sort translations alphabetical
2023-12-18 09:45:38 +01:00
Proddy
a28cdaa930 Merge pull request #1515 from proddy/dev
add SK entity translations (from Michael)
2023-12-18 09:44:25 +01:00
proddy
3f31962a9a add SK translations (from Michael) 2023-12-18 09:43:38 +01:00
proddy
651b1b1c50 package update 2023-12-18 09:43:21 +01:00
MichaelDvP
ca2ca972b9 add sk entity translations 2023-12-17 13:58:04 +01:00
MichaelDvP
215c4e49ca sort translation alphabetical 2023-12-17 12:48:36 +01:00
MichaelDvP
d1dbce84c7 ethernet working with arduino_3.0 2023-12-17 12:39:36 +01:00
MichaelDvP
fb4a0b0ae8 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-12-17 12:35:46 +01:00
Proddy
a01ee4a48d Merge pull request #1513 from proddy/dev
fix SK
2023-12-17 09:47:19 +01:00
proddy
8ed867314d fix SK 2023-12-17 09:46:53 +01:00
Proddy
abf4eeb39a Merge pull request #1508 from misa1515/patch-8
Update index.ts
2023-12-17 09:33:00 +01:00
Proddy
40a85634ef Merge pull request #1509 from misa1515/patch-9
Update LayoutAuthMenu.tsx
2023-12-17 09:32:31 +01:00
Proddy
a5c41a1cd8 Merge pull request #1510 from misa1515/patch-10
Update SignIn.tsx
2023-12-17 09:32:07 +01:00
Proddy
c6668e1d6a Merge pull request #1511 from misa1515/patch-11
Update system.cpp
2023-12-17 09:31:38 +01:00
misa1515
5384abc780 Update system.cpp 2023-12-16 22:54:14 +01:00
misa1515
444d5fb7c3 Update SignIn.tsx 2023-12-16 22:50:51 +01:00
misa1515
3b76a020c7 Update LayoutAuthMenu.tsx 2023-12-16 22:49:23 +01:00
misa1515
804187afb9 Update index.ts 2023-12-16 22:44:54 +01:00
Proddy
ef2ed0f4d1 Merge pull request #1507 from proddy/dev
add SK
2023-12-16 22:40:08 +01:00
proddy
68084fc9b5 add SK 2023-12-16 22:36:25 +01:00
MichaelDvP
1556bf02ba fix setting dhw comfort #1495 2023-12-14 07:57:48 +01:00
Proddy
68cb94547e Merge pull request #1499 from MichaelDvP/dev
latest entities
2023-12-13 11:51:58 +01:00
MichaelDvP
ee584375c5 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-12-13 07:15:52 +01:00
Proddy
ac288b794f Merge pull request #1493 from proddy/dev
update standalone server to bun and itty-router, add back router paths, add support download button
2023-12-12 22:37:56 +01:00
Proddy
a1f296b2ae upercase Remember 2023-12-12 22:37:48 +01:00
Proddy
9b1e399730 fixes #1494 2023-12-12 22:35:10 +01:00
Proddy
dd6b435417 merge latest change from official repo 2023-12-12 22:34:34 +01:00
Proddy
3d5c08118c package update 2023-12-12 22:34:18 +01:00
MichaelDvP
d78d4aed9d Merge branch 'dev' of https://github.com/proddy/EMS-ESP32 into dev 2023-12-12 14:40:38 +01:00
MichaelDvP
9f34531956 fix dhw comfort mode, #1495 2023-12-12 10:11:52 +01:00
MichaelDvP
d1f3ead8b9 fix mqtt::on_message, #1494 2023-12-12 10:09:02 +01:00
Proddy
a33f17932f support info downloaded as txt 2023-12-11 16:18:11 +01:00
Proddy
eb05b83009 package update 2023-12-11 16:17:57 +01:00
Proddy
367c022e6c updated vscode 2023-12-11 16:17:45 +01:00
MichaelDvP
b9af4325c9 set curBurnPower for 3.party burners, #1483 2023-12-11 10:57:17 +01:00
MichaelDvP
1ae2a624f7 add back lowres dewtemp, #1491 2023-12-11 09:12:23 +01:00
MichaelDvP
d4c9a3c846 Merge branch 'dev' of https://github.com/proddy/EMS-ESP32 into dev 2023-12-11 09:05:58 +01:00
Proddy
0b481a44a1 experiment with path args (for future change) 2023-12-10 14:58:33 +01:00
Proddy
513d0e982e replace express with itty router - its 2x faster 2023-12-10 14:52:15 +01:00
Proddy
2629471a56 package update 2023-12-10 14:51:33 +01:00
Proddy
c1ce4f1b73 tidy up support download - https://github.com/emsesp/EMS-ESP32/discussions/1489 2023-12-10 14:51:20 +01:00
Proddy
faa21abe54 revert back to absolute routing 2023-12-10 14:50:34 +01:00
MichaelDvP
c9f5b0a2c1 fix wwCurFlow #1334, fix active state #1483, dev.4 2023-12-09 15:39:10 +01:00
MichaelDvP
ed060a400d update packages 2023-12-08 19:15:15 +01:00
MichaelDvP
6c3e5d976c console tx_mode without reboot 2023-12-08 19:15:05 +01:00
MichaelDvP
443050ae28 fix syspress for ems+ 2023-12-08 19:14:29 +01:00
Proddy
c9ca395e6d Merge branch 'emsesp:dev' into dev 2023-12-04 17:39:07 +01:00
Proddy
c3ac215493 Merge pull request #1481 from MichaelDvP/dev
add hpMaxPower #1475
2023-12-04 17:38:54 +01:00
MichaelDvP
10cabd032b update packages, formatting, changelog 2023-12-04 17:27:07 +01:00
MichaelDvP
7b9a04ede1 add hpMaxPower fix #1475 2023-12-04 17:17:23 +01:00
Proddy
9375fb4d2d Merge branch 'emsesp:dev' into dev 2023-12-03 21:28:42 +01:00
Proddy
f9b8ac6f30 Merge pull request #1478 from MichaelDvP/dev
fixes for #1474 and #1477
2023-12-03 21:28:23 +01:00
MichaelDvP
42ba93bdc1 add checkbox for MQTT-TLS, fix #1474 2023-12-03 18:07:30 +01:00
MichaelDvP
fd5f5d49b7 add back boil2hyst, fix #1477 2023-12-03 17:23:02 +01:00
proddy
80f4e63850 adjust help text 2023-12-02 12:26:11 +01:00
Proddy
7efa8ffbe0 Merge pull request #1473 from proddy/dev
roll back dom-router changes
2023-12-02 11:06:46 +01:00
Proddy
85016d6582 Merge branch 'emsesp:dev' into dev 2023-12-02 11:06:06 +01:00
Proddy
06bf2f3427 rollback dom router changes - https://github.com/emsesp/EMS-ESP32/pull/1465 2023-12-02 11:05:17 +01:00
Proddy
c38832ef06 fix warning 2023-12-02 11:04:45 +01:00
Proddy
c1fa5c42c4 Merge pull request #1471 from MichaelDvP/dev
Some new/fixed entities
2023-11-29 20:55:14 +01:00
MichaelDvP
2faa78bc32 version 3.6.5-dev.2, changelog 2023-11-29 13:12:22 +01:00
MichaelDvP
b5633cd579 add texts 2023-11-29 13:02:43 +01:00
MichaelDvP
4275d144ca add boiler pumpmode and HP heat meter 2023-11-29 12:32:42 +01:00
MichaelDvP
7f794f35a6 add thermostat heatdelays, instantstart and boost 2023-11-29 12:32:04 +01:00
MichaelDvP
8d778f902f add heatpump energy meters 2023-11-29 12:31:05 +01:00
MichaelDvP
f83f22a6fb send step as string to avoid js-rounding issue for 0.1 2023-11-29 12:06:56 +01:00
MichaelDvP
03b6ebd861 fix exhaust temperature #1467 2023-11-29 12:05:46 +01:00
Proddy
306baee94d Merge pull request #1470 from proddy/dev
HA don't set entity_category to Diagnostic/Configuration for EMS entities
2023-11-28 20:54:20 +01:00
Proddy
cb1989b2ea HA don't set entity_category to Diagnostic/Configuration for EMS entities 2023-11-28 20:52:59 +01:00
Proddy
7ce99cb1fb 3.6.5-dev.1 2023-11-28 20:52:44 +01:00
Proddy
3a36663d94 package update 2023-11-28 20:52:27 +01:00
Proddy
e00eb8e64f 3.6.4 2023-11-26 20:11:36 +01:00
Proddy
ba21293c42 Merge pull request #1465 from proddy/dev
fix router loops
2023-11-26 18:44:35 +01:00
Proddy
8574b44d4e react-router-dom 6.20.0 minimal 2023-11-26 18:44:15 +01:00
Proddy
76901d97d2 fix router 2023-11-26 15:56:46 +01:00
Proddy
1cbfc91912 remove tab from help page 2023-11-26 15:56:30 +01:00
Proddy
c81f579464 Merge pull request #1464 from MichaelDvP/dev
revert to react-router-dom 6.18.0 to bring blue tab line back
2023-11-26 09:58:35 +01:00
MichaelDvP
8898ec9419 revert to react-router-dom 6.18.0 to bring blue tab line back 2023-11-26 08:59:32 +01:00
Proddy
b60127c3ba Merge pull request #1461 from MichaelDvP/dev
revert to react-router-dom 6.19.0 to fix tab-routing-issue
2023-11-25 10:08:17 +01:00
MichaelDvP
095255b9b7 revert to react-router-dom 6.19.0 to fix tab-routing-issue 2023-11-24 13:36:55 +01:00
Proddy
d36246d4d1 Merge pull request #1458 from proddy/dev
3.6.5-dev.0
2023-11-24 07:41:46 +01:00
Proddy
19094d47aa 3.6.5-dev.0 2023-11-24 07:41:23 +01:00
Proddy
f41bb3671c 3.6.4 2023-11-24 07:36:36 +01:00
Proddy
22c75e6df3 3.6.4 2023-11-24 07:36:29 +01:00
Proddy
24cca67625 Merge pull request #1457 from proddy/dev
update packages
2023-11-24 07:28:52 +01:00
Proddy
41443d4efe update packages 2023-11-24 07:28:29 +01:00
Proddy
6e08356ff7 Merge pull request #1455 from MichaelDvP/dev
fix boiler commands to ems telegrams
2023-11-23 19:07:13 +01:00
MichaelDvP
751410ca58 fix boiler commands to ems telegrams 2023-11-23 18:27:03 +01:00
proddy
5ab10b7aa6 fixes #1450 2023-11-22 09:48:09 +01:00
Proddy
01a15a5c85 Merge pull request #1451 from MichaelDvP/dev
next fix RC300 mode
2023-11-22 08:24:25 +01:00
MichaelDvP
1e15f65b0d get mode for seltemp, fix #1450 2023-11-22 07:50:50 +01:00
MichaelDvP
0818728c25 update packages 2023-11-22 07:50:21 +01:00
Proddy
ee5fd4d0eb 3.6.3 2023-11-21 14:40:47 +01:00
Proddy
46f35bc67c another patch on 3.6.3 2023-11-21 14:40:32 +01:00
Proddy
5ad03facce Merge pull request #1445 from proddy/dev
patch for 3.6.3 with fixes #1440 #1442
2023-11-21 10:43:08 +01:00
Proddy
ad3bf294d8 Merge branch 'emsesp:dev' into dev 2023-11-21 10:42:39 +01:00
Proddy
6dba452aea patch for 3.6.3 with fixes #1440 #1442 2023-11-21 10:42:19 +01:00
Proddy
cff5b8c949 Merge pull request #1444 from MichaelDvP/dev
set/read thermostat mode for RC100-RC300, fix #1440 and fix #1442
2023-11-21 10:33:46 +01:00
MichaelDvP
aed45968db set/read thermostat mode for RC100-RC300, fix #1440 2023-11-20 07:47:01 +01:00
Proddy
ec85a7ec24 3.6.3 (refershed) 2023-11-19 21:24:01 +01:00
Proddy
2de855e044 Merge pull request #1439 from proddy/dev
prepare another 3.6.3 build with board profile fixed
2023-11-19 21:19:10 +01:00
Proddy
dfd9fe4d01 add EMSESP_DEFAULT_BOARD_PROFILE to CI builds 2023-11-19 21:18:15 +01:00
Proddy
049f956131 minor cleanup 2023-11-19 21:17:54 +01:00
Proddy
b503e2bb90 package update 2023-11-19 21:17:43 +01:00
Proddy
b300181d33 add hosted target 2023-11-19 21:17:36 +01:00
Proddy
02f2389587 add workflow_dispatch: 2023-11-18 18:51:12 +01:00
Proddy
7f140021aa quick fix - https://github.com/emsesp/EMS-ESP32/pull/1438 2023-11-18 18:47:28 +01:00
Proddy
905b52e39d Merge pull request #1438 from MichaelDvP/dev
fix crash on wrong thermostat mode command (if not using HA)
2023-11-18 14:05:54 +01:00
MichaelDvP
8fcfb3d8f7 fix crash on wrong thermostat mode command (if not using HA) 2023-11-18 13:55:28 +01:00
Proddy
64d46fe8f7 Merge pull request #1437 from proddy/dev
update changelog
2023-11-18 13:43:27 +01:00
Proddy
7962af0872 update changelog 2023-11-18 13:42:50 +01:00
Proddy
873b75240c Merge pull request #1436 from proddy/dev
3.6.4-dev-0
2023-11-18 13:38:20 +01:00
Proddy
9e405c5a5a 3.6.4-dev-0 2023-11-18 13:37:55 +01:00
Proddy
6796962c1e 3.6.3 2023-11-18 13:35:20 +01:00
Proddy
df6de21cf4 Merge remote-tracking branch 'origin/dev' 2023-11-18 13:35:04 +01:00
Proddy
e20434da88 Merge pull request #1435 from proddy/dev
prepare for 3.6.3 release
2023-11-18 13:19:27 +01:00
Proddy
9c8677acb9 prepare for 3.6.3 release 2023-11-18 13:19:02 +01:00
Proddy
1c3bc98bbb Merge pull request #1434 from proddy/dev
fix web building with vite 5
2023-11-17 12:11:28 +01:00
Proddy
02616696dc move JS to ES module 2023-11-17 12:09:38 +01:00
Proddy
00d66c1c4e package update 2023-11-17 11:26:30 +01:00
Proddy
8cfc540670 Merge pull request #1432 from proddy/dev
fix building on osx, some package updates again
2023-11-16 22:44:23 +01:00
proddy
a4062f5d84 package update 2023-11-16 22:07:47 +01:00
proddy
edee463ade replace unstable_useBlocker 2023-11-16 22:07:42 +01:00
proddy
64471e4c0e dev.10 2023-11-16 22:07:00 +01:00
proddy
28a7ceb6aa fix build on osx - see https://docs.platformio.org/en/latest/projectconf/sections/env/options/build/build_flags.html#stringification 2023-11-16 22:06:43 +01:00
Proddy
e4a899912c Merge pull request #1430 from proddy/dev
fix for export_values and new command_allvalues()
2023-11-16 07:41:26 +01:00
proddy
cc9819b56b fix lint compile warnings 2023-11-15 21:40:49 +01:00
proddy
29f86c9ab9 make standalone work 2023-11-15 21:40:38 +01:00
proddy
722ca34a18 rollback and fix https://github.com/emsesp/EMS-ESP32/pull/1426 2023-11-15 21:40:23 +01:00
Proddy
bc39b738e2 auto formatting 2023-11-15 17:56:23 +01:00
Proddy
1ada18ec9a 3.6.3-dev.9 2023-11-15 17:56:15 +01:00
Proddy
6b9dadc0d9 Merge pull request #1428 from MichaelDvP/dev2x
latest changes
2023-11-15 12:08:18 +01:00
MichaelDvP
cf89a06437 do not remove fetches 2023-11-15 11:48:18 +01:00
MichaelDvP
4a1ea99ee7 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2x 2023-11-15 11:31:58 +01:00
MichaelDvP
3dbf8a0fd1 fix crash on wrong input for switchtime 2023-11-15 11:31:51 +01:00
Proddy
7b5a37a85d Merge pull request #1426 from proddy/dev
fix bug when traversing ems devices when using cmd allvalues
2023-11-15 09:50:40 +01:00
Proddy
0b5a7b9f2a fix bug when traversing ems devices when using cmd allvalues 2023-11-14 22:24:32 +01:00
Proddy
0f99415bbf add comments 2023-11-14 22:24:09 +01:00
Proddy
c9775c1edd Merge pull request #1425 from proddy/dev
only send command and value to backend write service
2023-11-14 21:41:59 +01:00
Proddy
1f1b571e91 update packages 2023-11-14 18:51:35 +01:00
Proddy
21e28e970c only send command and value to backend write service 2023-11-14 18:51:20 +01:00
MichaelDvP
4f1ef297c7 thermostat RC300 mode 2023-11-14 10:53:27 +01:00
MichaelDvP
3b30083e7c fix extension module 2023-11-14 10:52:39 +01:00
MichaelDvP
50590f4924 console api_data 2023-11-14 10:52:23 +01:00
MichaelDvP
fae876d7d2 Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2x 2023-11-14 10:12:11 +01:00
MichaelDvP
c1dabddf21 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2x 2023-11-14 10:12:02 +01:00
Proddy
a8ea6ef4a8 Merge pull request #1422 from ellepdesk/options-invert-pullup
Add options to invert RX and TX and to enable pullup on RX
2023-11-13 17:02:31 +01:00
Proddy
196e98b3bd Merge pull request #1418 from proddy/dev
show UOM in console when 'show values'. And added a new system command called 'values' which dumps the same to JSON
2023-11-13 17:00:33 +01:00
Proddy
a0f1f51cca rename system values -> allvalues 2023-11-13 16:58:32 +01:00
Proddy
d717b72a9e have its own show_values function 2023-11-13 16:58:20 +01:00
Proddy
eccece7207 minor code optimization 2023-11-13 16:57:35 +01:00
Proddy
499ff0d31e include (HS1) for standalone testing 2023-11-13 16:57:20 +01:00
Proddy
ae0599d13d optionally render with UOM attached 2023-11-13 16:56:48 +01:00
Proddy
1a9cf4ebdc added more space for longer names 2023-11-13 16:56:25 +01:00
Proddy
386082b747 update for vscode 2023-11-13 16:55:52 +01:00
Proddy
fc02721815 package update 2023-11-13 16:55:10 +01:00
Pelle van der Heide
529970fb19 remove option for RX_PULLUP, this is enabled by default in esp-idf 2023-11-13 14:30:42 +01:00
MichaelDvP
752ce333ec RC300/BC400 mode setting 2023-11-13 14:04:55 +01:00
MichaelDvP
8e844550bf sort HIU entities 2023-11-13 13:53:35 +01:00
Pelle van der Heide
dfd2a017c2 Add options to invert RX and TX and to enable pullup on RX
These option can be individually enabled at compile time by the
following defines:

EMSUART_RX_INVERT
EMSUART_TX_INVERT
EMSUART_RX_PULLUP
2023-11-13 12:00:56 +01:00
Proddy
c40a11504c Merge pull request #1417 from MichaelDvP/dev2x
uptime, inputs, output EA0, HIU entities
2023-11-12 16:05:52 +01:00
Proddy
fd81299da1 3.6.3-dev.8 2023-11-12 16:00:52 +01:00
Proddy
9993a7c739 fix UOM not showing in console - and added new command 'system values' 2023-11-12 15:59:29 +01:00
Proddy
ea38011085 add text to remind people about su command 2023-11-12 15:59:02 +01:00
Proddy
2079b7e602 formatting 2023-11-12 15:58:35 +01:00
Proddy
101159b9f6 add sensors to generic test 2023-11-12 15:58:22 +01:00
Proddy
1442568790 uppercase ems 2023-11-12 15:58:06 +01:00
MichaelDvP
1b27fae844 fix tag of hpEA0 2023-11-12 14:31:42 +01:00
MichaelDvP
4b6b89f1a0 add uptimetotal, #1416 2023-11-12 13:46:33 +01:00
MichaelDvP
a2422e1f6a add hpEA0, heatnigpump for all boilers/hps/hiu, remove input-state 2023-11-12 11:41:49 +01:00
Proddy
8ba40003e4 Merge pull request #1411 from proddy/dev
fix HA warnings - add a device name - #1393
2023-11-11 18:02:46 +01:00
Proddy
ac0fb52ce9 fix HA warnings - add a device name - #1393 2023-11-11 18:01:52 +01:00
Proddy
031c97a162 3.6.3-dev.7 2023-11-11 18:01:19 +01:00
Proddy
f7d3939c72 update packages 2023-11-11 18:01:09 +01:00
Proddy
20f32db8bc Merge pull request #1409 from MichaelDvP/dev2x
fix `retTemp`, #1334
2023-11-11 14:43:35 +01:00
MichaelDvP
4d5f8cc96a fix retTemp, #1334 2023-11-11 14:34:35 +01:00
Proddy
981d62dc2c Merge pull request #1384 from WiktorBuczko/patch-1
Update and fix translation
2023-11-11 10:56:53 +01:00
Proddy
ffcf0bf2d7 Merge pull request #1408 from proddy/dev
update gh actions
2023-11-11 10:18:18 +01:00
Proddy
7997544fb8 update gh actions 2023-11-11 10:17:48 +01:00
Proddy
7e1f16c865 Merge pull request #1407 from proddy/dev
remove set command (with no args)
2023-11-11 09:43:14 +01:00
proddy
765e6bcd69 remove set command (with no args) 2023-11-11 09:41:50 +01:00
Proddy
81b654cc41 Merge pull request #1405 from proddy/dev2
fix standalone compiling
2023-11-10 11:55:26 +01:00
Proddy
3fc36b5e50 fix standalone compiling 2023-11-10 11:54:41 +01:00
Proddy
52077cbd07 Merge pull request #1402 from proddy/dev2
package sync with dev
2023-11-09 23:47:11 +01:00
proddy
a45f1badba package update 2023-11-09 23:41:45 +01:00
proddy
f38f4bc85a package sync with dev 2023-11-09 23:38:57 +01:00
Proddy
8c03592157 Merge pull request #1400 from MichaelDvP/dev2x
Small change from my Dev2
2023-11-09 23:30:36 +01:00
Proddy
e7254bc7f4 Merge pull request #1395 from proddy/dev
fix MQTT base with paths not working in HA [#1393]
2023-11-09 23:29:43 +01:00
MichaelDvP
5d0242b47c sync & cleanup 2023-11-08 15:27:17 +01:00
MichaelDvP
5997dd1491 fix double publish scheduler 2023-11-08 15:05:40 +01:00
MichaelDvP
31a5216ae8 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2x 2023-11-08 15:02:20 +01:00
MichaelDvP
5c0c0675a2 boiler: sort entities, remove hpactivity-states, add 4-way-valve, input-states, eco+ 2023-11-08 14:53:56 +01:00
MichaelDvP
ba9f16da00 publish schedule 2023-11-08 14:51:37 +01:00
MichaelDvP
110ee59cd1 temperaturesensor -> F_(temperaturesensor), analog/temperature mqtt-base() 2023-11-08 14:51:07 +01:00
MichaelDvP
555bf8cb2f pl entity translations 2023-11-08 14:50:09 +01:00
MichaelDvP
5f1dddf7e4 enlarge uart-tx-queue, warn overflow 2023-11-08 14:49:45 +01:00
Proddy
bf5b40ccf4 fix MQTT base with paths not working in HA [#1393] 2023-11-06 21:51:05 +01:00
Proddy
58cbfbc0df update packages 2023-11-06 21:50:49 +01:00
Proddy
06f5e1226f Merge pull request #1391 from proddy/dev2
sync with latest dev
2023-11-05 17:15:20 +01:00
Proddy
af57af46b0 Merge pull request #1390 from proddy/dev
update changelog and bump version
2023-11-05 17:13:33 +01:00
Proddy
3f91377751 added notes on MQTT changes 2023-11-05 17:12:43 +01:00
Proddy
c4c9ed739f 3.6.3-dev.6 2023-11-05 17:12:35 +01:00
Proddy
2a8d3b8cd6 package update 2023-11-05 17:12:21 +01:00
Proddy
af1292caa0 update with notes from dev branch 2023-11-05 17:10:47 +01:00
Proddy
44afa1a30f auto formatting 2023-11-05 17:09:36 +01:00
Proddy
fa184a8f94 sync latest MQTT changes from dev 2023-11-05 17:09:26 +01:00
Proddy
387c2eebcd package update 2023-11-05 17:09:10 +01:00
Proddy
cd6a0da9f0 change version to 3.6.3-test.6 so not mistaken with dev builds 2023-11-05 17:09:00 +01:00
Wiktor
c10ecb097e Update and fix translation 2023-11-04 19:16:08 +01:00
Proddy
207953e8d1 Merge pull request #1383 from proddy/dev
no commands for nrgheat & nrgww - #1382
2023-11-04 14:11:13 +01:00
Proddy
a449ebd0ea improvements to #1382 2023-11-04 13:13:52 +01:00
Proddy
2afe50fc9e Merge pull request #1381 from MichaelDvP/dev2
Dev2: relais, fix exhausttemp, fix RC20 remote
2023-11-04 11:53:46 +01:00
Proddy
cd564f0c54 no commands for nrgheat & nrgww - #1382 2023-11-04 11:46:42 +01:00
Proddy
8eba09fea6 package update 2023-11-04 11:46:16 +01:00
MichaelDvP
6c17d61baf set energy entities to HA-category diagnostic (metioned on discord) 2023-11-03 20:00:16 +01:00
MichaelDvP
6df1f2850f analog: store only if needed 2023-11-03 16:08:45 +01:00
MichaelDvP
288d9b70b7 fix relais command 2023-11-03 14:43:23 +01:00
MichaelDvP
8307b0920c digital_out, settings #1375, dev.5b 2023-11-02 19:14:10 +01:00
MichaelDvP
1097b519ae do not overwrite mqtt-json items 2023-11-02 07:34:57 +01:00
MichaelDvP
e7b7002883 check RC20 master/remote thermostat, #1378 2023-11-02 07:34:18 +01:00
MichaelDvP
c934b9e8d9 fix gh build 2023-11-01 19:37:18 +01:00
MichaelDvP
0838d06ec4 Test for fixing #1378 2023-11-01 18:20:32 +01:00
MichaelDvP
41666458d9 merge mqttClinet PR 115 from BertMelis 2023-11-01 18:18:56 +01:00
MichaelDvP
b02207a0d7 set EMSESP_DEFAULT_BOARD_PROFILE nd store to NVS 2023-11-01 18:17:05 +01:00
MichaelDvP
faafd51e40 add optional exhausttemp from telegram E5 2023-11-01 18:16:21 +01:00
MichaelDvP
94cf81c164 Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-11-01 17:24:18 +01:00
MichaelDvP
1cd97cf1ee E32V2 button to 34, publish alert module 2023-11-01 17:23:45 +01:00
Proddy
6f097e4613 Merge pull request #1377 from proddy/dev
small updates
2023-10-31 22:09:04 +01:00
Proddy
90af88f36d Merge pull request #1376 from proddy/dev2
Dev2
2023-10-31 22:07:48 +01:00
proddy
862cc2545b group order of board profiles 2023-10-31 22:07:12 +01:00
proddy
74c6e54dc5 uppercase Value 2023-10-31 22:07:01 +01:00
proddy
33ac89e202 uppercase Value 2023-10-31 21:58:19 +01:00
proddy
89d591500c support HA writable text fields 2023-10-31 21:58:07 +01:00
proddy
9bf56b2e6d package update 2023-10-31 21:57:38 +01:00
proddy
7c3dac3da7 order board profiles in menu 2023-10-31 21:57:28 +01:00
Proddy
6853651c8b Merge pull request #1374 from proddy/dev2
Dev2
2023-10-31 18:09:45 +01:00
Proddy
16a9bc4fae package updates 2023-10-31 18:08:49 +01:00
Proddy
70d4bcf097 support String entities in Home Assistant #1373 2023-10-31 18:08:43 +01:00
Proddy
1991ca4128 Merge pull request #1372 from proddy/dev
shower duration in sec
2023-10-31 12:34:18 +01:00
Proddy
879df338e3 Merge pull request #1371 from proddy/dev2
small things
2023-10-31 12:33:53 +01:00
Proddy
29c1169b33 shower duration in sec 2023-10-31 12:32:57 +01:00
Proddy
362b6a1394 GNU++11 and not GNU++17 2023-10-31 12:32:12 +01:00
Proddy
f5f5901ad9 package update 2023-10-31 12:31:48 +01:00
Proddy
757bf58992 show duration in sec 2023-10-31 12:31:35 +01:00
Proddy
af8e77029e Merge pull request #1369 from MichaelDvP/dev2
Testbuild
2023-10-30 16:43:33 +01:00
Proddy
94519179df Merge pull request #1368 from proddy/dev
use DEBUG logging for commands with json output - #1364
2023-10-30 13:10:58 +01:00
Proddy
527dd870a2 change shower log message if using NTP 2023-10-30 13:10:03 +01:00
Proddy
b9e57414ce #1364 2023-10-30 13:01:43 +01:00
Proddy
e3a644182e switch back to C++11 2023-10-30 13:00:31 +01:00
MichaelDvP
caadb506d8 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-10-29 17:57:10 +01:00
MichaelDvP
597f0b147d logging commands 2023-10-29 17:10:54 +01:00
MichaelDvP
0b9a2483b2 add HIU entities #1334, fix hp nrgheat/ww offsets #1349 2023-10-29 17:10:26 +01:00
Proddy
6a221e84cc Merge pull request #1365 from proddy/dev
3.6.3-dev.5
2023-10-29 13:44:42 +01:00
Proddy
7ea7a4b25a Merge branch 'emsesp:dev' into dev 2023-10-29 13:44:17 +01:00
Proddy
c494627867 package updates 2023-10-29 13:43:54 +01:00
Proddy
5032c37f63 added 3.6.3-dev.5 2023-10-29 13:43:45 +01:00
Proddy
f5cd92d567 added comments 2023-10-29 13:43:33 +01:00
Proddy
240b7dad32 API commands logged at log level INFO - #1364 2023-10-29 13:43:24 +01:00
MichaelDvP
2bac805ebf update packages 2023-10-27 17:19:08 +02:00
MichaelDvP
b1a3d6ea20 update alert module 2023-10-27 15:58:12 +02:00
MichaelDvP
77cfad9ff0 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-10-27 13:04:11 +02:00
MichaelDvP
2dc1bd71ee changelog, dev.4g 2023-10-27 10:29:46 +02:00
MichaelDvP
fcdc4314e3 Wifi AP start after 10 sec, stay if not connected 2023-10-27 10:28:59 +02:00
MichaelDvP
900112a967 update packages 2023-10-27 10:27:22 +02:00
MichaelDvP
114a8af467 mqtt publish extension module 2023-10-27 10:27:08 +02:00
MichaelDvP
e2c2a12a2b Extension outPower UOM percent 2023-10-27 10:26:47 +02:00
Proddy
222f853616 Merge pull request #1362 from proddy/dev
messing with yarn again (bored)
2023-10-26 12:17:15 -07:00
proddy
450f5a465c messing with yarn again (bored) 2023-10-26 21:16:32 +02:00
MichaelDvP
ba106eecc0 AsyncTCP settings per DEFINE, prio 5 2023-10-26 16:54:05 +02:00
MichaelDvP
374bd7c5c2 extension module instead of pumpp module 2023-10-26 15:08:24 +02:00
MichaelDvP
31b2005320 Remove Wifi-all-channel-scan, it induces connect issues. dev.4f 2023-10-26 14:58:37 +02:00
MichaelDvP
8ae5570c70 NTP do not configure disconnect if already disconnected 2023-10-26 14:55:47 +02:00
MichaelDvP
96fe9aeb31 dont queue mqtt if not connected, dev.4e 2023-10-25 17:45:40 +02:00
MichaelDvP
4a7d69c797 add energy and meters #1359, #1350 2023-10-25 17:43:35 +02:00
MichaelDvP
7dca77450c Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-10-25 17:23:34 +02:00
Proddy
9bb157bbe6 yarn 4.0 2023-10-25 15:31:29 +02:00
Proddy
6c7787b2ae Merge pull request #1358 from owenvoke/feature/tls-typo
chore: fix typos of TLS
2023-10-25 06:22:16 -07:00
Owen Voke
ec5b5ef79d chore: fix typos of TLS 2023-10-25 11:19:15 +01:00
MichaelDvP
6abd56c7e2 update packages, add psram, dev.4d 2023-10-24 22:11:32 +02:00
MichaelDvP
1fdeaf8b24 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-10-24 21:56:09 +02:00
MichaelDvP
ad51870d2c no wifi disconnect until reboot on ssid cleared 2023-10-24 21:54:57 +02:00
Proddy
8929e15e00 Merge pull request #1356 from proddy/dev
show options and range in export - #1342
2023-10-23 07:12:04 -07:00
Proddy
3f31e636ec show options and range in export - #1342 2023-10-23 16:10:08 +02:00
MichaelDvP
5e7e1c30ca show writable in web export, dev.4c 2023-10-23 14:53:43 +02:00
MichaelDvP
5cf0d8d204 board_profile name in NVS after autodetect 2023-10-23 14:53:12 +02:00
MichaelDvP
dbbd475934 do not set forceheatingoff if not in settings 2023-10-23 14:46:39 +02:00
MichaelDvP
bf9877b528 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-10-22 18:25:40 +02:00
MichaelDvP
5e6b0f64bd add E32V2 board profile, fix autodetect and GPIOs 2023-10-22 17:40:38 +02:00
MichaelDvP
509d213536 add TA4/TW1, fix decimal, add EM100 values, update 2023-10-22 17:39:53 +02:00
Proddy
4c789a656b Merge pull request #1355 from proddy/dev
minor changes
2023-10-22 07:54:24 -07:00
Proddy
2f6edfd505 typo 2023-10-22 16:53:33 +02:00
Proddy
9c2d861b93 rename scan devices to just one scan command, and add more devices 2023-10-22 16:48:13 +02:00
Proddy
2c0d4fdcef suppress MQTT warnings on standalone 2023-10-22 16:47:52 +02:00
Proddy
be93627ec0 Merge pull request #1353 from proddy/dev
minor changes plus Michael's updated AsyncTCP library
2023-10-22 03:43:15 -07:00
Proddy
c6c7754735 added WSW196i to UI800 description 2023-10-22 12:41:39 +02:00
Proddy
07bdf28350 added Michael's AsyncTCP fixes for testing 2023-10-22 12:41:16 +02:00
Proddy
fd49f0372a add DIV10 for WS170 - #1334 2023-10-22 12:40:55 +02:00
Proddy
36ca7e09ca Merge pull request #1352 from proddy/dev
quick link from device entities to custom entities page (the list icon)
2023-10-21 07:15:47 -07:00
Proddy
7a36c5e8cb quick link from device entities to custom entities page (the list icon) 2023-10-21 16:14:25 +02:00
Proddy
15b97515bb replace useNavigate hook with redirect 2023-10-21 16:14:02 +02:00
Proddy
4048f58856 package update 2023-10-21 16:13:42 +02:00
Proddy
b0ea3184a4 fix custom entities endpoint 2023-10-21 16:13:31 +02:00
MichaelDvP
6ab2cc60e7 AsyncTCP reduce stack, include some PRs 2023-10-20 18:54:52 +02:00
MichaelDvP
237d631e2c remove double WiFi.disconnect 2023-10-20 17:08:38 +02:00
MichaelDvP
0ed46679e2 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-10-20 16:51:45 +02:00
Proddy
1fded64f2e Merge pull request #1343 from proddy/dev
show entity count in device list, remove type
2023-10-20 07:42:02 -07:00
MichaelDvP
161f782904 fix flodding bus with forceHeatingOff messages, dev3b 2023-10-20 14:39:38 +02:00
MichaelDvP
3fe9296139 EM100 to Alert, add first telegrams 2023-10-20 14:32:30 +02:00
Proddy
9698e787b2 remove dialog from upload as C++ code does restart immediately 2023-10-19 21:37:46 +02:00
Proddy
eb274a94c3 move system info to download page, add a restart warning on upload 2023-10-18 23:15:42 +02:00
Proddy
18be921c1b package update 2023-10-18 23:15:13 +02:00
Proddy
fddfa47b51 layout changes 2023-10-18 15:40:55 +02:00
MichaelDvP
c533e91643 heatburnpower does not count similar with wwburnpow, #1335 2023-10-18 11:22:53 +02:00
MichaelDvP
de2792ffdd add back esp32-s3 SSL for mqtt 2023-10-18 10:34:21 +02:00
MichaelDvP
97de23f521 add WLW176i to boilers 2023-10-18 07:56:08 +02:00
MichaelDvP
c212520f4f remove double dhw texts 2023-10-18 07:55:48 +02:00
MichaelDvP
dc739b97ab forceHeatingOff in E5 check telegram length 2023-10-18 07:55:19 +02:00
MichaelDvP
2583da8714 platform asdev, revert mqtt client changes, uart-isr to flash to save ram 2023-10-18 07:54:36 +02:00
MichaelDvP
ddfc9f9dd0 mqtt use main task again 2023-10-18 07:12:44 +02:00
MichaelDvP
7d855326d0 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-10-18 07:11:11 +02:00
Proddy
a1bb49359f show entity count in device list, remove type 2023-10-17 22:55:47 +02:00
Proddy
f9a176e09c Merge pull request #1341 from proddy/dev
fixes from previous checkin
2023-10-17 12:21:19 -07:00
Proddy
24d5ac7656 default test is general 2023-10-17 21:20:43 +02:00
Proddy
558fa20283 remove left over debug comments 2023-10-17 21:20:08 +02:00
Proddy
c42ead995e fix rollup mangle that prevented table clicks 2023-10-17 21:18:23 +02:00
Proddy
8584901229 Merge pull request #1340 from proddy/dev
add missing 'yarn webUI'
2023-10-17 11:29:14 -07:00
Proddy
a17f8db035 add missing 'yarn webUI' 2023-10-17 17:58:56 +02:00
Proddy
6783d5b3e8 fix typo in package 2023-10-17 16:57:56 +02:00
Proddy
9223a00270 Merge pull request #1339 from proddy/dev
update web building
2023-10-17 07:19:21 -07:00
Proddy
c150c578a6 update web building 2023-10-17 16:06:32 +02:00
proddy
5be1482c20 tidy up package builds 2023-10-17 13:35:25 +02:00
Proddy
20e301594c Update github-releases-to-discord.yml 2023-10-16 15:01:30 +02:00
Proddy
f90f4279d7 Create github-releases-to-discord.yml 2023-10-16 14:58:08 +02:00
Proddy
9962f16d62 Merge pull request #1336 from proddy/dev
fixed helper text in entity dialog for numeric values
2023-10-16 04:16:32 -07:00
proddy
cb10663735 updated 2023-10-16 13:15:30 +02:00
proddy
2ab247131f added WS170 - #1334 2023-10-16 13:13:13 +02:00
proddy
c0a3d03a09 fix formatting for ranges not showing 2023-10-16 12:17:00 +02:00
proddy
baa180cc79 added comments 2023-10-16 12:16:37 +02:00
proddy
dbc59b7c8c remove < and > from template texts 2023-10-16 12:16:25 +02:00
proddy
c4d1058133 add rootCA for testing 2023-10-16 12:16:04 +02:00
proddy
3a8495ca54 lowercase Optional 2023-10-16 12:15:42 +02:00
proddy
dad62613f6 update packages 2023-10-16 12:12:08 +02:00
Proddy
9641adce1c Merge pull request #1333 from proddy/dev
added timestamp to shower_data, add HA's ent_cat discovery to all sensors
2023-10-15 10:33:05 -07:00
Proddy
67693364cc Add entity category to HA Discovery topics - #1323 2023-10-15 17:03:59 +02:00
Proddy
d37a5c5713 bump 3.6.3-dev.2 2023-10-15 17:03:32 +02:00
Proddy
a881431010 auto formatting 2023-10-15 17:03:18 +02:00
Proddy
2866862730 add timestamp - #1329 2023-10-15 17:03:10 +02:00
Proddy
c234e70a87 use previous tasmota platform 2023-10-15 17:02:50 +02:00
Proddy
61296896bd update packages, use latest yarn 2023-10-15 17:02:37 +02:00
MichaelDvP
2acb45db47 send_info_mqtt called from main, not from ntp task 2023-10-15 14:55:42 +02:00
MichaelDvP
abe0d793d6 test mqtt with own task, dev.2i 2023-10-15 12:56:36 +02:00
MichaelDvP
654403ca3d shower time with timezone 2023-10-15 12:53:43 +02:00
MichaelDvP
b111e4762a remove SSL from S3 build 2023-10-15 10:25:32 +02:00
MichaelDvP
8bd796b772 add CS6800i boiler 2023-10-15 10:23:20 +02:00
MichaelDvP
84b6611ffd set ci builds without extends, S3 use arduino 2.0.13 2023-10-15 10:01:13 +02:00
MichaelDvP
58b3f309bd changelog, dev.2h 2023-10-14 18:31:53 +02:00
MichaelDvP
0bd4330881 shower time 2023-10-14 18:31:39 +02:00
MichaelDvP
68feb0fa30 exhausttemp only from E4/31, fetch 0x14 again 2023-10-14 18:31:24 +02:00
MichaelDvP
b4e266f128 mqtt secure only for S3 (avoid conflict with tasmota platform esp32) 2023-10-14 18:31:06 +02:00
MichaelDvP
855794dbe8 no command for remoteseltemp 2023-10-13 16:05:42 +02:00
MichaelDvP
2a38981c67 add some limits, ignore zero for exhausttemp, syspress, rettemp, errormessage check 2023-10-13 12:29:32 +02:00
MichaelDvP
63b4a62fac update packages 2023-10-13 12:25:58 +02:00
MichaelDvP
710fd1bc79 add control setting for RC300 2023-10-12 09:15:42 +02:00
MichaelDvP
f5ab7510b4 disable remote dew if temp or humidity are missing, v3.6.3-dev.2d 2023-10-11 10:36:59 +02:00
MichaelDvP
ecd37223e8 update packages 2023-10-11 10:35:07 +02:00
MichaelDvP
99992db9ac check more states for wifi reconnect 2023-10-10 13:24:59 +02:00
MichaelDvP
3ecea985ad check length for roomctrl response, dev.2c 2023-10-10 09:49:07 +02:00
MichaelDvP
ae1b6fc67b Weblog json dynamic 2023-10-10 09:48:11 +02:00
MichaelDvP
020bb628d6 no mqtt disconnect on GOT_IP if already connected 2023-10-10 09:47:27 +02:00
MichaelDvP
22a4338e7a fix buffer 2023-10-09 16:39:26 +02:00
MichaelDvP
1f089ec6f9 log commands as debug 2023-10-09 11:31:16 +02:00
MichaelDvP
0f78d4f34d fix remote humidity and calc dewpoint, dev.2b 2023-10-08 19:31:41 +02:00
Proddy
8395983106 Merge pull request #1319 from MichaelDvP/dev
add forceheatingoff #1262 and header/heatblock #1317
2023-10-08 12:19:22 +01:00
MichaelDvP
87ce1a6d9b add remotetemp to RC3xx 2023-10-08 12:06:06 +02:00
MichaelDvP
ac4eba5b72 add forceheatingoff 2023-10-07 15:19:04 +02:00
MichaelDvP
5e53689a81 add temperatures for low loss header and heatblock, add names BC400/GB192i, #1317 2023-10-05 18:00:06 +02:00
MichaelDvP
895eddd8d2 update packages 2023-10-05 17:50:49 +02:00
Proddy
a8c7b2bca4 Merge pull request #1318 from proddy/dev
fix shower duration
2023-10-03 22:08:55 +01:00
proddy
6f46382806 fix shower duration 2023-10-03 22:06:44 +01:00
proddy
b8af3e235f update packages 2023-10-03 22:06:34 +01:00
proddy
531c2e7b5d 3.6.3-dev.1 2023-10-03 22:06:23 +01:00
Proddy
f76e6b56b1 Merge pull request #1316 from MichaelDvP/dev
arduino 2.0.13 and 3.0.0 ready
2023-10-03 21:35:47 +01:00
MichaelDvP
c388b31b22 standalone compile 2023-10-03 16:13:36 +02:00
MichaelDvP
cbb6fa9fec update changelog 2023-10-03 15:34:00 +02:00
MichaelDvP
a3300e94a7 compiles for 2.0.13/idf4.4.6 and 3.0.0/idf5.1 (see pio_local.example) 2023-10-03 15:28:27 +02:00
MichaelDvP
3c8a00be09 merge and update changes from jason2866, tasmota platform 2.0.13 2023-10-03 15:26:34 +02:00
MichaelDvP
36ae55e543 update packages 2023-10-03 14:04:13 +02:00
MichaelDvP
8b5d893977 RC100H RF thermostat 2023-10-03 14:04:01 +02:00
MichaelDvP
bd851f9005 use nvs partition label 2023-10-03 10:59:27 +02:00
MichaelDvP
208be85304 lan only supported by esp32 2023-10-03 10:58:44 +02:00
MichaelDvP
9dd613394c add humidity to ventialtion 2023-10-03 10:57:41 +02:00
MichaelDvP
62eeca944b make NTP arduino3 ready 2023-10-03 10:57:20 +02:00
MichaelDvP
17d7487423 use arduino neopixel instead of adafruit lib 2023-10-03 10:54:17 +02:00
MichaelDvP
ae589c745b use onewire from tasmota, arduino3 ready 2023-10-03 10:53:04 +02:00
Proddy
4b41180785 Merge pull request #1312 from proddy/dev
preparing for 3.6.3
2023-10-01 17:50:27 +02:00
Proddy
7748f67b9a preparing for 3.6.3 2023-10-01 17:50:09 +02:00
Proddy
df9f75a5c9 updated yarn for 3.6.2 2023-10-01 17:42:54 +02:00
Proddy
7bd8710eb6 3.6.2 2023-10-01 17:40:09 +02:00
Proddy
32f2c6d341 Merge remote-tracking branch 'origin/dev' 2023-10-01 17:40:02 +02:00
Proddy
20d8b6400f Merge pull request #1311 from proddy/dev
minor changes
2023-10-01 17:32:50 +02:00
Proddy
d3b086a675 added more API tests 2023-10-01 17:32:16 +02:00
Proddy
e1ee83b907 update with 3.6.2 2023-10-01 17:31:43 +02:00
Proddy
763a2eaab1 bump version 2023-10-01 17:31:31 +02:00
Proddy
5d78f1c814 Reset command renamed to reset 2023-10-01 17:31:24 +02:00
Proddy
3f99806ddd sending dash/- to reset command doesn't error 2023-10-01 17:31:11 +02:00
Proddy
bc0a90ee41 update packages 2023-10-01 17:30:54 +02:00
Proddy
3900b8fc94 log API call 2023-10-01 17:30:47 +02:00
Proddy
f9a53cf320 Merge pull request #1309 from MichaelDvP/dev
Some small corrections
2023-09-29 11:18:24 +02:00
MichaelDvP
99467558b4 check each single nvs values before writing it 2023-09-29 10:21:20 +02:00
MichaelDvP
2e25e46f6f temperaturesensor commands only if enabled (gpio != 0) 2023-09-29 10:20:17 +02:00
MichaelDvP
3a1b7cae67 avoid possible div-zero 2023-09-29 10:19:34 +02:00
Proddy
5bc3bd23e2 Merge pull request #1306 from proddy/dev
small changes
2023-09-25 09:15:44 +02:00
Proddy
a04f4d784b fix standalone build and make - ignore warning when comparing signed/unsigned ints 2023-09-25 09:15:10 +02:00
Proddy
9c423dc886 remove comment 2023-09-25 09:14:40 +02:00
Proddy
1b0f840d18 update script 2023-09-25 09:14:29 +02:00
Proddy
21eaf70181 package update 2023-09-25 09:14:21 +02:00
Proddy
14f2cd4bee package update 2023-09-25 09:14:04 +02:00
Proddy
917e268ac9 add TODO on possible memory out-of-bounds error 2023-09-23 18:41:54 +02:00
Proddy
41228e894a lint warning work-around 2023-09-23 18:41:37 +02:00
Proddy
365c95991b revert default test to general 2023-09-23 18:41:11 +02:00
Proddy
ba4ebe221c make compile standalone on linux 2023-09-23 18:40:58 +02:00
Proddy
3ab5946e38 package updates 2023-09-23 18:40:37 +02:00
Proddy
f427288c06 minor changes to sonar checks 2023-09-23 18:40:29 +02:00
Proddy
398cbadb64 Merge pull request #1304 from MichaelDvP/dev
burner settings use min/max from telegram 4, fix max for values < 0
2023-09-21 20:31:06 +02:00
MichaelDvP
38a1c9e9d7 Merge branch 'emsesp:dev' into dev 2023-09-21 18:56:42 +02:00
MichaelDvP
5abfdf1177 burner settings use min/max from telegram 4, fix max for values < 0 2023-09-21 16:56:45 +02:00
Proddy
385d2377db Merge pull request #1303 from proddy/dev
disabled entity values shown in white text in web
2023-09-20 23:10:41 +02:00
proddy
6655035561 autoformatting 2023-09-20 23:09:29 +02:00
proddy
755408e6aa standalone build works 2023-09-20 23:09:21 +02:00
proddy
df70ed0062 remove comments 2023-09-20 23:09:10 +02:00
proddy
b893290b62 disabled entity values shown in white text 2023-09-20 23:09:02 +02:00
Proddy
96ff5ed123 Merge pull request #1302 from MichaelDvP/dev2
network connection and powerentities
2023-09-20 20:08:22 +02:00
MichaelDvP
dcdd8d9e44 cleanup, adapt comments, packages 2023-09-20 17:56:39 +02:00
MichaelDvP
5c484d58dc allow empty response in webAPI 2023-09-20 16:03:05 +02:00
MichaelDvP
96bf1a32ee v3.6.2-dev.2, changelog 2023-09-20 12:30:09 +02:00
MichaelDvP
ad81f84c02 tag more boiler dhw values 2023-09-20 12:25:49 +02:00
MichaelDvP
529b46d776 update packages needs changed svg handling 2023-09-20 12:18:32 +02:00
MichaelDvP
bbc5bc8585 sync mqtt client with origin 2023-09-20 12:17:24 +02:00
MichaelDvP
9c33b5cb8b limit mqtt queue to 300 2023-09-20 12:16:36 +02:00
MichaelDvP
ba7ceca798 Network, reconnect without waiting 2023-09-20 12:16:15 +02:00
MichaelDvP
4824152ae5 empty json instead of "no entries" 2023-09-19 19:46:46 +02:00
Proddy
af935d8124 Merge pull request #1298 from proddy/dev
some refactoring and change #1297
2023-09-19 16:47:30 +02:00
MichaelDvP
951e706fee add custom to "show devices" 2023-09-19 16:17:21 +02:00
MichaelDvP
9f1002df9a remove channel from networkSettings 2023-09-19 15:19:45 +02:00
MichaelDvP
6ab2135cea show commands always include internal devices. 2023-09-19 14:40:59 +02:00
MichaelDvP
e6bcdede73 Merge branch 'dev' of https://github.com/proddy/EMS-ESP32 into dev 2023-09-19 14:31:25 +02:00
MichaelDvP
8b136ddefe "no entries" is valid command execution 2023-09-19 14:22:38 +02:00
Proddy
ca9ac86fde package updates 2023-09-19 07:52:12 +02:00
MichaelDvP
42a4c792ad dont queue publish on change if not connected, keep flag 2023-09-18 16:24:24 +02:00
MichaelDvP
a6b0c74f5f add message "no entries" to analog/temperature/custom/sccheduler 2023-09-18 16:21:58 +02:00
MichaelDvP
09e2945c15 add BSSID and Channel to network settings, full_scan 2023-09-18 12:29:01 +02:00
Proddy
a3f05cb08b /api/custom show {} if no Custom Entities configured instead of an error #1297 2023-09-17 14:27:33 +02:00
Proddy
0ab573225d fix typos 2023-09-17 14:27:15 +02:00
Proddy
4c8fd45908 add test for custom entities 2023-09-17 14:27:04 +02:00
Proddy
8bb703fafe package update 2023-09-17 14:26:53 +02:00
Proddy
9cdeb7c07a refactor custom vs customizations 2023-09-17 14:26:24 +02:00
MichaelDvP
8d4b43e9f6 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-09-17 09:35:44 +02:00
MichaelDvP
d8c298f6fe network init 2023-09-17 09:27:08 +02:00
MichaelDvP
8a16566f53 translations 2023-09-17 09:22:57 +02:00
MichaelDvP
9d3456cb3a show scheduler/custom always 2023-09-17 09:22:25 +02:00
MichaelDvP
7310db6426 update packages 2023-09-17 09:21:47 +02:00
Proddy
ac08bb6037 add +x to execute scripts 2023-09-16 09:40:09 +02:00
Proddy
776f72650f update dump_entities.csv 2023-09-16 09:39:57 +02:00
Proddy
0eb96e764c Merge pull request #1296 from proddy/dev
3.6.2-dev-0
2023-09-16 09:27:09 +02:00
Proddy
ec939dfc2e rename 3.6.2-dev-0 2023-09-16 09:26:36 +02:00
Proddy
809b6be79c update packages 2023-09-16 09:26:14 +02:00
Proddy
34f87a0a21 Merge pull request #1292 from proddy/dev
use espressif core 2.0.12 via Tasmota for 4MB build
2023-09-10 13:18:46 +02:00
Proddy
bc4418755e use espressif core 2.0.12 via Tasmota for 4MB build 2023-09-10 13:18:12 +02:00
Proddy
d24742facd package update 2023-09-10 13:17:53 +02:00
MichaelDvP
9c16e2008e revert 'topic' to 't' 2023-09-09 18:11:58 +02:00
MichaelDvP
6a7a9636ac set esp32s2, esp32c3 to tasmota platform 2023-09-09 16:49:42 +02:00
MichaelDvP
5e76bfa210 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-09-09 16:46:53 +02:00
Proddy
4da45a7240 Merge pull request #1291 from proddy/dev
preparing 3.7.0
2023-09-09 15:02:12 +02:00
Proddy
3c84a1ced1 preparing 3.7.0 2023-09-09 15:00:09 +02:00
MichaelDvP
10c8c2b4a7 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-09-08 10:31:34 +02:00
MichaelDvP
c19345c345 color wifiicon in selector 2023-09-08 10:29:24 +02:00
MichaelDvP
6376ed2361 platform: esp32 use tasmota w/o tsl, S3 use development 2023-09-06 13:18:49 +02:00
MichaelDvP
04e43d5d41 nomPower is always editable 2023-09-06 12:46:38 +02:00
MichaelDvP
0ba5d8e2bd update packages 2023-09-06 12:25:31 +02:00
MichaelDvP
95b8e79624 use tasmota modified platform, v3.6.1-dev.1a 2023-09-06 12:05:26 +02:00
MichaelDvP
e9c3f8c6da Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-09-06 12:04:39 +02:00
MichaelDvP
1c4da53e75 publish energy in api/mqtt with 2 digits 2023-09-05 11:37:26 +02:00
MichaelDvP
09a15727c7 change ha-mqtt tto topic 2023-09-04 19:01:52 +02:00
MichaelDvP
f1034f4230 energy values as HA sensors with classes, v3.6.1-dev0e 2023-09-04 16:37:58 +02:00
MichaelDvP
06e9b8d303 round energy values to full kWh 2023-09-04 13:17:21 +02:00
MichaelDvP
b912779ef9 fix max for ULONG values, save counters every hour, 3.6.1-dev0c 2023-09-04 12:21:53 +02:00
MichaelDvP
ced63a6eb0 v3.6.1-dev0b, changelog 2023-09-03 17:54:39 +02:00
MichaelDvP
a5f5d36871 analogsensor counter store to nvs 2023-09-03 17:54:08 +02:00
MichaelDvP
bd92345793 boiler energy counter, stored in nvs 2023-09-03 17:53:48 +02:00
MichaelDvP
4c1b66279d update packages 2023-09-03 17:25:30 +02:00
MichaelDvP
fcf16eec4f HA register all entities for Custom and Scheduler 2023-09-03 17:25:14 +02:00
MichaelDvP
508f18c29b Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-09-03 16:07:30 +02:00
MichaelDvP
b165e1c20c fix read int from webpage 2023-09-03 16:07:21 +02:00
MichaelDvP
6173e94cc0 add back process dest, fixes #1275, v3.6.1-dev0a 2023-09-02 12:29:26 +02:00
520 changed files with 31105 additions and 29505 deletions

View File

@@ -0,0 +1,24 @@
name: 'github-releases-to-discord'
on:
workflow_dispatch:
release:
types: [published]
jobs:
github-releases-to-discord:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Github Releases To Discord
uses: SethCohen/github-releases-to-discord@v1.13.1
with:
webhook_url: ${{ secrets.WEBHOOK_URL }}
color: '2105893'
username: 'Release Changelog'
avatar_url: 'https://cdn.discordapp.com/icons/816637840644505620/0b14718532d855c452903851b4f0c9a2.png'
content: '||@everyone||'
footer_title: 'Changelog'
footer_icon_url: 'https://cdn.discordapp.com/icons/816637840644505620/0b14718532d855c452903851b4f0c9a2.png'
footer_timestamp: true

View File

@@ -12,8 +12,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/setup-python@v4 - uses: actions/setup-python@v4
with:
python-version: '3.11'
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: '18' node-version: '18'
@@ -33,9 +35,10 @@ jobs:
run: | run: |
cd interface cd interface
yarn install yarn install
yarn run typesafe-i18n --no-watch yarn typesafe-i18n --no-watch
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
yarn run build yarn build
yarn webUI
- name: Build firmware - name: Build firmware
run: | run: |
@@ -45,6 +48,10 @@ jobs:
run: | run: |
platformio run -e ci_s3 platformio run -e ci_s3
- name: Build E32V2 firmware
run: |
platformio run -e ci_16M
- name: Create a GH Release - name: Create a GH Release
id: 'automatic_releases' id: 'automatic_releases'
uses: 'marvinpinto/action-automatic-releases@latest' uses: 'marvinpinto/action-automatic-releases@latest'

View File

@@ -12,9 +12,9 @@ jobs:
# if: github.repository_owner == 'emsesp' # if: github.repository_owner == 'emsesp'
# if: github.repository == 'emsesp/EMS-ESP32' # if: github.repository == 'emsesp/EMS-ESP32'
env: env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory BUILD_WRAPPER_OUT_DIR: bw-output
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install sonar-scanner and build-wrapper - name: Install sonar-scanner and build-wrapper

View File

@@ -11,8 +11,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/setup-python@v4 - uses: actions/setup-python@v4
with:
python-version: '3.11'
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: '18' node-version: '18'
@@ -28,9 +30,10 @@ jobs:
run: | run: |
cd interface cd interface
yarn install yarn install
yarn run typesafe-i18n --no-watch yarn typesafe-i18n --no-watch
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
yarn run build yarn build
yarn webUI
- name: Build firmware - name: Build firmware
run: | run: |

View File

@@ -12,8 +12,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/setup-python@v4 - uses: actions/setup-python@v4
with:
python-version: '3.11'
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: '18' node-version: '18'
@@ -33,9 +35,10 @@ jobs:
run: | run: |
cd interface cd interface
yarn install yarn install
yarn run typesafe-i18n --no-watch yarn typesafe-i18n --no-watch
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
yarn run build yarn build
yarn webUI
- name: Build firmware - name: Build firmware
run: | run: |

20
.gitignore vendored
View File

@@ -1,8 +1,5 @@
# vscode # vscode
.vscode/c_cpp_properties.json .vscode/*
.vscode/extensions.json
.vscode/launch.json
# .vscode/settings.json
# c++ compiling # c++ compiling
.clang_complete .clang_complete
@@ -12,11 +9,11 @@ cppcheck.out.xml
# platformio # platformio
.pio .pio
pio_local.ini pio_local.ini
*_old
# OS specific # OS specific
.DS_Store .DS_Store
*Thumbs.db *Thumbs.db
emsesp
# web specfic # web specfic
build/ build/
@@ -36,12 +33,15 @@ stats.html
!.yarn/releases !.yarn/releases
!.yarn/sdks !.yarn/sdks
!.yarn/versions !.yarn/versions
yarn.lock
interface/analyse.html
interface/vite.config.ts.timestamp*
# scripts # scripts
test.sh test.sh
scripts/run.sh scripts/run.sh
scripts/__pycache__ scripts/__pycache__
/scripts/stackdmp.txt scripts/stackdmp.txt
# i18n generated files # i18n generated files
interface/src/i18n/i18n-react.tsx interface/src/i18n/i18n-react.tsx
@@ -53,8 +53,8 @@ interface/src/i18n/i18n-util.async.ts
# sonar # sonar
.scannerwork/ .scannerwork/
sonar/ sonar/
build_wrapper_output_directory/ bw-output/
# testing
emsesp
# entity dump results
# dump_entities.csv
# dump_entities.xls*

View File

@@ -2,8 +2,6 @@
// See http://go.microsoft.com/fwlink/?LinkId=827846 // See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format // for the documentation about the extensions.json format
"recommendations": [ "recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"platformio.platformio-ide" "platformio.platformio-ide"
], ],
"unwantedRecommendations": [ "unwantedRecommendations": [

46
.vscode/settings.json vendored
View File

@@ -1,46 +0,0 @@
{
"search.exclude": {
"**/.yarn": true,
"**/.pnp.*": true
},
"editor.codeActionsOnSave": {
"source.fixAll": true
// "source.organizeImports": true
},
"eslint.nodePath": "interface/.yarn/sdks",
"eslint.workingDirectories": ["interface"],
"prettier.prettierPath": "",
"typescript.tsdk": "interface/.yarn/sdks/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"files.associations": {
"*.tsx": "typescriptreact",
"*.tcc": "cpp",
"optional": "cpp",
"istream": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"system_error": "cpp",
"array": "cpp",
"functional": "cpp",
"regex": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"string": "cpp",
"string_view": "cpp"
},
"todo-tree.filtering.excludeGlobs": [
"**/vendor/**",
"**/node_modules/**",
"**/dist/**",
"**/bower_components/**",
"**/build/**",
"**/.vscode/**",
"**/.github/**",
"**/_output/**",
"**/*.min.*",
"**/*.map",
"**/ArduinoJson/**"
],
"cSpell.enableFiletypes": ["!cpp"]
}

18
.vscode/tasks.json vendored
View File

@@ -1,18 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "build standalone emsesp",
"command": "make",
"args": [],
"problemMatcher": ["$gcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@@ -5,7 +5,118 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# [3.6.1] September 9 2023 ## [3.6.5] March 23 2024
## **IMPORTANT! BREAKING CHANGES**
- The Wifi Tx Power setting in Network Settings will be reset to Auto
## Added
- thermostat boost mode and boost time [#1446](https://github.com/emsesp/EMS-ESP32/issues/1446)
- heatpump energy meters [#1463](https://github.com/emsesp/EMS-ESP32/issues/1463)
- heatpump max power [#1475](https://github.com/emsesp/EMS-ESP32/issues/1475)
- checkbox for MQTT-TLS enable [#1474](https://github.com/emsesp/EMS-ESP32/issues/1474)
- added SK (Slovak) language. Thanks @misa1515
- CPU info [#1497](https://github.com/emsesp/EMS-ESP32/pull/1497)
- Show network hostname in Web UI under Network Status
- Improved HA Discovery so each section (EMS device, Scheduler, Analog, Temperature, Custom, Shower) have their own section
- boiler Bosch C1200W, id 12, [#1536](https://github.com/emsesp/EMS-ESP32/issues/1536)
- mixer MM100 telegram 0x2CC [#1554](https://github.com/emsesp/EMS-ESP32/issues/1554)
- boiler hpSetDiffPressure [#1563](https://github.com/emsesp/EMS-ESP32/issues/1563)
- custom variables [#1423](https://github.com/emsesp/EMS-ESP32/issues/1423)
- weather compensation [#1642](https://github.com/emsesp/EMS-ESP32/issues/1642)
- env and partitions for DevKitC-1-N32R8 [#1635](https://github.com/emsesp/EMS-ESP32/discussions/1635)
- command `restart partitionname` and button long press to start with other partition [#1657](https://github.com/emsesp/EMS-ESP32/issues/1657)
- command `set service <mqtt|ota|ntp|ap> <enable|disable>` [#1663](https://github.com/emsesp/EMS-ESP32/issues/1663)
## Fixed
- exhaust temperature for some boilers
- add back boil2hyst [#1477](https://github.com/emsesp/EMS-ESP32/issues/1477)
- subscribed MQTT topics not detecting changes by EMS-ESP [#1494](https://github.com/emsesp/EMS-ESP32/issues/1494)
- changed HA name and grouping to be consistent [#1528](https://github.com/emsesp/EMS-ESP32/issues/1528)
- MQTT autodiscovery in Domoticz not working [#1360](https://github.com/emsesp/EMS-ESP32/issues/1528)
- dhw comfort for new ems+, [#1495](https://github.com/emsesp/EMS-ESP32/issues/1495)
- added writeable icon to Web's Custom Entity page for each entity shown in the table
- Wifi Tx Power not adjusted [#1614](https://github.com/emsesp/EMS-ESP32/issues/1614)
- MQTT discovery of custom entity doesn't consider type of data [#1587](https://github.com/emsesp/EMS-ESP32/issues/1587)
- WiFi TxPower wasn't correctly used. Added an 'Auto' setting, which is the default.
- dns w/wo IPv6 [#1644](https://github.com/emsesp/EMS-ESP32/issues/1644)
## Changed
- HA don't set entity_category to Diagnostic/Configuration for EMS entities [#1459](https://github.com/emsesp/EMS-ESP32/discussions/1459)
- upgraded ArduinoJson to 7.0.0 #1538 and then 7.0.2
- small changes to the API for analog and temperature sensors
- Length of mqtt Broker adress [#1619](https://github.com/emsesp/EMS-ESP32/issues/1619)
- C++ optimizations - see <https://github.com/emsesp/EMS-ESP32/pull/1615>
- Send MQTT heartbeat immediately after connection [#1628](https://github.com/emsesp/EMS-ESP32/issues/1628)
- 16MB partitions with second nvs, larger FS, Coredump, optional factory partition
- stop fetching empty telegrams after 5 min
## [3.6.4] November 24 2023
## **IMPORTANT! BREAKING CHANGES**
Writeable Text entities have moved from type `sensor` to `text` in Home Assistant to make them also editable within an HA dashboard. Examples are `datetime`, `holidays`, `switchtime`, `vacations`, `maintenancedate`. You will need to manually remove any old discovery topics from your MQTT broker using an application like MQTT Explorer.
## Added
- humidity for ventilation devices
- telegrams for RC100H, hc2, etc. (seen on discord, not tested)
- names for BC400, GB192i.2, read temperatures for low loss header and heatblock [#1317](https://github.com/emsesp/EMS-ESP32/discussions/1317)
- option for `forceheatingoff` [#1262](https://github.com/emsesp/EMS-ESP32/issues/1262)
- remote thermostat emulation RC100H for RC3xx [#1278](https://github.com/emsesp/EMS-ESP32/discussions/1278)
- shower_data MQTT payload contains the timestamp [#1329](https://github.com/emsesp/EMS-ESP32/issues/1329)
- HA discovery for writeable text entities [#1337](https://github.com/emsesp/EMS-ESP32/pull/1377)
- autodetect board_profile, store in nvs, add telnet command option, add E32V2
- heat pump high res energy counters [#1348, #1349. #1350](https://github.com/emsesp/EMS-ESP32/issues/1348)
- optional bssid in network settings
- extension module EM100 [#1315](https://github.com/emsesp/EMS-ESP32/discussions/1315)
- digital_out with new options for polarity and startup state
- added 'system allvalues' command that dumps all the EMS device values, plus sensors and any custom entities
## Fixed
- remove command `remoteseltemp`, thermostat accept it only from remote thermostat
- shower_data MQTT payload contains the timestamp [#1329](https://github.com/emsesp/EMS-ESP32/issues/1329)
- fixed helper text in Web Device Entity dialog box for numerical ranges
- MQTT base with paths not working in HA [#1393](https://github.com/emsesp/EMS-ESP32/issues/1393)
- set/read thermostat mode for RC100-RC300, [#1440](https://github.com/emsesp/EMS-ESP32/issues/1440) [#1442](https://github.com/emsesp/EMS-ESP32/issues/1442)
- some setting commands for ems-boiler have used wrong ems+ telegram in 3.6.3
## Changed
- update to platform 6.4.0, arduino 2.0.14 / idf 4.4.6
- small changes for arduino 3.0.0 / idf 5.1 compatibility (not backward compatible to platform 6.3.2 and before)
- AP start after 10 sec, stay until station/eth connected
- tested wifi-all-channel-scan (3.6.3-dev4 a-e), removed again because of connect issues
- mqtt disconnect stops queue
## [3.6.2] October 1 2023
## **IMPORTANT! BREAKING CHANGES**
## Added
- Power entities
- Optional input of BSSID for AP connection
- Return empty json if no entries in scheduler/custom/analogsensor/temperaturesensor
## Fixed
- Wifi full scan to get strongest AP
- Add missing dhw tags
- Sending a dash/- to the Reset command doesn't return an error [#1308](https://github.com/emsesp/EMS-ESP32/discussions/1308)
## Changed
- MQTT queue max 300 messages, check heap and maxAlloc
- API call commands are logged as WARN in the log
- Reset Command renamed to 'reset' in lowercase in EN
## [3.6.1] September 9 2023
## **IMPORTANT! BREAKING CHANGES** ## **IMPORTANT! BREAKING CHANGES**
@@ -13,7 +124,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Added ## Added
- show WiFi rssi in Network Status Page, show quality as color - Show WiFi rssi in Network Status Page, show quality as color
## Fixed ## Fixed
@@ -22,9 +133,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Changed ## Changed
- mqtt free mem check set to 60 kb - MQTT free mem check set to 60 kb
- small cosmetic changes to Searching in Customization web page - Small cosmetic changes to Searching in Customization web page
- updated to espressif32@6.4.0 - Updated to espressif32@6.4.0
# [3.6.0] August 13 2023 # [3.6.0] August 13 2023
@@ -36,7 +147,7 @@ There are breaking changes between 3.5.x and earlier versions of 3.6.0. Please r
## Added ## Added
- Workaround for better Domoticz MQTT intergration? [#904](https://github.com/emsesp/EMS-ESP32/issues/904) - Workaround for better Domoticz MQTT integration? [#904](https://github.com/emsesp/EMS-ESP32/issues/904)
- Show MAC address without connecting to network enhancement [#933](https://github.com/emsesp/EMS-ESP32/issues/933) - Show MAC address without connecting to network enhancement [#933](https://github.com/emsesp/EMS-ESP32/issues/933)
- Warn user in WebUI of unsaved changes [#911](https://github.com/emsesp/EMS-ESP32/issues/911) - Warn user in WebUI of unsaved changes [#911](https://github.com/emsesp/EMS-ESP32/issues/911)
- Detect old Tado thermostat, device-id 0x19, no entities - Detect old Tado thermostat, device-id 0x19, no entities
@@ -175,7 +286,7 @@ There are breaking changes between 3.5.x and earlier versions of 3.6.0. Please r
- fix Table resizing in WebUI [#519](https://github.com/emsesp/EMS-ESP32/issues/519) - fix Table resizing in WebUI [#519](https://github.com/emsesp/EMS-ESP32/issues/519)
- allow larger customization files [#570](https://github.com/emsesp/EMS-ESP32/issues/570) - allow larger customization files [#570](https://github.com/emsesp/EMS-ESP32/issues/570)
- losing entitiy wwcomfort [#581](https://github.com/emsesp/EMS-ESP32/issues/581) - losing entity wwcomfort [#581](https://github.com/emsesp/EMS-ESP32/issues/581)
## Changed ## Changed
@@ -202,7 +313,7 @@ There are breaking changes between 3.5.x and earlier versions of 3.6.0. Please r
- WebUI optimizations, updated look&feel and better performance [#124](https://github.com/emsesp/EMS-ESP32/issues/124) - WebUI optimizations, updated look&feel and better performance [#124](https://github.com/emsesp/EMS-ESP32/issues/124)
- Auto refresh of WebUI after successful firmware upload [#178](https://github.com/emsesp/EMS-ESP32/issues/178) - Auto refresh of WebUI after successful firmware upload [#178](https://github.com/emsesp/EMS-ESP32/issues/178)
- New Customization Service in WebUI. First feature is the ability to enable/disabled Enitites (device values) from EMS devices [#206](https://github.com/emsesp/EMS-ESP32/issues/206) - New Customization Service in WebUI. First feature is the ability to enable/disabled Entities (device values) from EMS devices [#206](https://github.com/emsesp/EMS-ESP32/issues/206)
- Option to disable Telnet Console [#209](https://github.com/emsesp/EMS-ESP32/issues/209) - Option to disable Telnet Console [#209](https://github.com/emsesp/EMS-ESP32/issues/209)
- Added Hide SSID, Max Clients and Preferred Channel to Access Point - Added Hide SSID, Max Clients and Preferred Channel to Access Point
- Merged in MichaelDvP's changes like Fahrenheit conversion, publish single (for IOBroker) and a few other critical optimizations - Merged in MichaelDvP's changes like Fahrenheit conversion, publish single (for IOBroker) and a few other critical optimizations

View File

@@ -1,22 +1,11 @@
# Changelog # Changelog
## [3.6.1] ## [3.x]
## **IMPORTANT! BREAKING CHANGES** ## **IMPORTANT! BREAKING CHANGES**
- `shower_data` MQTT topic shows duration is seconds (was previously a full english sentence)
## Added ## Added
- show WiFi rssi in Network Status Page, show quality as color
## Fixed ## Fixed
- Issue in espMqttClient causing a memory leak when MQTT broker is disconnected due to network unavailability [#1264](https://github.com/emsesp/EMS-ESP32/issues/1264)
- Using MQTT enum values correctly formatted in MQTT Discovery [#1280](https://github.com/emsesp/EMS-ESP32/issues/1280)
## Changed ## Changed
- mqtt free mem check set to 60 kb
- small cosmetic changes to Searching in Customization web page
- updated to espressif32@6.4.0

View File

@@ -42,7 +42,7 @@ DEFINES += -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DAR
DEFINES += -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_TEST -D__linux__ -DEMC_RX_BUFFER_SIZE=1500 DEFINES += -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_TEST -D__linux__ -DEMC_RX_BUFFER_SIZE=1500
DEFINES += $(ARGS) DEFINES += $(ARGS)
DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.7.0-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.5-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\"
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Sources & Files # Sources & Files
@@ -81,7 +81,7 @@ CPPFLAGS += -g3
CPPFLAGS += -Os CPPFLAGS += -Os
CFLAGS += $(CPPFLAGS) CFLAGS += $(CPPFLAGS)
CFLAGS += -Wall -Wextra -Werror -Wswitch-enum -Wno-unused-parameter -Wno-inconsistent-missing-override -Wno-missing-braces -Wno-unused-lambda-capture CFLAGS += -Wall -Wextra -Werror -Wswitch-enum -Wno-unused-parameter -Wno-inconsistent-missing-override -Wno-missing-braces -Wno-unused-lambda-capture -Wno-sign-compare
CXXFLAGS += $(CFLAGS) -MMD CXXFLAGS += $(CFLAGS) -MMD

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,8 @@
# Name, Type, SubType, Offset, Size, Flags # Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000, nvs, data, nvs, 0x9000, 0x005000,
otadata, data, ota, , 0x2000, otadata, data, ota, , 0x002000,
app0, app, ota_0, , 0x7F0000, app0, app, ota_0, , 0x5D0000,
app1, app, ota_1, , 0x7F0000, app1, app, ota_1, , 0x5D0000,
spiffs, data, spiffs, , 64K, nvs1, data, nvs, , 0x040000,
spiffs, data, spiffs, , 0x400000,
coredump, data, coredump,, 0x010000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000 0x005000
3 otadata data ota 0x2000 0x002000
4 app0 app ota_0 0x7F0000 0x5D0000
5 app1 app ota_1 0x7F0000 0x5D0000
6 spiffs nvs1 data spiffs nvs 64K 0x040000
7 spiffs data spiffs 0x400000
8 coredump data coredump 0x010000

View File

@@ -0,0 +1,9 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x005000,
otadata, data, ota, , 0x002000,
boot, app, factory, , 0x280000,
app0, app, ota_0, , 0x590000,
app1, app, ota_1, , 0x590000,
nvs1, data, nvs, , 0x040000,
spiffs, data, spiffs, , 0x200000,
coredump, data, coredump,, 0x010000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x005000
3 otadata data ota 0x002000
4 boot app factory 0x280000
5 app0 app ota_0 0x590000
6 app1 app ota_1 0x590000
7 nvs1 data nvs 0x040000
8 spiffs data spiffs 0x200000
9 coredump data coredump 0x010000

8
esp32_partition_32M.csv Normal file
View File

@@ -0,0 +1,8 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x005000,
otadata, data, ota, , 0x002000,
app0, app, ota_0, , 0xDD0000,
app1, app, ota_1, , 0xDD0000,
nvs1, data, nvs, , 0x040000,
spiffs, data, spiffs, , 0x400000,
coredump, data, coredump,, 0x010000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x005000
3 otadata data ota 0x002000
4 app0 app ota_0 0xDD0000
5 app1 app ota_1 0xDD0000
6 nvs1 data nvs 0x040000
7 spiffs data spiffs 0x400000
8 coredump data coredump 0x010000

View File

@@ -36,7 +36,6 @@ build_flags =
-D FACTORY_MQTT_PORT=1883 -D FACTORY_MQTT_PORT=1883
-D FACTORY_MQTT_USERNAME=\"\" -D FACTORY_MQTT_USERNAME=\"\"
-D FACTORY_MQTT_PASSWORD=\"\" -D FACTORY_MQTT_PASSWORD=\"\"
-D FACTORY_MQTT_CLIENT_ID=\"ems-esp\"
-D FACTORY_MQTT_KEEP_ALIVE=60 -D FACTORY_MQTT_KEEP_ALIVE=60
-D FACTORY_MQTT_CLEAN_SESSION=false -D FACTORY_MQTT_CLEAN_SESSION=false
-D FACTORY_MQTT_MAX_TOPIC_LENGTH=128 -D FACTORY_MQTT_MAX_TOPIC_LENGTH=128

View File

@@ -5,8 +5,8 @@
}, },
"extends": [ "extends": [
"eslint:recommended", "eslint:recommended",
"airbnb/hooks", // "airbnb/hooks",
"airbnb-typescript", // "airbnb-typescript",
"plugin:react/recommended", "plugin:react/recommended",
"plugin:react/jsx-runtime", "plugin:react/jsx-runtime",
"plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

893
interface/.yarn/releases/yarn-4.1.1.cjs vendored Executable file

File diff suppressed because one or more lines are too long

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require eslint/bin/eslint.js
require(absPnpApiPath).setup();
}
}
// Defer to the real eslint/bin/eslint.js your application uses
module.exports = absRequire(`eslint/bin/eslint.js`);

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require eslint
require(absPnpApiPath).setup();
}
}
// Defer to the real eslint your application uses
module.exports = absRequire(`eslint`);

View File

@@ -1,6 +0,0 @@
{
"name": "eslint",
"version": "8.36.0-sdk",
"main": "./lib/api.js",
"type": "commonjs"
}

View File

@@ -1,5 +0,0 @@
# This file is automatically generated by @yarnpkg/sdks.
# Manual changes might be lost!
integrations:
- vscode

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require prettier/index.js
require(absPnpApiPath).setup();
}
}
// Defer to the real prettier/index.js your application uses
module.exports = absRequire(`prettier/index.js`);

View File

@@ -1,6 +0,0 @@
{
"name": "prettier",
"version": "2.8.7-sdk",
"main": "./index.js",
"type": "commonjs"
}

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/bin/tsc
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/bin/tsc your application uses
module.exports = absRequire(`typescript/bin/tsc`);

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/bin/tsserver
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/bin/tsserver your application uses
module.exports = absRequire(`typescript/bin/tsserver`);

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/tsc.js
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/tsc.js your application uses
module.exports = absRequire(`typescript/lib/tsc.js`);

View File

@@ -1,223 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
const moduleWrapper = tsserver => {
if (!process.versions.pnp) {
return tsserver;
}
const {isAbsolute} = require(`path`);
const pnpApi = require(`pnpapi`);
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
const isPortal = str => str.startsWith("portal:/");
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
return `${locator.name}@${locator.reference}`;
}));
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
// doesn't understand. This layer makes sure to remove the protocol
// before forwarding it to TS, and to add it back on all returned paths.
function toEditorPath(str) {
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
// We also take the opportunity to turn virtual paths into physical ones;
// this makes it much easier to work with workspaces that list peer
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
// file instances instead of the real ones.
//
// We only do this to modules owned by the the dependency tree roots.
// This avoids breaking the resolution when jumping inside a vendor
// with peer dep (otherwise jumping into react-dom would show resolution
// errors on react).
//
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
if (resolved) {
const locator = pnpApi.findPackageLocator(resolved);
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
str = resolved;
}
}
str = normalize(str);
if (str.match(/\.zip\//)) {
switch (hostInfo) {
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
// VSCode only adds it automatically for supported schemes,
// so we have to do it manually for the `zip` scheme.
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
//
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
//
// 2021-10-08: VSCode changed the format in 1.61.
// Before | ^zip:/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
// 2022-04-06: VSCode changed the format in 1.66.
// Before | ^/zip//c:/foo/bar.zip/package.json
// After | ^/zip/c:/foo/bar.zip/package.json
//
// 2022-05-06: VSCode changed the format in 1.68
// Before | ^/zip/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
case `vscode <1.61`: {
str = `^zip:${str}`;
} break;
case `vscode <1.66`: {
str = `^/zip/${str}`;
} break;
case `vscode <1.68`: {
str = `^/zip${str}`;
} break;
case `vscode`: {
str = `^/zip/${str}`;
} break;
// To make "go to definition" work,
// We have to resolve the actual file system path from virtual path
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
case `coc-nvim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = resolve(`zipfile:${str}`);
} break;
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
// We have to resolve the actual file system path from virtual path,
// everything else is up to neovim
case `neovim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = `zipfile://${str}`;
} break;
default: {
str = `zip:${str}`;
} break;
}
}
}
return str;
}
function fromEditorPath(str) {
switch (hostInfo) {
case `coc-nvim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
// So in order to convert it back, we use .* to match all the thing
// before `zipfile:`
return process.platform === `win32`
? str.replace(/^.*zipfile:\//, ``)
: str.replace(/^.*zipfile:/, ``);
} break;
case `neovim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
return str.replace(/^zipfile:\/\//, ``);
} break;
case `vscode`:
default: {
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
} break;
}
}
// Force enable 'allowLocalPluginLoads'
// TypeScript tries to resolve plugins using a path relative to itself
// which doesn't work when using the global cache
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
// TypeScript already does local loads and if this code is running the user trusts the workspace
// https://github.com/microsoft/vscode/issues/45856
const ConfiguredProject = tsserver.server.ConfiguredProject;
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
this.projectService.allowLocalPluginLoads = true;
return originalEnablePluginsWithOptions.apply(this, arguments);
};
// And here is the point where we hijack the VSCode <-> TS communications
// by adding ourselves in the middle. We locate everything that looks
// like an absolute path of ours and normalize it.
const Session = tsserver.server.Session;
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
let hostInfo = `unknown`;
Object.assign(Session.prototype, {
onMessage(/** @type {string | object} */ message) {
const isStringMessage = typeof message === 'string';
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
if (
parsedMessage != null &&
typeof parsedMessage === `object` &&
parsedMessage.arguments &&
typeof parsedMessage.arguments.hostInfo === `string`
) {
hostInfo = parsedMessage.arguments.hostInfo;
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
// The RegExp from https://semver.org/ but without the caret at the start
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
) ?? []).map(Number)
if (major === 1) {
if (minor < 61) {
hostInfo += ` <1.61`;
} else if (minor < 66) {
hostInfo += ` <1.66`;
} else if (minor < 68) {
hostInfo += ` <1.68`;
}
}
}
}
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
return typeof value === 'string' ? fromEditorPath(value) : value;
});
return originalOnMessage.call(
this,
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
);
},
send(/** @type {any} */ msg) {
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
return typeof value === `string` ? toEditorPath(value) : value;
})));
}
});
return tsserver;
};
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/tsserver.js
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/tsserver.js your application uses
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`));

View File

@@ -1,223 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
const moduleWrapper = tsserver => {
if (!process.versions.pnp) {
return tsserver;
}
const {isAbsolute} = require(`path`);
const pnpApi = require(`pnpapi`);
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
const isPortal = str => str.startsWith("portal:/");
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
return `${locator.name}@${locator.reference}`;
}));
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
// doesn't understand. This layer makes sure to remove the protocol
// before forwarding it to TS, and to add it back on all returned paths.
function toEditorPath(str) {
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
// We also take the opportunity to turn virtual paths into physical ones;
// this makes it much easier to work with workspaces that list peer
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
// file instances instead of the real ones.
//
// We only do this to modules owned by the the dependency tree roots.
// This avoids breaking the resolution when jumping inside a vendor
// with peer dep (otherwise jumping into react-dom would show resolution
// errors on react).
//
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
if (resolved) {
const locator = pnpApi.findPackageLocator(resolved);
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
str = resolved;
}
}
str = normalize(str);
if (str.match(/\.zip\//)) {
switch (hostInfo) {
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
// VSCode only adds it automatically for supported schemes,
// so we have to do it manually for the `zip` scheme.
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
//
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
//
// 2021-10-08: VSCode changed the format in 1.61.
// Before | ^zip:/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
// 2022-04-06: VSCode changed the format in 1.66.
// Before | ^/zip//c:/foo/bar.zip/package.json
// After | ^/zip/c:/foo/bar.zip/package.json
//
// 2022-05-06: VSCode changed the format in 1.68
// Before | ^/zip/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
case `vscode <1.61`: {
str = `^zip:${str}`;
} break;
case `vscode <1.66`: {
str = `^/zip/${str}`;
} break;
case `vscode <1.68`: {
str = `^/zip${str}`;
} break;
case `vscode`: {
str = `^/zip/${str}`;
} break;
// To make "go to definition" work,
// We have to resolve the actual file system path from virtual path
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
case `coc-nvim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = resolve(`zipfile:${str}`);
} break;
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
// We have to resolve the actual file system path from virtual path,
// everything else is up to neovim
case `neovim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = `zipfile://${str}`;
} break;
default: {
str = `zip:${str}`;
} break;
}
}
}
return str;
}
function fromEditorPath(str) {
switch (hostInfo) {
case `coc-nvim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
// So in order to convert it back, we use .* to match all the thing
// before `zipfile:`
return process.platform === `win32`
? str.replace(/^.*zipfile:\//, ``)
: str.replace(/^.*zipfile:/, ``);
} break;
case `neovim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
return str.replace(/^zipfile:\/\//, ``);
} break;
case `vscode`:
default: {
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
} break;
}
}
// Force enable 'allowLocalPluginLoads'
// TypeScript tries to resolve plugins using a path relative to itself
// which doesn't work when using the global cache
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
// TypeScript already does local loads and if this code is running the user trusts the workspace
// https://github.com/microsoft/vscode/issues/45856
const ConfiguredProject = tsserver.server.ConfiguredProject;
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
this.projectService.allowLocalPluginLoads = true;
return originalEnablePluginsWithOptions.apply(this, arguments);
};
// And here is the point where we hijack the VSCode <-> TS communications
// by adding ourselves in the middle. We locate everything that looks
// like an absolute path of ours and normalize it.
const Session = tsserver.server.Session;
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
let hostInfo = `unknown`;
Object.assign(Session.prototype, {
onMessage(/** @type {string | object} */ message) {
const isStringMessage = typeof message === 'string';
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
if (
parsedMessage != null &&
typeof parsedMessage === `object` &&
parsedMessage.arguments &&
typeof parsedMessage.arguments.hostInfo === `string`
) {
hostInfo = parsedMessage.arguments.hostInfo;
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
// The RegExp from https://semver.org/ but without the caret at the start
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
) ?? []).map(Number)
if (major === 1) {
if (minor < 61) {
hostInfo += ` <1.61`;
} else if (minor < 66) {
hostInfo += ` <1.66`;
} else if (minor < 68) {
hostInfo += ` <1.68`;
}
}
}
}
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
return typeof value === 'string' ? fromEditorPath(value) : value;
});
return originalOnMessage.call(
this,
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
);
},
send(/** @type {any} */ msg) {
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
return typeof value === `string` ? toEditorPath(value) : value;
})));
}
});
return tsserver;
};
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/tsserverlibrary.js
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/tsserverlibrary.js your application uses
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`));

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/typescript.js
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/typescript.js your application uses
module.exports = absRequire(`typescript/lib/typescript.js`);

View File

@@ -1,6 +0,0 @@
{
"name": "typescript",
"version": "5.0.2-sdk",
"main": "./lib/typescript.js",
"type": "commonjs"
}

View File

@@ -1,14 +1,7 @@
plugins: compressionLevel: mixed
- path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs
spec: '@yarnpkg/plugin-typescript'
yarnPath: .yarn/releases/yarn-3.4.1.cjs enableGlobalCache: false
# uing pnp
# nodeLinker: pnp
# use these if not using PnP and have node_modules
nodeLinker: node-modules nodeLinker: node-modules
compressionLevel: 0
nmMode: hardlinks-local yarnPath: .yarn/releases/yarn-4.1.1.cjs
enableGlobalCache: true

View File

@@ -1,78 +1,78 @@
{ {
"name": "EMS-ESP", "name": "EMS-ESP",
"version": "3.6.0", "version": "3.6.5",
"description": "build EMS-ESP WebUI", "description": "build EMS-ESP WebUI",
"homepage": "https://emsesp.github.io/docs", "homepage": "https://emsesp.github.io/docs",
"author": "proddy", "author": "proddy",
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"type": "module",
"scripts": { "scripts": {
"dev": "vite",
"build": "vite build", "build": "vite build",
"build-hosted": "vite build --mode hosted",
"preview": "vite preview", "preview": "vite preview",
"preview-standalone": "npm-run-all -p preview typesafe-i18n mock-api", "build-hosted": "typesafe-i18n --no-watch && vite build --mode hosted",
"mock-api": "node --watch ../mock-api ../mock-api/server.js", "preview-standalone": "typesafe-i18n --no-watch && vite build && concurrently -c \"auto\" \"npm:mock-api\" \"vite preview\"",
"standalone": "npm-run-all -p dev typesafe-i18n mock-api", "mock-api": "bun --watch ../mock-api/server.ts",
"typesafe-i18n": "typesafe-i18n", "old_mock-api": "bun --watch ../mock-api/server.js",
"standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:mock-api\" \"vite\"",
"old_standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:old_mock-api\" \"vite\"",
"typesafe-i18n": "typesafe-i18n --no-watch",
"webUI": "node progmem-generator.js",
"format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'", "format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'",
"lint": "eslint . --cache --fix" "lint": "eslint . --cache --fix"
}, },
"dependencies": { "dependencies": {
"@alova/adapter-xhr": "^1.0.1", "@alova/adapter-xhr": "^1.0.3",
"@emotion/react": "^11.11.1", "@babel/core": "^7.24.3",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.8", "@mui/icons-material": "^5.15.14",
"@mui/material": "^5.14.8", "@mui/material": "^5.15.14",
"@preact/compat": "^17.1.2",
"@prefresh/vite": "^2.4.1",
"@table-library/react-table-library": "4.1.7", "@table-library/react-table-library": "4.1.7",
"@types/lodash-es": "^4.17.9", "@types/imagemin": "^8.0.5",
"@types/node": "^20.6.0", "@types/lodash-es": "^4.17.12",
"@types/react": "^18.2.21", "@types/node": "^20.11.30",
"@types/react-dom": "^18.2.7", "@types/react": "^18.2.69",
"@types/react-dom": "^18.2.22",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
"alova": "^2.11.1", "alova": "^2.18.0",
"async-validator": "^4.2.5", "async-validator": "^4.2.5",
"history": "^5.3.0", "history": "^5.3.0",
"jwt-decode": "^3.1.2", "jwt-decode": "^4.0.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"mime-types": "^2.1.35", "mime-types": "^2.1.35",
"preact": "^10.17.1",
"react": "latest", "react": "latest",
"react-dom": "latest", "react-dom": "latest",
"react-dropzone": "^14.2.3", "react-dropzone": "^14.2.3",
"react-icons": "^4.11.0", "react-icons": "^5.0.1",
"react-router-dom": "^6.15.0", "react-router-dom": "^6.22.3",
"react-toastify": "^9.1.3", "react-toastify": "^10.0.5",
"sockette": "^2.0.6", "sockette": "^2.0.6",
"typesafe-i18n": "^5.26.2", "typesafe-i18n": "^5.26.2",
"typescript": "^5.2.2" "typescript": "^5.4.3"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.22.17", "@preact/compat": "^17.1.2",
"@preact/preset-vite": "^2.5.0", "@preact/preset-vite": "^2.8.2",
"@types/babel__core": "^7", "@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/eslint-plugin": "^6.6.0", "@typescript-eslint/parser": "^7.3.1",
"@typescript-eslint/parser": "^6.6.0", "concurrently": "^8.2.2",
"eslint": "^8.49.0", "eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^9.1.0",
"eslint-config-airbnb-typescript": "^17.1.0", "eslint-import-resolver-typescript": "^3.6.1",
"eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-typescript": "^3.6.0",
"eslint-plugin-autofix": "^1.1.0", "eslint-plugin-autofix": "^1.1.0",
"eslint-plugin-import": "^2.28.1", "eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-prettier": "alpha", "eslint-plugin-prettier": "alpha",
"eslint-plugin-react": "^7.33.2", "eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"npm-run-all": "^4.1.5", "preact": "^10.20.1",
"prettier": "^3.0.3", "prettier": "^3.2.5",
"rollup-plugin-visualizer": "^5.9.2", "rollup-plugin-visualizer": "^5.12.0",
"terser": "^5.19.4", "terser": "^5.29.2",
"vite": "^4.4.9", "vite": "^5.2.4",
"vite-plugin-svgr": "^3.2.0", "vite-plugin-imagemin": "^0.6.1",
"vite-tsconfig-paths": "^4.2.0" "vite-tsconfig-paths": "^4.3.2"
}, },
"packageManager": "yarn@3.4.1" "packageManager": "yarn@4.1.1"
} }

View File

@@ -1,10 +1,32 @@
const { readdirSync, existsSync, unlinkSync, readFileSync, createWriteStream } = require('fs'); import { readdirSync, existsSync, unlinkSync, readFileSync, createWriteStream } from 'fs';
const { resolve, relative, sep } = require('path'); import { resolve, relative, sep } from 'path';
var zlib = require('zlib'); import zlib from 'zlib';
var mime = require('mime-types'); import mime from 'mime-types';
import crypto from 'crypto';
const ARDUINO_INCLUDES = '#include <Arduino.h>\n\n'; const ARDUINO_INCLUDES = '#include <Arduino.h>\n\n';
const INDENT = ' '; const INDENT = ' ';
const outputPath = '../lib/framework/WWWData.h';
const sourcePath = './dist';
const bytesPerLine = 20;
var totalSize = 0;
const generateWWWClass = () =>
`typedef std::function<void(const char * uri, const String & contentType, const uint8_t * content, size_t len, const String & hash)> RouteRegistrationHandler;
// Total size is ${totalSize} bytes
class WWWData {
${indent}public:
${indent.repeat(2)}static void registerRoutes(RouteRegistrationHandler handler) {
${fileInfo
.map(
(file) =>
`${indent.repeat(3)}handler("${file.uri}", "${file.mimeType}", ${file.variable}, ${file.size}, "${file.hash}");`
)
.join('\n')}
${indent.repeat(2)}}
};
`;
function getFilesSync(dir, files = []) { function getFilesSync(dir, files = []) {
readdirSync(dir, { withFileTypes: true }).forEach((entry) => { readdirSync(dir, { withFileTypes: true }).forEach((entry) => {
@@ -18,10 +40,6 @@ function getFilesSync(dir, files = []) {
return files; return files;
} }
// function coherseToBuffer(input) {
// return Buffer.isBuffer(input) ? input : Buffer.from(input);
// }
function cleanAndOpen(path) { function cleanAndOpen(path) {
if (existsSync(path)) { if (existsSync(path)) {
unlinkSync(path); unlinkSync(path);
@@ -29,90 +47,68 @@ function cleanAndOpen(path) {
return createWriteStream(path, { flags: 'w+' }); return createWriteStream(path, { flags: 'w+' });
} }
export default function ProgmemGenerator({ outputPath = './WWWData.h', bytesPerLine = 20 }) { const writeFile = (relativeFilePath, buffer) => {
return { const variable = 'ESP_REACT_DATA_' + fileInfo.length;
name: 'ProgmemGenerator', const mimeType = mime.lookup(relativeFilePath);
writeBundle: () => { var size = 0;
console.log('Generating ' + outputPath); writeStream.write('const uint8_t ' + variable + '[] = {');
const includes = ARDUINO_INCLUDES; // const zipBuffer = zlib.brotliCompressSync(buffer, { quality: 1 });
const indent = INDENT; const zipBuffer = zlib.gzipSync(buffer, { level: 9 });
const fileInfo = [];
const writeStream = cleanAndOpen(resolve(outputPath));
try { // create sha
const writeIncludes = () => { const hashSum = crypto.createHash('sha256');
writeStream.write(includes); hashSum.update(zipBuffer);
}; const hash = hashSum.digest('hex');
const writeFile = (relativeFilePath, buffer) => { zipBuffer.forEach((b) => {
const variable = 'ESP_REACT_DATA_' + fileInfo.length; if (!(size % bytesPerLine)) {
const mimeType = mime.lookup(relativeFilePath); writeStream.write('\n');
var size = 0; writeStream.write(indent);
writeStream.write('const uint8_t ' + variable + '[] = {');
// const zipBuffer = zlib.brotliCompressSync(buffer, { quality: 1 });
const zipBuffer = zlib.gzipSync(buffer);
zipBuffer.forEach((b) => {
if (!(size % bytesPerLine)) {
writeStream.write('\n');
writeStream.write(indent);
}
writeStream.write('0x' + ('00' + b.toString(16).toUpperCase()).substr(-2) + ',');
size++;
});
if (size % bytesPerLine) {
writeStream.write('\n');
}
writeStream.write('};\n\n');
fileInfo.push({
uri: '/' + relativeFilePath.replace(sep, '/'),
mimeType,
variable,
size
});
};
const writeFiles = () => {
// process static files
const buildPath = resolve('build');
for (const filePath of getFilesSync(buildPath)) {
const readStream = readFileSync(filePath);
const relativeFilePath = relative(buildPath, filePath);
writeFile(relativeFilePath, readStream);
}
// process assets
// const { assets } = compilation;
// Object.keys(assets).forEach((relativeFilePath) => {
// writeFile(relativeFilePath, coherseToBuffer(assets[relativeFilePath].source()));
// });
};
const generateWWWClass = () =>
`typedef std::function<void(const String& uri, const String& contentType, const uint8_t * content, size_t len)> RouteRegistrationHandler;
class WWWData {
${indent}public:
${indent.repeat(2)}static void registerRoutes(RouteRegistrationHandler handler) {
${fileInfo
.map((file) => `${indent.repeat(3)}handler("${file.uri}", "${file.mimeType}", ${file.variable}, ${file.size});`)
.join('\n')}
${indent.repeat(2)}}
};
`;
const writeWWWClass = () => {
writeStream.write(generateWWWClass());
};
writeIncludes();
writeFiles();
writeWWWClass();
writeStream.on('finish', () => {
// callback();
});
} finally {
writeStream.end();
}
} }
}; writeStream.write('0x' + ('00' + b.toString(16).toUpperCase()).slice(-2) + ',');
size++;
});
if (size % bytesPerLine) {
writeStream.write('\n');
}
writeStream.write('};\n\n');
fileInfo.push({
uri: '/' + relativeFilePath.replace(sep, '/'),
mimeType,
variable,
size,
hash
});
// console.log(relativeFilePath + ' (size ' + size + ' bytes)');
totalSize += size;
};
// start
console.log('Generating ' + outputPath + ' from ' + sourcePath);
const includes = ARDUINO_INCLUDES;
const indent = INDENT;
const fileInfo = [];
const writeStream = cleanAndOpen(resolve(outputPath));
// includes
writeStream.write(includes);
// process static files
const buildPath = resolve(sourcePath);
for (const filePath of getFilesSync(buildPath)) {
const readStream = readFileSync(filePath);
const relativeFilePath = relative(buildPath, filePath);
writeFile(relativeFilePath, readStream);
} }
// add class
writeStream.write(generateWWWClass());
// end
writeStream.end();
console.log('Total size: ' + totalSize / 1000 + ' KB');

Binary file not shown.

View File

@@ -4,7 +4,6 @@ import { ToastContainer, Slide } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.min.css'; import 'react-toastify/dist/ReactToastify.min.css';
import { localStorageDetector } from 'typesafe-i18n/detectors'; import { localStorageDetector } from 'typesafe-i18n/detectors';
import { FeaturesLoader } from './contexts/features';
import type { FC } from 'react'; import type { FC } from 'react';
import AppRouting from 'AppRouting'; import AppRouting from 'AppRouting';
import CustomTheme from 'CustomTheme'; import CustomTheme from 'CustomTheme';
@@ -27,9 +26,7 @@ const App: FC = () => {
return ( return (
<TypesafeI18n locale={detectedLocale}> <TypesafeI18n locale={detectedLocale}>
<CustomTheme> <CustomTheme>
<FeaturesLoader> <AppRouting />
<AppRouting />
</FeaturesLoader>
<ToastContainer <ToastContainer
position="bottom-left" position="bottom-left"
autoClose={3000} autoClose={3000}

View File

@@ -26,6 +26,9 @@ const theme = responsiveFontSizes(
}, },
info: { info: {
main: '#607d8b' // blueGrey[500] main: '#607d8b' // blueGrey[500]
},
text: {
disabled: '#eee' // white
} }
} }
}) })

View File

@@ -3,7 +3,6 @@ import { Box, Paper, Typography, MenuItem, TextField, Button } from '@mui/materi
import { useRequest } from 'alova'; import { useRequest } from 'alova';
import { useContext, useState } from 'react'; import { useContext, useState } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { FeaturesContext } from './contexts/features';
import type { ValidateFieldsError } from 'async-validator'; import type { ValidateFieldsError } from 'async-validator';
import type { Locales } from 'i18n/i18n-types'; import type { Locales } from 'i18n/i18n-types';
@@ -15,15 +14,16 @@ import { PROJECT_NAME } from 'api/env';
import { ValidatedPasswordField, ValidatedTextField } from 'components'; import { ValidatedPasswordField, ValidatedTextField } from 'components';
import { AuthenticationContext } from 'contexts/authentication'; import { AuthenticationContext } from 'contexts/authentication';
import { ReactComponent as DEflag } from 'i18n/DE.svg'; import DEflag from 'i18n/DE.svg';
import { ReactComponent as FRflag } from 'i18n/FR.svg'; import FRflag from 'i18n/FR.svg';
import { ReactComponent as GBflag } from 'i18n/GB.svg'; import GBflag from 'i18n/GB.svg';
import { ReactComponent as ITflag } from 'i18n/IT.svg'; import ITflag from 'i18n/IT.svg';
import { ReactComponent as NLflag } from 'i18n/NL.svg'; import NLflag from 'i18n/NL.svg';
import { ReactComponent as NOflag } from 'i18n/NO.svg'; import NOflag from 'i18n/NO.svg';
import { ReactComponent as PLflag } from 'i18n/PL.svg'; import PLflag from 'i18n/PL.svg';
import { ReactComponent as SVflag } from 'i18n/SV.svg'; import SKflag from 'i18n/SK.svg';
import { ReactComponent as TRflag } from 'i18n/TR.svg'; import SVflag from 'i18n/SV.svg';
import TRflag from 'i18n/TR.svg';
import { I18nContext } from 'i18n/i18n-react'; import { I18nContext } from 'i18n/i18n-react';
import { loadLocaleAsync } from 'i18n/i18n-util.async'; import { loadLocaleAsync } from 'i18n/i18n-util.async';
import { onEnterCallback, updateValue } from 'utils'; import { onEnterCallback, updateValue } from 'utils';
@@ -34,8 +34,6 @@ const SignIn: FC = () => {
const { LL, setLocale, locale } = useContext(I18nContext); const { LL, setLocale, locale } = useContext(I18nContext);
const { features } = useContext(FeaturesContext);
const [signInRequest, setSignInRequest] = useState<SignInRequest>({ const [signInRequest, setSignInRequest] = useState<SignInRequest>({
username: '', username: '',
password: '' password: ''
@@ -111,43 +109,46 @@ const SignIn: FC = () => {
})} })}
> >
<Typography variant="h4">{PROJECT_NAME}</Typography> <Typography variant="h4">{PROJECT_NAME}</Typography>
<Typography variant="subtitle2">{features.version}</Typography>
<TextField name="locale" variant="outlined" value={locale} onChange={onLocaleSelected} size="small" select> <TextField name="locale" variant="outlined" value={locale} onChange={onLocaleSelected} size="small" select>
<MenuItem key="de" value="de"> <MenuItem key="de" value="de">
<DEflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={DEflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;DE &nbsp;DE
</MenuItem> </MenuItem>
<MenuItem key="en" value="en"> <MenuItem key="en" value="en">
<GBflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={GBflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;EN &nbsp;EN
</MenuItem> </MenuItem>
<MenuItem key="fr" value="fr"> <MenuItem key="fr" value="fr">
<FRflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={FRflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;FR &nbsp;FR
</MenuItem> </MenuItem>
<MenuItem key="it" value="it"> <MenuItem key="it" value="it">
<ITflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={ITflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;IT &nbsp;IT
</MenuItem> </MenuItem>
<MenuItem key="nl" value="nl"> <MenuItem key="nl" value="nl">
<NLflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={NLflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;NL &nbsp;NL
</MenuItem> </MenuItem>
<MenuItem key="no" value="no"> <MenuItem key="no" value="no">
<NOflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={NOflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;NO &nbsp;NO
</MenuItem> </MenuItem>
<MenuItem key="pl" value="pl"> <MenuItem key="pl" value="pl">
<PLflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={PLflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;PL &nbsp;PL
</MenuItem> </MenuItem>
<MenuItem key="sk" value="sk">
<img src={SKflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;SK
</MenuItem>
<MenuItem key="sv" value="sv"> <MenuItem key="sv" value="sv">
<SVflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={SVflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;SV &nbsp;SV
</MenuItem> </MenuItem>
<MenuItem key="tr" value="tr"> <MenuItem key="tr" value="tr">
<TRflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={TRflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;TR &nbsp;TR
</MenuItem> </MenuItem>
</TextField> </TextField>

View File

@@ -1,4 +1,4 @@
import jwtDecode from 'jwt-decode'; import { jwtDecode } from 'jwt-decode';
import { ACCESS_TOKEN, alovaInstance } from './endpoints'; import { ACCESS_TOKEN, alovaInstance } from './endpoints';
import type * as H from 'history'; import type * as H from 'history';
import type { Path } from 'react-router-dom'; import type { Path } from 'react-router-dom';

View File

@@ -1,5 +0,0 @@
import { alovaInstance } from './endpoints';
import type { Features } from 'types';
export const readFeatures = () => alovaInstance.Get<Features>('/rest/features');

View File

@@ -498,8 +498,8 @@ function createStructureReader(structure, firstId) {
key === '__proto__' key === '__proto__'
? '__proto_:r()' ? '__proto_:r()'
: validName.test(key) : validName.test(key)
? key + ':r()' ? key + ':r()'
: '[' + JSON.stringify(key) + ']:r()' : '[' + JSON.stringify(key) + ']:r()'
) )
.join(',') + .join(',') +
'})}' '})}'

View File

@@ -14,20 +14,20 @@ import {
} from '@mui/material'; } from '@mui/material';
import { useState, useContext } from 'react'; import { useState, useContext } from 'react';
import type { TypographyProps } from '@mui/material'; import type { TypographyProps } from '@mui/material';
import type { Locales } from 'i18n/i18n-types'; import type { Locales } from 'i18n/i18n-types';
import type { FC, ChangeEventHandler } from 'react'; import type { FC, ChangeEventHandler } from 'react';
import { AuthenticatedContext } from 'contexts/authentication'; import { AuthenticatedContext } from 'contexts/authentication';
import DEflag from 'i18n/DE.svg';
import FRflag from 'i18n/FR.svg';
import GBflag from 'i18n/GB.svg';
import ITflag from 'i18n/IT.svg';
import NLflag from 'i18n/NL.svg';
import NOflag from 'i18n/NO.svg';
import PLflag from 'i18n/PL.svg';
import SKflag from 'i18n/SK.svg';
import SVflag from 'i18n/SV.svg';
import TRflag from 'i18n/TR.svg';
import { ReactComponent as DEflag } from 'i18n/DE.svg';
import { ReactComponent as FRflag } from 'i18n/FR.svg';
import { ReactComponent as GBflag } from 'i18n/GB.svg';
import { ReactComponent as ITflag } from 'i18n/IT.svg';
import { ReactComponent as NLflag } from 'i18n/NL.svg';
import { ReactComponent as NOflag } from 'i18n/NO.svg';
import { ReactComponent as PLflag } from 'i18n/PL.svg';
import { ReactComponent as SVflag } from 'i18n/SV.svg';
import { ReactComponent as TRflag } from 'i18n/TR.svg';
import { I18nContext } from 'i18n/i18n-react'; import { I18nContext } from 'i18n/i18n-react';
import { loadLocaleAsync } from 'i18n/i18n-util.async'; import { loadLocaleAsync } from 'i18n/i18n-util.async';
@@ -75,39 +75,43 @@ const LayoutAuthMenu: FC = () => {
select select
> >
<MenuItem key="de" value="de"> <MenuItem key="de" value="de">
<DEflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={DEflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;DE &nbsp;DE
</MenuItem> </MenuItem>
<MenuItem key="en" value="en"> <MenuItem key="en" value="en">
<GBflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={GBflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;EN &nbsp;EN
</MenuItem> </MenuItem>
<MenuItem key="fr" value="fr"> <MenuItem key="fr" value="fr">
<FRflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={FRflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;FR &nbsp;FR
</MenuItem> </MenuItem>
<MenuItem key="it" value="it"> <MenuItem key="it" value="it">
<ITflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={ITflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;IT &nbsp;IT
</MenuItem> </MenuItem>
<MenuItem key="nl" value="nl"> <MenuItem key="nl" value="nl">
<NLflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={NLflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;NL &nbsp;NL
</MenuItem> </MenuItem>
<MenuItem key="no" value="no"> <MenuItem key="no" value="no">
<NOflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={NOflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;NO &nbsp;NO
</MenuItem> </MenuItem>
<MenuItem key="pl" value="pl"> <MenuItem key="pl" value="pl">
<PLflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={PLflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;PL &nbsp;PL
</MenuItem> </MenuItem>
<MenuItem key="sk" value="sk">
<img src={SKflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;SK
</MenuItem>
<MenuItem key="sv" value="sv"> <MenuItem key="sv" value="sv">
<SVflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={SVflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;SV &nbsp;SV
</MenuItem> </MenuItem>
<MenuItem key="tr" value="tr"> <MenuItem key="tr" value="tr">
<TRflag style={{ width: 16, verticalAlign: 'middle' }} /> <img src={TRflag} style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;TR &nbsp;TR
</MenuItem> </MenuItem>
</TextField> </TextField>

View File

@@ -14,7 +14,7 @@ const RouterTabs: FC<RouterTabsProps> = ({ value, children }) => {
const theme = useTheme(); const theme = useTheme();
const smallDown = useMediaQuery(theme.breakpoints.down('sm')); const smallDown = useMediaQuery(theme.breakpoints.down('sm'));
const handleTabChange = (event: React.ChangeEvent<HTMLInputElement>, path: string) => { const handleTabChange = (_event: any, path: string) => {
navigate(path); navigate(path);
}; };

View File

@@ -1,9 +1,12 @@
import { useMatch, useResolvedPath } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
export const useRouterTab = () => { export const useRouterTab = () => {
const routerTabPath = useResolvedPath(':tab'); const loc = useLocation().pathname;
const routerTabPathMatch = useMatch(routerTabPath.pathname); const routerTab = loc.substring(0, loc.lastIndexOf('/')) ? loc : false;
// const routerTabPath = useResolvedPath(':tab');
// const routerTabPathMatch = useMatch(routerTabPath.pathname);
// const routerTab = routerTabPathMatch?.params?.tab || false;
const routerTab = routerTabPathMatch?.params?.tab || false;
return { routerTab } as const; return { routerTab } as const;
}; };

View File

@@ -50,8 +50,10 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, isUploading, pr
const progressText = () => { const progressText = () => {
if (uploading) { if (uploading) {
if (progress.total) { if (progress.total && progress.loaded) {
return LL.UPLOADING() + ': ' + Math.round((progress.loaded * 100) / progress.total) + '%'; return progress.loaded <= progress.total
? LL.UPLOADING() + ': ' + Math.round((progress.loaded * 100) / progress.total) + '%'
: LL.UPLOADING() + ': ' + Math.round((progress.total * 100) / progress.loaded) + '%';
} }
} }
return LL.UPLOAD_DROP_TEXT(); return LL.UPLOAD_DROP_TEXT();
@@ -83,7 +85,13 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, isUploading, pr
<Box width="100%" p={2}> <Box width="100%" p={2}>
<LinearProgress <LinearProgress
variant="determinate" variant="determinate"
value={progress.total === 0 ? 0 : Math.round((progress.loaded * 100) / progress.total)} value={
progress.total === 0 || progress.loaded === 0
? 0
: progress.loaded <= progress.total
? Math.round((progress.loaded * 100) / progress.total)
: Math.round((progress.total * 100) / progress.loaded)
}
/> />
</Box> </Box>
<Button startIcon={<CancelIcon />} variant="outlined" color="secondary" onClick={onCancel}> <Button startIcon={<CancelIcon />} variant="outlined" color="secondary" onClick={onCancel}>

View File

@@ -1,6 +1,6 @@
import { useRequest } from 'alova'; import { useRequest } from 'alova';
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { redirect } from 'react-router-dom';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { AuthenticationContext } from './context'; import { AuthenticationContext } from './context';
import type { FC } from 'react'; import type { FC } from 'react';
@@ -15,8 +15,6 @@ import { useI18nContext } from 'i18n/i18n-react';
const Authentication: FC<RequiredChildrenProps> = ({ children }) => { const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
const { LL } = useI18nContext(); const { LL } = useI18nContext();
const navigate = useNavigate();
const [initialized, setInitialized] = useState<boolean>(false); const [initialized, setInitialized] = useState<boolean>(false);
const [me, setMe] = useState<Me>(); const [me, setMe] = useState<Me>();
@@ -36,11 +34,12 @@ const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
} }
}; };
const signOut = (redirect: boolean) => { const signOut = (doRedirect: boolean) => {
AuthenticationApi.clearAccessToken(); AuthenticationApi.clearAccessToken();
setMe(undefined); setMe(undefined);
if (redirect) { if (doRedirect) {
navigate('/'); // navigate('/');
redirect('/');
} }
}; };

View File

@@ -1,25 +0,0 @@
import { useRequest } from 'alova';
import { FeaturesContext } from '.';
import type { FC } from 'react';
import type { RequiredChildrenProps } from 'utils';
import * as FeaturesApi from 'api/features';
const FeaturesLoader: FC<RequiredChildrenProps> = (props) => {
const { data: features } = useRequest(FeaturesApi.readFeatures);
if (features) {
return (
<FeaturesContext.Provider
value={{
features
}}
>
{props.children}
</FeaturesContext.Provider>
);
}
};
export default FeaturesLoader;

View File

@@ -1,10 +0,0 @@
import { createContext } from 'react';
import type { Features } from 'types';
export interface FeaturesContextValue {
features: Features;
}
const FeaturesContextDefaultValue = {} as FeaturesContextValue;
export const FeaturesContext = createContext(FeaturesContextDefaultValue);

View File

@@ -1,2 +0,0 @@
export * from './context';
export { default as FeaturesLoader } from './FeaturesLoader';

View File

@@ -22,8 +22,12 @@ const AccessPoint: FC = () => {
return ( return (
<> <>
<RouterTabs value={routerTab}> <RouterTabs value={routerTab}>
<Tab value="status" label={LL.STATUS_OF(LL.ACCESS_POINT(1))} /> <Tab value="/ap/status" label={LL.STATUS_OF(LL.ACCESS_POINT(1))} />
<Tab value="settings" label={LL.SETTINGS_OF(LL.ACCESS_POINT(1))} disabled={!authenticatedContext.me.admin} /> <Tab
value="/ap/settings"
label={LL.SETTINGS_OF(LL.ACCESS_POINT(1))}
disabled={!authenticatedContext.me.admin}
/>
</RouterTabs> </RouterTabs>
<Routes> <Routes>
<Route path="status" element={<APStatusForm />} /> <Route path="status" element={<APStatusForm />} />
@@ -36,7 +40,7 @@ const AccessPoint: FC = () => {
</RequireAdmin> </RequireAdmin>
} }
/> />
<Route path="/*" element={<Navigate replace to="status" />} /> <Route path="*" element={<Navigate replace to="/ap/status" />} />
</Routes> </Routes>
</> </>
); );

View File

@@ -21,8 +21,8 @@ const Mqtt: FC = () => {
return ( return (
<> <>
<RouterTabs value={routerTab}> <RouterTabs value={routerTab}>
<Tab value="status" label={LL.STATUS_OF('MQTT')} /> <Tab value="/mqtt/status" label={LL.STATUS_OF('MQTT')} />
<Tab value="settings" label={LL.SETTINGS_OF('MQTT')} disabled={!authenticatedContext.me.admin} /> <Tab value="/mqtt/settings" label={LL.SETTINGS_OF('MQTT')} disabled={!authenticatedContext.me.admin} />
</RouterTabs> </RouterTabs>
<Routes> <Routes>
<Route path="status" element={<MqttStatusForm />} /> <Route path="status" element={<MqttStatusForm />} />
@@ -34,7 +34,7 @@ const Mqtt: FC = () => {
</RequireAdmin> </RequireAdmin>
} }
/> />
<Route path="/*" element={<Navigate replace to="status" />} /> <Route path="*" element={<Navigate replace to="/mqtt/status" />} />
</Routes> </Routes>
</> </>
); );

View File

@@ -72,6 +72,7 @@ const MqttSettingsForm: FC = () => {
name="host" name="host"
label={LL.ADDRESS_OF(LL.BROKER())} label={LL.ADDRESS_OF(LL.BROKER())}
fullWidth fullWidth
multiline
variant="outlined" variant="outlined"
value={data.host} value={data.host}
onChange={updateFormValue} onChange={updateFormValue}
@@ -168,20 +169,24 @@ const MqttSettingsForm: FC = () => {
<MenuItem value={2}>2</MenuItem> <MenuItem value={2}>2</MenuItem>
</TextField> </TextField>
</Grid> </Grid>
{data.rootCA !== undefined && (
<Grid item xs={12} sm={6}>
<ValidatedPasswordField
name="rootCA"
label={LL.CERT()}
fullWidth
variant="outlined"
value={data.rootCA}
onChange={updateFormValue}
margin="normal"
/>
</Grid>
)}
</Grid> </Grid>
{data.enableTLS !== undefined && (
<BlockFormControlLabel
control={<Checkbox name="enableTLS" checked={data.enableTLS} onChange={updateFormValue} />}
label={LL.ENABLE_TLS()}
/>
)}
{data.enableTLS === true && (
<ValidatedPasswordField
name="rootCA"
label={LL.CERT()}
fullWidth
variant="outlined"
value={data.rootCA}
onChange={updateFormValue}
margin="normal"
/>
)}
<BlockFormControlLabel <BlockFormControlLabel
control={<Checkbox name="clean_session" checked={data.clean_session} onChange={updateFormValue} />} control={<Checkbox name="clean_session" checked={data.clean_session} onChange={updateFormValue} />}
@@ -269,6 +274,7 @@ const MqttSettingsForm: FC = () => {
> >
<MenuItem value={0}>Home Assistant</MenuItem> <MenuItem value={0}>Home Assistant</MenuItem>
<MenuItem value={1}>Domoticz</MenuItem> <MenuItem value={1}>Domoticz</MenuItem>
<MenuItem value={2}>Domoticz (latest)</MenuItem>
</TextField> </TextField>
</Grid> </Grid>
<Grid item xs={12} sm={6} md={4}> <Grid item xs={12} sm={6} md={4}>

View File

@@ -69,7 +69,7 @@ const MqttStatusForm: FC = () => {
case MqttDisconnectReason.MQTT_NOT_AUTHORIZED: case MqttDisconnectReason.MQTT_NOT_AUTHORIZED:
return 'Not authorized'; return 'Not authorized';
case MqttDisconnectReason.TLS_BAD_FINGERPRINT: case MqttDisconnectReason.TLS_BAD_FINGERPRINT:
return 'TSL fingerprint invalid'; return 'TLS fingerprint invalid';
default: default:
return 'Unknown'; return 'Unknown';
} }

View File

@@ -44,9 +44,13 @@ const NetworkConnection: FC = () => {
}} }}
> >
<RouterTabs value={routerTab}> <RouterTabs value={routerTab}>
<Tab value="status" label={LL.STATUS_OF(LL.NETWORK(1))} /> <Tab value="/network/status" label={LL.STATUS_OF(LL.NETWORK(1))} />
<Tab value="scan" label={LL.NETWORK_SCAN()} disabled={!authenticatedContext.me.admin} /> <Tab value="/network/scan" label={LL.NETWORK_SCAN()} disabled={!authenticatedContext.me.admin} />
<Tab value="settings" label={LL.SETTINGS_OF(LL.NETWORK(1))} disabled={!authenticatedContext.me.admin} /> <Tab
value="/network/settings"
label={LL.SETTINGS_OF(LL.NETWORK(1))}
disabled={!authenticatedContext.me.admin}
/>
</RouterTabs> </RouterTabs>
<Routes> <Routes>
<Route path="status" element={<NetworkStatusForm />} /> <Route path="status" element={<NetworkStatusForm />} />
@@ -66,7 +70,7 @@ const NetworkConnection: FC = () => {
</RequireAdmin> </RequireAdmin>
} }
/> />
<Route path="/*" element={<Navigate replace to="status" />} /> <Route path="*" element={<Navigate replace to="/network/status" />} />
</Routes> </Routes>
</WiFiConnectionContext.Provider> </WiFiConnectionContext.Provider>
); );

View File

@@ -15,8 +15,8 @@ import {
ListItemSecondaryAction, ListItemSecondaryAction,
ListItemText, ListItemText,
Typography, Typography,
InputAdornment, TextField,
TextField MenuItem
} from '@mui/material'; } from '@mui/material';
// eslint-disable-next-line import/named // eslint-disable-next-line import/named
import { updateState, useRequest } from 'alova'; import { updateState, useRequest } from 'alova';
@@ -43,7 +43,7 @@ import {
} from 'components'; } from 'components';
import { useI18nContext } from 'i18n/i18n-react'; import { useI18nContext } from 'i18n/i18n-react';
import { numberValue, updateValueDirty, useRest } from 'utils'; import { updateValueDirty, useRest } from 'utils';
import { validate } from 'validators'; import { validate } from 'validators';
import { createNetworkSettingsValidator } from 'validators/network'; import { createNetworkSettingsValidator } from 'validators/network';
@@ -82,12 +82,13 @@ const WiFiSettingsForm: FC = () => {
if (selectedNetwork) { if (selectedNetwork) {
updateState('networkSettings', (current_data) => ({ updateState('networkSettings', (current_data) => ({
ssid: selectedNetwork.ssid, ssid: selectedNetwork.ssid,
password: '', bssid: selectedNetwork.bssid,
password: current_data ? current_data.password : '',
hostname: current_data?.hostname, hostname: current_data?.hostname,
static_ip_config: false, static_ip_config: false,
enableIPv6: false, enableIPv6: false,
bandwidth20: false, bandwidth20: false,
tx_power: 20, tx_power: 0,
nosleep: false, nosleep: false,
enableMDNS: true, enableMDNS: true,
enableCORS: false, enableCORS: false,
@@ -117,6 +118,12 @@ const WiFiSettingsForm: FC = () => {
} catch (errors: any) { } catch (errors: any) {
setFieldErrors(errors); setFieldErrors(errors);
} }
deselectNetwork();
};
const setCancel = async () => {
deselectNetwork();
await loadData();
}; };
const restart = async () => { const restart = async () => {
@@ -139,10 +146,17 @@ const WiFiSettingsForm: FC = () => {
</ListItemAvatar> </ListItemAvatar>
<ListItemText <ListItemText
primary={selectedNetwork.ssid} primary={selectedNetwork.ssid}
secondary={'Security: ' + networkSecurityMode(selectedNetwork) + ', Ch: ' + selectedNetwork.channel} secondary={
'Security: ' +
networkSecurityMode(selectedNetwork) +
', Ch: ' +
selectedNetwork.channel +
', bssid: ' +
selectedNetwork.bssid
}
/> />
<ListItemSecondaryAction> <ListItemSecondaryAction>
<IconButton onClick={deselectNetwork}> <IconButton onClick={setCancel}>
<DeleteIcon /> <DeleteIcon />
</IconButton> </IconButton>
</ListItemSecondaryAction> </ListItemSecondaryAction>
@@ -160,6 +174,16 @@ const WiFiSettingsForm: FC = () => {
margin="normal" margin="normal"
/> />
)} )}
<ValidatedTextField
fieldErrors={fieldErrors}
name="bssid"
label={'BSSID (' + LL.NETWORK_BLANK_BSSID() + ')'}
fullWidth
variant="outlined"
value={data.bssid}
onChange={updateFormValue}
margin="normal"
/>
{(!selectedNetwork || !isNetworkOpen(selectedNetwork)) && ( {(!selectedNetwork || !isNetworkOpen(selectedNetwork)) && (
<ValidatedPasswordField <ValidatedPasswordField
fieldErrors={fieldErrors} fieldErrors={fieldErrors}
@@ -172,20 +196,29 @@ const WiFiSettingsForm: FC = () => {
margin="normal" margin="normal"
/> />
)} )}
<ValidatedTextField <TextField
fieldErrors={fieldErrors}
name="tx_power" name="tx_power"
label={LL.TX_POWER()} label={LL.TX_POWER()}
InputProps={{
endAdornment: <InputAdornment position="end">dBm</InputAdornment>
}}
fullWidth fullWidth
variant="outlined" variant="outlined"
value={numberValue(data.tx_power)} value={data.tx_power}
onChange={updateFormValue} onChange={updateFormValue}
type="number"
margin="normal" margin="normal"
/> select
>
<MenuItem value={0}>Auto</MenuItem>
<MenuItem value={78}>19.5 dBm</MenuItem>
<MenuItem value={76}>19 dBm</MenuItem>
<MenuItem value={74}>18.5 dBm</MenuItem>
<MenuItem value={68}>17 dBm</MenuItem>
<MenuItem value={60}>15 dBm</MenuItem>
<MenuItem value={52}>13 dBm</MenuItem>
<MenuItem value={44}>11 dBm</MenuItem>
<MenuItem value={34}>8.5 dBm</MenuItem>
<MenuItem value={28}>7 dBm</MenuItem>
<MenuItem value={20}>5 dBm</MenuItem>
<MenuItem value={8}>2 dBm</MenuItem>
</TextField>
<BlockFormControlLabel <BlockFormControlLabel
control={<Checkbox name="nosleep" checked={data.nosleep} onChange={updateFormValue} />} control={<Checkbox name="nosleep" checked={data.nosleep} onChange={updateFormValue} />}
label={LL.NETWORK_DISABLE_SLEEP()} label={LL.NETWORK_DISABLE_SLEEP()}
@@ -226,10 +259,12 @@ const WiFiSettingsForm: FC = () => {
margin="normal" margin="normal"
/> />
)} )}
<BlockFormControlLabel {data.enableIPv6 !== undefined && (
control={<Checkbox name="enableIPv6" checked={data.enableIPv6} onChange={updateFormValue} />} <BlockFormControlLabel
label={LL.NETWORK_ENABLE_IPV6()} control={<Checkbox name="enableIPv6" checked={data.enableIPv6} onChange={updateFormValue} />}
/> label={LL.NETWORK_ENABLE_IPV6()}
/>
)}
<BlockFormControlLabel <BlockFormControlLabel
control={<Checkbox name="static_ip_config" checked={data.static_ip_config} onChange={updateFormValue} />} control={<Checkbox name="static_ip_config" checked={data.static_ip_config} onChange={updateFormValue} />}
label={LL.NETWORK_FIXED_IP()} label={LL.NETWORK_FIXED_IP()}
@@ -289,14 +324,14 @@ const WiFiSettingsForm: FC = () => {
</> </>
)} )}
{restartNeeded && ( {restartNeeded && (
<MessageBox my={2} level="warning" message={LL.RESTART_TEXT()}> <MessageBox my={2} level="warning" message={LL.RESTART_TEXT(0)}>
<Button startIcon={<PowerSettingsNewIcon />} variant="contained" color="error" onClick={restart}> <Button startIcon={<PowerSettingsNewIcon />} variant="contained" color="error" onClick={restart}>
{LL.RESTART()} {LL.RESTART()}
</Button> </Button>
</MessageBox> </MessageBox>
)} )}
{!restartNeeded && dirtyFlags && dirtyFlags.length !== 0 && ( {!restartNeeded && (selectedNetwork || (dirtyFlags && dirtyFlags.length !== 0)) && (
<ButtonRow> <ButtonRow>
<Button <Button
startIcon={<CancelIcon />} startIcon={<CancelIcon />}

View File

@@ -1,5 +1,6 @@
import DeviceHubIcon from '@mui/icons-material/DeviceHub'; import DeviceHubIcon from '@mui/icons-material/DeviceHub';
import DnsIcon from '@mui/icons-material/Dns'; import DnsIcon from '@mui/icons-material/Dns';
import GiteIcon from '@mui/icons-material/Gite';
import RefreshIcon from '@mui/icons-material/Refresh'; import RefreshIcon from '@mui/icons-material/Refresh';
import RouterIcon from '@mui/icons-material/Router'; import RouterIcon from '@mui/icons-material/Router';
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna'; import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
@@ -115,6 +116,15 @@ const NetworkStatusForm: FC = () => {
<ListItemText primary="Status" secondary={networkStatus(data)} /> <ListItemText primary="Status" secondary={networkStatus(data)} />
</ListItem> </ListItem>
<Divider variant="inset" component="li" /> <Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar sx={{ bgcolor: networkStatusHighlight(data, theme) }}>
<GiteIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary="Hostname" secondary={data.hostname} />
</ListItem>
<Divider variant="inset" component="li" />
{isWiFi(data) && ( {isWiFi(data) && (
<> <>
<ListItem> <ListItem>

View File

@@ -65,7 +65,9 @@ const WiFiNetworkSelector: FC<WiFiNetworkSelectorProps> = ({ networkList }) => {
</ListItemAvatar> </ListItemAvatar>
<ListItemText <ListItemText
primary={network.ssid} primary={network.ssid}
secondary={'Security: ' + networkSecurityMode(network) + ', Ch: ' + network.channel} secondary={
'Security: ' + networkSecurityMode(network) + ', Ch: ' + network.channel + ', bssid: ' + network.bssid
}
/> />
<ListItemIcon> <ListItemIcon>
<Badge badgeContent={network.rssi + 'dBm'}> <Badge badgeContent={network.rssi + 'dBm'}>

View File

@@ -20,8 +20,8 @@ const NetworkTime: FC = () => {
return ( return (
<> <>
<RouterTabs value={routerTab}> <RouterTabs value={routerTab}>
<Tab value="status" label={LL.STATUS_OF('NTP')} /> <Tab value="/ntp/status" label={LL.STATUS_OF('NTP')} />
<Tab value="settings" label={LL.SETTINGS_OF('NTP')} disabled={!authenticatedContext.me.admin} /> <Tab value="/ntp/settings" label={LL.SETTINGS_OF('NTP')} disabled={!authenticatedContext.me.admin} />
</RouterTabs> </RouterTabs>
<Routes> <Routes>
<Route path="status" element={<NTPStatusForm />} /> <Route path="status" element={<NTPStatusForm />} />
@@ -33,7 +33,7 @@ const NetworkTime: FC = () => {
</RequireAdmin> </RequireAdmin>
} }
/> />
<Route path="/*" element={<Navigate replace to="status" />} /> <Route path="*" element={<Navigate replace to="/ntp/status" />} />
</Routes> </Routes>
</> </>
); );

View File

@@ -37,7 +37,8 @@ const GenerateToken: FC<GenerateTokenProps> = ({ username, onClose }) => {
if (open) { if (open) {
void generateToken(); void generateToken();
} }
}, [open, generateToken]); // eslint-disable-next-line react-hooks/exhaustive-deps
}, [open]);
return ( return (
<Dialog sx={dialogStyle} onClose={onClose} open={!!username} fullWidth maxWidth="sm"> <Dialog sx={dialogStyle} onClose={onClose} open={!!username} fullWidth maxWidth="sm">

View File

@@ -12,7 +12,7 @@ import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-li
import { useTheme } from '@table-library/react-table-library/theme'; import { useTheme } from '@table-library/react-table-library/theme';
import { useContext, useState } from 'react'; import { useContext, useState } from 'react';
import { unstable_useBlocker as useBlocker } from 'react-router-dom'; import { useBlocker } from 'react-router-dom';
import GenerateToken from './GenerateToken'; import GenerateToken from './GenerateToken';
import UserForm from './UserForm'; import UserForm from './UserForm';
import type { FC } from 'react'; import type { FC } from 'react';

View File

@@ -17,13 +17,13 @@ const Security: FC = () => {
return ( return (
<> <>
<RouterTabs value={routerTab}> <RouterTabs value={routerTab}>
<Tab value="users" label={LL.MANAGE_USERS()} /> <Tab value="/security/users" label={LL.MANAGE_USERS()} />
<Tab value="settings" label={LL.SETTINGS_OF(LL.SECURITY(1))} /> <Tab value="/security/settings" label={LL.SETTINGS_OF(LL.SECURITY(1))} />
</RouterTabs> </RouterTabs>
<Routes> <Routes>
<Route path="users" element={<ManageUsersForm />} /> <Route path="users" element={<ManageUsersForm />} />
<Route path="settings" element={<SecuritySettingsForm />} /> <Route path="settings" element={<SecuritySettingsForm />} />
<Route path="/*" element={<Navigate replace to="users" />} /> <Route path="*" element={<Navigate replace to="/security/users" />} />
</Routes> </Routes>
</> </>
); );

View File

@@ -23,10 +23,10 @@ const System: FC = () => {
return ( return (
<> <>
<RouterTabs value={routerTab}> <RouterTabs value={routerTab}>
<Tab value="status" label={LL.STATUS_OF(LL.SYSTEM(1))} /> <Tab value="/system/status" label={LL.STATUS_OF(LL.SYSTEM(1))} />
<Tab value="log" label={LL.LOG_OF(LL.SYSTEM(2))} /> <Tab value="/system/log" label={LL.LOG_OF(LL.SYSTEM(2))} />
<Tab value="ota" label={LL.SETTINGS_OF('OTA')} disabled={!me.admin} /> <Tab value="/system/ota" label={LL.SETTINGS_OF('OTA')} disabled={!me.admin} />
<Tab value="upload" label={LL.UPLOAD_DOWNLOAD()} disabled={!me.admin} /> <Tab value="/system/upload" label={LL.UPLOAD_DOWNLOAD()} disabled={!me.admin} />
</RouterTabs> </RouterTabs>
<Routes> <Routes>
<Route path="status" element={<SystemStatusForm />} /> <Route path="status" element={<SystemStatusForm />} />
@@ -47,7 +47,7 @@ const System: FC = () => {
</RequireAdmin> </RequireAdmin>
} }
/> />
<Route path="/*" element={<Navigate replace to="status" />} /> <Route path="*" element={<Navigate replace to="/system/status" />} />
</Routes> </Routes>
</> </>
); );

View File

@@ -1,6 +1,7 @@
import AppsIcon from '@mui/icons-material/Apps'; import AppsIcon from '@mui/icons-material/Apps';
import BuildIcon from '@mui/icons-material/Build'; import BuildIcon from '@mui/icons-material/Build';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import DeveloperBoardIcon from '@mui/icons-material/DeveloperBoard';
import DevicesIcon from '@mui/icons-material/Devices'; import DevicesIcon from '@mui/icons-material/Devices';
import FolderIcon from '@mui/icons-material/Folder'; import FolderIcon from '@mui/icons-material/Folder';
import MemoryIcon from '@mui/icons-material/Memory'; import MemoryIcon from '@mui/icons-material/Memory';
@@ -9,7 +10,6 @@ import RefreshIcon from '@mui/icons-material/Refresh';
import SdCardAlertIcon from '@mui/icons-material/SdCardAlert'; import SdCardAlertIcon from '@mui/icons-material/SdCardAlert';
import SdStorageIcon from '@mui/icons-material/SdStorage'; import SdStorageIcon from '@mui/icons-material/SdStorage';
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore'; import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
import ShowChartIcon from '@mui/icons-material/ShowChart';
import TimerIcon from '@mui/icons-material/Timer'; import TimerIcon from '@mui/icons-material/Timer';
import { import {
Avatar, Avatar,
@@ -29,7 +29,6 @@ import {
import { useRequest } from 'alova'; import { useRequest } from 'alova';
import { useContext, useState } from 'react'; import { useContext, useState } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { FeaturesContext } from '../../contexts/features';
import RestartMonitor from './RestartMonitor'; import RestartMonitor from './RestartMonitor';
import SystemStatusVersionDialog from './SystemStatusVersionDialog'; import SystemStatusVersionDialog from './SystemStatusVersionDialog';
import type { FC } from 'react'; import type { FC } from 'react';
@@ -54,8 +53,6 @@ const SystemStatusForm: FC = () => {
const [restarting, setRestarting] = useState<boolean>(); const [restarting, setRestarting] = useState<boolean>();
const [versionDialogOpen, setVersionDialogOpen] = useState<boolean>(false); const [versionDialogOpen, setVersionDialogOpen] = useState<boolean>(false);
const { features } = useContext(FeaturesContext);
const { send: restartCommand } = useRequest(SystemApi.restart(), { const { send: restartCommand } = useRequest(SystemApi.restart(), {
immediate: false immediate: false
}); });
@@ -200,15 +197,6 @@ const SystemStatusForm: FC = () => {
</Button> </Button>
</ListItem> </ListItem>
<Divider variant="inset" component="li" /> <Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar>
<DevicesIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary={LL.PLATFORM()} secondary={data.esp_platform + ' / ' + data.sdk_version} />
</ListItem>
<Divider variant="inset" component="li" />
<ListItem> <ListItem>
<ListItemAvatar> <ListItemAvatar>
<Avatar> <Avatar>
@@ -221,10 +209,33 @@ const SystemStatusForm: FC = () => {
<ListItem> <ListItem>
<ListItemAvatar> <ListItemAvatar>
<Avatar> <Avatar>
<ShowChartIcon /> <DevicesIcon />
</Avatar> </Avatar>
</ListItemAvatar> </ListItemAvatar>
<ListItemText primary={LL.CPU_FREQ()} secondary={data.cpu_freq_mhz + ' MHz'} /> <ListItemText primary="SDK" secondary={data.arduino_version + ' / ESP-IDF ' + data.sdk_version} />
</ListItem>
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar>
<DeveloperBoardIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary="CPU"
secondary={
data.esp_platform +
'/' +
data.cpu_type +
' (rev.' +
data.cpu_rev +
', ' +
(data.cpu_cores == 1 ? 'single-core)' : 'dual-core)') +
' @ ' +
data.cpu_freq_mhz +
' Mhz'
}
/>
</ListItem> </ListItem>
<Divider variant="inset" component="li" /> <Divider variant="inset" component="li" />
<ListItem> <ListItem>
@@ -277,7 +288,9 @@ const SystemStatusForm: FC = () => {
</ListItemAvatar> </ListItemAvatar>
<ListItemText <ListItemText
primary={LL.APPSIZE()} primary={LL.APPSIZE()}
secondary={formatNumber(data.app_used) + ' KB / ' + formatNumber(data.app_free) + ' KB'} secondary={
data.partition + ': ' + formatNumber(data.app_used) + ' KB / ' + formatNumber(data.app_free) + ' KB'
}
/> />
</ListItem> </ListItem>
<Divider variant="inset" component="li" /> <Divider variant="inset" component="li" />
@@ -339,7 +352,7 @@ const SystemStatusForm: FC = () => {
open={versionDialogOpen} open={versionDialogOpen}
onClose={() => setVersionDialogOpen(false)} onClose={() => setVersionDialogOpen(false)}
version={data.emsesp_version} version={data.emsesp_version}
platform={features.platform} platform={data.esp_platform}
/> />
)} )}
</SectionContent> </SectionContent>

View File

@@ -13,13 +13,13 @@ import * as EMSESP from 'project/api';
const UploadFileForm: FC = () => { const UploadFileForm: FC = () => {
const { LL } = useI18nContext(); const { LL } = useI18nContext();
const [restarting, setRestarting] = useState<boolean>(false); const [restarting, setRestarting] = useState<boolean>();
const [md5, setMd5] = useState<string>(); const [md5, setMd5] = useState<string>();
const { send: getSettings, onSuccess: onSuccessGetSettings } = useRequest(EMSESP.getSettings(), { const { send: getSettings, onSuccess: onSuccessGetSettings } = useRequest(EMSESP.getSettings(), {
immediate: false immediate: false
}); });
const { send: getCustomizations, onSuccess: onSuccessgetCustomizations } = useRequest(EMSESP.getCustomizations(), { const { send: getCustomizations, onSuccess: onSuccessGetCustomizations } = useRequest(EMSESP.getCustomizations(), {
immediate: false immediate: false
}); });
const { send: getEntities, onSuccess: onSuccessGetEntities } = useRequest(EMSESP.getEntities(), { const { send: getEntities, onSuccess: onSuccessGetEntities } = useRequest(EMSESP.getEntities(), {
@@ -28,6 +28,9 @@ const UploadFileForm: FC = () => {
const { send: getSchedule, onSuccess: onSuccessGetSchedule } = useRequest(EMSESP.getSchedule(), { const { send: getSchedule, onSuccess: onSuccessGetSchedule } = useRequest(EMSESP.getSchedule(), {
immediate: false immediate: false
}); });
const { send: getAPI, onSuccess: onGetAPI } = useRequest((data) => EMSESP.API(data), {
immediate: false
});
const { const {
loading: isUploading, loading: isUploading,
@@ -68,23 +71,26 @@ const UploadFileForm: FC = () => {
type: 'text/plain' type: 'text/plain'
}) })
); );
anchor.download = 'emsesp_' + endpoint + '.json'; anchor.download = 'emsesp_' + endpoint;
anchor.click(); anchor.click();
URL.revokeObjectURL(anchor.href); URL.revokeObjectURL(anchor.href);
toast.info(LL.DOWNLOAD_SUCCESSFUL()); toast.info(LL.DOWNLOAD_SUCCESSFUL());
}; };
onSuccessGetSettings((event) => { onSuccessGetSettings((event) => {
saveFile(event.data, 'settings'); saveFile(event.data, 'settings.json');
}); });
onSuccessgetCustomizations((event) => { onSuccessGetCustomizations((event) => {
saveFile(event.data, 'customizations'); saveFile(event.data, 'customizations.json');
}); });
onSuccessGetEntities((event) => { onSuccessGetEntities((event) => {
saveFile(event.data, 'entities'); saveFile(event.data, 'entities.json');
}); });
onSuccessGetSchedule((event) => { onSuccessGetSchedule((event) => {
saveFile(event.data, 'schedule'); saveFile(event.data, 'schedule.json');
});
onGetAPI((event) => {
saveFile(event.data, event.sendArgs[0].device + '_' + event.sendArgs[0].entity + '.txt');
}); });
const downloadSettings = async () => { const downloadSettings = async () => {
@@ -106,7 +112,17 @@ const UploadFileForm: FC = () => {
}; };
const downloadSchedule = async () => { const downloadSchedule = async () => {
await getSchedule().catch((error) => { await getSchedule()
.catch((error) => {
toast.error(error.message);
})
.finally(() => {
toast.info(LL.DOWNLOAD_SUCCESSFUL());
});
};
const callAPI = async (device: string, entity: string) => {
await getAPI({ device, entity, id: 0 }).catch((error) => {
toast.error(error.message); toast.error(error.message);
}); });
}; };
@@ -117,7 +133,12 @@ const UploadFileForm: FC = () => {
{LL.UPLOAD()} {LL.UPLOAD()}
</Typography> </Typography>
<Box mb={2} color="warning.main"> <Box mb={2} color="warning.main">
<Typography variant="body2">{LL.UPLOAD_TEXT()} </Typography> <Typography variant="body2">
{LL.UPLOAD_TEXT()}
<br />
<br />
{LL.RESTART_TEXT(1)}.
</Typography>
</Box> </Box>
{md5 && ( {md5 && (
<Box mb={2}> <Box mb={2}>
@@ -127,8 +148,34 @@ const UploadFileForm: FC = () => {
<SingleUpload onDrop={startUpload} onCancel={cancelUpload} isUploading={isUploading} progress={progress} /> <SingleUpload onDrop={startUpload} onCancel={cancelUpload} isUploading={isUploading} progress={progress} />
{!isUploading && ( {!isUploading && (
<> <>
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary"> <Typography sx={{ pt: 4, pb: 2 }} variant="h6" color="primary">
{LL.DOWNLOAD(0)} {LL.DOWNLOAD(0)}&nbsp;{LL.SUPPORT_INFORMATION(1)}
</Typography>
<Box color="warning.main">
<Typography mb={1} variant="body2">
{LL.HELP_INFORMATION_4()}
</Typography>
</Box>
<Button
startIcon={<DownloadIcon />}
variant="outlined"
color="primary"
onClick={() => callAPI('system', 'info')}
>
{LL.SUPPORT_INFORMATION(0)}
</Button>
<Button
sx={{ ml: 2 }}
startIcon={<DownloadIcon />}
variant="outlined"
color="primary"
onClick={() => callAPI('system', 'allvalues')}
>
All Values
</Button>
<Typography sx={{ pt: 4, pb: 2 }} variant="h6" color="primary">
{LL.DOWNLOAD(0)}&nbsp;{LL.SETTINGS(1)}
</Typography> </Typography>
<Box color="warning.main"> <Box color="warning.main">
<Typography mb={1} variant="body2"> <Typography mb={1} variant="body2">
@@ -140,7 +187,7 @@ const UploadFileForm: FC = () => {
</Button> </Button>
<Box color="warning.main"> <Box color="warning.main">
<Typography mt={2} mb={1} variant="body2"> <Typography mt={2} mb={1} variant="body2">
{LL.DOWNLOAD_CUSTOMIZATION_TEXT()}{' '} {LL.DOWNLOAD_CUSTOMIZATION_TEXT()}
</Typography> </Typography>
</Box> </Box>
<Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={downloadCustomizations}> <Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={downloadCustomizations}>
@@ -157,7 +204,7 @@ const UploadFileForm: FC = () => {
</Button> </Button>
<Box color="warning.main"> <Box color="warning.main">
<Typography mt={2} mb={1} variant="body2"> <Typography mt={2} mb={1} variant="body2">
{LL.DOWNLOAD_SCHEDULE_TEXT()}{' '} {LL.DOWNLOAD_SCHEDULE_TEXT()}
</Typography> </Typography>
</Box> </Box>
<Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={downloadSchedule}> <Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={downloadSchedule}>

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 85.333 512 341.333"><path fill="#FFF" d="M0 85.337h512v341.326H0z"/><path fill="#0052B4" d="M0 196.641h512v118.717H0z"/><path fill="#D80027" d="M0 315.359h512v111.304H0z"/><path fill="#FFF" d="M129.468 181.799v85.136c0 48.429 63.267 63.267 63.267 63.267S256 315.362 256 266.935v-85.136H129.468z"/><path fill="#D80027" d="M146.126 184.294v81.941c0 5.472 1.215 10.64 3.623 15.485h85.97c2.408-4.844 3.623-10.012 3.623-15.485v-81.941h-93.216z"/><path fill="#FFF" d="M221.301 241.427h-21.425v-14.283h14.284v-14.283h-14.284v-14.284h-14.283v14.284h-14.282v14.283h14.282v14.283h-21.426v14.284h21.426v14.283h14.283v-14.283h21.425z"/><path fill="#0052B4" d="M169.232 301.658c9.204 5.783 18.66 9.143 23.502 10.636 4.842-1.494 14.298-4.852 23.502-10.636 9.282-5.833 15.79-12.506 19.484-19.939a24.878 24.878 0 0 0-14.418-4.583c-1.956 0-3.856.232-5.682.657-3.871-8.796-12.658-14.94-22.884-14.94-10.227 0-19.013 6.144-22.884 14.94a25.048 25.048 0 0 0-5.682-.657 24.88 24.88 0 0 0-14.418 4.583c3.691 7.433 10.198 14.106 19.48 19.939z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -126,6 +126,7 @@ const de: Translation = {
BYPASS_TOKEN: 'Zugriffstoken-Autorisierung bei API-Aufrufen umgehen', BYPASS_TOKEN: 'Zugriffstoken-Autorisierung bei API-Aufrufen umgehen',
READONLY: 'Nur-Lese-Modus aktivieren (blockiert alle ausgehenden EMS Tx Write-Befehle)', READONLY: 'Nur-Lese-Modus aktivieren (blockiert alle ausgehenden EMS Tx Write-Befehle)',
UNDERCLOCK_CPU: 'CPU-Geschwindigkeit untertakten', UNDERCLOCK_CPU: 'CPU-Geschwindigkeit untertakten',
HEATINGOFF: 'Heizen ausschalten beim EMS-ESP Start',
ENABLE_SHOWER_TIMER: 'Duschtimer aktivieren', ENABLE_SHOWER_TIMER: 'Duschtimer aktivieren',
ENABLE_SHOWER_ALERT: 'Duschalarm aktivieren', ENABLE_SHOWER_ALERT: 'Duschalarm aktivieren',
TRIGGER_TIME: 'Auslösezeit', TRIGGER_TIME: 'Auslösezeit',
@@ -170,7 +171,6 @@ const de: Translation = {
HELP_INFORMATION_3: 'Um neue Funktionen anzufragen oder Fehler zu melden, eröffnen Sie ein Issue auf Github', HELP_INFORMATION_3: 'Um neue Funktionen anzufragen oder Fehler zu melden, eröffnen Sie ein Issue auf Github',
HELP_INFORMATION_4: 'Bitte laden Sie die System-Details und hängen Sie sie an das Support-Issue an. ', HELP_INFORMATION_4: 'Bitte laden Sie die System-Details und hängen Sie sie an das Support-Issue an. ',
HELP_INFORMATION_5: 'EMS-ESP ist ein freies Open-Source Projekt. Bitte unterstützen Sie die zukünftige Entwicklung mit einem "Star" auf Github!', HELP_INFORMATION_5: 'EMS-ESP ist ein freies Open-Source Projekt. Bitte unterstützen Sie die zukünftige Entwicklung mit einem "Star" auf Github!',
SUPPORT_INFO: 'Support Info',
UPLOAD: 'Hochladen', UPLOAD: 'Hochladen',
DOWNLOAD: '{{H|h|h}}erunterladen', DOWNLOAD: '{{H|h|h}}erunterladen',
ABORTED: 'abgebrochen', ABORTED: 'abgebrochen',
@@ -191,16 +191,14 @@ const de: Translation = {
THE_LATEST: 'Die neueste', THE_LATEST: 'Die neueste',
OFFICIAL: 'offizielle', OFFICIAL: 'offizielle',
DEVELOPMENT: 'Entwicklungs', DEVELOPMENT: 'Entwicklungs',
RELEASE_IS: 'release ist', // TODO translate RELEASE_IS: 'Release ist',
RELEASE_NOTES: 'Versionshinweise', RELEASE_NOTES: 'Versionshinweise',
EMS_ESP_VER: 'EMS-ESP Version', EMS_ESP_VER: 'EMS-ESP Version',
PLATFORM: 'Platform (Platform / SDK)',
UPTIME: 'System Betriebszeit', UPTIME: 'System Betriebszeit',
CPU_FREQ: 'CPU Frequenz',
HEAP: 'freier RAM Speicher (Gesamt / max. Block)', HEAP: 'freier RAM Speicher (Gesamt / max. Block)',
PSRAM: 'PSRAM (Größe / Frei)', PSRAM: 'PSRAM (Größe / Frei)',
FLASH: 'Flash Speicher (Größe / Geschwindigkeit)', FLASH: 'Flash Speicher (Größe / Geschwindigkeit)',
APPSIZE: 'Programm (Genutzt / Frei)', APPSIZE: 'Programm (Partition: Genutzt / Frei)',
FILESYSTEM: 'Dateisystem (Genutzt / Frei)', FILESYSTEM: 'Dateisystem (Genutzt / Frei)',
BUFFER_SIZE: 'max. Puffergröße', BUFFER_SIZE: 'max. Puffergröße',
COMPACT: 'Kompakte Darstellung', COMPACT: 'Kompakte Darstellung',
@@ -282,6 +280,7 @@ const de: Translation = {
NETWORK_SCANNER: 'Netzwerk Suche', NETWORK_SCANNER: 'Netzwerk Suche',
NETWORK_NO_WIFI: 'Keine WiFi Netzwerke gefunden', NETWORK_NO_WIFI: 'Keine WiFi Netzwerke gefunden',
NETWORK_BLANK_SSID: 'Freilassen um WiFi zu deaktivieren und ETH zu aktivieren', NETWORK_BLANK_SSID: 'Freilassen um WiFi zu deaktivieren und ETH zu aktivieren',
NETWORK_BLANK_BSSID: 'Freilassen um nur SSID für die Verbindung zu nutzen',
TX_POWER: 'Tx Leistung', TX_POWER: 'Tx Leistung',
HOSTNAME: 'Hostname', HOSTNAME: 'Hostname',
NETWORK_DISABLE_SLEEP: 'Deaktiviere WiFi Schlafmodus', NETWORK_DISABLE_SLEEP: 'Deaktiviere WiFi Schlafmodus',
@@ -308,7 +307,7 @@ const de: Translation = {
LEAVE: 'Verlassen', LEAVE: 'Verlassen',
SCHEDULER: 'Planer', SCHEDULER: 'Planer',
SCHEDULER_HELP_1: 'Fügen Sie eigene, geplante Befehle zur Automatisierung hinzu. Vergeben Sie einen Entitätsnamen um die Aktivierung über API/Mqtt zu steuern', SCHEDULER_HELP_1: 'Fügen Sie eigene, geplante Befehle zur Automatisierung hinzu. Vergeben Sie einen Entitätsnamen um die Aktivierung über API/Mqtt zu steuern',
SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate SCHEDULER_HELP_2: '00:00 aktiviert einmalige Ausführung am Start',
SCHEDULE: 'Zeitplan', SCHEDULE: 'Zeitplan',
TIME: 'Zeit', TIME: 'Zeit',
TIMER: 'Timer', TIMER: 'Timer',
@@ -317,12 +316,20 @@ const de: Translation = {
SCHEDULE_TIMER_2: 'jede Minute', SCHEDULE_TIMER_2: 'jede Minute',
SCHEDULE_TIMER_3: 'jede Stunde', SCHEDULE_TIMER_3: 'jede Stunde',
CUSTOM_ENTITIES: 'Individuelle Entitäten', CUSTOM_ENTITIES: 'Individuelle Entitäten',
ENTITIES_HELP_1: 'Abfrage von Werten auf dem EMS-Bus', ENTITIES_HELP_1: 'Definition eigener EMS-Werte oder dynamischer Variablen',
ENTITIES_UPDATED: 'Entitäten gespeichert', ENTITIES_UPDATED: 'Entitäten gespeichert',
WRITEABLE: 'Schreibbar', WRITEABLE: 'Schreibbar',
SHOWING: 'Anzeigen von', SHOWING: 'Anzeigen von',
SEARCH: 'Suche', SEARCH: 'Suche',
CERT: 'TSL Zertifikat (Freilassen um TSL zu deaktivieren)' CERT: 'TLS Zertifikat (Freilassen für unsichere Verbindung)',
ENABLE_TLS: 'Aktiviere TLS',
ON: 'An',
OFF: 'Aus',
POLARITY: 'Polarität',
ACTIVEHIGH: 'Aktiv Positiv',
ACTIVELOW: 'Aktiv Negativ',
UNCHANGED: 'Unverändert',
ALWAYS: 'Immer'
}; };
export default de; export default de;

View File

@@ -63,7 +63,7 @@ const en: Translation = {
FREQ: 'Frequency', FREQ: 'Frequency',
DUTY_CYCLE: 'Duty Cycle', DUTY_CYCLE: 'Duty Cycle',
UNIT: 'UoM', UNIT: 'UoM',
STARTVALUE: 'Start value', STARTVALUE: 'Start Value',
WARN_GPIO: 'Warning: be careful when assigning a GPIO!', WARN_GPIO: 'Warning: be careful when assigning a GPIO!',
EDIT: 'Edit', EDIT: 'Edit',
SENSOR: 'Sensor', SENSOR: 'Sensor',
@@ -126,6 +126,7 @@ const en: Translation = {
BYPASS_TOKEN: 'Bypass Access Token authorization on API calls', BYPASS_TOKEN: 'Bypass Access Token authorization on API calls',
READONLY: 'Enable read-only mode (blocks all outgoing EMS Tx Write commands)', READONLY: 'Enable read-only mode (blocks all outgoing EMS Tx Write commands)',
UNDERCLOCK_CPU: 'Underclock CPU speed', UNDERCLOCK_CPU: 'Underclock CPU speed',
HEATINGOFF: 'Start boiler with forced heating off',
ENABLE_SHOWER_TIMER: 'Enable Shower Timer', ENABLE_SHOWER_TIMER: 'Enable Shower Timer',
ENABLE_SHOWER_ALERT: 'Enable Shower Alert', ENABLE_SHOWER_ALERT: 'Enable Shower Alert',
TRIGGER_TIME: 'Trigger Time', TRIGGER_TIME: 'Trigger Time',
@@ -168,9 +169,8 @@ const en: Translation = {
HELP_INFORMATION_1: 'Visit the online wiki to get instructions on how to configure EMS-ESP', HELP_INFORMATION_1: 'Visit the online wiki to get instructions on how to configure EMS-ESP',
HELP_INFORMATION_2: 'For live community chat join our Discord server', HELP_INFORMATION_2: 'For live community chat join our Discord server',
HELP_INFORMATION_3: 'To request a feature or report a bug', HELP_INFORMATION_3: 'To request a feature or report a bug',
HELP_INFORMATION_4: 'remember to download and attach your system information for a faster response when reporting an issue', HELP_INFORMATION_4: 'Remember to download and attach your support information for a faster response when reporting an issue',
HELP_INFORMATION_5: 'EMS-ESP is a free and open-source project. Please support its future development by giving it a star on Github!', HELP_INFORMATION_5: 'EMS-ESP is a free and open-source project. Please support its future development by giving it a star on Github!',
SUPPORT_INFO: 'Support Info',
UPLOAD: 'Upload', UPLOAD: 'Upload',
DOWNLOAD: '{{D|d|d}}ownload', DOWNLOAD: '{{D|d|d}}ownload',
ABORTED: 'aborted', ABORTED: 'aborted',
@@ -196,11 +196,10 @@ const en: Translation = {
EMS_ESP_VER: 'EMS-ESP Version', EMS_ESP_VER: 'EMS-ESP Version',
PLATFORM: 'Device (Platform / SDK)', PLATFORM: 'Device (Platform / SDK)',
UPTIME: 'System Uptime', UPTIME: 'System Uptime',
CPU_FREQ: 'CPU Frequency',
HEAP: 'Heap (Free / Max Alloc)', HEAP: 'Heap (Free / Max Alloc)',
PSRAM: 'PSRAM (Size / Free)', PSRAM: 'PSRAM (Size / Free)',
FLASH: 'Flash Chip (Size / Speed)', FLASH: 'Flash Chip (Size / Speed)',
APPSIZE: 'Application (Used / Free)', APPSIZE: 'Application (Partition: Used / Free)',
FILESYSTEM: 'File System (Used / Free)', FILESYSTEM: 'File System (Used / Free)',
BUFFER_SIZE: 'Max Buffer Size', BUFFER_SIZE: 'Max Buffer Size',
COMPACT: 'Compact', COMPACT: 'Compact',
@@ -230,7 +229,7 @@ const en: Translation = {
BROKER: 'Broker', BROKER: 'Broker',
CLIENT: 'Client', CLIENT: 'Client',
BASE_TOPIC: 'Base', BASE_TOPIC: 'Base',
OPTIONAL: 'Optional', OPTIONAL: 'optional',
FORMATTING: 'Formatting', FORMATTING: 'Formatting',
MQTT_FORMAT: 'Topic/Payload Format', MQTT_FORMAT: 'Topic/Payload Format',
MQTT_NEST_1: 'Nested in a single topic', MQTT_NEST_1: 'Nested in a single topic',
@@ -282,6 +281,7 @@ const en: Translation = {
NETWORK_SCANNER: 'Network Scanner', NETWORK_SCANNER: 'Network Scanner',
NETWORK_NO_WIFI: 'No WiFi networks found', NETWORK_NO_WIFI: 'No WiFi networks found',
NETWORK_BLANK_SSID: 'leave blank to disable WiFi and enable ETH', NETWORK_BLANK_SSID: 'leave blank to disable WiFi and enable ETH',
NETWORK_BLANK_BSSID: 'leave blank to use only SSID',
TX_POWER: 'Tx Power', TX_POWER: 'Tx Power',
HOSTNAME: 'Hostname', HOSTNAME: 'Hostname',
NETWORK_DISABLE_SLEEP: 'Disable WiFi Sleep Mode', NETWORK_DISABLE_SLEEP: 'Disable WiFi Sleep Mode',
@@ -317,12 +317,20 @@ const en: Translation = {
SCHEDULE_TIMER_2: 'every minute', SCHEDULE_TIMER_2: 'every minute',
SCHEDULE_TIMER_3: 'every hour', SCHEDULE_TIMER_3: 'every hour',
CUSTOM_ENTITIES: 'Custom Entities', CUSTOM_ENTITIES: 'Custom Entities',
ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', ENTITIES_HELP_1: 'Define custom EMS entities or dynamic user variables',
ENTITIES_UPDATED: 'Entities Updated', ENTITIES_UPDATED: 'Entities Updated',
WRITEABLE: 'Writeable', WRITEABLE: 'Writeable',
SHOWING: 'Showing', SHOWING: 'Showing',
SEARCH: 'Search', SEARCH: 'Search',
CERT: 'TSL root certificate (leave blank to disable TSL)' CERT: 'TLS root certificate (leave blank for insecure)',
ENABLE_TLS: 'Enable TLS',
ON: 'On',
OFF: 'Off',
POLARITY: 'Polarity',
ACTIVEHIGH: 'Active High',
ACTIVELOW: 'Active Low',
UNCHANGED: 'Unchanged',
ALWAYS: 'Always'
}; };
export default en; export default en;

View File

@@ -126,6 +126,7 @@ const fr: Translation = {
BYPASS_TOKEN: 'Contourner l\'autorisation du jeton d\'accès sur les appels API', BYPASS_TOKEN: 'Contourner l\'autorisation du jeton d\'accès sur les appels API',
READONLY: 'Activer le mode lecture uniquement (bloque toutes les commandes EMS sortantes en écriture Tx)', READONLY: 'Activer le mode lecture uniquement (bloque toutes les commandes EMS sortantes en écriture Tx)',
UNDERCLOCK_CPU: 'Underclock du CPU', UNDERCLOCK_CPU: 'Underclock du CPU',
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
ENABLE_SHOWER_TIMER: 'Activer la minuterie de la douche', ENABLE_SHOWER_TIMER: 'Activer la minuterie de la douche',
ENABLE_SHOWER_ALERT: 'Activer les alertes de durée de douche', ENABLE_SHOWER_ALERT: 'Activer les alertes de durée de douche',
TRIGGER_TIME: 'Durée avant déclenchement', TRIGGER_TIME: 'Durée avant déclenchement',
@@ -168,9 +169,8 @@ const fr: Translation = {
HELP_INFORMATION_1: 'Visitez le wiki en ligne pour obtenir des instructions sur la façon de configurer EMS-ESP.', HELP_INFORMATION_1: 'Visitez le wiki en ligne pour obtenir des instructions sur la façon de configurer EMS-ESP.',
HELP_INFORMATION_2: 'Pour une discussion en direct avec la communauté, rejoignez notre serveur Discord', HELP_INFORMATION_2: 'Pour une discussion en direct avec la communauté, rejoignez notre serveur Discord',
HELP_INFORMATION_3: 'Pour demander une fonctionnalité ou signaler un problème', HELP_INFORMATION_3: 'Pour demander une fonctionnalité ou signaler un problème',
HELP_INFORMATION_4: 'n\'oubliez pas de télécharger et de joindre les informations relatives à votre système pour obtenir une réponse plus rapide lorsque vous signalez un problème', HELP_INFORMATION_4: 'N\'oubliez pas de télécharger et de joindre les informations relatives à votre système pour obtenir une réponse plus rapide lorsque vous signalez un problème',
HELP_INFORMATION_5: 'EMS-ESP est un projet libre et open-source. Merci de soutenir son développement futur en lui donnant une étoile sur Github !', HELP_INFORMATION_5: 'EMS-ESP est un projet libre et open-source. Merci de soutenir son développement futur en lui donnant une étoile sur Github !',
SUPPORT_INFO: 'Information de support',
UPLOAD: 'Upload', UPLOAD: 'Upload',
DOWNLOAD: '{{D|d|d}}ownload', DOWNLOAD: '{{D|d|d}}ownload',
ABORTED: 'annulé', ABORTED: 'annulé',
@@ -194,13 +194,11 @@ const fr: Translation = {
RELEASE_IS: 'release est', // TODO translate RELEASE_IS: 'release est', // TODO translate
RELEASE_NOTES: 'notes de version', RELEASE_NOTES: 'notes de version',
EMS_ESP_VER: 'Version EMS-ESP', EMS_ESP_VER: 'Version EMS-ESP',
PLATFORM: 'Appareil (Plateforme / SDK)',
UPTIME: 'Durée de fonctionnement du système', UPTIME: 'Durée de fonctionnement du système',
CPU_FREQ: 'Fréquence du CPU',
HEAP: 'Heap (Libre / Max Allouée)', HEAP: 'Heap (Libre / Max Allouée)',
PSRAM: 'PSRAM (Taille / Libre)', PSRAM: 'PSRAM (Taille / Libre)',
FLASH: 'Flash Chip (Taille / Vitesse)', FLASH: 'Flash Chip (Taille / Vitesse)',
APPSIZE: 'Application (Utilisée / Libre)', APPSIZE: 'Application (Partition: Utilisée / Libre)',
FILESYSTEM: 'File System (Utilisée / Libre)', FILESYSTEM: 'File System (Utilisée / Libre)',
BUFFER_SIZE: 'Max taille du buffer', BUFFER_SIZE: 'Max taille du buffer',
COMPACT: 'Compact', COMPACT: 'Compact',
@@ -230,7 +228,7 @@ const fr: Translation = {
BROKER: 'Broker', BROKER: 'Broker',
CLIENT: 'Client', CLIENT: 'Client',
BASE_TOPIC: 'Base', BASE_TOPIC: 'Base',
OPTIONAL: 'Optionnel', OPTIONAL: 'optionnel',
FORMATTING: 'Mise en forme', FORMATTING: 'Mise en forme',
MQTT_FORMAT: 'Format du Topic/Payload', MQTT_FORMAT: 'Format du Topic/Payload',
MQTT_NEST_1: 'Englobé dans un topic unique', MQTT_NEST_1: 'Englobé dans un topic unique',
@@ -282,6 +280,7 @@ const fr: Translation = {
NETWORK_SCANNER: 'Scan réseau', NETWORK_SCANNER: 'Scan réseau',
NETWORK_NO_WIFI: 'Pas de réseau WiFi trouvé', NETWORK_NO_WIFI: 'Pas de réseau WiFi trouvé',
NETWORK_BLANK_SSID: 'laisser vide pour désactiver le WiFi', // and enable ETH // TODO translate NETWORK_BLANK_SSID: 'laisser vide pour désactiver le WiFi', // and enable ETH // TODO translate
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
TX_POWER: 'Puissance Tx', TX_POWER: 'Puissance Tx',
HOSTNAME: 'Nom d\'hôte', HOSTNAME: 'Nom d\'hôte',
NETWORK_DISABLE_SLEEP: 'Désactiver le mode veille du WiFi', NETWORK_DISABLE_SLEEP: 'Désactiver le mode veille du WiFi',
@@ -322,7 +321,15 @@ const fr: Translation = {
WRITEABLE: 'Writeable', // TODO translate WRITEABLE: 'Writeable', // TODO translate
SHOWING: 'Showing', // TODO translate SHOWING: 'Showing', // TODO translate
SEARCH: 'Search', // TODO translate SEARCH: 'Search', // TODO translate
CERT: 'TSL root certificate (leave blank to disable TSL)' // TODO translate CERT: 'TLS root certificate (leave blank for insecure)', // TODO translate
ENABLE_TLS: 'Activer TLS',
ON: 'On', // TODO translate
OFF: 'Off', // TODO translate
POLARITY: 'Polarity', // TODO translate
ACTIVEHIGH: 'Active High', // TODO translate
ACTIVELOW: 'Active Low', // TODO translate
UNCHANGED: 'Unchanged', // TODO translate
ALWAYS: 'Always' // TODO translate
}; };
export default fr; export default fr;

View File

@@ -128,6 +128,7 @@ const it: Translation = {
BYPASS_TOKEN: 'Ignora autorizzazione del token di accesso sulle chiamate API', BYPASS_TOKEN: 'Ignora autorizzazione del token di accesso sulle chiamate API',
READONLY: 'Abilita modalità sola-lettura (blocca tutti i comandi di scrittura EMS Tx in uscita)', READONLY: 'Abilita modalità sola-lettura (blocca tutti i comandi di scrittura EMS Tx in uscita)',
UNDERCLOCK_CPU: 'Abbassa velocità della CPU', UNDERCLOCK_CPU: 'Abbassa velocità della CPU',
HEATINGOFF: 'Avviamento caldaia con riscaldamento forzato spento',
ENABLE_SHOWER_TIMER: 'Abilita timer doccia', ENABLE_SHOWER_TIMER: 'Abilita timer doccia',
ENABLE_SHOWER_ALERT: 'Abilita avviso doccia', ENABLE_SHOWER_ALERT: 'Abilita avviso doccia',
TRIGGER_TIME: 'Tempo di avvio', TRIGGER_TIME: 'Tempo di avvio',
@@ -170,9 +171,8 @@ const it: Translation = {
HELP_INFORMATION_1: 'Visita il wiki online per ottenere istruzioni su come configurare EMS-ESP', HELP_INFORMATION_1: 'Visita il wiki online per ottenere istruzioni su come configurare EMS-ESP',
HELP_INFORMATION_2: 'Per la chat della community dal vivo unisciti al nostro server Discord', HELP_INFORMATION_2: 'Per la chat della community dal vivo unisciti al nostro server Discord',
HELP_INFORMATION_3: 'Per richiedere una funzionalità o segnalare un errore', HELP_INFORMATION_3: 'Per richiedere una funzionalità o segnalare un errore',
HELP_INFORMATION_4: 'ricordati di scaricare e allegare le informazioni del tuo sistema per una risposta più rapida quando segnali un problema', HELP_INFORMATION_4: 'Ricordati di scaricare e allegare le informazioni del tuo sistema per una risposta più rapida quando segnali un problema',
HELP_INFORMATION_5: 'EMS-ESP è un progetto gratuito e open-source. Supporta il suo sviluppo futuro assegnandogli una stella su Github!', HELP_INFORMATION_5: 'EMS-ESP è un progetto gratuito e open-source. Supporta il suo sviluppo futuro assegnandogli una stella su Github!',
SUPPORT_INFO: 'Info Supporto',
UPLOAD: 'Carica', UPLOAD: 'Carica',
DOWNLOAD: 'Scarica', DOWNLOAD: 'Scarica',
ABORTED: 'Annullato', ABORTED: 'Annullato',
@@ -196,13 +196,11 @@ const it: Translation = {
RELEASE_IS: 'rilascio é', RELEASE_IS: 'rilascio é',
RELEASE_NOTES: 'note rilascio', RELEASE_NOTES: 'note rilascio',
EMS_ESP_VER: 'Versione EMS-ESP', EMS_ESP_VER: 'Versione EMS-ESP',
PLATFORM: 'Dispositivo (Piattaforma / SDK)',
UPTIME: 'Tempo di attività del sistema', UPTIME: 'Tempo di attività del sistema',
CPU_FREQ: 'Frequenza CPU ',
HEAP: 'Heap (Free / Max Alloc)', HEAP: 'Heap (Free / Max Alloc)',
PSRAM: 'PSRAM (Size / Free)', PSRAM: 'PSRAM (Size / Free)',
FLASH: 'Flash Chip (Size / Speed)', FLASH: 'Flash Chip (Size / Speed)',
APPSIZE: 'Applicazione (Usata / Libera)', APPSIZE: 'Applicazione (Partizione: Usata / Libera)',
FILESYSTEM: 'Memoria Sistema (Usata / Libera)', FILESYSTEM: 'Memoria Sistema (Usata / Libera)',
BUFFER_SIZE: 'Max Buffer Size', BUFFER_SIZE: 'Max Buffer Size',
COMPACT: 'Compact', COMPACT: 'Compact',
@@ -232,7 +230,7 @@ const it: Translation = {
BROKER: 'Broker', BROKER: 'Broker',
CLIENT: 'Cliente', CLIENT: 'Cliente',
BASE_TOPIC: 'Base', BASE_TOPIC: 'Base',
OPTIONAL: 'Opzionale', OPTIONAL: 'opzionale',
FORMATTING: 'Formattazione', FORMATTING: 'Formattazione',
MQTT_FORMAT: 'Formato Topic/Payload ', MQTT_FORMAT: 'Formato Topic/Payload ',
MQTT_NEST_1: 'Inserito in un singolo argomento', MQTT_NEST_1: 'Inserito in un singolo argomento',
@@ -284,6 +282,7 @@ const it: Translation = {
NETWORK_SCANNER: 'Scansione Rete', NETWORK_SCANNER: 'Scansione Rete',
NETWORK_NO_WIFI: 'Nessuana rete WiFi trovata', NETWORK_NO_WIFI: 'Nessuana rete WiFi trovata',
NETWORK_BLANK_SSID: 'lasciare vuoto per disattivare WiFi', NETWORK_BLANK_SSID: 'lasciare vuoto per disattivare WiFi',
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
TX_POWER: 'Potenza Tx', TX_POWER: 'Potenza Tx',
HOSTNAME: 'Nome ospite', HOSTNAME: 'Nome ospite',
NETWORK_DISABLE_SLEEP: 'Disabilita la modalità sospensione Wi-Fi', NETWORK_DISABLE_SLEEP: 'Disabilita la modalità sospensione Wi-Fi',
@@ -319,12 +318,20 @@ const it: Translation = {
SCHEDULE_TIMER_2: 'Ogni minuto', SCHEDULE_TIMER_2: 'Ogni minuto',
SCHEDULE_TIMER_3: 'Ogni ora', SCHEDULE_TIMER_3: 'Ogni ora',
CUSTOM_ENTITIES: 'Entità personalizzate', CUSTOM_ENTITIES: 'Entità personalizzate',
ENTITIES_HELP_1: 'Recupera entità personalizzate dal BUS EMS', ENTITIES_HELP_1: 'Recupera entità personalizzate dal BUS EMS', // TODO translate
ENTITIES_UPDATED: 'Entità aggiornate', ENTITIES_UPDATED: 'Entità aggiornate',
WRITEABLE: 'Scrivibile', WRITEABLE: 'Scrivibile',
SHOWING: 'Visualizza', SHOWING: 'Visualizza',
SEARCH: 'Ricerca', SEARCH: 'Ricerca',
CERT: 'TSL root certificate (leave blank to disable TSL)' // TODO translate CERT: 'TLS root certificate (leave blank for insecure)', // TODO translate
ENABLE_TLS: 'Abilita TLS',
ON: 'On', // TODO translate
OFF: 'Off', // TODO translate
POLARITY: 'Polarity', // TODO translate
ACTIVEHIGH: 'Active High', // TODO translate
ACTIVELOW: 'Active Low', // TODO translate
UNCHANGED: 'Unchanged', // TODO translate
ALWAYS: 'Always' // TODO translate
}; };
export default it; export default it;

View File

@@ -126,6 +126,7 @@ const nl: Translation = {
BYPASS_TOKEN: 'API Access Token authenticatie uitschakelen', BYPASS_TOKEN: 'API Access Token authenticatie uitschakelen',
READONLY: 'Activeer read-only modus (blokkeert alle outgaande EMS Tx schrijf commandos)', READONLY: 'Activeer read-only modus (blokkeert alle outgaande EMS Tx schrijf commandos)',
UNDERCLOCK_CPU: 'Underclock CPU snelheid', UNDERCLOCK_CPU: 'Underclock CPU snelheid',
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
ENABLE_SHOWER_TIMER: 'Activeer Douche Timer (tijdmeting)', ENABLE_SHOWER_TIMER: 'Activeer Douche Timer (tijdmeting)',
ENABLE_SHOWER_ALERT: 'Activeer Douchemelding', ENABLE_SHOWER_ALERT: 'Activeer Douchemelding',
TRIGGER_TIME: 'Trigger tijd', TRIGGER_TIME: 'Trigger tijd',
@@ -168,9 +169,8 @@ const nl: Translation = {
HELP_INFORMATION_1: 'Bezoek de online wiki om instructies te vinden om EMS-ESP te configureren', HELP_INFORMATION_1: 'Bezoek de online wiki om instructies te vinden om EMS-ESP te configureren',
HELP_INFORMATION_2: 'Voor de live community ga naar de Discord server', HELP_INFORMATION_2: 'Voor de live community ga naar de Discord server',
HELP_INFORMATION_3: 'Om een nieuwe feature te vragen of een bug te rapporteren', HELP_INFORMATION_3: 'Om een nieuwe feature te vragen of een bug te rapporteren',
HELP_INFORMATION_4: 'zorg dat je ook je systeem details zijn toevoeged voor een sneller antwoord', HELP_INFORMATION_4: 'Zorg dat je ook je systeem details zijn toevoeged voor een sneller antwoord',
HELP_INFORMATION_5: 'EMS-ESP is een gratis en open source project. Steun ons met een Star op Github!', HELP_INFORMATION_5: 'EMS-ESP is een gratis en open source project. Steun ons met een Star op Github!',
SUPPORT_INFO: 'Support Info',
UPLOAD: 'Upload', UPLOAD: 'Upload',
DOWNLOAD: '{{D|d|d}}ownload', DOWNLOAD: '{{D|d|d}}ownload',
ABORTED: 'afgebroken', ABORTED: 'afgebroken',
@@ -194,13 +194,11 @@ const nl: Translation = {
RELEASE_IS: 'release is', RELEASE_IS: 'release is',
RELEASE_NOTES: 'release notes', RELEASE_NOTES: 'release notes',
EMS_ESP_VER: 'EMS-ESP Versie', EMS_ESP_VER: 'EMS-ESP Versie',
PLATFORM: 'Apparaat (Platform / SDK)',
UPTIME: 'Systeem Uptime', UPTIME: 'Systeem Uptime',
CPU_FREQ: 'CPU Frequency',
HEAP: 'Heap (Free / Max Alloc)', HEAP: 'Heap (Free / Max Alloc)',
PSRAM: 'PSRAM (Size / Free)', PSRAM: 'PSRAM (Size / Free)',
FLASH: 'Flash Chip (Size / Speed)', FLASH: 'Flash Chip (Size / Speed)',
APPSIZE: 'Application (Used / Free)', APPSIZE: 'Application (Partition: Used / Free)',
FILESYSTEM: 'File System (Used / Free)', FILESYSTEM: 'File System (Used / Free)',
BUFFER_SIZE: 'Max Buffer Size', BUFFER_SIZE: 'Max Buffer Size',
COMPACT: 'Compact', COMPACT: 'Compact',
@@ -230,7 +228,7 @@ const nl: Translation = {
BROKER: 'Broker', BROKER: 'Broker',
CLIENT: 'Client', CLIENT: 'Client',
BASE_TOPIC: 'Base', BASE_TOPIC: 'Base',
OPTIONAL: 'Optioneel', OPTIONAL: 'optioneel',
FORMATTING: 'Formatteren', FORMATTING: 'Formatteren',
MQTT_FORMAT: 'Topic/Payload Formattering', MQTT_FORMAT: 'Topic/Payload Formattering',
MQTT_NEST_1: 'Genest in 1 topic', MQTT_NEST_1: 'Genest in 1 topic',
@@ -282,6 +280,7 @@ const nl: Translation = {
NETWORK_SCANNER: 'Netwerk Scanner', NETWORK_SCANNER: 'Netwerk Scanner',
NETWORK_NO_WIFI: 'Geen WiFi networken gevonden', NETWORK_NO_WIFI: 'Geen WiFi networken gevonden',
NETWORK_BLANK_SSID: 'laat leeg om WiFi uit te schakelen', NETWORK_BLANK_SSID: 'laat leeg om WiFi uit te schakelen',
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
TX_POWER: 'Tx Vermogen', TX_POWER: 'Tx Vermogen',
HOSTNAME: 'Hostname', HOSTNAME: 'Hostname',
NETWORK_DISABLE_SLEEP: 'WiFi Sleep Mode uitzetten', NETWORK_DISABLE_SLEEP: 'WiFi Sleep Mode uitzetten',
@@ -317,12 +316,20 @@ const nl: Translation = {
SCHEDULE_TIMER_2: 'elke minuut', SCHEDULE_TIMER_2: 'elke minuut',
SCHEDULE_TIMER_3: 'elke huur', SCHEDULE_TIMER_3: 'elke huur',
CUSTOM_ENTITIES: 'Aangepaste Entiteiten', CUSTOM_ENTITIES: 'Aangepaste Entiteiten',
ENTITIES_HELP_1: 'Aangepaste entiteiten ophalen uit de EMS-bus', ENTITIES_HELP_1: 'Aangepaste entiteiten ophalen uit de EMS-bus', // TODO translate
ENTITIES_UPDATED: 'Entiteiten bijgewerkt', ENTITIES_UPDATED: 'Entiteiten bijgewerkt',
WRITEABLE: 'Beschrijfbare', WRITEABLE: 'Beschrijfbare',
SHOWING: 'Tonen', SHOWING: 'Tonen',
SEARCH: 'Zoek', SEARCH: 'Zoek',
CERT: 'TSL rootcertificaat (laat leeg om TSL uit te schakelen)' CERT: 'TLS rootcertificaat (laat leeg om TLS-insecure)', // TODO translate
ENABLE_TLS: 'Activeer TLS',
ON: 'On', // TODO translate
OFF: 'Off', // TODO translate
POLARITY: 'Polarity', // TODO translate
ACTIVEHIGH: 'Active High', // TODO translate
ACTIVELOW: 'Active Low', // TODO translate
UNCHANGED: 'Unchanged', // TODO translate
ALWAYS: 'Always' // TODO translate
}; };
export default nl; export default nl;

View File

@@ -126,6 +126,7 @@ const no: Translation = {
BYPASS_TOKEN: 'Utelat Aksess Token authorisering av API kall', BYPASS_TOKEN: 'Utelat Aksess Token authorisering av API kall',
READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)', READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)',
UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet', UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet',
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer', ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer',
ENABLE_SHOWER_ALERT: 'Aktiver Dusj-varsling', ENABLE_SHOWER_ALERT: 'Aktiver Dusj-varsling',
TRIGGER_TIME: 'Aktiveringstid', TRIGGER_TIME: 'Aktiveringstid',
@@ -168,9 +169,8 @@ const no: Translation = {
HELP_INFORMATION_1: 'Besøk wiki for instruksjoner for å konfigurere EMS-ESP', HELP_INFORMATION_1: 'Besøk wiki for instruksjoner for å konfigurere EMS-ESP',
HELP_INFORMATION_2: 'For community-support besøk vår Discord-server', HELP_INFORMATION_2: 'For community-support besøk vår Discord-server',
HELP_INFORMATION_3: 'For å be om en ny funksjon eller melde feil', HELP_INFORMATION_3: 'For å be om en ny funksjon eller melde feil',
HELP_INFORMATION_4: 'husk å laste ned og legg ved din systeminformasjon for en raskere respons når du rapporterer et problem', HELP_INFORMATION_4: 'Husk å laste ned og legg ved din systeminformasjon for en raskere respons når du rapporterer et problem',
HELP_INFORMATION_5: 'EMS-ESP er gratis og åpen kildekode. Bidra til utviklingen ved å gi oss en stjerne på GitHub!', HELP_INFORMATION_5: 'EMS-ESP er gratis og åpen kildekode. Bidra til utviklingen ved å gi oss en stjerne på GitHub!',
SUPPORT_INFO: 'Supportinfo',
UPLOAD: 'Opplasning', UPLOAD: 'Opplasning',
DOWNLOAD: '{{N|n|n}}edlasting', DOWNLOAD: '{{N|n|n}}edlasting',
ABORTED: 'avbrutt', ABORTED: 'avbrutt',
@@ -194,13 +194,11 @@ const no: Translation = {
RELEASE_IS: 'release er', RELEASE_IS: 'release er',
RELEASE_NOTES: 'release notes', RELEASE_NOTES: 'release notes',
EMS_ESP_VER: 'EMS-ESP Version', EMS_ESP_VER: 'EMS-ESP Version',
PLATFORM: 'Enhet (Platform / SDK)',
UPTIME: 'System Oppetid', UPTIME: 'System Oppetid',
CPU_FREQ: 'CPU Frekvens',
HEAP: 'Heap (Ledig / Max Allokert)', HEAP: 'Heap (Ledig / Max Allokert)',
PSRAM: 'PSRAM (Størrelse / Ledig)', PSRAM: 'PSRAM (Størrelse / Ledig)',
FLASH: 'Flash Chip (Størrelse / Hastighet)', FLASH: 'Flash Chip (Størrelse / Hastighet)',
APPSIZE: 'Applikasjon (Brukt / Ledig)', APPSIZE: 'Applikasjon (Partition: Brukt / Ledig)',
FILESYSTEM: 'File System (Brukt / Ledig)', FILESYSTEM: 'File System (Brukt / Ledig)',
BUFFER_SIZE: 'Max Buffer Størrelse', BUFFER_SIZE: 'Max Buffer Størrelse',
COMPACT: 'Komprimere', COMPACT: 'Komprimere',
@@ -230,7 +228,7 @@ const no: Translation = {
BROKER: 'Broker', BROKER: 'Broker',
CLIENT: 'Client', CLIENT: 'Client',
BASE_TOPIC: 'Base', BASE_TOPIC: 'Base',
OPTIONAL: 'Valgfritt', OPTIONAL: 'valgfritt',
FORMATTING: 'Formatering', FORMATTING: 'Formatering',
MQTT_FORMAT: 'Topic/Payload Format', MQTT_FORMAT: 'Topic/Payload Format',
MQTT_NEST_1: 'Nestet i en topic', MQTT_NEST_1: 'Nestet i en topic',
@@ -282,6 +280,7 @@ const no: Translation = {
NETWORK_SCANNER: 'Nettverk Scanner', NETWORK_SCANNER: 'Nettverk Scanner',
NETWORK_NO_WIFI: 'Ingen trådløse nett funnet', NETWORK_NO_WIFI: 'Ingen trådløse nett funnet',
NETWORK_BLANK_SSID: 'la feltet være blankt for å deaktivisere trådløst nettverk', // TODO translate NETWORK_BLANK_SSID: 'la feltet være blankt for å deaktivisere trådløst nettverk', // TODO translate
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
TX_POWER: 'Tx Effekt', TX_POWER: 'Tx Effekt',
HOSTNAME: 'Hostname', HOSTNAME: 'Hostname',
NETWORK_DISABLE_SLEEP: 'Hindre at trådløst nettverk går i Sleep Mode', NETWORK_DISABLE_SLEEP: 'Hindre at trådløst nettverk går i Sleep Mode',
@@ -322,7 +321,15 @@ const no: Translation = {
WRITEABLE: 'Writeable', // TODO translate WRITEABLE: 'Writeable', // TODO translate
SHOWING: 'Showing', // TODO translate SHOWING: 'Showing', // TODO translate
SEARCH: 'Search', // TODO translate SEARCH: 'Search', // TODO translate
CERT: 'TSL root certificate (leave blank to disable TSL)' // TODO translate CERT: 'TLS root certificate (leave blank for insecure)', // TODO translate
ENABLE_TLS: 'Aktiviser TLS',
ON: 'On', // TODO translate
OFF: 'Off', // TODO translate
POLARITY: 'Polarity', // TODO translate
ACTIVEHIGH: 'Active High', // TODO translate
ACTIVELOW: 'Active Low', // TODO translate
UNCHANGED: 'Unchanged', // TODO translate
ALWAYS: 'Always' // TODO translate
}; };
export default no; export default no;

View File

@@ -53,7 +53,7 @@ const pl: BaseTranslation = {
PROBLEM_LOADING: 'Problem z załadowaniem!', PROBLEM_LOADING: 'Problem z załadowaniem!',
ANALOG_SENSOR: '{{u|u||ustawienia u|ustawień u}}rządzeni{{a podłączonego do EMS-ESP|e||a podłączonego do EMS-ESP|a podłączonego do EMS-ESP}}', ANALOG_SENSOR: '{{u|u||ustawienia u|ustawień u}}rządzeni{{a podłączonego do EMS-ESP|e||a podłączonego do EMS-ESP|a podłączonego do EMS-ESP}}',
ANALOG_SENSORS: 'Urządzenia podłączone do EMS-ESP', ANALOG_SENSORS: 'Urządzenia podłączone do EMS-ESP',
SETTINGS: 'ustawienia', SETTINGS: 'ustawie{{nia|ń|}}',
UPDATED_OF: 'Zaktualizowano {0}.', UPDATED_OF: 'Zaktualizowano {0}.',
UPDATE_OF: 'Aktualizacja {0}', UPDATE_OF: 'Aktualizacja {0}',
REMOVED_OF: 'Usunięto ustawienia {0}.', REMOVED_OF: 'Usunięto ustawienia {0}.',
@@ -126,6 +126,7 @@ const pl: BaseTranslation = {
BYPASS_TOKEN: 'Pomiń autoryzację tokenem w wywołaniach API', BYPASS_TOKEN: 'Pomiń autoryzację tokenem w wywołaniach API',
READONLY: 'Tryb pracy "tylko do odczytu" (blokuje wszystkie komendy zapisu na magistralę EMS)', READONLY: 'Tryb pracy "tylko do odczytu" (blokuje wszystkie komendy zapisu na magistralę EMS)',
UNDERCLOCK_CPU: 'Obniż taktowanie CPU', UNDERCLOCK_CPU: 'Obniż taktowanie CPU',
HEATINGOFF: 'Uruchom kocioł z wymuszonym wyłączonym grzaniem',
ENABLE_SHOWER_TIMER: 'Aktywuj minutnik prysznica', ENABLE_SHOWER_TIMER: 'Aktywuj minutnik prysznica',
ENABLE_SHOWER_ALERT: 'Aktywuj alarm prysznica', ENABLE_SHOWER_ALERT: 'Aktywuj alarm prysznica',
TRIGGER_TIME: 'Wyzwalaj po czasie', TRIGGER_TIME: 'Wyzwalaj po czasie',
@@ -145,13 +146,13 @@ const pl: BaseTranslation = {
MINUTES: 'minut', MINUTES: 'minut',
HOURS: 'godzin', HOURS: 'godzin',
RESTART: 'Restart', RESTART: 'Restart',
RESTART_TEXT: 'Aby zastosować wprowadzone zmiany interfejs EMS-ESP musi zostać zrestartowany.', RESTART_TEXT: 'Aby zastosować wprowadzone zmiany, interfejs EMS-ESP {{musi zostać|zostanie|}} uruchomiony ponowni{{e.|e|}}',
RESTART_CONFIRM: 'Na pewno chcesz zrestartować interfejs EMS-ESP?', RESTART_CONFIRM: 'Na pewno chcesz zrestartować interfejs EMS-ESP?',
COMMAND: '{{Komenda|KOMENDA|}}', COMMAND: '{{Komenda|KOMENDA|}}',
CUSTOMIZATIONS_RESTART: 'Wszystkie personalizacje zostały usunięte. Restartuję...', CUSTOMIZATIONS_RESTART: 'Wszystkie personalizacje zostały usunięte. Restartuję...',
CUSTOMIZATIONS_FULL: 'Wybrano za dużo obiektów. Wprowadź zmiany w mniejszych partiach.', CUSTOMIZATIONS_FULL: 'Wybrano za dużo obiektów. Wprowadź zmiany w mniejszych partiach.',
CUSTOMIZATIONS_SAVED: 'Personalizacje zostały zapisane.', CUSTOMIZATIONS_SAVED: 'Personalizacje zostały zapisane.',
CUSTOMIZATIONS_HELP_1: 'Wybierz urządzenie EMS, dostosuj opcje lub kliknij by zmienić nazwę encji.', CUSTOMIZATIONS_HELP_1: 'Wybierz urządzenie EMS, a następnie dostosuj opcje lub kliknij na nazwie encji by tę nazwę zmienić',
CUSTOMIZATIONS_HELP_2: 'oznacz jako ulubioną', CUSTOMIZATIONS_HELP_2: 'oznacz jako ulubioną',
CUSTOMIZATIONS_HELP_3: 'zablokuj akcje zapisu', CUSTOMIZATIONS_HELP_3: 'zablokuj akcje zapisu',
CUSTOMIZATIONS_HELP_4: 'wyklucz z MQTT i API', CUSTOMIZATIONS_HELP_4: 'wyklucz z MQTT i API',
@@ -163,14 +164,13 @@ const pl: BaseTranslation = {
NAME: '{{Nazwa|nazwa|}}', NAME: '{{Nazwa|nazwa|}}',
CUSTOMIZATIONS_RESET: 'Na pewno chcesz usunąć wszystkie personalizacje łącznie z ustawieniami dla czujników temperatury 1-Wire® i urządzeń podłączonych do EMS-ESP?', CUSTOMIZATIONS_RESET: 'Na pewno chcesz usunąć wszystkie personalizacje łącznie z ustawieniami dla czujników temperatury 1-Wire® i urządzeń podłączonych do EMS-ESP?',
DEVICE_ENTITIES: 'Encje urządzenia', DEVICE_ENTITIES: 'Encje urządzenia',
SUPPORT_INFORMATION: 'Informacje dotyczące wsparcia', SUPPORT_INFORMATION: '{{I|i|}}nformacj{{e|i|}} o systemie',
CLICK_HERE: 'Kliknij tu', CLICK_HERE: 'Kliknij tu',
HELP_INFORMATION_1: 'Aby uzyskać instrukcje dotyczące konfiguracji EMS-ESP skorzystaj z wiki w internecie', HELP_INFORMATION_1: 'Aby uzyskać instrukcje dotyczące konfiguracji EMS-ESP, skorzystaj z wiki w internecie',
HELP_INFORMATION_2: 'Aby dołączyć do naszego serwera Discord i komunikować się na żywo ze społecznością', HELP_INFORMATION_2: 'Aby dołączyć do naszego serwera Discord i komunikować się na żywo ze społecznością',
HELP_INFORMATION_3: 'Aby zaproponować nową funkcjonalność lub zgłosić problem', HELP_INFORMATION_3: 'Aby zaproponować nową funkcjonalność lub zgłosić problem',
HELP_INFORMATION_4: 'Zgłaszając problem, nie zapomnij dołączyć informacji o swoim systemie!', HELP_INFORMATION_4: 'Zgłaszając problem, nie zapomnij pobrać i dołączyć informacji o swoim systemie!',
HELP_INFORMATION_5: 'EMS-ESP jest darmowym projektem typu open-source. Aby go wesprzeć, rozważ przyznanie nam gwiazdki na Github!', HELP_INFORMATION_5: 'EMS-ESP jest darmowym projektem typu open-source. Aby go wesprzeć, rozważ przyznanie nam gwiazdki na Github!',
SUPPORT_INFO: 'Pobierz informacje',
UPLOAD: 'Wysyłanie', UPLOAD: 'Wysyłanie',
DOWNLOAD: '{{P|p||P}}obier{{anie|z||z}}', DOWNLOAD: '{{P|p||P}}obier{{anie|z||z}}',
ABORTED: 'zostało przerwane!', ABORTED: 'zostało przerwane!',
@@ -194,21 +194,19 @@ const pl: BaseTranslation = {
RELEASE_IS: 'wydanie to', RELEASE_IS: 'wydanie to',
RELEASE_NOTES: 'lista zmian', RELEASE_NOTES: 'lista zmian',
EMS_ESP_VER: 'Wersja EMS-ESP', EMS_ESP_VER: 'Wersja EMS-ESP',
PLATFORM: 'Urządzenie (platforma / SDK)',
UPTIME: 'Czas działania systemu', UPTIME: 'Czas działania systemu',
CPU_FREQ: 'Taktowanie CPU',
HEAP: 'HEAP (wolne / maksymalny przydział)', HEAP: 'HEAP (wolne / maksymalny przydział)',
PSRAM: 'PSRAM (rozmiar / wolne)', PSRAM: 'PSRAM (rozmiar / wolne)',
FLASH: 'FLASH (rozmiar / taktowanie)', FLASH: 'FLASH (rozmiar / taktowanie)',
APPSIZE: 'Aplikacja (wykorzystane / wolne)', APPSIZE: 'Aplikacja (partycja: wykorzystane / wolne)',
FILESYSTEM: 'System plików (wykorzystane / wolne)', FILESYSTEM: 'System plików (wykorzystane / wolne)',
BUFFER_SIZE: 'Maksymalna pojemność bufora (ilość wpisów)', BUFFER_SIZE: 'Maksymalna pojemność bufora (ilość wpisów)',
COMPACT: 'Kompaktowy', COMPACT: 'Kompaktowy',
ENABLE_OTA: 'Aktywuj aktualizację OTA', ENABLE_OTA: 'Aktywuj aktualizację OTA',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Pobierz personalizacje.', DOWNLOAD_CUSTOMIZATION_TEXT: 'Pobierz personalizacje.',
DOWNLOAD_SCHEDULE_TEXT: 'Pobierz harmonogram zdarzeń.', DOWNLOAD_SCHEDULE_TEXT: 'Pobierz harmonogram zdarzeń.',
DOWNLOAD_SETTINGS_TEXT: 'Pobierz ustawienia aplikacji. Uważaj jeśli udostępniasz plik z ustawieniami, ponieważ zawiera on hasła oraz inne wrażliwe informacje!', DOWNLOAD_SETTINGS_TEXT: 'Pobierz ustawienia aplikacji. Uwaga! Plik z ustawieniami zawiera hasła oraz inne wrażliwe informacje systemowe! Nie udostepniaj go pochopnie!',
UPLOAD_TEXT: 'Wyślij firmware (.bin), ustawienia lub personalizacje (.json). Opcjonalnie, wyślij wcześniej plik walidacji (.md5).', UPLOAD_TEXT: 'Wyślij firmware (.bin), ustawienia lub personalizacje (.json). Opcjonalnie, wyślij wcześniej plik walidacji z sumą kontrolną (.md5).',
UPLOADING: 'Wysłano', UPLOADING: 'Wysłano',
UPLOAD_DROP_TEXT: 'Przeciągnij tutaj plik lub kliknij', UPLOAD_DROP_TEXT: 'Przeciągnij tutaj plik lub kliknij',
ERROR: 'Nieoczekiwany błąd, spróbuj ponownie!', ERROR: 'Nieoczekiwany błąd, spróbuj ponownie!',
@@ -281,14 +279,15 @@ const pl: BaseTranslation = {
SCAN_AGAIN: 'Skanuj ponownie', SCAN_AGAIN: 'Skanuj ponownie',
NETWORK_SCANNER: 'Skaner sieci WiFi', NETWORK_SCANNER: 'Skaner sieci WiFi',
NETWORK_NO_WIFI: 'Brak sieci WiFi w zasięgu', NETWORK_NO_WIFI: 'Brak sieci WiFi w zasięgu',
NETWORK_BLANK_SSID: 'pozostaw puste aby wyłączyć WiFi', // and enable ETH // TODO translate NETWORK_BLANK_SSID: 'pozostaw puste aby wyłączyć WiFi i włączyć ETH',
NETWORK_BLANK_BSSID: 'pozostaw puste aby używać tylko SSID',
TX_POWER: 'Moc nadawania', TX_POWER: 'Moc nadawania',
HOSTNAME: 'Nazwa w sieci', HOSTNAME: 'Nazwa w sieci',
NETWORK_DISABLE_SLEEP: 'Wyłącz tryb uśpienia WiFi', NETWORK_DISABLE_SLEEP: 'Wyłącz tryb uśpienia WiFi',
NETWORK_LOW_BAND: 'Używaj mniejszej szerokości pasma WiFi (20MHz)', NETWORK_LOW_BAND: 'Używaj mniejszej szerokości pasma WiFi (20MHz)',
NETWORK_USE_DNS: 'Włącz wsparcie dla mDNS', NETWORK_USE_DNS: 'Włącz wsparcie dla mDNS',
NETWORK_ENABLE_CORS: 'Włącz wsparcie dla CORS', NETWORK_ENABLE_CORS: 'Włącz wsparcie dla CORS',
NETWORK_CORS_ORIGIN: 'CORS origin', NETWORK_CORS_ORIGIN: 'CORS Origin',
NETWORK_ENABLE_IPV6: 'Włącz wsparcie dla IPv6', NETWORK_ENABLE_IPV6: 'Włącz wsparcie dla IPv6',
NETWORK_FIXED_IP: 'Użyj stałego adresu IP', NETWORK_FIXED_IP: 'Użyj stałego adresu IP',
NETWORK_GATEWAY: 'Brama', NETWORK_GATEWAY: 'Brama',
@@ -317,12 +316,20 @@ const pl: BaseTranslation = {
SCHEDULE_TIMER_2: 'co minutę', SCHEDULE_TIMER_2: 'co minutę',
SCHEDULE_TIMER_3: 'co godzinę', SCHEDULE_TIMER_3: 'co godzinę',
CUSTOM_ENTITIES: '{{N|n|}}iestandardowe{{|j|}} encj{{e|i|}}', CUSTOM_ENTITIES: '{{N|n|}}iestandardowe{{|j|}} encj{{e|i|}}',
ENTITIES_HELP_1: 'Zdefiniuj niestandardowe encje dla magistrali EMS.', ENTITIES_HELP_1: 'Zdefiniuj niestandardowe encje dla magistrali EMS.', // TODO translate
ENTITIES_UPDATED: 'Niestandardowe encje zostały uaktualnione.', ENTITIES_UPDATED: 'Niestandardowe encje zostały uaktualnione.',
WRITEABLE: 'zapisywalna', WRITEABLE: 'Zapisywalna',
SHOWING: 'Wyświetlane', SHOWING: 'Wyświetlane',
SEARCH: 'Szukaj', SEARCH: 'Szukaj',
CERT: 'TSL root certificate (leave blank to disable TSL)' // TODO translate CERT: 'Certyfikat główny TLS (pozostaw puste dla TLS-insecure)',
ENABLE_TLS: 'Włącz wsparcie dla TLS',
ON: 'włączony',
OFF: 'wyłączony',
POLARITY: 'Typ przekaźnika',
ACTIVEHIGH: 'Wyzwalany stanem wysokim',
ACTIVELOW: 'Wyzwalany stanem niskim',
UNCHANGED: 'Zachowaj stan',
ALWAYS: 'Zawsze'
}; };
export default pl; export default pl;

View File

@@ -0,0 +1,335 @@
import type { Translation } from '../i18n-types';
/* prettier-ignore */
/* eslint-disable */
const sk: Translation = {
LANGUAGE: 'Jazyk',
RETRY: 'Opakovať',
LOADING: 'Načítanie',
IS_REQUIRED: '{0} je požadovaných',
SIGN_IN: 'Prihlásiť sa',
SIGN_OUT: 'Odhlásiť sa',
USERNAME: 'Užívateľské meno',
PASSWORD: 'Heslo',
SU_PASSWORD: 'su heslo',
DASHBOARD: 'Panel',
SETTINGS_OF: '{0} Nastavenia',
HELP_OF: '{0} Pomoc',
LOGGED_IN: 'Prihlásený ako {name}',
PLEASE_SIGNIN: 'Ak chcete pokračovať, prihláste sa',
UPLOAD_SUCCESSFUL: 'Nahratie úspešné',
DOWNLOAD_SUCCESSFUL: 'Stiahnutie úspešné',
INVALID_LOGIN: 'Nesprávne prihlasovacie údaje',
NETWORK: 'Sieť',
SECURITY: 'Zabezpečenie',
ONOFF_CAP: 'ZAP/VYP',
ONOFF: 'zap/vyp',
TYPE: 'Typ',
DESCRIPTION: 'Popis',
ENTITIES: 'Entity',
REFRESH: 'Obnoviť',
EXPORT: 'Export',
DEVICE_DETAILS: 'Detaily zariadenia',
ID_OF: '{0} ID',
DEVICE: 'Zariadenie',
PRODUCT: 'Produkt',
VERSION: 'Verzia',
BRAND: 'Značka',
ENTITY_NAME: 'Názov entity',
VALUE: '{{Value|value}}',
DEVICE_DATA: 'Dáta zariadenia',
SENSOR_DATA: 'Dáta snímača',
DEVICES: 'Zariadenia',
SENSORS: 'Snímače',
RUN_COMMAND: 'Volať príkaz',
CHANGE_VALUE: 'Zmena hodnoty',
CANCEL: 'Zrušiť',
RESET: 'Reset',
APPLY_CHANGES: 'Aplikovať zmeny ({0})',
UPDATE: 'Aktualizovať',
EXECUTE: 'Spustiť',
REMOVE: 'Odstrániť',
PROBLEM_UPDATING: 'Problém s aktualizáciou',
PROBLEM_LOADING: 'Problém s načítaním',
ANALOG_SENSOR: 'Analógový snímač',
ANALOG_SENSORS: 'Analógové snímače',
SETTINGS: 'Nastavenia',
UPDATED_OF: '{0} aktualizovaných',
UPDATE_OF: '{0} aktualizované',
REMOVED_OF: '{0} odstránených',
DELETION_OF: '{0} zmazaných',
OFFSET: 'Ofset',
FACTOR: 'Faktor',
FREQ: 'Frekvencia',
DUTY_CYCLE: 'Duty Cycle',
UNIT: 'UoM',
STARTVALUE: 'Počiatočná hodnota',
WARN_GPIO: 'Upozornenie: Buďte opatrní pri priraďovaní GPIO!',
EDIT: 'Editovať',
SENSOR: 'Snímač',
TEMP_SENSOR: 'Snímač teploty',
TEMP_SENSORS: 'Snímače teploty',
WRITE_CMD_SENT: 'Príkaz zápisu bol odoslaný',
EMS_BUS_WARNING: 'Zbernica EMS odpojená. Ak toto upozornenie pretrváva aj po niekoľkých sekundách, skontrolujte nastavenia a profil dosky',
EMS_BUS_SCANNING: 'Zisťovanie EMS zariadení...',
CONNECTED: 'Pripojené',
TX_ISSUES: 'Problémy s Tx skontrolujte Tx režim',
DISCONNECTED: 'Odpojené',
EMS_SCAN: 'Naozaj chcete spustiť úplnú kontrolu zariadenia zbernice EMS?',
EMS_BUS_STATUS: 'Stav zbernice EMS',
ACTIVE_DEVICES: 'Aktívne zariadenia a snímače',
EMS_DEVICE: 'EMS zariadenie',
SUCCESS: 'ÚSPEŠNÉ',
FAIL: 'ZLYHANIE',
QUALITY: 'KVALITA',
SCAN_DEVICES: 'Scan pre nové zariadenia',
EMS_BUS_STATUS_TITLE: 'EMS zbernica & stav aktivity',
SCAN: 'Scan',
STATUS_NAMES: [
'EMS Telegramy prijaté (Rx)',
'EMS Čítania (Tx)',
'EMS Zápisy (Tx)',
'Čítanie snímača teploty',
'Analógové snímanie',
'MQTT Publikovanie',
'API volania',
'Syslog správy'
],
NUM_DEVICES: '{num} Zariadenia{{s}}',
NUM_TEMP_SENSORS: '{num} Teplotné snímače{{s}}',
NUM_ANALOG_SENSORS: '{num} Analógové snímače{{s}}',
NUM_DAYS: '{num} dní{{s}}',
NUM_SECONDS: '{num} sekúnd{{s}}',
NUM_HOURS: '{num} hodín{{s}}',
NUM_MINUTES: '{num} minút{{s}}',
APPLICATION_SETTINGS: 'Nastavenia aplikácie',
CUSTOMIZATIONS: 'Prispôsobenia',
APPLICATION_RESTARTING: 'EMS-ESP sa reštartuje',
INTERFACE_BOARD_PROFILE: 'Profil boardu rozhrania',
BOARD_PROFILE_TEXT: 'Vyberte vopred nakonfigurovaný profil dosky rozhrania zo zoznamu nižšie alebo vyberte možnosť Vlastné a nakonfigurujte svoje vlastné hardvérové nastavenia',
BOARD_PROFILE: 'Board profil',
CUSTOM: 'Vlastné',
GPIO_OF: '{0} GPIO',
BUTTON: 'Tlačidlo',
TEMPERATURE: 'Teplota',
PHY_TYPE: 'Eth PHY Typ',
DISABLED: 'zakázané',
TX_MODE: 'Tx režim',
HARDWARE: 'Hardware',
EMS_BUS: '{{BUS|EMS BUS}}',
GENERAL_OPTIONS: 'Všeobecné možnosti',
LANGUAGE_ENTITIES: 'Jazyk (pre entity zariadenia)',
HIDE_LED: 'Skryť LED',
ENABLE_TELNET: 'Povoliť Telnet konzolu',
ENABLE_ANALOG: 'Povoliť analógové snímače',
CONVERT_FAHRENHEIT: 'Previesť hodnoty teploty na fahrenheity',
BYPASS_TOKEN: 'Vynechajte autorizáciu prístupového tokenu pri volaniach API',
READONLY: 'Povoliť režim len na čítanie (blokuje všetky odchádzajúce príkazy EMS Tx Write)',
UNDERCLOCK_CPU: 'Podtaktovanie rýchlosti procesora',
HEATINGOFF: 'Spustite kotol s núteným vykurovaním',
ENABLE_SHOWER_TIMER: 'Povoliť časovač sprchovania',
ENABLE_SHOWER_ALERT: 'Povoliť upozornenie na sprchu',
TRIGGER_TIME: 'Čas spustenia',
COLD_SHOT_DURATION: 'Trvanie studeného záberu',
FORMATTING_OPTIONS: 'Možnosti formátovania',
BOOLEAN_FORMAT_DASHBOARD: 'Panel Boolean formát',
BOOLEAN_FORMAT_API: 'Boolean formát API/MQTT',
ENUM_FORMAT: 'Enum formát API/MQTT',
INDEX: 'Index',
ENABLE_PARASITE: 'Povolenie parazitného napájania',
LOGGING: 'Logovanie',
LOG_HEX: 'Záznam telegramov EMS v hexadecimálnej sústave',
ENABLE_SYSLOG: 'Povoliť Syslog',
LOG_LEVEL: 'Log úroveň',
MARK_INTERVAL: 'Označenie intervalu',
SECONDS: 'sekundy',
MINUTES: 'minúty',
HOURS: 'hodiny',
RESTART: 'Reštart',
RESTART_TEXT: 'EMS-ESP sa musí reštartovať, aby sa použili zmenené systémové nastavenia',
RESTART_CONFIRM: 'Ste si istí, že chcete reštartovať EMS-ESP?',
COMMAND: 'Príkaz',
CUSTOMIZATIONS_RESTART: 'Ste si istí, že chcete reštartovať EMS-ESP?',
CUSTOMIZATIONS_FULL: 'Vybrané subjekty prekročili limit. Prosím, ukladajte v dávkach',
CUSTOMIZATIONS_SAVED: 'Uložené prispôsobenia',
CUSTOMIZATIONS_HELP_1: 'Vyberte zariadenie a prispôsobte možnosti entít alebo kliknutím premenujte',
CUSTOMIZATIONS_HELP_2: 'označiť ako obľúbené',
CUSTOMIZATIONS_HELP_3: 'zakázať akciu zápisu',
CUSTOMIZATIONS_HELP_4: 'vylúčiť z MQTT a API',
CUSTOMIZATIONS_HELP_5: 'skryť z panela',
CUSTOMIZATIONS_HELP_6: 'odstrániť z pamäte',
SELECT_DEVICE: 'Zvoliť zariadenie',
SET_ALL: 'nastaviť všetko',
OPTIONS: 'Možnosti',
NAME: 'Názov',
CUSTOMIZATIONS_RESET: 'Naozaj chcete odstrániť všetky prispôsobenia vrátane vlastných nastavení snímačov teploty a analógových snímačov?',
DEVICE_ENTITIES: 'Entity zariadenia',
SUPPORT_INFORMATION: 'Informácie o podpore',
CLICK_HERE: 'Kliknite tu',
HELP_INFORMATION_1: 'Navštívte online wiki, kde nájdete pokyny na konfiguráciu EMS-ESP',
HELP_INFORMATION_2: 'Pre živý komunitný chat sa pripojte na náš Discord server',
HELP_INFORMATION_3: 'Ak chcete požiadať o funkciu alebo nahlásiť chybu',
HELP_INFORMATION_4: 'nezabudnite si stiahnuť a pripojiť informácie o vašom systéme, aby ste mohli rýchlejšie reagovať pri nahlasovaní problému',
HELP_INFORMATION_5: 'EMS-ESP je bezplatný a open source projekt. Podporte jeho budúci vývoj tým, že mu dáte hviezdičku na Github!',
UPLOAD: 'Nahrať',
DOWNLOAD: '{{S|s|s}}tiahnuť',
ABORTED: 'zrušené',
FAILED: 'chybné',
SUCCESSFUL: 'úspešné',
SYSTEM: 'Systém',
LOG_OF: '{0} Log',
STATUS_OF: '{0} Stav',
UPLOAD_DOWNLOAD: 'Nahrať/Stiahnuť',
VERSION_ON: 'Momentálne ste vo verzii',
SYSTEM_APPLY_FIRMWARE: 'na použitie nového firmvéru',
CLOSE: 'Zatvoriť',
USE: 'Použiť',
FACTORY_RESET: 'Továrenské nastavenia',
SYSTEM_FACTORY_TEXT: 'Zariadenie bolo obnovené z výroby a teraz sa reštartuje',
SYSTEM_FACTORY_TEXT_DIALOG: 'Naozaj chcete resetovať EMS-ESP na predvolené výrobné nastavenia?',
VERSION_CHECK: 'Kontrola verzie',
THE_LATEST: 'Posledná',
OFFICIAL: 'officiálna',
DEVELOPMENT: 'vývojárska',
RELEASE_IS: 'vydanie je',
RELEASE_NOTES: 'poznámky k vydaniu',
EMS_ESP_VER: 'EMS-ESP verzia',
UPTIME: 'Beh systému',
HEAP: 'Zásobník (voľné / max pridelenie)',
PSRAM: 'PSRAM (Veľkosť / Voľné)',
FLASH: 'Flash chip (Veľkosť / Rýchlosť)',
APPSIZE: 'Applikácia (Priečka: Použité / Voľné)',
FILESYSTEM: 'Súborový systém (Použité / Voľné)',
BUFFER_SIZE: 'Maximálna veľkosť vyrovnávacej pamäte',
COMPACT: 'Kompaktné',
ENABLE_OTA: 'Povoliť OTA aktualizácie',
DOWNLOAD_CUSTOMIZATION_TEXT: 'Stiahnutie prispôsobení entity',
DOWNLOAD_SCHEDULE_TEXT: 'Stiahnutie plánovača udalostí',
DOWNLOAD_SETTINGS_TEXT: 'Stiahnite si nastavenia aplikácie. Pri zdieľaní nastavení buďte opatrní, pretože tento súbor obsahuje heslá a iné citlivé systémové informácie.',
UPLOAD_TEXT: 'Najskôr nahrajte nový súbor firmvéru (.bin), nastavenia alebo prispôsobenia (.json), pre voliteľné overenie nahrajte súbor (.md5)',
UPLOADING: 'Nahrávanie',
UPLOAD_DROP_TEXT: 'Zahodiť súbor alebo kliknúť sem',
ERROR: 'Neočakávaná chyba, prosím skúste to znova',
TIME_SET: 'Nastavený čas',
MANAGE_USERS: 'Správa používateľov',
IS_ADMIN: 'je Admin',
USER_WARNING: 'Musíte mať nakonfigurovaného aspoň jedného používateľa administrátora',
ADD: 'Pridať',
ACCESS_TOKEN_FOR: 'Prístupový token pre',
ACCESS_TOKEN_TEXT: 'Nižšie uvedený token sa používa pri volaniach REST API, ktoré vyžadujú autorizáciu. Môže byť odovzdaný buď ako token Bearer v hlavičke Authorization (Autorizácia), alebo v parametri dotazu URL access_token.',
GENERATING_TOKEN: 'Generovanie tokenu',
USER: 'Užívateľ',
MODIFY: 'Upraviť',
SU_TEXT: 'Heslo su (superužívateľ) sa používa na podpisovanie autentifikačných tokenov a tiež na povolenie oprávnení správcu v rámci konzoly.',
NOT_ENABLED: 'Nie je povolené',
ERRORS_OF: '{0} errory',
DISCONNECT_REASON: 'Dôvod odpojenia',
ENABLE_MQTT: 'Povoliť MQTT',
BROKER: 'Broker',
CLIENT: 'Klient',
BASE_TOPIC: 'Base',
OPTIONAL: 'voliteľné',
FORMATTING: 'Formátovanie',
MQTT_FORMAT: 'Formát témy/záťaže',
MQTT_NEST_1: 'Vnorené do jednej témy',
MQTT_NEST_2: 'Ako jednotlivé témy',
MQTT_RESPONSE: 'Publikovanie výstupu príkazu do témy `response`',
MQTT_PUBLISH_TEXT_1: 'Zverejňovanie tém jednotlivých hodnôt pri zmene',
MQTT_PUBLISH_TEXT_2: 'Publikovanie do tém príkazov (ioBroker)',
MQTT_PUBLISH_TEXT_3: 'Povolenie zisťovania MQTT',
MQTT_PUBLISH_TEXT_4: 'Predpona tém Discovery',
MQTT_PUBLISH_TEXT_5: 'Typ zistenia',
MQTT_PUBLISH_INTERVALS: 'Intervaly zverejňovania',
MQTT_INT_BOILER: 'Kotly a tepelné čerpadlá',
MQTT_INT_THERMOSTATS: 'Termostaty',
MQTT_INT_SOLAR: 'Solárne moduly',
MQTT_INT_MIXER: 'Zmiešavacie moduley',
MQTT_QUEUE: 'Fronta MQTT',
DEFAULT: 'Predvolené',
MQTT_ENTITY_FORMAT: 'ID formát entity',
MQTT_ENTITY_FORMAT_0: 'Jedna inštancia, dlhý názov (v3.4)',
MQTT_ENTITY_FORMAT_1: 'Jedna inštancia, krátky názov',
MQTT_ENTITY_FORMAT_2: 'Viacero inštancií, krátky názov',
MQTT_CLEAN_SESSION: 'Nastavenie čistej relácie',
MQTT_RETAIN_FLAG: 'Vždy nastaviť príznak Retain',
INACTIVE: 'Neaktívne',
ACTIVE: 'Aktívne',
UNKNOWN: 'Neznáme',
SET_TIME: 'Nastavený čas',
SET_TIME_TEXT: 'Na nastavenie času zadajte miestny dátum a čas nižšie',
LOCAL_TIME: 'Lokálny čas',
UTC_TIME: 'UTC čas',
ENABLE_NTP: 'Povoliť NTP',
NTP_SERVER: 'NTP Server',
TIME_ZONE: 'Časová zóna',
ACCESS_POINT: 'Prístupový bod',
AP_PROVIDE: 'Povoliť prístupový bod',
AP_PROVIDE_TEXT_1: 'vždy',
AP_PROVIDE_TEXT_2: 'keď WiFi je odpojená',
AP_PROVIDE_TEXT_3: 'nikdy',
AP_PREFERRED_CHANNEL: 'Preferovaný kanál',
AP_HIDE_SSID: 'Skryť SSID',
AP_CLIENTS: 'AP klienti',
AP_MAX_CLIENTS: 'Max klientov',
AP_LOCAL_IP: 'Lokálna IP',
NETWORK_SCAN: 'Scan WiFi siete',
IDLE: 'Nečinné',
LOST: 'Stratené',
SCANNING: 'Scanovanie',
SCAN_AGAIN: 'Scanovať znova',
NETWORK_SCANNER: 'Sieťový scanner',
NETWORK_NO_WIFI: 'WiFi siete nenájdené',
NETWORK_BLANK_SSID: 'nechajte prázdne, ak chcete zakázať WiFi a povoliť ETH',
NETWORK_BLANK_BSSID: 'ponechajte prázdne, ak chcete používať iba SSID',
TX_POWER: 'Tx výkon',
HOSTNAME: 'Hostname',
NETWORK_DISABLE_SLEEP: 'Zakázanie režimu spánku WiFi',
NETWORK_LOW_BAND: 'Používanie menšej šírky pásma WiFi',
NETWORK_USE_DNS: 'Povoliť mDNS službu',
NETWORK_ENABLE_CORS: 'Povoliť CORS',
NETWORK_CORS_ORIGIN: 'CORS origin',
NETWORK_ENABLE_IPV6: 'Povoliť podporu IPv6',
NETWORK_FIXED_IP: 'Použiť fixnú IP adresu',
NETWORK_GATEWAY: 'Brána',
NETWORK_SUBNET: 'Maska podsiete',
NETWORK_DNS: 'DNS servery',
ADDRESS_OF: '{0} adries',
ADMIN: 'Admin',
GUEST: 'Hosť',
NEW: 'Nová',
NEW_NAME_OF: 'Nových {0} názvov',
ENTITY: 'entita',
MIN: 'min',
MAX: 'max',
BLOCK_NAVIGATE_1: 'Máte neuložené zmeny',
BLOCK_NAVIGATE_2: 'Ak prejdete na inú stránku, neuložené zmeny sa stratia. Ste si istí, že chcete opustiť túto stránku?',
STAY: 'Zostať',
LEAVE: 'Opustiť',
SCHEDULER: 'Plánovač',
SCHEDULER_HELP_1: 'Automatizujte príkazy pridaním naplánovaných udalostí nižšie. Nastavte jedinečné meno na aktiváciu/deaktiváciu cez API/MQTT.',
SCHEDULER_HELP_2: 'Použite 00:00 na jednorazové spustenie pri štarte',
SCHEDULE: 'Plánovať',
TIME: 'Čas',
TIMER: 'Časovač',
SCHEDULE_UPDATED: 'Plánovanie aktualizované',
SCHEDULE_TIMER_1: 'pri spustení',
SCHEDULE_TIMER_2: 'každú minútu',
SCHEDULE_TIMER_3: 'každú hodinu',
CUSTOM_ENTITIES: 'Vlastné entity',
ENTITIES_HELP_1: 'Získavanie vlastných entít zo zbernice EMS', // TODO translate
ENTITIES_UPDATED: 'Aktualizované entity',
WRITEABLE: 'Zapísateľný',
SHOWING: 'Zobrazenie',
SEARCH: 'Vyhľadať',
CERT: 'Koreňový certifikát TLS (ak chcete vypnúť TLS, nechajte prázdne)',
ENABLE_TLS: 'Povoliť TLS',
ON: 'Zap',
OFF: 'Vyp',
POLARITY: 'Polarita',
ACTIVEHIGH: 'Aktívny Vysoký',
ACTIVELOW: 'Aktívny Nízky',
UNCHANGED: 'Nezmenené',
ALWAYS: 'Vždy'
};
export default sk;

View File

@@ -126,6 +126,7 @@ const sv: Translation = {
BYPASS_TOKEN: 'Inaktivera Token-autensiering för API-anrop', BYPASS_TOKEN: 'Inaktivera Token-autensiering för API-anrop',
READONLY: 'Aktivera read-only (blockerar alla utgående skrivkommandon mot EMS-bussen)', READONLY: 'Aktivera read-only (blockerar alla utgående skrivkommandon mot EMS-bussen)',
UNDERCLOCK_CPU: 'Nedklocka Processorhastighet', UNDERCLOCK_CPU: 'Nedklocka Processorhastighet',
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
ENABLE_SHOWER_TIMER: 'Aktivera Dusch-timer', ENABLE_SHOWER_TIMER: 'Aktivera Dusch-timer',
ENABLE_SHOWER_ALERT: 'Aktivera Dusch-varning', ENABLE_SHOWER_ALERT: 'Aktivera Dusch-varning',
TRIGGER_TIME: 'Aktiveringstid', TRIGGER_TIME: 'Aktiveringstid',
@@ -170,7 +171,6 @@ const sv: Translation = {
HELP_INFORMATION_3: 'Önska en ny funktion eller rapportera en bugg', HELP_INFORMATION_3: 'Önska en ny funktion eller rapportera en bugg',
HELP_INFORMATION_4: 'Bifoga din systeminformation för snabbare hantering när du rapporterar ett problem', HELP_INFORMATION_4: 'Bifoga din systeminformation för snabbare hantering när du rapporterar ett problem',
HELP_INFORMATION_5: 'EMS-ESP är gratis och är öppen källkod. Bidra till utvecklingen genom att ge oss en stjärna på GitHub!', HELP_INFORMATION_5: 'EMS-ESP är gratis och är öppen källkod. Bidra till utvecklingen genom att ge oss en stjärna på GitHub!',
SUPPORT_INFO: 'Supportinfo',
UPLOAD: 'Uppladdning', UPLOAD: 'Uppladdning',
DOWNLOAD: '{{N|n|n}}edladdning', DOWNLOAD: '{{N|n|n}}edladdning',
ABORTED: 'Avbruten', ABORTED: 'Avbruten',
@@ -194,13 +194,11 @@ const sv: Translation = {
RELEASE_IS: 'release är', // TODO translate RELEASE_IS: 'release är', // TODO translate
RELEASE_NOTES: 'release-logg', RELEASE_NOTES: 'release-logg',
EMS_ESP_VER: 'EMS-ESP Version', EMS_ESP_VER: 'EMS-ESP Version',
PLATFORM: 'Enhet (Plattform / SDK)',
UPTIME: 'Systemets Upptid', UPTIME: 'Systemets Upptid',
CPU_FREQ: 'CPU-frekvens',
HEAP: 'Heap (Ledigt / Max allokerat)', HEAP: 'Heap (Ledigt / Max allokerat)',
PSRAM: 'PSRAM (Storlek / Ledigt)', PSRAM: 'PSRAM (Storlek / Ledigt)',
FLASH: 'Flashminne (Storlek / Hastighet)', FLASH: 'Flashminne (Storlek / Hastighet)',
APPSIZE: 'Applikationer (Använt / Ledigt)', APPSIZE: 'Applikationer (Partition: Använt / Ledigt)',
FILESYSTEM: 'Filsystem (Använt / Ledigt)', FILESYSTEM: 'Filsystem (Använt / Ledigt)',
BUFFER_SIZE: 'Max Bufferstorlek', BUFFER_SIZE: 'Max Bufferstorlek',
COMPACT: 'Komprimera', COMPACT: 'Komprimera',
@@ -230,7 +228,7 @@ const sv: Translation = {
BROKER: 'Broker', BROKER: 'Broker',
CLIENT: 'Client', CLIENT: 'Client',
BASE_TOPIC: 'Base', BASE_TOPIC: 'Base',
OPTIONAL: 'Valfritt', OPTIONAL: 'valfritt',
FORMATTING: 'Formatering', FORMATTING: 'Formatering',
MQTT_FORMAT: 'Topic/Payload Format', MQTT_FORMAT: 'Topic/Payload Format',
MQTT_NEST_1: 'Nestlat i en topic.', MQTT_NEST_1: 'Nestlat i en topic.',
@@ -282,6 +280,7 @@ const sv: Translation = {
NETWORK_SCANNER: 'Hittade nätverk', NETWORK_SCANNER: 'Hittade nätverk',
NETWORK_NO_WIFI: 'Inga WiFi-nätverk hittades', NETWORK_NO_WIFI: 'Inga WiFi-nätverk hittades',
NETWORK_BLANK_SSID: 'lämna blankt för att inaktivera WiFi', // and enable ETH // TODO translate NETWORK_BLANK_SSID: 'lämna blankt för att inaktivera WiFi', // and enable ETH // TODO translate
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
TX_POWER: 'Tx Effekt', TX_POWER: 'Tx Effekt',
HOSTNAME: 'Värdnamn', HOSTNAME: 'Värdnamn',
NETWORK_DISABLE_SLEEP: 'Inaktivera sömnläge', NETWORK_DISABLE_SLEEP: 'Inaktivera sömnläge',
@@ -322,7 +321,15 @@ const sv: Translation = {
WRITEABLE: 'Writeable', // TODO translate WRITEABLE: 'Writeable', // TODO translate
SHOWING: 'Showing', // TODO translate SHOWING: 'Showing', // TODO translate
SEARCH: 'Search', // TODO translate SEARCH: 'Search', // TODO translate
CERT: 'TSL root certificate (leave blank to disable TSL)' // TODO translate CERT: 'TLS root certificate (leave blank for insecure)', // TODO translate
ENABLE_TLS: 'Aktivera TLS',
ON: 'On', // TODO translate
OFF: 'Off', // TODO translate
POLARITY: 'Polarity', // TODO translate
ACTIVEHIGH: 'Active High', // TODO translate
ACTIVELOW: 'Active Low', // TODO translate
UNCHANGED: 'Unchanged', // TODO translate
ALWAYS: 'Always' // TODO translate
}; };
export default sv; export default sv;

View File

@@ -126,6 +126,7 @@ const tr: Translation = {
BYPASS_TOKEN: 'API bağlantılarında Erişim Jeton onaylamasını geç', BYPASS_TOKEN: 'API bağlantılarında Erişim Jeton onaylamasını geç',
READONLY: 'Salt okunur modu devreye al (bütün giden EMS Tx Yazma komutlarını engeller)', READONLY: 'Salt okunur modu devreye al (bütün giden EMS Tx Yazma komutlarını engeller)',
UNDERCLOCK_CPU: 'İşlemci hızını düşür', UNDERCLOCK_CPU: 'İşlemci hızını düşür',
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
ENABLE_SHOWER_TIMER: 'Duş Sayacını Devreye Al', ENABLE_SHOWER_TIMER: 'Duş Sayacını Devreye Al',
ENABLE_SHOWER_ALERT: 'Duş Alarmını Devreye Al', ENABLE_SHOWER_ALERT: 'Duş Alarmını Devreye Al',
TRIGGER_TIME: 'Tetikleme Zamanı', TRIGGER_TIME: 'Tetikleme Zamanı',
@@ -170,7 +171,6 @@ const tr: Translation = {
HELP_INFORMATION_3: 'Yeni bir özellik talep etmek yada hata bildirmek için', HELP_INFORMATION_3: 'Yeni bir özellik talep etmek yada hata bildirmek için',
HELP_INFORMATION_4: 'Bir sorun bildirirken daha hızlı bir dönüş için sistem bilginizi indirip eklemeyi unutmayın', HELP_INFORMATION_4: 'Bir sorun bildirirken daha hızlı bir dönüş için sistem bilginizi indirip eklemeyi unutmayın',
HELP_INFORMATION_5: 'EMS-ESP ücretsiz ve açık kaynaklı bir projedir. Lütfen geliştirmeyi desteklemek için Githubda projeye yıldız verin!', HELP_INFORMATION_5: 'EMS-ESP ücretsiz ve açık kaynaklı bir projedir. Lütfen geliştirmeyi desteklemek için Githubda projeye yıldız verin!',
SUPPORT_INFO: 'Destek Bilgisi',
UPLOAD: 'Yükleme', UPLOAD: 'Yükleme',
DOWNLOAD: '{{İ|i|i}}İndirme', DOWNLOAD: '{{İ|i|i}}İndirme',
ABORTED: 'iptal edildi', ABORTED: 'iptal edildi',
@@ -194,13 +194,11 @@ const tr: Translation = {
RELEASE_IS: 'release is', // TODO translate RELEASE_IS: 'release is', // TODO translate
RELEASE_NOTES: 'yayınlanma notları', RELEASE_NOTES: 'yayınlanma notları',
EMS_ESP_VER: 'EMS-ESP Sürümü', EMS_ESP_VER: 'EMS-ESP Sürümü',
PLATFORM: 'Cihaz (Platform / SDK)',
UPTIME: 'Sistem Çalışma Süresi', UPTIME: 'Sistem Çalışma Süresi',
CPU_FREQ: 'İşlemci frekansı',
HEAP: 'Yığın (Boş / Maksimum Tahsis)', HEAP: 'Yığın (Boş / Maksimum Tahsis)',
PSRAM: 'PSRAM (Boyut / Boş)', PSRAM: 'PSRAM (Boyut / Boş)',
FLASH: 'Flash Çipi (Boyut / Hız)', FLASH: 'Flash Çipi (Boyut / Hız)',
APPSIZE: 'Uygulama (Kullanılmış / Boş)', APPSIZE: 'Uygulama (Bölme: Kullanılmış / Boş)',
FILESYSTEM: 'Dosya Sistemi (Kullanılmış / Boş)', FILESYSTEM: 'Dosya Sistemi (Kullanılmış / Boş)',
BUFFER_SIZE: 'En fazla bellek boyutu', BUFFER_SIZE: 'En fazla bellek boyutu',
COMPACT: 'Sıkışık', COMPACT: 'Sıkışık',
@@ -230,7 +228,7 @@ const tr: Translation = {
BROKER: 'Aracı', BROKER: 'Aracı',
CLIENT: 'İstemci', CLIENT: 'İstemci',
BASE_TOPIC: 'Merkez', BASE_TOPIC: 'Merkez',
OPTIONAL: 'Seçenekli', OPTIONAL: 'seçenekli',
FORMATTING: 'Biçimlendiriliyor', FORMATTING: 'Biçimlendiriliyor',
MQTT_FORMAT: 'Konu/Mesaj Biçimi', MQTT_FORMAT: 'Konu/Mesaj Biçimi',
MQTT_NEST_1: 'Tek konu üzerine yerleşmiş', MQTT_NEST_1: 'Tek konu üzerine yerleşmiş',
@@ -282,6 +280,7 @@ const tr: Translation = {
NETWORK_SCANNER: 'Ağ Tarayıcısı', NETWORK_SCANNER: 'Ağ Tarayıcısı',
NETWORK_NO_WIFI: 'Hiçbir Kablosuz Ağ bulunamadı', NETWORK_NO_WIFI: 'Hiçbir Kablosuz Ağ bulunamadı',
NETWORK_BLANK_SSID: 'Kablosuz ağı devre dışı bırakmak için boş bırakın', // TODO translate NETWORK_BLANK_SSID: 'Kablosuz ağı devre dışı bırakmak için boş bırakın', // TODO translate
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
TX_POWER: 'Aktarım gücü', TX_POWER: 'Aktarım gücü',
HOSTNAME: 'Ana Makine Adı', HOSTNAME: 'Ana Makine Adı',
NETWORK_DISABLE_SLEEP: 'Kablosuz uyku modunu devre dışına al', NETWORK_DISABLE_SLEEP: 'Kablosuz uyku modunu devre dışına al',
@@ -322,7 +321,15 @@ const tr: Translation = {
WRITEABLE: 'Writeable', // TODO translate WRITEABLE: 'Writeable', // TODO translate
SHOWING: 'Showing', // TODO translate SHOWING: 'Showing', // TODO translate
SEARCH: 'Search', // TODO translate SEARCH: 'Search', // TODO translate
CERT: 'TSL root certificate (leave blank to disable TSL)' // TODO translate CERT: 'TLS root certificate (leave blank for insecure)',
ENABLE_TLS: 'TLS deveye al',
ON: 'On', // TODO translate
OFF: 'Off', // TODO translate
POLARITY: 'Polarity', // TODO translate
ACTIVEHIGH: 'Active High', // TODO translate
ACTIVELOW: 'Active Low', // TODO translate
UNCHANGED: 'Unchanged', // TODO translate
ALWAYS: 'Always' // TODO translate
}; };
export default tr; export default tr;

View File

@@ -20,15 +20,15 @@ const Dashboard: FC = () => {
return ( return (
<> <>
<RouterTabs value={routerTab}> <RouterTabs value={routerTab}>
<Tab value="devices" label={LL.DEVICES()} /> <Tab value="/dashboard/devices" label={LL.DEVICES()} />
<Tab value="sensors" label={LL.SENSORS()} /> <Tab value="/dashboard/sensors" label={LL.SENSORS()} />
<Tab value="status" label="Status" /> <Tab value="/dashboard/status" label="Status" />
</RouterTabs> </RouterTabs>
<Routes> <Routes>
<Route path="devices" element={<DashboardDevices />} /> <Route path="devices" element={<DashboardDevices />} />
<Route path="sensors" element={<DashboardSensors />} /> <Route path="sensors" element={<DashboardSensors />} />
<Route path="status" element={<DashboardStatus />} /> <Route path="status" element={<DashboardStatus />} />
<Route path="/*" element={<Navigate replace to="devices" />} /> <Route path="*" element={<Navigate replace to="/dashboard/devices" />} />
</Routes> </Routes>
</> </>
); );

View File

@@ -1,8 +1,9 @@
import CancelIcon from '@mui/icons-material/Cancel';
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined'; import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
import EditIcon from '@mui/icons-material/Edit'; import EditIcon from '@mui/icons-material/Edit';
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined'; import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
import FormatListNumberedIcon from '@mui/icons-material/FormatListNumbered';
import DownloadIcon from '@mui/icons-material/GetApp'; import DownloadIcon from '@mui/icons-material/GetApp';
import HighlightOffIcon from '@mui/icons-material/HighlightOff';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined'; import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined'; import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined';
@@ -26,6 +27,7 @@ import {
Grid, Grid,
Typography Typography
} from '@mui/material'; } from '@mui/material';
import { useRowSelect } from '@table-library/react-table-library/select'; import { useRowSelect } from '@table-library/react-table-library/select';
import { useSort, SortToggleType } from '@table-library/react-table-library/sort'; import { useSort, SortToggleType } from '@table-library/react-table-library/sort';
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table'; import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
@@ -34,6 +36,7 @@ import { useRequest } from 'alova';
import { useState, useContext, useEffect, useCallback, useLayoutEffect } from 'react'; import { useState, useContext, useEffect, useCallback, useLayoutEffect } from 'react';
import { IconContext } from 'react-icons'; import { IconContext } from 'react-icons';
import { useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import DashboardDevicesDialog from './DashboardDevicesDialog'; import DashboardDevicesDialog from './DashboardDevicesDialog';
import DeviceIcon from './DeviceIcon'; import DeviceIcon from './DeviceIcon';
@@ -52,15 +55,17 @@ import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react'; import { useI18nContext } from 'i18n/i18n-react';
const DashboardDevices: FC = () => { const DashboardDevices: FC = () => {
const [size, setSize] = useState([0, 0]);
const { me } = useContext(AuthenticatedContext); const { me } = useContext(AuthenticatedContext);
const { LL } = useI18nContext(); const { LL } = useI18nContext();
const [size, setSize] = useState([0, 0]);
const [selectedDeviceValue, setSelectedDeviceValue] = useState<DeviceValue>(); const [selectedDeviceValue, setSelectedDeviceValue] = useState<DeviceValue>();
const [onlyFav, setOnlyFav] = useState(false); const [onlyFav, setOnlyFav] = useState(false);
const [deviceValueDialogOpen, setDeviceValueDialogOpen] = useState(false); const [deviceValueDialogOpen, setDeviceValueDialogOpen] = useState(false);
const [showDeviceInfo, setShowDeviceInfo] = useState<boolean>(false); const [showDeviceInfo, setShowDeviceInfo] = useState<boolean>(false);
const [selectedDevice, setSelectedDevice] = useState<number>(); const [selectedDevice, setSelectedDevice] = useState<number>();
const navigate = useNavigate();
const { data: coreData, send: readCoreData } = useRequest(() => EMSESP.readCoreData(), { const { data: coreData, send: readCoreData } = useRequest(() => EMSESP.readCoreData(), {
initialData: { initialData: {
connected: true, connected: true,
@@ -89,8 +94,14 @@ const DashboardDevices: FC = () => {
}, []); }, []);
const leftOffset = () => { const leftOffset = () => {
const left = document.getElementById('devices-window')?.getBoundingClientRect().left; const devicesWindow = document.getElementById('devices-window');
const right = document.getElementById('devices-window')?.getBoundingClientRect().right; if (!devicesWindow) {
return 0;
}
const clientRect = devicesWindow.getBoundingClientRect();
const left = clientRect.left;
const right = clientRect.right;
if (!left || !right) { if (!left || !right) {
return 0; return 0;
@@ -263,13 +274,16 @@ const DashboardDevices: FC = () => {
}, [escFunction]); }, [escFunction]);
const refreshData = () => { const refreshData = () => {
if (deviceValueDialogOpen) { if (!deviceValueDialogOpen) {
return; selectedDevice ? void readDeviceData(selectedDevice) : void readCoreData();
} }
if (selectedDevice) { };
void readDeviceData(selectedDevice);
const customize = () => {
if (selectedDevice == 99) {
navigate('/settings/customentities');
} else { } else {
void readCoreData(); navigate('/settings/customization', { state: selectedDevice });
} }
}; };
@@ -287,48 +301,50 @@ const DashboardDevices: FC = () => {
return sc; return sc;
}; };
const makeCsvData = (columns: any, data: any) =>
data.reduce(
(csvString: any, rowItem: any) =>
csvString + columns.map(({ accessor }: any) => escapeCsvCell(accessor(rowItem))).join(';') + '\r\n',
columns.map(({ name }: any) => escapeCsvCell(name)).join(';') + '\r\n'
);
const downloadAsCsv = (columns: any, data: any, filename: string) => {
const csvData = makeCsvData(columns, data);
const csvFile = new Blob([csvData], { type: 'text/csv;charset:utf-8' });
const downloadLink = document.createElement('a');
downloadLink.download = filename;
downloadLink.href = window.URL.createObjectURL(csvFile);
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
};
const hasMask = (id: string, mask: number) => (parseInt(id.slice(0, 2), 16) & mask) === mask; const hasMask = (id: string, mask: number) => (parseInt(id.slice(0, 2), 16) & mask) === mask;
const handleDownloadCsv = () => { const handleDownloadCsv = () => {
const columns = [
{ accessor: (dv: any) => dv.id.slice(2), name: LL.ENTITY_NAME(0) },
{
accessor: (dv: any) => (typeof dv.v === 'number' ? new Intl.NumberFormat().format(dv.v) : dv.v),
name: LL.VALUE(0)
},
{ accessor: (dv: any) => DeviceValueUOM_s[dv.u], name: 'UoM' }
];
const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id); const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id);
if (deviceIndex === -1) { if (deviceIndex === -1) {
return; return;
} }
const filename = coreData.devices[deviceIndex].tn + '_' + coreData.devices[deviceIndex].n; const filename = coreData.devices[deviceIndex].tn + '_' + coreData.devices[deviceIndex].n;
downloadAsCsv( const columns = [
columns, { accessor: (dv: DeviceValue) => dv.id.slice(2), name: LL.ENTITY_NAME(0) },
onlyFav ? deviceData.data.filter((dv) => hasMask(dv.id, DeviceEntityMask.DV_FAVORITE)) : deviceData.data, {
filename accessor: (dv: DeviceValue) => (typeof dv.v === 'number' ? new Intl.NumberFormat().format(dv.v) : dv.v),
name: LL.VALUE(1)
},
{ accessor: (dv: DeviceValue) => DeviceValueUOM_s[dv.u].replace(/[^a-zA-Z0-9]/g, ''), name: 'UoM' },
{
accessor: (dv: DeviceValue) => (dv.c && !hasMask(dv.id, DeviceEntityMask.DV_READONLY) ? 'yes' : 'no'),
name: LL.WRITEABLE()
},
{
accessor: (dv: DeviceValue) =>
dv.h ? dv.h : dv.l ? dv.l.join(' | ') : dv.m !== undefined && dv.x !== undefined ? dv.m + ', ' + dv.x : '',
name: 'Range'
}
];
const data = onlyFav
? deviceData.data.filter((dv) => hasMask(dv.id, DeviceEntityMask.DV_FAVORITE))
: deviceData.data;
const csvData = data.reduce(
(csvString: any, rowItem: any) =>
csvString + columns.map(({ accessor }: any) => escapeCsvCell(accessor(rowItem))).join(';') + '\r\n',
columns.map(({ name }: any) => escapeCsvCell(name)).join(';') + '\r\n'
); );
const csvFile = new Blob([csvData], { type: 'text/csv;charset:utf-8' });
const downloadLink = document.createElement('a');
downloadLink.download = filename;
downloadLink.href = window.URL.createObjectURL(csvFile);
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}; };
useEffect(() => { useEffect(() => {
@@ -340,7 +356,7 @@ const DashboardDevices: FC = () => {
const deviceValueDialogSave = async (devicevalue: DeviceValue) => { const deviceValueDialogSave = async (devicevalue: DeviceValue) => {
const id = Number(device_select.state.id); const id = Number(device_select.state.id);
await writeDeviceValue({ id, devicevalue }) await writeDeviceValue({ id, c: devicevalue.c, v: devicevalue.v })
.then(() => { .then(() => {
toast.success(LL.WRITE_CMD_SENT()); toast.success(LL.WRITE_CMD_SENT());
}) })
@@ -406,34 +422,39 @@ const DashboardDevices: FC = () => {
const renderCoreData = () => ( const renderCoreData = () => (
<IconContext.Provider value={{ color: 'lightblue', size: '24', style: { verticalAlign: 'middle' } }}> <IconContext.Provider value={{ color: 'lightblue', size: '24', style: { verticalAlign: 'middle' } }}>
{!coreData.connected && <MessageBox my={2} level="error" message={LL.EMS_BUS_WARNING()} />} {!coreData.connected && <MessageBox my={2} level="error" message={LL.EMS_BUS_WARNING()} />}
{coreData.connected && coreData.devices.length === 0 && ( {/* {coreData.connected && coreData.devices.length === 0 && (
<MessageBox my={2} level="warning" message={LL.EMS_BUS_SCANNING()} /> <MessageBox my={2} level="warning" message={LL.EMS_BUS_SCANNING()} />
)} )} */}
<Table data={{ nodes: coreData.devices }} select={device_select} theme={device_theme} layout={{ custom: true }}> {coreData.connected && (
{(tableList: any) => ( <Table data={{ nodes: coreData.devices }} select={device_select} theme={device_theme} layout={{ custom: true }}>
<> {(tableList: any) => (
<Header> <>
<HeaderRow> <Header>
<HeaderCell stiff /> <HeaderRow>
<HeaderCell resize>{LL.DESCRIPTION()}</HeaderCell> <HeaderCell stiff />
<HeaderCell stiff>{LL.TYPE(0)}</HeaderCell> <HeaderCell resize>{LL.DESCRIPTION()}</HeaderCell>
</HeaderRow> <HeaderCell stiff>{LL.TYPE(0)}</HeaderCell>
</Header> </HeaderRow>
<Body> </Header>
{tableList.map((device: Device) => ( <Body>
<Row key={device.id} item={device}> {tableList.map((device: Device) => (
<Cell stiff> <Row key={device.id} item={device}>
<DeviceIcon type_id={device.t} /> <Cell stiff>
</Cell> <DeviceIcon type_id={device.t} />
<Cell>{device.n}</Cell> </Cell>
<Cell stiff>{device.tn}</Cell> <Cell>
</Row> {device.n}
))} <span style={{ color: 'lightblue' }}>&nbsp;&nbsp;({device.e})</span>
</Body> </Cell>
</> <Cell stiff>{device.tn}</Cell>
)} </Row>
</Table> ))}
</Body>
</>
)}
</Table>
)}
</IconContext.Provider> </IconContext.Provider>
); );
@@ -480,21 +501,31 @@ const DashboardDevices: FC = () => {
right: 16, right: 16,
bottom: 0, bottom: 0,
top: 128, top: 128,
maxHeight: () => size[1] - 210, zIndex: 'modal',
zIndex: 'modal' maxHeight: () => size[1] - 189,
border: '1px solid #177ac9'
}} }}
> >
<Box sx={{ border: '1px solid #177ac9' }}> <Box sx={{ border: '1px solid #177ac9' }}>
<Typography noWrap variant="subtitle1" color="warning.main" sx={{ mx: 1 }}> <Typography noWrap variant="subtitle1" color="warning.main" sx={{ ml: 1 }}>
{coreData.devices[deviceIndex].n} {coreData.devices[deviceIndex].tn}&nbsp;&#124;&nbsp;{coreData.devices[deviceIndex].n}
</Typography> </Typography>
<Grid container justifyContent="space-between"> <Grid container justifyContent="space-between">
<Typography sx={{ ml: 1 }} variant="subtitle2" color="primary"> <Typography sx={{ ml: 1 }} variant="subtitle2" color="primary">
{shown_data.length + ' ' + LL.ENTITIES(shown_data.length)} {LL.SHOWING() +
' ' +
shown_data.length +
'/' +
coreData.devices[deviceIndex].e +
' ' +
LL.ENTITIES(shown_data.length)}
<IconButton onClick={() => setShowDeviceInfo(true)}> <IconButton onClick={() => setShowDeviceInfo(true)}>
<InfoOutlinedIcon color="primary" sx={{ fontSize: 18, verticalAlign: 'middle' }} /> <InfoOutlinedIcon color="primary" sx={{ fontSize: 18, verticalAlign: 'middle' }} />
</IconButton> </IconButton>
<IconButton onClick={customize}>
<FormatListNumberedIcon color="primary" sx={{ fontSize: 18, verticalAlign: 'middle' }} />
</IconButton>
<IconButton onClick={handleDownloadCsv}> <IconButton onClick={handleDownloadCsv}>
<DownloadIcon color="primary" sx={{ fontSize: 18, verticalAlign: 'middle' }} /> <DownloadIcon color="primary" sx={{ fontSize: 18, verticalAlign: 'middle' }} />
</IconButton> </IconButton>
@@ -511,7 +542,7 @@ const DashboardDevices: FC = () => {
</Typography> </Typography>
<Grid item zeroMinWidth justifyContent="flex-end"> <Grid item zeroMinWidth justifyContent="flex-end">
<IconButton onClick={resetDeviceSelect}> <IconButton onClick={resetDeviceSelect}>
<CancelIcon color="info" sx={{ fontSize: 18, verticalAlign: 'middle' }} /> <HighlightOffIcon color="primary" sx={{ fontSize: 18, verticalAlign: 'middle' }} />
</IconButton> </IconButton>
</Grid> </Grid>
</Grid> </Grid>

View File

@@ -26,20 +26,10 @@ import type { ValidateFieldsError } from 'async-validator';
import { dialogStyle } from 'CustomTheme'; import { dialogStyle } from 'CustomTheme';
import { ValidatedTextField } from 'components'; import { ValidatedTextField } from 'components';
import { useI18nContext } from 'i18n/i18n-react'; import { useI18nContext } from 'i18n/i18n-react';
import { updateValue } from 'utils'; import { updateValue, numberValue } from 'utils';
import { validate } from 'validators'; import { validate } from 'validators';
// const dialogStyle = {
// '& .MuiDialog-paper': {
// borderRadius: '8px',
// borderColor: '#565656',
// borderStyle: 'solid',
// borderWidth: '1px'
// },
// backdropFilter: 'blur(1px)'
// };
type DashboardDevicesDialogProps = { type DashboardDevicesDialogProps = {
open: boolean; open: boolean;
onClose: () => void; onClose: () => void;
@@ -99,32 +89,21 @@ const DashboardDevicesDialog = ({
} }
}; };
const showHelperText = (dv: DeviceValue) => { const showHelperText = (dv: DeviceValue) =>
if (dv.h) { dv.h ? (
return dv.h; dv.h
} ) : dv.l ? (
if (dv.l) { dv.l.join(' | ')
return '[ ' + dv.l.join(' | ') + ' ]'; ) : dv.m !== undefined && dv.x !== undefined ? (
} <>
{dv.m}&nbsp;&rarr;&nbsp;{dv.x}
let helperText = '<'; </>
if (dv.s) { ) : undefined;
helperText += 'n';
if (dv.m !== undefined && dv.x !== undefined) {
helperText += ' between ' + dv.m + ' and ' + dv.x;
} else {
helperText += ' , step ' + dv.s;
}
} else {
helperText += 'text';
}
return helperText + '>';
};
return ( return (
<Dialog sx={dialogStyle} open={open} onClose={close}> <Dialog sx={dialogStyle} open={open} onClose={close}>
<DialogTitle> <DialogTitle>
{selectedItem.v === '' && selectedItem.c ? LL.RUN_COMMAND() : writeable ? LL.CHANGE_VALUE() : LL.VALUE(0)} {selectedItem.v === '' && selectedItem.c ? LL.RUN_COMMAND() : writeable ? LL.CHANGE_VALUE() : LL.VALUE(1)}
</DialogTitle> </DialogTitle>
<DialogContent dividers> <DialogContent dividers>
<Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}> <Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}>
@@ -135,7 +114,7 @@ const DashboardDevicesDialog = ({
{editItem.l ? ( {editItem.l ? (
<TextField <TextField
name="v" name="v"
label={LL.VALUE(0)} label={LL.VALUE(1)}
value={editItem.v} value={editItem.v}
disabled={!writeable} disabled={!writeable}
autoFocus autoFocus
@@ -153,8 +132,8 @@ const DashboardDevicesDialog = ({
<ValidatedTextField <ValidatedTextField
fieldErrors={fieldErrors} fieldErrors={fieldErrors}
name="v" name="v"
label={LL.VALUE(0)} label={LL.VALUE(1)}
value={Math.round(editItem.v * 10) / 10} value={numberValue(Math.round(editItem.v * 10) / 10)}
autoFocus autoFocus
disabled={!writeable} disabled={!writeable}
type="number" type="number"
@@ -169,7 +148,7 @@ const DashboardDevicesDialog = ({
<ValidatedTextField <ValidatedTextField
fieldErrors={fieldErrors} fieldErrors={fieldErrors}
name="v" name="v"
label={LL.VALUE(0)} label={LL.VALUE(1)}
value={editItem.v} value={editItem.v}
disabled={!writeable} disabled={!writeable}
autoFocus autoFocus
@@ -181,7 +160,7 @@ const DashboardDevicesDialog = ({
</Grid> </Grid>
{writeable && ( {writeable && (
<Grid item> <Grid item>
<FormHelperText>format:&nbsp;{showHelperText(editItem)}</FormHelperText> <FormHelperText>{showHelperText(editItem)}</FormHelperText>
</Grid> </Grid>
)} )}
</Grid> </Grid>

View File

@@ -16,7 +16,7 @@ import DashboardSensorsAnalogDialog from './DashboardSensorsAnalogDialog';
import DashboardSensorsTemperatureDialog from './DashboardSensorsTemperatureDialog'; import DashboardSensorsTemperatureDialog from './DashboardSensorsTemperatureDialog';
import * as EMSESP from './api'; import * as EMSESP from './api';
import { DeviceValueUOM, DeviceValueUOM_s, AnalogTypeNames } from './types'; import { DeviceValueUOM, DeviceValueUOM_s, AnalogTypeNames, AnalogType } from './types';
import { temperatureSensorItemValidation, analogSensorItemValidation } from './validators'; import { temperatureSensorItemValidation, analogSensorItemValidation } from './validators';
import type { TemperatureSensor, AnalogSensor } from './types'; import type { TemperatureSensor, AnalogSensor } from './types';
import type { FC } from 'react'; import type { FC } from 'react';
@@ -38,7 +38,8 @@ const DashboardSensors: FC = () => {
initialData: { initialData: {
ts: [], ts: [],
as: [], as: [],
analog_enabled: false analog_enabled: false,
platform: 'ESP32'
} }
}); });
@@ -261,7 +262,7 @@ const DashboardSensors: FC = () => {
setSelectedAnalogSensor({ setSelectedAnalogSensor({
id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100), id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100),
n: '', n: '',
g: 40, g: 21, // default GPIO 21 which is safe for all platforms
u: 0, u: 0,
v: 0, v: 0,
o: 0, o: 0,
@@ -391,7 +392,11 @@ const DashboardSensors: FC = () => {
<Cell stiff>{a.g}</Cell> <Cell stiff>{a.g}</Cell>
<Cell>{a.n}</Cell> <Cell>{a.n}</Cell>
<Cell stiff>{AnalogTypeNames[a.t]} </Cell> <Cell stiff>{AnalogTypeNames[a.t]} </Cell>
<Cell stiff>{a.t ? formatValue(a.v, a.u) : ''}</Cell> {a.t === AnalogType.DIGITAL_OUT || a.t === AnalogType.DIGITAL_IN ? (
<Cell stiff>{a.v ? LL.ON() : LL.OFF()}</Cell>
) : (
<Cell stiff>{a.t ? formatValue(a.v, a.u) : ''}</Cell>
)}
</Row> </Row>
))} ))}
</Body> </Body>
@@ -402,18 +407,22 @@ const DashboardSensors: FC = () => {
return ( return (
<SectionContent title={LL.SENSOR_DATA()} titleGutter> <SectionContent title={LL.SENSOR_DATA()} titleGutter>
<Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="secondary"> {sensorData.ts.length > 0 && (
{LL.TEMP_SENSORS()} <>
</Typography> <Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="secondary">
<RenderTemperatureSensors /> {LL.TEMP_SENSORS()}
{selectedTemperatureSensor && ( </Typography>
<DashboardSensorsTemperatureDialog <RenderTemperatureSensors />
open={temperatureDialogOpen} {selectedTemperatureSensor && (
onClose={onTemperatureDialogClose} <DashboardSensorsTemperatureDialog
onSave={onTemperatureDialogSave} open={temperatureDialogOpen}
selectedItem={selectedTemperatureSensor} onClose={onTemperatureDialogClose}
validator={temperatureSensorItemValidation()} onSave={onTemperatureDialogSave}
/> selectedItem={selectedTemperatureSensor}
validator={temperatureSensorItemValidation()}
/>
)}
</>
)} )}
{sensorData?.analog_enabled === true && ( {sensorData?.analog_enabled === true && (
@@ -429,7 +438,7 @@ const DashboardSensors: FC = () => {
onSave={onAnalogDialogSave} onSave={onAnalogDialogSave}
creating={creating} creating={creating}
selectedItem={selectedAnalogSensor} selectedItem={selectedAnalogSensor}
validator={analogSensorItemValidation(sensorData.as, creating)} validator={analogSensorItemValidation(sensorData.as, creating, sensorData.platform)}
/> />
)} )}
</> </>
@@ -442,14 +451,16 @@ const DashboardSensors: FC = () => {
{LL.REFRESH()} {LL.REFRESH()}
</Button> </Button>
</Box> </Box>
<Button {sensorData?.analog_enabled === true && (
variant="outlined" <Button
color="primary" variant="outlined"
startIcon={<AddCircleOutlineOutlinedIcon />} color="primary"
onClick={addAnalogSensor} startIcon={<AddCircleOutlineOutlinedIcon />}
> onClick={addAnalogSensor}
{LL.ADD(0) + ' ' + LL.ANALOG_SENSOR(1)} >
</Button> {LL.ADD(0) + ' ' + LL.ANALOG_SENSOR(1)}
</Button>
)}
</Box> </Box>
</ButtonRow> </ButtonRow>
</SectionContent> </SectionContent>

View File

@@ -89,7 +89,6 @@ const DashboardSensorsAnalogDialog = ({
fieldErrors={fieldErrors} fieldErrors={fieldErrors}
name="g" name="g"
label="GPIO" label="GPIO"
disabled={!creating}
value={numberValue(editItem.g)} value={numberValue(editItem.g)}
type="number" type="number"
variant="outlined" variant="outlined"
@@ -124,66 +123,66 @@ const DashboardSensorsAnalogDialog = ({
</TextField> </TextField>
</Grid> </Grid>
{editItem.t >= AnalogType.COUNTER && editItem.t <= AnalogType.RATE && ( {editItem.t >= AnalogType.COUNTER && editItem.t <= AnalogType.RATE && (
<> <Grid item xs={4}>
<Grid item xs={4}> <TextField name="u" label={LL.UNIT()} value={editItem.u} fullWidth select onChange={updateFormValue}>
<TextField name="u" label={LL.UNIT()} value={editItem.u} fullWidth select onChange={updateFormValue}> {DeviceValueUOM_s.map((val, i) => (
{DeviceValueUOM_s.map((val, i) => ( <MenuItem key={i} value={i}>
<MenuItem key={i} value={i}> {val}
{val} </MenuItem>
</MenuItem> ))}
))} </TextField>
</TextField> </Grid>
</Grid> )}
{editItem.t === AnalogType.ADC && ( {editItem.t === AnalogType.ADC && (
<Grid item xs={4}> <Grid item xs={4}>
<TextField <TextField
name="o" name="o"
label={LL.OFFSET()} label={LL.OFFSET()}
value={numberValue(editItem.o)} value={numberValue(editItem.o)}
fullWidth fullWidth
type="number" type="number"
variant="outlined" variant="outlined"
onChange={updateFormValue} onChange={updateFormValue}
inputProps={{ min: '0', max: '3300', step: '1' }} inputProps={{ min: '0', max: '3300', step: '1' }}
InputProps={{ InputProps={{
startAdornment: <InputAdornment position="start">mV</InputAdornment> startAdornment: <InputAdornment position="start">mV</InputAdornment>
}} }}
/> />
</Grid> </Grid>
)} )}
{editItem.t === AnalogType.COUNTER && ( {editItem.t === AnalogType.COUNTER && (
<Grid item xs={4}> <Grid item xs={4}>
<TextField <TextField
name="o" name="o"
label={LL.STARTVALUE()} label={LL.STARTVALUE()}
value={numberValue(editItem.o)} value={numberValue(editItem.o)}
fullWidth fullWidth
type="number" type="number"
variant="outlined" variant="outlined"
onChange={updateFormValue} onChange={updateFormValue}
inputProps={{ step: '0.001' }} inputProps={{ step: '0.001' }}
/> />
</Grid> </Grid>
)} )}
<Grid item xs={4}> {editItem.t >= AnalogType.COUNTER && editItem.t <= AnalogType.RATE && (
<TextField <Grid item xs={4}>
name="f" <TextField
label={LL.FACTOR()} name="f"
value={numberValue(editItem.f)} label={LL.FACTOR()}
fullWidth value={numberValue(editItem.f)}
type="number" fullWidth
variant="outlined" type="number"
onChange={updateFormValue} variant="outlined"
inputProps={{ step: '0.001' }} onChange={updateFormValue}
/> inputProps={{ step: '0.001' }}
</Grid> />
</> </Grid>
)} )}
{editItem.t === AnalogType.DIGITAL_OUT && (editItem.g === 25 || editItem.g === 26) && ( {editItem.t === AnalogType.DIGITAL_OUT && (editItem.g === 25 || editItem.g === 26) && (
<Grid item xs={4}> <Grid item xs={4}>
<TextField <TextField
name="o" name="o"
label={LL.VALUE(0)} label={LL.VALUE(1)}
value={numberValue(editItem.o)} value={numberValue(editItem.o)}
fullWidth fullWidth
type="number" type="number"
@@ -194,20 +193,55 @@ const DashboardSensorsAnalogDialog = ({
</Grid> </Grid>
)} )}
{editItem.t === AnalogType.DIGITAL_OUT && editItem.g !== 25 && editItem.g !== 26 && ( {editItem.t === AnalogType.DIGITAL_OUT && editItem.g !== 25 && editItem.g !== 26 && (
<Grid item xs={4}> <>
<TextField <Grid item xs={4}>
name="o" <TextField
label={LL.VALUE(0)} name="o"
value={numberValue(editItem.o)} label={LL.VALUE(1)}
fullWidth value={numberValue(editItem.o)}
type="number" fullWidth
variant="outlined" select
onChange={updateFormValue} variant="outlined"
inputProps={{ min: '0', max: '1', step: '1' }} onChange={updateFormValue}
/> >
</Grid> <MenuItem value={0}>{LL.OFF()}</MenuItem>
<MenuItem value={1}>{LL.ON()}</MenuItem>
</TextField>
</Grid>
<Grid item xs={4}>
<TextField
name="f"
label={LL.POLARITY()}
value={editItem.f}
fullWidth
select
onChange={updateFormValue}
>
<MenuItem value={1}>{LL.ACTIVEHIGH()}</MenuItem>
<MenuItem value={-1}>{LL.ACTIVELOW()}</MenuItem>
</TextField>
</Grid>
<Grid item xs={4}>
<TextField
name="u"
label={LL.STARTVALUE()}
value={editItem.u}
fullWidth
select
onChange={updateFormValue}
>
<MenuItem value={0}>{LL.UNCHANGED()}</MenuItem>
<MenuItem value={1}>
{LL.ALWAYS()}&nbsp;{LL.OFF()}
</MenuItem>
<MenuItem value={2}>
{LL.ALWAYS()}&nbsp;{LL.ON()}
</MenuItem>
</TextField>
</Grid>
</>
)} )}
{editItem.t >= AnalogType.PWM_0 && ( {(editItem.t === AnalogType.PWM_0 || editItem.t === AnalogType.PWM_1 || editItem.t === AnalogType.PWM_2) && (
<> <>
<Grid item xs={4}> <Grid item xs={4}>
<TextField <TextField

View File

@@ -1,9 +1,9 @@
import { AiOutlineControl, AiOutlineGateway, AiOutlineAlert, AiOutlineChrome } from 'react-icons/ai'; import { AiOutlineControl, AiOutlineGateway, AiOutlineAlert } from 'react-icons/ai';
import { CgSmartHomeBoiler } from 'react-icons/cg'; import { CgSmartHomeBoiler } from 'react-icons/cg';
import { FaSolarPanel } from 'react-icons/fa'; import { FaSolarPanel } from 'react-icons/fa';
import { GiHeatHaze } from 'react-icons/gi'; import { GiHeatHaze } from 'react-icons/gi';
import { MdThermostatAuto, MdOutlineSensors, MdOutlineExtension } from 'react-icons/md'; import { MdThermostatAuto, MdOutlineSensors, MdOutlineExtension, MdOutlineDevices } from 'react-icons/md';
import { TiFlowSwitch } from 'react-icons/ti'; import { TiFlowSwitch } from 'react-icons/ti';
import { VscVmConnect } from 'react-icons/vsc'; import { VscVmConnect } from 'react-icons/vsc';
import { DeviceType } from './types'; import { DeviceType } from './types';
@@ -38,8 +38,8 @@ const DeviceIcon: FC<DeviceIconProps> = ({ type_id }) => {
return <VscVmConnect />; return <VscVmConnect />;
case DeviceType.ALERT: case DeviceType.ALERT:
return <AiOutlineAlert />; return <AiOutlineAlert />;
case DeviceType.PUMP: case DeviceType.EXTENSION:
return <AiOutlineChrome />; return <MdOutlineDevices />;
case DeviceType.CUSTOM: case DeviceType.CUSTOM:
return <MdOutlineExtension />; return <MdOutlineExtension />;
default: default:

View File

@@ -1,28 +1,121 @@
import { Tab } from '@mui/material'; import CommentIcon from '@mui/icons-material/CommentTwoTone';
import { Navigate, Route, Routes } from 'react-router-dom'; import EastIcon from '@mui/icons-material/East';
import HelpInformation from './HelpInformation'; import DownloadIcon from '@mui/icons-material/GetApp';
import GitHubIcon from '@mui/icons-material/GitHub';
import MenuBookIcon from '@mui/icons-material/MenuBookTwoTone';
import { Box, List, ListItem, ListItemAvatar, ListItemText, Link, Typography, Button } from '@mui/material';
import { useRequest } from 'alova';
import { toast } from 'react-toastify';
import type { FC } from 'react'; import type { FC } from 'react';
import { SectionContent, useLayoutTitle } from 'components';
import { RouterTabs, useRouterTab, useLayoutTitle } from 'components';
import { useI18nContext } from 'i18n/i18n-react'; import { useI18nContext } from 'i18n/i18n-react';
import * as EMSESP from 'project/api';
const Help: FC = () => { const Help: FC = () => {
const { LL } = useI18nContext(); const { LL } = useI18nContext();
const { routerTab } = useRouterTab();
useLayoutTitle(LL.HELP_OF('')); useLayoutTitle(LL.HELP_OF(''));
const { send: getAPI, onSuccess: onGetAPI } = useRequest((data) => EMSESP.API(data), {
immediate: false
});
onGetAPI((event) => {
const anchor = document.createElement('a');
anchor.href = URL.createObjectURL(
new Blob([JSON.stringify(event.data, null, 2)], {
type: 'text/plain'
})
);
anchor.download = 'emsesp_' + event.sendArgs[0].device + '_' + event.sendArgs[0].entity + '.txt';
anchor.click();
URL.revokeObjectURL(anchor.href);
toast.info(LL.DOWNLOAD_SUCCESSFUL());
});
const callAPI = async (device: string, entity: string) => {
await getAPI({ device, entity, id: 0 }).catch((error) => {
toast.error(error.message);
});
};
return ( return (
<> <SectionContent title={LL.SUPPORT_INFORMATION(0)} titleGutter>
<RouterTabs value={routerTab}> <List>
<Tab value="information" label={LL.HELP_OF('EMS-ESP')} /> <ListItem>
</RouterTabs> <ListItemAvatar>
<Routes> <MenuBookIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
<Route path="information" element={<HelpInformation />} /> </ListItemAvatar>
<Route path="/*" element={<Navigate replace to="information" />} /> <ListItemText>
</Routes> {LL.HELP_INFORMATION_1()}&nbsp;
</> <EastIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
&nbsp;
<Link target="_blank" href="https://emsesp.github.io/docs" color="primary">
{LL.CLICK_HERE()}
</Link>
</ListItemText>
</ListItem>
<ListItem>
<ListItemAvatar>
<CommentIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
</ListItemAvatar>
<ListItemText>
{LL.HELP_INFORMATION_2()}&nbsp;
<EastIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
&nbsp;
<Link target="_blank" href="https://discord.gg/3J3GgnzpyT" color="primary">
{LL.CLICK_HERE()}
</Link>
</ListItemText>
</ListItem>
<ListItem>
<ListItemAvatar>
<GitHubIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
</ListItemAvatar>
<ListItemText>
{LL.HELP_INFORMATION_3()}&nbsp;
<EastIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
<Link target="_blank" href="https://github.com/emsesp/EMS-ESP32/issues/new/choose" color="primary">
{LL.CLICK_HERE()}
</Link>
<br />
</ListItemText>
</ListItem>
</List>
<Box color="warning.main">
<Typography mb={1} variant="body2">
{LL.HELP_INFORMATION_4()}
</Typography>
</Box>
<Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={() => callAPI('system', 'info')}>
{LL.SUPPORT_INFORMATION(0)}
</Button>
<Button
sx={{ ml: 2 }}
startIcon={<DownloadIcon />}
variant="outlined"
color="primary"
onClick={() => callAPI('system', 'allvalues')}
>
All Values
</Button>
<Box border={1} p={1} mt={4} color="orange">
<Typography align="center" variant="subtitle1" color="orange">
<b>{LL.HELP_INFORMATION_5()}</b>
</Typography>
<Typography align="center">
<Link target="_blank" href="https://github.com/emsesp/EMS-ESP32" color="primary">
{'github.com/emsesp/EMS-ESP32'}
</Link>
</Typography>
<Typography color="white" variant="subtitle2" align="center">
@proddy @MichaelDvP
</Typography>
</Box>
</SectionContent>
); );
}; };

View File

@@ -1,118 +0,0 @@
import CommentIcon from '@mui/icons-material/CommentTwoTone';
import EastIcon from '@mui/icons-material/East';
import DownloadIcon from '@mui/icons-material/GetApp';
import GitHubIcon from '@mui/icons-material/GitHub';
import MenuBookIcon from '@mui/icons-material/MenuBookTwoTone';
import { Typography, Button, Box, List, ListItem, ListItemText, Link, ListItemAvatar } from '@mui/material';
import { useRequest } from 'alova';
import { toast } from 'react-toastify';
import * as EMSESP from './api';
import type { FC } from 'react';
import { SectionContent } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
const HelpInformation: FC = () => {
const { LL } = useI18nContext();
const { send: API, onSuccess: onSuccessAPI } = useRequest((data) => EMSESP.API(data), {
immediate: false
});
onSuccessAPI((event) => {
const a = document.createElement('a');
const filename = 'emsesp_info.txt';
a.href = URL.createObjectURL(
new Blob([JSON.stringify(event.data, null, 2)], {
type: 'text/plain'
})
);
a.setAttribute('download', filename);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
toast.info(LL.DOWNLOAD_SUCCESSFUL());
});
const callAPI = async () => {
await API({ device: 'system', entity: 'info', id: 0 }).catch((error) => {
toast.error(error.message);
});
};
return (
<SectionContent title={LL.SUPPORT_INFORMATION()} titleGutter>
<List>
<ListItem>
<ListItemAvatar>
<MenuBookIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
</ListItemAvatar>
<ListItemText>
{LL.HELP_INFORMATION_1()}&nbsp;
<EastIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
&nbsp;
<Link target="_blank" href="https://emsesp.github.io/docs" color="primary">
{LL.CLICK_HERE()}
</Link>
</ListItemText>
</ListItem>
<ListItem>
<ListItemAvatar>
<CommentIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
</ListItemAvatar>
<ListItemText>
{LL.HELP_INFORMATION_2()}&nbsp;
<EastIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
&nbsp;
<Link target="_blank" href="https://discord.gg/3J3GgnzpyT" color="primary">
{LL.CLICK_HERE()}
</Link>
</ListItemText>
</ListItem>
<ListItem>
<ListItemAvatar>
<GitHubIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
</ListItemAvatar>
<ListItemText>
{LL.HELP_INFORMATION_3()}&nbsp;
<EastIcon style={{ fontSize: 24, color: 'lightblue', verticalAlign: 'middle' }} />
<Link target="_blank" href="https://github.com/emsesp/EMS-ESP32/issues/new/choose" color="primary">
{LL.CLICK_HERE()}
</Link>
<br />
<i>({LL.HELP_INFORMATION_4()}</i>&nbsp;&nbsp;
<Button
startIcon={<DownloadIcon />}
size="small"
variant="outlined"
color="primary"
onClick={() => callAPI()}
>
{LL.SUPPORT_INFO()}
</Button>
&nbsp;)
</ListItemText>
</ListItem>
</List>
<Box border={1} p={1} mt={4} color="orange">
<Typography align="center" variant="subtitle1" color="orange">
<b>{LL.HELP_INFORMATION_5()}</b>
</Typography>
<Typography align="center">
<Link target="_blank" href="https://github.com/emsesp/EMS-ESP32" color="primary">
{'github.com/emsesp/EMS-ESP32'}
</Link>
</Typography>
<Typography color="white" align="center">
@proddy @MichaelDvP
</Typography>
</Box>
</SectionContent>
);
};
export default HelpInformation;

View File

@@ -2,8 +2,8 @@ import { Tab } from '@mui/material';
import { Navigate, Route, Routes } from 'react-router-dom'; import { Navigate, Route, Routes } from 'react-router-dom';
import SettingsApplication from './SettingsApplication'; import SettingsApplication from './SettingsApplication';
import SettingsCustomEntities from './SettingsCustomEntities';
import SettingsCustomization from './SettingsCustomization'; import SettingsCustomization from './SettingsCustomization';
import SettingsEntities from './SettingsEntities';
import SettingsScheduler from './SettingsScheduler'; import SettingsScheduler from './SettingsScheduler';
import type { FC } from 'react'; import type { FC } from 'react';
import { RouterTabs, useRouterTab, useLayoutTitle } from 'components'; import { RouterTabs, useRouterTab, useLayoutTitle } from 'components';
@@ -18,17 +18,17 @@ const Settings: FC = () => {
return ( return (
<> <>
<RouterTabs value={routerTab}> <RouterTabs value={routerTab}>
<Tab value="application" label={LL.APPLICATION_SETTINGS()} /> <Tab value="/settings/application" label={LL.APPLICATION_SETTINGS()} />
<Tab value="customization" label={LL.CUSTOMIZATIONS()} /> <Tab value="/settings/customization" label={LL.CUSTOMIZATIONS()} />
<Tab value="scheduler" label={LL.SCHEDULER()} /> <Tab value="/settings/scheduler" label={LL.SCHEDULER()} />
<Tab value="customentities" label={LL.CUSTOM_ENTITIES(0)} /> <Tab value="/settings/customentities" label={LL.CUSTOM_ENTITIES(0)} />
</RouterTabs> </RouterTabs>
<Routes> <Routes>
<Route path="application" element={<SettingsApplication />} /> <Route path="application" element={<SettingsApplication />} />
<Route path="customization" element={<SettingsCustomization />} /> <Route path="customization" element={<SettingsCustomization />} />
<Route path="scheduler" element={<SettingsScheduler />} /> <Route path="scheduler" element={<SettingsScheduler />} />
<Route path="customentities" element={<SettingsEntities />} /> <Route path="customentities" element={<SettingsCustomEntities />} />
<Route path="/*" element={<Navigate replace to="application" />} /> <Route path="*" element={<Navigate replace to="/settings/application" />} />
</Routes> </Routes>
</> </>
); );

View File

@@ -384,6 +384,7 @@ const SettingsApplication: FC = () => {
<MenuItem value="nl">Nederlands (NL)</MenuItem> <MenuItem value="nl">Nederlands (NL)</MenuItem>
<MenuItem value="no">Norsk (NO)</MenuItem> <MenuItem value="no">Norsk (NO)</MenuItem>
<MenuItem value="pl">Polski (PL)</MenuItem> <MenuItem value="pl">Polski (PL)</MenuItem>
<MenuItem value="sk">Slovenčina (SK)</MenuItem>
<MenuItem value="sv">Svenska (SV)</MenuItem> <MenuItem value="sv">Svenska (SV)</MenuItem>
<MenuItem value="tr">Türk (TR)</MenuItem> <MenuItem value="tr">Türk (TR)</MenuItem>
</TextField> </TextField>
@@ -425,6 +426,11 @@ const SettingsApplication: FC = () => {
label={LL.UNDERCLOCK_CPU()} label={LL.UNDERCLOCK_CPU()}
disabled={saving} disabled={saving}
/> />
<BlockFormControlLabel
control={<Checkbox checked={data.boiler_heatingoff} onChange={updateFormValue} name="boiler_heatingoff" />}
label={LL.HEATINGOFF()}
disabled={saving}
/>
<Grid container spacing={0} direction="row" justifyContent="flex-start" alignItems="flex-start"> <Grid container spacing={0} direction="row" justifyContent="flex-start" alignItems="flex-start">
<BlockFormControlLabel <BlockFormControlLabel
control={<Checkbox checked={data.shower_timer} onChange={updateFormValue} name="shower_timer" />} control={<Checkbox checked={data.shower_timer} onChange={updateFormValue} name="shower_timer" />}
@@ -639,7 +645,7 @@ const SettingsApplication: FC = () => {
</Grid> </Grid>
)} )}
{restartNeeded && ( {restartNeeded && (
<MessageBox my={2} level="warning" message={LL.RESTART_TEXT()}> <MessageBox my={2} level="warning" message={LL.RESTART_TEXT(0)}>
<Button startIcon={<PowerSettingsNewIcon />} variant="contained" color="error" onClick={restart}> <Button startIcon={<PowerSettingsNewIcon />} variant="contained" color="error" onClick={restart}>
{LL.RESTART()} {LL.RESTART()}
</Button> </Button>

View File

@@ -1,5 +1,7 @@
import AddIcon from '@mui/icons-material/Add'; import AddIcon from '@mui/icons-material/Add';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import RefreshIcon from '@mui/icons-material/Refresh';
import WarningIcon from '@mui/icons-material/Warning'; import WarningIcon from '@mui/icons-material/Warning';
import { Button, Typography, Box } from '@mui/material'; import { Button, Typography, Box } from '@mui/material';
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table'; import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
@@ -7,11 +9,11 @@ import { useTheme } from '@table-library/react-table-library/theme';
// eslint-disable-next-line import/named // eslint-disable-next-line import/named
import { updateState, useRequest } from 'alova'; import { updateState, useRequest } from 'alova';
import { useState, useCallback } from 'react'; import { useState, useCallback } from 'react';
import { unstable_useBlocker as useBlocker } from 'react-router-dom'; import { useBlocker } from 'react-router-dom';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import SettingsEntitiesDialog from './SettingsEntitiesDialog'; import SettingsCustomEntitiesDialog from './SettingsCustomEntitiesDialog';
import * as EMSESP from './api'; import * as EMSESP from './api';
import { DeviceValueTypeNames, DeviceValueUOM_s } from './types'; import { DeviceValueTypeNames, DeviceValueUOM_s } from './types';
import { entityItemValidation } from './validators'; import { entityItemValidation } from './validators';
@@ -21,7 +23,7 @@ import { ButtonRow, FormLoader, SectionContent, BlockNavigation } from 'componen
import { useI18nContext } from 'i18n/i18n-react'; import { useI18nContext } from 'i18n/i18n-react';
const SettingsEntities: FC = () => { const SettingsCustomEntities: FC = () => {
const { LL } = useI18nContext(); const { LL } = useI18nContext();
const [numChanges, setNumChanges] = useState<number>(0); const [numChanges, setNumChanges] = useState<number>(0);
const blocker = useBlocker(numChanges !== 0); const blocker = useBlocker(numChanges !== 0);
@@ -33,16 +35,17 @@ const SettingsEntities: FC = () => {
data: entities, data: entities,
send: fetchEntities, send: fetchEntities,
error error
} = useRequest(EMSESP.readEntities, { } = useRequest(EMSESP.readCustomEntities, {
initialData: [], initialData: [],
force: true force: true
}); });
const { send: writeEntities } = useRequest((data) => EMSESP.writeEntities(data), { immediate: false }); const { send: writeEntities } = useRequest((data) => EMSESP.writeCustomEntities(data), { immediate: false });
function hasEntityChanged(ei: EntityItem) { function hasEntityChanged(ei: EntityItem) {
return ( return (
ei.id !== ei.o_id || ei.id !== ei.o_id ||
ei.ram !== ei.o_ram ||
(ei?.name || '') !== (ei?.o_name || '') || (ei?.name || '') !== (ei?.o_name || '') ||
ei.device_id !== ei.o_device_id || ei.device_id !== ei.o_device_id ||
ei.type_id !== ei.o_type_id || ei.type_id !== ei.o_type_id ||
@@ -51,7 +54,8 @@ const SettingsEntities: FC = () => {
ei.factor !== ei.o_factor || ei.factor !== ei.o_factor ||
ei.value_type !== ei.o_value_type || ei.value_type !== ei.o_value_type ||
ei.writeable !== ei.o_writeable || ei.writeable !== ei.o_writeable ||
ei.deleted !== ei.o_deleted ei.deleted !== ei.o_deleted ||
(ei.value || '') !== (ei.o_value || '')
); );
} }
@@ -118,6 +122,7 @@ const SettingsEntities: FC = () => {
.filter((ei) => !ei.deleted) .filter((ei) => !ei.deleted)
.map((condensed_ei) => ({ .map((condensed_ei) => ({
id: condensed_ei.id, id: condensed_ei.id,
ram: condensed_ei.ram,
name: condensed_ei.name, name: condensed_ei.name,
device_id: condensed_ei.device_id, device_id: condensed_ei.device_id,
type_id: condensed_ei.type_id, type_id: condensed_ei.type_id,
@@ -125,7 +130,8 @@ const SettingsEntities: FC = () => {
factor: condensed_ei.factor, factor: condensed_ei.factor,
uom: condensed_ei.uom, uom: condensed_ei.uom,
writeable: condensed_ei.writeable, writeable: condensed_ei.writeable,
value_type: condensed_ei.value_type value_type: condensed_ei.value_type,
value: condensed_ei.value
})) }))
}) })
.then(() => { .then(() => {
@@ -173,14 +179,16 @@ const SettingsEntities: FC = () => {
setSelectedEntityItem({ setSelectedEntityItem({
id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100), id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100),
name: '', name: '',
device_id: '', ram: 0,
type_id: '', device_id: '0',
type_id: '0',
offset: 0, offset: 0,
factor: 1, factor: 1,
uom: 0, uom: 0,
value_type: 0, value_type: 0,
writeable: false, writeable: false,
deleted: false deleted: false,
value: ''
}); });
setDialogOpen(true); setDialogOpen(true);
}; };
@@ -189,8 +197,8 @@ const SettingsEntities: FC = () => {
return value === undefined || uom === undefined return value === undefined || uom === undefined
? '' ? ''
: typeof value === 'number' : typeof value === 'number'
? new Intl.NumberFormat().format(value) + (uom === 0 ? '' : ' ' + DeviceValueUOM_s[uom]) ? new Intl.NumberFormat().format(value) + (uom === 0 ? '' : ' ' + DeviceValueUOM_s[uom])
: value; : value;
} }
function showHex(value: number, digit: number) { function showHex(value: number, digit: number) {
@@ -212,18 +220,21 @@ const SettingsEntities: FC = () => {
<HeaderCell stiff>{LL.ID_OF(LL.DEVICE())}</HeaderCell> <HeaderCell stiff>{LL.ID_OF(LL.DEVICE())}</HeaderCell>
<HeaderCell stiff>{LL.ID_OF(LL.TYPE(1))}</HeaderCell> <HeaderCell stiff>{LL.ID_OF(LL.TYPE(1))}</HeaderCell>
<HeaderCell stiff>{LL.OFFSET()}</HeaderCell> <HeaderCell stiff>{LL.OFFSET()}</HeaderCell>
<HeaderCell stiff>{LL.VALUE(1) + ' ' + LL.TYPE(1)}</HeaderCell> <HeaderCell stiff>{LL.TYPE(1)}</HeaderCell>
<HeaderCell stiff>{LL.VALUE(1)}</HeaderCell> <HeaderCell stiff>{LL.VALUE(1)}</HeaderCell>
</HeaderRow> </HeaderRow>
</Header> </Header>
<Body> <Body>
{tableList.map((ei: EntityItem) => ( {tableList.map((ei: EntityItem) => (
<Row key={ei.name} item={ei} onClick={() => editEntityItem(ei)}> <Row key={ei.name} item={ei} onClick={() => editEntityItem(ei)}>
<Cell>{ei.name}</Cell> <Cell>
<Cell>{showHex(ei.device_id as number, 2)}</Cell> {ei.name}&nbsp;
<Cell>{showHex(ei.type_id as number, 3)}</Cell> {ei.writeable && <EditOutlinedIcon color="primary" sx={{ fontSize: 12 }} />}
<Cell>{ei.offset}</Cell> </Cell>
<Cell>{DeviceValueTypeNames[ei.value_type]}</Cell> <Cell>{ei.ram === 1 ? '' : showHex(ei.device_id as number, 2)}</Cell>
<Cell>{ei.ram === 1 ? '' : showHex(ei.type_id as number, 3)}</Cell>
<Cell>{ei.ram === 1 ? '' : ei.offset}</Cell>
<Cell>{ei.ram === 1 ? 'RAM' : DeviceValueTypeNames[ei.value_type]}</Cell>
<Cell>{formatValue(ei.value, ei.uom)}</Cell> <Cell>{formatValue(ei.value, ei.uom)}</Cell>
</Row> </Row>
))} ))}
@@ -244,7 +255,7 @@ const SettingsEntities: FC = () => {
{renderEntity()} {renderEntity()}
{selectedEntityItem && ( {selectedEntityItem && (
<SettingsEntitiesDialog <SettingsCustomEntitiesDialog
open={dialogOpen} open={dialogOpen}
creating={creating} creating={creating}
onClose={onDialogClose} onClose={onDialogClose}
@@ -274,7 +285,10 @@ const SettingsEntities: FC = () => {
</Box> </Box>
<Box flexWrap="nowrap" whiteSpace="nowrap"> <Box flexWrap="nowrap" whiteSpace="nowrap">
<ButtonRow> <ButtonRow>
<Button startIcon={<AddIcon />} variant="outlined" color="secondary" onClick={addEntityItem}> <Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={fetchEntities}>
{LL.REFRESH()}
</Button>
<Button startIcon={<AddIcon />} variant="outlined" color="primary" onClick={addEntityItem}>
{LL.ADD(0)} {LL.ADD(0)}
</Button> </Button>
</ButtonRow> </ButtonRow>
@@ -284,4 +298,4 @@ const SettingsEntities: FC = () => {
); );
}; };
export default SettingsEntities; export default SettingsCustomEntities;

View File

@@ -0,0 +1,284 @@
import AddIcon from '@mui/icons-material/Add';
import CancelIcon from '@mui/icons-material/Cancel';
import DoneIcon from '@mui/icons-material/Done';
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
import {
Box,
Button,
Checkbox,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Grid,
InputAdornment,
MenuItem,
TextField
} from '@mui/material';
import { useEffect, useState } from 'react';
import { DeviceValueUOM_s, DeviceValueType } from './types';
import type { EntityItem } from './types';
import type Schema from 'async-validator';
import type { ValidateFieldsError } from 'async-validator';
import { dialogStyle } from 'CustomTheme';
import { BlockFormControlLabel, ValidatedTextField } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
import { numberValue, updateValue } from 'utils';
import { validate } from 'validators';
type SettingsCustomEntitiesDialogProps = {
open: boolean;
creating: boolean;
onClose: () => void;
onSave: (ei: EntityItem) => void;
selectedItem: EntityItem;
validator: Schema;
};
const SettingsCustomEntitiesDialog = ({
open,
creating,
onClose,
onSave,
selectedItem,
validator
}: SettingsCustomEntitiesDialogProps) => {
const { LL } = useI18nContext();
const [editItem, setEditItem] = useState<EntityItem>(selectedItem);
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
const updateFormValue = updateValue(setEditItem);
useEffect(() => {
if (open) {
setFieldErrors(undefined);
setEditItem(selectedItem);
// convert to hex strings straight away
setEditItem({
...selectedItem,
device_id: selectedItem.device_id.toString(16).toUpperCase(),
type_id: selectedItem.type_id.toString(16).toUpperCase()
});
}
}, [open, selectedItem]);
const close = () => {
onClose();
};
const save = async () => {
try {
setFieldErrors(undefined);
await validate(validator, editItem);
if (typeof editItem.device_id === 'string') {
editItem.device_id = parseInt(editItem.device_id, 16);
}
if (typeof editItem.type_id === 'string') {
editItem.type_id = parseInt(editItem.type_id, 16);
}
onSave(editItem);
} catch (errors: any) {
setFieldErrors(errors);
}
};
const remove = () => {
editItem.deleted = true;
onSave(editItem);
};
return (
<Dialog sx={dialogStyle} open={open} onClose={close}>
<DialogTitle>
{creating ? LL.ADD(1) + ' ' + LL.NEW(1) : LL.EDIT()}&nbsp;{LL.ENTITY()}
</DialogTitle>
<DialogContent dividers>
<Box display="flex" flexWrap="wrap" mb={1}>
<Box flexWrap="nowrap" whiteSpace="nowrap" />
</Box>
<Grid container spacing={2}>
<Grid item xs={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="name"
label={LL.NAME(0)}
value={editItem.name}
margin="normal"
fullWidth
onChange={updateFormValue}
/>
</Grid>
<Grid item xs={4}>
<TextField
name="ram"
label={LL.VALUE(1) + ' ' + LL.TYPE(1)}
value={editItem.ram}
variant="outlined"
onChange={updateFormValue}
margin="normal"
fullWidth
select
>
<MenuItem value={0}>EMS-{LL.VALUE(1)}</MenuItem>
<MenuItem value={1}>RAM-{LL.VALUE(1)}</MenuItem>
</TextField>
</Grid>
{editItem.ram === 1 && (
<Grid item xs={4}>
<TextField
name="value"
label={LL.DEFAULT(0) + ' ' + LL.VALUE(1)}
value={editItem.value}
variant="outlined"
onChange={updateFormValue}
fullWidth
margin="normal"
/>
</Grid>
)}
{editItem.ram === 0 && (
<>
<Grid item xs={4} mt={3}>
<BlockFormControlLabel
control={<Checkbox checked={editItem.writeable} onChange={updateFormValue} name="writeable" />}
label={LL.WRITEABLE()}
/>
</Grid>
<Grid item xs={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="device_id"
label={LL.ID_OF(LL.DEVICE())}
margin="normal"
type="string"
fullWidth
value={editItem.device_id as string}
onChange={updateFormValue}
inputProps={{ style: { textTransform: 'uppercase' } }}
InputProps={{ startAdornment: <InputAdornment position="start">0x</InputAdornment> }}
/>
</Grid>
<Grid item xs={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="type_id"
label={LL.ID_OF(LL.TYPE(1))}
margin="normal"
fullWidth
value={editItem.type_id}
onChange={updateFormValue}
inputProps={{ style: { textTransform: 'uppercase' } }}
InputProps={{ startAdornment: <InputAdornment position="start">0x</InputAdornment> }}
/>
</Grid>
<Grid item xs={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="offset"
label={LL.OFFSET()}
margin="normal"
fullWidth
type="number"
value={editItem.offset}
onChange={updateFormValue}
/>
</Grid>
<Grid item xs={4}>
<TextField
name="value_type"
label={LL.VALUE(1) + ' ' + LL.TYPE(1)}
value={editItem.value_type}
variant="outlined"
onChange={updateFormValue}
margin="normal"
fullWidth
select
>
<MenuItem value={DeviceValueType.BOOL}>BOOL</MenuItem>
<MenuItem value={DeviceValueType.INT}>INT</MenuItem>
<MenuItem value={DeviceValueType.UINT}>UINT</MenuItem>
<MenuItem value={DeviceValueType.SHORT}>SHORT</MenuItem>
<MenuItem value={DeviceValueType.USHORT}>USHORT</MenuItem>
<MenuItem value={DeviceValueType.ULONG}>ULONG</MenuItem>
<MenuItem value={DeviceValueType.TIME}>TIME</MenuItem>
<MenuItem value={DeviceValueType.STRING}>RAW</MenuItem>
</TextField>
</Grid>
{editItem.value_type !== DeviceValueType.BOOL && editItem.value_type !== DeviceValueType.STRING && (
<>
<Grid item xs={4}>
<TextField
name="factor"
label={LL.FACTOR()}
value={numberValue(editItem.factor)}
variant="outlined"
onChange={updateFormValue}
fullWidth
margin="normal"
type="number"
inputProps={{ step: '0.001' }}
/>
</Grid>
<Grid item xs={4}>
<TextField
name="uom"
label={LL.UNIT()}
value={editItem.uom}
margin="normal"
fullWidth
onChange={updateFormValue}
select
>
{DeviceValueUOM_s.map((val, i) => (
<MenuItem key={i} value={i}>
{val}
</MenuItem>
))}
</TextField>
</Grid>
</>
)}
{editItem.value_type === DeviceValueType.STRING && editItem.device_id !== '0' && (
<Grid item xs={4}>
<TextField
name="factor"
label="Bytes"
value={editItem.factor}
variant="outlined"
onChange={updateFormValue}
fullWidth
margin="normal"
type="number"
inputProps={{ min: '1', max: '27', step: '1' }}
/>
</Grid>
)}
</>
)}
</Grid>
</DialogContent>
<DialogActions>
{!creating && (
<Box flexGrow={1}>
<Button startIcon={<RemoveIcon />} variant="outlined" color="warning" onClick={remove}>
{LL.REMOVE()}
</Button>
</Box>
)}
<Button startIcon={<CancelIcon />} variant="outlined" onClick={close} color="secondary">
{LL.CANCEL()}
</Button>
<Button startIcon={creating ? <AddIcon /> : <DoneIcon />} variant="outlined" onClick={save} color="primary">
{creating ? LL.ADD(0) : LL.UPDATE()}
</Button>
</DialogActions>
</Dialog>
);
};
export default SettingsCustomEntitiesDialog;

View File

@@ -23,7 +23,7 @@ import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-li
import { useTheme } from '@table-library/react-table-library/theme'; import { useTheme } from '@table-library/react-table-library/theme';
import { useRequest } from 'alova'; import { useRequest } from 'alova';
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect, useCallback } from 'react';
import { unstable_useBlocker as useBlocker } from 'react-router-dom'; import { useBlocker, useLocation } from 'react-router-dom';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import EntityMaskToggle from './EntityMaskToggle'; import EntityMaskToggle from './EntityMaskToggle';
@@ -52,20 +52,26 @@ const SettingsCustomization: FC = () => {
const [restarting, setRestarting] = useState<boolean>(false); const [restarting, setRestarting] = useState<boolean>(false);
const [restartNeeded, setRestartNeeded] = useState<boolean>(false); const [restartNeeded, setRestartNeeded] = useState<boolean>(false);
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([]); const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([]);
const [selectedDevice, setSelectedDevice] = useState<number>(-1);
const [confirmReset, setConfirmReset] = useState<boolean>(false); const [confirmReset, setConfirmReset] = useState<boolean>(false);
const [selectedFilters, setSelectedFilters] = useState<number>(0); const [selectedFilters, setSelectedFilters] = useState<number>(0);
const [search, setSearch] = useState(''); const [search, setSearch] = useState('');
const [selectedDeviceEntity, setSelectedDeviceEntity] = useState<DeviceEntity>(); const [selectedDeviceEntity, setSelectedDeviceEntity] = useState<DeviceEntity>();
const [dialogOpen, setDialogOpen] = useState<boolean>(false); const [dialogOpen, setDialogOpen] = useState<boolean>(false);
// fetch devices first
const { data: devices } = useRequest(EMSESP.readDevices);
// const { state } = useLocation();
const [selectedDevice, setSelectedDevice] = useState<number>(useLocation().state || -1);
const [selectedDeviceName, setSelectedDeviceName] = useState<string>('');
const { send: resetCustomizations } = useRequest(EMSESP.resetCustomizations(), { const { send: resetCustomizations } = useRequest(EMSESP.resetCustomizations(), {
immediate: false immediate: false
}); });
const { data: devices } = useRequest(EMSESP.readDevices); const { send: writeCustomizationEntities } = useRequest((data) => EMSESP.writeCustomizationEntities(data), {
immediate: false
const { send: writeCustomEntities } = useRequest((data) => EMSESP.writeCustomEntities(data), { immediate: false }); });
const { send: readDeviceEntities, onSuccess: onSuccess } = useRequest((data) => EMSESP.readDeviceEntities(data), { const { send: readDeviceEntities, onSuccess: onSuccess } = useRequest((data) => EMSESP.readDeviceEntities(data), {
initialData: [], initialData: [],
@@ -174,6 +180,22 @@ const SettingsCustomization: FC = () => {
} }
}, [deviceEntities]); }, [deviceEntities]);
useEffect(() => {
if (devices && selectedDevice !== -1) {
void readDeviceEntities(selectedDevice);
const id = devices.devices.findIndex((d) => d.i === selectedDevice);
if (id === -1) {
setSelectedDevice(-1);
setSelectedDeviceName('');
} else {
setSelectedDeviceName(devices.devices[id].tn || '');
setNumChanges(0);
setRestartNeeded(false);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [devices, selectedDevice]);
const restart = async () => { const restart = async () => {
await restartCommand().catch((error) => { await restartCommand().catch((error) => {
toast.error(error.message); toast.error(error.message);
@@ -244,16 +266,6 @@ const SettingsCustomization: FC = () => {
); );
}; };
const changeSelectedDevice = (event: React.ChangeEvent<HTMLInputElement>) => {
if (devices) {
const selected_device = parseInt(event.target.value, 10);
setSelectedDevice(selected_device);
setNumChanges(0);
void readDeviceEntities(devices?.devices[selected_device].i);
setRestartNeeded(false);
}
};
const resetCustomization = async () => { const resetCustomization = async () => {
try { try {
await resetCustomizations(); await resetCustomizations();
@@ -312,30 +324,21 @@ const SettingsCustomization: FC = () => {
return; return;
} }
await writeCustomEntities({ id: devices?.devices[selectedDevice].i, entity_ids: masked_entities }).catch( await writeCustomizationEntities({ id: selectedDevice, entity_ids: masked_entities }).catch((error) => {
(error) => { if (error.message === 'Reboot required') {
if (error.message === 'Reboot required') { setRestartNeeded(true);
setRestartNeeded(true); } else {
} else { toast.error(error.message);
toast.error(error.message);
}
} }
); });
setOriginalSettings(deviceEntities); setOriginalSettings(deviceEntities);
} }
}; };
const renderDeviceList = () => ( const renderDeviceList = () => (
<> <>
<Box mb={2} color="warning.main"> <Box mb={1} color="warning.main">
<Typography variant="body2">{LL.CUSTOMIZATIONS_HELP_1()}.</Typography> <Typography variant="body2">{LL.CUSTOMIZATIONS_HELP_1()}.</Typography>
<Typography variant="body2" mt={1}>
<OptionIcon type="favorite" isSet={true} />={LL.CUSTOMIZATIONS_HELP_2()}&nbsp;&nbsp;
<OptionIcon type="readonly" isSet={true} />={LL.CUSTOMIZATIONS_HELP_3()}&nbsp;&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_4()}&nbsp;&nbsp;
<OptionIcon type="web_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_5()}&nbsp;&nbsp;
<OptionIcon type="deleted" isSet={true} />={LL.CUSTOMIZATIONS_HELP_6()}
</Typography>
</Box> </Box>
<TextField <TextField
name="device" name="device"
@@ -344,15 +347,15 @@ const SettingsCustomization: FC = () => {
fullWidth fullWidth
value={selectedDevice} value={selectedDevice}
disabled={numChanges !== 0} disabled={numChanges !== 0}
onChange={changeSelectedDevice} onChange={(e) => setSelectedDevice(parseInt(e.target.value))}
margin="normal" margin="normal"
select select
> >
<MenuItem disabled key={-1} value={-1}> <MenuItem disabled key={-1} value={-1}>
{LL.SELECT_DEVICE()}... {LL.SELECT_DEVICE()}...
</MenuItem> </MenuItem>
{devices.devices.map((device: DeviceShort, index) => ( {devices.devices.map((device: DeviceShort) => (
<MenuItem key={index} value={index}> <MenuItem key={device.i} value={device.i}>
{device.s} {device.s}
</MenuItem> </MenuItem>
))} ))}
@@ -361,14 +364,19 @@ const SettingsCustomization: FC = () => {
); );
const renderDeviceData = () => { const renderDeviceData = () => {
if (deviceEntities.length === 0) {
return;
}
const shown_data = deviceEntities.filter((de) => filter_entity(de)); const shown_data = deviceEntities.filter((de) => filter_entity(de));
return ( return (
<> <>
<Box color="warning.main">
<Typography variant="body2" mt={1}>
<OptionIcon type="favorite" isSet={true} />={LL.CUSTOMIZATIONS_HELP_2()}&nbsp;&nbsp;
<OptionIcon type="readonly" isSet={true} />={LL.CUSTOMIZATIONS_HELP_3()}&nbsp;&nbsp;
<OptionIcon type="api_mqtt_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_4()}&nbsp;&nbsp;
<OptionIcon type="web_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_5()}&nbsp;&nbsp;
<OptionIcon type="deleted" isSet={true} />={LL.CUSTOMIZATIONS_HELP_6()}
</Typography>
</Box>
<Grid container mb={1} mt={0} spacing={1} direction="row" justifyContent="flex-start" alignItems="center"> <Grid container mb={1} mt={0} spacing={1} direction="row" justifyContent="flex-start" alignItems="center">
<Grid item xs={2}> <Grid item xs={2}>
<TextField <TextField
@@ -441,7 +449,7 @@ const SettingsCustomization: FC = () => {
</Grid> </Grid>
<Grid item> <Grid item>
<Typography variant="subtitle2" color="primary"> <Typography variant="subtitle2" color="primary">
{LL.SHOWING()}&nbsp;{shown_data.length}/{deviceEntities.length} {LL.SHOWING()}&nbsp;{shown_data.length}/{deviceEntities.length}&nbsp;{LL.ENTITIES(deviceEntities.length)}
</Typography> </Typography>
</Grid> </Grid>
</Grid> </Grid>
@@ -465,7 +473,7 @@ const SettingsCustomization: FC = () => {
</Cell> </Cell>
<Cell> <Cell>
{formatName(de, false)}&nbsp;( {formatName(de, false)}&nbsp;(
<Link target="_blank" href={APIURL + devices?.devices[selectedDevice].tn + '/' + de.id}> <Link target="_blank" href={APIURL + selectedDeviceName + '/' + de.id}>
{de.id} {de.id}
</Link> </Link>
) )
@@ -504,9 +512,9 @@ const SettingsCustomization: FC = () => {
{LL.DEVICE_ENTITIES()} {LL.DEVICE_ENTITIES()}
</Typography> </Typography>
{devices && renderDeviceList()} {devices && renderDeviceList()}
{renderDeviceData()} {deviceEntities && renderDeviceData()}
{restartNeeded && ( {restartNeeded && (
<MessageBox my={2} level="warning" message={LL.RESTART_TEXT()}> <MessageBox my={2} level="warning" message={LL.RESTART_TEXT(0)}>
<Button startIcon={<PowerSettingsNewIcon />} variant="contained" color="error" onClick={restart}> <Button startIcon={<PowerSettingsNewIcon />} variant="contained" color="error" onClick={restart}>
{LL.RESTART()} {LL.RESTART()}
</Button> </Button>
@@ -521,7 +529,7 @@ const SettingsCustomization: FC = () => {
startIcon={<CancelIcon />} startIcon={<CancelIcon />}
variant="outlined" variant="outlined"
color="secondary" color="secondary"
onClick={() => devices && readDeviceEntities(devices.devices[selectedDevice].i)} onClick={() => devices && readDeviceEntities(selectedDevice)}
> >
{LL.CANCEL()} {LL.CANCEL()}
</Button> </Button>

View File

@@ -70,7 +70,7 @@ const SettingsCustomizationDialog = ({ open, onClose, onSave, selectedItem }: Se
<DialogContent dividers> <DialogContent dividers>
<Grid container direction="row"> <Grid container direction="row">
<Typography variant="body2" color="warning.main"> <Typography variant="body2" color="warning.main">
{LL.ENTITY() + ' ID'}:&nbsp; {LL.ID_OF(LL.ENTITY())}:&nbsp;
</Typography> </Typography>
<Typography variant="body2">{editItem.id}</Typography> <Typography variant="body2">{editItem.id}</Typography>
</Grid> </Grid>

View File

@@ -1,252 +0,0 @@
import AddIcon from '@mui/icons-material/Add';
import CancelIcon from '@mui/icons-material/Cancel';
import DoneIcon from '@mui/icons-material/Done';
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
import {
Box,
Button,
Checkbox,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Grid,
InputAdornment,
MenuItem,
TextField
} from '@mui/material';
import { useEffect, useState } from 'react';
import { DeviceValueUOM_s, DeviceValueType } from './types';
import type { EntityItem } from './types';
import type Schema from 'async-validator';
import type { ValidateFieldsError } from 'async-validator';
import { dialogStyle } from 'CustomTheme';
import { BlockFormControlLabel, ValidatedTextField } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
import { updateValue } from 'utils';
import { validate } from 'validators';
type SettingsEntitiesDialogProps = {
open: boolean;
creating: boolean;
onClose: () => void;
onSave: (ei: EntityItem) => void;
selectedItem: EntityItem;
validator: Schema;
};
const SettingsEntitiesDialog = ({
open,
creating,
onClose,
onSave,
selectedItem,
validator
}: SettingsEntitiesDialogProps) => {
const { LL } = useI18nContext();
const [editItem, setEditItem] = useState<EntityItem>(selectedItem);
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
const updateFormValue = updateValue(setEditItem);
useEffect(() => {
if (open) {
setFieldErrors(undefined);
setEditItem(selectedItem);
// convert to hex strings straight away
setEditItem({
...selectedItem,
device_id: selectedItem.device_id.toString(16).toUpperCase(),
type_id: selectedItem.type_id.toString(16).toUpperCase()
});
}
}, [open, selectedItem]);
const close = () => {
onClose();
};
const save = async () => {
try {
setFieldErrors(undefined);
await validate(validator, editItem);
if (typeof editItem.device_id === 'string') {
editItem.device_id = parseInt(editItem.device_id, 16);
}
if (typeof editItem.type_id === 'string') {
editItem.type_id = parseInt(editItem.type_id, 16);
}
onSave(editItem);
} catch (errors: any) {
setFieldErrors(errors);
}
};
const remove = () => {
editItem.deleted = true;
onSave(editItem);
};
return (
<Dialog sx={dialogStyle} open={open} onClose={close}>
<DialogTitle>
{creating ? LL.ADD(1) + ' ' + LL.NEW(1) : LL.EDIT()}&nbsp;{LL.ENTITY()}
</DialogTitle>
<DialogContent dividers>
<Box display="flex" flexWrap="wrap" mb={1}>
<Box flexWrap="nowrap" whiteSpace="nowrap" />
</Box>
<Grid container spacing={2}>
<Grid item xs={8}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="name"
label={LL.NAME(0)}
value={editItem.name}
margin="normal"
fullWidth
onChange={updateFormValue}
/>
</Grid>
<Grid item xs={4} mt={3}>
<BlockFormControlLabel
control={<Checkbox checked={editItem.writeable} onChange={updateFormValue} name="writeable" />}
label={LL.WRITEABLE()}
/>
</Grid>
<Grid item xs={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="device_id"
label={LL.ID_OF(LL.DEVICE())}
margin="normal"
type="string"
fullWidth
value={editItem.device_id as string}
onChange={updateFormValue}
inputProps={{ style: { textTransform: 'uppercase' } }}
InputProps={{ startAdornment: <InputAdornment position="start">0x</InputAdornment> }}
/>
</Grid>
<Grid item xs={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="type_id"
label={LL.ID_OF(LL.TYPE(1))}
margin="normal"
fullWidth
value={editItem.type_id}
onChange={updateFormValue}
inputProps={{ style: { textTransform: 'uppercase' } }}
InputProps={{ startAdornment: <InputAdornment position="start">0x</InputAdornment> }}
/>
</Grid>
<Grid item xs={4}>
<ValidatedTextField
fieldErrors={fieldErrors}
name="offset"
label={LL.OFFSET()}
margin="normal"
fullWidth
type="number"
value={editItem.offset}
onChange={updateFormValue}
/>
</Grid>
<Grid item xs={4}>
<TextField
name="value_type"
label={LL.VALUE(1) + ' ' + LL.TYPE(1)}
value={editItem.value_type}
variant="outlined"
onChange={updateFormValue}
margin="normal"
fullWidth
select
>
<MenuItem value={DeviceValueType.BOOL}>BOOL</MenuItem>
<MenuItem value={DeviceValueType.INT}>INT</MenuItem>
<MenuItem value={DeviceValueType.UINT}>UINT</MenuItem>
<MenuItem value={DeviceValueType.SHORT}>SHORT</MenuItem>
<MenuItem value={DeviceValueType.USHORT}>USHORT</MenuItem>
<MenuItem value={DeviceValueType.ULONG}>ULONG</MenuItem>
<MenuItem value={DeviceValueType.TIME}>TIME</MenuItem>
<MenuItem value={DeviceValueType.STRING}>RAW</MenuItem>
</TextField>
</Grid>
{editItem.value_type !== DeviceValueType.BOOL && editItem.value_type !== DeviceValueType.STRING && (
<>
<Grid item xs={4}>
<TextField
name="factor"
label={LL.FACTOR()}
value={editItem.factor}
variant="outlined"
onChange={updateFormValue}
fullWidth
margin="normal"
type="number"
inputProps={{ step: '0.001' }}
/>
</Grid>
<Grid item xs={4}>
<TextField
name="uom"
label={LL.UNIT()}
value={editItem.uom}
margin="normal"
fullWidth
onChange={updateFormValue}
select
>
{DeviceValueUOM_s.map((val, i) => (
<MenuItem key={i} value={i}>
{val}
</MenuItem>
))}
</TextField>
</Grid>
</>
)}
{editItem.value_type === DeviceValueType.STRING && (
<Grid item xs={4}>
<TextField
name="factor"
label="Bytes"
value={editItem.factor}
variant="outlined"
onChange={updateFormValue}
fullWidth
margin="normal"
type="number"
inputProps={{ min: '1', max: '27', step: '1' }}
/>
</Grid>
)}
</Grid>
</DialogContent>
<DialogActions>
{!creating && (
<Box flexGrow={1}>
<Button startIcon={<RemoveIcon />} variant="outlined" color="warning" onClick={remove}>
{LL.REMOVE()}
</Button>
</Box>
)}
<Button startIcon={<CancelIcon />} variant="outlined" onClick={close} color="secondary">
{LL.CANCEL()}
</Button>
<Button startIcon={creating ? <AddIcon /> : <DoneIcon />} variant="outlined" onClick={save} color="primary">
{creating ? LL.ADD(0) : LL.UPDATE()}
</Button>
</DialogActions>
</Dialog>
);
};
export default SettingsEntitiesDialog;

View File

@@ -9,7 +9,7 @@ import { useTheme } from '@table-library/react-table-library/theme';
// eslint-disable-next-line import/named // eslint-disable-next-line import/named
import { updateState, useRequest } from 'alova'; import { updateState, useRequest } from 'alova';
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect, useCallback } from 'react';
import { unstable_useBlocker as useBlocker } from 'react-router-dom'; import { useBlocker } from 'react-router-dom';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import SettingsSchedulerDialog from './SettingsSchedulerDialog'; import SettingsSchedulerDialog from './SettingsSchedulerDialog';
import * as EMSESP from './api'; import * as EMSESP from './api';
@@ -208,7 +208,7 @@ const SettingsScheduler: FC = () => {
<HeaderCell stiff>{LL.SCHEDULE(0)}</HeaderCell> <HeaderCell stiff>{LL.SCHEDULE(0)}</HeaderCell>
<HeaderCell stiff>{LL.TIME(0)}</HeaderCell> <HeaderCell stiff>{LL.TIME(0)}</HeaderCell>
<HeaderCell stiff>{LL.COMMAND(0)}</HeaderCell> <HeaderCell stiff>{LL.COMMAND(0)}</HeaderCell>
<HeaderCell stiff>{LL.VALUE(0)}</HeaderCell> <HeaderCell stiff>{LL.VALUE(1)}</HeaderCell>
<HeaderCell stiff>{LL.NAME(0)}</HeaderCell> <HeaderCell stiff>{LL.NAME(0)}</HeaderCell>
</HeaderRow> </HeaderRow>
</Header> </Header>

View File

@@ -19,7 +19,8 @@ import { alovaInstance } from 'api/endpoints';
export const readCoreData = () => alovaInstance.Get<CoreData>(`/rest/coreData`); export const readCoreData = () => alovaInstance.Get<CoreData>(`/rest/coreData`);
export const readDeviceData = (id: number) => export const readDeviceData = (id: number) =>
alovaInstance.Get<DeviceData>('/rest/deviceData', { alovaInstance.Get<DeviceData>('/rest/deviceData', {
params: { id }, // alovaInstance.Get<DeviceData>(`/rest/deviceData/${id}`, {
params: { id }, // TODO replace later with id
responseType: 'arraybuffer' // uses msgpack responseType: 'arraybuffer' // uses msgpack
}); });
export const writeDeviceValue = (data: any) => alovaInstance.Post('/rest/writeDeviceValue', data); export const writeDeviceValue = (data: any) => alovaInstance.Post('/rest/writeDeviceValue', data);
@@ -53,8 +54,9 @@ export const getSchedule = () => alovaInstance.Get('/rest/getSchedule');
// SettingsCustomization // SettingsCustomization
export const readDeviceEntities = (id: number) => export const readDeviceEntities = (id: number) =>
alovaInstance.Get<DeviceEntity[]>('/rest/deviceEntities', { // alovaInstance.Get<DeviceEntity[]>(`/rest/deviceEntities/${id}`, {
params: { id }, alovaInstance.Get<DeviceEntity[]>(`/rest/deviceEntities`, {
params: { id }, // TODO replace later with id
responseType: 'arraybuffer', responseType: 'arraybuffer',
transformData(data: any) { transformData(data: any) {
return data.map((de: DeviceEntity) => ({ ...de, o_m: de.m, o_cn: de.cn, o_mi: de.mi, o_ma: de.ma })); return data.map((de: DeviceEntity) => ({ ...de, o_m: de.m, o_cn: de.cn, o_mi: de.mi, o_ma: de.ma }));
@@ -62,7 +64,7 @@ export const readDeviceEntities = (id: number) =>
}); });
export const readDevices = () => alovaInstance.Get<Devices>('/rest/devices'); export const readDevices = () => alovaInstance.Get<Devices>('/rest/devices');
export const resetCustomizations = () => alovaInstance.Post('/rest/resetCustomizations'); export const resetCustomizations = () => alovaInstance.Post('/rest/resetCustomizations');
export const writeCustomEntities = (data: any) => alovaInstance.Post('/rest/customEntities', data); export const writeCustomizationEntities = (data: any) => alovaInstance.Post('/rest/customizationEntities', data);
// SettingsScheduler // SettingsScheduler
export const readSchedule = () => export const readSchedule = () =>
@@ -85,8 +87,8 @@ export const readSchedule = () =>
export const writeSchedule = (data: any) => alovaInstance.Post('/rest/schedule', data); export const writeSchedule = (data: any) => alovaInstance.Post('/rest/schedule', data);
// SettingsEntities // SettingsEntities
export const readEntities = () => export const readCustomEntities = () =>
alovaInstance.Get<EntityItem[]>('/rest/entities', { alovaInstance.Get<EntityItem[]>('/rest/customEntities', {
name: 'entities', name: 'entities',
transformData(data: any) { transformData(data: any) {
return data.entities.map((ei: EntityItem) => ({ return data.entities.map((ei: EntityItem) => ({
@@ -104,4 +106,4 @@ export const readEntities = () =>
})); }));
} }
}); });
export const writeEntities = (data: any) => alovaInstance.Post('/rest/entities', data); export const writeCustomEntities = (data: any) => alovaInstance.Post('/rest/customEntities', data);

View File

@@ -7,6 +7,7 @@ export interface Settings {
syslog_mark_interval: number; syslog_mark_interval: number;
syslog_host: string; syslog_host: string;
syslog_port: number; syslog_port: number;
boiler_heatingoff: boolean;
shower_timer: boolean; shower_timer: boolean;
shower_alert: boolean; shower_alert: boolean;
shower_alert_coldshot: number; shower_alert_coldshot: number;
@@ -68,6 +69,7 @@ export interface Device {
d: number; // deviceid d: number; // deviceid
p: number; // productid p: number; // productid
v: string; // version v: string; // version
e: number; // entities
} }
export interface TemperatureSensor { export interface TemperatureSensor {
@@ -100,6 +102,7 @@ export interface SensorData {
ts: TemperatureSensor[]; ts: TemperatureSensor[];
as: AnalogSensor[]; as: AnalogSensor[];
analog_enabled: boolean; analog_enabled: boolean;
platform: string;
} }
export interface CoreData { export interface CoreData {
@@ -127,7 +130,7 @@ export interface DeviceValue {
c?: string; // command, optional c?: string; // command, optional
l?: string[]; // list, optional l?: string[]; // list, optional
h?: string; // help text, optional h?: string; // help text, optional
s?: number; // steps for up/down, optional s?: string; // steps for up/down, optional
m?: number; // min, optional m?: number; // min, optional
x?: number; // max, optional x?: number; // max, optional
} }
@@ -173,7 +176,9 @@ export enum DeviceValueUOM {
M3, M3,
L, L,
KMIN, KMIN,
K K,
VOLTS,
MBAR
} }
export const DeviceValueUOM_s = [ export const DeviceValueUOM_s = [
@@ -199,7 +204,9 @@ export const DeviceValueUOM_s = [
'm³', 'm³',
'l', 'l',
'K*min', 'K*min',
'K' 'K',
'V',
'mbar'
]; ];
export enum AnalogType { export enum AnalogType {
@@ -218,12 +225,12 @@ export enum AnalogType {
export const AnalogTypeNames = [ export const AnalogTypeNames = [
'(disabled)', '(disabled)',
'Digital in', 'Digital In',
'Counter', 'Counter',
'ADC', 'ADC',
'Timer', 'Timer',
'Rate', 'Rate',
'Digital out', 'Digital Out',
'PWM 0', 'PWM 0',
'PWM 1', 'PWM 1',
'PWM 2' 'PWM 2'
@@ -235,7 +242,9 @@ type BoardProfiles = {
export const BOARD_PROFILES: BoardProfiles = { export const BOARD_PROFILES: BoardProfiles = {
S32: 'BBQKees Gateway S32', S32: 'BBQKees Gateway S32',
S32S3: 'BBQKees Gateway S3',
E32: 'BBQKees Gateway E32', E32: 'BBQKees Gateway E32',
E32V2: 'BBQKees Gateway E32 V2',
NODEMCU: 'NodeMCU 32S', NODEMCU: 'NodeMCU 32S',
'MH-ET': 'MH-ET Live D1 Mini', 'MH-ET': 'MH-ET Live D1 Mini',
LOLIN: 'Lolin D32', LOLIN: 'Lolin D32',
@@ -243,8 +252,7 @@ export const BOARD_PROFILES: BoardProfiles = {
OLIMEXPOE: 'Olimex ESP32-POE', OLIMEXPOE: 'Olimex ESP32-POE',
C3MINI: 'Wemos C3 Mini', C3MINI: 'Wemos C3 Mini',
S2MINI: 'Wemos S2 Mini', S2MINI: 'Wemos S2 Mini',
S3MINI: 'Liligo S3', S3MINI: 'Liligo S3'
S32S3: 'BBQKees Gateway S3'
}; };
export interface BoardProfile { export interface BoardProfile {
@@ -317,6 +325,7 @@ export enum ScheduleFlag {
export interface EntityItem { export interface EntityItem {
id: number; // unique number id: number; // unique number
ram: number;
name: string; name: string;
device_id: number | string; device_id: number | string;
type_id: number | string; type_id: number | string;
@@ -328,6 +337,7 @@ export interface EntityItem {
writeable: boolean; writeable: boolean;
deleted?: boolean; deleted?: boolean;
o_id?: number; o_id?: number;
o_ram?: number;
o_name?: string; o_name?: string;
o_device_id?: number | string; o_device_id?: number | string;
o_type_id?: number | string; o_type_id?: number | string;
@@ -337,6 +347,7 @@ export interface EntityItem {
o_value_type?: number; o_value_type?: number;
o_deleted?: boolean; o_deleted?: boolean;
o_writeable?: boolean; o_writeable?: boolean;
o_value?: any;
} }
export interface Entities { export interface Entities {
@@ -359,7 +370,7 @@ export const enum DeviceType {
CONTROLLER, CONTROLLER,
CONNECT, CONNECT,
ALERT, ALERT,
PUMP, EXTENSION,
GENERIC, GENERIC,
HEATSOURCE, HEATSOURCE,
CUSTOM, CUSTOM,
@@ -381,6 +392,7 @@ export const enum DeviceValueType {
} }
export const DeviceValueTypeNames = [ export const DeviceValueTypeNames = [
//
'BOOL', 'BOOL',
'INT', 'INT',
'UINT', 'UINT',
@@ -389,6 +401,6 @@ export const DeviceValueTypeNames = [
'ULONG', 'ULONG',
'TIME', 'TIME',
'ENUM', 'ENUM',
'STRING', 'RAW',
'CMD' 'CMD'
]; ];

View File

@@ -8,8 +8,7 @@ export const GPIO_VALIDATOR = {
if ( if (
value && value &&
(value === 1 || (value === 1 ||
(value >= 6 && value <= 12) || (value >= 6 && value <= 11) ||
(value >= 14 && value <= 15) ||
value === 20 || value === 20 ||
value === 24 || value === 24 ||
(value >= 28 && value <= 31) || (value >= 28 && value <= 31) ||
@@ -189,12 +188,12 @@ export const isGPIOUniqueValidator = (sensors: AnalogSensor[]) => ({
} }
}); });
export const analogSensorItemValidation = (sensors: AnalogSensor[], creating: boolean) => export const analogSensorItemValidation = (sensors: AnalogSensor[], creating: boolean, platform: string) =>
new Schema({ new Schema({
n: [{ required: true, message: 'Name is required' }], n: [{ required: true, message: 'Name is required' }],
g: [ g: [
{ required: true, message: 'GPIO is required' }, { required: true, message: 'GPIO is required' },
GPIO_VALIDATOR, platform === 'ESP32-S3' ? GPIO_VALIDATORS3 : platform === 'ESP32-C3' ? GPIO_VALIDATORC3 : GPIO_VALIDATOR,
...(creating ? [isGPIOUniqueValidator(sensors)] : []) ...(creating ? [isGPIOUniqueValidator(sensors)] : [])
] ]
}); });

View File

@@ -1,5 +1,4 @@
export * from './ap'; export * from './ap';
export * from './features';
export * from './me'; export * from './me';
export * from './mqtt'; export * from './mqtt';
export * from './ntp'; export * from './ntp';

View File

@@ -25,6 +25,7 @@ export interface MqttSettings {
port: number; port: number;
base: string; base: string;
rootCA?: string; rootCA?: string;
enableTLS?: boolean;
username: string; username: string;
password: string; password: string;
client_id: string; client_id: string;

View File

@@ -33,14 +33,16 @@ export interface NetworkStatus {
gateway_ip: string; gateway_ip: string;
dns_ip_1: string; dns_ip_1: string;
dns_ip_2: string; dns_ip_2: string;
hostname: string;
} }
export interface NetworkSettings { export interface NetworkSettings {
ssid: string; ssid: string;
bssid: string;
password: string; password: string;
hostname: string; hostname: string;
static_ip_config: boolean; static_ip_config: boolean;
enableIPv6: boolean; enableIPv6?: boolean;
bandwidth20: boolean; bandwidth20: boolean;
nosleep: boolean; nosleep: boolean;
tx_power: number; tx_power: number;

Some files were not shown because too many files have changed in this diff Show More