927 Commits

Author SHA1 Message Date
Proddy
86919c1684 Merge branch 'origin/dev' 2023-09-09 14:12:07 +02:00
Proddy
677f6c5a6e Merge pull request #1290 from proddy/dev
#1280 sample value is a string for enums
2023-09-09 13:43:09 +02:00
Proddy
3ce67b8e6e Merge branch 'dev' of https://github.com/proddy/EMS-ESP32 into dev 2023-09-09 13:42:29 +02:00
Proddy
aad9c12a7e fixes MQTT enum index option leads to error in HA #1280 2023-09-09 13:42:28 +02:00
Proddy
877d60f46f Merge pull request #1289 from MichaelDvP/dev
Fixes from testbuild
2023-09-09 12:32:57 +02:00
MichaelDvP
bf02b0ad1c Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-09-09 12:29:01 +02:00
MichaelDvP
2f5b7cd0aa add back process dest, fixes #1275 2023-09-09 12:25:18 +02:00
MichaelDvP
4bec32ea56 HA register all values from custom and scheduler 2023-09-09 12:11:30 +02:00
Proddy
33ea1c6863 Merge pull request #1288 from proddy/dev
fix for MQTT enum index option leads to error in HA #1280
2023-09-09 10:26:25 +02:00
Proddy
09ff892b91 fix for MQTT enum index option leads to error in HA #1280 2023-09-09 10:25:14 +02:00
Proddy
f462afb547 update pacakges 2023-09-09 10:25:05 +02:00
Proddy
83211e0ef8 Merge pull request #1286 from MichaelDvP/dev
show color wifi-quality in network selector
2023-09-08 15:26:05 +02:00
MichaelDvP
b7b3cb177f show wifi-quality in network selector 2023-09-08 10:35:39 +02:00
Proddy
04fd04b2ab Merge pull request #1285 from proddy/dev
mqtt fix
2023-09-08 09:26:50 +02:00
Proddy
6e3c2b2ec9 update example for debug 2023-09-08 08:34:19 +02:00
Proddy
98e29516b0 fix mqtt enum in discovery #1280 2023-09-08 08:30:51 +02:00
Proddy
6db5058e3d updated to 3.6.1-dev.2 2023-09-08 08:30:24 +02:00
Proddy
b3ada4a01f 3.6.1-dev.2 2023-09-08 08:30:17 +02:00
Proddy
f38e0abf73 package updates 2023-09-08 08:30:05 +02:00
Proddy
27aa72eda1 Merge pull request #1284 from MichaelDvP/dev
fix for espressif@6.4.0
2023-09-06 10:59:49 +02:00
MichaelDvP
01f6024776 color network antenna icon for wifi quality 2023-09-06 10:33:58 +02:00
MichaelDvP
aa5730c683 stay on platform 6.3.2 for esp32 until heap issue is solved 2023-09-06 09:20:31 +02:00
MichaelDvP
fcc2a48192 Update to espressif32@6.4.0, v3.6.1-dev.1 2023-09-06 08:05:45 +02:00
Proddy
9ebcfe38bc Merge pull request #1279 from proddy/dev
add missing translations and show value type in table
2023-09-02 13:41:58 +02:00
Proddy
57a585741d addd missing translations and show value type in table 2023-09-02 13:40:33 +02:00
Proddy
243aec37fd Merge pull request #1277 from proddy/dev
minor changes
2023-09-02 11:14:30 +02:00
Proddy
fb44e020fc fix standalone build 2023-09-02 11:12:52 +02:00
Proddy
81842e544b auto formatting with clang 2023-09-02 11:10:32 +02:00
Proddy
6babdab8de change 3.7.0 to 3.6.1 as we need a critical patch soon 2023-09-02 11:10:16 +02:00
Proddy
93d50bbee1 update for 3.6.1 2023-09-02 11:09:55 +02:00
Proddy
e6f0ecce62 show green/red circles if active 2023-09-02 11:00:00 +02:00
Proddy
aba597aa6a searches both custom name and shortname, show writable 2023-09-02 10:54:13 +02:00
Proddy
7444fdceff package update 2023-09-02 10:53:31 +02:00
Proddy
f60197e9bf Merge pull request #1273 from MichaelDvP/dev
update Mqtt Client
2023-08-31 12:12:08 +02:00
MichaelDvP
4778206e3a changelog 2023-08-31 12:09:17 +02:00
MichaelDvP
005463c41f update espMqttClient 2023-08-31 11:50:31 +02:00
MichaelDvP
ae1bf1cbfb merge mqtt changes from bertmelis, dev2 2023-08-31 09:47:07 +02:00
MichaelDvP
bde06621bd add log message for mqtt low memory 2023-08-31 08:29:08 +02:00
MichaelDvP
647acf6a68 show rssi in networkstatus 2023-08-31 08:19:24 +02:00
MichaelDvP
120c0b5ca2 update espMqttClient, add own mqtt limit, fix queue display, 3.7.0-dev1d 2023-08-31 08:09:54 +02:00
MichaelDvP
7e45c89fcd add missing subscribes 2023-08-31 08:07:06 +02:00
MichaelDvP
b7611c67bb Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-08-31 07:51:36 +02:00
Proddy
d6ae55218f Merge pull request #1272 from proddy/dev 2023-08-30 22:35:49 +02:00
MichaelDvP
d17582d697 mqtt check 60k free heap (not maxalloc), dev1c 2023-08-30 13:39:19 +02:00
MichaelDvP
c3227a6352 mqtt:min alloc to 45k, fix memcheck for PSRAM, dev1b 2023-08-30 12:38:29 +02:00
MichaelDvP
d0c368f6a0 dont allow not_connected_publish, fix mqtt success/fail counters, v3.7.0-dev1a 2023-08-30 12:19:55 +02:00
Proddy
9aa9cc46e9 bump version 3.7.0-dev1 2023-08-29 22:34:09 +02:00
Proddy
4ee045b84e formatting and adding a t command in debug/standalone 2023-08-29 22:33:50 +02:00
Proddy
2fe18c14c7 text changes and formatting 2023-08-29 22:33:26 +02:00
Proddy
f46b002c5a API call for shower coldshot - #1267 2023-08-29 22:32:36 +02:00
Proddy
65ea11b48b formatting only 2023-08-29 22:31:35 +02:00
Proddy
b2113add02 update API tests from VSC 2023-08-29 22:31:18 +02:00
Proddy
152e6ce1b9 don't spell check C files 2023-08-29 22:31:05 +02:00
Proddy
78a5166e48 update packages 2023-08-29 22:30:48 +02:00
MichaelDvP
f6a4da0584 mqtt free mem to 40k, v3.7.0-dev1 2023-08-29 12:40:10 +02:00
MichaelDvP
1818057c4c update packages 2023-08-29 12:39:14 +02:00
Proddy
9c946b9808 Merge branch 'dev' of https://github.com/proddy/EMS-ESP32 into dev 2023-08-20 16:55:15 +02:00
Proddy
c703106058 update packages 2023-08-20 16:55:14 +02:00
Proddy
1bc70f09c5 remove polling 2023-08-20 16:55:05 +02:00
Proddy
d049572239 Merge pull request #1266 from proddy/dev
update web packages
2023-08-19 10:07:50 +02:00
Proddy
0feaed8869 update web packages 2023-08-19 10:07:14 +02:00
Proddy
7496f482ab remove zipfs 2023-08-19 10:07:07 +02:00
Proddy
f6faad7255 Merge pull request #1263 from proddy/dev
build s3
2023-08-15 18:54:36 +02:00
Proddy
757757fa3f package update 2023-08-15 18:51:04 +02:00
Proddy
1fd3c11e12 build s3 2023-08-15 18:50:58 +02:00
Proddy
86e29515e7 build s3 2023-08-15 18:44:24 +02:00
Proddy
b1f2273bb5 Merge pull request #1261 from proddy/dev
prepare for 3.7.0
2023-08-13 14:40:29 +02:00
Proddy
e9cf3f5ab5 prepare for 3.7.0 2023-08-13 14:40:03 +02:00
Proddy
46eb4185d7 update with 3.6.0 2023-08-13 14:37:13 +02:00
Proddy
8da6761a48 Merge branch 'dev' 2023-08-13 14:32:41 +02:00
Proddy
f6c34ee2c9 Merge pull request #1258 from proddy/dev
minor updates
2023-08-11 21:19:31 +02:00
Proddy
b500076f32 bump version to v18 with Michael's upgrade fix 2023-08-11 21:19:00 +02:00
Proddy
e87ea67435 update packages 2023-08-11 21:18:23 +02:00
Proddy
86c965b94d move prettier - so "yarn run format" works 2023-08-11 21:18:16 +02:00
Proddy
faec42ac71 Merge pull request #1257 from MichaelDvP/dev 2023-08-11 20:43:49 +02:00
MichaelDvP
86737fb38a also Network 2023-08-11 19:33:06 +02:00
MichaelDvP
c8e64668e9 fix upload settings file #1256 2023-08-11 19:14:52 +02:00
MichaelDvP
89b7eaac1c fix MM10 pump command 2023-08-11 19:14:23 +02:00
Proddy
ac889d921f Merge pull request #1254 from MichaelDvP/dev
nl translations from BBQKees
2023-08-10 21:05:12 +02:00
MichaelDvP
a652a3a0c3 nl translations 2023-08-10 16:18:09 +02:00
Proddy
0f88b7cfbc Merge pull request #1253 from proddy/dev
update sonar scanner
2023-08-09 13:51:43 +02:00
Proddy
8bb2157cd9 update sonar scanner 2023-08-09 13:51:13 +02:00
Proddy
b96cede131 Merge pull request #1252 from proddy/dev
rename EMS-ESP Status to System Status so HA doesn't complain (fixes #1243)
2023-08-09 09:16:20 +02:00
Proddy
b2590fc9e0 Merge branch 'emsesp:dev' into dev 2023-08-09 09:15:15 +02:00
Proddy
8dfff29389 fixes #1243 2023-08-09 09:03:52 +02:00
Proddy
0ab081c135 package update 2023-08-09 09:03:44 +02:00
Proddy
7a3aca1220 Merge pull request #1251 from MichaelDvP/dev
Fix HM200 compressor speed
2023-08-08 17:09:56 +02:00
MichaelDvP
1360a5d35b Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-08-08 16:28:13 +02:00
Proddy
9226e5b303 Merge pull request #1250 from proddy/dev
small changes
2023-08-08 15:53:52 +02:00
Proddy
4e4cc93092 Merge branch 'emsesp:dev' into dev 2023-08-08 15:49:24 +02:00
Proddy
faa3479f0a make progmem work again 2023-08-08 15:49:08 +02:00
Proddy
0924f441cb update packages 2023-08-08 15:48:54 +02:00
Proddy
f39deefbb4 add vscode extensions 2023-08-08 15:48:45 +02:00
MichaelDvP
461f1bb102 Merge branch 'dev' of https://github.com/proddy/EMS-ESP32 into dev 2023-08-08 12:28:54 +02:00
MichaelDvP
1d1aaef291 add back progmem generation 2023-08-08 12:06:24 +02:00
Proddy
3c51e80408 remove translation for Heatbeat 2023-08-08 10:36:14 +02:00
Proddy
ff68d23642 add style to Dialog boxes 2023-08-08 10:35:55 +02:00
Proddy
643b42469e hardcode colours 2023-08-08 10:34:45 +02:00
Proddy
a996d00f70 remove aria labels 2023-08-08 10:34:10 +02:00
MichaelDvP
6ccab21791 fix HM200 compressor speed, #1247 2023-08-08 09:07:09 +02:00
Proddy
b5b965e339 fix typo 2023-08-08 09:02:21 +02:00
Proddy
2b54db255e update prettier for windows 2023-08-08 09:02:14 +02:00
Proddy
45fc13f7a0 Merge pull request #1249 from proddy/dev
hardcode links to release notes
2023-08-08 07:59:04 +02:00
Proddy
94407e5192 Merge branch 'emsesp:dev' into dev 2023-08-08 07:58:13 +02:00
proddy
7e791e56ce hardcode links to release notes 2023-08-08 07:57:51 +02:00
Proddy
2698116c63 Merge pull request #1245 from proddy/dev
Enhance version check to differentiate between ESP32 and ESP32-S3 bin versions #1240
2023-08-08 07:51:20 +02:00
proddy
e17f709fe1 increase size of username/password fields 2023-08-08 07:50:03 +02:00
proddy
c4ec535a82 update packages 2023-08-08 07:49:50 +02:00
proddy
7efc7616f8 fix platform to espressif32@6.3.2 2023-08-08 07:49:37 +02:00
Proddy
9468248995 fix ci_s3 2023-08-06 22:57:29 +02:00
Proddy
a72cbe9c0c bump version 2023-08-06 22:57:25 +02:00
Proddy
171df2c5b7 hardcode "platform = espressif32@6.3.1" for all targets 2023-08-06 18:48:28 +02:00
proddy
ca2bb4ba6f language menu in login page 2023-08-06 18:33:01 +02:00
proddy
9b92bfa81c Enhance version check to differentiate between ESP32 and ESP32-S3 bin versions #1240 2023-08-04 16:42:37 +02:00
proddy
0cc14215e6 dev.15 2023-08-01 22:02:53 +02:00
proddy
2e1e294baf update packages 2023-08-01 22:02:30 +02:00
proddy
6cee81aeb0 README.md: Fix link to supported devices #1239 2023-08-01 21:54:33 +02:00
Proddy
6e653eea7e Merge pull request #1237 from MichaelDvP/dev
more tr translations #1076
2023-07-31 14:53:15 +02:00
MichaelDvP
f788be691f more tr translations 2023-07-31 08:17:27 +02:00
Proddy
c167aa90bc Merge pull request #1236 from proddy/dev
merge dev2
2023-07-30 22:38:25 +02:00
proddy
657056d774 bump version 2023-07-30 22:32:43 +02:00
proddy
1d979cc894 Merge remote-tracking branch 'origin/dev2' into dev 2023-07-30 22:26:15 +02:00
Proddy
dda2d6316d Merge pull request #1235 from MichaelDvP/dev2
tr translation (part), response api
2023-07-30 14:54:27 +02:00
MichaelDvP
cac7ddd6bb log_trace for response 2023-07-30 08:29:01 +02:00
MichaelDvP
f677616b22 notice telegram log only for read, not for response 2023-07-29 17:11:11 +02:00
MichaelDvP
26daf548ff update packages 2023-07-29 16:51:05 +02:00
MichaelDvP
d92974dd88 read all telegram parts in one poll 2023-07-29 16:40:39 +02:00
MichaelDvP
52de833b19 response error messages 2023-07-29 16:39:37 +02:00
MichaelDvP
bb39e8bd4c update tr translation 2023-07-29 11:43:38 +02:00
Proddy
4295b2d114 Merge pull request #1234 from MichaelDvP/dev2
add cooling state, make mqtt on_message more clear
2023-07-24 21:11:07 +01:00
MichaelDvP
01060574ab mqtt on_message: make char * conversion more clear 2023-07-24 19:56:07 +02:00
MichaelDvP
2e829b560d thermostat cooling state 2023-07-24 19:03:44 +02:00
MichaelDvP
a2f0cafc5c update packages 2023-07-24 19:02:16 +02:00
Proddy
6a675736eb Merge pull request #1232 from proddy/dev2
upgrade arduinojson 6.21.3 and other minor formatting
2023-07-24 08:37:58 +01:00
proddy
c8466df61d exclude arduinojson with Todo Tree 2023-07-24 08:31:49 +01:00
proddy
ded26feeb6 upgrade arduinojson 6.21.3 2023-07-24 08:16:37 +01:00
proddy
b2482b092c bump version 2023-07-24 08:16:08 +01:00
proddy
67397dc345 auto format 2023-07-24 08:15:56 +01:00
Proddy
4a11147467 Merge pull request #1231 from MichaelDvP/dev2
fix mqtt `on_message`
2023-07-24 08:03:39 +01:00
MichaelDvP
962131592f fix mqtt on_message 2023-07-23 13:51:40 +02:00
Proddy
168a31d331 Merge pull request #1230 from proddy/dev2
Dev2
2023-07-21 23:49:12 +02:00
proddy
00f08951db mention preact 2023-07-21 22:48:17 +01:00
proddy
96d7069e8d make standalone compile 2023-07-21 22:44:27 +01:00
proddy
a4ddacb29c package update 2023-07-21 22:44:16 +01:00
proddy
93bbf2570e terser package update 2023-07-21 22:44:08 +01:00
Proddy
ba409b808d Merge pull request #1229 from MichaelDvP/dev2
api/response, Gateway S3, small fixes
2023-07-21 23:33:47 +02:00
MichaelDvP
207d92be64 scheduler value info 2023-07-21 21:18:51 +02:00
MichaelDvP
e3c775d0dd Add BBQKees Gateway S3, update changelog 2023-07-21 12:02:13 +02:00
MichaelDvP
2bd7e04d18 update packages 2023-07-21 10:31:39 +02:00
MichaelDvP
8b58282bde Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-07-21 09:16:51 +02:00
Proddy
ad6be2d5ef Merge pull request #1227 from proddy/dev2
standalone compiling and some formatting
2023-07-19 07:25:19 +02:00
MichaelDvP
c47414dad5 response show combined telegram 2023-07-17 09:53:40 +02:00
proddy
d84a555171 make standalone compile on osx 2023-07-15 12:42:54 +02:00
MichaelDvP
7a5f13bcad respond all telegram parts if request length >= 32 2023-07-15 12:27:48 +02:00
Proddy
1b6e3b89b6 formatting 2023-07-15 11:40:35 +02:00
Proddy
ed694f4ec5 formatting 2023-07-15 11:36:18 +02:00
Proddy
b659218d13 use original formatting 2023-07-15 11:34:57 +02:00
Proddy
cbecebd80a formatting 2023-07-15 11:34:46 +02:00
Proddy
7bb6427ec9 updated comments 2023-07-15 11:34:38 +02:00
Proddy
37724814be changes to compile standalone 2023-07-15 11:33:38 +02:00
Proddy
98dd25c5bb make EMS-ESP compile standalone on osx/darwin and linux 2023-07-15 11:00:04 +02:00
proddy
ccd69c2c3a compile on mac osx 2023-07-15 10:24:43 +02:00
MichaelDvP
6d0bd099e1 Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-07-14 19:15:28 +02:00
MichaelDvP
660a715893 4M asym partitions for usb flash 2023-07-14 19:11:59 +02:00
Proddy
981cdaecf1 Merge pull request #1226 from proddy/dev2
dev2 - minor changes
2023-07-14 17:25:37 +02:00
Proddy
18e4c3aa88 fix odd spelling mistakes 2023-07-14 16:45:58 +02:00
Proddy
116c51443e dev.13d 2023-07-14 16:45:52 +02:00
Proddy
66799d0c6c update packages 2023-07-14 16:45:38 +02:00
Proddy
9ad9bc5536 default esp32_4M 2023-07-14 16:45:27 +02:00
Proddy
d1ebf378dc update example 2023-07-14 16:45:14 +02:00
Proddy
4730389668 remove log line 2023-07-14 16:45:01 +02:00
Proddy
7881abaca2 run make from vsc 2023-07-14 12:12:53 +02:00
Proddy
f3d3a386ee get standadlone working with espMqttClient 2023-07-14 12:11:48 +02:00
Proddy
1b623014c1 added log message 2023-07-14 12:11:22 +02:00
Proddy
af3ed871af text change 2023-07-14 12:10:29 +02:00
Proddy
2a9be94f6e package cleanup 2023-07-14 12:10:19 +02:00
MichaelDvP
08a5437210 packages, custom entiie small fixes 2023-07-14 08:52:06 +02:00
Proddy
9ff8d01e93 make standalone compile 2023-07-13 21:50:34 +02:00
Proddy
0afda87092 update packages 2023-07-13 21:50:26 +02:00
MichaelDvP
18d32de483 fix custom entity value info 2023-07-13 18:23:04 +02:00
MichaelDvP
d9ad835fbc Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-07-13 12:42:30 +02:00
MichaelDvP
afad1d7b95 small updates 2023-07-13 12:42:07 +02:00
Proddy
e2f5124db9 Merge branch 'dev' of https://github.com/proddy/EMS-ESP32 into dev 2023-07-13 12:13:42 +02:00
Proddy
875507d7a9 Merge pull request #1225 from proddy/dev2
replace react with preact #1224
2023-07-13 12:10:48 +02:00
MichaelDvP
17b4964b01 test response and custom entity raw, #1212 2023-07-13 11:09:42 +02:00
Proddy
5af1f932bd Merge branch 'emsesp:dev2' into dev2 2023-07-13 08:28:22 +02:00
MichaelDvP
25ff2bd150 Merge branch 'dev2' of https://github.com/proddy/EMS-ESP32 into dev2 2023-07-12 19:17:16 +02:00
Proddy
3654003577 replace react with preact #1224 2023-07-12 13:26:47 +02:00
Proddy
ac96ea5308 Merge pull request #1223 from proddy/dev2
update changelog & version
2023-07-12 08:22:54 +02:00
Proddy
dde270a84c package update 2023-07-12 08:22:08 +02:00
Proddy
52c3153123 update changelog 2023-07-12 08:22:03 +02:00
Proddy
8557fec581 Merge pull request #1222 from MichaelDvP/dev2
MqttSecure, see #1178
2023-07-12 08:02:23 +02:00
MichaelDvP
b8e36eb13b Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-07-12 07:11:10 +02:00
Proddy
39624dcfcc Merge pull request #1219 from proddy/dev2
Add endpoint to read firmware capabilities #1218
2023-07-11 21:33:08 +02:00
Proddy
156d5a02d3 update text - bea0922ee8 2023-07-11 21:30:50 +02:00
Proddy
eb7ed0c524 don't render until we have a GET value 2023-07-11 21:28:19 +02:00
Proddy
0415ade906 show version on signin 2023-07-11 21:14:19 +02:00
Proddy
bf6c522918 remove features 2023-07-11 21:14:05 +02:00
Proddy
5f8f13e1a5 update lint & packages 2023-07-11 21:13:52 +02:00
Proddy
d92cd4ea2c Add endpoint to read firmware capabilities #1218 2023-07-11 13:28:29 +02:00
MichaelDvP
2c19b9369a Change MqttClient without restart, use secureClient for port >8800 2023-07-11 11:35:54 +02:00
MichaelDvP
78403adeb4 mqtt tls only for esp32-S3, certificate input strips header/footer/CR/LF 2023-07-11 07:50:13 +02:00
MichaelDvP
5374127d56 show WPA3 in networkselector 2023-07-11 07:08:30 +02:00
MichaelDvP
87f28e7804 adapt limits #1215, #1190 2023-07-11 07:07:45 +02:00
MichaelDvP
1e8adfb34f activate setInsecure to make tsl work 2023-07-10 15:22:33 +02:00
MichaelDvP
d3175e3d64 update packages 2023-07-10 12:44:27 +02:00
MichaelDvP
1b832b541a Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-07-10 12:38:56 +02:00
MichaelDvP
29557d764a Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-07-10 12:38:29 +02:00
MichaelDvP
ae46f40fce fix secure mqtt 2023-07-10 12:36:59 +02:00
Proddy
362d837baa Merge pull request #1211 from proddy/dev2
report on invalid extension - fixes #1210
2023-07-10 08:36:57 +02:00
MichaelDvP
2db7174068 fix cutting output of large numbers #1213 2023-07-10 07:57:24 +02:00
Proddy
1360ffaec0 remove bogus import 2023-07-09 20:08:03 +02:00
Proddy
91e0a29494 autoscroll in system log 2023-07-09 18:07:11 +02:00
Proddy
99b2da752f package update 2023-07-09 18:07:03 +02:00
Proddy
32884da60d Merge branch 'emsesp:dev2' into dev2 2023-07-09 17:43:38 +02:00
Proddy
d537247ead package updates 2023-07-09 10:55:30 +02:00
Proddy
d8364c5df2 close only on 406 2023-07-09 10:55:25 +02:00
MichaelDvP
f62b5548a3 add missing \n in certificate 2023-07-09 08:40:22 +02:00
MichaelDvP
443fe640b3 add optional secure mqtt 2023-07-08 16:24:44 +02:00
Proddy
365d246a89 fix prettier in vscode 2023-07-08 15:53:44 +02:00
Proddy
bea0922ee8 report on invalid extension - Validate file name extension on file upload #1210 2023-07-08 14:10:33 +02:00
Proddy
eb6e8d0c93 comments 2023-07-08 14:10:08 +02:00
Proddy
1b27ccf70e formatting 2023-07-08 14:08:25 +02:00
Proddy
3aa806ca65 formatting 2023-07-08 14:08:13 +02:00
Proddy
f99735921c package update, fixing lint 2023-07-08 14:07:58 +02:00
Proddy
c934e6617c some textual cleanup 2023-07-08 14:07:38 +02:00
Proddy
67ce23337f remove mention of scan devices 2023-07-08 14:07:25 +02:00
Proddy
b57bc11070 Merge pull request #1209 from proddy/dev2
add timeout so Wifi Scan works
2023-07-07 17:07:45 +02:00
Proddy
f3d1ed5596 add timeout so Wifi Scan works 2023-07-07 17:06:48 +02:00
Proddy
5112bf9e08 package update 2023-07-07 17:06:39 +02:00
Proddy
60594ff4b7 Merge pull request #1208 from proddy/dev2
refresh change log with all 3.6.0 updates
2023-07-07 14:43:14 +02:00
Proddy
dc3467e7fc package update 2023-07-06 20:37:37 +02:00
Proddy
bb87d064a5 formatting 2023-07-06 20:37:31 +02:00
Proddy
30388da021 refresh change log with all 3.6.0 updates 2023-07-06 20:37:25 +02:00
Proddy
1f7ddcec55 Merge pull request #1207 from MichaelDvP/dev2 2023-07-05 15:16:03 +02:00
MichaelDvP
942eba868a fix offsets for #1187 2023-07-05 15:13:30 +02:00
Proddy
d6e7b136a8 Merge pull request #1206 from proddy/dev2
order languages alphabetically
2023-07-05 09:39:38 +02:00
Proddy
55c33ef51f order languages alphabetically 2023-07-05 09:38:51 +02:00
Proddy
d33a554ab1 package update 2023-07-05 09:38:41 +02:00
Proddy
cbbe6ac589 Merge pull request #1205 from MichaelDvP/dev2
update it translations, etc
2023-07-03 21:32:42 +02:00
MichaelDvP
84b8fa8ff5 update it translations 2023-07-03 21:11:05 +02:00
MichaelDvP
3a7eb634de update packages 2023-07-03 21:10:20 +02:00
MichaelDvP
5977b0585d update mqtClient 2023-07-03 21:09:56 +02:00
Proddy
7b0d73e275 Merge pull request #1203 from MichaelDvP/dev2
reset dirty when saving
2023-07-03 13:15:38 +02:00
MichaelDvP
143ce8c80f Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-07-03 12:43:57 +02:00
MichaelDvP
4e736a4ff1 reset dirty when saving 2023-07-03 12:38:31 +02:00
Proddy
d2523fc5d2 upgrade ArduinoJson to 6.21.2 2023-07-03 11:44:37 +02:00
Proddy
ab4f8d46ad fix standalone build 2023-07-03 11:44:23 +02:00
Proddy
75defd0858 always add dump_entities for reference 2023-07-03 11:44:13 +02:00
Proddy
e52f0954cd fix build standalone 2023-07-03 11:43:50 +02:00
Proddy
98e9b62c85 fix lint warning 2023-07-03 10:18:52 +02:00
Proddy
40737ea552 fix typo 2023-07-03 10:02:30 +02:00
Proddy
523f501bd0 added yarn 2023-07-03 10:00:34 +02:00
Proddy
905c496fa3 ignore uploaded files 2023-07-03 10:00:03 +02:00
Proddy
2ad375884f add back json body parsing 2023-07-03 09:59:52 +02:00
Proddy
50b8db0c96 remove divider after EN. All countries are equals! 2023-07-03 09:59:34 +02:00
Proddy
36f88c772f increase timeout to 3 seconds 2023-07-03 09:59:12 +02:00
Proddy
7086358ebc fix for alova multi-cancel 2023-07-03 09:58:58 +02:00
Proddy
51769011be autoformatting 2023-07-03 08:56:08 +02:00
Proddy
d15de88065 Merge pull request #1202 from MichaelDvP/dev2
github action
2023-07-03 08:48:24 +02:00
Proddy
f909b32db8 remove todo 2023-07-02 23:45:01 +02:00
Proddy
e8e3fc5fb6 remove todo 2023-07-02 23:44:51 +02:00
Proddy
90a1bdd5d9 add back signon endpoint 2023-07-02 23:44:38 +02:00
Proddy
0b6eba294e add dutch translations 2023-07-02 23:44:21 +02:00
MichaelDvP
98b2a3a6e1 Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-07-02 22:10:45 +02:00
MichaelDvP
3bd21d4486 try to fix standalone 2023-07-02 22:10:34 +02:00
MichaelDvP
2094d42c3b readme 2023-07-02 22:09:52 +02:00
MichaelDvP
0156dd4956 test release 2023-07-02 22:02:43 +02:00
Proddy
da3e118444 fix restart monitor 2023-07-02 21:56:31 +02:00
Proddy
2663bc15f4 Merge pull request #1201 from MichaelDvP/dev2
Merge dev2
2023-07-02 15:43:16 +02:00
MichaelDvP
50939c1077 changelog 2023-07-02 13:57:34 +02:00
MichaelDvP
b0fc26b6eb remove unused async-mqtt-client-lib 2023-07-02 13:57:26 +02:00
MichaelDvP
476f84be77 Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2 2023-07-02 13:56:47 +02:00
Proddy
449bb4055c Merge pull request #1200 from proddy/dev-alova
Dev alova - #1112
2023-07-02 13:09:01 +02:00
Proddy
86daa13426 fix for cancel upload 2023-07-02 12:38:05 +02:00
MichaelDvP
09aea280b5 add it-translations 2023-07-02 12:09:14 +02:00
Proddy
34113c3698 fix progress bar when uploading 2023-07-02 10:12:31 +02:00
Proddy
9b21607da5 show EMS-ESP welcome message first 2023-07-02 10:12:17 +02:00
Proddy
985da48947 fix upload, except cancel 2023-07-01 17:01:08 +02:00
MichaelDvP
32f3c646f8 fix translation cooling 2023-07-01 15:51:26 +02:00
MichaelDvP
d27ef2530d fix crash on min/max check 2023-07-01 09:08:27 +02:00
proddy
fb41606e43 alova upload experiments 2023-06-30 14:25:01 +02:00
MichaelDvP
cbb7d46ede add cooling #1198, fix min limit of noreducetemp 2023-06-30 10:00:04 +02:00
MichaelDvP
3efe16c840 fix min/max adaption 2023-06-30 09:58:24 +02:00
MichaelDvP
8b800ded21 update packages 2023-06-30 09:57:49 +02:00
MichaelDvP
31220b3fde fix webEntity commands 2023-06-25 08:54:11 +02:00
MichaelDvP
f4cae5027e update packages 2023-06-25 08:53:20 +02:00
MichaelDvP
d17705db6c thermostat hpmodes 2023-06-25 08:52:55 +02:00
proddy
d6c5c87412 fix Cancel 2023-06-24 16:51:04 +02:00
proddy
89f14f1dba add comments 2023-06-24 16:50:59 +02:00
proddy
5fddb08330 increase timeout to 3 secs 2023-06-24 16:50:49 +02:00
proddy
f61c447ea5 add duplicate name check 2023-06-24 16:50:38 +02:00
Proddy
8b8b023665 update with 1196 2023-06-24 14:51:58 +02:00
Proddy
158617f56b fixes #1196 - use basename as ids in HA to support multiple EMS-ESP's 2023-06-24 13:28:48 +02:00
Proddy
27b9aa6ddd fix timeout 2023-06-24 09:09:34 +02:00
proddy
e615274f83 package updates 2023-06-23 19:12:29 +02:00
proddy
2b24f2585f optimize restart using alova lib 2023-06-21 23:15:38 +02:00
Proddy
0e52deae7b package updates 2023-06-20 22:52:16 +02:00
Proddy
bc6b48bd07 fix signin 2023-06-18 17:12:43 +02:00
Proddy
ce1b9f22cb alova - add interceptor 2023-06-18 16:35:32 +02:00
Proddy
b1d666d7b9 alova - refactor wifi scan 2023-06-18 10:46:50 +02:00
Proddy
ed55a96b80 more alova ports 2023-06-17 13:06:31 +02:00
proddy
2ae45ecd6e merging to sync - still need to fix system.ts 2023-06-16 06:44:49 +02:00
proddy
f58dbf6ec1 alova - update comments 2023-06-15 16:08:25 +02:00
proddy
adc4760b5f alova - implementing UpdateState 2023-06-14 23:30:52 +02:00
proddy
c44903e1b0 update #6 2023-06-13 23:36:50 +02:00
proddy
8e081ce04f alova update #6 2023-06-11 20:31:23 +02:00
proddy
5c6d704a48 alova updates #4 2023-06-08 16:50:40 +02:00
proddy
e11d5bed9d fix truncate of long device names in data box 2023-06-08 16:50:29 +02:00
proddy
5784bf744e added blur 2023-06-08 16:50:04 +02:00
Proddy
85716bc6bc update #4 - more alova 2023-06-05 22:40:21 +02:00
MichaelDvP
81e5ee8364 fix typo ventMode 2023-06-05 19:16:43 +02:00
Proddy
52d4505410 updates #3 2023-06-05 18:09:02 +02:00
MichaelDvP
b28865a283 use only espMqttClient queue 2023-06-05 10:06:19 +02:00
MichaelDvP
d2ff44e1cf Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-06-04 17:25:19 +02:00
MichaelDvP
9a34b2dd81 force mqtt disconnect on wifi disconnect 2023-06-04 17:24:03 +02:00
Proddy
43dc177a6d Merge pull request #1189 from emsesp/dev_fix 2023-06-04 16:41:39 +02:00
MichaelDvP
34046795b7 fix #1188 2023-06-04 16:40:42 +02:00
MichaelDvP
2c132a86b0 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-06-04 15:40:10 +02:00
MichaelDvP
759fe69909 fix prefix of customizations 2023-06-04 15:39:57 +02:00
MichaelDvP
181b672c1a add ventilation bypass 2023-06-04 15:32:43 +02:00
proddy
2e63d60273 alova implementation, testing 2023-06-04 15:22:09 +02:00
Proddy
46578dbe69 Update roboto.css - fix typo 2023-06-04 12:18:05 +02:00
MichaelDvP
cbc9607b26 apply changes/blocker for manage users 2023-06-03 17:46:26 +02:00
MichaelDvP
7865ddc51f use espMqttClient, qos2 fixed 2023-06-03 16:36:53 +02:00
Proddy
d9c2fe0fb9 Merge pull request #1186 from proddy/dev
suppress lint warning with make
2023-06-03 11:12:51 +04:00
proddy
02c386d76f supress lint warning wirh make 2023-06-03 09:11:43 +02:00
Proddy
ee0e6ed29f Merge pull request #1185 from proddy/dev
minor updates
2023-06-03 10:09:59 +04:00
Proddy
e858596658 package update 2023-06-03 08:09:23 +02:00
Proddy
b4519b40eb minor updates 2023-06-03 08:06:36 +02:00
Proddy
a0bc5fed35 update packages 2023-06-02 14:37:31 +02:00
Proddy
2a7bd7e963 remove DEBUG 2023-06-02 14:37:25 +02:00
Proddy
26b873da9e Merge pull request #1184 from emsesp/dev-fix
fix #1182
2023-05-31 23:18:48 +04:00
MichaelDvP
82a8f0481e fix #1182 2023-05-31 19:13:53 +02:00
Proddy
53c8d9372e Merge pull request #1180 from pswid/dev 2023-05-30 23:04:58 +04:00
Proddy
d314e1d050 Merge pull request #1181 from emsesp/dev-fix 2023-05-30 23:03:13 +04:00
MichaelDvP
e4a0799163 3 retrys on rejected tx, fixes #1179
please delete branch after merge. My dev branch contains the mqtt lib, so i edit on github directly.
2023-05-30 09:41:26 +02:00
pswid
685f987a8e automatic (some) columns expansion to avoid truncation 2023-05-29 12:54:58 +02:00
pswid
b57fff13eb Polish translation fixes 2023-05-29 12:43:55 +02:00
Proddy
4a3201f194 Merge pull request #1177 from proddy/dev
formatting
2023-05-27 09:43:41 +02:00
Proddy
8b948bc521 don't build web on pio clean target 2023-05-27 09:42:50 +02:00
Proddy
91f0da84d2 clang auto formatting 2023-05-27 09:42:33 +02:00
Proddy
551b2d900e package update 2023-05-27 09:42:21 +02:00
Proddy
06e3c0a41f Merge pull request #1176 from MichaelDvP/dev
AM20, HIU, Ventilation and other
2023-05-27 08:39:48 +02:00
MichaelDvP
ac3d16b2b4 version dev.12, update changelog 2023-05-26 10:48:30 +02:00
MichaelDvP
c8c4a3d450 build s3 bin 2023-05-26 10:26:25 +02:00
MichaelDvP
6aaccf4f90 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-05-26 09:46:16 +02:00
Proddy
2d70f637c9 Merge pull request #1175 from proddy/dev
Table sizes
2023-05-25 20:20:52 +02:00
Proddy
cf042271c3 Merge branch 'emsesp:dev' into dev 2023-05-25 20:20:26 +02:00
proddy
7330ca20f8 condensed table for entity data 2023-05-25 20:16:19 +02:00
MichaelDvP
b5ccf79f70 ventilation temperatures div10 2023-05-25 12:27:58 +02:00
MichaelDvP
9a2303ab73 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-05-25 10:17:41 +02:00
MichaelDvP
07102e0279 add ventilation air temperatures 2023-05-25 09:46:34 +02:00
Proddy
0c1042abc9 Merge pull request #1162 from proddy/dev
web render update - #1116
2023-05-24 20:42:36 +02:00
proddy
2571f5e5e6 package update 2023-05-24 20:41:01 +02:00
Proddy
c9a968c1a5 package update 2023-05-23 22:51:35 +02:00
Proddy
b74e56974e package update 2023-05-14 10:57:03 +02:00
Proddy
fabaa230de shorten greenstar 2023-05-14 10:56:58 +02:00
Proddy
c224abfc61 layout improvements 2023-05-13 16:55:49 +02:00
Proddy
26f5c9debf improvements to #1169 2023-05-13 10:51:18 +02:00
Proddy
ae9a86e796 remove comments 2023-05-13 10:51:06 +02:00
Proddy
c57a5c04d6 pacakge update 2023-05-12 08:26:08 +02:00
Proddy
d1df21cb8e add refresh to device data 2023-05-12 08:25:45 +02:00
Proddy
ff59276387 table formatting 2023-05-11 21:51:15 +02:00
Proddy
0e0ec7a7c7 improve layout 2023-05-11 21:37:24 +02:00
Proddy
3ecaeffec0 improve mobile layout 2023-05-11 21:26:41 +02:00
Proddy
4f8d3d27ba updates to data view 2023-05-11 18:19:47 +02:00
Proddy
6575e1d790 escape key closes data window 2023-05-11 00:23:35 +02:00
Proddy
b255b65dc4 experiment with a pop up device data table 2023-05-11 00:16:03 +02:00
Proddy
b1b15eef4c package update 2023-05-11 00:15:44 +02:00
MichaelDvP
2f5e5535c8 connect wifi or eth, only one 2023-05-10 18:48:36 +02:00
MichaelDvP
5abe9530d7 update packages 2023-05-10 18:48:00 +02:00
MichaelDvP
a5113eb90d add HIU 2023-05-10 18:47:39 +02:00
MichaelDvP
e6f839b554 Merge branch 'dev11' into dev 2023-05-10 18:47:07 +02:00
MichaelDvP
b2ad600de2 add ventilation device class 2023-05-10 16:55:03 +02:00
Proddy
ea71b43f78 package update 2023-05-08 17:59:49 +02:00
Proddy
d939795b8c fix pio for 6.1.7 2023-05-08 17:59:44 +02:00
Proddy
db9b9992d6 make menu pane less wide 2023-05-07 17:49:58 +02:00
Proddy
c8fd8c4928 replace msgpack with msgpackr - https://github.com/emsesp/EMS-ESP32/issues/1112 2023-05-07 17:34:13 +02:00
Proddy
a5fae64db6 fix typo 2023-05-07 17:28:10 +02:00
Proddy
5767d83c85 add notes about fonts 2023-05-07 14:26:34 +02:00
Proddy
7910893529 rename reset 2023-05-07 14:26:23 +02:00
proddy
3c003657b9 move device types to types.ts 2023-05-07 09:47:13 +02:00
proddy
348ffcd077 remove obsolete import 2023-05-07 09:46:52 +02:00
proddy
09ea35e340 add comment 2023-05-06 17:11:57 +02:00
proddy
fcac70a2ca update test data - Need fresh test data #1168 2023-05-06 17:11:48 +02:00
proddy
b5b890beaa package update 2023-05-06 17:11:26 +02:00
Proddy
ca964c13a7 fix row unselect 2023-05-05 20:37:48 +02:00
Proddy
979503256a package update 2023-05-05 20:25:59 +02:00
MichaelDvP
c9ab6b23ea fix #600, read telegram 486 2023-05-05 09:32:57 +02:00
Proddy
e84a3bc99a improve dv validation, add back ugly step 2023-05-03 08:54:57 +02:00
Proddy
310bb53985 package update 2023-05-03 08:54:36 +02:00
Proddy
5b87e74be8 update comment 2023-05-03 08:54:27 +02:00
Proddy
8aa7cd166b experiment showing only 1 device 2023-05-01 22:13:53 +02:00
Proddy
72f530b969 export setOrigData needed for systemlog 2023-05-01 22:13:39 +02:00
Proddy
b027ce0d91 remember old settings 2023-05-01 22:13:17 +02:00
Proddy
ff5247eaf5 update eslint 2023-05-01 22:13:00 +02:00
proddy
148e35ea53 improve device value helper text 2023-05-01 13:39:12 +02:00
Proddy
8a01a1e471 merge changes from Michael for #600 2023-04-30 20:35:29 +02:00
Proddy
c34208c3df fix logo on mobile devices 2023-04-30 20:25:04 +02:00
Proddy
bf5c11156a reduce margins so data fills plane 2023-04-30 20:24:50 +02:00
Proddy
6e3b36c070 update for 3.6.0-dev-11 2023-04-30 16:36:50 +02:00
Proddy
dc4bd64aff fixes PlatformIO 6.2.0 breaks compilation #1166 (thanks Michael) 2023-04-30 16:22:51 +02:00
proddy
0d9cd64619 rename upload finished to successful 2023-04-30 15:51:15 +02:00
proddy
cc10c494c6 version release text changes 2023-04-30 15:47:59 +02:00
Proddy
3ef3f561b9 text changes 2023-04-30 10:41:23 +02:00
Proddy
2d9627373c ignore internationl number settings when changing value 2023-04-30 10:41:01 +02:00
proddy
d618d09bdf min, max and step are sent as Numbers to the webUI 2023-04-30 09:57:25 +02:00
proddy
8a02f2a27a add check for min/max when sending device values 2023-04-30 09:53:10 +02:00
proddy
ceb63fa09f rename lint 2023-04-30 09:52:47 +02:00
proddy
a256d2573c remove unused lib 2023-04-30 09:52:35 +02:00
Proddy
5fe9049537 but device data in scrollable body 2023-04-29 16:26:20 +02:00
Proddy
6f681aa451 remove useWindowSize 2023-04-29 16:26:07 +02:00
Proddy
63d105437f comment change 2023-04-29 16:25:55 +02:00
Proddy
2254bf9c16 fix eslint warnings 2023-04-29 15:35:54 +02:00
Proddy
90a719561b remove comment 2023-04-29 15:35:33 +02:00
proddy
d06dc3e2cf fic dialog deviceentities 2023-04-29 14:34:56 +02:00
proddy
ff058b06a1 changed comment 2023-04-29 14:34:48 +02:00
proddy
26b0c67d13 update packages, but not router as it breaks 2023-04-29 14:34:34 +02:00
proddy
ab24695371 use blocker from main lib 2023-04-29 14:34:19 +02:00
Proddy
1861365124 removed SAVE 2023-04-28 21:03:29 +02:00
Proddy
321558c583 minor optimizations 2023-04-28 15:46:45 +02:00
Proddy
dd25900af4 make icon bigger 2023-04-28 15:46:37 +02:00
Proddy
28252b987b added missing analog_enabled 2023-04-28 15:46:24 +02:00
Proddy
b823366a82 fixed changing log settings - https://github.com/emsesp/EMS-ESP32/pull/1162#issuecomment-1525877550 2023-04-28 15:46:07 +02:00
MichaelDvP
90ce8bc8ce HP inputs #600, custom entity bool display 2023-04-28 14:36:35 +02:00
Proddy
1362976508 disable changing gpio 2023-04-28 14:13:09 +02:00
Proddy
cfe8c410ae Optimize WebUI rendering when using Dialog Boxes #1116 2023-04-28 12:46:59 +02:00
MichaelDvP
5f87718deb heatpump inputs, fix #600 2023-04-27 09:12:53 +02:00
MichaelDvP
f15fb9a5d1 custom entities: bool write, dashboard show and count 2023-04-27 09:07:38 +02:00
MichaelDvP
57cc39c087 Add Worcester Comfort RF Thermostat emsesp#1163 2023-04-25 18:17:32 +02:00
Proddy
b9402d3a01 remove unused libs 2023-04-24 21:56:40 +02:00
Proddy
b59c76df3b replace void with await 2023-04-24 21:39:30 +02:00
Proddy
7d526196a0 don't show uptime if disconnected 2023-04-24 21:39:16 +02:00
Proddy
f1b3cb9646 added test for bus disconnect 2023-04-24 21:38:52 +02:00
Proddy
67de1c6a47 add one more line to box so it fits 'patch' 2023-04-24 21:38:35 +02:00
Proddy
41b2a67f09 remove hidden spaces 2023-04-24 21:38:21 +02:00
Proddy
f2636d42a4 updated packages 2023-04-24 21:38:03 +02:00
Proddy
0c0ef80025 rename 'Tx issues - check Tx Mode' 2023-04-24 21:37:47 +02:00
Proddy
bcd0c5ac52 only show Update when changes made - https://github.com/emsesp/EMS-ESP32/pull/1162 2023-04-24 17:42:44 +02:00
Proddy
005485188f updates to https://github.com/emsesp/EMS-ESP32/pull/1162 2023-04-24 16:50:28 +02:00
Proddy
9553161b07 remove force from check_active() 2023-04-24 16:50:05 +02:00
Proddy
71e7887da3 replace MUI Slider, saves 5KB 2023-04-23 11:02:10 +02:00
Proddy
300fe721a1 tidy up files 2023-04-23 10:14:35 +02:00
Proddy
047eae2d40 package update 2023-04-23 09:45:12 +02:00
Proddy
c3e5e8d6d1 Merge branch 'dev' into dev 2023-04-23 01:05:36 +02:00
Proddy
466e9ec6fe rename endpoint to entities to be consistent 2023-04-22 21:20:00 +02:00
Proddy
74c88caa19 add empty entity test 2023-04-22 21:19:48 +02:00
Proddy
71d086a8db device_id and type_id as numbers 2023-04-22 21:04:54 +02:00
Proddy
728e15772f bump version 2023-04-22 21:04:37 +02:00
Proddy
e1ffd8860d optimize Settings Customization for rendering 2023-04-22 21:02:11 +02:00
Proddy
4b9bddd565 add comment 2023-04-22 21:01:39 +02:00
Proddy
f53921d068 device entity min/max as numbers 2023-04-22 21:01:19 +02:00
Proddy
445618d232 add min/max for entity customization 2023-04-22 21:01:04 +02:00
Proddy
b035e27bc8 device entity min/max sent as numbers 2023-04-22 21:00:43 +02:00
Proddy
cecbb25857 device_id and type_id sent as numbers 2023-04-22 21:00:29 +02:00
Proddy
c2823a5ed6 add SHOWING and SEARCH 2023-04-22 21:00:12 +02:00
MichaelDvP
3dba97239d AM200 with device-id 08 2023-04-22 16:49:03 +02:00
Proddy
209afc87bb fix lint warnings 2023-04-22 10:05:13 +02:00
Proddy
19e8e4a7a1 initial lint cleanup 2023-04-22 09:47:29 +02:00
Proddy
d8ff088231 formatting 2023-04-22 09:47:03 +02:00
Proddy
6f14fcb6e8 id no longer needed 2023-04-22 09:46:41 +02:00
Proddy
56e95d1d85 updated for custom entities 2023-04-22 09:46:11 +02:00
Proddy
e12083e3ba added more eslint rules 2023-04-22 09:45:54 +02:00
Proddy
fa263918ba updated packages 2023-04-22 09:45:37 +02:00
Proddy
e81b1b9277 rename entities_saved to updated 2023-04-22 09:45:12 +02:00
Proddy
84635ac889 autoformat 2023-04-22 09:44:39 +02:00
Proddy
f80764d72b refactor diallogs 2023-04-22 09:44:24 +02:00
Proddy
04dd9eef09 Polish translation update #1156 2023-04-22 08:46:13 +02:00
Proddy
6bd744f12e refactor dialog to prevent multiple parent renders 2023-04-18 22:04:00 +02:00
Proddy
6f155fab0b Merge pull request #1159 from MichaelDvP/dev
add writeable setting to custom entities
2023-04-15 18:32:50 +02:00
MichaelDvP
a54f3f7085 add writeable checkbox to custom entities 2023-04-15 10:45:41 +02:00
MichaelDvP
d86153a08e add custom entity with empty strings 2023-04-14 14:59:57 +02:00
Proddy
8eb7793cd0 update libs 2023-04-11 18:30:45 +02:00
Proddy
79bff902e1 Merge pull request #1154 from proddy/dev
standalone compile issues
2023-04-06 21:20:42 +02:00
proddy
825e33c3ea standalone compile issues 2023-04-06 21:19:24 +02:00
Proddy
0c8a7d51a8 Merge pull request #1151 from MichaelDvP/dev
Custom telegram handler #1079
2023-04-06 21:08:28 +02:00
Proddy
05e1bbf86b Merge branch 'dev' into dev 2023-04-06 21:08:18 +02:00
Proddy
004ec92d68 Merge pull request #1153 from proddy/dev
minor updates, can't remember what
2023-04-06 20:56:53 +02:00
proddy
f00502863f update packages 2023-04-06 20:55:18 +02:00
proddy
fe8aa8f727 don't use yarn pnp 2023-04-04 11:27:02 +02:00
Proddy
24eccf1e04 Merge branch 'emsesp:dev' into dev 2023-04-02 16:14:01 +02:00
proddy
5ef494b702 tsx config 2023-04-02 16:08:42 +02:00
Proddy
1673acd537 Merge pull request #1149 from pswid/dev
fixed PL and NO translation of "haclimate"
2023-04-02 10:57:48 +02:00
Proddy
d993b356f9 Merge pull request #1150 from minusdreidb/dev
Fix #1147 - Exhaust temperature always zero on GB125/MC110/RC310
2023-04-02 10:43:35 +02:00
marcel
e2fec03a21 Use exhaust temperature from 0xe4, remove from 0xe5 until verified, closes #1147. 2023-04-01 19:15:54 +02:00
MichaelDvP
5e2d97c0b9 Typo, fix string-compare standalone 2023-03-31 17:35:31 +02:00
MichaelDvP
594e79be5d update changelog, version dev.9 2023-03-31 16:52:23 +02:00
MichaelDvP
fa50846a05 add own entities read from ems-bus with free factor 2023-03-31 16:51:28 +02:00
MichaelDvP
36d5df65b8 env for asymetric partitions (loader) 2023-03-31 16:49:30 +02:00
MichaelDvP
486b365f9b update packages 2023-03-31 16:48:08 +02:00
marcel
5c59a20714 Accept exhaustTemp_ update from telegram 0xE5 if value is unequal zero. 2023-03-27 21:57:31 +02:00
pswid
1c10d8015c fixed PL and NO translation of "haclimate" 2023-03-27 09:55:30 +02:00
Proddy
d2d29afcbe update es build 2023-03-26 22:56:43 +02:00
marcel
982a43b8d4 Fix Exhaust Temperature for Logano plus GB125 with Logamatic MC110.
Exhaust Temperature was always zero prior to fix. On the setup

- Logano plus GB125 with Logamatic MM110 (SW-Version 02.10)
- Logamatic RC310 (SW-Version 74.03)
- MM100 (SW-Version 24.05)

the exhaust temperature ist found in telegram type 0xe4 at offset 31.
The original location in telegram 0xe5, offset 6 is always zero.
2023-03-26 17:49:01 +02:00
Proddy
17b108597e Merge pull request #1145 from MichaelDvP/dev
revert another wrong translation
2023-03-25 11:12:33 +01:00
MichaelDvP
28e42b7920 revert another wrong translation 2023-03-25 08:25:04 +01:00
Proddy
904403f8fa Merge pull request #1142 from MichaelDvP/dev
fixes
2023-03-24 20:32:16 +01:00
MichaelDvP
84e8eaf33c Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-03-24 14:17:52 +01:00
MichaelDvP
959e09f6c1 add missing german translation, add back //TODO translate 2023-03-24 13:41:40 +01:00
MichaelDvP
c8c4b36ebd Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-03-24 13:38:59 +01:00
Proddy
ddad1bbe09 Merge pull request #1141 from proddy/dev
minor fixes
2023-03-24 13:36:26 +01:00
Proddy
a2fc137ebe bump version with new NO translations 2023-03-24 13:35:11 +01:00
Proddy
936d887394 fix lint error 2023-03-24 13:34:47 +01:00
Proddy
a396d0335f formatting 2023-03-24 13:32:09 +01:00
Proddy
d575f3b3c2 package update 2023-03-24 13:32:03 +01:00
Proddy
0674426d29 Merge pull request #1139 from proddy/dev
use number as table id's - #1126
2023-03-24 12:14:17 +01:00
Proddy
80ec86361a Merge pull request #1138 from Vikingn/dev
Norwegian translations added again
2023-03-24 12:13:56 +01:00
Vikingn
1ebd38bf03 Norwegian Index.ts translated 2023-03-23 22:09:03 +01:00
Proddy
274855a19e Merge branch 'emsesp:dev' into dev 2023-03-23 20:40:15 +01:00
Proddy
d26d2ae556 Merge pull request #1137 from pswid/dev
improve view of settings pages (app and mqtt)
2023-03-23 20:37:06 +01:00
proddy
0a7e1f629e use number as table id's - #1126 2023-03-23 20:29:01 +01:00
MichaelDvP
a84e9e0923 update packages 2023-03-22 18:09:55 +01:00
MichaelDvP
aea2277e26 fix up/download scheduler files 2023-03-22 17:33:34 +01:00
MichaelDvP
a5d2beb3e7 missing translations 2023-03-22 17:31:55 +01:00
Vikingn
729832ae76 Norwegian fixed line 271-275 2023-03-22 17:22:53 +01:00
Vikingn
21f746d1fa Norwegian translation 2023-03-22 16:23:18 +01:00
Vikingn
d83de8bd15 Norwegian translations added again 2023-03-22 15:36:38 +01:00
pswid
12da8f9b67 improve view of app and mqtt settings pages
The appearance of the configuration pages has been unified. Additionally on very narrow screens (e.g. smartphones) only one parameter per row is displayed (on wider screens up to three per row).
2023-03-22 13:31:53 +01:00
MichaelDvP
70550a4866 enlarge uart stack to 2,5k, 2023-03-22 11:04:04 +01:00
MichaelDvP
789a4e1340 formatting 2023-03-22 11:03:18 +01:00
MichaelDvP
35c999e2fd fix fullname #1136 2023-03-22 07:19:55 +01:00
MichaelDvP
bfdffc14c5 package update 2023-03-20 15:05:12 +01:00
MichaelDvP
e74d3d4cd5 mqtt resend timeout from 10 min to 10 sec 2023-03-20 12:17:27 +01:00
MichaelDvP
514a96c8e4 merge "NO" translations from Vikingn 2023-03-20 09:34:25 +01:00
MichaelDvP
210181feef fix recreate HA config on language change (from discord) 2023-03-20 09:28:43 +01:00
MichaelDvP
942de63b83 fix heartbeat interval, #1131 2023-03-20 09:27:26 +01:00
Proddy
93d68996b4 Merge pull request #1128 from MichaelDvP/dev 2023-03-18 14:17:19 +01:00
MichaelDvP
369c7554f2 fix updating of board profile 2023-03-18 13:53:13 +01:00
MichaelDvP
c92d9123a0 fix enum order of nofrostmode 2023-03-18 10:18:48 +01:00
MichaelDvP
f0be8cf581 add boiler Greenstar HIU, #1127 2023-03-18 10:18:18 +01:00
MichaelDvP
bb85255ef1 add tr characters to css 2023-03-18 10:17:48 +01:00
Proddy
e46c5263d9 Merge pull request #1124 from MichaelDvP/dev
fix device icons in dashboard
2023-03-15 12:36:08 +01:00
MichaelDvP
e7372922d7 fix device icons in dashboard 2023-03-15 10:41:05 +01:00
Proddy
0c9c15f854 Merge pull request #1123 from MichaelDvP/dev
fix translations for EMSESP_EN_ONLY, EMSESP_DE_ONLY
2023-03-15 08:22:09 +01:00
MichaelDvP
216e7e5307 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-03-15 07:16:34 +01:00
MichaelDvP
a92474bf37 fix EMSESSP_EN_ONLY and EMSESP_DE_ONLY 2023-03-15 07:13:23 +01:00
Proddy
432220dc86 Merge pull request #1122 from proddy/dev
update ArduinoJson to 6.21.0
2023-03-14 22:06:17 +01:00
Proddy
a921b4c7b4 3.6.0-dev.7 2023-03-14 22:04:17 +01:00
Proddy
d1348f2be4 formatting 2023-03-14 22:03:28 +01:00
Proddy
f191f1c81d Merge branch 'dev' of https://github.com/proddy/EMS-ESP32 into dev 2023-03-14 21:59:41 +01:00
Proddy
3dfd34b7bf upgrade 6.21.0 2023-03-14 21:59:40 +01:00
Proddy
ada142ff29 add comment 2023-03-14 21:59:31 +01:00
Proddy
ec8b55c1e8 package updates 2023-03-14 21:59:25 +01:00
Proddy
70eb9e6b08 fix no web translations 2023-03-14 21:59:07 +01:00
Proddy
7eef95f57c lint warning fix 2023-03-14 21:58:54 +01:00
Proddy
bac266eadc Merge pull request #1121 from MichaelDvP/dev
some small fixes
2023-03-14 18:17:37 +01:00
MichaelDvP
4ba9f6f330 names for entityFormat and discoveryType 2023-03-14 15:17:16 +01:00
MichaelDvP
0b0ae2fbc2 fix update on S3 SOC 2023-03-14 15:16:16 +01:00
MichaelDvP
50bf7932a0 fix download settings and schedules 2023-03-14 15:05:23 +01:00
MichaelDvP
d3615d2961 fix stack overflow in lwip task 2023-03-14 15:04:48 +01:00
Proddy
2c572f8099 Merge pull request #1119 from pswid/dev
fix: tags in names in HA were not translated
2023-03-14 09:12:15 +01:00
pswid
944aa861f8 make 'eco+ switch_off' enity unique in v.3.4 format
HA ignores characters '+' in uniq_id/obj_id, so to make the entity 'eco+ switch_off' different from 'eco switch_off', it will be renamed to 'eco2 switch_off'.
2023-03-12 21:24:03 +01:00
pswid
62c3c91665 fixed entity id format v.3.4 2023-03-12 20:02:07 +01:00
pswid
ecafda86f1 fix: tags in names in HA were not translated 2023-03-12 19:14:28 +01:00
Proddy
354741a81d Merge pull request #1117 from proddy/dev
add EMSESP_EN_ONLY and EMSESP_DE_ONLY to be safe
2023-03-12 11:15:57 +01:00
proddy
63e6752bd1 add EMSESP_EN_ONLY and EMSESP_DE_ONLY to be safe 2023-03-12 11:14:03 +01:00
Proddy
1e1baa9781 Update sonar_check.yml 2023-03-12 10:59:22 +01:00
Proddy
94678a6726 Merge pull request #1114 from proddy/dev
#1112 - web optimizations
2023-03-12 08:49:45 +01:00
proddy
64b202225a rollback changes 2023-03-12 08:48:56 +01:00
Proddy
0d81dcde10 don't bold row selection 2023-03-11 17:42:02 +01:00
Proddy
d0ccbc2963 typo in table header height 2023-03-11 17:38:08 +01:00
Proddy
8b29c1973d DEMSESP_EN_ONLY 2023-03-11 17:31:33 +01:00
Proddy
c960db5180 added compile flag -DEMSESP_DE_ONLY 2023-03-11 17:23:41 +01:00
Proddy
9233f0dfcc v3.5.1 - merge with patch 2023-03-11 16:06:05 +01:00
Proddy
dc3c6cad05 success toast after upload 2023-03-11 15:41:46 +01:00
Proddy
77798085ce upgraded sonar 2023-03-11 15:32:14 +01:00
Proddy
3c03f4b18f test new sonar 2023-03-11 15:22:43 +01:00
Proddy
955c8b4346 remove minify 2023-03-11 13:45:05 +01:00
Proddy
a3759b1959 add minify and use terser 2023-03-11 11:31:33 +01:00
Proddy
00e87dc3b0 fix table not showing on edit 2023-03-11 11:09:27 +01:00
Proddy
13211249c9 toast styling 2023-03-11 11:09:14 +01:00
Proddy
c677fed916 cleanup 2023-03-11 11:08:56 +01:00
proddy
cc5a28ca14 remove bold font and replace notistack to save flash 2023-03-11 09:22:55 +01:00
Proddy
8cbae88dc3 replace notistack 2023-03-10 20:28:43 +01:00
Proddy
ae890dab37 Merge pull request #1113 from proddy/dev
rollback notistack to 2.0.8 so it fits flash
2023-03-10 17:25:57 +05:30
Proddy
45ec315252 3.6.0-dev.5 2023-03-10 12:54:55 +01:00
Proddy
d27cd392f6 rollback notistack to 2.0.8 so it fits flash 2023-03-10 12:54:29 +01:00
Proddy
751008dcf2 cleanup platforms 2023-03-10 12:54:05 +01:00
Proddy
c16b9968e1 Merge pull request #1108 from proddy/dev
fix standalone
2023-03-08 12:01:24 +05:30
proddy
ab798bee12 package updates, formatting 2023-03-08 11:59:47 +05:30
proddy
30561411e1 fix compile standalone 2023-03-08 11:58:46 +05:30
Proddy
e1e8c1064a Merge pull request #1107 from MichaelDvP/dev
add thermostat names, missing turk locale
2023-03-08 11:49:36 +05:30
Proddy
94ff01bf2c Merge pull request #1106 from pswid/dev
Polish translation update
2023-03-08 11:48:57 +05:30
MichaelDvP
4b1b0e74df add thermostat names, missing turk locale 2023-03-07 17:46:33 +01:00
pswid
78205d77f3 fix typo 2023-03-07 12:38:41 +01:00
pswid
53a0a41a02 Polish translation update 2023-03-07 12:37:30 +01:00
Proddy
8d437c31ce Merge pull request #1105 from MichaelDvP/dev
scheduler and fixes
2023-03-06 19:45:52 +01:00
MichaelDvP
6f396087d2 fix climate publish 2023-03-06 19:12:02 +01:00
MichaelDvP
a6cd5d2ddb Merge branch 'dev' of https://github.com/MichaelDvP/EMS-ESP32 into dev 2023-03-06 18:49:38 +01:00
MichaelDvP
261cfe3911 remove dallas/analo domoticz test 2023-03-06 18:48:57 +01:00
MichaelDvP
bafe23431e fix avty 2023-03-06 18:43:46 +01:00
MichaelDvP
5759012914 fix avty 2023-03-06 18:36:27 +01:00
MichaelDvP
c9dbf282f6 add scheduler api commands/info/value 2023-03-06 16:26:52 +01:00
MichaelDvP
db1a335509 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2023-03-06 16:15:28 +01:00
Proddy
cdb64a4c15 Merge pull request #1103 from proddy/dev
#701 scheduler web dialog updates
2023-03-05 18:28:33 +01:00
proddy
fd7cbdbdc4 green ticky circle thingy 2023-03-05 18:28:01 +01:00
proddy
bcbfc09bf4 yet another package update 2023-03-05 18:27:51 +01:00
MichaelDvP
5f3212afc4 fix domoticz setting (was ignored) 2023-03-05 18:17:57 +01:00
MichaelDvP
af7d072486 Test for domoticz discovery 2023-03-05 17:54:04 +01:00
MichaelDvP
a93fd314ec fix typo and text size 2023-03-05 15:32:45 +01:00
proddy
501f4a856a minor updates 2023-03-05 14:34:35 +01:00
proddy
55af79dfeb name message updated 2023-03-05 14:33:37 +01:00
proddy
607a725395 add type cast so compiles standalone 2023-03-05 14:33:01 +01:00
proddy
ef602ca70b remove TODO 2023-03-05 14:32:27 +01:00
proddy
50d489d3c1 use safer strcmp() instead of comparing pointers 2023-03-05 14:32:20 +01:00
proddy
3c10d750f0 add TODO for translations 2023-03-05 14:31:48 +01:00
proddy
cab93b16b6 id uses counter 2023-03-05 14:31:38 +01:00
proddy
d3d2270f80 typo 2023-03-05 14:31:27 +01:00
proddy
9b3b758be7 update TODOs 2023-03-05 14:31:14 +01:00
MichaelDvP
dfdaf596bc domoticz setting, analog boolformat, dallas discovery 2023-03-05 12:03:47 +01:00
proddy
8ee8998381 Scheduler #701 updates to dialog 2023-03-05 10:08:26 +01:00
proddy
de59434d95 vscode setup 2023-03-05 09:44:50 +01:00
Proddy
e6f9d9b3c8 scheduler dialog changes 2023-03-04 22:16:10 +01:00
Proddy
a41dc71965 test 2023-03-04 19:14:25 +01:00
Proddy
dd200f6d34 Merge pull request #1101 from MichaelDvP/dev
some case and nullptr checks
2023-03-04 18:43:08 +01:00
MichaelDvP
b1c42b8d8f some case and nullptr checks 2023-03-04 17:42:14 +01:00
Proddy
aba870f0ba Merge pull request #1099 from MichaelDvP/dev
mqtt/commands for scheduler
2023-03-04 16:03:34 +01:00
MichaelDvP
0380fe1fff mqtt/commands for scheduler 2023-03-04 14:10:32 +01:00
Proddy
78c4a646d2 Merge pull request #1097 from emsesp/fix_RC35Monitor
fix RC35Monitor active detection
2023-03-04 11:23:41 +01:00
MichaelDvP
44056318fd fix RC35Monitor active detection
editied direct on github, delete branch after merge.
2023-03-04 11:09:14 +01:00
Proddy
f1bb2c75a6 Merge pull request #1095 from proddy/dev
fix routing issue
2023-03-03 18:09:52 +01:00
Proddy
dd0489596e fix routing issue 2023-03-03 12:41:48 +01:00
Proddy
8389e06aae lint optimizations 2023-03-03 12:41:42 +01:00
Proddy
afbb670c78 package update 2023-03-03 12:41:21 +01:00
Proddy
666da8d4e3 Merge pull request #1094 from proddy/dev
edit name from dialog
2023-03-02 17:15:54 +01:00
Proddy
8bb42addc0 Merge branch 'dev' of https://github.com/proddy/EMS-ESP32 into dev 2023-03-02 17:14:44 +01:00
Proddy
0dfd32412e edit name from dialog 2023-03-02 17:13:29 +01:00
Proddy
54eee7ca9f package update 2023-03-02 17:13:04 +01:00
Proddy
ad936c7f6c Merge pull request #1093 from proddy/dev
add name as unique id - #701
2023-03-01 21:50:35 +01:00
Proddy
ee5ec1b7d1 add name as unique id - #701 2023-03-01 21:49:17 +01:00
Proddy
d2c5ae8aa9 Merge pull request #1090 from proddy/dev
remove project router, make everything from root
2023-02-28 18:52:01 +01:00
Proddy
9e3c4134e1 remove project router, make everything from root 2023-02-28 18:48:00 +01:00
Proddy
c8ea1d0c8a Merge pull request #1088 from proddy/dev
show name not number in device dialog info box
2023-02-28 17:52:32 +01:00
Proddy
bba5c5472c fix device type name in pop up info dialog 2023-02-28 17:51:39 +01:00
Proddy
29c3923a52 package update 2023-02-28 17:51:22 +01:00
Proddy
1c20929886 package updates 2023-02-28 09:16:29 +01:00
Proddy
0078a2ef8e formatting 2023-02-28 09:16:24 +01:00
Proddy
ee1c70f608 remove obsolete defaults 2023-02-28 08:47:07 +01:00
Proddy
e29bc4e56a Merge pull request #1085 from MichaelDvP/dev
add TR (some translations still missing) #907
2023-02-28 08:43:12 +01:00
MichaelDvP
e1595daeb9 Merge branch 'tech-upgrade' into dev 2023-02-28 07:17:22 +01:00
Proddy
77e85f02de Merge pull request #1084 from proddy/dev
merge with tech-upgrade
2023-02-27 16:44:50 +01:00
Proddy
557892bbc7 updates for 3.6.0-dev-0 2023-02-27 16:38:56 +01:00
Proddy
f3bfc6f126 Merge remote-tracking branch 'origin/tech-upgrade' into dev 2023-02-27 16:38:38 +01:00
MichaelDvP
5937a0e3b2 Merge branch 'tech-upgrade' of https://github.com/emsesp/EMS-ESP32 into tech-upgrade 2023-02-27 15:22:26 +01:00
MichaelDvP
94749e4615 Add TR language (some still missing) #907 2023-02-27 15:22:17 +01:00
Proddy
ea093844b4 minor update 2023-02-27 14:35:43 +01:00
Proddy
4d496de488 Merge pull request #1082 from MichaelDvP/tech-upgrade
schedule commands timing, retry
2023-02-27 13:53:49 +01:00
Proddy
31bfc5388c Merge branch 'tech-upgrade' into tech-upgrade 2023-02-27 13:49:02 +01:00
MichaelDvP
e9cc86e072 scheduler-command: use const char*, publish response for queries 2023-02-27 12:04:41 +01:00
proddy
9ed32307d3 fix lint warnings 2023-02-27 10:51:41 +01:00
proddy
23cfdb95f2 update package 2023-02-27 10:51:33 +01:00
proddy
71ff695290 update packages 2023-02-27 10:51:00 +01:00
MichaelDvP
f48aeb0917 schedule commands timing, retry 2023-02-27 09:16:41 +01:00
Proddy
84c90dd587 align timing with EMS-ESP 2023-02-26 20:59:03 +01:00
Proddy
4c186606bd hide MAC and IPs 2023-02-26 19:16:53 +01:00
Proddy
2ffa5fbe36 fix system log in standalone 2023-02-26 16:43:56 +01:00
Proddy
471d18f7fa add automatic id so table renders 2023-02-26 15:20:55 +01:00
Proddy
0985cea3d3 add writeback for scheduler 2023-02-26 15:20:28 +01:00
Proddy
f0509ae333 remove ntp message 2023-02-26 15:20:18 +01:00
Proddy
127a20b29c update eslint 2023-02-26 13:45:07 +01:00
Proddy
f179030d6c replace deprecated JS substr() 2023-02-26 13:44:51 +01:00
Proddy
76db7b3d21 back-end implementation 2023-02-26 12:58:49 +01:00
Proddy
00a3d67707 calling backend services 2023-02-26 12:58:37 +01:00
Proddy
a165dd51c4 remove ntp, dow starts on Sun to match tm_weekday in C's time library 2023-02-26 12:58:11 +01:00
Proddy
05eaa3ce54 fix schedule endpoints typo 2023-02-26 12:57:19 +01:00
Proddy
d652bca32d package update 2023-02-26 12:57:03 +01:00
Proddy
0464030544 schedule upload & download feature 2023-02-26 12:56:48 +01:00
Proddy
5927781a6b added stub for webSchedulerService 2023-02-25 22:24:11 +01:00
Proddy
763efaf4af bump 2023-02-25 22:23:50 +01:00
Proddy
d9f4ce7347 added string2minutes() 2023-02-25 22:23:41 +01:00
Proddy
218cab3935 updated 2023-02-25 22:23:22 +01:00
Proddy
81c6351c93 added tester for minutes conversion 2023-02-25 22:23:11 +01:00
Proddy
dce29857d3 added test to convert HH:MM to minutes for scheduler 2023-02-25 22:22:59 +01:00
Proddy
3b9da0ecfd GET and POST now same for scheduler 2023-02-25 22:22:41 +01:00
Proddy
a728a4d779 minor improvements to add dialog 2023-02-25 18:40:31 +01:00
Proddy
9bae82592f add ADD and put in a validator as cmd can't be empty 2023-02-25 18:11:37 +01:00
Proddy
50400459ee add NTP check to scheduler 2023-02-25 16:13:47 +01:00
Proddy
2ede730cfb Scheduler #701 2023-02-25 14:06:40 +01:00
proddy
45609e30ea fix axios include 2023-02-24 12:13:26 +01:00
Proddy
20f817410f default OTA disabled, saves 1.5KB heap 2023-02-23 21:38:44 +01:00
Proddy
e276025d60 change imports suggested by lint 2023-02-23 20:15:29 +01:00
Proddy
a89a7b5430 fix uniq_id for HA sensors 2023-02-23 19:57:35 +01:00
Proddy
044807accb bump version 2023-02-23 19:57:21 +01:00
Proddy
3e9f63a913 cleanup 2023-02-23 19:29:38 +01:00
Proddy
c80470d8f5 cleanup unused variables 2023-02-23 19:28:32 +01:00
Proddy
55d19bbc2d comment 2023-02-23 19:28:11 +01:00
Proddy
a3f4376d8f removed DV_HA_CONFIG_RECREATE 2023-02-23 19:27:59 +01:00
Proddy
2466df0c3d climate renamed to haclimate and given a shortname 2023-02-23 19:27:25 +01:00
Proddy
425cf33f74 added back MAX_MQTT_MESSAGES 2023-02-23 19:26:58 +01:00
Proddy
077a9937fe comment 2023-02-23 19:26:45 +01:00
Proddy
e6d41f6697 added Michael's changes 2023-02-23 19:26:25 +01:00
Proddy
59791cdaa5 added Michael's changes 2023-02-23 19:25:40 +01:00
Proddy
c7a76f90ea updated tests for mqtt 2023-02-23 19:25:28 +01:00
Proddy
605e3c26d7 formatting 2023-02-23 19:25:08 +01:00
Proddy
a59fc3f3e7 copied in Michael's change 2023-02-23 19:24:53 +01:00
Proddy
b5667c17d3 package update 2023-02-23 19:24:37 +01:00
Proddy
bc80aaea63 rename publish functions to queue_* because that is what they do 2023-02-22 20:54:38 +01:00
Proddy
6746c9a2d3 updated comments, remove DV_HA_CONFIG_RECREATE 2023-02-22 19:45:56 +01:00
Proddy
11ad4d8a0f merge with https://github.com/emsesp/EMS-ESP32/pull/1077 2023-02-22 19:01:58 +01:00
Proddy
752f0177cf make it compile standalone 2023-02-22 13:16:20 +01:00
Proddy
2078305ff4 use heap check instead of message queue - https://github.com/emsesp/EMS-ESP32/issues/1067 2023-02-22 13:08:53 +01:00
Proddy
924502113e functions don't need to return std::shared_ptr<const MqttMessage> 2023-02-22 13:08:07 +01:00
Proddy
c95e804733 add brands as flash strings 2023-02-22 13:07:24 +01:00
proddy
6a356d4a45 show how to override platform 2023-02-22 09:38:48 +01:00
proddy
2bfcbd8fb1 added comments 2023-02-22 09:36:59 +01:00
proddy
19bfcea412 EMSESP_TEST uses EN language only 2023-02-22 09:36:51 +01:00
proddy
0d7a013bba update elint 2023-02-22 09:36:34 +01:00
Proddy
931b153290 now I know why michael shortened the names ! 2023-02-21 22:21:30 +01:00
Proddy
9f91fffcab bump version 2023-02-21 21:55:04 +01:00
Proddy
6aea27e30f tidy up EMSESP_DEBUG and EMSESP_TEST 2023-02-21 21:49:21 +01:00
Proddy
134f2671fb compiling with EMSESP_DEBUG only sends to DEBUG log 2023-02-21 21:28:49 +01:00
Proddy
6438d1ee57 compile with EMSESP_TEST to run tests (not DEBUG) 2023-02-21 21:28:19 +01:00
Proddy
a6a1d44204 Merge pull request #1075 from MichaelDvP/tech-upgrade
HA config recreate #1067
2023-02-21 15:37:42 +01:00
MichaelDvP
cf97c7eb59 HA config recreate #1067 2023-02-21 14:00:43 +01:00
Proddy
e8713ff260 go back to espressif 5.2.0 2023-02-21 12:56:30 +01:00
Proddy
993724d945 use en only in debug 2023-02-21 12:53:31 +01:00
Proddy
8c89fdec95 package update 2023-02-21 12:53:31 +01:00
proddy
a49bfec7d9 fix write back on standalone 2023-02-21 09:27:14 +01:00
Proddy
050ecd9290 Merge pull request #1069 from MichaelDvP/tech-upgrade
fix for #1067 and ems-esp restarting
2023-02-20 19:03:43 +01:00
MichaelDvP
395bd604ce fix for #1067 and ems-esp restarting 2023-02-20 18:30:56 +01:00
Proddy
4f91c78b4f Merge pull request #1068 from MichaelDvP/tech-upgrade
fix for #1067
2023-02-20 18:10:20 +01:00
Proddy
20405ae9ab updated comment 2023-02-20 18:09:39 +01:00
Proddy
c18640eab0 brand_to_string to brand_to_char. use const char * where possible 2023-02-20 18:09:32 +01:00
Proddy
854584138b update memory test 2023-02-20 18:08:41 +01:00
MichaelDvP
2d129f6233 recreate instaed of remove/recreate HA config when mqtt reconnecs #1067 2023-02-20 17:30:12 +01:00
MichaelDvP
4aa3e27880 fix appfree display for asymmetric partitions. 2023-02-20 17:27:51 +01:00
Proddy
094387335d minor package updates again 2023-02-20 14:25:03 +01:00
Proddy
ff1cf12e0c Merge pull request #1038 from proddy/dev
3.5.1
2023-02-19 11:29:46 +01:00
Proddy
2f44beccc2 typesafe-i18@5.24.1 2023-02-19 11:29:03 +01:00
Proddy
558e48f671 update gh issue template 2023-02-19 11:28:08 +01:00
Proddy
e60048f5fb v3.5.1 2023-02-19 11:27:58 +01:00
Proddy
6ad1dd1a77 update packages 2023-02-19 11:27:49 +01:00
Proddy
4bfbdf31e4 gh issue template update 2023-02-19 11:23:42 +01:00
Proddy
71c2b4b7e8 package updates 2023-02-19 11:23:31 +01:00
Proddy
292f743b14 Update bug_report.md 2023-02-19 11:18:08 +01:00
Proddy
dd6dfffd57 Delete questions---troubleshooting.md 2023-02-19 10:49:52 +01:00
Proddy
ec705a5307 Delete feature_request.md 2023-02-19 10:49:45 +01:00
Proddy
f45f071710 Create config.yml 2023-02-19 10:49:32 +01:00
Proddy
4630e4f4a0 #911 2023-02-18 13:13:00 +01:00
Proddy
d872ce0ab6 fix apply updates after change #911 2023-02-18 10:49:18 +01:00
Proddy
c04b032abf update packages 2023-02-18 10:48:54 +01:00
proddy
b218bf1d2e hardcode espressif 6.0.1 2023-02-13 22:46:03 +01:00
proddy
18f787703a update packages 2023-02-13 22:45:52 +01:00
proddy
a3719b12e5 fix mqtt enabled check 2023-02-13 22:45:35 +01:00
Proddy
8c91311c1e use node v18 2023-02-12 16:27:46 +01:00
proddy
096336042e minor changes to yarn 2023-02-12 15:35:51 +01:00
Proddy
4ca25fcfc2 experiment with moving from npm to yarn 2023-02-12 14:14:08 +01:00
proddy
12b4bd3795 Workaround for better Domoticz MQTT intergration? #904 2023-02-11 23:26:15 +01:00
proddy
ba96d587ab update 2023-02-11 23:25:30 +01:00
proddy
411f3be3aa fix native compiling on OSX 2023-02-11 20:53:46 +01:00
Proddy
ffacefb792 update copyright year 2023-02-11 19:06:02 +01:00
Proddy
2d1689b79a make syslog work again 2023-02-11 19:05:43 +01:00
Proddy
78e0d30687 add publish command to mqtt code 2023-02-11 18:46:25 +01:00
Proddy
deb0952266 fix syslog 2023-02-11 18:46:10 +01:00
Proddy
9f77cfd0bf formatting 2023-02-11 18:45:41 +01:00
Proddy
767c6da325 move log command to main context 2023-02-11 18:45:20 +01:00
Proddy
f034d908b6 add comment 2023-02-11 18:45:05 +01:00
Proddy
bc391d014e update packages 2023-02-11 18:43:46 +01:00
Proddy
d42cd8ebf9 remove comment 2023-02-11 18:43:38 +01:00
Proddy
ac5635b671 F2 calls 'show values' 2023-02-11 12:23:56 +01:00
Proddy
c76b250c3b fix warning when building native on windows 2023-02-11 12:14:46 +01:00
Proddy
4630287924 fix warning when building native on windows 2023-02-11 12:14:28 +01:00
proddy
d3cae8ec52 update packages 2023-02-11 10:40:15 +01:00
proddy
149fa72566 remove extra brackets 2023-02-11 10:40:09 +01:00
Proddy
a0d13df033 fix react-virtualized-auto-sizer to "1.0.7" 2023-02-10 20:33:24 +01:00
Proddy
c9a3fad9eb updates 2023-02-10 20:30:35 +01:00
Proddy
eeb96199f9 6.20.1 2023-02-10 20:27:45 +01:00
Proddy
765b1a1b39 esp32s3 2023-02-10 20:27:23 +01:00
Proddy
78eef7cb9d cleanup 2023-02-10 20:27:13 +01:00
Proddy
1ad9f8d9cf use descriptive telegrams when watching 2023-02-10 20:27:05 +01:00
Proddy
36734a4768 change version 2023-02-09 22:41:53 +01:00
Proddy
d0f91c5f43 add hosted for online demo 2023-02-09 22:41:47 +01:00
Proddy
1cd980f46a use espressif 6.0.1 and c+17 for testing 2023-02-09 20:38:35 +01:00
Proddy
74162ab4e7 bump to tec-3 2023-02-09 20:38:21 +01:00
Proddy
0ef5579540 update package 2023-02-09 20:38:14 +01:00
Proddy
9501f02aa2 replace React bunder based on webpack with Vite #952 2023-02-09 20:23:31 +01:00
Proddy
ea8850f8bd update packages 2023-02-07 21:30:30 +01:00
Proddy
949842118b add BundleAnalyzerPlugin (optional) 2023-02-07 21:30:22 +01:00
Proddy
a4d31711a0 use lodash-es to save space 2023-02-07 21:29:50 +01:00
Proddy
94f0d040ea smaller icon.png to save space 2023-02-07 21:29:28 +01:00
Proddy
bb6e2b9336 Update CHANGELOG_LATEST.md 2023-02-06 22:34:08 +01:00
Proddy
d0166f7f12 Update CHANGELOG.md 2023-02-06 22:33:16 +01:00
Proddy
3cef6d7a65 merge PR 944 - https://github.com/emsesp/EMS-ESP32/pull/947/files 2023-02-06 22:27:55 +01:00
Proddy
6a1bc00f04 Merge pull request #949 from proddy/dev
3.6.0-dev.0
2023-02-06 22:17:12 +01:00
Proddy
bee4b3970d 3.6.0-dev.0 2023-02-06 22:16:45 +01:00
proddy
2ac3640760 fix package conflicts 2023-02-05 22:12:27 +01:00
proddy
71de48fd32 Warn user in WebUI of unsaved changes #911 2023-02-05 18:53:13 +01:00
Proddy
834eceab16 update packages 2023-02-05 11:13:55 +01:00
Proddy
20de1734d1 formatting 2023-02-05 10:58:48 +01:00
Proddy
63e734b0aa in EMSESP_DEBUG only use EN language to save space 2023-02-05 10:58:32 +01:00
Proddy
cf53c56ac7 add listDir to debug too 2023-02-05 10:58:01 +01:00
Proddy
e82433c530 formatting 2023-02-05 10:57:28 +01:00
Proddy
3a4e6aa852 only publish if MQTT is enabled 2023-02-05 10:57:20 +01:00
Proddy
6c46770330 merge PR 940 - https://github.com/emsesp/EMS-ESP32/pull/940 2023-02-04 14:25:29 +01:00
Proddy
6dc63907f1 merge PR https://github.com/emsesp/EMS-ESP32/pull/939 2023-01-30 20:21:28 +01:00
proddy
e2f149caf9 package update 2023-01-30 19:01:50 +01:00
proddy
da94fc052d fix compile errors on OSX for standalone 2023-01-30 19:01:43 +01:00
Proddy
77a6304fc3 merge PR https://github.com/emsesp/EMS-ESP32/pull/936 2023-01-30 17:14:53 +01:00
Proddy
7c44f22c45 add comment 2023-01-30 17:04:44 +01:00
Proddy
d39d62c2f8 show mqtt disconnect error in log, on first connect only 2023-01-30 17:04:33 +01:00
Proddy
8f68163f90 fix exit not exiting in standalone mode 2023-01-30 17:04:10 +01:00
Proddy
7a2038e124 uptime should be a string 2023-01-29 12:09:54 +01:00
Proddy
e98d84efdb update packages 2023-01-29 12:09:35 +01:00
Proddy
7faffafd8a remove duplicate cmdfunction_p 2023-01-29 12:09:27 +01:00
Proddy
bedfd3ee30 revert back to 5.2.0 2023-01-28 16:20:28 +01:00
Proddy
94473bdeaa merge PL translation update - https://github.com/emsesp/EMS-ESP32/pull/929 2023-01-28 16:20:16 +01:00
Proddy
59af1fd62a use espressif32 6.0.0 2023-01-28 12:19:28 +01:00
Proddy
55ae0bec93 Show MAC address without connecting to network #933 2023-01-28 12:19:13 +01:00
Proddy
64cb509d3b show MAC for ETH always 2023-01-27 18:00:52 +01:00
Proddy
9d67a56f29 ignore web build analysis files 2023-01-27 17:57:36 +01:00
Proddy
b5ee7100f4 remove showing MAC 2023-01-27 17:57:20 +01:00
Proddy
ee1515d787 testing brotlin compression 2023-01-27 17:57:05 +01:00
Proddy
6f0e98b1a1 testing brotlin compression 2023-01-27 17:56:50 +01:00
Proddy
b8e4430a14 testing with brotlin compression 2023-01-27 17:56:36 +01:00
Proddy
65e3187418 package updates 2023-01-27 17:56:19 +01:00
Proddy
ea48cf3722 show MAC address on startup, before connection 2023-01-25 21:37:29 +01:00
Proddy
2c0ad1a4cc minor changes to script 2023-01-25 21:28:07 +01:00
Proddy
7de8fd8b53 update packages 2023-01-25 21:22:18 +01:00
Proddy
7eddf4882c change help string 2023-01-25 21:22:07 +01:00
Proddy
58e95610e8 show MAC address if SSID is empty or ethernet present but not connected 2023-01-25 21:10:06 +01:00
Proddy
0dcc953100 add timing 2023-01-23 23:21:07 +01:00
Proddy
38fffd4932 add debug line to show we're using dummy entity values 2023-01-23 23:20:44 +01:00
Proddy
17c7ae7d7c fix syslog starting 2023-01-23 23:20:27 +01:00
Proddy
15760117ee add comment so we remember the reserve functions 2023-01-23 23:20:16 +01:00
Proddy
1cd5e0781d rename Saved to Updated 2023-01-23 18:52:10 +01:00
Proddy
f64fbd1040 added ping test 2023-01-23 15:59:54 +01:00
Proddy
ceb9246cf2 reset dirtyflags after successful save 2023-01-23 15:59:43 +01:00
proddy
ff14fab492 add missing sv translations 2023-01-22 22:04:23 +01:00
Proddy
df66d0441c merge PR #926 - Additional SV translations#2 2023-01-22 21:20:20 +01:00
proddy
4edfa4d244 HA - use box for numbers 2023-01-22 19:11:27 +01:00
Proddy
bb24da92e4 merge PR #923 - fixes and the tested heatpump/heatsource entities by mvdp 2023-01-22 17:08:17 +01:00
Proddy
7f5e3d3b4c merge PR #901 - added dhw alternating operation 2023-01-22 12:17:39 +01:00
Proddy
66d5d3db8c default back to c+11 2023-01-22 12:16:49 +01:00
proddy
71d22f6768 default to arduino/espressif core 6.0.0 2023-01-19 16:24:43 +01:00
proddy
b68e9dfd4b formatting 2023-01-19 16:14:32 +01:00
Proddy
b4362a4539 Merge pull request #909 from MichaelDvP/tech-upgrade
weblog send queue one by one, no json buffer needed
2023-01-19 16:06:36 +01:00
proddy
4e783d414c merge PR #909 (weblog send queue one by one, no json buffer needed #909) 2023-01-19 16:05:43 +01:00
proddy
9fe6b9d0e5 fix customizations Warn user in WebUI of unsaved changes #911 2023-01-19 15:51:27 +01:00
proddy
665c33d1a9 updated packages 2023-01-19 09:22:37 +01:00
proddy
0ed3bfff4a rename SAVE to APPLY, show number of updates - #911 2023-01-19 09:11:59 +01:00
proddy
9ba0c6df37 add missing items 2023-01-19 09:11:30 +01:00
proddy
312b0d4665 update package 2023-01-19 09:11:12 +01:00
proddy
7acbda4cda un-used, saving for later 2023-01-19 09:10:59 +01:00
proddy
247fc6be8e remove unused colormode 2023-01-19 09:10:40 +01:00
proddy
1407a61f7a remove unused functions 2023-01-19 09:10:03 +01:00
proddy
a3c302176b formatting 2023-01-19 09:09:46 +01:00
proddy
03130d3de2 formatting 2023-01-19 09:09:34 +01:00
proddy
80d42d92db show number of edits on screen 2023-01-19 09:09:10 +01:00
proddy
115a596c1e remove import React 2023-01-19 09:08:33 +01:00
proddy
ab5815a944 remove import react 2023-01-19 09:05:01 +01:00
Proddy
0946254764 adjustments to syslog (still not 100% working) 2023-01-13 18:17:54 +01:00
Proddy
316dfd02e4 fix telnet not starting 2023-01-13 18:17:31 +01:00
Proddy
c35833fab1 moved dummy entity values to consts 2023-01-13 18:17:19 +01:00
MichaelDvP
81cd6ed764 weblog send queue one by one, no json buffer needed 2023-01-13 13:44:16 +01:00
proddy
63ff517b30 show Not Enabled like in MQTT instead of 'disabled' 2023-01-12 23:09:02 +01:00
proddy
30a2a9aa2a updated test runner 2023-01-12 23:08:37 +01:00
Proddy
cfc8570dca formatting 2023-01-12 17:48:12 +01:00
Proddy
7841b44b43 formatting 2023-01-12 17:41:24 +01:00
Proddy
e3f51b34b5 added comments 2023-01-12 17:40:18 +01:00
Proddy
dcedced8fe rename "HA climate config creation" to describe the entity name 2023-01-12 17:40:07 +01:00
Proddy
e437597ef4 typo 2023-01-12 17:39:36 +01:00
Proddy
6d3f768e92 in debug, don't show empty payloads 2023-01-12 17:39:24 +01:00
Proddy
c114581400 formatting 2023-01-12 17:39:14 +01:00
Proddy
fbfd792416 add back TZ to syslog 2023-01-12 17:39:07 +01:00
Proddy
755f1d17d6 added FS libs 2023-01-12 17:38:57 +01:00
Proddy
3e4f7fdc17 error handling in tests 2023-01-12 17:38:50 +01:00
Proddy
754f4e8244 add arguments for test runner 2023-01-12 11:33:51 +01:00
Proddy
a2925011ed update test runner 2023-01-12 11:04:24 +01:00
Proddy
9b7b5ebfa8 exclude most of tests when not in standalone 2023-01-11 23:35:31 +01:00
Proddy
b54777bccb add debug comment 2023-01-11 23:34:52 +01:00
Proddy
17b9b8ec3a script to perform memory test 2023-01-11 23:34:41 +01:00
Proddy
3dc2ab54ac systematically fetch heap mem settings, before allocating buffers so console and web show same results 2023-01-11 23:34:27 +01:00
proddy
97451d2b7a enable API for test 2023-01-11 20:47:36 +01:00
Proddy
c99aaf1e7d add debug 2023-01-10 22:19:20 +01:00
Proddy
7e87dc9de6 add back climate 2023-01-10 22:19:13 +01:00
Proddy
f556fb61ca include shortname in console show values 2023-01-10 22:19:04 +01:00
Proddy
84dca5e794 add back climate config creation 2023-01-10 22:18:34 +01:00
Proddy
60d4997985 optimize tests for ESP32 2023-01-10 22:18:19 +01:00
Proddy
d2900c347a typo/text changes 2023-01-10 22:18:09 +01:00
proddy
3627f884c3 file updates 2023-01-09 22:03:07 +01:00
proddy
e89260b8b0 added 'set mqtt on|off' for easier debugging 2023-01-09 21:49:59 +01:00
proddy
ab6267e122 update packages 2023-01-09 21:49:40 +01:00
Proddy
731ec684f0 loads 1 boiler/160 entities, crash with MQTT (no Discovery) 2023-01-08 21:44:04 +01:00
Proddy
bbf43a0744 updates packages 2023-01-08 21:43:32 +01:00
Proddy
ae51189953 minor changes 2023-01-08 19:51:36 +01:00
Proddy
9b54c1aa04 minor changes 2023-01-08 19:51:30 +01:00
Proddy
da04a0d161 remove logout and t command 2023-01-08 15:16:54 +01:00
Proddy
9351b6c44a remove logout 2023-01-08 15:16:34 +01:00
Proddy
5d6231f51c removed unused strings 2023-01-08 15:16:24 +01:00
Proddy
945697c538 add max alloc 2023-01-08 15:16:11 +01:00
proddy
687c76703b standalone test for memory optimizations (200+ entities) 2023-01-08 09:42:48 +01:00
proddy
e5558f7fa9 remove Serial 2023-01-07 21:28:42 +01:00
proddy
60b424705d replace STANDALONE_DUMP with a parameter set during tests call test_test_set_all_active 2023-01-07 21:28:33 +01:00
proddy
6ed378086b remove Serial 2023-01-07 21:26:23 +01:00
proddy
66d7dde79e rename Customizaton to Customizations 2023-01-07 18:30:22 +01:00
proddy
c7628ac07f NUM_TAGS is used to check of overflow 2023-01-07 14:39:30 +01:00
proddy
8cd08fa765 comment 2023-01-07 14:38:58 +01:00
proddy
1f493b208c replace std::string with const char #869 2023-01-07 14:38:49 +01:00
proddy
3e8d175242 rename num_languages 2023-01-07 14:38:02 +01:00
proddy
360240ee58 fixes to num_entities 2023-01-07 14:37:46 +01:00
proddy
95c5fb7391 merge with MichaelDvP's PR 870 - https://github.com/emsesp/EMS-ESP32/pull/870 2023-01-06 21:51:17 +01:00
proddy
fcd221a9b0 ignore vscode 2023-01-06 19:38:24 +01:00
proddy
397522292c change default_envs 2023-01-06 19:38:17 +01:00
Proddy
fbf799e4c4 use pio native to build standalone 2023-01-06 14:14:03 +01:00
Proddy
ad2dbd6fc5 formatting 2023-01-05 15:14:26 +01:00
Proddy
a51bc276b5 use new SIZES 2023-01-05 15:11:34 +01:00
Proddy
132acaf758 updated console based on latest uuid::console 2023-01-05 15:11:15 +01:00
Proddy
cd807cd035 move shell to main app, check for thread safe 2023-01-05 15:10:22 +01:00
Proddy
df547de5f6 adjusted comment 2023-01-05 15:09:55 +01:00
Proddy
e1ed362d7b optimize for uuid 2023-01-05 15:09:43 +01:00
Proddy
4cbf7e2a2d added max_alloc to heartbeat, use new SIZE names 2023-01-05 15:09:32 +01:00
Proddy
1ec00bceed use new SIZES and optimize for new uuid 2023-01-05 15:09:07 +01:00
Proddy
68ebe55ca4 remove console, remove syslog destination(host) 2023-01-05 15:08:24 +01:00
Proddy
be854ec14c 3.5.0-tec.0 2023-01-05 15:07:32 +01:00
Proddy
ca8647578b current version is 3.5.0-dev 2023-01-05 15:07:22 +01:00
Proddy
c90a1ca9ea add comment on translations 2023-01-05 15:07:10 +01:00
Proddy
45734d52af added word console 2023-01-05 15:06:49 +01:00
Proddy
da0850124c new console library handling multiple streams 2023-01-05 15:06:39 +01:00
Proddy
3eb86fd6c3 add C++17 and optional espressif 5.3.0 libs 2023-01-05 15:06:23 +01:00
Proddy
df2a0f6ec4 remove loop() from testing 2023-01-05 15:06:02 +01:00
Proddy
3b196fc90d updated uuid libs 2023-01-05 15:05:30 +01:00
Proddy
6370296c53 add comment for EMS-ESP testing 2023-01-05 15:05:12 +01:00
Proddy
6ffb0d9676 update package 2023-01-05 15:04:47 +01:00
Proddy
0e85b54cba remove PROGMEM 2023-01-05 15:04:27 +01:00
Proddy
d1b948aa56 typo 2023-01-05 15:04:18 +01:00
Proddy
5e85c4f8ec standalone optimization 2023-01-05 15:04:05 +01:00
594 changed files with 41397 additions and 36944 deletions

View File

@@ -1,35 +1,50 @@
--- ---
name: Bug report name: Problem Report
about: Create a report to help us improve about: Create a Report to help us improve
title: ''
labels: bug
assignees: ''
--- ---
*Before creating a new issue please check that you have:* <!-- Thanks for reporting a problem for this project. READ THIS FIRST:
* *searched the existing [issues](https://github.com/emsesp/EMS-ESP32/issues) (both open and closed)* Please DO NOT OPEN AN ISSUE if your EMS-ESP version is not the latest from the dev branch, please update your device before submitting your issue. Your problem might already be solved. The latest precompiled binaries of EMS-ESP can be downloaded from https://github.com/emsesp/EMS-ESP32/releases/tag/latest
* *searched the [documentation help section](https://emsesp.github.io/docs)*
*Completing this template will help developers and contributors to address the issue. Try to be as specific and extensive as possible. If the information provided is not enough the issue will likely be closed.* Please take a few minutes to complete the requested information below.
*You can now remove this line and the above ones. Text in italic is meant to be replaced by your own words. If any of the sections below are not relevant to the issue (for instance, the screenshots) then you can delete them.* -->
**Bug description** ### PROBLEM DESCRIPTION
*A clear and concise description of what the bug is. Mention which EMS-ESP version you're using.*
**Steps to reproduce** _A clear and concise description of what the problem is._
*Steps to reproduce the behavior.*
**Expected behavior** ### REQUESTED INFORMATION
*A clear and concise description of what you expected to happen.*
**Screenshots** _Make sure your have performed every step and checked the applicable boxes before submitting your issue. Thank you!_
*If applicable, add screenshots to help explain your problem.*
**Device information** - [ ] Searched the problem in [issues](https://github.com/emsesp/EMS-ESP32/issues)
*Copy-paste here the information as it is outputted by the device. You can get this information by from http://ems-esp.local/api/system* - [ ] Searched the problem in [discussions](https://github.com/emsesp/EMS-ESP32/discussions)
- [ ] Searched the problem in the [docs](https://emsesp.github.io/docs/Troubleshooting/)
- [ ] Searched the problem in the [chat](https://discord.gg/3J3GgnzpyT)
- [ ] Provide the output of http://ems-esp.local/api/system :
**Additional context** ```lua
*Add any other context about the problem here.* System information output here:
```
### TO REPRODUCE
_Steps to reproduce the behavior:_
### EXPECTED BEHAVIOUR
_A clear and concise description of what you expected to happen._
### SCREENSHOTS
_If applicable, add screenshots to help explain your problem._
### ADDITIONAL CONTEXT
_Add any other context about the problem here._
**(Please, remember to close the issue when the problem has been addressed)**

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: EMS-ESP Docs
url: https://emsesp.github.io/docs/
about: All the information related to EMS-ESP.
- name: EMS-ESP Discussions and Support
url: https://github.com/emsesp/EMS-ESP32/discussions
about: EMS-ESP usage Questions, Feature Requests and Projects.
- name: EMS-ESP Users Chat
url: https://discord.gg/3J3GgnzpyT
about: Chat for feedback, questions and troubleshooting.

View File

@@ -1,26 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
*Before creating a new feature request please check that you have searched the existing [issues](https://github.com/emsesp/EMS-ESP32/issues) (both open and closed)*
*Completing this template will help developers and contributors evaluating the feature. If the information provided is not enough the issue will likely be closed.*
*You can now remove this line and the above ones. Text in italic is meant to be replaced by your own words. If any of the sections below are not relevant to the request then you can delete them.*
**Is your feature request related to a problem? Please describe.**
*A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]*
**Describe the solution you'd like**
*A clear and concise description of what you want to happen.*
**Describe alternatives you've considered**
*A clear and concise description of any alternative solutions or features you've considered.*
**Additional context**
*Add any other context or screenshots about the feature request here.*

View File

@@ -1,29 +0,0 @@
---
name: Questions & Troubleshooting
about: Anything not a bug or feature request
title: ''
labels: question
assignees: ''
---
*Before creating a new issue please check that you have:*
* *searched the existing [issues](https://github.com/emsesp/EMS-ESP32/issues) (both open and closed)*
* *searched the [documentation help section](https://emsesp.github.io/docs)*
*Completing this template will help developers and contributors help you. Try to be as specific and extensive as possible. If the information provided is not enough the issue will likely be closed.*
*You can now remove this line and the above ones. Text in italic is meant to be replaced by your own words. If any of the sections below are not relevant to the issue (for instance, the screenshots) then you can delete them.*
**Question**
*A clear and concise description of what the problem/doubt is.*
**Screenshots**
*If applicable, add screenshots to help explain your problem.*
**Device information**
*Copy-paste here the information as it is outputted by the device. You can get this information from http://ems-esp.local/api/system*
**Additional context**
*Add any other context about the problem here.*

View File

@@ -1,24 +1,22 @@
name: "pre-release" name: 'pre-release'
on: on:
workflow_dispatch: workflow_dispatch:
push: push:
branches: branches:
- "dev" - 'dev'
jobs: jobs:
pre-release: pre-release:
name: 'Automatic pre-release build'
name: "Automatic pre-release build"
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-python@v4 - uses: actions/setup-python@v4
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: '16' node-version: '18'
- name: Get EMS-ESP source code and version - name: Get EMS-ESP source code and version
id: build_info id: build_info
@@ -34,24 +32,27 @@ jobs:
- name: Build WebUI - name: Build WebUI
run: | run: |
cd interface cd interface
npm ci yarn install
npx typesafe-i18n --no-watch yarn run typesafe-i18n --no-watch
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
npm run build yarn run build
- name: Build firmware - name: Build firmware
run: | run: |
platformio run -e ci platformio run -e ci
- name: Build S3 firmware
run: |
platformio run -e ci_s3
- 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'
with: with:
repo_token: "${{ secrets.GITHUB_TOKEN }}" repo_token: '${{ secrets.GITHUB_TOKEN }}'
title: Development Build v${{steps.build_info.outputs.VERSION}} title: Development Build v${{steps.build_info.outputs.VERSION}}
automatic_release_tag: "latest" automatic_release_tag: 'latest'
prerelease: true prerelease: true
files: | files: |
CHANGELOG_LATEST.md CHANGELOG_LATEST.md
./build/firmware/*.* ./build/firmware/*.*

View File

@@ -7,51 +7,24 @@ on:
types: [opened, synchronize, reopened] types: [opened, synchronize, reopened]
jobs: jobs:
build: build:
name: Build name: Build and analyze
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository_owner == 'emsesp' # if: github.repository_owner == 'emsesp'
# if: github.repository == 'emsesp/EMS-ESP32' # if: github.repository == 'emsesp/EMS-ESP32'
env: env:
# https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/
SONAR_SCANNER_VERSION: 4.7.0.2747
SONAR_SERVER_URL: "https://sonarcloud.io"
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
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: Set up JDK 11 - name: Install sonar-scanner and build-wrapper
uses: actions/setup-java@v1 uses: SonarSource/sonarcloud-github-c-cpp@v2
with:
java-version: 11
- name: Cache SonarCloud packages
uses: actions/cache@v1
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Download and set up sonar-scanner
env:
SONAR_SCANNER_DOWNLOAD_URL: https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${{ env.SONAR_SCANNER_VERSION }}-linux.zip
run: |
mkdir -p $HOME/.sonar
curl -sSLo $HOME/.sonar/sonar-scanner.zip ${{ env.SONAR_SCANNER_DOWNLOAD_URL }}
unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
echo "$HOME/.sonar/sonar-scanner-${{ env.SONAR_SCANNER_VERSION }}-linux/bin" >> $GITHUB_PATH
- name: Download and set up build-wrapper
env:
BUILD_WRAPPER_DOWNLOAD_URL: ${{ env.SONAR_SERVER_URL }}/static/cpp/build-wrapper-linux-x86.zip
run: |
curl -sSLo $HOME/.sonar/build-wrapper-linux-x86.zip ${{ env.BUILD_WRAPPER_DOWNLOAD_URL }}
unzip -o $HOME/.sonar/build-wrapper-linux-x86.zip -d $HOME/.sonar/
echo "$HOME/.sonar/build-wrapper-linux-x86" >> $GITHUB_PATH
- name: Run build-wrapper - name: Run build-wrapper
run: | run: |
make clean build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make clean all
- name: Run sonar-scanner - name: Run sonar-scanner
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: | run: |
sonar-scanner sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"

View File

@@ -1,23 +1,21 @@
name: "tagged-release" name: 'tagged-release'
on: on:
push: push:
tags: tags:
- "v*" - 'v*'
jobs: jobs:
tagged-release: tagged-release:
name: 'Tagged Release'
name: "Tagged Release"
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2 - uses: actions/setup-python@v4
- uses: actions/setup-python@v2 - uses: actions/setup-node@v3
- uses: actions/setup-node@v2
with: with:
node-version: '16' node-version: '18'
- name: Install PlatformIO - name: Install PlatformIO
run: | run: |
@@ -29,19 +27,23 @@ jobs:
- name: Build WebUI - name: Build WebUI
run: | run: |
cd interface cd interface
npm ci yarn install
npx typesafe-i18n --no-watch yarn run typesafe-i18n --no-watch
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
npm run build yarn run build
- name: Build firmware - name: Build firmware
run: | run: |
platformio run -e ci platformio run -e ci
- name: Build S3 firmware
run: |
platformio run -e ci_s3
- name: Release - name: Release
uses: "marvinpinto/action-automatic-releases@latest" uses: 'marvinpinto/action-automatic-releases@latest'
with: with:
repo_token: "${{ secrets.GITHUB_TOKEN }}" repo_token: '${{ secrets.GITHUB_TOKEN }}'
prerelease: false prerelease: false
files: | files: |
CHANGELOG.md CHANGELOG.md

58
.github/workflows/test_release.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
name: 'test-release'
on:
workflow_dispatch:
push:
branches:
- 'dev2'
jobs:
pre-release:
name: 'Automatic test-release build'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: Get EMS-ESP source code and version
id: build_info
run: |
version=`grep -E '^#define EMSESP_APP_VERSION' ./src/version.h | awk -F'"' '{print $2}'`
echo "VERSION=$version" >> $GITHUB_OUTPUT
- name: Install PlatformIO
run: |
python -m pip install --upgrade pip
pip install -U platformio
- name: Build WebUI
run: |
cd interface
yarn install
yarn run typesafe-i18n --no-watch
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
yarn run build
- name: Build firmware
run: |
platformio run -e ci
- name: Build S3 firmware
run: |
platformio run -e ci_s3
- name: Create a GH Release
id: 'automatic_releases'
uses: 'marvinpinto/action-automatic-releases@latest'
with:
repo_token: '${{ secrets.GITHUB_TOKEN }}'
title: Test Build v${{steps.build_info.outputs.VERSION}}
automatic_release_tag: 'test'
prerelease: true
files: |
CHANGELOG_LATEST.md
./build/firmware/*.*

39
.gitignore vendored
View File

@@ -1,14 +1,13 @@
# vscode # vscode
.vscode .vscode/c_cpp_properties.json
.directory .vscode/extensions.json
workspace.code-workspace .vscode/launch.json
# .vscode/settings.json
# build # c++ compiling
build/
.clang_complete .clang_complete
.gcc-flags.json .gcc-flags.json
cppcheck.out.xml cppcheck.out.xml
debug.log
# platformio # platformio
.pio .pio
@@ -17,18 +16,32 @@ pio_local.ini
# OS specific # OS specific
.DS_Store .DS_Store
*Thumbs.db *Thumbs.db
# project specfic
/scripts/stackdmp.txt
emsesp emsesp
# web specfic
build/
dist/
/data/www /data/www
/lib/framework/WWWData.h /lib/framework/WWWData.h
/interface/build /interface/build
node_modules node_modules
/interface/.eslintcache /interface/.eslintcache
stats.html
*.sln
*.sw?
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
# scripts
test.sh test.sh
scripts/run.sh
scripts/__pycache__ scripts/__pycache__
.temp /scripts/stackdmp.txt
# i18n generated files # i18n generated files
interface/src/i18n/i18n-react.tsx interface/src/i18n/i18n-react.tsx
@@ -42,6 +55,6 @@ interface/src/i18n/i18n-util.async.ts
sonar/ sonar/
build_wrapper_output_directory/ build_wrapper_output_directory/
# other build files # entity dump results
dump_entities.csv # dump_entities.csv
dump_entities.xls* # dump_entities.xls*

View File

@@ -1,6 +1,8 @@
{ {
"singleQuote": true,
"semi": true,
"trailingComma": "none", "trailingComma": "none",
"printWidth": 120 "tabWidth": 2,
"semi": true,
"singleQuote": true,
"printWidth": 120,
"bracketSpacing": true
} }

12
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,12 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

46
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,46 @@
{
"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 Normal file
View File

@@ -0,0 +1,18 @@
{
// 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,12 +5,101 @@ 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.5.0] # [3.6.1] September 9 2023
## **IMPORTANT! BREAKING CHANGES**
- `shower_data` MQTT topic shows duration is seconds (was previously a full english sentence)
## Added
- show WiFi rssi in Network Status Page, show quality as color
## 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
- mqtt free mem check set to 60 kb
- small cosmetic changes to Searching in Customization web page
- updated to espressif32@6.4.0
# [3.6.0] August 13 2023
## **IMPORTANT! BREAKING CHANGES**
There are breaking changes between 3.5.x and earlier versions of 3.6.0. Please read carefully before applying the update.
- The sensors have been renamed. `dallassensor` is now `temperaturesensor` in the MQTT topic and named `ts` in the Customizations file. Likewise `analogs` is now `analogsensor` in MQTT and called `as` in the Customizations file. If you have previous customizations you will need to manually update by downloading, changing the JSON file and uploading. It's also recommended cleaning up any old MQTT topics from your broker using an application like MQTTExplorer.
## Added
- Workaround for better Domoticz MQTT intergration? [#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)
- 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
- Some more HM200 entities [#500](https://github.com/emsesp/EMS-ESP32/issues/500)
- Added Scheduler [#701](https://github.com/emsesp/EMS-ESP32/issues/701)
- Added Custom Entities read/write from EMS bus
- Build S3 binary with github actions
- Greenstar HIU [#1158](https://github.com/emsesp/EMS-ESP32/issues/1158)
- AM200 code 10 [#1161](https://github.com/emsesp/EMS-ESP32/issues/1161)
- Ventilation device (Logavent HRV176) [#1172](https://github.com/emsesp/EMS-ESP32/issues/1172)
- Turn ETH off on wifi connect [#1167](https://github.com/emsesp/EMS-ESP32/issues/1167)
- Support for multiple EMS-ESPs with HA [#1196](https://github.com/emsesp/EMS-ESP32/issues/1196)
- Italian translation [#1199](https://github.com/emsesp/EMS-ESP32/issues/1199)
- Turkish language support [#1076](https://github.com/emsesp/EMS-ESP32/issues/1076)
- Buderus GB182 - HC1 mode change not work bug [#1193](https://github.com/emsesp/EMS-ESP32/issues/1193)
- Minimal flow temperature enhancement [#1192](https://github.com/emsesp/EMS-ESP32/issues/1192)
- Roomtemperature Switching Difference enhancement [#1191](https://github.com/emsesp/EMS-ESP32/issues/1191)
- Dew Point Temperature Difference enhancement [#1190](https://github.com/emsesp/EMS-ESP32/issues/1190)
- Control of heating circuit mode enhancement [#1187](https://github.com/emsesp/EMS-ESP32/issues/1187)
- Warn user in WebUI of unsaved changes enhancement [#911](https://github.com/emsesp/EMS-ESP32/issues/911)
- Create safebuild app to fit into factory partition to give ESP32 more flash memory enhancement [#608](https://github.com/emsesp/EMS-ESP32/issues/608)
- Support ESP32 S2, C3 mini and S3 [#605](https://github.com/emsesp/EMS-ESP32/issues/605)
- Support Buderus AM200 [#1161](https://github.com/emsesp/EMS-ESP32/issues/1161)
- Custom telegram handler [#1155](https://github.com/emsesp/EMS-ESP32/issues/1155)
- Added support for TLS in MQTT (ESP32-S3 only) [#1178](https://github.com/emsesp/EMS-ESP32/issues/1178)
- Boardprofile BBQKees Gateway S3
- Custom entity type RAW [#1212](https://github.com/emsesp/EMS-ESP32/discussions/1212)
- API command response [#1212](https://github.com/emsesp/EMS-ESP32/discussions/1212)
## Fixed
- HA-discovery for analog sensor commands [#1035](https://github.com/emsesp/EMS-ESP32/issues/1035)
- Enum order of RC3x nofrost mode
- Heartbeat interval
- Exhaust temperature always zero on GB125/MC110/RC310 bug [#1147](https://github.com/emsesp/EMS-ESP32/issues/1147)
- thermostat modetype is not changing when mode changes (e.g. to night) bugSomething isn't working [#1098](https://github.com/emsesp/EMS-ESP32/issues/1098)
- NTP: cant apply changed timezone [#1182](https://github.com/emsesp/EMS-ESP32/issues/1182)
- Missing Status of VS1 for Buderus SM200 enhancement [#1034](https://github.com/emsesp/EMS-ESP32/issues/1034)
- Allowed gpios for S3
## Changed
- Optional upgrade to platform-espressif32 6.3.0 (after 5.3.0) [#862](https://github.com/emsesp/EMS-ESP32/issues/862)
- Use byte 3 for detection RC30 active heatingcircuit [#786](https://github.com/emsesp/EMS-ESP32/issues/786)
- Write repeated selflowtemp if tx-queue is empty without verify [#954](https://github.com/emsesp/EMS-ESP32/issues/954)
- HA discovery recreate after disconnect by device [#1067](https://github.com/emsesp/EMS-ESP32/issues/1067)
- File upload: check flash size (overflow) instead of filesize
- Improved HA Discovery so previous configs no longer need to be removed when starting [#1077](https://github.com/emsesp/EMS-ESP32/pull/1077) (thanks @pswid)
- Enlarge UART-Stack to 2,5k
- Retry timeout for Mqtt-QOS1/2 10seconds
- Optimize WebUI rendering when using Dialog Boxes [#1116](https://github.com/emsesp/EMS-ESP32/issues/1116)
- Optimize Web libraries to reduce bundle size (3.6.x) [#1112](https://github.com/emsesp/EMS-ESP32/issues/1112)
- Use [espMqttClient](https://github.com/bertmelis/espMqttClient) with integrated queue [#1178](https://github.com/emsesp/EMS-ESP32/issues/1178)
- Move Sensors from Web dashboard to it's own tab enhancement [#1170](https://github.com/emsesp/EMS-ESP32/issues/1170)
- Optimize WebUI dashboard data [#1169](https://github.com/emsesp/EMS-ESP32/issues/1169)
- Replace React core library with Preact to save on memory footprint
- Response to `system/send` raw reads gives combined data for telegrams with more parts
# [3.5.0] February 6 2023
## **IMPORTANT! BREAKING CHANGES** ## **IMPORTANT! BREAKING CHANGES**
- When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade. - When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade.
- Support for multiple EMS-ESPs [#759] has been added as an optional setting for MQTT. When enabled, which is now the default, all MQTT Discovery Entity IDs will include the MQTT base name and the shortname of the EMS-ESP device entity. For example what was previously `sensor.boiler_actual_boiler_temperature` will now become `sensor.ems_esp_boiler_boiltemp`. If you still want to use the old format and retain the history and script compatibility in Home Assistant then set this back to the old format.
## Added ## Added
@@ -67,19 +156,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- HA duration class for time entities [[#822](https://github.com/emsesp/EMS-ESP32/issues/822) - HA duration class for time entities [[#822](https://github.com/emsesp/EMS-ESP32/issues/822)
- AM200 alternative heatsource as class heatsource [[#857](https://github.com/emsesp/EMS-ESP32/issues/857) - AM200 alternative heatsource as class heatsource [[#857](https://github.com/emsesp/EMS-ESP32/issues/857)
# [3.4.4] # [3.4.2] September 18 2022
## Fixed
- Fix for new installations with filesystem not initializing
# [3.4.3]
## Fixed
- Fix for new installations with filesystem not initializing
# [3.4.2]
## Added ## Added
@@ -115,6 +192,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Changed ## Changed
- Controller data in web-ui only for IVT [#522](https://github.com/emsesp/EMS-ESP32/issues/522)
- Rename hidden `climate` to a more explaining name [#523](https://github.com/emsesp/EMS-ESP32/issues/523)
- Minor changes to the Customizations web page [#527](https://github.com/emsesp/EMS-ESP32/pull/527)
# [3.4.0] May 23 2022 # [3.4.0] May 23 2022
## Added ## Added
@@ -221,7 +302,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added pool data to telegrams 0x494 & 0x495 [#102](https://github.com/emsesp/EMS-ESP32/issues/102) - Added pool data to telegrams 0x494 & 0x495 [#102](https://github.com/emsesp/EMS-ESP32/issues/102)
- Add RC300 second summermode telegram [#108](https://github.com/emsesp/EMS-ESP32/issues/108) - Add RC300 second summermode telegram [#108](https://github.com/emsesp/EMS-ESP32/issues/108)
- Add support for the RC25 thermostat [#106](https://github.com/emsesp/EMS-ESP32/issues/106) - Add support for the RC25 thermostat [#106](https://github.com/emsesp/EMS-ESP32/issues/106)
- Add new command 'entities' for a device, e.g. http://ems-esp/api/boiler/entities to show the shortname, description and HA Entity name (if HA enabled) [#116](https://github.com/emsesp/EMS-ESP32/issues/116) - Add new command 'entities' for a device, e.g. <http://ems-esp/api/boiler/entities> to show the shortname, description and HA Entity name (if HA enabled) [#116](https://github.com/emsesp/EMS-ESP32/issues/116)
- Support for Junkers program and remote (fb10/fb110) temperature - Support for Junkers program and remote (fb10/fb110) temperature
- Home Assistant `state_class` attribute for Wh, kWh, W and KW [#129](https://github.com/emsesp/EMS-ESP32/issues/129) - Home Assistant `state_class` attribute for Wh, kWh, W and KW [#129](https://github.com/emsesp/EMS-ESP32/issues/129)
- Add current room influence for RC300 [#136](https://github.com/emsesp/EMS-ESP32/issues/136) - Add current room influence for RC300 [#136](https://github.com/emsesp/EMS-ESP32/issues/136)
@@ -443,4 +524,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- some names of mqtt-tags like in v2.2.1 - some names of mqtt-tags like in v2.2.1
- new ESP32 partition side to allow for smoother OTA and fallback - new ESP32 partition side to allow for smoother OTA and fallback
- Network Gateway IP is optional (#682)emsesp/EMS-ESP - Network Gateway IP is optional (#682)emsesp/EMS-ESP
- moved to a new GitHub repo https://github.com/emsesp/EMS-ESP32 - moved to a new GitHub repo <https://github.com/emsesp/EMS-ESP32>

View File

@@ -0,0 +1,22 @@
# Changelog
## [3.6.1]
## **IMPORTANT! BREAKING CHANGES**
- `shower_data` MQTT topic shows duration is seconds (was previously a full english sentence)
## Added
- show WiFi rssi in Network Status Page, show quality as color
## 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
- 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

@@ -17,8 +17,8 @@ MAKEFLAGS+="j "
#TARGET := $(notdir $(CURDIR)) #TARGET := $(notdir $(CURDIR))
TARGET := emsesp TARGET := emsesp
BUILD := build BUILD := build
SOURCES := src src/* lib_standalone lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src src/devices lib/ArduinoJson/src lib/PButton lib/semver SOURCES := src src/* lib_standalone lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src src/devices lib/ArduinoJson/src lib/PButton lib/semver lib/espMqttClient/src lib/espMqttClient/src/*
INCLUDES := src lib_standalone lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/uuid-telnet/src lib/uuid-syslog/src lib/semver lib/* src/devices INCLUDES := src lib_standalone lib/espMqttClient/src lib/espMqttClient/src/Transport lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/uuid-telnet/src lib/uuid-syslog/src lib/semver lib/* src/devices
LIBRARIES := LIBRARIES :=
CPPCHECK = cppcheck CPPCHECK = cppcheck
@@ -28,19 +28,21 @@ CHECKFLAGS = -q --force --std=c++11
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Languages Standard # Languages Standard
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# C_STANDARD := -std=c17 C_STANDARD := -std=c17
# CXX_STANDARD := -std=c++17 # CXX_STANDARD := -std=c++17
C_STANDARD := -std=c11 CXX_STANDARD := -std=gnu++11
CXX_STANDARD := -std=c++11
# C_STANDARD := -std=c11
# CXX_STANDARD := -std=c++11
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Defined Symbols # Defined Symbols
#---------------------------------------------------------------------- #----------------------------------------------------------------------
DEFINES += -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE=0 DEFINES += -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE=0
DEFINES += -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_USE_SERIAL 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.5.0b11\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.7.0-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\"
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Sources & Files # Sources & Files
@@ -79,9 +81,7 @@ CPPFLAGS += -g3
CPPFLAGS += -Os CPPFLAGS += -Os
CFLAGS += $(CPPFLAGS) CFLAGS += $(CPPFLAGS)
CFLAGS += -Wall CFLAGS += -Wall -Wextra -Werror -Wswitch-enum -Wno-unused-parameter -Wno-inconsistent-missing-override -Wno-missing-braces -Wno-unused-lambda-capture
CFLAGS += -Wextra
CFLAGS += -Wno-unused-parameter
CXXFLAGS += $(CFLAGS) -MMD CXXFLAGS += $(CFLAGS) -MMD

View File

@@ -21,7 +21,7 @@
- Native support for Home Assistant, Domoticz and openHAB via [MQTT Discovery](https://www.home-assistant.io/docs/mqtt/discovery/) - Native support for Home Assistant, Domoticz and openHAB via [MQTT Discovery](https://www.home-assistant.io/docs/mqtt/discovery/)
- Can run standalone as an independent WiFi Access Point or join an existing WiFi network - Can run standalone as an independent WiFi Access Point or join an existing WiFi network
- Easy first-time configuration via a web Captive Portal - Easy first-time configuration via a web Captive Portal
- Support for more than [110 EMS devices](https://emsesp.github.io/docs/#/Supported-EMS-Devices) (boilers, thermostats, solar modules, mixer modules, heat pumps, gateways, switches, heat sources) - Support for more than [110+ EMS devices](https://emsesp.github.io/docs/All-Devices/) (boilers, thermostats, solar modules, mixer modules, heat pumps, gateways, switches, heat sources)
## **Documentation** ## **Documentation**
@@ -46,7 +46,7 @@ EMS-ESP is a project owned and maintained by [proddy](https://github.com/proddy)
- [esp8266-react](https://github.com/rjwats/esp8266-react) by @rjwats for the framework that provides the core of the Web UI - [esp8266-react](https://github.com/rjwats/esp8266-react) by @rjwats for the framework that provides the core of the Web UI
- [uuid-\*](https://github.com/nomis/mcu-uuid-console) from @nomis. The console, syslog, telnet and logging are based off these open source libraries - [uuid-\*](https://github.com/nomis/mcu-uuid-console) from @nomis. The console, syslog, telnet and logging are based off these open source libraries
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson) for all the JSON - [ArduinoJson](https://github.com/bblanchon/ArduinoJson) for all the JSON
- [AsyncMqttClient](https://github.com/marvinroger/async-mqtt-client) for the MQTT client, with custom modifications from @bertmelis and @proddy - [espMqttClient](https://github.com/bertmelis/espMqttClient) for the MQTT client, with custom modifications from @MichaelDvP and @proddy
- ESPAsyncWebServer and AsyncTCP for the Web server and TCP backends, with custom modifications for performance - ESPAsyncWebServer and AsyncTCP for the Web server and TCP backends, with custom modifications for performance
## **License** ## **License**

View File

@@ -1,5 +0,0 @@
# ![logo](https://github.com/emsesp/EMS-ESP32/blob/main/media/EMS-ESP_logo_dark.png)
# Firmware Installation
Follow the instructions in the [documentation](https://emsesp.github.io/docs) on how to install the firmware binaries in the Assets below.

View File

@@ -1,7 +0,0 @@
# ![logo](https://github.com/emsesp/EMS-ESP32/blob/main/media/EMS-ESP_logo_dark.png)
This is a snapshot of the current "beta" development code and firmware binaries for the ESP32. It has all the latest features and fixes but please be aware that this is still experimental firmware used for testing and thus may contain the odd bug. Use at your own risk and remember to report an issue if you find something unusual.
# Firmware Installation
Follow the instructions in the [documentation](https://emsesp.github.io/docs) on how to install the firmware binaries in the Assets below.

4005
dump_entities.csv Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, , 0x2000,
app0, app, ota_0, , 0x2A0000,
app1, app, ota_1, , 0x140000,
spiffs, data, spiffs, , 64K,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0x2000
4 app0 app ota_0 0x2A0000
5 app1 app ota_1 0x140000
6 spiffs data spiffs 64K

View File

@@ -1,8 +0,0 @@
# This enables lint extensions
EXTEND_ESLINT=true
# This is the name of your project. It appears on the sign-in page and in the menu bar.
REACT_APP_PROJECT_NAME=EMS-ESP
# This is the url path your project will be exposed under.
REACT_APP_PROJECT_PATH=ems-esp

View File

@@ -0,0 +1,2 @@
VITE_ALOVA_TIPS=0
REACT_APP_ALOVA_TIPS=0

View File

@@ -1,3 +0,0 @@
GENERATE_SOURCEMAP=false
REACT_APP_HOSTED=true

View File

@@ -1 +0,0 @@
GENERATE_SOURCEMAP=false

12
interface/.eslintignore Normal file
View File

@@ -0,0 +1,12 @@
node_modules/
build/
dist/
.yarn/
.prettierrc
.eslintrc*
env.d.ts
progmem-generator.js
unpack.ts
vite.config.ts
package.json

108
interface/.eslintrc.json Normal file
View File

@@ -0,0 +1,108 @@
{
"env": {
"browser": true,
"es6": true
},
"extends": [
"eslint:recommended",
"airbnb/hooks",
"airbnb-typescript",
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:prettier/recommended",
"plugin:import/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": "latest",
"sourceType": "module",
"tsconfigRootDir": ".",
"project": ["tsconfig.json"]
},
"plugins": ["react", "@typescript-eslint", "autofix", "react-hooks"],
"settings": {
"import/resolver": {
"typescript": {
"project": "./tsconfig.json"
}
},
"react": {
"version": "18.x"
}
},
"rules": {
"object-shorthand": "error",
"no-console": "warn",
"@typescript-eslint/consistent-type-definitions": ["off", "type"],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-enum-comparison": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/restrict-plus-operands": "off",
"@typescript-eslint/no-unused-expressions": "off",
"@typescript-eslint/no-implied-eval": "off",
"@typescript-eslint/no-misused-promises": "off",
"arrow-body-style": ["error", "as-needed"],
"react-hooks/exhaustive-deps": "warn",
"@typescript-eslint/consistent-type-imports": [
"error",
{
"prefer": "type-imports"
}
],
"import/order": [
"warn",
{
"groups": ["builtin", "external", "parent", "sibling", "index", "object", "type"],
"pathGroups": [
{
"pattern": "@/**/**",
"group": "parent",
"position": "before"
}
],
"alphabetize": { "order": "asc" }
}
],
// "autofix/no-unused-vars": [
// "error",
// {
// "argsIgnorePattern": "^_",
// "ignoreRestSiblings": true,
// "destructuredArrayIgnorePattern": "^_"
// }
// ],
"react/self-closing-comp": [
"error",
{
"component": true,
"html": true
}
],
"@typescript-eslint/ban-types": [
"error",
{
"extendDefaults": true,
"types": {
"{}": false
}
}
],
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
]
}
}

7
interface/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

View File

@@ -0,0 +1,6 @@
node_modules/
build/
dist/
.prettierrc
.yarn/
.typesafe-i18n.json

View File

@@ -1,5 +1,5 @@
{ {
"adapter": "react", "adapter": "react",
"baseLocale": "pl", "baseLocale": "pl",
"$schema": "https://unpkg.com/typesafe-i18n@5.24.0/schema/typesafe-i18n.json" "$schema": "https://unpkg.com/typesafe-i18n@5.26.2/schema/typesafe-i18n.json"
} }

File diff suppressed because one or more lines are too long

873
interface/.yarn/releases/yarn-3.4.1.cjs vendored Executable file

File diff suppressed because one or more lines are too long

20
interface/.yarn/sdks/eslint/bin/eslint.js vendored Executable file
View File

@@ -0,0 +1,20 @@
#!/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`);

20
interface/.yarn/sdks/eslint/lib/api.js vendored Normal file
View File

@@ -0,0 +1,20 @@
#!/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

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

5
interface/.yarn/sdks/integrations.yml vendored Normal file
View File

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

20
interface/.yarn/sdks/prettier/index.js vendored Executable file
View File

@@ -0,0 +1,20 @@
#!/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

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

20
interface/.yarn/sdks/typescript/bin/tsc vendored Executable file
View File

@@ -0,0 +1,20 @@
#!/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`);

20
interface/.yarn/sdks/typescript/bin/tsserver vendored Executable file
View File

@@ -0,0 +1,20 @@
#!/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

@@ -0,0 +1,20 @@
#!/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

@@ -0,0 +1,223 @@
#!/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

@@ -0,0 +1,223 @@
#!/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

@@ -0,0 +1,20 @@
#!/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

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

14
interface/.yarnrc.yml Normal file
View File

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

View File

@@ -1,30 +0,0 @@
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ProgmemGenerator = require('./progmem-generator.js');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = function override(config, env) {
const hosted = process.env.REACT_APP_HOSTED;
if (env === 'production' && !hosted) {
// rename the ouput file, we need it's path to be short, for embedded FS
config.output.filename = 'js/[id].[chunkhash:4].js';
config.output.chunkFilename = 'js/[id].[chunkhash:4].js';
// take out the manifest plugin
config.plugins = config.plugins.filter((plugin) => !(plugin instanceof WebpackManifestPlugin));
// shorten css filenames
const miniCssExtractPlugin = config.plugins.find((plugin) => plugin instanceof MiniCssExtractPlugin);
miniCssExtractPlugin.options.filename = 'css/[id].[contenthash:4].css';
miniCssExtractPlugin.options.chunkFilename = 'css/[id].[contenthash:4].c.css';
// don't emit license file
const terserPlugin = config.optimization.minimizer.find((plugin) => plugin instanceof TerserPlugin);
terserPlugin.options.extractComments = false;
// build progmem data files
config.plugins.push(new ProgmemGenerator({ outputPath: '../lib/framework/WWWData.h', bytesPerLine: 20 }));
}
return config;
};

14
interface/index.html Normal file
View File

@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="/css/roboto.css" />
<link rel="manifest" href="/app/manifest.json" />
<title>EMS-ESP</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>

17983
interface/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,104 +1,78 @@
{ {
"name": "EMS-ESP", "name": "EMS-ESP",
"version": "3.5.0", "version": "3.6.0",
"description": "build EMS-ESP WebUI",
"homepage": "https://emsesp.github.io/docs",
"author": "proddy",
"license": "MIT",
"private": true, "private": true,
"proxy": "http://localhost:3080",
"dependencies": {
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"@msgpack/msgpack": "^2.8.0",
"@mui/icons-material": "^5.11.0",
"@mui/material": "^5.11.7",
"@table-library/react-table-library": "4.0.24",
"@types/lodash": "^4.14.191",
"@types/node": "^18.11.19",
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
"@types/react-router-dom": "^5.3.3",
"async-validator": "^4.2.5",
"axios": "^1.3.2",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21",
"notistack": "^2.0.8",
"react": "^18.2.0",
"react-app-rewired": "^2.2.1",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-icons": "^4.7.1",
"react-router-dom": "^6.8.1",
"react-scripts": "5.0.1",
"sockette": "^2.0.6",
"typesafe-i18n": "^5.24.0",
"typescript": "^4.9.5"
},
"scripts": { "scripts": {
"start": "react-app-rewired start", "dev": "vite",
"build": "react-app-rewired build", "build": "vite build",
"test": "react-app-rewired test", "build-hosted": "vite build --mode hosted",
"eject": "react-scripts eject", "preview": "vite preview",
"preview-standalone": "npm-run-all -p preview typesafe-i18n mock-api",
"mock-api": "node --watch ../mock-api ../mock-api/server.js",
"standalone": "npm-run-all -p dev typesafe-i18n mock-api",
"typesafe-i18n": "typesafe-i18n",
"format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'", "format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'",
"build-hosted": "env-cmd -f .env.hosted npm run build", "lint": "eslint . --cache --fix"
"build-localhost": "PUBLIC_URL=/ react-app-rewired build",
"mock-api": "nodemon --watch ../mock-api ../mock-api/server.js",
"standalone": "npm-run-all -p start typesafe-i18n mock-api",
"lint": "eslint . --ext .ts,.tsx",
"typesafe-i18n": "typesafe-i18n"
}, },
"eslintConfig": { "dependencies": {
"extends": [ "@alova/adapter-xhr": "^1.0.1",
"react-app", "@emotion/react": "^11.11.1",
"react-app/jest" "@emotion/styled": "^11.11.0",
], "@mui/icons-material": "^5.14.8",
"rules": { "@mui/material": "^5.14.8",
"eol-last": 1, "@preact/compat": "^17.1.2",
"react/jsx-closing-bracket-location": 1, "@prefresh/vite": "^2.4.1",
"react/jsx-closing-tag-location": 1, "@table-library/react-table-library": "4.1.7",
"react/jsx-wrap-multilines": 1, "@types/lodash-es": "^4.17.9",
"react/jsx-curly-newline": 1, "@types/node": "^20.6.0",
"no-multiple-empty-lines": [ "@types/react": "^18.2.21",
1, "@types/react-dom": "^18.2.7",
{ "@types/react-router-dom": "^5.3.3",
"max": 1 "alova": "^2.11.1",
} "async-validator": "^4.2.5",
], "history": "^5.3.0",
"no-trailing-spaces": 1, "jwt-decode": "^3.1.2",
"semi": 1, "lodash-es": "^4.17.21",
"no-extra-semi": 1, "mime-types": "^2.1.35",
"react/jsx-max-props-per-line": [ "preact": "^10.17.1",
1, "react": "latest",
{ "react-dom": "latest",
"when": "multiline" "react-dropzone": "^14.2.3",
} "react-icons": "^4.11.0",
], "react-router-dom": "^6.15.0",
"react/jsx-first-prop-new-line": [ "react-toastify": "^9.1.3",
1, "sockette": "^2.0.6",
"multiline" "typesafe-i18n": "^5.26.2",
], "typescript": "^5.2.2"
"@typescript-eslint/no-shadow": 1,
"max-len": [
1,
{
"code": 220
}
],
"arrow-parens": 1
}
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}, },
"devDependencies": { "devDependencies": {
"nodemon": "^2.0.20", "@babel/core": "^7.22.17",
"@preact/preset-vite": "^2.5.0",
"@types/babel__core": "^7",
"@typescript-eslint/eslint-plugin": "^6.6.0",
"@typescript-eslint/parser": "^6.6.0",
"eslint": "^8.49.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-typescript": "^3.6.0",
"eslint-plugin-autofix": "^1.1.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-prettier": "alpha",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"http-proxy-middleware": "^2.0.6" "prettier": "^3.0.3",
} "rollup-plugin-visualizer": "^5.9.2",
"terser": "^5.19.4",
"vite": "^4.4.9",
"vite-plugin-svgr": "^3.2.0",
"vite-tsconfig-paths": "^4.2.0"
},
"packageManager": "yarn@3.4.1"
} }

View File

@@ -1,9 +1,10 @@
const { resolve, relative, sep } = require('path');
const { readdirSync, existsSync, unlinkSync, readFileSync, createWriteStream } = require('fs'); const { readdirSync, existsSync, unlinkSync, readFileSync, createWriteStream } = require('fs');
const { resolve, relative, sep } = require('path');
var zlib = require('zlib'); var zlib = require('zlib');
var mime = require('mime-types'); var mime = require('mime-types');
const ARDUINO_INCLUDES = '#include <Arduino.h>\n\n'; const ARDUINO_INCLUDES = '#include <Arduino.h>\n\n';
const INDENT = ' ';
function getFilesSync(dir, files = []) { function getFilesSync(dir, files = []) {
readdirSync(dir, { withFileTypes: true }).forEach((entry) => { readdirSync(dir, { withFileTypes: true }).forEach((entry) => {
@@ -17,9 +18,9 @@ function getFilesSync(dir, files = []) {
return files; return files;
} }
function coherseToBuffer(input) { // function coherseToBuffer(input) {
return Buffer.isBuffer(input) ? input : Buffer.from(input); // return Buffer.isBuffer(input) ? input : Buffer.from(input);
} // }
function cleanAndOpen(path) { function cleanAndOpen(path) {
if (existsSync(path)) { if (existsSync(path)) {
@@ -28,17 +29,16 @@ function cleanAndOpen(path) {
return createWriteStream(path, { flags: 'w+' }); return createWriteStream(path, { flags: 'w+' });
} }
class ProgmemGenerator { export default function ProgmemGenerator({ outputPath = './WWWData.h', bytesPerLine = 20 }) {
constructor(options = {}) { return {
const { outputPath, bytesPerLine = 20, indent = ' ', includes = ARDUINO_INCLUDES } = options; name: 'ProgmemGenerator',
this.options = { outputPath, bytesPerLine, indent, includes }; writeBundle: () => {
} console.log('Generating ' + outputPath);
const includes = ARDUINO_INCLUDES;
apply(compiler) { const indent = INDENT;
compiler.hooks.emit.tapAsync({ name: 'ProgmemGenerator' }, (compilation, callback) => {
const { outputPath, bytesPerLine, indent, includes } = this.options;
const fileInfo = []; const fileInfo = [];
const writeStream = cleanAndOpen(resolve(compilation.options.context, outputPath)); const writeStream = cleanAndOpen(resolve(outputPath));
try { try {
const writeIncludes = () => { const writeIncludes = () => {
writeStream.write(includes); writeStream.write(includes);
@@ -48,7 +48,8 @@ class ProgmemGenerator {
const variable = 'ESP_REACT_DATA_' + fileInfo.length; const variable = 'ESP_REACT_DATA_' + fileInfo.length;
const mimeType = mime.lookup(relativeFilePath); const mimeType = mime.lookup(relativeFilePath);
var size = 0; var size = 0;
writeStream.write('const uint8_t ' + variable + '[] PROGMEM = {'); writeStream.write('const uint8_t ' + variable + '[] = {');
// const zipBuffer = zlib.brotliCompressSync(buffer, { quality: 1 });
const zipBuffer = zlib.gzipSync(buffer); const zipBuffer = zlib.gzipSync(buffer);
zipBuffer.forEach((b) => { zipBuffer.forEach((b) => {
if (!(size % bytesPerLine)) { if (!(size % bytesPerLine)) {
@@ -72,22 +73,22 @@ class ProgmemGenerator {
const writeFiles = () => { const writeFiles = () => {
// process static files // process static files
const buildPath = compilation.options.output.path; const buildPath = resolve('build');
for (const filePath of getFilesSync(buildPath)) { for (const filePath of getFilesSync(buildPath)) {
const readStream = readFileSync(filePath); const readStream = readFileSync(filePath);
const relativeFilePath = relative(buildPath, filePath); const relativeFilePath = relative(buildPath, filePath);
writeFile(relativeFilePath, readStream); writeFile(relativeFilePath, readStream);
} }
// process assets // process assets
const { assets } = compilation; // const { assets } = compilation;
Object.keys(assets).forEach((relativeFilePath) => { // Object.keys(assets).forEach((relativeFilePath) => {
writeFile(relativeFilePath, coherseToBuffer(assets[relativeFilePath].source())); // writeFile(relativeFilePath, coherseToBuffer(assets[relativeFilePath].source()));
}); // });
}; };
const generateWWWClass = () => { const generateWWWClass = () =>
// eslint-disable-next-line max-len `typedef std::function<void(const String& uri, const String& contentType, const uint8_t * content, size_t len)> RouteRegistrationHandler;
return `typedef std::function<void(const String& uri, const String& contentType, const uint8_t * content, size_t len)> RouteRegistrationHandler;
class WWWData { class WWWData {
${indent}public: ${indent}public:
@@ -98,8 +99,6 @@ ${fileInfo
${indent.repeat(2)}} ${indent.repeat(2)}}
}; };
`; `;
};
const writeWWWClass = () => { const writeWWWClass = () => {
writeStream.write(generateWWWClass()); writeStream.write(generateWWWClass());
}; };
@@ -109,13 +108,11 @@ ${indent.repeat(2)}}
writeWWWClass(); writeWWWClass();
writeStream.on('finish', () => { writeStream.on('finish', () => {
callback(); // callback();
}); });
} finally { } finally {
writeStream.end(); writeStream.end();
} }
});
} }
};
} }
module.exports = ProgmemGenerator;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -1,26 +1,18 @@
/* /*
* Just supporting latin due to size constrains on the esp chip * Uses font-size 400 (normal) only and Latin (plus extra unicode chars) to keep flash memory to a minimum
* * View fonts on https://fonts.google.com/
* The framework only makes use of 400 (regular) + 500 (medium) weight fonts. * Download woff2 using e.g. https://fonts.googleapis.com/css2?family=Lato or https://fonts.googleapis.com/css2?family=Roboto
*
* If using light or strong typography variants you will need to add additional fonts.
*/ */
@font-face { @font-face {
font-family: 'Roboto'; font-family: 'Roboto';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../fonts/re.woff2) format('woff2'); /* src: url(https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2) format('woff2'); */
unicode-range: U+0000-00FF, U+0104-0107, U+0118-0119, U+0131, U+0141-0144, U+0152-0153, U+015A-015B, U+0179-017C, src:
U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, local('Roboto'),
U+FFFD; local('Roboto-Regular'),
} url(../fonts/re.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0104-0107, U+0118-0119, U+011E-011F, U+0130-0131, U+0141-0144, U+0152-0153, U+015A-015B,
@font-face { U+015E-015F, U+0179-017C, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
font-family: 'Roboto'; U+2212, U+2215, U+FEFF, U+FFFD;
font-style: normal;
font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/md.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0104-0107, U+0118-0119, U+0131, U+0141-0144, U+0152-0153, U+015A-015B, U+0179-017C,
U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
U+FFFD;
} }

Binary file not shown.

Binary file not shown.

View File

@@ -1,17 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, user-scalable=0, maximum-scale=1, minimum-scale=1"
/>
<link rel="stylesheet" href="%PUBLIC_URL%/css/roboto.css" />
<link rel="manifest" href="%PUBLIC_URL%/app/manifest.json" />
<title>EMS-ESP</title>
</head>
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<div id="root"></div>
</body>
</html>

View File

@@ -1,61 +1,51 @@
import { FC, createRef, createContext, useContext, useEffect, useState, RefObject } from 'react'; import { useEffect, useState } from 'react';
import { SnackbarProvider } from 'notistack'; import { ToastContainer, Slide } from 'react-toastify';
import { IconButton } from '@mui/material'; import 'react-toastify/dist/ReactToastify.min.css';
import CloseIcon from '@mui/icons-material/Close';
import { FeaturesLoader } from './contexts/features';
import CustomTheme from './CustomTheme';
import AppRouting from './AppRouting';
import { localStorageDetector } from 'typesafe-i18n/detectors'; import { localStorageDetector } from 'typesafe-i18n/detectors';
import TypesafeI18n from './i18n/i18n-react'; import { FeaturesLoader } from './contexts/features';
import { detectLocale } from './i18n/i18n-util'; import type { FC } from 'react';
import { loadLocaleAsync } from './i18n/i18n-util.async'; import AppRouting from 'AppRouting';
import CustomTheme from 'CustomTheme';
import TypesafeI18n from 'i18n/i18n-react';
import { detectLocale } from 'i18n/i18n-util';
import { loadLocaleAsync } from 'i18n/i18n-util.async';
const detectedLocale = detectLocale(localStorageDetector); const detectedLocale = detectLocale(localStorageDetector);
const App: FC = () => { const App: FC = () => {
const notistackRef: RefObject<any> = createRef();
const onClickDismiss = (key: string | number | undefined) => () => {
notistackRef.current.closeSnackbar(key);
};
const ColorModeContext = createContext({ toggleColorMode: () => {} });
const colorMode = useContext(ColorModeContext);
const [wasLoaded, setWasLoaded] = useState(false); const [wasLoaded, setWasLoaded] = useState(false);
useEffect(() => { useEffect(() => {
loadLocaleAsync(detectedLocale).then(() => setWasLoaded(true)); void loadLocaleAsync(detectedLocale).then(() => setWasLoaded(true));
}, []); }, []);
if (!wasLoaded) return null; if (!wasLoaded) return null;
return ( return (
<ColorModeContext.Provider value={colorMode}>
<TypesafeI18n locale={detectedLocale}> <TypesafeI18n locale={detectedLocale}>
<CustomTheme> <CustomTheme>
<SnackbarProvider
maxSnack={3}
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
ref={notistackRef}
action={(key) => (
<IconButton onClick={onClickDismiss(key)} size="small">
<CloseIcon />
</IconButton>
)}
>
<FeaturesLoader> <FeaturesLoader>
<AppRouting /> <AppRouting />
</FeaturesLoader> </FeaturesLoader>
</SnackbarProvider> <ToastContainer
position="bottom-left"
autoClose={3000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick={true}
rtl={false}
pauseOnFocusLoss={false}
draggable={false}
pauseOnHover={false}
transition={Slide}
closeButton={false}
theme="light"
/>
</CustomTheme> </CustomTheme>
</TypesafeI18n> </TypesafeI18n>
</ColorModeContext.Provider>
); );
}; };

View File

@@ -1,29 +1,28 @@
import { FC, useContext, useEffect } from 'react'; import { useContext, useEffect } from 'react';
import { Navigate, Routes, Route, useLocation } from 'react-router-dom';
import { useSnackbar, VariantType } from 'notistack';
import { useI18nContext } from './i18n/i18n-react'; import { Route, Routes, Navigate, useLocation } from 'react-router-dom';
import { Authentication, AuthenticationContext } from './contexts/authentication'; import { toast } from 'react-toastify';
import { FeaturesContext } from './contexts/features'; import type { FC } from 'react';
import { RequireAuthenticated, RequireUnauthenticated } from './components';
import SignIn from './SignIn'; import AuthenticatedRouting from 'AuthenticatedRouting';
import AuthenticatedRouting from './AuthenticatedRouting'; import SignIn from 'SignIn';
import { RequireAuthenticated, RequireUnauthenticated } from 'components';
import { Authentication, AuthenticationContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
interface SecurityRedirectProps { interface SecurityRedirectProps {
message: string; message: string;
variant?: VariantType;
signOut?: boolean; signOut?: boolean;
} }
const RootRedirect: FC<SecurityRedirectProps> = ({ message, variant, signOut }) => { const RootRedirect: FC<SecurityRedirectProps> = ({ message, signOut }) => {
const authenticationContext = useContext(AuthenticationContext); const authenticationContext = useContext(AuthenticationContext);
const { enqueueSnackbar } = useSnackbar();
useEffect(() => { useEffect(() => {
signOut && authenticationContext.signOut(false); signOut && authenticationContext.signOut(false);
enqueueSnackbar(message, { variant }); toast.success(message);
}, [message, variant, signOut, authenticationContext, enqueueSnackbar]); }, [message, signOut, authenticationContext]);
return <Navigate to="/" />; return <Navigate to="/" />;
}; };
@@ -42,7 +41,6 @@ export const RemoveTrailingSlashes = () => {
}; };
const AppRouting: FC = () => { const AppRouting: FC = () => {
const { features } = useContext(FeaturesContext);
const { LL } = useI18nContext(); const { LL } = useI18nContext();
return ( return (
@@ -50,8 +48,7 @@ const AppRouting: FC = () => {
<RemoveTrailingSlashes /> <RemoveTrailingSlashes />
<Routes> <Routes>
<Route path="/unauthorized" element={<RootRedirect message={LL.PLEASE_SIGNIN()} signOut />} /> <Route path="/unauthorized" element={<RootRedirect message={LL.PLEASE_SIGNIN()} signOut />} />
<Route path="/fileUpdated" element={<RootRedirect message={LL.UPLOAD_SUCCESSFUL()} variant="success" />} /> <Route path="/fileUpdated" element={<RootRedirect message={LL.UPLOAD_SUCCESSFUL()} />} />
{features.security && (
<Route <Route
path="/" path="/"
element={ element={
@@ -60,7 +57,6 @@ const AppRouting: FC = () => {
</RequireUnauthenticated> </RequireUnauthenticated>
} }
/> />
)}
<Route <Route
path="/*" path="/*"
element={ element={

View File

@@ -1,52 +1,52 @@
import { FC, useCallback, useContext, useEffect } from 'react'; import { Navigate, Routes, Route } from 'react-router-dom';
import { Navigate, Routes, Route, useNavigate, useLocation } from 'react-router-dom'; import Dashboard from './project/Dashboard';
import { AxiosError } from 'axios'; import Help from './project/Help';
import Settings from './project/Settings';
import type { FC } from 'react';
import { FeaturesContext } from './contexts/features'; import { Layout, RequireAdmin } from 'components';
import * as AuthenticationApi from './api/authentication'; import AccessPoint from 'framework/ap/AccessPoint';
import { PROJECT_PATH } from './api/env'; import Mqtt from 'framework/mqtt/Mqtt';
import { AXIOS } from './api/endpoints'; import NetworkConnection from 'framework/network/NetworkConnection';
import { Layout, RequireAdmin } from './components'; import NetworkTime from 'framework/ntp/NetworkTime';
import Security from 'framework/security/Security';
import System from 'framework/system/System';
import ProjectRouting from './project/ProjectRouting'; const AuthenticatedRouting: FC = () => (
// const location = useLocation();
// const navigate = useNavigate();
// const handleApiResponseError = useCallback(
// (error: AxiosError) => {
// if (error.response && error.response.status === 401) {
// AuthenticationApi.storeLoginRedirect(location);
// navigate('/unauthorized');
// }
// return Promise.reject(error);
// },
// [location, navigate]
// );
// useEffect(() => {
// const axiosHandlerId = AXIOS.interceptors.response.use((response) => response, handleApiResponseError);
// return () => AXIOS.interceptors.response.eject(axiosHandlerId);
// }, [handleApiResponseError]);
import NetworkConnection from './framework/network/NetworkConnection';
import AccessPoint from './framework/ap/AccessPoint';
import NetworkTime from './framework/ntp/NetworkTime';
import Mqtt from './framework/mqtt/Mqtt';
import System from './framework/system/System';
import Security from './framework/security/Security';
const AuthenticatedRouting: FC = () => {
const { features } = useContext(FeaturesContext);
const location = useLocation();
const navigate = useNavigate();
const handleApiResponseError = useCallback(
(error: AxiosError) => {
if (error.response && error.response.status === 401) {
AuthenticationApi.storeLoginRedirect(location);
navigate('/unauthorized');
}
return Promise.reject(error);
},
[location, navigate]
);
useEffect(() => {
const axiosHandlerId = AXIOS.interceptors.response.use((response) => response, handleApiResponseError);
return () => AXIOS.interceptors.response.eject(axiosHandlerId);
}, [handleApiResponseError]);
return (
<Layout> <Layout>
<Routes> <Routes>
{features.project && <Route path={`/${PROJECT_PATH}/*`} element={<ProjectRouting />} />} <Route path="/dashboard/*" element={<Dashboard />} />
<Route
path="/settings/*"
element={
<RequireAdmin>
<Settings />
</RequireAdmin>
}
/>
<Route path="/help/*" element={<Help />} />
<Route path="/network/*" element={<NetworkConnection />} /> <Route path="/network/*" element={<NetworkConnection />} />
<Route path="/ap/*" element={<AccessPoint />} /> <Route path="/ap/*" element={<AccessPoint />} />
{features.ntp && <Route path="/ntp/*" element={<NetworkTime />} />} <Route path="/ntp/*" element={<NetworkTime />} />
{features.mqtt && <Route path="/mqtt/*" element={<Mqtt />} />} <Route path="/mqtt/*" element={<Mqtt />} />
{features.security && (
<Route <Route
path="/security/*" path="/security/*"
element={ element={
@@ -55,12 +55,10 @@ const AuthenticatedRouting: FC = () => {
</RequireAdmin> </RequireAdmin>
} }
/> />
)}
<Route path="/system/*" element={<System />} /> <Route path="/system/*" element={<System />} />
<Route path="/*" element={<Navigate to={AuthenticationApi.getDefaultRoute(features)} />} /> <Route path="/*" element={<Navigate to="/" />} />
</Routes> </Routes>
</Layout> </Layout>
); );
};
export default AuthenticatedRouting; export default AuthenticatedRouting;

View File

@@ -1,10 +1,18 @@
import { FC } from 'react';
import { CssBaseline } from '@mui/material'; import { CssBaseline } from '@mui/material';
import { createTheme, responsiveFontSizes, ThemeProvider } from '@mui/material/styles'; import { createTheme, responsiveFontSizes, ThemeProvider } from '@mui/material/styles';
import { blueGrey, blue } from '@mui/material/colors'; import type { FC } from 'react';
import { RequiredChildrenProps } from './utils'; import type { RequiredChildrenProps } from 'utils';
export const dialogStyle = {
'& .MuiDialog-paper': {
borderRadius: '8px',
borderColor: '#565656',
borderStyle: 'solid',
borderWidth: '1px'
},
backdropFilter: 'blur(1px)'
};
const theme = responsiveFontSizes( const theme = responsiveFontSizes(
createTheme({ createTheme({
@@ -14,10 +22,10 @@ const theme = responsiveFontSizes(
palette: { palette: {
mode: 'dark', mode: 'dark',
secondary: { secondary: {
main: blue[500] main: '#2196f3' // blue[500]
}, },
info: { info: {
main: blueGrey[500] main: '#607d8b' // blueGrey[500]
} }
} }
}) })

View File

@@ -1,34 +1,40 @@
import { FC, useContext, useState } from 'react';
import { ValidateFieldsError } from 'async-validator';
import { useSnackbar } from 'notistack';
import { Box, Fab, Paper, Typography, Button } from '@mui/material';
import ForwardIcon from '@mui/icons-material/Forward'; import ForwardIcon from '@mui/icons-material/Forward';
import { Box, Paper, Typography, MenuItem, TextField, Button } from '@mui/material';
import { useRequest } from 'alova';
import { useContext, useState } from 'react';
import { toast } from 'react-toastify';
import { FeaturesContext } from './contexts/features';
import type { ValidateFieldsError } from 'async-validator';
import * as AuthenticationApi from './api/authentication'; import type { Locales } from 'i18n/i18n-types';
import { PROJECT_NAME } from './api/env'; import type { ChangeEventHandler, FC } from 'react';
import { AuthenticationContext } from './contexts/authentication'; import type { SignInRequest } from 'types';
import * as AuthenticationApi from 'api/authentication';
import { PROJECT_NAME } from 'api/env';
import { extractErrorMessage, onEnterCallback, updateValue } from './utils'; import { ValidatedPasswordField, ValidatedTextField } from 'components';
import { SignInRequest } from './types'; import { AuthenticationContext } from 'contexts/authentication';
import { ValidatedTextField } from './components';
import { SIGN_IN_REQUEST_VALIDATOR, validate } from './validators';
import { I18nContext } from './i18n/i18n-react'; import { ReactComponent as DEflag } from 'i18n/DE.svg';
import type { Locales } from './i18n/i18n-types'; import { ReactComponent as FRflag } from 'i18n/FR.svg';
import { loadLocaleAsync } from './i18n/i18n-util.async'; 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 NLflag } from 'i18n/NL.svg';
import { ReactComponent as DEflag } from './i18n/DE.svg'; import { ReactComponent as NOflag } from 'i18n/NO.svg';
import { ReactComponent as GBflag } from './i18n/GB.svg'; import { ReactComponent as PLflag } from 'i18n/PL.svg';
import { ReactComponent as SVflag } from './i18n/SV.svg'; import { ReactComponent as SVflag } from 'i18n/SV.svg';
import { ReactComponent as PLflag } from './i18n/PL.svg'; import { ReactComponent as TRflag } from 'i18n/TR.svg';
import { ReactComponent as NOflag } from './i18n/NO.svg'; import { I18nContext } from 'i18n/i18n-react';
import { ReactComponent as FRflag } from './i18n/FR.svg'; import { loadLocaleAsync } from 'i18n/i18n-util.async';
import { onEnterCallback, updateValue } from 'utils';
import { SIGN_IN_REQUEST_VALIDATOR, validate } from 'validators';
const SignIn: FC = () => { const SignIn: FC = () => {
const authenticationContext = useContext(AuthenticationContext); const authenticationContext = useContext(AuthenticationContext);
const { enqueueSnackbar } = useSnackbar();
const { LL, setLocale, locale } = useContext(I18nContext);
const { features } = useContext(FeaturesContext);
const [signInRequest, setSignInRequest] = useState<SignInRequest>({ const [signInRequest, setSignInRequest] = useState<SignInRequest>({
username: '', username: '',
@@ -37,8 +43,29 @@ const SignIn: FC = () => {
const [processing, setProcessing] = useState<boolean>(false); const [processing, setProcessing] = useState<boolean>(false);
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>(); const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
const { send: callSignIn, onSuccess } = useRequest((request: SignInRequest) => AuthenticationApi.signIn(request), {
immediate: false
});
onSuccess((response) => {
if (response.data) {
authenticationContext.signIn(response.data.access_token);
}
});
const updateLoginRequestValue = updateValue(setSignInRequest); const updateLoginRequestValue = updateValue(setSignInRequest);
const signIn = async () => {
await callSignIn(signInRequest).catch((event) => {
if (event.message === 'Unauthorized') {
toast.warning(LL.INVALID_LOGIN());
} else {
toast.error(LL.ERROR() + ' ' + event.message);
}
setProcessing(false);
});
};
const validateAndSignIn = async () => { const validateAndSignIn = async () => {
setProcessing(true); setProcessing(true);
SIGN_IN_REQUEST_VALIDATOR.messages({ SIGN_IN_REQUEST_VALIDATOR.messages({
@@ -46,34 +73,17 @@ const SignIn: FC = () => {
}); });
try { try {
await validate(SIGN_IN_REQUEST_VALIDATOR, signInRequest); await validate(SIGN_IN_REQUEST_VALIDATOR, signInRequest);
signIn(); await signIn();
} catch (errors: any) { } catch (errors: any) {
setFieldErrors(errors); setFieldErrors(errors);
setProcessing(false); setProcessing(false);
} }
}; };
const signIn = async () => {
try {
const { data: loginResponse } = await AuthenticationApi.signIn(signInRequest);
authenticationContext.signIn(loginResponse.access_token);
} catch (error) {
if (error.response) {
if (error.response?.status === 401) {
enqueueSnackbar(LL.INVALID_LOGIN(), { variant: 'warning' });
}
} else {
enqueueSnackbar(extractErrorMessage(error, LL.ERROR()), { variant: 'error' });
}
setProcessing(false);
}
};
const submitOnEnter = onEnterCallback(signIn); const submitOnEnter = onEnterCallback(signIn);
const { LL, setLocale, locale } = useContext(I18nContext); const onLocaleSelected: ChangeEventHandler<HTMLInputElement> = async ({ target }) => {
const loc = target.value as Locales;
const selectLocale = async (loc: Locales) => {
localStorage.setItem('lang', loc); localStorage.setItem('lang', loc);
await loadLocaleAsync(loc); await loadLocaleAsync(loc);
setLocale(loc); setLocale(loc);
@@ -93,81 +103,88 @@ const SignIn: FC = () => {
sx={(theme) => ({ sx={(theme) => ({
textAlign: 'center', textAlign: 'center',
padding: theme.spacing(2), padding: theme.spacing(2),
paddingTop: '200px', paddingTop: '172px',
backgroundImage: 'url("/app/icon.png")', backgroundImage: 'url("/app/icon.png")',
backgroundRepeat: 'no-repeat', backgroundRepeat: 'no-repeat',
backgroundPosition: '50% ' + theme.spacing(2), backgroundPosition: '50% ' + theme.spacing(2),
backgroundSize: 'auto 150px',
width: '100%' width: '100%'
})} })}
> >
<Typography variant="h4">{PROJECT_NAME}</Typography> <Typography variant="h4">{PROJECT_NAME}</Typography>
<Box <Typography variant="subtitle2">{features.version}</Typography>
sx={{
'& button, & a, & .MuiCard-root': {
mt: 0.5,
mx: 0.5
}
}}
>
<Button size="small" variant={locale === 'en' ? 'contained' : 'outlined'} onClick={() => selectLocale('en')}>
<GBflag style={{ width: 24 }} />
&nbsp;EN
</Button>
<Button size="small" variant={locale === 'de' ? 'contained' : 'outlined'} onClick={() => selectLocale('de')}>
<DEflag style={{ width: 24 }} />
&nbsp;DE
</Button>
<Button size="small" variant={locale === 'fr' ? 'contained' : 'outlined'} onClick={() => selectLocale('fr')}>
<FRflag style={{ width: 24 }} />
&nbsp;FR
</Button>
<Button size="small" variant={locale === 'nl' ? 'contained' : 'outlined'} onClick={() => selectLocale('nl')}>
<NLflag style={{ width: 24 }} />
&nbsp;NL
</Button>
<Button size="small" variant={locale === 'no' ? 'contained' : 'outlined'} onClick={() => selectLocale('no')}>
<NOflag style={{ width: 24 }} />
&nbsp;NO
</Button>
<Button size="small" variant={locale === 'pl' ? 'contained' : 'outlined'} onClick={() => selectLocale('pl')}>
<PLflag style={{ width: 24 }} />
&nbsp;PL
</Button>
<Button size="small" variant={locale === 'sv' ? 'contained' : 'outlined'} onClick={() => selectLocale('sv')}>
<SVflag style={{ width: 24 }} />
&nbsp;SV
</Button>
</Box>
<TextField name="locale" variant="outlined" value={locale} onChange={onLocaleSelected} size="small" select>
<MenuItem key="de" value="de">
<DEflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;DE
</MenuItem>
<MenuItem key="en" value="en">
<GBflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;EN
</MenuItem>
<MenuItem key="fr" value="fr">
<FRflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;FR
</MenuItem>
<MenuItem key="it" value="it">
<ITflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;IT
</MenuItem>
<MenuItem key="nl" value="nl">
<NLflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;NL
</MenuItem>
<MenuItem key="no" value="no">
<NOflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;NO
</MenuItem>
<MenuItem key="pl" value="pl">
<PLflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;PL
</MenuItem>
<MenuItem key="sv" value="sv">
<SVflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;SV
</MenuItem>
<MenuItem key="tr" value="tr">
<TRflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;TR
</MenuItem>
</TextField>
<Box display="flex" flexDirection="column" alignItems="center">
<ValidatedTextField <ValidatedTextField
fieldErrors={fieldErrors} fieldErrors={fieldErrors}
disabled={processing} disabled={processing}
sx={{
width: 240
}}
name="username" name="username"
label={LL.USERNAME(0)} label={LL.USERNAME(0)}
value={signInRequest.username} value={signInRequest.username}
onChange={updateLoginRequestValue} onChange={updateLoginRequestValue}
margin="normal" margin="normal"
variant="outlined" variant="outlined"
fullWidth
/> />
<ValidatedTextField <ValidatedPasswordField
fieldErrors={fieldErrors} fieldErrors={fieldErrors}
disabled={processing} disabled={processing}
type="password" sx={{
width: 240
}}
name="password" name="password"
label={LL.PASSWORD()} label={LL.PASSWORD()}
value={signInRequest.password} value={signInRequest.password}
onChange={updateLoginRequestValue} onChange={updateLoginRequestValue}
onKeyDown={submitOnEnter} onKeyDown={submitOnEnter}
margin="normal"
variant="outlined" variant="outlined"
fullWidth
/> />
<Fab variant="extended" color="primary" sx={{ mt: 2 }} onClick={validateAndSignIn} disabled={processing}> </Box>
<Button variant="contained" color="primary" sx={{ mt: 2 }} onClick={validateAndSignIn} disabled={processing}>
<ForwardIcon sx={{ mr: 1 }} /> <ForwardIcon sx={{ mr: 1 }} />
{LL.SIGN_IN()} {LL.SIGN_IN()}
</Fab> </Button>
</Paper> </Paper>
</Box> </Box>
); );

View File

@@ -1,16 +1,7 @@
import { AxiosPromise } from 'axios'; import { alovaInstance } from './endpoints';
import { APSettings, APStatus } from '../types'; import type { APSettings, APStatus } from 'types';
import { AXIOS } from './endpoints';
export function readAPStatus(): AxiosPromise<APStatus> { export const readAPStatus = () => alovaInstance.Get<APStatus>('/rest/apStatus');
return AXIOS.get('/apStatus'); export const readAPSettings = () => alovaInstance.Get<APSettings>('/rest/apSettings');
} export const updateAPSettings = (data: APSettings) => alovaInstance.Post<APSettings>('/rest/apSettings', data);
export function readAPSettings(): AxiosPromise<APSettings> {
return AXIOS.get('/apSettings');
}
export function updateAPSettings(apSettings: APSettings): AxiosPromise<APSettings> {
return AXIOS.post('/apSettings', apSettings);
}

View File

@@ -1,29 +1,16 @@
import { AxiosPromise } from 'axios';
import * as H from 'history';
import jwtDecode from 'jwt-decode'; import jwtDecode from 'jwt-decode';
import { Path } from 'react-router-dom'; import { ACCESS_TOKEN, alovaInstance } from './endpoints';
import type * as H from 'history';
import type { Path } from 'react-router-dom';
import { Features, Me, SignInRequest, SignInResponse } from '../types'; import type { Me, SignInRequest, SignInResponse } from 'types';
import { ACCESS_TOKEN, AXIOS } from './endpoints';
import { PROJECT_PATH } from './env';
export const SIGN_IN_PATHNAME = 'loginPathname'; export const SIGN_IN_PATHNAME = 'loginPathname';
export const SIGN_IN_SEARCH = 'loginSearch'; export const SIGN_IN_SEARCH = 'loginSearch';
export const getDefaultRoute = (features: Features) => (features.project ? `/${PROJECT_PATH}` : '/wifi'); export const verifyAuthorization = () => alovaInstance.Get('/rest/verifyAuthorization');
export const signIn = (request: SignInRequest) => alovaInstance.Post<SignInResponse>('/rest/signIn', request);
export function verifyAuthorization(): AxiosPromise<void> {
return AXIOS.get('/verifyAuthorization');
}
export function signIn(request: SignInRequest): AxiosPromise<SignInResponse> {
return AXIOS.post('/signIn', request);
}
/**
* Fallback to sessionStorage if localStorage is absent. WebView may not have local storage enabled.
*/
export function getStorage() { export function getStorage() {
return localStorage || sessionStorage; return localStorage || sessionStorage;
} }
@@ -40,18 +27,18 @@ export function clearLoginRedirect() {
getStorage().removeItem(SIGN_IN_SEARCH); getStorage().removeItem(SIGN_IN_SEARCH);
} }
export function fetchLoginRedirect(features: Features): Partial<Path> { export function fetchLoginRedirect(): Partial<Path> {
const signInPathname = getStorage().getItem(SIGN_IN_PATHNAME); const signInPathname = getStorage().getItem(SIGN_IN_PATHNAME);
const signInSearch = getStorage().getItem(SIGN_IN_SEARCH); const signInSearch = getStorage().getItem(SIGN_IN_SEARCH);
clearLoginRedirect(); clearLoginRedirect();
return { return {
pathname: signInPathname || getDefaultRoute(features), pathname: signInPathname || `/dashboard`,
search: (signInPathname && signInSearch) || undefined search: (signInPathname && signInSearch) || undefined
}; };
} }
export const clearAccessToken = () => localStorage.removeItem(ACCESS_TOKEN); export const clearAccessToken = () => localStorage.removeItem(ACCESS_TOKEN);
export const decodeMeJWT = (accessToken: string): Me => jwtDecode(accessToken) as Me; export const decodeMeJWT = (accessToken: string): Me => jwtDecode(accessToken);
export function addAccessTokenParameter(url: string) { export function addAccessTokenParameter(url: string) {
const accessToken = getStorage().getItem(ACCESS_TOKEN); const accessToken = getStorage().getItem(ACCESS_TOKEN);

View File

@@ -1,105 +1,60 @@
import axios, { AxiosPromise, CancelToken, AxiosProgressEvent } from 'axios'; import { xhrRequestAdapter } from '@alova/adapter-xhr';
import { createAlova } from 'alova';
import ReactHook from 'alova/react';
import { unpack } from '../api/unpack';
import { decode } from '@msgpack/msgpack';
export const WS_BASE_URL = '/ws/';
export const API_BASE_URL = '/rest/';
export const ES_BASE_URL = '/es/';
export const EMSESP_API_BASE_URL = '/api/';
export const ACCESS_TOKEN = 'access_token'; export const ACCESS_TOKEN = 'access_token';
export const WEB_SOCKET_ROOT = calculateWebSocketRoot(WS_BASE_URL);
export const EVENT_SOURCE_ROOT = calculateEventSourceRoot(ES_BASE_URL);
export const AXIOS = axios.create({ const host = window.location.host;
baseURL: API_BASE_URL, export const WEB_SOCKET_ROOT = 'ws://' + host + '/ws/';
headers: { export const EVENT_SOURCE_ROOT = 'http://' + host + '/es/';
'Content-Type': 'application/json'
}, export const alovaInstance = createAlova({
transformRequest: [ statesHook: ReactHook,
(data, headers) => { timeout: 3000, // 3 seconds but throwing a timeout error
if (headers) { localCache: null,
// localCache: {
// GET: {
// mode: 'placeholder', // see https://alova.js.org/learning/response-cache/#cache-replaceholder-mode
// expire: 2000
// }
// },
requestAdapter: xhrRequestAdapter(),
beforeRequest(method) {
if (localStorage.getItem(ACCESS_TOKEN)) { if (localStorage.getItem(ACCESS_TOKEN)) {
headers.Authorization = 'Bearer ' + localStorage.getItem(ACCESS_TOKEN); method.config.headers.Authorization = 'Bearer ' + localStorage.getItem(ACCESS_TOKEN);
}
},
responded: {
onSuccess: async (response) => {
// if (response.status === 202) {
// throw new Error('Wait'); // wifi scan in progress
// } else
if (response.status === 205) {
throw new Error('Reboot required');
} else if (response.status === 400) {
throw new Error('Request Failed');
} else if (response.status >= 400) {
throw new Error(response.statusText);
}
const data = await response.data;
if (response.data instanceof ArrayBuffer) {
return unpack(data);
} }
if (headers['Content-Type'] !== 'application/json') {
return data; return data;
} }
// Interceptor for request failure. This interceptor will be entered when the request is wrong.
// http errors like 401 (unauthorized) are handled either in the methods or AuthenticatedRouting()
// onError: (error, method) => {
// alert(error.message);
// }
} }
return JSON.stringify(data);
}
]
}); });
export const AXIOS_API = axios.create({ export const alovaInstanceGH = createAlova({
baseURL: EMSESP_API_BASE_URL, baseURL: 'https://api.github.com/repos/emsesp/EMS-ESP32/releases',
headers: { statesHook: ReactHook,
'Content-Type': 'application/json' requestAdapter: xhrRequestAdapter()
},
transformRequest: [
(data, headers) => {
if (headers) {
if (localStorage.getItem(ACCESS_TOKEN)) {
headers.Authorization = 'Bearer ' + localStorage.getItem(ACCESS_TOKEN);
}
if (headers['Content-Type'] !== 'application/json') {
return data;
}
}
return JSON.stringify(data);
}
]
}); });
export const AXIOS_BIN = axios.create({
baseURL: API_BASE_URL,
headers: {
'Content-Type': 'application/json'
},
responseType: 'arraybuffer',
transformRequest: [
(data, headers) => {
if (headers) {
if (localStorage.getItem(ACCESS_TOKEN)) {
headers.Authorization = 'Bearer ' + localStorage.getItem(ACCESS_TOKEN);
}
if (headers['Content-Type'] !== 'application/json') {
return data;
}
}
return JSON.stringify(data);
}
],
transformResponse: [
(data) => {
return decode(data);
}
]
});
function calculateWebSocketRoot(webSocketPath: string) {
const location = window.location;
const webProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
return webProtocol + '//' + location.host + webSocketPath;
}
function calculateEventSourceRoot(endpointPath: string) {
const location = window.location;
return location.protocol + '//' + location.host + endpointPath;
}
export interface FileUploadConfig {
cancelToken?: CancelToken;
onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;
}
export const startUploadFile = (url: string, file: File, config?: FileUploadConfig): AxiosPromise<void> => {
const formData = new FormData();
formData.append('file', file);
return AXIOS.post(url, formData, {
headers: {
'Content-Type': 'multipart/form-data'
},
...(config || {})
});
};

View File

@@ -1,2 +1 @@
export const PROJECT_NAME = process.env.REACT_APP_PROJECT_NAME || 'EMS-ESP'; export const PROJECT_NAME = 'EMS-ESP';
export const PROJECT_PATH = process.env.REACT_APP_PROJECT_PATH || 'project';

View File

@@ -1,9 +1,5 @@
import { AxiosPromise } from 'axios'; import { alovaInstance } from './endpoints';
import { Features } from '../types'; import type { Features } from 'types';
import { AXIOS } from './endpoints'; export const readFeatures = () => alovaInstance.Get<Features>('/rest/features');
export function readFeatures(): AxiosPromise<Features> {
return AXIOS.get('/features');
}

View File

@@ -1,16 +1,6 @@
import { AxiosPromise } from 'axios'; import { alovaInstance } from './endpoints';
import { MqttSettings, MqttStatus } from '../types'; import type { MqttSettings, MqttStatus } from 'types';
import { AXIOS } from './endpoints'; export const readMqttStatus = () => alovaInstance.Get<MqttStatus>('/rest/mqttStatus');
export const readMqttSettings = () => alovaInstance.Get<MqttSettings>('/rest/mqttSettings');
export function readMqttStatus(): AxiosPromise<MqttStatus> { export const updateMqttSettings = (data: MqttSettings) => alovaInstance.Post<MqttSettings>('/rest/mqttSettings', data);
return AXIOS.get('/mqttStatus');
}
export function readMqttSettings(): AxiosPromise<MqttSettings> {
return AXIOS.get('/mqttSettings');
}
export function updateMqttSettings(mqttSettings: MqttSettings): AxiosPromise<MqttSettings> {
return AXIOS.post('/mqttSettings', mqttSettings);
}

View File

@@ -1,25 +1,15 @@
import { AxiosPromise } from 'axios'; import { alovaInstance } from './endpoints';
import { WiFiNetworkList, NetworkSettings, NetworkStatus } from '../types'; import type { WiFiNetworkList, NetworkSettings, NetworkStatus } from 'types';
import { AXIOS } from './endpoints'; export const readNetworkStatus = () => alovaInstance.Get<NetworkStatus>('/rest/networkStatus');
export const scanNetworks = () => alovaInstance.Get('/rest/scanNetworks');
export function readNetworkStatus(): AxiosPromise<NetworkStatus> { export const listNetworks = () =>
return AXIOS.get('/networkStatus'); alovaInstance.Get<WiFiNetworkList>('/rest/listNetworks', {
} name: 'listNetworks',
timeout: 20000 // timeout 20 seconds
export function scanNetworks(): AxiosPromise<void> { });
return AXIOS.get('/scanNetworks'); export const readNetworkSettings = () =>
} alovaInstance.Get<NetworkSettings>('/rest/networkSettings', { name: 'networkSettings' });
export const updateNetworkSettings = (wifiSettings: NetworkSettings) =>
export function listNetworks(): AxiosPromise<WiFiNetworkList> { alovaInstance.Post<NetworkSettings>('/rest/networkSettings', wifiSettings);
return AXIOS.get('/listNetworks');
}
export function readNetworkSettings(): AxiosPromise<NetworkSettings> {
return AXIOS.get('/networkSettings');
}
export function updateNetworkSettings(wifiSettings: NetworkSettings): AxiosPromise<NetworkSettings> {
return AXIOS.post('/networkSettings', wifiSettings);
}

View File

@@ -1,20 +1,11 @@
import { AxiosPromise } from 'axios'; import { alovaInstance } from './endpoints';
import { NTPSettings, NTPStatus, Time } from '../types'; import type { NTPSettings, NTPStatus, Time } from 'types';
import { AXIOS } from './endpoints'; export const readNTPStatus = () => alovaInstance.Get<NTPStatus>('/rest/ntpStatus');
export const readNTPSettings = () =>
alovaInstance.Get<NTPSettings>('/rest/ntpSettings', {
name: 'ntpSettings'
});
export const updateNTPSettings = (data: NTPSettings) => alovaInstance.Post<NTPSettings>('/rest/ntpSettings', data);
export function readNTPStatus(): AxiosPromise<NTPStatus> { export const updateTime = (data: Time) => alovaInstance.Post<Time>('/rest/time', data);
return AXIOS.get('/ntpStatus');
}
export function readNTPSettings(): AxiosPromise<NTPSettings> {
return AXIOS.get('/ntpSettings');
}
export function updateNTPSettings(ntpSettings: NTPSettings): AxiosPromise<NTPSettings> {
return AXIOS.post('/ntpSettings', ntpSettings);
}
export function updateTime(time: Time): AxiosPromise<Time> {
return AXIOS.post('/time', time);
}

View File

@@ -1,17 +1,13 @@
import { AxiosPromise } from 'axios'; import { alovaInstance } from './endpoints';
import { SecuritySettings, Token } from '../types'; import type { SecuritySettings, Token } from 'types';
import { AXIOS } from './endpoints'; export const readSecuritySettings = () => alovaInstance.Get<SecuritySettings>('/rest/securitySettings');
export function readSecuritySettings(): AxiosPromise<SecuritySettings> { export const updateSecuritySettings = (securitySettings: SecuritySettings) =>
return AXIOS.get('/securitySettings'); alovaInstance.Post('/rest/securitySettings', securitySettings);
}
export function updateSecuritySettings(securitySettings: SecuritySettings): AxiosPromise<SecuritySettings> { export const generateToken = (username?: string) =>
return AXIOS.post('/securitySettings', securitySettings); alovaInstance.Get<Token>('/rest/generateToken', {
} params: { username }
});
export function generateToken(username?: string): AxiosPromise<Token> {
return AXIOS.get('/generateToken', { params: { username } });
}

View File

@@ -1,44 +1,42 @@
import { AxiosPromise } from 'axios'; import { alovaInstance, alovaInstanceGH } from './endpoints';
import type { OTASettings, SystemStatus, LogSettings } from 'types';
import { OTASettings, SystemStatus, LogSettings, LogEntries } from '../types'; // SystemStatus - also used to ping in Restart monitor for pinging
export const readSystemStatus = () => alovaInstance.Get<SystemStatus>('/rest/systemStatus');
import { AXIOS, AXIOS_BIN, FileUploadConfig, startUploadFile } from './endpoints'; // commands
export const restart = () => alovaInstance.Post('/rest/restart');
export const partition = () => alovaInstance.Post('/rest/partition');
export const factoryReset = () => alovaInstance.Post('/rest/factoryReset');
export function readSystemStatus(timeout?: number): AxiosPromise<SystemStatus> { // OTA
return AXIOS.get('/systemStatus', { timeout }); export const readOTASettings = () => alovaInstance.Get<OTASettings>(`/rest/otaSettings`);
export const updateOTASettings = (data: any) => alovaInstance.Post('/rest/otaSettings', data);
// SystemLog
export const readLogSettings = () => alovaInstance.Get<LogSettings>(`/rest/logSettings`);
export const updateLogSettings = (data: any) => alovaInstance.Post('/rest/logSettings', data);
export const fetchLog = () => alovaInstance.Post('/rest/fetchLog');
// Get versions from github
export const getStableVersion = () =>
alovaInstanceGH.Get('latest', {
transformData(response: any) {
return response.data.name.substring(1);
} }
});
export function restart(): AxiosPromise<void> { export const getDevVersion = () =>
return AXIOS.post('/restart'); alovaInstanceGH.Get('tags/latest', {
transformData(response: any) {
return response.data.name.split(/\s+/).splice(-1)[0].substring(1);
} }
});
export function partition(): AxiosPromise<void> { export const uploadFile = (file: File) => {
return AXIOS.post('/partition'); const formData = new FormData();
} formData.append('file', file);
return alovaInstance.Post('/rest/uploadFile', formData, {
export function factoryReset(): AxiosPromise<void> { timeout: 60000, // override timeout for uploading firmware - 1 minute
return AXIOS.post('/factoryReset'); enableUpload: true
} });
};
export function readOTASettings(): AxiosPromise<OTASettings> {
return AXIOS.get('/otaSettings');
}
export function updateOTASettings(otaSettings: OTASettings): AxiosPromise<OTASettings> {
return AXIOS.post('/otaSettings', otaSettings);
}
export const uploadFile = (file: File, config?: FileUploadConfig): AxiosPromise<void> =>
startUploadFile('/uploadFile', file, config);
export function readLogSettings(): AxiosPromise<LogSettings> {
return AXIOS.get('/logSettings');
}
export function updateLogSettings(logSettings: LogSettings): AxiosPromise<LogSettings> {
return AXIOS.post('/logSettings', logSettings);
}
export function readLogEntries(): AxiosPromise<LogEntries> {
return AXIOS_BIN.get('/fetchLog');
}

1131
interface/src/api/unpack.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
import { FC } from 'react'; import { Box } from '@mui/material';
import { Box, BoxProps } from '@mui/material'; import type { BoxProps } from '@mui/material';
import type { FC } from 'react';
const ButtonRow: FC<BoxProps> = ({ children, ...rest }) => { const ButtonRow: FC<BoxProps> = ({ children, ...rest }) => (
return (
<Box <Box
sx={{ sx={{
'& button, & a, & .MuiCard-root': { '& button, & a, & .MuiCard-root': {
@@ -21,6 +21,5 @@ const ButtonRow: FC<BoxProps> = ({ children, ...rest }) => {
{children} {children}
</Box> </Box>
); );
};
export default ButtonRow; export default ButtonRow;

View File

@@ -1,11 +1,10 @@
import { FC } from 'react';
import { Box, BoxProps, SvgIconProps, Theme, Typography, useTheme } from '@mui/material';
import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
import ErrorIcon from '@mui/icons-material/Error';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import ReportProblemOutlinedIcon from '@mui/icons-material/ReportProblemOutlined'; import ReportProblemOutlinedIcon from '@mui/icons-material/ReportProblemOutlined';
import ErrorIcon from '@mui/icons-material/Error'; import { Box, Typography, useTheme } from '@mui/material';
import type { BoxProps, SvgIconProps, Theme } from '@mui/material';
import type { FC } from 'react';
type MessageBoxLevel = 'warning' | 'success' | 'info' | 'error'; type MessageBoxLevel = 'warning' | 'success' | 'info' | 'error';

View File

@@ -1,8 +1,7 @@
import { FC } from 'react';
import { Paper, Divider } from '@mui/material'; import { Paper, Divider } from '@mui/material';
import type { FC } from 'react';
import { RequiredChildrenProps } from '../utils'; import type { RequiredChildrenProps } from 'utils';
interface SectionContentProps extends RequiredChildrenProps { interface SectionContentProps extends RequiredChildrenProps {
title: string; title: string;

View File

@@ -6,3 +6,4 @@ export * from './upload';
export { default as SectionContent } from './SectionContent'; export { default as SectionContent } from './SectionContent';
export { default as ButtonRow } from './ButtonRow'; export { default as ButtonRow } from './ButtonRow';
export { default as MessageBox } from './MessageBox'; export { default as MessageBox } from './MessageBox';
export { default as BlockNavigation } from './routing/BlockNavigation';

View File

@@ -1,5 +1,6 @@
import { FC } from 'react'; import { FormControlLabel } from '@mui/material';
import { FormControlLabel, FormControlLabelProps } from '@mui/material'; import type { FormControlLabelProps } from '@mui/material';
import type { FC } from 'react';
const BlockFormControlLabel: FC<FormControlLabelProps> = (props) => ( const BlockFormControlLabel: FC<FormControlLabelProps> = (props) => (
<div> <div>

View File

@@ -1,10 +1,11 @@
import { FC, useState } from 'react';
import { IconButton, InputAdornment } from '@mui/material';
import VisibilityIcon from '@mui/icons-material/Visibility'; import VisibilityIcon from '@mui/icons-material/Visibility';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
import { IconButton, InputAdornment } from '@mui/material';
import { useState } from 'react';
import ValidatedTextField, { ValidatedTextFieldProps } from './ValidatedTextField'; import ValidatedTextField from './ValidatedTextField';
import type { ValidatedTextFieldProps } from './ValidatedTextField';
import type { FC } from 'react';
type ValidatedPasswordFieldProps = Omit<ValidatedTextFieldProps, 'type'>; type ValidatedPasswordFieldProps = Omit<ValidatedTextFieldProps, 'type'>;
@@ -19,11 +20,7 @@ const ValidatedPasswordField: FC<ValidatedPasswordFieldProps> = ({ InputProps, .
...InputProps, ...InputProps,
endAdornment: ( endAdornment: (
<InputAdornment position="end"> <InputAdornment position="end">
<IconButton <IconButton onClick={() => setShowPassword(!showPassword)} edge="end">
aria-label="toggle password visibility"
onClick={() => setShowPassword(!showPassword)}
edge="end"
>
{showPassword ? <VisibilityIcon /> : <VisibilityOffIcon />} {showPassword ? <VisibilityIcon /> : <VisibilityOffIcon />}
</IconButton> </IconButton>
</InputAdornment> </InputAdornment>

View File

@@ -1,7 +1,7 @@
import { FC } from 'react'; import { FormHelperText, TextField } from '@mui/material';
import { ValidateFieldsError } from 'async-validator'; import type { TextFieldProps } from '@mui/material';
import type { ValidateFieldsError } from 'async-validator';
import { FormHelperText, TextField, TextFieldProps } from '@mui/material'; import type { FC } from 'react';
interface ValidatedFieldProps { interface ValidatedFieldProps {
fieldErrors?: ValidateFieldsError; fieldErrors?: ValidateFieldsError;

View File

@@ -1,16 +1,15 @@
import { FC, useState, useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { Box, Toolbar } from '@mui/material'; import { Box, Toolbar } from '@mui/material';
import { useState, useEffect } from 'react';
import { PROJECT_NAME } from '../../api/env'; import { useLocation } from 'react-router-dom';
import { RequiredChildrenProps } from '../../utils';
import LayoutDrawer from './LayoutDrawer';
import LayoutAppBar from './LayoutAppBar'; import LayoutAppBar from './LayoutAppBar';
import LayoutDrawer from './LayoutDrawer';
import { LayoutContext } from './context'; import { LayoutContext } from './context';
import type { FC } from 'react';
export const DRAWER_WIDTH = 240; import type { RequiredChildrenProps } from 'utils';
import { PROJECT_NAME } from 'api/env';
export const DRAWER_WIDTH = 210;
const Layout: FC<RequiredChildrenProps> = ({ children }) => { const Layout: FC<RequiredChildrenProps> = ({ children }) => {
const [mobileOpen, setMobileOpen] = useState(false); const [mobileOpen, setMobileOpen] = useState(false);

View File

@@ -1,23 +1,16 @@
import { FC, useContext } from 'react';
import { AppBar, Box, IconButton, Toolbar, Typography } from '@mui/material';
import MenuIcon from '@mui/icons-material/Menu'; import MenuIcon from '@mui/icons-material/Menu';
import { AppBar, Box, IconButton, Toolbar, Typography } from '@mui/material';
import LayoutAuthMenu from './LayoutAuthMenu'; import LayoutAuthMenu from './LayoutAuthMenu';
import type { FC } from 'react';
import { FeaturesContext } from '../../contexts/features'; export const DRAWER_WIDTH = 210;
export const DRAWER_WIDTH = 240;
interface LayoutAppBarProps { interface LayoutAppBarProps {
title: string; title: string;
onToggleDrawer: () => void; onToggleDrawer: () => void;
} }
const LayoutAppBar: FC<LayoutAppBarProps> = ({ title, onToggleDrawer }) => { const LayoutAppBar: FC<LayoutAppBarProps> = ({ title, onToggleDrawer }) => (
const { features } = useContext(FeaturesContext);
return (
<AppBar <AppBar
position="fixed" position="fixed"
sx={{ sx={{
@@ -28,23 +21,16 @@ const LayoutAppBar: FC<LayoutAppBarProps> = ({ title, onToggleDrawer }) => {
}} }}
> >
<Toolbar> <Toolbar>
<IconButton <IconButton color="inherit" edge="start" onClick={onToggleDrawer} sx={{ mr: 2, display: { md: 'none' } }}>
color="inherit"
aria-label="open drawer"
edge="start"
onClick={onToggleDrawer}
sx={{ mr: 2, display: { md: 'none' } }}
>
<MenuIcon /> <MenuIcon />
</IconButton> </IconButton>
<Typography variant="h6" noWrap component="div"> <Typography variant="h6" noWrap component="div">
{title} {title}
</Typography> </Typography>
<Box flexGrow={1} /> <Box flexGrow={1} />
{features.security && <LayoutAuthMenu />} <LayoutAuthMenu />
</Toolbar> </Toolbar>
</AppBar> </AppBar>
); );
};
export default LayoutAppBar; export default LayoutAppBar;

View File

@@ -1,5 +1,5 @@
import { FC, useState, useContext, ChangeEventHandler } from 'react'; import AccountCircleIcon from '@mui/icons-material/AccountCircle';
import PersonIcon from '@mui/icons-material/Person';
import { import {
Box, Box,
Button, Button,
@@ -9,27 +9,27 @@ import {
Typography, Typography,
Avatar, Avatar,
styled, styled,
TypographyProps,
MenuItem, MenuItem,
TextField TextField
} from '@mui/material'; } from '@mui/material';
import { useState, useContext } from 'react';
import type { TypographyProps } from '@mui/material';
import PersonIcon from '@mui/icons-material/Person'; import type { Locales } from 'i18n/i18n-types';
import AccountCircleIcon from '@mui/icons-material/AccountCircle'; import type { FC, ChangeEventHandler } from 'react';
import { AuthenticatedContext } from 'contexts/authentication';
import { AuthenticatedContext } from '../../contexts/authentication'; import { ReactComponent as DEflag } from 'i18n/DE.svg';
import { ReactComponent as FRflag } from 'i18n/FR.svg';
import { I18nContext } from '../../i18n/i18n-react'; import { ReactComponent as GBflag } from 'i18n/GB.svg';
import type { Locales } from '../../i18n/i18n-types'; import { ReactComponent as ITflag } from 'i18n/IT.svg';
import { loadLocaleAsync } from '../../i18n/i18n-util.async'; import { ReactComponent as NLflag } from 'i18n/NL.svg';
import { ReactComponent as NOflag } from 'i18n/NO.svg';
import { ReactComponent as NLflag } from '../../i18n/NL.svg'; import { ReactComponent as PLflag } from 'i18n/PL.svg';
import { ReactComponent as DEflag } from '../../i18n/DE.svg'; import { ReactComponent as SVflag } from 'i18n/SV.svg';
import { ReactComponent as GBflag } from '../../i18n/GB.svg'; import { ReactComponent as TRflag } from 'i18n/TR.svg';
import { ReactComponent as SVflag } from '../../i18n/SV.svg'; import { I18nContext } from 'i18n/i18n-react';
import { ReactComponent as PLflag } from '../../i18n/PL.svg'; import { loadLocaleAsync } from 'i18n/i18n-util.async';
import { ReactComponent as NOflag } from '../../i18n/NO.svg';
import { ReactComponent as FRflag } from '../../i18n/FR.svg';
const ItemTypography = styled(Typography)<TypographyProps>({ const ItemTypography = styled(Typography)<TypographyProps>({
maxWidth: '250px', maxWidth: '250px',
@@ -74,19 +74,22 @@ const LayoutAuthMenu: FC = () => {
size="small" size="small"
select select
> >
<MenuItem key="en" value="en">
<GBflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;EN
</MenuItem>
<Divider />
<MenuItem key="de" value="de"> <MenuItem key="de" value="de">
<DEflag style={{ width: 16, verticalAlign: 'middle' }} /> <DEflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;DE &nbsp;DE
</MenuItem> </MenuItem>
<MenuItem key="en" value="en">
<GBflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;EN
</MenuItem>
<MenuItem key="fr" value="fr"> <MenuItem key="fr" value="fr">
<FRflag style={{ width: 16, verticalAlign: 'middle' }} /> <FRflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;FR &nbsp;FR
</MenuItem> </MenuItem>
<MenuItem key="it" value="it">
<ITflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;IT
</MenuItem>
<MenuItem key="nl" value="nl"> <MenuItem key="nl" value="nl">
<NLflag style={{ width: 16, verticalAlign: 'middle' }} /> <NLflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;NL &nbsp;NL
@@ -103,6 +106,10 @@ const LayoutAuthMenu: FC = () => {
<SVflag style={{ width: 16, verticalAlign: 'middle' }} /> <SVflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;SV &nbsp;SV
</MenuItem> </MenuItem>
<MenuItem key="tr" value="tr">
<TRflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;TR
</MenuItem>
</TextField> </TextField>
<IconButton <IconButton

View File

@@ -1,11 +1,9 @@
import { FC } from 'react';
import { Box, Divider, Drawer, Toolbar, Typography, styled } from '@mui/material'; import { Box, Divider, Drawer, Toolbar, Typography, styled } from '@mui/material';
import { PROJECT_NAME } from '../../api/env';
import LayoutMenu from './LayoutMenu';
import { DRAWER_WIDTH } from './Layout'; import { DRAWER_WIDTH } from './Layout';
import LayoutMenu from './LayoutMenu';
import type { FC } from 'react';
import { PROJECT_NAME } from 'api/env';
const LayoutDrawerLogo = styled('img')(({ theme }) => ({ const LayoutDrawerLogo = styled('img')(({ theme }) => ({
[theme.breakpoints.down('sm')]: { [theme.breakpoints.down('sm')]: {
@@ -13,7 +11,7 @@ const LayoutDrawerLogo = styled('img')(({ theme }) => ({
marginRight: theme.spacing(2) marginRight: theme.spacing(2)
}, },
[theme.breakpoints.up('sm')]: { [theme.breakpoints.up('sm')]: {
height: 36, height: 38,
marginRight: theme.spacing(2) marginRight: theme.spacing(2)
} }
})); }));
@@ -29,9 +27,7 @@ const LayoutDrawer: FC<LayoutDrawerProps> = ({ mobileOpen, onClose }) => {
<Toolbar disableGutters> <Toolbar disableGutters>
<Box display="flex" alignItems="center" px={2}> <Box display="flex" alignItems="center" px={2}>
<LayoutDrawerLogo src="/app/icon.png" alt={PROJECT_NAME} /> <LayoutDrawerLogo src="/app/icon.png" alt={PROJECT_NAME} />
<Typography variant="h6" color="textPrimary"> <Typography variant="h6">{PROJECT_NAME}</Typography>
{PROJECT_NAME}
</Typography>
</Box> </Box>
<Divider absolute /> <Divider absolute />
</Toolbar> </Toolbar>

View File

@@ -1,40 +1,45 @@
import { FC, useContext } from 'react';
import { Divider, List } from '@mui/material';
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
import AccessTimeIcon from '@mui/icons-material/AccessTime'; import AccessTimeIcon from '@mui/icons-material/AccessTime';
import DashboardIcon from '@mui/icons-material/Dashboard';
import DeviceHubIcon from '@mui/icons-material/DeviceHub'; import DeviceHubIcon from '@mui/icons-material/DeviceHub';
import SettingsIcon from '@mui/icons-material/Settings'; import InfoIcon from '@mui/icons-material/Info';
import LockIcon from '@mui/icons-material/Lock'; import LockIcon from '@mui/icons-material/Lock';
import SettingsIcon from '@mui/icons-material/Settings';
import SettingsEthernetIcon from '@mui/icons-material/SettingsEthernet'; import SettingsEthernetIcon from '@mui/icons-material/SettingsEthernet';
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
import TuneIcon from '@mui/icons-material/Tune';
import { Divider, List } from '@mui/material';
import { useContext } from 'react';
import type { FC } from 'react';
import { FeaturesContext } from '../../contexts/features'; import LayoutMenuItem from 'components/layout/LayoutMenuItem';
import ProjectMenu from '../../project/ProjectMenu';
import LayoutMenuItem from './LayoutMenuItem'; import { AuthenticatedContext } from 'contexts/authentication';
import { AuthenticatedContext } from '../../contexts/authentication';
import { useI18nContext } from '../../i18n/i18n-react'; import { useI18nContext } from 'i18n/i18n-react';
const LayoutMenu: FC = () => { const LayoutMenu: FC = () => {
const { features } = useContext(FeaturesContext);
const authenticatedContext = useContext(AuthenticatedContext); const authenticatedContext = useContext(AuthenticatedContext);
const { LL } = useI18nContext(); const { LL } = useI18nContext();
return ( return (
<> <>
{features.project && (
<List disablePadding component="nav"> <List disablePadding component="nav">
<ProjectMenu /> <LayoutMenuItem icon={DashboardIcon} label={LL.DASHBOARD()} to={`/dashboard`} />
<LayoutMenuItem
icon={TuneIcon}
label={LL.SETTINGS_OF('')}
to={`/settings`}
disabled={!authenticatedContext.me.admin}
/>
<LayoutMenuItem icon={InfoIcon} label={LL.HELP_OF('')} to={`/help`} />
<Divider /> <Divider />
</List> </List>
)}
<List disablePadding component="nav"> <List disablePadding component="nav">
<LayoutMenuItem icon={SettingsEthernetIcon} label={LL.NETWORK(0)} to="/network" /> <LayoutMenuItem icon={SettingsEthernetIcon} label={LL.NETWORK(0)} to="/network" />
<LayoutMenuItem icon={SettingsInputAntennaIcon} label={LL.ACCESS_POINT(0)} to="/ap" /> <LayoutMenuItem icon={SettingsInputAntennaIcon} label={LL.ACCESS_POINT(0)} to="/ap" />
{features.ntp && <LayoutMenuItem icon={AccessTimeIcon} label="NTP" to="/ntp" />} <LayoutMenuItem icon={AccessTimeIcon} label="NTP" to="/ntp" />
{features.mqtt && <LayoutMenuItem icon={DeviceHubIcon} label="MQTT" to="/mqtt" />} <LayoutMenuItem icon={DeviceHubIcon} label="MQTT" to="/mqtt" />
<LayoutMenuItem <LayoutMenuItem
icon={LockIcon} icon={LockIcon}
label={LL.SECURITY(0)} label={LL.SECURITY(0)}

View File

@@ -1,11 +1,9 @@
import { FC } from 'react'; import { ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material';
import { Link, useLocation } from 'react-router-dom'; import { Link, useLocation } from 'react-router-dom';
import type { SvgIconProps } from '@mui/material';
import type { FC } from 'react';
import { ListItem, ListItemButton, ListItemIcon, ListItemText, SvgIconProps } from '@mui/material'; import { routeMatches } from 'utils';
import { grey } from '@mui/material/colors';
import { routeMatches } from '../../utils';
interface LayoutMenuItemProps { interface LayoutMenuItemProps {
icon: React.ComponentType<SvgIconProps>; icon: React.ComponentType<SvgIconProps>;
@@ -17,13 +15,15 @@ interface LayoutMenuItemProps {
const LayoutMenuItem: FC<LayoutMenuItemProps> = ({ icon: Icon, label, to, disabled }) => { const LayoutMenuItem: FC<LayoutMenuItemProps> = ({ icon: Icon, label, to, disabled }) => {
const { pathname } = useLocation(); const { pathname } = useLocation();
const selected = routeMatches(to, pathname);
return ( return (
<ListItem disablePadding selected={routeMatches(to, pathname)}> <ListItem disablePadding>
<ListItemButton component={Link} to={to} disabled={disabled}> <ListItemButton component={Link} to={to} disabled={disabled} selected={selected}>
<ListItemIcon sx={{ color: grey[500] }}> <ListItemIcon sx={{ color: selected ? '#90caf9' : '#9e9e9e' }}>
<Icon /> <Icon />
</ListItemIcon> </ListItemIcon>
<ListItemText>{label}</ListItemText> <ListItemText sx={{ color: selected ? '#90caf9' : '#f5f5f5' }}>{label}</ListItemText>
</ListItemButton> </ListItemButton>
</ListItem> </ListItem>
); );

View File

@@ -1,7 +1,6 @@
import { FC } from 'react';
import { Box, Paper, Typography } from '@mui/material';
import WarningIcon from '@mui/icons-material/Warning'; import WarningIcon from '@mui/icons-material/Warning';
import { Box, Paper, Typography } from '@mui/material';
import type { FC } from 'react';
interface ApplicationErrorProps { interface ApplicationErrorProps {
message?: string; message?: string;

View File

@@ -1,11 +1,10 @@
import { FC } from 'react';
import { Box, Button, CircularProgress, Typography } from '@mui/material';
import RefreshIcon from '@mui/icons-material/Refresh'; import RefreshIcon from '@mui/icons-material/Refresh';
import { Box, Button, CircularProgress, Typography } from '@mui/material';
import type { FC } from 'react';
import { MessageBox } from '..'; import { MessageBox } from 'components';
import { useI18nContext } from '../../i18n/i18n-react'; import { useI18nContext } from 'i18n/i18n-react';
interface FormLoaderProps { interface FormLoaderProps {
message?: string; message?: string;

View File

@@ -1,8 +1,8 @@
import { FC } from 'react'; import { CircularProgress, Box, Typography } from '@mui/material';
import type { Theme } from '@mui/material';
import type { FC } from 'react';
import { CircularProgress, Box, Typography, Theme } from '@mui/material'; import { useI18nContext } from 'i18n/i18n-react';
import { useI18nContext } from '../../i18n/i18n-react';
interface LoadingSpinnerProps { interface LoadingSpinnerProps {
height?: number | string; height?: number | string;

View File

@@ -0,0 +1,32 @@
import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material';
import type { FC } from 'react';
import type { unstable_Blocker as Blocker } from 'react-router-dom';
import { dialogStyle } from 'CustomTheme';
import { useI18nContext } from 'i18n/i18n-react';
interface BlockNavigationProps {
blocker: Blocker;
}
const BlockNavigation: FC<BlockNavigationProps> = ({ blocker }) => {
const { LL } = useI18nContext();
return (
<Dialog sx={dialogStyle} open={blocker.state === 'blocked'}>
<DialogTitle>{LL.BLOCK_NAVIGATE_1()}</DialogTitle>
<DialogContent dividers>{LL.BLOCK_NAVIGATE_2()}</DialogContent>
<DialogActions>
<Button variant="outlined" onClick={() => blocker.reset?.()} color="secondary">
{LL.STAY()}
</Button>
<Button variant="contained" onClick={() => blocker.proceed?.()} color="primary">
{LL.LEAVE()}
</Button>
</DialogActions>
</Dialog>
);
};
export default BlockNavigation;

View File

@@ -1,8 +1,9 @@
import { FC, useContext } from 'react'; import { useContext } from 'react';
import { Navigate } from 'react-router-dom'; import { Navigate } from 'react-router-dom';
import type { FC } from 'react';
import { AuthenticatedContext } from '../../contexts/authentication'; import type { RequiredChildrenProps } from 'utils';
import { RequiredChildrenProps } from '../../utils'; import { AuthenticatedContext } from 'contexts/authentication';
const RequireAdmin: FC<RequiredChildrenProps> = ({ children }) => { const RequireAdmin: FC<RequiredChildrenProps> = ({ children }) => {
const authenticatedContext = useContext(AuthenticatedContext); const authenticatedContext = useContext(AuthenticatedContext);

View File

@@ -1,14 +1,12 @@
import { FC, useContext, useEffect } from 'react'; import { useContext, useEffect } from 'react';
import { Navigate, useLocation } from 'react-router-dom'; import { Navigate, useLocation } from 'react-router-dom';
import { import type { AuthenticatedContextValue } from 'contexts/authentication/context';
AuthenticatedContext, import type { FC } from 'react';
AuthenticatedContextValue,
AuthenticationContext
} from '../../contexts/authentication/context';
import { storeLoginRedirect } from '../../api/authentication';
import { RequiredChildrenProps } from '../../utils'; import type { RequiredChildrenProps } from 'utils';
import { storeLoginRedirect } from 'api/authentication';
import { AuthenticatedContext, AuthenticationContext } from 'contexts/authentication/context';
const RequireAuthenticated: FC<RequiredChildrenProps> = ({ children }) => { const RequireAuthenticated: FC<RequiredChildrenProps> = ({ children }) => {
const authenticationContext = useContext(AuthenticationContext); const authenticationContext = useContext(AuthenticationContext);

View File

@@ -1,16 +1,15 @@
import { FC, useContext } from 'react'; import { useContext } from 'react';
import { Navigate } from 'react-router-dom'; import { Navigate } from 'react-router-dom';
import type { FC } from 'react';
import * as AuthenticationApi from '../../api/authentication'; import type { RequiredChildrenProps } from 'utils';
import { AuthenticationContext } from '../../contexts/authentication'; import * as AuthenticationApi from 'api/authentication';
import { RequiredChildrenProps } from '../../utils'; import { AuthenticationContext } from 'contexts/authentication';
import { FeaturesContext } from '../../contexts/features';
const RequireUnauthenticated: FC<RequiredChildrenProps> = ({ children }) => { const RequireUnauthenticated: FC<RequiredChildrenProps> = ({ children }) => {
const { features } = useContext(FeaturesContext);
const authenticationContext = useContext(AuthenticationContext); const authenticationContext = useContext(AuthenticationContext);
return authenticationContext.me ? <Navigate to={AuthenticationApi.fetchLoginRedirect(features)} /> : <>{children}</>; return authenticationContext.me ? <Navigate to={AuthenticationApi.fetchLoginRedirect()} /> : <>{children}</>;
}; };
export default RequireUnauthenticated; export default RequireUnauthenticated;

View File

@@ -1,9 +1,8 @@
import React, { FC } from 'react';
import { useNavigate } from 'react-router-dom';
import { Tabs, useMediaQuery, useTheme } from '@mui/material'; import { Tabs, useMediaQuery, useTheme } from '@mui/material';
import { useNavigate } from 'react-router-dom';
import type { FC } from 'react';
import { RequiredChildrenProps } from '../../utils'; import type { RequiredChildrenProps } from 'utils';
interface RouterTabsProps extends RequiredChildrenProps { interface RouterTabsProps extends RequiredChildrenProps {
value: string | false; value: string | false;
@@ -15,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<{}>, path: string) => { const handleTabChange = (event: React.ChangeEvent<HTMLInputElement>, path: string) => {
navigate(path); navigate(path);
}; };

View File

@@ -1,14 +1,14 @@
import { FC, Fragment } from 'react';
import { useDropzone, DropzoneState } from 'react-dropzone';
import { AxiosProgressEvent } from 'axios';
import { Box, Button, LinearProgress, Theme, Typography, useTheme } from '@mui/material';
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
import { Box, Button, LinearProgress, Typography, useTheme } from '@mui/material';
import { Fragment } from 'react';
import { useDropzone } from 'react-dropzone';
import type { Theme } from '@mui/material';
import type { Progress } from 'alova';
import type { FC } from 'react';
import type { DropzoneState } from 'react-dropzone';
import { useI18nContext } from '../../i18n/i18n-react'; import { useI18nContext } from 'i18n/i18n-react';
const getBorderColor = (theme: Theme, props: DropzoneState) => { const getBorderColor = (theme: Theme, props: DropzoneState) => {
if (props.isDragAccept) { if (props.isDragAccept) {
@@ -26,11 +26,13 @@ const getBorderColor = (theme: Theme, props: DropzoneState) => {
export interface SingleUploadProps { export interface SingleUploadProps {
onDrop: (acceptedFiles: File[]) => void; onDrop: (acceptedFiles: File[]) => void;
onCancel: () => void; onCancel: () => void;
uploading: boolean; isUploading: boolean;
progress?: AxiosProgressEvent; progress: Progress;
} }
const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, uploading, progress }) => { const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, isUploading, progress }) => {
const uploading = isUploading && progress.total > 0;
const dropzoneState = useDropzone({ const dropzoneState = useDropzone({
onDrop, onDrop,
accept: { accept: {
@@ -38,20 +40,19 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, uploading, prog
'application/json': ['.json'], 'application/json': ['.json'],
'text/plain': ['.md5'] 'text/plain': ['.md5']
}, },
disabled: uploading, disabled: isUploading,
multiple: false multiple: false
}); });
const { getRootProps, getInputProps } = dropzoneState; const { getRootProps, getInputProps } = dropzoneState;
const theme = useTheme(); const theme = useTheme();
const { LL } = useI18nContext(); const { LL } = useI18nContext();
const progressText = () => { const progressText = () => {
if (uploading) { if (uploading) {
if (progress?.total) { if (progress.total) {
return LL.UPLOADING() + ': ' + Math.round((progress.loaded * 100) / progress.total) + '%'; return LL.UPLOADING() + ': ' + Math.round((progress.loaded * 100) / progress.total) + '%';
} }
return LL.UPLOADING() + `\u2026`;
} }
return LL.UPLOAD_DROP_TEXT(); return LL.UPLOAD_DROP_TEXT();
}; };
@@ -81,8 +82,8 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, uploading, prog
<Fragment> <Fragment>
<Box width="100%" p={2}> <Box width="100%" p={2}>
<LinearProgress <LinearProgress
variant={!progress || progress.total ? 'determinate' : 'indeterminate'} variant="determinate"
value={!progress ? 0 : progress.total ? Math.round((progress.loaded * 100) / progress.total) : 0} value={progress.total === 0 ? 0 : Math.round((progress.loaded * 100) / progress.total)}
/> />
</Box> </Box>
<Button startIcon={<CancelIcon />} variant="outlined" color="secondary" onClick={onCancel}> <Button startIcon={<CancelIcon />} variant="outlined" color="secondary" onClick={onCancel}>

View File

@@ -1,2 +1 @@
export { default as SingleUpload } from './SingleUpload'; export { default as SingleUpload } from './SingleUpload';
export { default as useFileUpload } from './useFileUpload';

View File

@@ -1,70 +0,0 @@
import { useCallback, useEffect, useState } from 'react';
import axios, { AxiosPromise, CancelTokenSource, AxiosProgressEvent } from 'axios';
import { useSnackbar } from 'notistack';
import { extractErrorMessage } from '../../utils';
import { FileUploadConfig } from '../../api/endpoints';
import { useI18nContext } from '../../i18n/i18n-react';
interface MediaUploadOptions {
upload: (file: File, config?: FileUploadConfig) => AxiosPromise<void>;
}
const useFileUpload = ({ upload }: MediaUploadOptions) => {
const { LL } = useI18nContext();
const { enqueueSnackbar } = useSnackbar();
const [uploading, setUploading] = useState<boolean>(false);
const [md5, setMd5] = useState<string>('');
const [uploadProgress, setUploadProgress] = useState<AxiosProgressEvent>();
const [uploadCancelToken, setUploadCancelToken] = useState<CancelTokenSource>();
const resetUploadingStates = () => {
setUploading(false);
setUploadProgress(undefined);
setUploadCancelToken(undefined);
setMd5('');
};
const cancelUpload = useCallback(() => {
uploadCancelToken?.cancel();
resetUploadingStates();
}, [uploadCancelToken]);
useEffect(() => {
return () => {
uploadCancelToken?.cancel();
};
}, [uploadCancelToken]);
const uploadFile = async (images: File[]) => {
try {
const cancelToken = axios.CancelToken.source();
setUploadCancelToken(cancelToken);
setUploading(true);
const response = await upload(images[0], {
onUploadProgress: setUploadProgress,
cancelToken: cancelToken.token
});
resetUploadingStates();
if (response.status === 200) {
enqueueSnackbar(LL.UPLOAD() + ' ' + LL.SUCCESSFUL(), { variant: 'success' });
} else if (response.status === 201) {
setMd5(String(response.data));
enqueueSnackbar(LL.UPLOAD() + ' MD5 ' + LL.SUCCESSFUL(), { variant: 'success' });
}
} catch (error) {
if (axios.isCancel(error)) {
enqueueSnackbar(LL.UPLOAD() + ' ' + LL.ABORTED(), { variant: 'warning' });
} else {
resetUploadingStates();
enqueueSnackbar(extractErrorMessage(error, LL.UPLOAD() + ' ' + LL.FAILED()), { variant: 'error' });
}
}
};
return [uploadFile, cancelUpload, uploading, uploadProgress, md5] as const;
};
export default useFileUpload;

View File

@@ -1,33 +1,35 @@
import { FC, useCallback, useContext, useEffect, useState } from 'react'; import { useRequest } from 'alova';
import { useSnackbar } from 'notistack'; import { useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify';
import { useI18nContext } from '../../i18n/i18n-react';
import * as AuthenticationApi from '../../api/authentication';
import { ACCESS_TOKEN } from '../../api/endpoints';
import { RequiredChildrenProps } from '../../utils';
import { LoadingSpinner } from '../../components';
import { Me } from '../../types';
import { FeaturesContext } from '../features';
import { AuthenticationContext } from './context'; import { AuthenticationContext } from './context';
import type { FC } from 'react';
import type { Me } from 'types';
import type { RequiredChildrenProps } from 'utils';
import * as AuthenticationApi from 'api/authentication';
import { ACCESS_TOKEN } from 'api/endpoints';
import { LoadingSpinner } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
const Authentication: FC<RequiredChildrenProps> = ({ children }) => { const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
const { features } = useContext(FeaturesContext);
const { LL } = useI18nContext(); const { LL } = useI18nContext();
const navigate = useNavigate(); const navigate = useNavigate();
const { enqueueSnackbar } = useSnackbar();
const [initialized, setInitialized] = useState<boolean>(false); const [initialized, setInitialized] = useState<boolean>(false);
const [me, setMe] = useState<Me>(); const [me, setMe] = useState<Me>();
const { send: verifyAuthorization } = useRequest(AuthenticationApi.verifyAuthorization(), {
immediate: false
});
const signIn = (accessToken: string) => { const signIn = (accessToken: string) => {
try { try {
AuthenticationApi.getStorage().setItem(ACCESS_TOKEN, accessToken); AuthenticationApi.getStorage().setItem(ACCESS_TOKEN, accessToken);
const decodedMe = AuthenticationApi.decodeMeJWT(accessToken); const decodedMe = AuthenticationApi.decodeMeJWT(accessToken);
setMe(decodedMe); setMe(decodedMe);
enqueueSnackbar(LL.LOGGED_IN({ name: decodedMe.username }), { variant: 'success' }); toast.success(LL.LOGGED_IN({ name: decodedMe.username }));
} catch (error) { } catch (error) {
setMe(undefined); setMe(undefined);
throw new Error('Failed to parse JWT'); throw new Error('Failed to parse JWT');
@@ -43,29 +45,26 @@ const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
}; };
const refresh = useCallback(async () => { const refresh = useCallback(async () => {
if (!features.security) {
setMe({ admin: true, username: 'admin' });
setInitialized(true);
return;
}
const accessToken = AuthenticationApi.getStorage().getItem(ACCESS_TOKEN); const accessToken = AuthenticationApi.getStorage().getItem(ACCESS_TOKEN);
if (accessToken) { if (accessToken) {
try { await verifyAuthorization()
await AuthenticationApi.verifyAuthorization(); .then(() => {
setMe(AuthenticationApi.decodeMeJWT(accessToken)); setMe(AuthenticationApi.decodeMeJWT(accessToken));
setInitialized(true); setInitialized(true);
} catch (error) { })
.catch(() => {
setMe(undefined); setMe(undefined);
setInitialized(true); setInitialized(true);
} });
} else { } else {
setMe(undefined); setMe(undefined);
setInitialized(true); setInitialized(true);
} }
}, [features]); // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => { useEffect(() => {
refresh(); void refresh();
}, [refresh]); }, [refresh]);
if (initialized) { if (initialized) {

View File

@@ -1,5 +1,5 @@
import { createContext } from 'react'; import { createContext } from 'react';
import { Me } from '../../types'; import type { Me } from 'types';
export interface AuthenticationContextValue { export interface AuthenticationContextValue {
refresh: () => Promise<void>; refresh: () => Promise<void>;

View File

@@ -1,29 +1,13 @@
import { FC, useCallback, useEffect, useState } from 'react'; import { useRequest } from 'alova';
import * as FeaturesApi from '../../api/features';
import { extractErrorMessage, RequiredChildrenProps } from '../../utils';
import { Features } from '../../types';
import { ApplicationError, LoadingSpinner } from '../../components';
import { FeaturesContext } from '.'; 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 FeaturesLoader: FC<RequiredChildrenProps> = (props) => {
const [errorMessage, setErrorMessage] = useState<string>(); const { data: features } = useRequest(FeaturesApi.readFeatures);
const [features, setFeatures] = useState<Features>();
const loadFeatures = useCallback(async () => {
try {
const response = await FeaturesApi.readFeatures();
setFeatures(response.data);
} catch (error) {
setErrorMessage(extractErrorMessage(error, 'Failed to fetch application details.'));
}
}, []);
useEffect(() => {
loadFeatures();
}, [loadFeatures]);
if (features) { if (features) {
return ( return (
@@ -36,12 +20,6 @@ const FeaturesLoader: FC<RequiredChildrenProps> = (props) => {
</FeaturesContext.Provider> </FeaturesContext.Provider>
); );
} }
if (errorMessage) {
return <ApplicationError message={errorMessage} />;
}
return <LoadingSpinner height="100vh" />;
}; };
export default FeaturesLoader; export default FeaturesLoader;

View File

@@ -1,6 +1,6 @@
import { createContext } from 'react'; import { createContext } from 'react';
import { Features } from '../../types'; import type { Features } from 'types';
export interface FeaturesContextValue { export interface FeaturesContextValue {
features: Features; features: Features;

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