mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-05-09 07:25:49 +00:00
Compare commits
822 Commits
v3.7.1
...
b5f4eb6c62
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5f4eb6c62 | ||
|
|
ee4f58ce20 | ||
|
|
0fe0ee77b3 | ||
|
|
74e58aaa3d | ||
|
|
d39d6c7f1f | ||
|
|
4043eaf271 | ||
|
|
73ac60a8b2 | ||
|
|
1d6b283033 | ||
|
|
08ca4e44e8 | ||
|
|
255c173469 | ||
|
|
aeee318cca | ||
|
|
eb14e89c35 | ||
|
|
8411ea6773 | ||
|
|
015110a72e | ||
|
|
dae345f359 | ||
|
|
4cfd9b699c | ||
|
|
bd6371fd9d | ||
|
|
7507596869 | ||
|
|
5d99bd923b | ||
|
|
7402776248 | ||
|
|
8b5cc82df9 | ||
|
|
7c5351f15f | ||
|
|
b29f02e5dd | ||
|
|
e9e7162bcd | ||
|
|
b24aae9123 | ||
|
|
9dbd634322 | ||
|
|
daffc94c7f | ||
|
|
93de0e2f42 | ||
|
|
145172b6e9 | ||
|
|
c4a2f8bac8 | ||
|
|
0c0c928efc | ||
|
|
4d829b0b78 | ||
|
|
01e7d9b027 | ||
|
|
439da1d1e9 | ||
|
|
ac45c17204 | ||
|
|
cd24c7815b | ||
|
|
9665efbf38 | ||
|
|
d8aafdbfd4 | ||
|
|
0c6aef5b60 | ||
|
|
48a1bd0fe6 | ||
|
|
44cfffe8a4 | ||
|
|
e75bf8871e | ||
|
|
22703f4100 | ||
|
|
c066ab8400 | ||
|
|
4a0625e31c | ||
|
|
9aaaba5bb7 | ||
|
|
689a3a9a69 | ||
|
|
391a312f0c | ||
|
|
f782eac0cf | ||
|
|
d88513d789 | ||
|
|
59d07e81d6 | ||
|
|
419fe8ef5d | ||
|
|
4cfcba18ee | ||
|
|
b1d6ab3c96 | ||
|
|
ae26754bc8 | ||
|
|
61c3b47269 | ||
|
|
50bedb2b39 | ||
|
|
13db83a6de | ||
|
|
ec43a07866 | ||
|
|
fbc11b8ef8 | ||
|
|
f1c5a911f9 | ||
|
|
76c0aa6be8 | ||
|
|
61bf2332bb | ||
|
|
39ca956e1f | ||
|
|
0683b77437 | ||
|
|
5da2760dc6 | ||
|
|
3fabaf900f | ||
|
|
b2a8738672 | ||
|
|
c3b9c1ef98 | ||
|
|
aef6b6e92d | ||
|
|
dc46dac02a | ||
|
|
025c430611 | ||
|
|
995ab7233d | ||
|
|
1507989ca3 | ||
|
|
022e808b14 | ||
|
|
9b604e9c78 | ||
|
|
cd3cc09386 | ||
|
|
0df21a7843 | ||
|
|
9225ad2ad9 | ||
|
|
227b1ac59b | ||
|
|
a9a6e32dd1 | ||
|
|
3c4278029f | ||
|
|
3b4e09208e | ||
|
|
e9e0688737 | ||
|
|
7bb1b7bb91 | ||
|
|
4302bc9978 | ||
|
|
60d884df88 | ||
|
|
177c635bc1 | ||
|
|
9a97c28bf0 | ||
|
|
deb87cf5d7 | ||
|
|
a50227638b | ||
|
|
92b1515c8a | ||
|
|
0c5cf0475c | ||
|
|
f26e937514 | ||
|
|
1e4ca8b57f | ||
|
|
4d88bbd28f | ||
|
|
0ce110df9e | ||
|
|
3759fc81ba | ||
|
|
7965ecd856 | ||
|
|
7b0169bb68 | ||
|
|
f10f3d5305 | ||
|
|
ed9e2704b0 | ||
|
|
c47dd0e523 | ||
|
|
80c75bae77 | ||
|
|
cfa973b08b | ||
|
|
83987b71e0 | ||
|
|
a318f34988 | ||
|
|
5cc1660675 | ||
|
|
8a48da38b8 | ||
|
|
d514e67eb8 | ||
|
|
69964482f8 | ||
|
|
2aa691212c | ||
|
|
c27134f185 | ||
|
|
c8033692b1 | ||
|
|
c537d0ab8b | ||
|
|
bee703eb1f | ||
|
|
5d2bd6a2af | ||
|
|
67f0f40a8a | ||
|
|
e796fbef7a | ||
|
|
da7ef04741 | ||
|
|
ddb318dfc6 | ||
|
|
88643dc8e3 | ||
|
|
cf3854563d | ||
|
|
4b2468d616 | ||
|
|
4b08aba9c4 | ||
|
|
0a18add447 | ||
|
|
ca8d23ff3a | ||
|
|
c7e833194f | ||
|
|
f63f658421 | ||
|
|
13fcf09470 | ||
|
|
f560cbd60c | ||
|
|
38ead7e10f | ||
|
|
326bba9b42 | ||
|
|
d9a18bf255 | ||
|
|
6c42cbfb4b | ||
|
|
6691c81956 | ||
|
|
2f95ef305d | ||
|
|
7afde0ce6e | ||
|
|
f3cdafe7d0 | ||
|
|
4bf23e1bda | ||
|
|
aca66457f9 | ||
|
|
121887bdce | ||
|
|
32d7cf4e9c | ||
|
|
3f8227e95e | ||
|
|
10d84261da | ||
|
|
51848d8347 | ||
|
|
1c0669144f | ||
|
|
41a2ba6e5d | ||
|
|
b6fe9e7569 | ||
|
|
faa2c5f1aa | ||
|
|
c71034ff12 | ||
|
|
71be615bbe | ||
|
|
ce53fd1d04 | ||
|
|
1772876f9e | ||
|
|
cd5dbebea9 | ||
|
|
6c67b78a1c | ||
|
|
9b4deb271b | ||
|
|
0e9283af5c | ||
|
|
58011700fe | ||
|
|
079a08ff7b | ||
|
|
b64a55e460 | ||
|
|
2b7ef5b6ba | ||
|
|
d62eef4eca | ||
|
|
0f6d6e69f5 | ||
|
|
97f689b8a7 | ||
|
|
be9b4a070c | ||
|
|
bc15dd4463 | ||
|
|
1613caea86 | ||
|
|
4b39ab76ab | ||
|
|
d04c882590 | ||
|
|
a199bf21e1 | ||
|
|
3ae8722ece | ||
|
|
6a6cef57cf | ||
|
|
090491aab6 | ||
|
|
ca81a02a8c | ||
|
|
f64188bd5d | ||
|
|
d3e0f180c5 | ||
|
|
3f4d87a1d2 | ||
|
|
1d89e651a4 | ||
|
|
fad67b4ef9 | ||
|
|
ce1c22ee35 | ||
|
|
169b5f34ea | ||
|
|
131c03714f | ||
|
|
024c4a0c21 | ||
|
|
b0d111d86f | ||
|
|
faeef9c821 | ||
|
|
60a5b28a21 | ||
|
|
f4b5cf04a0 | ||
|
|
d69f26acac | ||
|
|
2a50701107 | ||
|
|
ab099c45b8 | ||
|
|
47f21019a0 | ||
|
|
5c473c2b3d | ||
|
|
9ddc587334 | ||
|
|
9b0a7a4872 | ||
|
|
97528e9df6 | ||
|
|
b797e1e2bb | ||
|
|
bb52d35c99 | ||
|
|
4c9026e11a | ||
|
|
6cd4e8a5b6 | ||
|
|
dfe037a7d3 | ||
|
|
b87622185d | ||
|
|
0318f8156d | ||
|
|
0c03fa1308 | ||
|
|
2d6e02171f | ||
|
|
2da312bf15 | ||
|
|
52f59a7b1d | ||
|
|
6c8624298c | ||
|
|
ce2d2fb867 | ||
|
|
ba2ad4e175 | ||
|
|
b3320c3e48 | ||
|
|
dc1094b6ba | ||
|
|
bb60568d83 | ||
|
|
67b5c5dd26 | ||
|
|
6866d5b7a9 | ||
|
|
b4e9af89ee | ||
|
|
775ed99b22 | ||
|
|
2ec13273fd | ||
|
|
a846b01103 | ||
|
|
6dffb08545 | ||
|
|
16f7cc148d | ||
|
|
568431ada4 | ||
|
|
6034c1e5eb | ||
|
|
e3566feefb | ||
|
|
ea46c79278 | ||
|
|
a02831e04e | ||
|
|
3b8c973f2a | ||
|
|
2c65936b3e | ||
|
|
bc04c34d58 | ||
|
|
5047f1752e | ||
|
|
1fa7a6c549 | ||
|
|
f9ebe33a7d | ||
|
|
e719dd963d | ||
|
|
c6b0099581 | ||
|
|
71726530c0 | ||
|
|
a749ecb298 | ||
|
|
7e963529c4 | ||
|
|
c76409cf3f | ||
|
|
efd0872690 | ||
|
|
57098b578f | ||
|
|
6472e9e224 | ||
|
|
026828efc7 | ||
|
|
fe6e9be4d3 | ||
|
|
7745a6f9a1 | ||
|
|
c523a379fe | ||
|
|
2854e9cbe9 | ||
|
|
4985f104c7 | ||
|
|
a0ea5f7ea1 | ||
|
|
efc35d0594 | ||
|
|
ccd6c6f8ad | ||
|
|
b426e0eb45 | ||
|
|
c53e1de569 | ||
|
|
8058e98748 | ||
|
|
ba419d09eb | ||
|
|
c701247652 | ||
|
|
12754d1c07 | ||
|
|
9a4daba31a | ||
|
|
a2aa2dccdd | ||
|
|
25af51a8e8 | ||
|
|
ddc597ff03 | ||
|
|
75310afd63 | ||
|
|
3095323c93 | ||
|
|
4667718f12 | ||
|
|
2cb1c5d7e7 | ||
|
|
d7b9754ddb | ||
|
|
99b769626e | ||
|
|
70035b059c | ||
|
|
b252c2f95a | ||
|
|
baa4f2eb39 | ||
|
|
c7b970b5b0 | ||
|
|
3ed5b65191 | ||
|
|
6e01c00d46 | ||
|
|
e72afc9065 | ||
|
|
de2f3e712d | ||
|
|
cacb92cd47 | ||
|
|
3eb20fa700 | ||
|
|
d35574d494 | ||
|
|
3cb29220ab | ||
|
|
d91812ab8f | ||
|
|
856f8efd25 | ||
|
|
d32378ccd4 | ||
|
|
f5006d1a11 | ||
|
|
c3468e6308 | ||
|
|
9f4de56099 | ||
|
|
78738de811 | ||
|
|
e64596ad61 | ||
|
|
024357ae80 | ||
|
|
3f07d3b75f | ||
|
|
cb7c695c67 | ||
|
|
912a764c2d | ||
|
|
c9c0f55b64 | ||
|
|
6991677cf9 | ||
|
|
83330907cd | ||
|
|
3571998da3 | ||
|
|
77465ebe81 | ||
|
|
006e5493e2 | ||
|
|
b29136433d | ||
|
|
0347a4b8b0 | ||
|
|
3330103a8d | ||
|
|
0a02252fee | ||
|
|
642f2116d2 | ||
|
|
7b8e45c2f7 | ||
|
|
0f2244607f | ||
|
|
32ab9dda45 | ||
|
|
b6659b8586 | ||
|
|
5eb85066ef | ||
|
|
9398fc72a0 | ||
|
|
1bcd453e3f | ||
|
|
d405478a13 | ||
|
|
c927e5f496 | ||
|
|
c5dbd7452e | ||
|
|
3a0b4ea587 | ||
|
|
6f4cdb7122 | ||
|
|
b5d6757660 | ||
|
|
0dcde46296 | ||
|
|
ac7e91beff | ||
|
|
9ea1e2752d | ||
|
|
b5471aef94 | ||
|
|
f31329ceff | ||
|
|
40d48f4407 | ||
|
|
11b7e1f86e | ||
|
|
e364a71eda | ||
|
|
e006bebb86 | ||
|
|
fa3d42a1c7 | ||
|
|
e435fd4391 | ||
|
|
d42efb32ab | ||
|
|
ad8f2dc823 | ||
|
|
f2ff14f511 | ||
|
|
e5e9d4c713 | ||
|
|
4c5f93000b | ||
|
|
0c7301a020 | ||
|
|
74c63bf17e | ||
|
|
4564e0b828 | ||
|
|
2ab9607989 | ||
|
|
29d198b46d | ||
|
|
8387ca0c07 | ||
|
|
3796fb8027 | ||
|
|
1da08633ec | ||
|
|
b097e372e4 | ||
|
|
846776929e | ||
|
|
6e1d56b8ee | ||
|
|
32f7eb7299 | ||
|
|
3fc9c3b56c | ||
|
|
e2e46543d2 | ||
|
|
a2b22198ec | ||
|
|
642b59f729 | ||
|
|
9e81de2164 | ||
|
|
d44797db1d | ||
|
|
673ee3f79b | ||
|
|
38a8179544 | ||
|
|
cfb59ac6a0 | ||
|
|
80c26e1adb | ||
|
|
d0de6e8d0f | ||
|
|
68be7d00ff | ||
|
|
d3e6043911 | ||
|
|
373895b36a | ||
|
|
594e10dbe1 | ||
|
|
e3c5b462da | ||
|
|
8a1376b169 | ||
|
|
900e26cf9f | ||
|
|
071e81f29b | ||
|
|
d1bd861ff0 | ||
|
|
f5925dbb3b | ||
|
|
b1eedcb1d8 | ||
|
|
ed7a9f43de | ||
|
|
67885950ef | ||
|
|
74ddb771e9 | ||
|
|
584d0e0b48 | ||
|
|
8d9ca33ea3 | ||
|
|
f0eea1a6a3 | ||
|
|
79cc0377c0 | ||
|
|
115cec08fa | ||
|
|
6df592c2b8 | ||
|
|
f2b81489ba | ||
|
|
0d8760219a | ||
|
|
e8e8d9c130 | ||
|
|
8f712412f5 | ||
|
|
f8ece46163 | ||
|
|
cd8b1add54 | ||
|
|
1c415a9715 | ||
|
|
e1e3601640 | ||
|
|
c2f718b49a | ||
|
|
cee1874689 | ||
|
|
57d172aac2 | ||
|
|
bb26900213 | ||
|
|
9d1ee27533 | ||
|
|
7fd735f667 | ||
|
|
2e79c3a5c6 | ||
|
|
d769999f10 | ||
|
|
bd93d26361 | ||
|
|
72feefe709 | ||
|
|
1d6c2c9664 | ||
|
|
85c78bc8e9 | ||
|
|
18bdcfe050 | ||
|
|
a6f77250b5 | ||
|
|
9874ecde82 | ||
|
|
584b8788be | ||
|
|
7eb15652c7 | ||
|
|
2c28a607ba | ||
|
|
45eca462e7 | ||
|
|
4474868afc | ||
|
|
6c6b5b060d | ||
|
|
c03eb290d1 | ||
|
|
de9bd44071 | ||
|
|
b7458b0686 | ||
|
|
a660ec1afa | ||
|
|
c4f6f01f7e | ||
|
|
9f60560f2b | ||
|
|
7b50f80cb8 | ||
|
|
656d275c56 | ||
|
|
eca17f2b2c | ||
|
|
7f60279aa3 | ||
|
|
5227fafa1b | ||
|
|
4991e2b7cd | ||
|
|
34c514709a | ||
|
|
7dfedfeb10 | ||
|
|
c8bf4cae17 | ||
|
|
2818e268b6 | ||
|
|
7a95c11f62 | ||
|
|
d712b1cce9 | ||
|
|
03fa92352b | ||
|
|
e121fdb47f | ||
|
|
c05793f64f | ||
|
|
3836610d81 | ||
|
|
c3f87cd321 | ||
|
|
4d5a27f45e | ||
|
|
c37c1aaad5 | ||
|
|
110c0df6fb | ||
|
|
04ac3be242 | ||
|
|
44c4ee8bc0 | ||
|
|
57c4d550a3 | ||
|
|
4bcb95eece | ||
|
|
0a92d455c8 | ||
|
|
edb30931ae | ||
|
|
d03ab7a16f | ||
|
|
ea9b6b3e00 | ||
|
|
bae6b600bd | ||
|
|
7eac920985 | ||
|
|
00c2b5992c | ||
|
|
43d2fa1f00 | ||
|
|
92d40d9287 | ||
|
|
7a47a2090f | ||
|
|
0d98491a97 | ||
|
|
16cf16616e | ||
|
|
d9f56ef3ae | ||
|
|
c8934af9bb | ||
|
|
cbacaa98d9 | ||
|
|
f1b6a0baf3 | ||
|
|
4d15f48e2b | ||
|
|
2ffd00e28a | ||
|
|
8ef5be9a7f | ||
|
|
8769faeb83 | ||
|
|
cefbf2d4d6 | ||
|
|
bfd5082054 | ||
|
|
3d3a634d94 | ||
|
|
1cb078cd3c | ||
|
|
22683f5d12 | ||
|
|
57b42aa7c2 | ||
|
|
4a59743024 | ||
|
|
66cec18dee | ||
|
|
ad71938fde | ||
|
|
d4155d6e9e | ||
|
|
af6be4c6b1 | ||
|
|
cfbd0168c3 | ||
|
|
61b9bd7581 | ||
|
|
4c7ad7124e | ||
|
|
0413314cfb | ||
|
|
ab7cbe8ead | ||
|
|
d1264828eb | ||
|
|
76a317b5c0 | ||
|
|
ec11ae2ef7 | ||
|
|
b857c6eb44 | ||
|
|
3f8add73ac | ||
|
|
08b0ddbb7f | ||
|
|
c44cb7e7fd | ||
|
|
77ff61046e | ||
|
|
a8eb06bef2 | ||
|
|
566b5c8ea5 | ||
|
|
eeccd076a0 | ||
|
|
f45ac9d0ef | ||
|
|
cdd9acddfa | ||
|
|
e484f11d12 | ||
|
|
19572f313a | ||
|
|
af9ad5d624 | ||
|
|
8adca69140 | ||
|
|
01710316ed | ||
|
|
ab80c82a22 | ||
|
|
dceafe65a7 | ||
|
|
4734a81fdb | ||
|
|
a2c099e615 | ||
|
|
f9b88a1b6b | ||
|
|
7f2b8cc971 | ||
|
|
582fb3d72f | ||
|
|
bf4fa74742 | ||
|
|
c62b3b9864 | ||
|
|
0ae9795d6b | ||
|
|
7488c31cd3 | ||
|
|
dc0e634004 | ||
|
|
57e7c0ae4f | ||
|
|
7214acfa20 | ||
|
|
ff6d47bb9c | ||
|
|
81971ba53f | ||
|
|
a58f37e3eb | ||
|
|
09a746cf8e | ||
|
|
ea70119138 | ||
|
|
5a9c5b5e2d | ||
|
|
7fb09c5045 | ||
|
|
705171f305 | ||
|
|
400d1a5f1a | ||
|
|
c4855cc5f2 | ||
|
|
1e4b487299 | ||
|
|
cbd883103e | ||
|
|
2ce12943cd | ||
|
|
4151a82b3b | ||
|
|
b871081ef1 | ||
|
|
da51d1d7d9 | ||
|
|
82dae30224 | ||
|
|
1fdac2fdab | ||
|
|
56b23e27d7 | ||
|
|
ba29aa62d3 | ||
|
|
be2342285f | ||
|
|
5595c01221 | ||
|
|
133cddef5b | ||
|
|
0fdba1f84d | ||
|
|
e10ec26e79 | ||
|
|
ffbb397dba | ||
|
|
799076d0c4 | ||
|
|
1fbd10df27 | ||
|
|
4a2f82f1e8 | ||
|
|
d913e4d90b | ||
|
|
0958c29c9e | ||
|
|
36e1c9f79d | ||
|
|
8fedac53dd | ||
|
|
a1c6159fc5 | ||
|
|
5b33acba5e | ||
|
|
4abaef2943 | ||
|
|
ad71773293 | ||
|
|
5b07309939 | ||
|
|
7a044a1dcd | ||
|
|
6507764157 | ||
|
|
7dfa8fc883 | ||
|
|
6df7965bb2 | ||
|
|
02a3dee764 | ||
|
|
d5895f1710 | ||
|
|
2b90ad3f6d | ||
|
|
0bb61b4296 | ||
|
|
2378fb547c | ||
|
|
a79ff3f417 | ||
|
|
4bc93615c5 | ||
|
|
685f0d93e5 | ||
|
|
1d7b6674bb | ||
|
|
014405e451 | ||
|
|
aff3ca3ad3 | ||
|
|
b723d09952 | ||
|
|
bfff842c82 | ||
|
|
ad7d21764d | ||
|
|
f2ae84b004 | ||
|
|
a81956654e | ||
|
|
3cb662799f | ||
|
|
9188d03d61 | ||
|
|
3df2d36453 | ||
|
|
0ab7eb42e4 | ||
|
|
84d4fb37fa | ||
|
|
aa9b38da03 | ||
|
|
8342867807 | ||
|
|
d8cff865da | ||
|
|
096f7e1c88 | ||
|
|
0608d847f5 | ||
|
|
b20360c2a5 | ||
|
|
59b5086cab | ||
|
|
2e3024ab61 | ||
|
|
b5299719da | ||
|
|
2620f56e0d | ||
|
|
20b978c46c | ||
|
|
5c8a18df68 | ||
|
|
3464d6c324 | ||
|
|
eac0cc0521 | ||
|
|
0953d37303 | ||
|
|
1d3fec2a95 | ||
|
|
61b374b7c0 | ||
|
|
c47cc0d5f1 | ||
|
|
939882efbf | ||
|
|
f42cbf548e | ||
|
|
91075ace37 | ||
|
|
de6405f8d1 | ||
|
|
2ffcaf4a9e | ||
|
|
1bda62309b | ||
|
|
83659e5da8 | ||
|
|
a6e136561e | ||
|
|
a75d7487fc | ||
|
|
31b0dd8d58 | ||
|
|
696bd1f455 | ||
|
|
18355efde2 | ||
|
|
d5100134e4 | ||
|
|
b932242e04 | ||
|
|
73ccff3412 | ||
|
|
e5f852a7ed | ||
|
|
581f19462d | ||
|
|
eb59b37251 | ||
|
|
f3696f60cd | ||
|
|
6b4e21f5db | ||
|
|
3d4d5b7bbc | ||
|
|
e6f15681c0 | ||
|
|
5f52a646ff | ||
|
|
be4f9296a5 | ||
|
|
c3181f589c | ||
|
|
872cd40f56 | ||
|
|
30b9de49bf | ||
|
|
8a91c6eb2f | ||
|
|
243471e21d | ||
|
|
b8f97ec94d | ||
|
|
8576a6f253 | ||
|
|
b33e6ceca9 | ||
|
|
8eaf7f32cd | ||
|
|
becdc8cef5 | ||
|
|
651688219c | ||
|
|
b9a4bb3511 | ||
|
|
b318274129 | ||
|
|
8b0e5ba8e7 | ||
|
|
4a9b74b311 | ||
|
|
371b198eb6 | ||
|
|
a6dfdb2c4c | ||
|
|
3122c2b2a9 | ||
|
|
9ac8d149fb | ||
|
|
91e1b0b3b8 | ||
|
|
01636ced88 | ||
|
|
53e587537f | ||
|
|
77eeacf121 | ||
|
|
a89c42d659 | ||
|
|
ba4bc423f4 | ||
|
|
8cd341576d | ||
|
|
006eae5862 | ||
|
|
6e29de4463 | ||
|
|
92d816b990 | ||
|
|
37ad1968b5 | ||
|
|
01793dd4f6 | ||
|
|
9a7f7fa1d5 | ||
|
|
648675d002 | ||
|
|
462d865fc9 | ||
|
|
9f24851948 | ||
|
|
a5e5ec5098 | ||
|
|
db90546bc3 | ||
|
|
2d9ea3ee8d | ||
|
|
4d3cafcf29 | ||
|
|
8685ffb1bf | ||
|
|
86408b3452 | ||
|
|
eab94f3b84 | ||
|
|
9123dbcc9e | ||
|
|
ec6f426b06 | ||
|
|
5482937332 | ||
|
|
0b667703c2 | ||
|
|
c732c96fc2 | ||
|
|
e3d260429c | ||
|
|
77eb2c747b | ||
|
|
6853cd738f | ||
|
|
d58776beab | ||
|
|
94a7b1e438 | ||
|
|
c3f7540f74 | ||
|
|
4642a50f69 | ||
|
|
b23bcf3f0b | ||
|
|
570678e3d3 | ||
|
|
64a2f5eb11 | ||
|
|
24fba8b382 | ||
|
|
9339ef481a | ||
|
|
075789b902 | ||
|
|
1dd1b47faf | ||
|
|
525a164c69 | ||
|
|
b60f333edb | ||
|
|
2323fdfe56 | ||
|
|
9b7fed4d1f | ||
|
|
67c59c9b4b | ||
|
|
b5fea921e6 | ||
|
|
eeb071afc6 | ||
|
|
5669873101 | ||
|
|
d371c9bc82 | ||
|
|
153dd19fc6 | ||
|
|
ae258a75d9 | ||
|
|
37c4be321f | ||
|
|
c810d58064 | ||
|
|
5a27817d11 | ||
|
|
4be2f9283d | ||
|
|
a65162fbbc | ||
|
|
494cf3b6a8 | ||
|
|
b900194402 | ||
|
|
d6e72e72d7 | ||
|
|
960baadeca | ||
|
|
ed92b37869 | ||
|
|
1598809815 | ||
|
|
3131969fc1 | ||
|
|
fb44bc33b9 | ||
|
|
59a806ac8c | ||
|
|
6a2a27e47e | ||
|
|
251d0af028 | ||
|
|
8fa800e2f7 | ||
|
|
df9d20ad88 | ||
|
|
c07754047d | ||
|
|
9c00af317e | ||
|
|
d3d132ec45 | ||
|
|
7adba972e7 | ||
|
|
d83399bd1f | ||
|
|
4471da4aa9 | ||
|
|
b3be1d9351 | ||
|
|
c6b8c2a630 | ||
|
|
3f51c21dc7 | ||
|
|
a8cdbc4fd6 | ||
|
|
95e5babb13 | ||
|
|
74cb23a8bb | ||
|
|
6be304f295 | ||
|
|
e702b0b733 | ||
|
|
bfbd263c74 | ||
|
|
472f922369 | ||
|
|
b13c608ff3 | ||
|
|
5464909121 | ||
|
|
d874b3f808 | ||
|
|
92108bc743 | ||
|
|
66ca1e52bb | ||
|
|
3589094d06 | ||
|
|
801ed6ef79 | ||
|
|
2547ae45a8 | ||
|
|
93e4abe72d | ||
|
|
eb87651c47 | ||
|
|
4138598db2 | ||
|
|
913bbd6e3b | ||
|
|
d35881b05b | ||
|
|
33b54ccf12 | ||
|
|
a8775b2200 | ||
|
|
6d3746222d | ||
|
|
fe169ac80f | ||
|
|
83724e3d44 | ||
|
|
a4db3ef5c4 | ||
|
|
f8adad7865 | ||
|
|
12c094228e | ||
|
|
902ea80807 | ||
|
|
73831d9ac6 | ||
|
|
6bfda79441 | ||
|
|
112de78fc5 | ||
|
|
adbd2381e1 | ||
|
|
397f3f546e | ||
|
|
43d3c28e16 | ||
|
|
747a64b869 | ||
|
|
7c2e5560bd | ||
|
|
9194db9f70 | ||
|
|
fece00c0c6 | ||
|
|
ba3ae5ea56 | ||
|
|
4c69c9e445 | ||
|
|
97925c47fd | ||
|
|
ad89fe15b1 | ||
|
|
29035cabfe | ||
|
|
9b3d43d27f | ||
|
|
0b4f17473a | ||
|
|
b0c29b57c7 | ||
|
|
6d22f6aebf | ||
|
|
3e3e10e6a0 | ||
|
|
b854c777c8 | ||
|
|
b71fdd77e8 | ||
|
|
0f6f7cea19 | ||
|
|
58beb092c2 | ||
|
|
c3f200f73b | ||
|
|
98640c11b1 | ||
|
|
d7904bdcaf | ||
|
|
ce05a94d58 | ||
|
|
c0ed62dc7a | ||
|
|
1557fa98b1 | ||
|
|
81a530f153 | ||
|
|
a4733c3e6a | ||
|
|
7851b8e94c | ||
|
|
36838f7690 | ||
|
|
fdd87d0757 | ||
|
|
c8822aff64 | ||
|
|
4b3205fc9c | ||
|
|
afc05ae9e8 | ||
|
|
9c3044efa0 | ||
|
|
8caeb129c1 | ||
|
|
0427504f0e | ||
|
|
4f11a7caa1 | ||
|
|
150695c185 | ||
|
|
3558591480 | ||
|
|
f7a24052c2 | ||
|
|
75c452486c | ||
|
|
40cab6775c | ||
|
|
392829c7db | ||
|
|
4621c9d616 | ||
|
|
006d664ec9 | ||
|
|
0cc9ac4dd8 | ||
|
|
502096dc22 | ||
|
|
8c424c7a64 | ||
|
|
d7c118b88a | ||
|
|
1fdb0b7516 | ||
|
|
c2fc771756 | ||
|
|
6f759c5bc4 | ||
|
|
facbbf1353 | ||
|
|
a218c7a781 | ||
|
|
5f42709eab | ||
|
|
5ec0f657a0 | ||
|
|
812911ffbb | ||
|
|
55235687ba | ||
|
|
a970009d20 | ||
|
|
4afc16e2cb | ||
|
|
3772d72b43 | ||
|
|
607f949638 | ||
|
|
473cf7c8af | ||
|
|
e0909df06c | ||
|
|
5fc606ef6d | ||
|
|
a3032f4da7 | ||
|
|
7fdd65e8ca | ||
|
|
dc6bf883f1 | ||
|
|
ce5edd93b4 | ||
|
|
e36e6bec9c | ||
|
|
c8fd08b6d2 | ||
|
|
c0d693c1c8 | ||
|
|
5d2a6e2898 | ||
|
|
4547a5ceb0 | ||
|
|
76151c4395 | ||
|
|
481089b1b4 | ||
|
|
463787b7f4 | ||
|
|
e2258a1c43 | ||
|
|
5528f29b6a | ||
|
|
e3861d54c9 | ||
|
|
3368f2803c | ||
|
|
6ca1d68d23 | ||
|
|
cf93081252 | ||
|
|
30fca2a190 |
@@ -1,55 +1,64 @@
|
|||||||
name: 'pre-release'
|
name: 'Build dev release'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
|
paths:
|
||||||
|
- 'src/emsesp_version.h'
|
||||||
branches:
|
branches:
|
||||||
- 'dev'
|
- 'dev'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-release:
|
pre-release:
|
||||||
name: 'Automatic pre-release build'
|
name: 'Build Dev Release'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Enable Corepack
|
|
||||||
run: corepack enable
|
|
||||||
|
|
||||||
- name: Install python 3.11
|
- name: Install python 3.13
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.13'
|
||||||
|
|
||||||
- name: Install Node.js 20
|
- name: Install Node.js 22
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '20.x'
|
node-version: 22
|
||||||
|
|
||||||
- name: Get EMS-ESP version
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Enable Corepack
|
||||||
|
run: corepack enable pnpm
|
||||||
|
|
||||||
|
- name: Get the EMS-ESP version
|
||||||
id: build_info
|
id: build_info
|
||||||
run: |
|
run: |
|
||||||
version=`grep -E '^#define EMSESP_APP_VERSION' ./src/version.h | awk -F'"' '{print $2}'`
|
version=`grep -E '^#define EMSESP_APP_VERSION' ./src/emsesp_version.h | awk -F'"' '{print $2}'`
|
||||||
echo "VERSION=$version" >> $GITHUB_OUTPUT
|
echo "VERSION=$version" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Install PlatformIO
|
- name: Install PlatformIO
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio
|
pip install -U platformio
|
||||||
|
python -m pip install intelhex
|
||||||
|
|
||||||
- name: Build WebUI
|
- name: Build the WebUI
|
||||||
run: |
|
run: |
|
||||||
cd interface
|
cd interface
|
||||||
yarn install
|
pnpm install
|
||||||
yarn typesafe-i18n --no-watch
|
pnpm typesafe-i18n --no-watch
|
||||||
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
|
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
|
||||||
yarn build
|
pnpm build
|
||||||
yarn webUI
|
pnpm webUI
|
||||||
|
|
||||||
- name: Build all PIO target environments from default_envs
|
- name: Build all PIO target environments
|
||||||
run: |
|
run: |
|
||||||
platformio run
|
platformio run
|
||||||
|
env:
|
||||||
|
NO_BUILD_WEBUI: true
|
||||||
|
|
||||||
- name: Create GitHub Release
|
- name: Create GitHub Release
|
||||||
id: 'automatic_releases'
|
id: 'automatic_releases'
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
name: 'github-releases-to-discord'
|
name: 'Publish releases to discord'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
|
|||||||
2
.github/workflows/pr_check.yml
vendored
2
.github/workflows/pr_check.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: 'pr_check'
|
name: 'Pre-check on PR'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|||||||
17
.github/workflows/sonar_check.yml
vendored
17
.github/workflows/sonar_check.yml
vendored
@@ -20,15 +20,12 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
- name: Install Build Wrapper
|
||||||
- name: Install sonar-scanner and build-wrapper
|
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@master
|
||||||
uses: SonarSource/sonarcloud-github-c-cpp@v2
|
- name: Run Build Wrapper
|
||||||
|
run: build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all
|
||||||
- name: Run build-wrapper
|
- name: SonarQube Scan
|
||||||
run: build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all
|
uses: SonarSource/sonarqube-scan-action@master
|
||||||
|
|
||||||
- name: Run sonar-scanner
|
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
run: sonar-scanner --define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json"
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
name: 'tagged-release'
|
name: 'Build stable release'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -8,42 +11,46 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tagged-release:
|
tagged-release:
|
||||||
name: 'Tagged Release'
|
name: 'Build Stable Release'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Enable Corepack
|
- name: Install python 3.13
|
||||||
run: corepack enable
|
|
||||||
|
|
||||||
- name: Install python 3.11
|
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.13'
|
||||||
|
|
||||||
- name: Install Node.js 20
|
- name: Install Node.js 22
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '20.x'
|
node-version: 22
|
||||||
|
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Enable Corepack
|
||||||
|
run: corepack enable pnpm
|
||||||
|
|
||||||
- name: Install PlatformIO
|
- name: Install PlatformIO
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio
|
pip install -U platformio
|
||||||
|
python -m pip install intelhex
|
||||||
|
|
||||||
- name: Build WebUI
|
- name: Build the WebUI
|
||||||
run: |
|
run: |
|
||||||
cd interface
|
cd interface
|
||||||
yarn install
|
pnpm install
|
||||||
yarn typesafe-i18n --no-watch
|
pnpm typesafe-i18n --no-watch
|
||||||
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
|
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
|
||||||
yarn build
|
pnpm build
|
||||||
yarn webUI
|
pnpm webUI
|
||||||
|
|
||||||
- name: Build all PIO target environments from default_envs
|
- name: Build all PIO target environments
|
||||||
run: |
|
run: |
|
||||||
platformio run
|
platformio run
|
||||||
|
env:
|
||||||
|
NO_BUILD_WEBUI: true
|
||||||
|
|
||||||
- name: Create GitHub Release
|
- name: Create GitHub Release
|
||||||
uses: emsesp/action-automatic-releases@v1.0.0
|
uses: emsesp/action-automatic-releases@v1.0.0
|
||||||
23
.github/workflows/stale_issues.yml
vendored
Normal file
23
.github/workflows/stale_issues.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
name: "Mark or close stale issues and PRs"
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "30 1 * * *"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v9
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
days-before-stale: 30
|
||||||
|
days-before-close: 5
|
||||||
|
stale-issue-message: "This issue is stale because it has been open 30 days with no activity. Remove stale label or comment otherwise this will be closed in 5 days."
|
||||||
|
stale-pr-message: "This PR has been automatically marked as stale because there has been no activity in last 30 days. It will be closed if no further activity occurs. Thank you for your contributions."
|
||||||
|
close-issue-message: "This issue was closed because it has been stalled for 5 days with no activity."
|
||||||
|
close-pr-message: "This PR was automatically closed because of being stale."
|
||||||
|
stale-pr-label: "stale"
|
||||||
|
stale-issue-label: "stale"
|
||||||
|
exempt-issue-labels: "bug,enhancement,pinned,security"
|
||||||
|
exempt-pr-labels: "bug,enhancement,pinned,security"
|
||||||
54
.github/workflows/test_release.yml
vendored
54
.github/workflows/test_release.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: 'test-release'
|
name: 'Build test release'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -6,41 +6,60 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- 'dev2'
|
- 'dev2'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-release:
|
pre-release:
|
||||||
name: 'Automatic test-release build'
|
name: 'Build Test Release'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Enable Corepack
|
- name: Install python 3.13
|
||||||
run: corepack enable
|
uses: actions/setup-python@v5
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.13'
|
||||||
- name: Use Node.js 20.x
|
|
||||||
|
- name: Install Node.js 22
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '20.x'
|
node-version: 22
|
||||||
- name: Get EMS-ESP source code and version
|
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Enable Corepack
|
||||||
|
run: corepack enable pnpm
|
||||||
|
|
||||||
|
- name: Get the EMS-ESP version
|
||||||
id: build_info
|
id: build_info
|
||||||
run: |
|
run: |
|
||||||
version=`grep -E '^#define EMSESP_APP_VERSION' ./src/version.h | awk -F'"' '{print $2}'`
|
version=`grep -E '^#define EMSESP_APP_VERSION' ./src/emsesp_version.h | awk -F'"' '{print $2}'`
|
||||||
echo "VERSION=$version" >> $GITHUB_OUTPUT
|
echo "VERSION=$version" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Install PlatformIO
|
- name: Install PlatformIO
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio
|
pip install -U platformio
|
||||||
- name: Build WebUI
|
python -m pip install intelhex
|
||||||
|
|
||||||
|
- name: Build the WebUI
|
||||||
run: |
|
run: |
|
||||||
cd interface
|
cd interface
|
||||||
yarn install
|
pnpm install
|
||||||
yarn typesafe-i18n --no-watch
|
pnpm typesafe-i18n --no-watch
|
||||||
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
|
sed -i "s/= 'pl'/= 'en'/" ./src/i18n/i18n-util.ts
|
||||||
yarn build
|
pnpm build
|
||||||
yarn webUI
|
pnpm webUI
|
||||||
- name: Build all target environments from default_envs
|
|
||||||
|
- name: Build all target environments
|
||||||
run: |
|
run: |
|
||||||
platformio run
|
platformio run
|
||||||
|
env:
|
||||||
|
NO_BUILD_WEBUI: true
|
||||||
|
|
||||||
- name: Create GitHub Release
|
- name: Create GitHub Release
|
||||||
id: 'automatic_releases'
|
id: 'automatic_releases'
|
||||||
uses: emsesp/action-automatic-releases@v1.0.0
|
uses: emsesp/action-automatic-releases@v1.0.0
|
||||||
@@ -52,3 +71,4 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
CHANGELOG_LATEST.md
|
CHANGELOG_LATEST.md
|
||||||
./build/firmware/*.*
|
./build/firmware/*.*
|
||||||
|
|
||||||
|
|||||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -12,17 +12,15 @@ cppcheck.out.xml
|
|||||||
# platformio
|
# platformio
|
||||||
.pio
|
.pio
|
||||||
pio_local.ini
|
pio_local.ini
|
||||||
*_old
|
|
||||||
|
|
||||||
# OS specific
|
# OS specific
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*Thumbs.db
|
*Thumbs.db
|
||||||
|
|
||||||
# web specfic
|
# web specific
|
||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
/data/www
|
/data/www
|
||||||
/lib/framework/WWWData.h
|
|
||||||
/interface/build
|
/interface/build
|
||||||
node_modules
|
node_modules
|
||||||
/interface/.eslintcache
|
/interface/.eslintcache
|
||||||
@@ -30,11 +28,10 @@ stats.html
|
|||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
.pnp.*
|
.pnp.*
|
||||||
*/.yarn/cache/*
|
|
||||||
*/.yarn/install-state.gz
|
|
||||||
analyse.html
|
analyse.html
|
||||||
interface/vite.config.ts.timestamp*
|
interface/vite.config.ts.timestamp*
|
||||||
*.local
|
*.local
|
||||||
|
src/ESP32React/WWWData.h
|
||||||
|
|
||||||
# i18n generated files
|
# i18n generated files
|
||||||
interface/src/i18n/i18n-react.tsx
|
interface/src/i18n/i18n-react.tsx
|
||||||
@@ -66,3 +63,12 @@ words-found-verbose.txt
|
|||||||
|
|
||||||
# sonarlint
|
# sonarlint
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
|
||||||
|
# pioarduino + hybrid
|
||||||
|
managed_components
|
||||||
|
dependencies.lock
|
||||||
|
CMakeLists.txt
|
||||||
|
.dummy/*
|
||||||
|
logs/*
|
||||||
|
sdkconfig.*
|
||||||
|
sdkconfig_tasmota_esp32
|
||||||
|
|||||||
71
CHANGELOG.md
71
CHANGELOG.md
@@ -5,6 +5,77 @@ 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.7.2] 22 March 2025
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- change enum_heatingtype for remote control [#2268](https://github.com/emsesp/EMS-ESP32/issues/2268)
|
||||||
|
- system service commands [#2182](https://github.com/emsesp/EMS-ESP32/issues/2182)
|
||||||
|
- read 0x02A5 for thermostat CT200 [#2277](https://github.com/emsesp/EMS-ESP32/issues/2277)
|
||||||
|
- add "duplicate" option to Custom Entities [#2266](https://github.com/emsesp/EMS-ESP32/discussion/2266)
|
||||||
|
- mask bits for bool custom entities
|
||||||
|
- thermostat `reduce threshold` [#2288](https://github.com/emsesp/EMS-ESP32/issues/2288)
|
||||||
|
- thermostat `absent` [#1957](https://github.com/emsesp/EMS-ESP32/issues/1957)
|
||||||
|
- CR11 thermostat [#2295](https://github.com/emsesp/EMS-ESP32/issues/2295)
|
||||||
|
- Show ESP32's CPU temp in Hardware Status
|
||||||
|
- vacation mode for the CR50 [#2403](https://github.com/emsesp/EMS-ESP32/issues/2403)
|
||||||
|
- new Console command "set admin password" to set WebUI admin password
|
||||||
|
- support nested conditions in scheduler [#2451](https://github.com/emsesp/EMS-ESP32/issues/2451)
|
||||||
|
- allow mixed case in scheduler expressions [#2457](https://github.com/emsesp/EMS-ESP32/issues/2457)
|
||||||
|
- Suprapur-o [#2470](https://github.com/emsesp/EMS-ESP32/issues/2470)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- long numbers of custom entities [#2267](https://github.com/emsesp/EMS-ESP32/issues/2267)
|
||||||
|
- modbus command path to `api/` [#2276](https://github.com/emsesp/EMS-ESP32/issues/2276)
|
||||||
|
- info command for devices without entity-commands [#2274](https://github.com/emsesp/EMS-ESP32/issues/2274)
|
||||||
|
- CW100 settings telegram 0x241 [#2290](https://github.com/emsesp/EMS-ESP32/issues/2290)
|
||||||
|
- modbus signed 8bit values [#2294](https://github.com/emsesp/EMS-ESP32/issues/2294)
|
||||||
|
- thermostat date [#2313](https://github.com/emsesp/EMS-ESP32/issues/2313)
|
||||||
|
- Updated unknown compressor stati "enum_hpactivity" [#2311](https://github.com/emsesp/EMS-ESP32/pull/2311)
|
||||||
|
- Underline Tab headers in WebUI
|
||||||
|
- console unit tests fixed due to changed shell output
|
||||||
|
- tx-queue overflow in some heatpump systems [#2455](https://github.com/emsesp/EMS-ESP32/issues/2455)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- show operation in pretty telegram between src and dst [#2263](https://github.com/emsesp/EMS-ESP32/discussions/2263)
|
||||||
|
- update eModbus to 1.7.2 [#2254](https://github.com/emsesp/EMS-ESP32/issues/2254)
|
||||||
|
- modbus timeout default to 300 sec, change setting from ms to sec [#2254](https://github.com/emsesp/EMS-ESP32/issues/2254)
|
||||||
|
- update AsyncTCP and ESPAsyncWebServer to latest versions
|
||||||
|
- update Arduino pio platform to 3.10.0 and optimized flash using build flags
|
||||||
|
- Version checker in WebUI improved
|
||||||
|
- rename `remoteseltemp` to `cooltemp` [#2456](https://github.com/emsesp/EMS-ESP32/issues/2456)
|
||||||
|
|
||||||
|
## [3.7.1] 29 November 2024
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- include HA "unit_of_meas", "stat_cla" and "dev_cla" attributes for Number sensors [#2149](https://github.com/emsesp/EMS-ESP32/issues/2149)
|
||||||
|
- Bosch CS6800i AW - Silent Mode + Electrical Power Reduction (HP) [#2147](https://github.com/emsesp/EMS-ESP32/issues/2147)
|
||||||
|
- `/api/system/showeralert` and `/api/system/showertimer` [#2182](https://github.com/emsesp/EMS-ESP32/issues/2182)
|
||||||
|
- MX400 [#2198](https://github.com/emsesp/EMS-ESP32/issues/2198)
|
||||||
|
- SM200 values [#2212](https://github.com/emsesp/EMS-ESP32/discussions/2212)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- Modbus integration in 3.7.0 missing offset [#2148](https://github.com/emsesp/EMS-ESP32/issues/2148)
|
||||||
|
- fix changing TZ in NTPsettings without clearing enable+server, added DST support [#2142](https://github.com/emsesp/EMS-ESP32/issues/2142)
|
||||||
|
- Support MQTT Discovery (AD) with Domoticz [#2177](https://github.com/emsesp/EMS-ESP32/issues/2177)
|
||||||
|
- wwExtra (dhw extra) changed from temperature reading to number
|
||||||
|
- auxheaterstatus [#2192](https://github.com/emsesp/EMS-ESP32/issues/2192)
|
||||||
|
- lastCode character check [#2189](https://github.com/emsesp/EMS-ESP32/issues/2189)
|
||||||
|
- reading too many telegram parts
|
||||||
|
- heatpump cost UOMs [#2188](https://github.com/emsesp/EMS-ESP32/issues/2188)
|
||||||
|
- analog dac output and inputs on dac pins [#2201](https://github.com/emsesp/EMS-ESP32/discussions/2201)
|
||||||
|
- api memory leak [#2216](https://github.com/emsesp/EMS-ESP32/issues/2216)
|
||||||
|
- modbus multiple mixers [#2229](https://github.com/emsesp/EMS-ESP32/issues/2229)
|
||||||
|
- Last Will (LWT) not set on MQTT Connect [#2247](https://github.com/emsesp/EMS-ESP32/issues/2247)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- name of wwstarts2 [#2217](https://github.com/emsesp/EMS-ESP32/discussions/2217)
|
||||||
|
|
||||||
## [3.7.0] 27 October 2024
|
## [3.7.0] 27 October 2024
|
||||||
|
|
||||||
## **IMPORTANT! BREAKING CHANGES with 3.6.5**
|
## **IMPORTANT! BREAKING CHANGES with 3.6.5**
|
||||||
|
|||||||
@@ -2,33 +2,54 @@
|
|||||||
|
|
||||||
For more details go to [docs.emsesp.org](https://docs.emsesp.org/).
|
For more details go to [docs.emsesp.org](https://docs.emsesp.org/).
|
||||||
|
|
||||||
## [3.7.1]
|
## [3.7.3]
|
||||||
|
|
||||||
## **IMPORTANT! BREAKING CHANGES since v3.7.0**
|
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
- include HA "unit_of_meas", "stat_cla" and "dev_cla" attributes for Number sensors [#2149](https://github.com/emsesp/EMS-ESP32/issues/2149)
|
- analogsensor types: NTC and RGB-Led
|
||||||
- Bosch CS6800i AW - Silent Mode + Electrical Power Reduction (HP) [#2147](https://github.com/emsesp/EMS-ESP32/issues/2147)
|
- Flag for HMC310 [#2465](https://github.com/emsesp/EMS-ESP32/issues/2465)
|
||||||
- `/api/system/showeralert` and `/api/system/showertimer` [#2182](https://github.com/emsesp/EMS-ESP32/issues/2182)
|
- boiler auxheatersource [#2489](https://github.com/emsesp/EMS-ESP32/discussions/2489)
|
||||||
- MX400 [#2198](https://github.com/emsesp/EMS-ESP32/issues/2198)
|
- thermostat last error for RC100/300 [#2501](https://github.com/emsesp/EMS-ESP32/issues/2501)
|
||||||
- SM200 values [#2212](https://github.com/emsesp/EMS-ESP32/discussions/2212)
|
- boiler 0xC6 telegram [#1963](https://github.com/emsesp/EMS-ESP32/issues/1963)
|
||||||
|
- CS6800i changes [#2448](https://github.com/emsesp/EMS-ESP32/issues/2448), [#2449](https://github.com/emsesp/EMS-ESP32/issues/2449)
|
||||||
|
- charging pump [#2544](https://github.com/emsesp/EMS-ESP32/issues/2544)
|
||||||
|
- hybrid CSH5800iG [#2569](https://github.com/emsesp/EMS-ESP32/issues/2569)
|
||||||
|
- add EMS Device details to Home Assistant MQTT Discovery
|
||||||
|
- disinfection command [#2601](https://github.com/emsesp/EMS-ESP32/issues/2601)
|
||||||
|
- added new board profile for upcoming BBQKees E32V2.2
|
||||||
|
- set differential pressure entity in Mixer device
|
||||||
|
- set set climate action cooling/heating in HA [#2583](https://github.com/emsesp/EMS-ESP32/issues/2583)
|
||||||
|
- Internal sensors of E32V2_2
|
||||||
|
- FW200 display options [#2610](https://github.com/emsesp/EMS-ESP32/discussions/2610)
|
||||||
|
- CR11 mode settings OFF/MANUAL depends on selTemp [#2437](https://github.com/emsesp/EMS-ESP32/issues/2437)
|
||||||
|
- Fuse settings for BBQKees boards
|
||||||
|
- Analogsensors for pulse output [#2624](https://github.com/emsesp/EMS-ESP32/discussions/2624)
|
||||||
|
- Analogsensors frequency input [#2631](https://github.com/emsesp/EMS-ESP32/discussions/2631)
|
||||||
|
- SRC plus thermostats [#2636](https://github.com/emsesp/EMS-ESP32/issues/2636)
|
||||||
|
- Greenstar 2000 [#2645](https://github.com/emsesp/EMS-ESP32/issues/2645)
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
- Modbus integration in 3.7.0 missing offset [#2148](https://github.com/emsesp/EMS-ESP32/issues/2148)
|
- dhw/switchtime [#2490](https://github.com/emsesp/EMS-ESP32/issues/2490)
|
||||||
- fix changing TZ in NTPsettings without clearing enable+server, added DST support [#2142](https://github.com/emsesp/EMS-ESP32/issues/2142)
|
- switch to secure mqtt [#2492](https://github.com/emsesp/EMS-ESP32/issues/2492)
|
||||||
- Support MQTT Discovery (AD) with Domoticz [#2177](https://github.com/emsesp/EMS-ESP32/issues/2177)
|
- update link buttons [#2497](https://github.com/emsesp/EMS-ESP32/issues/2497)
|
||||||
- wwExtra (dhw extra) changed from temperature reading to number
|
- refresh scheduler states [#2502](https://github.com/emsesp/EMS-ESP32/discussions/2502)
|
||||||
- auxheaterstatus [#2192](https://github.com/emsesp/EMS-ESP32/issues/2192)
|
- also rebuild HA config on mqtt connect for scheduler, custom and shower
|
||||||
- lastCode character check [#2189](https://github.com/emsesp/EMS-ESP32/issues/2189)
|
- FB100 controls the hc, not the master [#2510](https://github.com/emsesp/EMS-ESP32/issues/2510)
|
||||||
- reading too many telegram parts
|
- IPM DHW module, [#2524](https://github.com/emsesp/EMS-ESP32/issues/2524)
|
||||||
- heatpump cost UOMs [#2188](https://github.com/emsesp/EMS-ESP32/issues/2188)
|
- charge optimization [#2543](https://github.com/emsesp/EMS-ESP32/issues/2543)
|
||||||
- analog dac output and inputs on dac pins [#2201](https://github.com/emsesp/EMS-ESP32/discussions/2201)
|
- shower active state retained, shows correctly in HA
|
||||||
- api memory leak [#2216](https://github.com/emsesp/EMS-ESP32/issues/2216)
|
- MQTT Command Topic with slashes [#2571](https://github.com/emsesp/EMS-ESP32/issues/2571)
|
||||||
- modbus multiple mixers [#2229](https://github.com/emsesp/EMS-ESP32/issues/2229)
|
- Add pulsed water meter input to V1.3 gateway with Lilygo S3 [#2550](https://github.com/emsesp/EMS-ESP32/issues/2550)
|
||||||
- Last Will (LWT) not set on MQTT Connect [#2247](https://github.com/emsesp/EMS-ESP32/issues/2247)
|
- fix missing long 10-second press of Button to perform a factory reset
|
||||||
|
- fix wwMaxPower on Junkers ZBS14 [#2609](https://github.com/emsesp/EMS-ESP32/issues/2609)
|
||||||
|
- ventilation bypass state from telegram 0x55C [#1197](https://github.com/emsesp/EMS-ESP32/issues/1197)
|
||||||
|
- set selflowtemp for ems+ boilers [#2641](https://github.com/emsesp/EMS-ESP32/discussions/2641)
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
- name of wwstarts2 [#2217](https://github.com/emsesp/EMS-ESP32/discussions/2217)
|
- show console log with ISO date/time [#2533](https://github.com/emsesp/EMS-ESP32/discussions/2533)
|
||||||
|
- remove ESP32 CPU temperature
|
||||||
|
- updated core libraries like AsyncTCP, AsyncWebServer and Modbus
|
||||||
|
- remove command `scan deep`
|
||||||
|
- ignore repeated `forceheatingoff` commands [#2641](https://github.com/emsesp/EMS-ESP32/discussions/2641)
|
||||||
|
|||||||
48
Makefile
48
Makefile
@@ -16,13 +16,23 @@ T := $(shell $(MAKE) $(MAKECMDGOALS) --no-print-directory \
|
|||||||
ECHO="COUNTTHIS" | grep -c "COUNTTHIS")
|
ECHO="COUNTTHIS" | grep -c "COUNTTHIS")
|
||||||
N := x
|
N := x
|
||||||
C = $(words $N)$(eval N := x $N)
|
C = $(words $N)$(eval N := x $N)
|
||||||
ECHO = python $(I)/echo_progress.py --stepno=$C --nsteps=$T
|
ECHO = python3 $(I)/scripts/echo_progress.py --stepno=$C --nsteps=$T
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# number of parallel compiles
|
# determine number of parallel compiles based on OS
|
||||||
JOBS ?= $(shell nproc)
|
UNAME_S := $(shell uname -s)
|
||||||
|
ifeq ($(UNAME_S),Linux)
|
||||||
|
EXTRA_CPPFLAGS = -D LINUX
|
||||||
|
JOBS ?= $(shell nproc)
|
||||||
|
endif
|
||||||
|
ifeq ($(UNAME_S),Darwin)
|
||||||
|
EXTRA_CPPFLAGS = -D OSX -Wno-tautological-constant-out-of-range-compare
|
||||||
|
JOBS ?= $(shell sysctl -n hw.ncpu)
|
||||||
|
endif
|
||||||
MAKEFLAGS += -j $(JOBS) -l $(JOBS)
|
MAKEFLAGS += -j $(JOBS) -l $(JOBS)
|
||||||
|
|
||||||
|
# $(info Number of jobs: $(JOBS))
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# Project Structure
|
# Project Structure
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@@ -32,26 +42,20 @@ MAKEFLAGS += -j $(JOBS) -l $(JOBS)
|
|||||||
# INCLUDES is a list of directories containing header files
|
# INCLUDES is a list of directories containing header files
|
||||||
# LIBRARIES is a list of directories containing libraries, this must be the top level containing include and lib
|
# LIBRARIES is a list of directories containing libraries, this must be the top level containing include and lib
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
#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 lib/espMqttClient/src lib/espMqttClient/src/*
|
SOURCES := src/core src/devices src/web src/test lib_standalone lib/semver lib/espMqttClient/src lib/espMqttClient/src/* lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/PButton
|
||||||
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
|
INCLUDES := src/core src/devices src/web src/test lib/* lib_standalone lib/semver 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
|
||||||
LIBRARIES :=
|
LIBRARIES :=
|
||||||
|
|
||||||
CPPCHECK = cppcheck
|
CPPCHECK = cppcheck
|
||||||
# CHECKFLAGS = -q --force --std=c++17
|
CHECKFLAGS = -q --force --std=gnu++17
|
||||||
CHECKFLAGS = -q --force --std=c++11
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# Languages Standard
|
# Languages Standard
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
C_STANDARD := -std=c17
|
C_STANDARD := -std=c17
|
||||||
CXX_STANDARD := -std=gnu++14
|
CXX_STANDARD := -std=gnu++17
|
||||||
|
|
||||||
# C_STANDARD := -std=c11
|
|
||||||
# CXX_STANDARD := -std=c++11
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# Defined Symbols
|
# Defined Symbols
|
||||||
@@ -60,7 +64,7 @@ DEFINES += -DARDUINOJSON_ENABLE -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSO
|
|||||||
DEFINES += -DEMSESP_STANDALONE -DEMSESP_TEST -DEMSESP_DEBUG -DEMC_RX_BUFFER_SIZE=1500
|
DEFINES += -DEMSESP_STANDALONE -DEMSESP_TEST -DEMSESP_DEBUG -DEMC_RX_BUFFER_SIZE=1500
|
||||||
DEFINES += $(ARGS)
|
DEFINES += $(ARGS)
|
||||||
|
|
||||||
DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.7.1-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S3\"
|
DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.7.3-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32S3\"
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# Sources & Files
|
# Sources & Files
|
||||||
@@ -94,14 +98,16 @@ CXX := /usr/bin/g++
|
|||||||
# LDFLAGS Linker Flags
|
# LDFLAGS Linker Flags
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
CPPFLAGS += $(DEFINES) $(DEFAULTS) $(INCLUDE)
|
CPPFLAGS += $(DEFINES) $(DEFAULTS) $(INCLUDE)
|
||||||
CPPFLAGS += -ggdb
|
CPPFLAGS += -ggdb -g3 -MMD
|
||||||
CPPFLAGS += -g3
|
CPPFLAGS += -flto=auto -fno-lto
|
||||||
CPPFLAGS += -Os
|
CPPFLAGS += -Wall -Wextra -Werror -Wswitch-enum
|
||||||
|
CPPFLAGS += -Wno-unused-parameter -Wno-missing-braces -Wno-vla-cxx-extension
|
||||||
|
|
||||||
|
CPPFLAGS += $(EXTRA_CPPFLAGS)
|
||||||
|
|
||||||
CFLAGS += $(CPPFLAGS)
|
CFLAGS += $(CPPFLAGS)
|
||||||
CFLAGS += -Wall -Wextra -Werror -Wswitch-enum
|
CXXFLAGS += $(CPPFLAGS)
|
||||||
CFLAGS += -Wno-tautological-constant-out-of-range-compare -Wno-unused-parameter -Wno-inconsistent-missing-override -Wno-missing-braces -Wno-unused-lambda-capture -Wno-sign-compare
|
LDFLAGS =
|
||||||
CXXFLAGS += $(CFLAGS) -MMD
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# Compiler & Linker Commands
|
# Compiler & Linker Commands
|
||||||
@@ -142,7 +148,7 @@ COMPILE.cpp = $(CXX) $(CXX_STANDARD) $(CXXFLAGS) $(DEPFLAGS) -c $< -o $@
|
|||||||
.SILENT: $(OUTPUT)
|
.SILENT: $(OUTPUT)
|
||||||
|
|
||||||
all: $(OUTPUT)
|
all: $(OUTPUT)
|
||||||
@$(ECHO) All done
|
@$(ECHO) Build complete.
|
||||||
|
|
||||||
$(OUTPUT): $(OBJS)
|
$(OUTPUT): $(OBJS)
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ It requires a small circuit to interface with the EMS bus which can be purchased
|
|||||||
|
|
||||||
## 🚀 **Installing**
|
## 🚀 **Installing**
|
||||||
|
|
||||||
Head over to [download.emsesp.org](https://download.emsesp.org) for instructions on how to install EMS-ESP. There is also further details on which boards are supported in [this section](https://docs.emsesp.org/Getting-Started/#first-time-install) of the documentation.
|
Head over to [download.emsesp.org](https://download.emsesp.org) for instructions on how to install EMS-ESP. There is also further details on which boards are supported in [this section](https://docs.emsesp.org/Installing/) of the documentation.
|
||||||
|
|
||||||
## 📋 **Documentation**
|
## 📋 **Documentation**
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ If you like **EMS-ESP**, please give it a ✨ on GitHub, or even better fork it
|
|||||||
- [uuid-\*](https://github.com/nomis/mcu-uuid-console) from @nomis. The console, syslog, telnet and logging are based off these awesome open source libraries
|
- [uuid-\*](https://github.com/nomis/mcu-uuid-console) from @nomis. The console, syslog, telnet and logging are based off these awesome open source libraries
|
||||||
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson) for all the JSON processing
|
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson) for all the JSON processing
|
||||||
- [espMqttClient](https://github.com/bertmelis/espMqttClient) for the MQTT client
|
- [espMqttClient](https://github.com/bertmelis/espMqttClient) for the MQTT client
|
||||||
- ESPAsyncWebServer and AsyncTCP for the Web server and TCP backends, with custom modifications for performance
|
- [ESPAsyncWebServer](https://github.com/ESP32Async/ESPAsyncWebServer) and [AsyncTCP](https://github.com/ESP32Async/AsyncTCP) for the Web server and TCP backends
|
||||||
|
|
||||||
## 📜 **License**
|
## 📜 **License**
|
||||||
|
|
||||||
|
|||||||
45
boards/c3_mini_4M.json
Normal file
45
boards/c3_mini_4M.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32c3_out.ld"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DTASMOTA_SDK",
|
||||||
|
"-DARDUINO_LOLIN_C3_MINI",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "160000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [
|
||||||
|
[
|
||||||
|
"0X303A",
|
||||||
|
"0x1001"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"mcu": "esp32c3",
|
||||||
|
"variant": "lolin_c3_mini"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32c3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "WEMOS LOLIN C3 Mini",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "4MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 4194304,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"url": "https://www.wemos.cc/en/latest/c3/c3_mini.html",
|
||||||
|
"vendor": "WEMOS"
|
||||||
|
}
|
||||||
34
boards/esp32dev.json
Normal file
34
boards/esp32dev.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"core": "esp32",
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "40000000L",
|
||||||
|
"flash_mode": "dio",
|
||||||
|
"mcu": "esp32",
|
||||||
|
"variant": "esp32"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi",
|
||||||
|
"ethernet"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_board": "esp32.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Espressif ESP32 Dev Module",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"speed": 230400
|
||||||
|
},
|
||||||
|
"url": "https://en.wikipedia.org/wiki/ESP32",
|
||||||
|
"vendor": "Espressif"
|
||||||
|
}
|
||||||
47
boards/s2_4M_P.json
Normal file
47
boards/s2_4M_P.json
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s2_out.ld"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DBOARD_HAS_PSRAM",
|
||||||
|
"-DTASMOTA_SDK",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
|
"-DARDUINO_USB_MODE=0"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "dio",
|
||||||
|
"hwids": [
|
||||||
|
[
|
||||||
|
"0X303A",
|
||||||
|
"0x80C2"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"mcu": "esp32s2",
|
||||||
|
"variant": "lolin_s2_mini"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32s2.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "WEMOS LOLIN S2 Mini",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "4MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 4194304,
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"wait_for_upload_port": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://www.wemos.cc/en/latest/s2/s2_mini.html",
|
||||||
|
"vendor": "WEMOS"
|
||||||
|
}
|
||||||
44
boards/s3_16M_P.json
Normal file
44
boards/s3_16M_P.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s3_out.ld",
|
||||||
|
"memory_type": "qio_opi"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DBOARD_HAS_PSRAM",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "esp32s3"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Espressif ESP32-S3 16M Flash OPI PSRAM, 4608KB Code/OTA, 2MB FS",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"speed": 230400
|
||||||
|
},
|
||||||
|
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/",
|
||||||
|
"vendor": "Espressif"
|
||||||
|
}
|
||||||
37
boards/s3_32M_P.json
Normal file
37
boards/s3_32M_P.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino":{
|
||||||
|
"memory_type": "opi_opi"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": "-DBOARD_HAS_PSRAM",
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "opi",
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "esp32s3"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Espressif ESP32-S3 32M Flash OPI PSRAM, 4608KB Code/OTA, 2MB FS",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "32MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"speed": 230400
|
||||||
|
},
|
||||||
|
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/",
|
||||||
|
"vendor": "Espressif"
|
||||||
|
}
|
||||||
35
boards/s_16M.json
Normal file
35
boards/s_16M.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": "-DTASMOTA_SDK",
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "40000000L",
|
||||||
|
"flash_mode": "dio",
|
||||||
|
"mcu": "esp32",
|
||||||
|
"variant": "esp32"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi",
|
||||||
|
"ethernet"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Espressif ESP32 16M Flash, 4608KB Code/OTA, 2MB FS",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"speed": 230400
|
||||||
|
},
|
||||||
|
"url": "https://en.wikipedia.org/wiki/ESP32",
|
||||||
|
"vendor": "Espressif"
|
||||||
|
}
|
||||||
35
boards/s_16M_P.json
Normal file
35
boards/s_16M_P.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": "-DBOARD_HAS_PSRAM",
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "dio",
|
||||||
|
"mcu": "esp32",
|
||||||
|
"variant": "esp32"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi",
|
||||||
|
"ethernet"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Espressif ESP32 16M Flash DIO PSRAM, 4608KB Code/OTA, 2MB FS",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"speed": 230400
|
||||||
|
},
|
||||||
|
"url": "https://en.wikipedia.org/wiki/ESP32",
|
||||||
|
"vendor": "Espressif"
|
||||||
|
}
|
||||||
34
boards/s_4M.json
Normal file
34
boards/s_4M.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": "-DTASMOTA_SDK",
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "40000000L",
|
||||||
|
"flash_mode": "dio",
|
||||||
|
"mcu": "esp32",
|
||||||
|
"variant": "esp32"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Tasmota ESP32 4M Flash, 4608KB Code/OTA, 2MB FS",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "4MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 4194304,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"speed": 230400
|
||||||
|
},
|
||||||
|
"url": "https://en.wikipedia.org/wiki/ESP32",
|
||||||
|
"vendor": "Espressif"
|
||||||
|
}
|
||||||
48
boards/seeed_xiao_esp32c6.json
Normal file
48
boards/seeed_xiao_esp32c6.json
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DARDUINO_XIAO_ESP32C6",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "160000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [
|
||||||
|
[
|
||||||
|
"0x2886",
|
||||||
|
"0x0046"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"0x303a",
|
||||||
|
"0x1001"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"mcu": "esp32c6",
|
||||||
|
"variant": "XIAO_ESP32C6"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi",
|
||||||
|
"bluetooth",
|
||||||
|
"zigbee",
|
||||||
|
"thread"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32c6.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"espidf"
|
||||||
|
],
|
||||||
|
"name": "Seeed Studio XIAO ESP32C6",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "4MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 4194304,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 460800
|
||||||
|
},
|
||||||
|
"url": "https://wiki.seeedstudio.com/XIAO_ESP32C6_Getting_Started/",
|
||||||
|
"vendor": "Seeed Studio"
|
||||||
|
}
|
||||||
@@ -28,6 +28,11 @@
|
|||||||
"**/i18n/**",
|
"**/i18n/**",
|
||||||
"/project-words.txt",
|
"/project-words.txt",
|
||||||
"Makefile",
|
"Makefile",
|
||||||
"src/modbus_entity_parameters.hpp"
|
"**/*.ini",
|
||||||
|
"**/*.json",
|
||||||
|
"src/core/modbus_entity_parameters.hpp",
|
||||||
|
"sdkconfig.*",
|
||||||
|
"managed_components/**",
|
||||||
|
"pnpm-*.yaml"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -13,9 +13,9 @@ telegram_type_id,name,is_fetched
|
|||||||
0x19,UBAMonitorSlow,
|
0x19,UBAMonitorSlow,
|
||||||
0x1A,UBASetPoints,
|
0x1A,UBASetPoints,
|
||||||
0x1C,UBAMaintenanceStatus,
|
0x1C,UBAMaintenanceStatus,
|
||||||
0x1E,WM10TempMessage,
|
0x1E,HydrTemp,
|
||||||
0x23,JunkersSetMixer,fetched
|
0x23,JunkersSetMixer,fetched
|
||||||
0x26,UBASettingsWW,fetched
|
0x27,UBASettingsWW,fetched
|
||||||
0x28,WeatherComp,fetched
|
0x28,WeatherComp,fetched
|
||||||
0x2A,MC110Status,
|
0x2A,MC110Status,
|
||||||
0x2E,Meters,
|
0x2E,Meters,
|
||||||
@@ -29,7 +29,7 @@ telegram_type_id,name,is_fetched
|
|||||||
0x3B,Energy,
|
0x3B,Energy,
|
||||||
0x3D,RC35Set,
|
0x3D,RC35Set,
|
||||||
0x3E,RC35Monitor,
|
0x3E,RC35Monitor,
|
||||||
0x3F,RC30Timer,
|
0x3F,RC35Timer,
|
||||||
0x40,RC30Temp,
|
0x40,RC30Temp,
|
||||||
0x41,RC30Monitor,
|
0x41,RC30Monitor,
|
||||||
0x42,RC35Timer2,
|
0x42,RC35Timer2,
|
||||||
@@ -62,7 +62,9 @@ telegram_type_id,name,is_fetched
|
|||||||
0xB1,RC10Monitor,
|
0xB1,RC10Monitor,
|
||||||
0xBB,HybridSettings,fetched
|
0xBB,HybridSettings,fetched
|
||||||
0xBF,ErrorMessage,
|
0xBF,ErrorMessage,
|
||||||
|
0xC0,RCErrorMessage,
|
||||||
0xC2,UBAErrorMessage3,
|
0xC2,UBAErrorMessage3,
|
||||||
|
0xC6,UBAErrorMessage3,
|
||||||
0xD1,UBAOutdoorTemp,
|
0xD1,UBAOutdoorTemp,
|
||||||
0xE3,UBAMonitorSlowPlus2,
|
0xE3,UBAMonitorSlowPlus2,
|
||||||
0xE4,UBAMonitorFastPlus,
|
0xE4,UBAMonitorFastPlus,
|
||||||
@@ -74,13 +76,14 @@ telegram_type_id,name,is_fetched
|
|||||||
0x0103,ISM1StatusMessage,fetched
|
0x0103,ISM1StatusMessage,fetched
|
||||||
0x0104,ISM2StatusMessage,
|
0x0104,ISM2StatusMessage,
|
||||||
0x010C,IPMStatusMessage,
|
0x010C,IPMStatusMessage,
|
||||||
0x011E,IPMTempMessage,
|
0x011E,JunkersDisp,fetched
|
||||||
0x012E,HPEnergy1,
|
0x012E,HPEnergy1,
|
||||||
0x013B,HPEnergy2,
|
0x013B,HPEnergy2,
|
||||||
0x0165,JunkersSet,
|
0x0165,JunkersSet,
|
||||||
0x0166,JunkersSet,
|
0x0166,JunkersSet,
|
||||||
0x0167,JunkersSet,
|
0x0167,JunkersSet,
|
||||||
0x0168,JunkersSet,
|
0x0168,JunkersSet,
|
||||||
|
0x016E,Absent,fetched
|
||||||
0x016F,JunkersMonitor,
|
0x016F,JunkersMonitor,
|
||||||
0x0170,JunkersMonitor,
|
0x0170,JunkersMonitor,
|
||||||
0x0171,JunkersMonitor,
|
0x0171,JunkersMonitor,
|
||||||
@@ -93,8 +96,9 @@ telegram_type_id,name,is_fetched
|
|||||||
0x023A,RC300OutdoorTemp,fetched
|
0x023A,RC300OutdoorTemp,fetched
|
||||||
0x023E,PVSettings,fetched
|
0x023E,PVSettings,fetched
|
||||||
0x0240,RC300Settings,fetched
|
0x0240,RC300Settings,fetched
|
||||||
|
0x0241,RC300Settings,fetched
|
||||||
0x0267,RC300Floordry,
|
0x0267,RC300Floordry,
|
||||||
0x0269,RC300Holiday1,fetched
|
0x0269,RC300Holiday,fetched
|
||||||
0x0291,HPMode,fetched
|
0x0291,HPMode,fetched
|
||||||
0x0292,HPMode,fetched
|
0x0292,HPMode,fetched
|
||||||
0x0293,HPMode,fetched
|
0x0293,HPMode,fetched
|
||||||
@@ -109,7 +113,7 @@ telegram_type_id,name,is_fetched
|
|||||||
0x02A2,RC300Curves,
|
0x02A2,RC300Curves,
|
||||||
0x02A5,RC300Monitor,
|
0x02A5,RC300Monitor,
|
||||||
0x02A6,RC300Monitor,
|
0x02A6,RC300Monitor,
|
||||||
0x02A7,CRFMonitor,
|
0x02A7,RC300Monitor,
|
||||||
0x02A8,RC300Monitor,
|
0x02A8,RC300Monitor,
|
||||||
0x02A9,RC300Monitor,
|
0x02A9,RC300Monitor,
|
||||||
0x02AA,RC300Monitor,
|
0x02AA,RC300Monitor,
|
||||||
@@ -138,6 +142,7 @@ telegram_type_id,name,is_fetched
|
|||||||
0x02D2,RC300Set2,
|
0x02D2,RC300Set2,
|
||||||
0x02D6,HPPump2,fetched
|
0x02D6,HPPump2,fetched
|
||||||
0x02D7,MMPLUSStatusMessage,
|
0x02D7,MMPLUSStatusMessage,
|
||||||
|
0x02E0,UBASetPoints,
|
||||||
0x02F5,RC300WWmode,fetched
|
0x02F5,RC300WWmode,fetched
|
||||||
0x02F6,RC300WW2mode,fetched
|
0x02F6,RC300WW2mode,fetched
|
||||||
0x0313,MMPLUSConfigMessage_WWC,fetched
|
0x0313,MMPLUSConfigMessage_WWC,fetched
|
||||||
@@ -159,6 +164,7 @@ telegram_type_id,name,is_fetched
|
|||||||
0x0380,SM100CollectorConfig,fetched
|
0x0380,SM100CollectorConfig,fetched
|
||||||
0x038E,SM100Energy,fetched
|
0x038E,SM100Energy,fetched
|
||||||
0x0391,SM100Time,fetched
|
0x0391,SM100Time,fetched
|
||||||
|
0x043F,CRHolidays,fetched
|
||||||
0x0467,HPSet,
|
0x0467,HPSet,
|
||||||
0x0468,HPSet,
|
0x0468,HPSet,
|
||||||
0x0469,HPSet,
|
0x0469,HPSet,
|
||||||
@@ -193,6 +199,7 @@ telegram_type_id,name,is_fetched
|
|||||||
0x04AA,HPPower2,fetched
|
0x04AA,HPPower2,fetched
|
||||||
0x04AE,HPEnergy,fetched
|
0x04AE,HPEnergy,fetched
|
||||||
0x04AF,HPMeters,fetched
|
0x04AF,HPMeters,fetched
|
||||||
|
0x055C,VentilationSet,fetched
|
||||||
0x056B,VentilationMode,fetched
|
0x056B,VentilationMode,fetched
|
||||||
0x0583,VentilationMonitor,
|
0x0583,VentilationMonitor,
|
||||||
0x0585,Blowerspeed,
|
0x0585,Blowerspeed,
|
||||||
|
|||||||
|
@@ -1,28 +0,0 @@
|
|||||||
"""
|
|
||||||
Print makefile progress
|
|
||||||
From https://stackoverflow.com/questions/451413/make-makefile-progress-indication
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import math
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(description=__doc__)
|
|
||||||
parser.add_argument("--stepno", type=int, required=True)
|
|
||||||
parser.add_argument("--nsteps", type=int, required=True)
|
|
||||||
parser.add_argument("remainder", nargs=argparse.REMAINDER)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
nchars = int(math.log(args.nsteps, 10)) + 1
|
|
||||||
fmt_str = "[{:Xd}/{:Xd}]({:6.2f}%)".replace("X", str(nchars))
|
|
||||||
progress = 100 * args.stepno / args.nsteps
|
|
||||||
sys.stdout.write(fmt_str.format(args.stepno, args.nsteps, progress))
|
|
||||||
for item in args.remainder:
|
|
||||||
sys.stdout.write(" ")
|
|
||||||
sys.stdout.write(item)
|
|
||||||
sys.stdout.write("\n")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
|
||||||
4
interface/.gitattributes
vendored
4
interface/.gitattributes
vendored
@@ -1,4 +0,0 @@
|
|||||||
/.yarn/** linguist-vendored
|
|
||||||
/.yarn/releases/* binary
|
|
||||||
/.yarn/plugins/**/* binary
|
|
||||||
/.pnp.* binary linguist-generated
|
|
||||||
@@ -4,5 +4,4 @@ dist/
|
|||||||
src/i18n/*
|
src/i18n/*
|
||||||
|
|
||||||
.prettierrc
|
.prettierrc
|
||||||
.yarn/
|
.typesafe-i18n.json
|
||||||
.typesafe-i18n.json
|
|
||||||
|
|||||||
934
interface/.yarn/releases/yarn-4.5.3.cjs
vendored
934
interface/.yarn/releases/yarn-4.5.3.cjs
vendored
File diff suppressed because one or more lines are too long
@@ -1,3 +0,0 @@
|
|||||||
nodeLinker: node-modules
|
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-4.5.3.cjs
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "EMS-ESP",
|
"name": "EMS-ESP",
|
||||||
"version": "3.7.1",
|
"version": "3.7.2",
|
||||||
"description": "EMS-ESP WebUI",
|
"description": "EMS-ESP WebUI",
|
||||||
"homepage": "https://emsesp.org",
|
"homepage": "https://emsesp.org",
|
||||||
"author": "proddy, emsesp.org",
|
"author": "proddy, emsesp.org",
|
||||||
@@ -8,59 +8,60 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"preinstall": "npx only-allow pnpm",
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"build-hosted": "typesafe-i18n --no-watch && vite build --mode hosted",
|
"build-hosted": "typesafe-i18n && vite build --mode hosted",
|
||||||
"preview-standalone": "typesafe-i18n --no-watch && vite build && concurrently -c \"auto\" \"yarn:mock-rest\" \"vite preview\"",
|
"preview-standalone": "typesafe-i18n --no-watch && vite build && concurrently -c \"auto\" \"pnpm:mock-rest\" \"vite preview\"",
|
||||||
"mock-rest": "bun --watch ../mock-api/rest_server.ts",
|
"mock-rest": "bun --watch ../mock-api/restServer.ts",
|
||||||
"standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"yarn:mock-rest\" \"vite\"",
|
"standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"pnpm:mock-rest\" \"vite\"",
|
||||||
"typesafe-i18n": "typesafe-i18n --no-watch",
|
"typesafe-i18n": "typesafe-i18n --no-watch",
|
||||||
"webUI": "node progmem-generator.js",
|
"webUI": "node progmem-generator.js",
|
||||||
"format": "prettier -l -w '**/*.{ts,tsx,js,css,json,md}'",
|
"format": "prettier -l -w '**/*.{ts,tsx,js,css,json,md}'",
|
||||||
"lint": "eslint . --fix"
|
"lint": "eslint . --fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alova/adapter-xhr": "2.0.10",
|
"@alova/adapter-xhr": "2.2.1",
|
||||||
"@emotion/react": "^11.13.5",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.13.5",
|
"@emotion/styled": "^11.14.1",
|
||||||
"@mui/icons-material": "^6.1.9",
|
"@mui/icons-material": "^7.3.4",
|
||||||
"@mui/material": "^6.1.9",
|
"@mui/material": "^7.3.4",
|
||||||
"@table-library/react-table-library": "4.1.7",
|
"@table-library/react-table-library": "4.1.15",
|
||||||
"alova": "3.2.5",
|
"alova": "3.3.4",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
|
"formidable": "^3.5.4",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"mime-types": "^2.1.35",
|
"magic-string": "^0.30.19",
|
||||||
"preact": "^10.25.0",
|
"mime-types": "^3.0.1",
|
||||||
"react": "^18.3.1",
|
"preact": "^10.27.2",
|
||||||
"react-dom": "^18.3.1",
|
"react": "^19.2.0",
|
||||||
"react-icons": "^5.3.0",
|
"react-dom": "^19.2.0",
|
||||||
"react-router": "^7.0.1",
|
"react-icons": "^5.5.0",
|
||||||
"react-toastify": "^10.0.6",
|
"react-router": "^7.9.4",
|
||||||
|
"react-toastify": "^11.0.5",
|
||||||
"typesafe-i18n": "^5.26.2",
|
"typesafe-i18n": "^5.26.2",
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.9.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.26.0",
|
"@babel/core": "^7.28.4",
|
||||||
"@eslint/js": "^9.15.0",
|
"@eslint/js": "^9.37.0",
|
||||||
"@preact/compat": "^18.3.1",
|
"@preact/compat": "^18.3.1",
|
||||||
"@preact/preset-vite": "^2.9.2",
|
"@preact/preset-vite": "^2.10.2",
|
||||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||||
"@types/formidable": "^3",
|
"@types/node": "^24.7.0",
|
||||||
"@types/node": "^22.10.1",
|
"@types/react": "^19.2.2",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react-dom": "^19.2.1",
|
||||||
"@types/react-dom": "^18.3.1",
|
"concurrently": "^9.2.1",
|
||||||
"concurrently": "^9.1.0",
|
"eslint": "^9.37.0",
|
||||||
"eslint": "^9.15.0",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"prettier": "^3.6.2",
|
||||||
"formidable": "^3.5.2",
|
"rollup-plugin-visualizer": "^6.0.4",
|
||||||
"prettier": "^3.4.1",
|
"terser": "^5.44.0",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"typescript-eslint": "^8.46.0",
|
||||||
"terser": "^5.36.0",
|
"vite": "^7.1.9",
|
||||||
"typescript-eslint": "8.16.0",
|
|
||||||
"vite": "^6.0.1",
|
|
||||||
"vite-plugin-imagemin": "^0.6.1",
|
"vite-plugin-imagemin": "^0.6.1",
|
||||||
"vite-tsconfig-paths": "^5.1.3"
|
"vite-tsconfig-paths": "^5.1.4"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@4.5.3"
|
"packageManager": "pnpm@10.18.1+sha512.77a884a165cbba2d8d1c19e3b4880eee6d2fcabd0d879121e282196b80042351d5eb3ca0935fa599da1dc51265cc68816ad2bddd2a2de5ea9fdf92adbec7cd34"
|
||||||
}
|
}
|
||||||
|
|||||||
6057
interface/pnpm-lock.yaml
generated
Normal file
6057
interface/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
8
interface/pnpm-workspace.yaml
Normal file
8
interface/pnpm-workspace.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
onlyBuiltDependencies:
|
||||||
|
- cwebp-bin
|
||||||
|
- esbuild
|
||||||
|
- gifsicle
|
||||||
|
- jpegtran-bin
|
||||||
|
- mozjpeg
|
||||||
|
- optipng-bin
|
||||||
|
- pngquant-bin
|
||||||
@@ -12,7 +12,7 @@ import zlib from 'zlib';
|
|||||||
|
|
||||||
const ARDUINO_INCLUDES = '#include <Arduino.h>\n\n';
|
const ARDUINO_INCLUDES = '#include <Arduino.h>\n\n';
|
||||||
const INDENT = ' ';
|
const INDENT = ' ';
|
||||||
const outputPath = '../lib/framework/WWWData.h';
|
const outputPath = '../src/ESP32React/WWWData.h';
|
||||||
const sourcePath = './dist';
|
const sourcePath = './dist';
|
||||||
const bytesPerLine = 20;
|
const bytesPerLine = 20;
|
||||||
var totalSize = 0;
|
var totalSize = 0;
|
||||||
|
|||||||
@@ -13,8 +13,9 @@
|
|||||||
local('Roboto'),
|
local('Roboto'),
|
||||||
local('Roboto-Regular'),
|
local('Roboto-Regular'),
|
||||||
url(../fonts/re.woff2) format('woff2');
|
url(../fonts/re.woff2) format('woff2');
|
||||||
unicode-range: U+0000-00FF, U+0104-0107, U+0118-0119, U+011E-011F, U+0130-0131,
|
unicode-range:
|
||||||
U+0141-0144, U+0152-0153, U+015A-015B, U+015E-015F, U+0179-017C, U+02BB-02BC,
|
U+0000-00FF, U+0104-0107, U+0118-0119, U+011E-011F, U+0130-0131, U+0141-0144,
|
||||||
U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
|
U+0152-0153, U+015A-015B, U+015E-015F, U+0179-017C, U+02BB-02BC, U+02C6, U+02DA,
|
||||||
U+2212, U+2215, U+FEFF, U+FFFD;
|
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
|
||||||
|
U+FEFF, U+FFFD;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,44 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Slide, ToastContainer } from 'react-toastify';
|
import { ToastContainer, Zoom } from 'react-toastify';
|
||||||
import 'react-toastify/dist/ReactToastify.min.css';
|
|
||||||
|
|
||||||
import AppRouting from 'AppRouting';
|
import AppRouting from 'AppRouting';
|
||||||
import CustomTheme from 'CustomTheme';
|
import CustomTheme from 'CustomTheme';
|
||||||
import TypesafeI18n from 'i18n/i18n-react';
|
import TypesafeI18n from 'i18n/i18n-react';
|
||||||
import { detectLocale } from 'i18n/i18n-util';
|
import type { Locales } from 'i18n/i18n-types';
|
||||||
import { loadLocaleAsync } from 'i18n/i18n-util.async';
|
import { loadLocaleAsync } from 'i18n/i18n-util.async';
|
||||||
import { localStorageDetector } from 'typesafe-i18n/detectors';
|
import { detectLocale, navigatorDetector } from 'typesafe-i18n/detectors';
|
||||||
|
|
||||||
const detectedLocale = detectLocale(localStorageDetector);
|
const availableLocales = [
|
||||||
|
'de',
|
||||||
|
'en',
|
||||||
|
'it',
|
||||||
|
'fr',
|
||||||
|
'nl',
|
||||||
|
'no',
|
||||||
|
'pl',
|
||||||
|
'sk',
|
||||||
|
'sv',
|
||||||
|
'tr',
|
||||||
|
'cz'
|
||||||
|
];
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [wasLoaded, setWasLoaded] = useState(false);
|
const [wasLoaded, setWasLoaded] = useState(false);
|
||||||
|
const [locale, setLocale] = useState<Locales>('en');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void loadLocaleAsync(detectedLocale).then(() => setWasLoaded(true));
|
// determine locale, take from session if set other default to browser language
|
||||||
|
const browserLocale = detectLocale('en', availableLocales, navigatorDetector);
|
||||||
|
const newLocale = (localStorage.getItem('lang') || browserLocale) as Locales;
|
||||||
|
localStorage.setItem('lang', newLocale);
|
||||||
|
setLocale(newLocale);
|
||||||
|
void loadLocaleAsync(newLocale).then(() => setWasLoaded(true));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!wasLoaded) return null;
|
if (!wasLoaded) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypesafeI18n locale={detectedLocale}>
|
<TypesafeI18n locale={locale}>
|
||||||
<CustomTheme>
|
<CustomTheme>
|
||||||
<AppRouting />
|
<AppRouting />
|
||||||
<ToastContainer
|
<ToastContainer
|
||||||
@@ -29,14 +46,17 @@ const App = () => {
|
|||||||
autoClose={3000}
|
autoClose={3000}
|
||||||
hideProgressBar={false}
|
hideProgressBar={false}
|
||||||
newestOnTop={false}
|
newestOnTop={false}
|
||||||
closeOnClick={true}
|
closeOnClick
|
||||||
rtl={false}
|
rtl={false}
|
||||||
pauseOnFocusLoss={false}
|
pauseOnFocusLoss
|
||||||
draggable={false}
|
draggable={false}
|
||||||
pauseOnHover={false}
|
pauseOnHover={false}
|
||||||
transition={Slide}
|
transition={Zoom}
|
||||||
closeButton={false}
|
closeButton={false}
|
||||||
theme="light"
|
theme="dark"
|
||||||
|
toastStyle={{
|
||||||
|
border: '1px solid #177ac9'
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</CustomTheme>
|
</CustomTheme>
|
||||||
</TypesafeI18n>
|
</TypesafeI18n>
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import DownloadUpload from 'app/settings/DownloadUpload';
|
|||||||
import MqttSettings from 'app/settings/MqttSettings';
|
import MqttSettings from 'app/settings/MqttSettings';
|
||||||
import NTPSettings from 'app/settings/NTPSettings';
|
import NTPSettings from 'app/settings/NTPSettings';
|
||||||
import Settings from 'app/settings/Settings';
|
import Settings from 'app/settings/Settings';
|
||||||
import Version from 'app/settings/Version';
|
|
||||||
import Network from 'app/settings/network/Network';
|
import Network from 'app/settings/network/Network';
|
||||||
import Security from 'app/settings/security/Security';
|
import Security from 'app/settings/security/Security';
|
||||||
import APStatus from 'app/status/APStatus';
|
import APStatus from 'app/status/APStatus';
|
||||||
@@ -26,6 +25,7 @@ import NTPStatus from 'app/status/NTPStatus';
|
|||||||
import NetworkStatus from 'app/status/NetworkStatus';
|
import NetworkStatus from 'app/status/NetworkStatus';
|
||||||
import Status from 'app/status/Status';
|
import Status from 'app/status/Status';
|
||||||
import SystemLog from 'app/status/SystemLog';
|
import SystemLog from 'app/status/SystemLog';
|
||||||
|
import Version from 'app/status/Version';
|
||||||
import { Layout } from 'components';
|
import { Layout } from 'components';
|
||||||
import { AuthenticatedContext } from 'contexts/authentication';
|
import { AuthenticatedContext } from 'contexts/authentication';
|
||||||
|
|
||||||
@@ -48,17 +48,17 @@ const AuthenticatedRouting = () => {
|
|||||||
<Route path="/status/ntp" element={<NTPStatus />} />
|
<Route path="/status/ntp" element={<NTPStatus />} />
|
||||||
<Route path="/status/ap" element={<APStatus />} />
|
<Route path="/status/ap" element={<APStatus />} />
|
||||||
<Route path="/status/network" element={<NetworkStatus />} />
|
<Route path="/status/network" element={<NetworkStatus />} />
|
||||||
|
<Route path="/status/version" element={<Version />} />
|
||||||
|
|
||||||
{me.admin && (
|
{me.admin && (
|
||||||
<>
|
<>
|
||||||
<Route path="/settings" element={<Settings />} />
|
<Route path="/settings" element={<Settings />} />
|
||||||
<Route path="/settings/version" element={<Version />} />
|
|
||||||
<Route path="/settings/application" element={<ApplicationSettings />} />
|
<Route path="/settings/application" element={<ApplicationSettings />} />
|
||||||
<Route path="/settings/mqtt" element={<MqttSettings />} />
|
<Route path="/settings/mqtt" element={<MqttSettings />} />
|
||||||
<Route path="/settings/ntp" element={<NTPSettings />} />
|
<Route path="/settings/ntp" element={<NTPSettings />} />
|
||||||
<Route path="/settings/ap" element={<APSettings />} />
|
<Route path="/settings/ap" element={<APSettings />} />
|
||||||
<Route path="/settings/modules" element={<Modules />} />
|
<Route path="/settings/modules" element={<Modules />} />
|
||||||
<Route path="/settings/upload" element={<DownloadUpload />} />
|
<Route path="/settings/downloadUpload" element={<DownloadUpload />} />
|
||||||
|
|
||||||
<Route path="/settings/network/*" element={<Network />} />
|
<Route path="/settings/network/*" element={<Network />} />
|
||||||
<Route path="/settings/security/*" element={<Security />} />
|
<Route path="/settings/security/*" element={<Security />} />
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
import { CssBaseline } from '@mui/material';
|
import { CssBaseline, ThemeProvider, responsiveFontSizes } from '@mui/material';
|
||||||
import {
|
import { createTheme } from '@mui/material/styles';
|
||||||
ThemeProvider,
|
|
||||||
createTheme,
|
|
||||||
responsiveFontSizes
|
|
||||||
} from '@mui/material/styles';
|
|
||||||
|
|
||||||
import type { RequiredChildrenProps } from 'utils';
|
import type { RequiredChildrenProps } from 'utils';
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import type {
|
|||||||
Action,
|
Action,
|
||||||
Activity,
|
Activity,
|
||||||
CoreData,
|
CoreData,
|
||||||
DashboardItem,
|
DashboardData,
|
||||||
DeviceData,
|
DeviceData,
|
||||||
DeviceEntity,
|
DeviceEntity,
|
||||||
Entities,
|
Entities,
|
||||||
@@ -22,7 +22,7 @@ import type {
|
|||||||
|
|
||||||
// Dashboard
|
// Dashboard
|
||||||
export const readDashboard = () =>
|
export const readDashboard = () =>
|
||||||
alovaInstance.Get<DashboardItem[]>('/rest/dashboardData', {
|
alovaInstance.Get<DashboardData>('/rest/dashboardData', {
|
||||||
responseType: 'arraybuffer' // uses msgpack
|
responseType: 'arraybuffer' // uses msgpack
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -143,7 +143,8 @@ export const readCustomEntities = () =>
|
|||||||
o_name: ei.name,
|
o_name: ei.name,
|
||||||
o_writeable: ei.writeable,
|
o_writeable: ei.writeable,
|
||||||
o_value: ei.value,
|
o_value: ei.value,
|
||||||
o_deleted: ei.deleted
|
o_deleted: ei.deleted,
|
||||||
|
o_hide: ei.hide
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const alovaInstance = createAlova({
|
|||||||
method.config.headers.Authorization =
|
method.config.headers.Authorization =
|
||||||
'Bearer ' + localStorage.getItem(ACCESS_TOKEN);
|
'Bearer ' + localStorage.getItem(ACCESS_TOKEN);
|
||||||
}
|
}
|
||||||
// for simulating vrey slow networks
|
// for simulating very slow networks
|
||||||
// return new Promise((resolve) => {
|
// return new Promise((resolve) => {
|
||||||
// const random = 3000 + Math.random() * 2000;
|
// const random = 3000 + Math.random() * 2000;
|
||||||
// setTimeout(resolve, Math.floor(random));
|
// setTimeout(resolve, Math.floor(random));
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { LogSettings, SystemStatus } from 'types';
|
|||||||
|
|
||||||
import { alovaInstance, alovaInstanceGH } from './endpoints';
|
import { alovaInstance, alovaInstanceGH } from './endpoints';
|
||||||
|
|
||||||
// systemStatus - also used to ping in Restart monitor for pinging
|
// systemStatus - also used to ping in System Monitor for pinging
|
||||||
export const readSystemStatus = () =>
|
export const readSystemStatus = () =>
|
||||||
alovaInstance.Get<SystemStatus>('/rest/systemStatus');
|
alovaInstance.Get<SystemStatus>('/rest/systemStatus');
|
||||||
|
|
||||||
@@ -14,16 +14,25 @@ export const updateLogSettings = (data: LogSettings) =>
|
|||||||
export const fetchLogES = () => alovaInstance.Get('/es/log');
|
export const fetchLogES = () => alovaInstance.Get('/es/log');
|
||||||
|
|
||||||
// Get versions from GitHub
|
// Get versions from GitHub
|
||||||
|
// cache for 10 minutes to stop getting the IP blocked by GitHub
|
||||||
export const getStableVersion = () =>
|
export const getStableVersion = () =>
|
||||||
alovaInstanceGH.Get('latest', {
|
alovaInstanceGH.Get('latest', {
|
||||||
transform(response: { data: { name: string } }) {
|
cacheFor: 60 * 10 * 1000,
|
||||||
return response.data.name.substring(1);
|
transform(response: { data: { name: string; published_at: string } }) {
|
||||||
|
return {
|
||||||
|
name: response.data.name.substring(1),
|
||||||
|
published_at: response.data.published_at
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
export const getDevVersion = () =>
|
export const getDevVersion = () =>
|
||||||
alovaInstanceGH.Get('tags/latest', {
|
alovaInstanceGH.Get('tags/latest', {
|
||||||
transform(response: { data: { name: string } }) {
|
cacheFor: 60 * 10 * 1000,
|
||||||
return response.data.name.split(/\s+/).splice(-1)[0].substring(1);
|
transform(response: { data: { name: string; published_at: string } }) {
|
||||||
|
return {
|
||||||
|
name: response.data.name.split(/\s+/).splice(-1)[0].substring(1),
|
||||||
|
published_at: response.data.published_at
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const CustomEntities = () => {
|
|||||||
if (!dialogOpen && !numChanges) {
|
if (!dialogOpen && !numChanges) {
|
||||||
void fetchEntities();
|
void fetchEntities();
|
||||||
}
|
}
|
||||||
}, 3000);
|
});
|
||||||
|
|
||||||
const { send: writeEntities } = useRequest(
|
const { send: writeEntities } = useRequest(
|
||||||
(data: Entities) => writeCustomEntities(data),
|
(data: Entities) => writeCustomEntities(data),
|
||||||
@@ -76,6 +76,7 @@ const CustomEntities = () => {
|
|||||||
ei.factor !== ei.o_factor ||
|
ei.factor !== ei.o_factor ||
|
||||||
ei.value_type !== ei.o_value_type ||
|
ei.value_type !== ei.o_value_type ||
|
||||||
ei.writeable !== ei.o_writeable ||
|
ei.writeable !== ei.o_writeable ||
|
||||||
|
ei.hide !== ei.o_hide ||
|
||||||
ei.deleted !== ei.o_deleted ||
|
ei.deleted !== ei.o_deleted ||
|
||||||
(ei.value || '') !== (ei.o_value || '')
|
(ei.value || '') !== (ei.o_value || '')
|
||||||
);
|
);
|
||||||
@@ -83,7 +84,7 @@ const CustomEntities = () => {
|
|||||||
|
|
||||||
const entity_theme = useTheme({
|
const entity_theme = useTheme({
|
||||||
Table: `
|
Table: `
|
||||||
--data-table-library_grid-template-columns: repeat(1, minmax(60px, 1fr)) minmax(80px, auto) 80px 80px 80px 90px;
|
--data-table-library_grid-template-columns: repeat(1, minmax(60px, 1fr)) minmax(80px, auto) 80px 80px 80px 120px;
|
||||||
`,
|
`,
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -147,6 +148,7 @@ const CustomEntities = () => {
|
|||||||
factor: condensed_ei.factor,
|
factor: condensed_ei.factor,
|
||||||
uom: condensed_ei.uom,
|
uom: condensed_ei.uom,
|
||||||
writeable: condensed_ei.writeable,
|
writeable: condensed_ei.writeable,
|
||||||
|
hide: condensed_ei.hide,
|
||||||
value_type: condensed_ei.value_type,
|
value_type: condensed_ei.value_type,
|
||||||
value: condensed_ei.value
|
value: condensed_ei.value
|
||||||
}))
|
}))
|
||||||
@@ -195,6 +197,26 @@ const CustomEntities = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onDialogDup = (item: EntityItem) => {
|
||||||
|
setCreating(true);
|
||||||
|
setSelectedEntityItem({
|
||||||
|
id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100),
|
||||||
|
name: item.name + '_',
|
||||||
|
ram: item.ram,
|
||||||
|
device_id: item.device_id,
|
||||||
|
type_id: item.type_id,
|
||||||
|
offset: item.offset,
|
||||||
|
factor: item.factor,
|
||||||
|
uom: item.uom,
|
||||||
|
value_type: item.value_type,
|
||||||
|
writeable: item.writeable,
|
||||||
|
deleted: false,
|
||||||
|
hide: item.hide,
|
||||||
|
value: item.value
|
||||||
|
});
|
||||||
|
setDialogOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
const addEntityItem = () => {
|
const addEntityItem = () => {
|
||||||
setCreating(true);
|
setCreating(true);
|
||||||
setSelectedEntityItem({
|
setSelectedEntityItem({
|
||||||
@@ -220,7 +242,7 @@ const CustomEntities = () => {
|
|||||||
: typeof value === 'number'
|
: typeof value === 'number'
|
||||||
? new Intl.NumberFormat().format(value) +
|
? new Intl.NumberFormat().format(value) +
|
||||||
(uom === 0 ? '' : ' ' + DeviceValueUOM_s[uom])
|
(uom === 0 ? '' : ' ' + DeviceValueUOM_s[uom])
|
||||||
: (value as string);
|
: (value as string) + (uom === 0 ? '' : ' ' + DeviceValueUOM_s[uom]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showHex(value: number, digit: number) {
|
function showHex(value: number, digit: number) {
|
||||||
@@ -296,6 +318,7 @@ const CustomEntities = () => {
|
|||||||
creating={creating}
|
creating={creating}
|
||||||
onClose={onDialogClose}
|
onClose={onDialogClose}
|
||||||
onSave={onDialogSave}
|
onSave={onDialogSave}
|
||||||
|
onDup={onDialogDup}
|
||||||
selectedItem={selectedEntityItem}
|
selectedItem={selectedEntityItem}
|
||||||
validator={entityItemValidation(entities, selectedEntityItem)}
|
validator={entityItemValidation(entities, selectedEntityItem)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ import { useEffect, useState } from 'react';
|
|||||||
|
|
||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
||||||
import DoneIcon from '@mui/icons-material/Done';
|
import DoneIcon from '@mui/icons-material/Done';
|
||||||
|
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
||||||
|
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
|
||||||
|
import InsertCommentOutlinedIcon from '@mui/icons-material/InsertCommentOutlined';
|
||||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
@@ -12,11 +16,11 @@ import {
|
|||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
TextField
|
TextField
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import type Schema from 'async-validator';
|
import type Schema from 'async-validator';
|
||||||
@@ -34,6 +38,7 @@ interface CustomEntitiesDialogProps {
|
|||||||
creating: boolean;
|
creating: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSave: (ei: EntityItem) => void;
|
onSave: (ei: EntityItem) => void;
|
||||||
|
onDup: (ei: EntityItem) => void;
|
||||||
selectedItem: EntityItem;
|
selectedItem: EntityItem;
|
||||||
validator: Schema;
|
validator: Schema;
|
||||||
}
|
}
|
||||||
@@ -43,6 +48,7 @@ const CustomEntitiesDialog = ({
|
|||||||
creating,
|
creating,
|
||||||
onClose,
|
onClose,
|
||||||
onSave,
|
onSave,
|
||||||
|
onDup,
|
||||||
selectedItem,
|
selectedItem,
|
||||||
validator
|
validator
|
||||||
}: CustomEntitiesDialogProps) => {
|
}: CustomEntitiesDialogProps) => {
|
||||||
@@ -59,7 +65,11 @@ const CustomEntitiesDialog = ({
|
|||||||
setEditItem({
|
setEditItem({
|
||||||
...selectedItem,
|
...selectedItem,
|
||||||
device_id: selectedItem.device_id.toString(16).toUpperCase(),
|
device_id: selectedItem.device_id.toString(16).toUpperCase(),
|
||||||
type_id: selectedItem.type_id.toString(16).toUpperCase()
|
type_id: selectedItem.type_id.toString(16).toUpperCase(),
|
||||||
|
factor:
|
||||||
|
selectedItem.value_type === DeviceValueType.BOOL
|
||||||
|
? selectedItem.factor.toString(16).toUpperCase()
|
||||||
|
: selectedItem.factor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [open, selectedItem]);
|
}, [open, selectedItem]);
|
||||||
@@ -80,6 +90,12 @@ const CustomEntitiesDialog = ({
|
|||||||
if (typeof editItem.type_id === 'string') {
|
if (typeof editItem.type_id === 'string') {
|
||||||
editItem.type_id = parseInt(editItem.type_id, 16);
|
editItem.type_id = parseInt(editItem.type_id, 16);
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
editItem.value_type === DeviceValueType.BOOL &&
|
||||||
|
typeof editItem.factor === 'string'
|
||||||
|
) {
|
||||||
|
editItem.factor = parseInt(editItem.factor, 16);
|
||||||
|
}
|
||||||
onSave(editItem);
|
onSave(editItem);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setFieldErrors(error as ValidateFieldsError);
|
setFieldErrors(error as ValidateFieldsError);
|
||||||
@@ -91,6 +107,10 @@ const CustomEntitiesDialog = ({
|
|||||||
onSave(editItem);
|
onSave(editItem);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dup = () => {
|
||||||
|
onDup(editItem);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog sx={dialogStyle} open={open} onClose={handleClose}>
|
<Dialog sx={dialogStyle} open={open} onClose={handleClose}>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
@@ -112,6 +132,20 @@ const CustomEntitiesDialog = ({
|
|||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid mt={3}>
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
icon={<InsertCommentOutlinedIcon htmlColor="white" />}
|
||||||
|
checkedIcon={<CommentsDisabledOutlinedIcon color="primary" />}
|
||||||
|
checked={editItem.hide}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
name="hide"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="API/MQTT"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextField
|
<TextField
|
||||||
name="ram"
|
name="ram"
|
||||||
@@ -128,25 +162,45 @@ const CustomEntitiesDialog = ({
|
|||||||
</TextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
{editItem.ram === 1 && (
|
{editItem.ram === 1 && (
|
||||||
<Grid>
|
<>
|
||||||
<TextField
|
<Grid>
|
||||||
name="value"
|
<TextField
|
||||||
label={LL.DEFAULT(0) + ' ' + LL.VALUE(0)}
|
name="value"
|
||||||
type="string"
|
label={LL.DEFAULT(0) + ' ' + LL.VALUE(0)}
|
||||||
value={editItem.value as string}
|
type="string"
|
||||||
variant="outlined"
|
value={editItem.value as string}
|
||||||
onChange={updateFormValue}
|
variant="outlined"
|
||||||
fullWidth
|
onChange={updateFormValue}
|
||||||
margin="normal"
|
fullWidth
|
||||||
/>
|
margin="normal"
|
||||||
</Grid>
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<TextField
|
||||||
|
name="uom"
|
||||||
|
label={LL.UNIT()}
|
||||||
|
value={editItem.uom}
|
||||||
|
margin="normal"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
select
|
||||||
|
>
|
||||||
|
{DeviceValueUOM_s.map((val, i) => (
|
||||||
|
<MenuItem key={val} value={i}>
|
||||||
|
{val}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
{editItem.ram === 0 && (
|
{editItem.ram === 0 && (
|
||||||
<>
|
<>
|
||||||
<Grid mt={3} size={9}>
|
<Grid mt={3}>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
icon={<EditOffOutlinedIcon color="primary" />}
|
||||||
|
checkedIcon={<EditOutlinedIcon htmlColor="white" />}
|
||||||
checked={editItem.writeable}
|
checked={editItem.writeable}
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
name="writeable"
|
name="writeable"
|
||||||
@@ -255,7 +309,7 @@ const CustomEntitiesDialog = ({
|
|||||||
<TextField
|
<TextField
|
||||||
name="factor"
|
name="factor"
|
||||||
label={LL.FACTOR()}
|
label={LL.FACTOR()}
|
||||||
value={numberValue(editItem.factor)}
|
value={numberValue(editItem.factor as number)}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
sx={{ width: '11ch' }}
|
sx={{ width: '11ch' }}
|
||||||
@@ -291,16 +345,42 @@ const CustomEntitiesDialog = ({
|
|||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="factor"
|
name="factor"
|
||||||
label="Bytes"
|
label={LL.BYTES()}
|
||||||
value={numberValue(editItem.factor)}
|
value={numberValue(editItem.factor as number)}
|
||||||
sx={{ width: '11ch' }}
|
sx={{ width: '11ch' }}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
type="number"
|
type="number"
|
||||||
|
slotProps={{
|
||||||
|
htmlInput: { step: '1', min: '1', max: '255' }
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
|
{editItem.value_type === DeviceValueType.BOOL && (
|
||||||
|
<Grid>
|
||||||
|
<ValidatedTextField
|
||||||
|
fieldErrors={fieldErrors}
|
||||||
|
name="factor"
|
||||||
|
label={LL.BITMASK()}
|
||||||
|
value={editItem.factor as string}
|
||||||
|
sx={{ width: '11ch' }}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
margin="normal"
|
||||||
|
type="string"
|
||||||
|
slotProps={{
|
||||||
|
input: {
|
||||||
|
startAdornment: (
|
||||||
|
<InputAdornment position="start">0x</InputAdornment>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
htmlInput: { style: { textTransform: 'uppercase' } }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -316,6 +396,15 @@ const CustomEntitiesDialog = ({
|
|||||||
>
|
>
|
||||||
{LL.REMOVE()}
|
{LL.REMOVE()}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
sx={{ ml: 1 }}
|
||||||
|
startIcon={<AddIcon />}
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
onClick={dup}
|
||||||
|
>
|
||||||
|
{LL.DUPLICATE()}
|
||||||
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
Link,
|
Link,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
@@ -24,7 +25,6 @@ import {
|
|||||||
ToggleButtonGroup,
|
ToggleButtonGroup,
|
||||||
Typography
|
Typography
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Body,
|
Body,
|
||||||
@@ -38,7 +38,7 @@ import {
|
|||||||
import { useTheme } from '@table-library/react-table-library/theme';
|
import { useTheme } from '@table-library/react-table-library/theme';
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import { useRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import RestartMonitor from 'app/status/RestartMonitor';
|
import SystemMonitor from 'app/status/SystemMonitor';
|
||||||
import {
|
import {
|
||||||
BlockNavigation,
|
BlockNavigation,
|
||||||
ButtonRow,
|
ButtonRow,
|
||||||
@@ -306,7 +306,7 @@ const Customizations = () => {
|
|||||||
|
|
||||||
const filter_entity = (de: DeviceEntity) =>
|
const filter_entity = (de: DeviceEntity) =>
|
||||||
(de.m & selectedFilters || !selectedFilters) &&
|
(de.m & selectedFilters || !selectedFilters) &&
|
||||||
formatName(de, true).includes(search);
|
formatName(de, true).toLowerCase().includes(search.toLowerCase());
|
||||||
|
|
||||||
const maskDisabled = (set: boolean) => {
|
const maskDisabled = (set: boolean) => {
|
||||||
setDeviceEntities(
|
setDeviceEntities(
|
||||||
@@ -593,7 +593,7 @@ const Customizations = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Typography variant="subtitle2" color="primary">
|
<Typography variant="subtitle2" color="grey">
|
||||||
{LL.SHOWING()} {shown_data.length}/{deviceEntities.length}
|
{LL.SHOWING()} {shown_data.length}/{deviceEntities.length}
|
||||||
{LL.ENTITIES(deviceEntities.length)}
|
{LL.ENTITIES(deviceEntities.length)}
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -737,7 +737,7 @@ const Customizations = () => {
|
|||||||
return (
|
return (
|
||||||
<SectionContent>
|
<SectionContent>
|
||||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||||
{restarting ? <RestartMonitor /> : renderContent()}
|
{restarting ? <SystemMonitor /> : renderContent()}
|
||||||
{selectedDeviceEntity && (
|
{selectedDeviceEntity && (
|
||||||
<SettingsCustomizationsDialog
|
<SettingsCustomizationsDialog
|
||||||
open={dialogOpen}
|
open={dialogOpen}
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import {
|
|||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
TextField,
|
TextField,
|
||||||
Typography
|
Typography
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { useContext, useEffect, useState } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import { IconContext } from 'react-icons/lib';
|
import { IconContext } from 'react-icons/lib';
|
||||||
|
import { Link } from 'react-router';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
||||||
import EditIcon from '@mui/icons-material/Edit';
|
import EditIcon from '@mui/icons-material/Edit';
|
||||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||||
|
import HelpOutlineIcon from '@mui/icons-material/HelpOutline';
|
||||||
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
|
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
|
||||||
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
|
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
|
||||||
import {
|
import {
|
||||||
@@ -12,16 +14,20 @@ import {
|
|||||||
IconButton,
|
IconButton,
|
||||||
ToggleButton,
|
ToggleButton,
|
||||||
ToggleButtonGroup,
|
ToggleButtonGroup,
|
||||||
Tooltip,
|
|
||||||
Typography
|
Typography
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { Body, Cell, Row, Table } from '@table-library/react-table-library/table';
|
import { Body, Cell, Row, Table } from '@table-library/react-table-library/table';
|
||||||
import { useTheme } from '@table-library/react-table-library/theme';
|
import { useTheme } from '@table-library/react-table-library/theme';
|
||||||
import { CellTree, useTree } from '@table-library/react-table-library/tree';
|
import { CellTree, useTree } from '@table-library/react-table-library/tree';
|
||||||
import { useRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
import {
|
||||||
|
ButtonTooltip,
|
||||||
|
FormLoader,
|
||||||
|
MessageBox,
|
||||||
|
SectionContent,
|
||||||
|
useLayoutTitle
|
||||||
|
} from 'components';
|
||||||
import { AuthenticatedContext } from 'contexts/authentication';
|
import { AuthenticatedContext } from 'contexts/authentication';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import { useInterval, usePersistState } from 'utils';
|
import { useInterval, usePersistState } from 'utils';
|
||||||
@@ -54,13 +60,12 @@ const Dashboard = () => {
|
|||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
send: fetchDashboard,
|
send: fetchDashboard,
|
||||||
error,
|
error
|
||||||
loading
|
|
||||||
} = useRequest(readDashboard, {
|
} = useRequest(readDashboard, {
|
||||||
initialData: []
|
initialData: { connected: true, nodes: [] }
|
||||||
}).onSuccess((event) => {
|
}).onSuccess((event) => {
|
||||||
if (event.data.length !== parentNodes) {
|
if (event.data.nodes.length !== parentNodes) {
|
||||||
setParentNodes(event.data.length); // count number of parents/devices
|
setParentNodes(event.data.nodes.length); // count number of parents/devices
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -120,7 +125,7 @@ const Dashboard = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const tree = useTree(
|
const tree = useTree(
|
||||||
{ nodes: data },
|
{ nodes: data.nodes },
|
||||||
{
|
{
|
||||||
onChange: undefined // not used but needed
|
onChange: undefined // not used but needed
|
||||||
},
|
},
|
||||||
@@ -149,11 +154,11 @@ const Dashboard = () => {
|
|||||||
if (!deviceValueDialogOpen) {
|
if (!deviceValueDialogOpen) {
|
||||||
void fetchDashboard();
|
void fetchDashboard();
|
||||||
}
|
}
|
||||||
}, 3000);
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
showAll
|
showAll
|
||||||
? tree.fns.onAddAll(data.map((item: DashboardItem) => item.id)) // expand tree
|
? tree.fns.onAddAll(data.nodes.map((item: DashboardItem) => item.id)) // expand tree
|
||||||
: tree.fns.onRemoveAll(); // collapse tree
|
: tree.fns.onRemoveAll(); // collapse tree
|
||||||
}, [parentNodes]);
|
}, [parentNodes]);
|
||||||
|
|
||||||
@@ -223,120 +228,133 @@ const Dashboard = () => {
|
|||||||
return <FormLoader onRetry={fetchDashboard} errorMessage={error?.message} />;
|
return <FormLoader onRetry={fetchDashboard} errorMessage={error?.message} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hasFavEntities = data.nodes.filter(
|
||||||
|
(item: DashboardItem) => item.id <= 90
|
||||||
|
).length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box
|
{!data.connected && (
|
||||||
sx={{
|
<MessageBox mb={2} level="error" message={LL.EMS_BUS_WARNING()} />
|
||||||
backgroundColor: 'black',
|
)}
|
||||||
pt: 1,
|
|
||||||
pl: 2
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Grid container spacing={0} justifyContent="flex-start">
|
|
||||||
<Grid size={11}>
|
|
||||||
<Typography mb={2} variant="body1" color="warning">
|
|
||||||
{LL.DASHBOARD_1()}.
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid size={1} alignItems="end">
|
{data.connected && data.nodes.length > 0 && !hasFavEntities && (
|
||||||
<ToggleButtonGroup
|
<MessageBox mb={2} level="warning">
|
||||||
color="primary"
|
<Typography>
|
||||||
size="small"
|
{LL.NO_DATA_1()}
|
||||||
value={showAll}
|
<Link to="/customizations" style={{ color: 'white' }}>
|
||||||
exclusive
|
{LL.CUSTOMIZATIONS()}
|
||||||
onChange={handleShowAll}
|
</Link>
|
||||||
>
|
{LL.NO_DATA_2()}
|
||||||
|
{LL.NO_DATA_3()}
|
||||||
|
<Link to="/devices" style={{ color: 'white' }}>
|
||||||
|
{LL.DEVICES()}
|
||||||
|
</Link>
|
||||||
|
.
|
||||||
|
</Typography>
|
||||||
|
</MessageBox>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{data.nodes.length > 0 && (
|
||||||
|
<>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
color="primary"
|
||||||
|
size="small"
|
||||||
|
value={showAll}
|
||||||
|
exclusive
|
||||||
|
onChange={handleShowAll}
|
||||||
|
>
|
||||||
|
<ButtonTooltip title={LL.ALLVALUES()} arrow>
|
||||||
<ToggleButton value={true}>
|
<ToggleButton value={true}>
|
||||||
<UnfoldMoreIcon sx={{ fontSize: 18 }} />
|
<UnfoldMoreIcon sx={{ fontSize: 18 }} />
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
|
</ButtonTooltip>
|
||||||
|
<ButtonTooltip title={LL.COMPACT()} arrow>
|
||||||
<ToggleButton value={false}>
|
<ToggleButton value={false}>
|
||||||
<UnfoldLessIcon sx={{ fontSize: 18 }} />
|
<UnfoldLessIcon sx={{ fontSize: 18 }} />
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
</ToggleButtonGroup>
|
</ButtonTooltip>
|
||||||
</Grid>
|
</ToggleButtonGroup>
|
||||||
</Grid>
|
<ButtonTooltip title={LL.DASHBOARD_1()} arrow>
|
||||||
</Box>
|
<HelpOutlineIcon color="primary" sx={{ ml: 1, fontSize: 20 }} />
|
||||||
|
</ButtonTooltip>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
padding={1}
|
padding={1}
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
sx={{
|
sx={{
|
||||||
borderRadius: 1,
|
borderRadius: 1,
|
||||||
border: '1px solid grey'
|
border: '1px solid grey'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconContext.Provider
|
<IconContext.Provider
|
||||||
value={{
|
value={{
|
||||||
color: 'lightblue',
|
color: 'lightblue',
|
||||||
size: '16',
|
size: '18',
|
||||||
style: { verticalAlign: 'middle' }
|
style: { verticalAlign: 'middle' }
|
||||||
}}
|
}}
|
||||||
>
|
|
||||||
{!loading && data.length === 0 ? (
|
|
||||||
<Typography variant="subtitle2" color="secondary">
|
|
||||||
{LL.NO_DATA()}
|
|
||||||
</Typography>
|
|
||||||
) : (
|
|
||||||
<Table
|
|
||||||
data={{ nodes: data }}
|
|
||||||
theme={dashboard_theme}
|
|
||||||
layout={{ custom: true }}
|
|
||||||
tree={tree}
|
|
||||||
>
|
>
|
||||||
{(tableList: DashboardItem[]) => (
|
<Table
|
||||||
<Body>
|
data={{ nodes: data.nodes }}
|
||||||
{tableList.map((di: DashboardItem) => (
|
theme={dashboard_theme}
|
||||||
<Row
|
layout={{ custom: true }}
|
||||||
key={di.id}
|
tree={tree}
|
||||||
item={di}
|
>
|
||||||
onClick={() => editDashboardValue(di)}
|
{(tableList: DashboardItem[]) => (
|
||||||
>
|
<Body>
|
||||||
{di.id > 99 ? (
|
{tableList.map((di: DashboardItem) => (
|
||||||
<>
|
<Row
|
||||||
<Cell>{showName(di)}</Cell>
|
key={di.id}
|
||||||
<Cell>
|
item={di}
|
||||||
<Tooltip
|
onClick={() => editDashboardValue(di)}
|
||||||
placement="left"
|
>
|
||||||
title={formatValue(LL, di.dv?.v, di.dv?.u)}
|
{di.id > 99 ? (
|
||||||
arrow
|
<>
|
||||||
>
|
<Cell>{showName(di)}</Cell>
|
||||||
<span>{formatValue(LL, di.dv?.v, di.dv?.u)}</span>
|
<Cell>
|
||||||
</Tooltip>
|
<ButtonTooltip
|
||||||
</Cell>
|
title={formatValue(LL, di.dv?.v, di.dv?.u)}
|
||||||
|
>
|
||||||
|
<span>{formatValue(LL, di.dv?.v, di.dv?.u)}</span>
|
||||||
|
</ButtonTooltip>
|
||||||
|
</Cell>
|
||||||
|
|
||||||
<Cell>
|
<Cell>
|
||||||
{me.admin &&
|
{me.admin &&
|
||||||
di.dv?.c &&
|
di.dv?.c &&
|
||||||
!hasMask(di.dv.id, DeviceEntityMask.DV_READONLY) && (
|
!hasMask(
|
||||||
<IconButton
|
di.dv.id,
|
||||||
size="small"
|
DeviceEntityMask.DV_READONLY
|
||||||
onClick={() => editDashboardValue(di)}
|
) && (
|
||||||
>
|
<IconButton
|
||||||
<EditIcon
|
size="small"
|
||||||
color="primary"
|
onClick={() => editDashboardValue(di)}
|
||||||
sx={{ fontSize: 16 }}
|
>
|
||||||
/>
|
<EditIcon
|
||||||
</IconButton>
|
color="primary"
|
||||||
)}
|
sx={{ fontSize: 16 }}
|
||||||
</Cell>
|
/>
|
||||||
</>
|
</IconButton>
|
||||||
) : (
|
)}
|
||||||
<>
|
</Cell>
|
||||||
<CellTree item={di}>{showName(di)}</CellTree>
|
</>
|
||||||
<Cell />
|
) : (
|
||||||
<Cell />
|
<>
|
||||||
</>
|
<CellTree item={di}>{showName(di)}</CellTree>
|
||||||
)}
|
<Cell />
|
||||||
</Row>
|
<Cell />
|
||||||
))}
|
</>
|
||||||
</Body>
|
)}
|
||||||
)}
|
</Row>
|
||||||
</Table>
|
))}
|
||||||
)}
|
</Body>
|
||||||
</IconContext.Provider>
|
)}
|
||||||
</Box>
|
</Table>
|
||||||
|
</IconContext.Provider>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,15 +10,16 @@ import { useNavigate } from 'react-router';
|
|||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
||||||
|
import ConstructionIcon from '@mui/icons-material/Construction';
|
||||||
import EditIcon from '@mui/icons-material/Edit';
|
import EditIcon from '@mui/icons-material/Edit';
|
||||||
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
||||||
import FormatListNumberedIcon from '@mui/icons-material/FormatListNumbered';
|
|
||||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||||
import HighlightOffIcon from '@mui/icons-material/HighlightOff';
|
import HighlightOffIcon from '@mui/icons-material/HighlightOff';
|
||||||
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
||||||
import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
|
import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
|
||||||
import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined';
|
import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined';
|
||||||
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
||||||
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
import StarIcon from '@mui/icons-material/Star';
|
import StarIcon from '@mui/icons-material/Star';
|
||||||
import StarBorderOutlinedIcon from '@mui/icons-material/StarBorderOutlined';
|
import StarBorderOutlinedIcon from '@mui/icons-material/StarBorderOutlined';
|
||||||
import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined';
|
import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined';
|
||||||
@@ -30,17 +31,16 @@ import {
|
|||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
IconButton,
|
IconButton,
|
||||||
|
InputAdornment,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
Tooltip,
|
TextField,
|
||||||
type TooltipProps,
|
ToggleButton,
|
||||||
Typography,
|
Typography
|
||||||
styled,
|
|
||||||
tooltipClasses
|
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { useRowSelect } from '@table-library/react-table-library/select';
|
import { useRowSelect } from '@table-library/react-table-library/select';
|
||||||
import { SortToggleType, useSort } from '@table-library/react-table-library/sort';
|
import { SortToggleType, useSort } from '@table-library/react-table-library/sort';
|
||||||
@@ -57,7 +57,12 @@ import { useTheme } from '@table-library/react-table-library/theme';
|
|||||||
import type { Action, State } from '@table-library/react-table-library/types/common';
|
import type { Action, State } from '@table-library/react-table-library/types/common';
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import { useRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import { MessageBox, SectionContent, useLayoutTitle } from 'components';
|
import {
|
||||||
|
ButtonTooltip,
|
||||||
|
MessageBox,
|
||||||
|
SectionContent,
|
||||||
|
useLayoutTitle
|
||||||
|
} from 'components';
|
||||||
import { AuthenticatedContext } from 'contexts/authentication';
|
import { AuthenticatedContext } from 'contexts/authentication';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import { useInterval } from 'utils';
|
import { useInterval } from 'utils';
|
||||||
@@ -80,6 +85,7 @@ const Devices = () => {
|
|||||||
const [deviceValueDialogOpen, setDeviceValueDialogOpen] = useState(false);
|
const [deviceValueDialogOpen, setDeviceValueDialogOpen] = useState(false);
|
||||||
const [showDeviceInfo, setShowDeviceInfo] = useState(false);
|
const [showDeviceInfo, setShowDeviceInfo] = useState(false);
|
||||||
const [selectedDevice, setSelectedDevice] = useState<number>();
|
const [selectedDevice, setSelectedDevice] = useState<number>();
|
||||||
|
const [search, setSearch] = useState('');
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@@ -221,20 +227,6 @@ const Devices = () => {
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const ButtonTooltip = styled(({ className, ...props }: TooltipProps) => (
|
|
||||||
<Tooltip {...props} arrow classes={{ popper: className }} />
|
|
||||||
))(({ theme }) => ({
|
|
||||||
[`& .${tooltipClasses.arrow}`]: {
|
|
||||||
color: theme.palette.success.main
|
|
||||||
},
|
|
||||||
[`& .${tooltipClasses.tooltip}`]: {
|
|
||||||
backgroundColor: theme.palette.success.main,
|
|
||||||
color: 'rgba(0, 0, 0, 0.87)',
|
|
||||||
boxShadow: theme.shadows[1],
|
|
||||||
fontSize: 10
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
const getSortIcon = (state: State, sortKey: unknown) => {
|
const getSortIcon = (state: State, sortKey: unknown) => {
|
||||||
if (state.sortKey === sortKey && state.reverse) {
|
if (state.sortKey === sortKey && state.reverse) {
|
||||||
return <KeyboardArrowDownOutlinedIcon />;
|
return <KeyboardArrowDownOutlinedIcon />;
|
||||||
@@ -284,6 +276,7 @@ const Devices = () => {
|
|||||||
|
|
||||||
const resetDeviceSelect = () => {
|
const resetDeviceSelect = () => {
|
||||||
device_select.fns.onRemoveAll();
|
device_select.fns.onRemoveAll();
|
||||||
|
setSearch('');
|
||||||
};
|
};
|
||||||
|
|
||||||
const escFunction = useCallback(
|
const escFunction = useCallback(
|
||||||
@@ -419,7 +412,7 @@ const Devices = () => {
|
|||||||
if (!deviceValueDialogOpen) {
|
if (!deviceValueDialogOpen) {
|
||||||
selectedDevice ? void sendDeviceData(selectedDevice) : void sendCoreData();
|
selectedDevice ? void sendDeviceData(selectedDevice) : void sendCoreData();
|
||||||
}
|
}
|
||||||
}, 3000);
|
});
|
||||||
|
|
||||||
const deviceValueDialogSave = async (devicevalue: DeviceValue) => {
|
const deviceValueDialogSave = async (devicevalue: DeviceValue) => {
|
||||||
const id = Number(device_select.state.id);
|
const id = Number(device_select.state.id);
|
||||||
@@ -522,7 +515,7 @@ const Devices = () => {
|
|||||||
<IconContext.Provider
|
<IconContext.Provider
|
||||||
value={{
|
value={{
|
||||||
color: 'lightblue',
|
color: 'lightblue',
|
||||||
size: '16',
|
size: '18',
|
||||||
style: { verticalAlign: 'middle' }
|
style: { verticalAlign: 'middle' }
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -604,8 +597,14 @@ const Devices = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const shown_data = onlyFav
|
const shown_data = onlyFav
|
||||||
? deviceData.nodes.filter((dv) => hasMask(dv.id, DeviceEntityMask.DV_FAVORITE))
|
? deviceData.nodes.filter(
|
||||||
: deviceData.nodes;
|
(dv) =>
|
||||||
|
hasMask(dv.id, DeviceEntityMask.DV_FAVORITE) &&
|
||||||
|
dv.id.slice(2).toLowerCase().includes(search.toLowerCase())
|
||||||
|
)
|
||||||
|
: deviceData.nodes.filter((dv) =>
|
||||||
|
dv.id.slice(2).toLowerCase().includes(search.toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
const deviceIndex = coreData.devices.findIndex(
|
const deviceIndex = coreData.devices.findIndex(
|
||||||
(d) => d.id === device_select.state.id
|
(d) => d.id === device_select.state.id
|
||||||
@@ -628,56 +627,84 @@ const Devices = () => {
|
|||||||
border: '1px solid #177ac9'
|
border: '1px solid #177ac9'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ border: '1px solid #177ac9' }}>
|
<Box sx={{ p: 1 }}>
|
||||||
<Typography noWrap variant="subtitle1" color="warning.main" sx={{ ml: 1 }}>
|
|
||||||
{coreData.devices[deviceIndex].n} (
|
|
||||||
{coreData.devices[deviceIndex].tn})
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Grid container justifyContent="space-between">
|
<Grid container justifyContent="space-between">
|
||||||
<Typography sx={{ ml: 1 }} variant="subtitle2" color="grey">
|
<Typography noWrap variant="subtitle1" color="warning.main">
|
||||||
{LL.SHOWING() +
|
{coreData.devices[deviceIndex].n} (
|
||||||
' ' +
|
{coreData.devices[deviceIndex].tn})
|
||||||
shown_data.length +
|
|
||||||
'/' +
|
|
||||||
coreData.devices[deviceIndex].e +
|
|
||||||
' ' +
|
|
||||||
LL.ENTITIES(shown_data.length)}
|
|
||||||
<ButtonTooltip title="Info">
|
|
||||||
<IconButton onClick={() => setShowDeviceInfo(true)}>
|
|
||||||
<InfoOutlinedIcon color="primary" sx={{ fontSize: 18 }} />
|
|
||||||
</IconButton>
|
|
||||||
</ButtonTooltip>
|
|
||||||
{me.admin && (
|
|
||||||
<ButtonTooltip title={LL.CUSTOMIZATIONS()}>
|
|
||||||
<IconButton onClick={customize}>
|
|
||||||
<FormatListNumberedIcon color="primary" sx={{ fontSize: 18 }} />
|
|
||||||
</IconButton>
|
|
||||||
</ButtonTooltip>
|
|
||||||
)}
|
|
||||||
<ButtonTooltip title={LL.EXPORT()}>
|
|
||||||
<IconButton onClick={handleDownloadCsv}>
|
|
||||||
<DownloadIcon color="primary" sx={{ fontSize: 18 }} />
|
|
||||||
</IconButton>
|
|
||||||
</ButtonTooltip>
|
|
||||||
<ButtonTooltip title={LL.FAVORITES()}>
|
|
||||||
<IconButton onClick={() => setOnlyFav(!onlyFav)}>
|
|
||||||
{onlyFav ? (
|
|
||||||
<StarIcon color="primary" sx={{ fontSize: 18 }} />
|
|
||||||
) : (
|
|
||||||
<StarBorderOutlinedIcon color="primary" sx={{ fontSize: 18 }} />
|
|
||||||
)}
|
|
||||||
</IconButton>
|
|
||||||
</ButtonTooltip>
|
|
||||||
</Typography>
|
</Typography>
|
||||||
<Grid justifyContent="flex-end">
|
<Grid justifyContent="flex-end">
|
||||||
<ButtonTooltip title={LL.CANCEL()}>
|
<ButtonTooltip title={LL.CLOSE()}>
|
||||||
<IconButton onClick={resetDeviceSelect}>
|
<IconButton onClick={resetDeviceSelect}>
|
||||||
<HighlightOffIcon color="primary" sx={{ fontSize: 18 }} />
|
<HighlightOffIcon color="primary" sx={{ fontSize: 18 }} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</ButtonTooltip>
|
</ButtonTooltip>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
size="small"
|
||||||
|
variant="outlined"
|
||||||
|
sx={{ width: '22ch' }}
|
||||||
|
placeholder={LL.SEARCH()}
|
||||||
|
onChange={(event) => {
|
||||||
|
setSearch(event.target.value);
|
||||||
|
}}
|
||||||
|
slotProps={{
|
||||||
|
input: {
|
||||||
|
startAdornment: (
|
||||||
|
<InputAdornment position="start">
|
||||||
|
<SearchIcon color="primary" sx={{ fontSize: 16 }} />
|
||||||
|
</InputAdornment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ButtonTooltip title={LL.DEVICE_DETAILS()}>
|
||||||
|
<IconButton onClick={() => setShowDeviceInfo(true)}>
|
||||||
|
<InfoOutlinedIcon color="primary" sx={{ fontSize: 18 }} />
|
||||||
|
</IconButton>
|
||||||
|
</ButtonTooltip>
|
||||||
|
{me.admin && (
|
||||||
|
<ButtonTooltip title={LL.CUSTOMIZATIONS()}>
|
||||||
|
<IconButton onClick={customize}>
|
||||||
|
<ConstructionIcon color="primary" sx={{ fontSize: 18 }} />
|
||||||
|
</IconButton>
|
||||||
|
</ButtonTooltip>
|
||||||
|
)}
|
||||||
|
<ButtonTooltip title={LL.EXPORT()}>
|
||||||
|
<IconButton onClick={handleDownloadCsv}>
|
||||||
|
<DownloadIcon color="primary" sx={{ fontSize: 18 }} />
|
||||||
|
</IconButton>
|
||||||
|
</ButtonTooltip>
|
||||||
|
|
||||||
|
<ButtonTooltip title={LL.FAVORITES()}>
|
||||||
|
<ToggleButton
|
||||||
|
value="1"
|
||||||
|
size="small"
|
||||||
|
selected={onlyFav}
|
||||||
|
onChange={() => {
|
||||||
|
setOnlyFav(!onlyFav);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{onlyFav ? (
|
||||||
|
<StarIcon color="primary" sx={{ fontSize: 18 }} />
|
||||||
|
) : (
|
||||||
|
<StarBorderOutlinedIcon color="primary" sx={{ fontSize: 18 }} />
|
||||||
|
)}{' '}
|
||||||
|
</ToggleButton>
|
||||||
|
</ButtonTooltip>
|
||||||
|
|
||||||
|
<span style={{ color: 'grey', fontSize: '12px' }}>
|
||||||
|
|
||||||
|
{LL.SHOWING() +
|
||||||
|
' ' +
|
||||||
|
shown_data.length +
|
||||||
|
'/' +
|
||||||
|
coreData.devices[deviceIndex].e +
|
||||||
|
' ' +
|
||||||
|
LL.ENTITIES(shown_data.length)}
|
||||||
|
</span>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Table
|
<Table
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ import {
|
|||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
FormHelperText,
|
FormHelperText,
|
||||||
|
Grid,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
TextField,
|
TextField,
|
||||||
Typography
|
Typography
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import type Schema from 'async-validator';
|
import type Schema from 'async-validator';
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ const Help = () => {
|
|||||||
|
|
||||||
useRequest(() => callAction({ action: 'getCustomSupport' })).onSuccess((event) => {
|
useRequest(() => callAction({ action: 'getCustomSupport' })).onSuccess((event) => {
|
||||||
if (event && event.data && Object.keys(event.data).length !== 0) {
|
if (event && event.data && Object.keys(event.data).length !== 0) {
|
||||||
const data = event.data.Support;
|
const data = (event.data as { Support: { img_url?: string; html?: string[] } })
|
||||||
|
.Support;
|
||||||
if (data.img_url) {
|
if (data.img_url) {
|
||||||
setCustomSupportIMG(data.img_url);
|
setCustomSupportIMG(data.img_url);
|
||||||
}
|
}
|
||||||
@@ -51,20 +52,6 @@ const Help = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// const { send: sendExportAllValues } = useRequest(
|
|
||||||
// () => callAction({ action: 'export', param: 'allvalues' }),
|
|
||||||
// {
|
|
||||||
// immediate: false
|
|
||||||
// }
|
|
||||||
// )
|
|
||||||
// .onSuccess((event) => {
|
|
||||||
// saveFile(event.data, 'allvalues', '.txt');
|
|
||||||
// toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
|
||||||
// })
|
|
||||||
// .onError((error) => {
|
|
||||||
// toast.error(error.message);
|
|
||||||
// });
|
|
||||||
|
|
||||||
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
|
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
|
||||||
immediate: false
|
immediate: false
|
||||||
})
|
})
|
||||||
@@ -73,7 +60,7 @@ const Help = () => {
|
|||||||
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
||||||
})
|
})
|
||||||
.onError((error) => {
|
.onError((error) => {
|
||||||
toast.error(error.message);
|
toast.error(String(error.error?.message || 'An error occurred'));
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -114,7 +101,12 @@ const Help = () => {
|
|||||||
{me.admin && (
|
{me.admin && (
|
||||||
<List sx={{ borderRadius: 3, border: '2px solid grey' }}>
|
<List sx={{ borderRadius: 3, border: '2px solid grey' }}>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemButton component="a" href="https://docs.emsesp.org">
|
<ListItemButton
|
||||||
|
component="a"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
href="https://docs.emsesp.org"
|
||||||
|
>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<Avatar sx={{ bgcolor: '#72caf9' }}>
|
<Avatar sx={{ bgcolor: '#72caf9' }}>
|
||||||
<MenuBookIcon />
|
<MenuBookIcon />
|
||||||
@@ -125,7 +117,12 @@ const Help = () => {
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemButton component="a" href="https://discord.gg/3J3GgnzpyT">
|
<ListItemButton
|
||||||
|
component="a"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
href="https://discord.gg/3J3GgnzpyT"
|
||||||
|
>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<Avatar sx={{ bgcolor: '#72caf9' }}>
|
<Avatar sx={{ bgcolor: '#72caf9' }}>
|
||||||
<CommentIcon />
|
<CommentIcon />
|
||||||
@@ -138,6 +135,8 @@ const Help = () => {
|
|||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
component="a"
|
component="a"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
href="https://github.com/emsesp/EMS-ESP32/issues/new/choose"
|
href="https://github.com/emsesp/EMS-ESP32/issues/new/choose"
|
||||||
>
|
>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
@@ -165,21 +164,16 @@ const Help = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* <Button
|
|
||||||
sx={{ ml: 2 }}
|
|
||||||
startIcon={<DownloadIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
onClick={() => sendExportAllValues()}
|
|
||||||
>
|
|
||||||
{LL.DOWNLOAD(1)} {LL.ALLVALUES()}
|
|
||||||
</Button> */}
|
|
||||||
|
|
||||||
<Divider sx={{ mt: 4 }} />
|
<Divider sx={{ mt: 4 }} />
|
||||||
|
|
||||||
<Typography color="white" variant="subtitle1" align="center" mt={1}>
|
<Typography color="white" variant="subtitle1" align="center" mt={1}>
|
||||||
©
|
©
|
||||||
<Link target="_blank" href="https://emsesp.org" color="primary">
|
<Link
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
href="https://emsesp.org"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
{'emsesp.org'}
|
{'emsesp.org'}
|
||||||
</Link>
|
</Link>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import {
|
|||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
TextField
|
TextField
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import { BlockFormControlLabel } from 'components';
|
import { BlockFormControlLabel } from 'components';
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
useLayoutTitle
|
useLayoutTitle
|
||||||
} from 'components';
|
} from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
import { useInterval } from 'utils';
|
||||||
|
|
||||||
import { readSchedule, writeSchedule } from '../../api/app';
|
import { readSchedule, writeSchedule } from '../../api/app';
|
||||||
import SettingsSchedulerDialog from './SchedulerDialog';
|
import SettingsSchedulerDialog from './SchedulerDialog';
|
||||||
@@ -73,6 +74,12 @@ const Scheduler = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useInterval(() => {
|
||||||
|
if (numChanges === 0) {
|
||||||
|
void fetchSchedule();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const formatter = new Intl.DateTimeFormat(locale, {
|
const formatter = new Intl.DateTimeFormat(locale, {
|
||||||
weekday: 'short',
|
weekday: 'short',
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ import {
|
|||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
TextField,
|
TextField,
|
||||||
ToggleButton,
|
ToggleButton,
|
||||||
ToggleButtonGroup,
|
ToggleButtonGroup,
|
||||||
Typography
|
Typography
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import type Schema from 'async-validator';
|
import type Schema from 'async-validator';
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ const Sensors = () => {
|
|||||||
if (!temperatureDialogOpen && !analogDialogOpen) {
|
if (!temperatureDialogOpen && !analogDialogOpen) {
|
||||||
void fetchSensorData();
|
void fetchSensorData();
|
||||||
}
|
}
|
||||||
}, 3000);
|
});
|
||||||
|
|
||||||
const common_theme = useTheme({
|
const common_theme = useTheme({
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
@@ -439,7 +439,8 @@ const Sensors = () => {
|
|||||||
<Cell>{a.n}</Cell>
|
<Cell>{a.n}</Cell>
|
||||||
<Cell stiff>{AnalogTypeNames[a.t]} </Cell>
|
<Cell stiff>{AnalogTypeNames[a.t]} </Cell>
|
||||||
{(a.t === AnalogType.DIGITAL_OUT && a.g !== 25 && a.g !== 26) ||
|
{(a.t === AnalogType.DIGITAL_OUT && a.g !== 25 && a.g !== 26) ||
|
||||||
a.t === AnalogType.DIGITAL_IN ? (
|
a.t === AnalogType.DIGITAL_IN ||
|
||||||
|
a.t === AnalogType.PULSE ? (
|
||||||
<Cell stiff>{a.v ? LL.ON() : LL.OFF()}</Cell>
|
<Cell stiff>{a.v ? LL.ON() : LL.OFF()}</Cell>
|
||||||
) : (
|
) : (
|
||||||
<Cell stiff>{a.t ? formatValue(a.v, a.u) : ''}</Cell>
|
<Cell stiff>{a.t ? formatValue(a.v, a.u) : ''}</Cell>
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ import {
|
|||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
TextField,
|
TextField,
|
||||||
Typography
|
Typography
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import type Schema from 'async-validator';
|
import type Schema from 'async-validator';
|
||||||
@@ -132,7 +132,9 @@ const SensorsAnalogDialog = ({
|
|||||||
))}
|
))}
|
||||||
</TextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
{editItem.t >= AnalogType.COUNTER && editItem.t <= AnalogType.RATE && (
|
{((editItem.t >= AnalogType.COUNTER && editItem.t <= AnalogType.RATE) ||
|
||||||
|
(editItem.t >= AnalogType.FREQ_0 &&
|
||||||
|
editItem.t <= AnalogType.FREQ_2)) && (
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextField
|
<TextField
|
||||||
name="u"
|
name="u"
|
||||||
@@ -171,6 +173,27 @@ const SensorsAnalogDialog = ({
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
|
{editItem.t === AnalogType.NTC && (
|
||||||
|
<Grid>
|
||||||
|
<TextField
|
||||||
|
name="o"
|
||||||
|
label={LL.OFFSET()}
|
||||||
|
value={numberValue(editItem.o)}
|
||||||
|
sx={{ width: '11ch' }}
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
slotProps={{
|
||||||
|
input: {
|
||||||
|
startAdornment: (
|
||||||
|
<InputAdornment position="start">°C</InputAdornment>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
htmlInput: { min: '-20', max: '20', step: '0.1' }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
{editItem.t === AnalogType.COUNTER && (
|
{editItem.t === AnalogType.COUNTER && (
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextField
|
<TextField
|
||||||
@@ -187,6 +210,19 @@ const SensorsAnalogDialog = ({
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
|
{editItem.t === AnalogType.RGB && (
|
||||||
|
<Grid>
|
||||||
|
<TextField
|
||||||
|
name="o"
|
||||||
|
label={'RGB ' + LL.VALUE(0)}
|
||||||
|
value={numberValue(editItem.o)}
|
||||||
|
type="number"
|
||||||
|
sx={{ width: '11ch' }}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
{editItem.t >= AnalogType.COUNTER && editItem.t <= AnalogType.RATE && (
|
{editItem.t >= AnalogType.COUNTER && editItem.t <= AnalogType.RATE && (
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextField
|
<TextField
|
||||||
@@ -314,6 +350,42 @@ const SensorsAnalogDialog = ({
|
|||||||
</Grid>
|
</Grid>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{editItem.t === AnalogType.PULSE && (
|
||||||
|
<>
|
||||||
|
<Grid>
|
||||||
|
<TextField
|
||||||
|
name="o"
|
||||||
|
label={LL.POLARITY()}
|
||||||
|
value={editItem.o}
|
||||||
|
sx={{ width: '11ch' }}
|
||||||
|
select
|
||||||
|
onChange={updateFormValue}
|
||||||
|
>
|
||||||
|
<MenuItem value={0}>{LL.ACTIVEHIGH()}</MenuItem>
|
||||||
|
<MenuItem value={1}>{LL.ACTIVELOW()}</MenuItem>
|
||||||
|
</TextField>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<TextField
|
||||||
|
name="f"
|
||||||
|
label="Pulse"
|
||||||
|
value={numberValue(editItem.f)}
|
||||||
|
type="number"
|
||||||
|
sx={{ width: '15ch' }}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
slotProps={{
|
||||||
|
input: {
|
||||||
|
startAdornment: (
|
||||||
|
<InputAdornment position="start">s</InputAdornment>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
htmlInput: { min: '0', max: '10000', step: '0.1' }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import {
|
|||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
TextField,
|
TextField,
|
||||||
Typography
|
Typography
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import type Schema from 'async-validator';
|
import type Schema from 'async-validator';
|
||||||
|
|||||||
@@ -34,7 +34,12 @@ export function formatValue(
|
|||||||
if (value === undefined || typeof value === 'boolean') {
|
if (value === undefined || typeof value === 'boolean') {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return value as string;
|
return (
|
||||||
|
(value as string) +
|
||||||
|
(value === '' || uom === undefined || uom === 0
|
||||||
|
? ''
|
||||||
|
: ' ' + DeviceValueUOM_s[uom])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (uom) {
|
switch (uom) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export interface Settings {
|
|||||||
dallas_gpio: number;
|
dallas_gpio: number;
|
||||||
dallas_parasite: boolean;
|
dallas_parasite: boolean;
|
||||||
led_gpio: number;
|
led_gpio: number;
|
||||||
|
led_type: number;
|
||||||
hide_led: boolean;
|
hide_led: boolean;
|
||||||
low_clock: boolean;
|
low_clock: boolean;
|
||||||
notoken_api: boolean;
|
notoken_api: boolean;
|
||||||
@@ -71,7 +72,7 @@ export interface Device {
|
|||||||
d: number; // deviceid
|
d: number; // deviceid
|
||||||
p: number; // productid
|
p: number; // productid
|
||||||
v: string; // version
|
v: string; // version
|
||||||
e: number; // entities
|
e: number; // total number of entities
|
||||||
url?: string; // lowercase type name used in API URL
|
url?: string; // lowercase type name used in API URL
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +124,11 @@ export interface DashboardItem {
|
|||||||
nodes?: DashboardItem[]; // children nodes, optional
|
nodes?: DashboardItem[]; // children nodes, optional
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DashboardData {
|
||||||
|
connected: boolean; // true if connected to EMS bus
|
||||||
|
nodes: DashboardItem[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface DeviceValue {
|
export interface DeviceValue {
|
||||||
id: string; // index, contains mask+name
|
id: string; // index, contains mask+name
|
||||||
v?: unknown; // value, Number, String or Boolean - can be undefined
|
v?: unknown; // value, Number, String or Boolean - can be undefined
|
||||||
@@ -182,7 +188,8 @@ export enum DeviceValueUOM {
|
|||||||
VOLTS,
|
VOLTS,
|
||||||
MBAR,
|
MBAR,
|
||||||
LH,
|
LH,
|
||||||
CTKWH
|
CTKWH,
|
||||||
|
HZ
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DeviceValueUOM_s = [
|
export const DeviceValueUOM_s = [
|
||||||
@@ -212,7 +219,8 @@ export const DeviceValueUOM_s = [
|
|||||||
'V',
|
'V',
|
||||||
'mbar',
|
'mbar',
|
||||||
'l/h',
|
'l/h',
|
||||||
'ct/kWh'
|
'ct/kWh',
|
||||||
|
'Hz'
|
||||||
];
|
];
|
||||||
|
|
||||||
export enum AnalogType {
|
export enum AnalogType {
|
||||||
@@ -226,20 +234,32 @@ export enum AnalogType {
|
|||||||
DIGITAL_OUT = 6,
|
DIGITAL_OUT = 6,
|
||||||
PWM_0 = 7,
|
PWM_0 = 7,
|
||||||
PWM_1 = 8,
|
PWM_1 = 8,
|
||||||
PWM_2 = 9
|
PWM_2 = 9,
|
||||||
|
NTC = 10,
|
||||||
|
RGB = 11,
|
||||||
|
PULSE = 12,
|
||||||
|
FREQ_0 = 13,
|
||||||
|
FREQ_1 = 14,
|
||||||
|
FREQ_2 = 15
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AnalogTypeNames = [
|
export const AnalogTypeNames = [
|
||||||
'(disabled)',
|
'(disabled)',
|
||||||
'Digital In',
|
'Digital In',
|
||||||
'Counter',
|
'Counter',
|
||||||
'ADC',
|
'ADC In',
|
||||||
'Timer',
|
'Timer',
|
||||||
'Rate',
|
'Rate',
|
||||||
'Digital Out',
|
'Digital Out',
|
||||||
'PWM 0',
|
'PWM 0',
|
||||||
'PWM 1',
|
'PWM 1',
|
||||||
'PWM 2'
|
'PWM 2',
|
||||||
|
'NTC Temp.',
|
||||||
|
'RGB Led',
|
||||||
|
'Pulse',
|
||||||
|
'Freq 0',
|
||||||
|
'Freq 1',
|
||||||
|
'Freq 2'
|
||||||
];
|
];
|
||||||
|
|
||||||
type BoardProfiles = Record<string, string>;
|
type BoardProfiles = Record<string, string>;
|
||||||
@@ -249,6 +269,7 @@ export const BOARD_PROFILES: BoardProfiles = {
|
|||||||
S32S3: 'BBQKees Gateway S3',
|
S32S3: 'BBQKees Gateway S3',
|
||||||
E32: 'BBQKees Gateway E32',
|
E32: 'BBQKees Gateway E32',
|
||||||
E32V2: 'BBQKees Gateway E32 V2',
|
E32V2: 'BBQKees Gateway E32 V2',
|
||||||
|
E32V2_2: 'BBQKees Gateway E32 V2.2',
|
||||||
NODEMCU: 'NodeMCU 32S',
|
NODEMCU: 'NodeMCU 32S',
|
||||||
'MH-ET': 'MH-ET Live D1 Mini',
|
'MH-ET': 'MH-ET Live D1 Mini',
|
||||||
LOLIN: 'Lolin D32',
|
LOLIN: 'Lolin D32',
|
||||||
@@ -262,6 +283,7 @@ export const BOARD_PROFILES: BoardProfiles = {
|
|||||||
export interface BoardProfile {
|
export interface BoardProfile {
|
||||||
board_profile: string;
|
board_profile: string;
|
||||||
led_gpio: number;
|
led_gpio: number;
|
||||||
|
led_type: number;
|
||||||
dallas_gpio: number;
|
dallas_gpio: number;
|
||||||
rx_gpio: number;
|
rx_gpio: number;
|
||||||
tx_gpio: number;
|
tx_gpio: number;
|
||||||
@@ -368,11 +390,12 @@ export interface EntityItem {
|
|||||||
device_id: number | string;
|
device_id: number | string;
|
||||||
type_id: number | string;
|
type_id: number | string;
|
||||||
offset: number;
|
offset: number;
|
||||||
factor: number;
|
factor: number | string;
|
||||||
uom: number;
|
uom: number;
|
||||||
value_type: number;
|
value_type: number;
|
||||||
value?: unknown;
|
value?: unknown;
|
||||||
writeable: boolean;
|
writeable: boolean;
|
||||||
|
hide: boolean;
|
||||||
deleted?: boolean;
|
deleted?: boolean;
|
||||||
o_id?: number;
|
o_id?: number;
|
||||||
o_ram?: number;
|
o_ram?: number;
|
||||||
@@ -380,12 +403,13 @@ export interface EntityItem {
|
|||||||
o_device_id?: number | string;
|
o_device_id?: number | string;
|
||||||
o_type_id?: number | string;
|
o_type_id?: number | string;
|
||||||
o_offset?: number;
|
o_offset?: number;
|
||||||
o_factor?: number;
|
o_factor?: number | string;
|
||||||
o_uom?: number;
|
o_uom?: number;
|
||||||
o_value_type?: number;
|
o_value_type?: number;
|
||||||
o_deleted?: boolean;
|
o_deleted?: boolean;
|
||||||
o_writeable?: boolean;
|
o_writeable?: boolean;
|
||||||
o_value?: unknown;
|
o_value?: unknown;
|
||||||
|
o_hide?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Entities {
|
export interface Entities {
|
||||||
|
|||||||
@@ -382,10 +382,7 @@ export const entityItemValidation = (entity: EntityItem[], entityItem: EntityIte
|
|||||||
{ required: true, message: 'Offset is required' },
|
{ required: true, message: 'Offset is required' },
|
||||||
{ type: 'number', min: 0, max: 255, message: 'Must be between 0 and 255' }
|
{ type: 'number', min: 0, max: 255, message: 'Must be between 0 and 255' }
|
||||||
],
|
],
|
||||||
factor: [
|
factor: [{ required: true, message: 'is required' }]
|
||||||
{ required: true, message: 'is required' },
|
|
||||||
{ type: 'number', message: 'Must be a number' }
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const uniqueTemperatureNameValidator = (
|
export const uniqueTemperatureNameValidator = (
|
||||||
|
|||||||
@@ -9,17 +9,17 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Divider,
|
Divider,
|
||||||
|
Grid,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
TextField,
|
TextField,
|
||||||
Typography
|
Typography
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { readSystemStatus } from 'api/system';
|
import { readSystemStatus } from 'api/system';
|
||||||
|
|
||||||
import { useRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import RestartMonitor from 'app/status/RestartMonitor';
|
import SystemMonitor from 'app/status/SystemMonitor';
|
||||||
import type { ValidateFieldsError } from 'async-validator';
|
import type { ValidateFieldsError } from 'async-validator';
|
||||||
import {
|
import {
|
||||||
BlockFormControlLabel,
|
BlockFormControlLabel,
|
||||||
@@ -126,9 +126,6 @@ const ApplicationSettings = () => {
|
|||||||
const SecondsInputProps = {
|
const SecondsInputProps = {
|
||||||
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
|
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
|
||||||
};
|
};
|
||||||
const MilliSecondsInputProps = {
|
|
||||||
endAdornment: <InputAdornment position="end">ms</InputAdornment>
|
|
||||||
};
|
|
||||||
const MinutesInputProps = {
|
const MinutesInputProps = {
|
||||||
endAdornment: <InputAdornment position="end">{LL.MINUTES()}</InputAdornment>
|
endAdornment: <InputAdornment position="end">{LL.MINUTES()}</InputAdornment>
|
||||||
};
|
};
|
||||||
@@ -207,7 +204,16 @@ const ApplicationSettings = () => {
|
|||||||
disabled={!hardwareData.psram}
|
disabled={!hardwareData.psram}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={LL.ENABLE_MODBUS()}
|
label={
|
||||||
|
<Typography color={!hardwareData.psram ? 'grey' : 'default'}>
|
||||||
|
{LL.ENABLE_MODBUS()}
|
||||||
|
{!hardwareData.psram && (
|
||||||
|
<Typography variant="caption">
|
||||||
|
({LL.IS_REQUIRED('PSRAM')})
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
{data.modbus_enabled && (
|
{data.modbus_enabled && (
|
||||||
<Grid container spacing={2} rowSpacing={0}>
|
<Grid container spacing={2} rowSpacing={0}>
|
||||||
@@ -241,7 +247,7 @@ const ApplicationSettings = () => {
|
|||||||
name="modbus_timeout"
|
name="modbus_timeout"
|
||||||
label="Timeout"
|
label="Timeout"
|
||||||
slotProps={{
|
slotProps={{
|
||||||
input: MilliSecondsInputProps
|
input: SecondsInputProps
|
||||||
}}
|
}}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={numberValue(data.modbus_timeout)}
|
value={numberValue(data.modbus_timeout)}
|
||||||
@@ -544,6 +550,23 @@ const ApplicationSettings = () => {
|
|||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{data.led_gpio !== 0 && (
|
||||||
|
<Grid>
|
||||||
|
<TextField
|
||||||
|
name="led_type"
|
||||||
|
label={'LED ' + LL.TYPE(0)}
|
||||||
|
value={data.led_type}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
margin="normal"
|
||||||
|
select
|
||||||
|
>
|
||||||
|
<MenuItem value={0}>LED</MenuItem>
|
||||||
|
<MenuItem value={1}>RGB-LED</MenuItem>
|
||||||
|
</TextField>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextField
|
<TextField
|
||||||
name="phy_type"
|
name="phy_type"
|
||||||
@@ -853,7 +876,7 @@ const ApplicationSettings = () => {
|
|||||||
return (
|
return (
|
||||||
<SectionContent>
|
<SectionContent>
|
||||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||||
{restarting ? <RestartMonitor /> : content()}
|
{restarting ? <SystemMonitor /> : content()}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,15 +2,14 @@ import { useState } from 'react';
|
|||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||||
import { Box, Button, Typography } from '@mui/material';
|
import { Box, Button, Grid, Typography } from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import * as SystemApi from 'api/system';
|
import * as SystemApi from 'api/system';
|
||||||
import { API, callAction } from 'api/app';
|
import { API, callAction } from 'api/app';
|
||||||
|
|
||||||
import { useRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import type { APIcall } from 'app/main/types';
|
import type { APIcall } from 'app/main/types';
|
||||||
import RestartMonitor from 'app/status/RestartMonitor';
|
import SystemMonitor from 'app/status/SystemMonitor';
|
||||||
import {
|
import {
|
||||||
FormLoader,
|
FormLoader,
|
||||||
SectionContent,
|
SectionContent,
|
||||||
@@ -36,7 +35,7 @@ const DownloadUpload = () => {
|
|||||||
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
||||||
})
|
})
|
||||||
.onError((error) => {
|
.onError((error) => {
|
||||||
toast.error(error.message);
|
toast.error(String(error.error?.message || 'An error occurred'));
|
||||||
});
|
});
|
||||||
|
|
||||||
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
|
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
|
||||||
@@ -109,6 +108,15 @@ const DownloadUpload = () => {
|
|||||||
{LL.SCHEDULE(0)}
|
{LL.SCHEDULE(0)}
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Button
|
||||||
|
sx={{ ml: 2, mt: 2 }}
|
||||||
|
startIcon={<DownloadIcon />}
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
onClick={() => sendExportData('allvalues')}
|
||||||
|
>
|
||||||
|
{LL.ALLVALUES()}
|
||||||
|
</Button>
|
||||||
|
|
||||||
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||||
{LL.UPLOAD()}
|
{LL.UPLOAD()}
|
||||||
@@ -118,13 +126,13 @@ const DownloadUpload = () => {
|
|||||||
<Typography variant="body1">{LL.UPLOAD_TEXT()}.</Typography>
|
<Typography variant="body1">{LL.UPLOAD_TEXT()}.</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<SingleUpload doRestart={doRestart} />
|
<SingleUpload text={LL.UPLOAD_DRAG()} doRestart={doRestart} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
|
<SectionContent>{restarting ? <SystemMonitor /> : content()}</SectionContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import WarningIcon from '@mui/icons-material/Warning';
|
|||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
|
Grid,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
TextField,
|
TextField,
|
||||||
Typography
|
Typography
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import * as MqttApi from 'api/mqtt';
|
import * as MqttApi from 'api/mqtt';
|
||||||
|
|
||||||
@@ -254,102 +254,100 @@ const MqttSettings = () => {
|
|||||||
}
|
}
|
||||||
label={LL.MQTT_RESPONSE()}
|
label={LL.MQTT_RESPONSE()}
|
||||||
/>
|
/>
|
||||||
{!data.ha_enabled && (
|
<Grid container spacing={2} rowSpacing={0}>
|
||||||
<Grid container spacing={2} rowSpacing={0}>
|
<Grid>
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
name="publish_single"
|
||||||
|
checked={data.publish_single}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
disabled={data.ha_enabled}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={LL.MQTT_PUBLISH_TEXT_1()}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
{data.publish_single && (
|
||||||
<Grid>
|
<Grid>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
name="publish_single"
|
name="publish_single2cmd"
|
||||||
checked={data.publish_single}
|
checked={data.publish_single2cmd}
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={LL.MQTT_PUBLISH_TEXT_1()}
|
label={LL.MQTT_PUBLISH_TEXT_2()}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
{data.publish_single && (
|
)}
|
||||||
|
</Grid>
|
||||||
|
<Grid container spacing={2} rowSpacing={0}>
|
||||||
|
<Grid>
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
name="ha_enabled"
|
||||||
|
checked={data.ha_enabled}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
disabled={data.publish_single}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={LL.MQTT_PUBLISH_TEXT_3()}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
{data.ha_enabled && (
|
||||||
|
<Grid container spacing={2} rowSpacing={0}>
|
||||||
<Grid>
|
<Grid>
|
||||||
<BlockFormControlLabel
|
<TextField
|
||||||
control={
|
name="discovery_type"
|
||||||
<Checkbox
|
label={LL.MQTT_PUBLISH_TEXT_5()}
|
||||||
name="publish_single2cmd"
|
value={data.discovery_type}
|
||||||
checked={data.publish_single2cmd}
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
/>
|
margin="normal"
|
||||||
}
|
select
|
||||||
label={LL.MQTT_PUBLISH_TEXT_2()}
|
>
|
||||||
|
<MenuItem value={0}>Home Assistant</MenuItem>
|
||||||
|
<MenuItem value={1}>Domoticz</MenuItem>
|
||||||
|
<MenuItem value={2}>Domoticz (latest)</MenuItem>
|
||||||
|
</TextField>
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<TextField
|
||||||
|
name="discovery_prefix"
|
||||||
|
label={LL.MQTT_PUBLISH_TEXT_4()}
|
||||||
|
variant="outlined"
|
||||||
|
value={data.discovery_prefix}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
<Grid>
|
||||||
</Grid>
|
<TextField
|
||||||
)}
|
name="entity_format"
|
||||||
{!data.publish_single && (
|
label={LL.MQTT_ENTITY_FORMAT()}
|
||||||
<Grid container spacing={2} rowSpacing={0}>
|
value={data.entity_format}
|
||||||
<Grid>
|
variant="outlined"
|
||||||
<BlockFormControlLabel
|
onChange={updateFormValue}
|
||||||
control={
|
margin="normal"
|
||||||
<Checkbox
|
select
|
||||||
name="ha_enabled"
|
>
|
||||||
checked={data.ha_enabled}
|
<MenuItem value={0}>{LL.MQTT_ENTITY_FORMAT_0()}</MenuItem>
|
||||||
onChange={updateFormValue}
|
<MenuItem value={3}>
|
||||||
/>
|
{LL.MQTT_ENTITY_FORMAT_1()} (v3.6)
|
||||||
}
|
</MenuItem>
|
||||||
label={LL.MQTT_PUBLISH_TEXT_3()}
|
<MenuItem value={4}>
|
||||||
/>
|
{LL.MQTT_ENTITY_FORMAT_2()} (v3.6)
|
||||||
</Grid>
|
</MenuItem>
|
||||||
{data.ha_enabled && (
|
<MenuItem value={1}>{LL.MQTT_ENTITY_FORMAT_1()}</MenuItem>
|
||||||
<Grid container spacing={2} rowSpacing={0}>
|
<MenuItem value={2}>{LL.MQTT_ENTITY_FORMAT_2()}</MenuItem>
|
||||||
<Grid>
|
</TextField>
|
||||||
<TextField
|
|
||||||
name="discovery_type"
|
|
||||||
label={LL.MQTT_PUBLISH_TEXT_5()}
|
|
||||||
value={data.discovery_type}
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
select
|
|
||||||
>
|
|
||||||
<MenuItem value={0}>Home Assistant</MenuItem>
|
|
||||||
<MenuItem value={1}>Domoticz</MenuItem>
|
|
||||||
<MenuItem value={2}>Domoticz (latest)</MenuItem>
|
|
||||||
</TextField>
|
|
||||||
</Grid>
|
|
||||||
<Grid>
|
|
||||||
<TextField
|
|
||||||
name="discovery_prefix"
|
|
||||||
label={LL.MQTT_PUBLISH_TEXT_4()}
|
|
||||||
variant="outlined"
|
|
||||||
value={data.discovery_prefix}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid>
|
|
||||||
<TextField
|
|
||||||
name="entity_format"
|
|
||||||
label={LL.MQTT_ENTITY_FORMAT()}
|
|
||||||
value={data.entity_format}
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
select
|
|
||||||
>
|
|
||||||
<MenuItem value={0}>{LL.MQTT_ENTITY_FORMAT_0()}</MenuItem>
|
|
||||||
<MenuItem value={3}>
|
|
||||||
{LL.MQTT_ENTITY_FORMAT_1()} (v3.6)
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem value={4}>
|
|
||||||
{LL.MQTT_ENTITY_FORMAT_2()} (v3.6)
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem value={1}>{LL.MQTT_ENTITY_FORMAT_1()}</MenuItem>
|
|
||||||
<MenuItem value={2}>{LL.MQTT_ENTITY_FORMAT_2()}</MenuItem>
|
|
||||||
</TextField>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
</Grid>
|
||||||
</Grid>
|
)}
|
||||||
)}
|
</Grid>
|
||||||
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
||||||
{LL.MQTT_PUBLISH_INTERVALS()} (0=auto)
|
{LL.MQTT_PUBLISH_INTERVALS()} (0=auto)
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -442,7 +440,7 @@ const MqttSettings = () => {
|
|||||||
<Grid>
|
<Grid>
|
||||||
<TextField
|
<TextField
|
||||||
name="publish_time_sensor"
|
name="publish_time_sensor"
|
||||||
label={LL.TEMP_SENSORS()}
|
label={LL.SENSORS()}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={numberValue(data.publish_time_sensor)}
|
value={numberValue(data.publish_time_sensor)}
|
||||||
type="number"
|
type="number"
|
||||||
|
|||||||
@@ -1,12 +1,27 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import { Button, Checkbox, MenuItem } from '@mui/material';
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
MenuItem,
|
||||||
|
TextField,
|
||||||
|
Typography
|
||||||
|
} from '@mui/material';
|
||||||
|
|
||||||
import * as NTPApi from 'api/ntp';
|
import * as NTPApi from 'api/ntp';
|
||||||
import { readNTPSettings } from 'api/ntp';
|
import { readNTPSettings } from 'api/ntp';
|
||||||
|
|
||||||
|
import { dialogStyle } from 'CustomTheme';
|
||||||
|
import { useRequest } from 'alova/client';
|
||||||
import { updateState } from 'alova/client';
|
import { updateState } from 'alova/client';
|
||||||
import type { ValidateFieldsError } from 'async-validator';
|
import type { ValidateFieldsError } from 'async-validator';
|
||||||
import {
|
import {
|
||||||
@@ -19,8 +34,8 @@ import {
|
|||||||
useLayoutTitle
|
useLayoutTitle
|
||||||
} from 'components';
|
} from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import type { NTPSettingsType } from 'types';
|
import type { NTPSettingsType, Time } from 'types';
|
||||||
import { updateValueDirty, useRest } from 'utils';
|
import { formatLocalDateTime, updateValueDirty, useRest } from 'utils';
|
||||||
import { validate } from 'validators';
|
import { validate } from 'validators';
|
||||||
import { NTP_SETTINGS_VALIDATOR } from 'validators/ntp';
|
import { NTP_SETTINGS_VALIDATOR } from 'validators/ntp';
|
||||||
|
|
||||||
@@ -46,6 +61,17 @@ const NTPSettings = () => {
|
|||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
useLayoutTitle('NTP');
|
useLayoutTitle('NTP');
|
||||||
|
|
||||||
|
const [localTime, setLocalTime] = useState<string>('');
|
||||||
|
const [settingTime, setSettingTime] = useState<boolean>(false);
|
||||||
|
const [processing, setProcessing] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const { send: updateTime } = useRequest(
|
||||||
|
(local_time: Time) => NTPApi.updateTime(local_time),
|
||||||
|
{
|
||||||
|
immediate: false
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const updateFormValue = updateValueDirty(
|
const updateFormValue = updateValueDirty(
|
||||||
origData,
|
origData,
|
||||||
dirtyFlags,
|
dirtyFlags,
|
||||||
@@ -55,6 +81,78 @@ const NTPSettings = () => {
|
|||||||
|
|
||||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
|
|
||||||
|
const updateLocalTime = (event: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
|
setLocalTime(event.target.value);
|
||||||
|
|
||||||
|
const openSetTime = () => {
|
||||||
|
setLocalTime(formatLocalDateTime(new Date()));
|
||||||
|
setSettingTime(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const configureTime = async () => {
|
||||||
|
setProcessing(true);
|
||||||
|
|
||||||
|
await updateTime({ local_time: formatLocalDateTime(new Date(localTime)) })
|
||||||
|
.then(async () => {
|
||||||
|
toast.success(LL.TIME_SET());
|
||||||
|
setSettingTime(false);
|
||||||
|
await loadData();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
toast.error(LL.PROBLEM_UPDATING());
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setProcessing(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderSetTimeDialog = () => (
|
||||||
|
<Dialog
|
||||||
|
sx={dialogStyle}
|
||||||
|
open={settingTime}
|
||||||
|
onClose={() => setSettingTime(false)}
|
||||||
|
>
|
||||||
|
<DialogTitle>{LL.SET_TIME(1)}</DialogTitle>
|
||||||
|
<DialogContent dividers>
|
||||||
|
<Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}>
|
||||||
|
<Typography variant="body2">{LL.SET_TIME_TEXT()}</Typography>
|
||||||
|
</Box>
|
||||||
|
<TextField
|
||||||
|
label={LL.LOCAL_TIME(0)}
|
||||||
|
type="datetime-local"
|
||||||
|
value={localTime}
|
||||||
|
onChange={updateLocalTime}
|
||||||
|
disabled={processing}
|
||||||
|
fullWidth
|
||||||
|
slotProps={{
|
||||||
|
inputLabel: {
|
||||||
|
shrink: true
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button
|
||||||
|
startIcon={<CancelIcon />}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => setSettingTime(false)}
|
||||||
|
color="secondary"
|
||||||
|
>
|
||||||
|
{LL.CANCEL()}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
startIcon={<AccessTimeIcon />}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={configureTime}
|
||||||
|
disabled={processing}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
{LL.UPDATE()}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
|
||||||
const content = () => {
|
const content = () => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return <FormLoader onRetry={loadData} errorMessage={errorMessage} />;
|
return <FormLoader onRetry={loadData} errorMessage={errorMessage} />;
|
||||||
@@ -115,6 +213,25 @@ const NTPSettings = () => {
|
|||||||
<MenuItem disabled>{LL.TIME_ZONE()}...</MenuItem>
|
<MenuItem disabled>{LL.TIME_ZONE()}...</MenuItem>
|
||||||
{timeZoneSelectItems()}
|
{timeZoneSelectItems()}
|
||||||
</ValidatedTextField>
|
</ValidatedTextField>
|
||||||
|
|
||||||
|
<Box display="flex" flexWrap="wrap">
|
||||||
|
{!data.enabled && !dirtyFlags.length && (
|
||||||
|
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
||||||
|
<ButtonRow>
|
||||||
|
<Button
|
||||||
|
onClick={openSetTime}
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
startIcon={<AccessTimeIcon />}
|
||||||
|
>
|
||||||
|
{LL.SET_TIME(0)}
|
||||||
|
</Button>
|
||||||
|
</ButtonRow>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
{renderSetTimeDialog()}
|
||||||
|
|
||||||
{dirtyFlags && dirtyFlags.length !== 0 && (
|
{dirtyFlags && dirtyFlags.length !== 0 && (
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||||
import BuildIcon from '@mui/icons-material/Build';
|
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||||
import ImportExportIcon from '@mui/icons-material/ImportExport';
|
import ImportExportIcon from '@mui/icons-material/ImportExport';
|
||||||
@@ -21,7 +20,7 @@ import {
|
|||||||
List
|
List
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
|
||||||
import { API, callAction } from 'api/app';
|
import { API } from 'api/app';
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import { useRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
@@ -40,11 +39,6 @@ const Settings = () => {
|
|||||||
immediate: false
|
immediate: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// call checkUpgrade with no param to fetch EMS-ESP version
|
|
||||||
const { data } = useRequest(() => callAction({ action: 'checkUpgrade' }), {
|
|
||||||
initialData: { emsesp_version: '...' }
|
|
||||||
});
|
|
||||||
|
|
||||||
const doFormat = async () => {
|
const doFormat = async () => {
|
||||||
await sendAPI({ device: 'system', cmd: 'format', id: 0 }).then(() => {
|
await sendAPI({ device: 'system', cmd: 'format', id: 0 }).then(() => {
|
||||||
setConfirmFactoryReset(false);
|
setConfirmFactoryReset(false);
|
||||||
@@ -83,14 +77,6 @@ const Settings = () => {
|
|||||||
const content = () => (
|
const content = () => (
|
||||||
<>
|
<>
|
||||||
<List sx={{ borderRadius: 3, border: '2px solid grey' }}>
|
<List sx={{ borderRadius: 3, border: '2px solid grey' }}>
|
||||||
<ListMenuItem
|
|
||||||
icon={BuildIcon}
|
|
||||||
bgcolor="#72caf9"
|
|
||||||
label="EMS-ESP Firmware"
|
|
||||||
text={'v' + data.emsesp_version}
|
|
||||||
to="version"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ListMenuItem
|
<ListMenuItem
|
||||||
icon={TuneIcon}
|
icon={TuneIcon}
|
||||||
bgcolor="#134ba2"
|
bgcolor="#134ba2"
|
||||||
@@ -151,7 +137,7 @@ const Settings = () => {
|
|||||||
bgcolor="#5d89f7"
|
bgcolor="#5d89f7"
|
||||||
label={LL.DOWNLOAD_UPLOAD()}
|
label={LL.DOWNLOAD_UPLOAD()}
|
||||||
text={LL.DOWNLOAD_UPLOAD_1()}
|
text={LL.DOWNLOAD_UPLOAD_1()}
|
||||||
to="upload"
|
to="downloadUpload"
|
||||||
/>
|
/>
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
|
|||||||
@@ -1,344 +0,0 @@
|
|||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { toast } from 'react-toastify';
|
|
||||||
|
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
|
||||||
import CheckIcon from '@mui/icons-material/Done';
|
|
||||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
|
||||||
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
Dialog,
|
|
||||||
DialogActions,
|
|
||||||
DialogContent,
|
|
||||||
DialogTitle,
|
|
||||||
Link,
|
|
||||||
Typography
|
|
||||||
} from '@mui/material';
|
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import * as SystemApi from 'api/system';
|
|
||||||
import { callAction } from 'api/app';
|
|
||||||
import { getDevVersion, getStableVersion } from 'api/system';
|
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
|
||||||
import { useRequest } from 'alova/client';
|
|
||||||
import RestartMonitor from 'app/status/RestartMonitor';
|
|
||||||
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
|
||||||
|
|
||||||
const Version = () => {
|
|
||||||
const { LL } = useI18nContext();
|
|
||||||
const [restarting, setRestarting] = useState<boolean>(false);
|
|
||||||
const [openInstallDialog, setOpenInstallDialog] = useState<boolean>(false);
|
|
||||||
const [usingDevVersion, setUsingDevVersion] = useState<boolean>(false);
|
|
||||||
const [upgradeAvailable, setUpgradeAvailable] = useState<boolean>(false);
|
|
||||||
const [internetLive, setInternetLive] = useState<boolean>(false);
|
|
||||||
const [downloadOnly, setDownloadOnly] = useState<boolean>(false);
|
|
||||||
|
|
||||||
const STABLE_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/';
|
|
||||||
const STABLE_RELNOTES_URL =
|
|
||||||
'https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md';
|
|
||||||
|
|
||||||
const DEV_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/latest/';
|
|
||||||
const DEV_RELNOTES_URL =
|
|
||||||
'https://github.com/emsesp/EMS-ESP32/blob/dev/CHANGELOG_LATEST.md';
|
|
||||||
|
|
||||||
const { send: sendCheckUpgrade } = useRequest(
|
|
||||||
(versions: string) => callAction({ action: 'checkUpgrade', param: versions }),
|
|
||||||
{
|
|
||||||
immediate: false
|
|
||||||
}
|
|
||||||
).onSuccess((event) => {
|
|
||||||
const data = event.data as { emsesp_version: string; upgradeable: boolean };
|
|
||||||
setUpgradeAvailable(data.upgradeable);
|
|
||||||
});
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: data,
|
|
||||||
send: loadData,
|
|
||||||
error
|
|
||||||
} = useRequest(SystemApi.readSystemStatus).onSuccess((event) => {
|
|
||||||
// older version of EMS-ESP didn't have the psram set, so we can't do an OTA upgrade
|
|
||||||
setDownloadOnly(event.data.psram === undefined);
|
|
||||||
setUsingDevVersion(event.data.emsesp_version.includes('dev'));
|
|
||||||
});
|
|
||||||
|
|
||||||
const { send: sendUploadURL } = useRequest(
|
|
||||||
(url: string) => callAction({ action: 'uploadURL', param: url }),
|
|
||||||
{
|
|
||||||
immediate: false
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// called immediately to get the latest versions on page load
|
|
||||||
const { data: latestVersion } = useRequest(getStableVersion);
|
|
||||||
const { data: latestDevVersion } = useRequest(getDevVersion);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (latestVersion && latestDevVersion) {
|
|
||||||
sendCheckUpgrade(latestDevVersion + ',' + latestVersion)
|
|
||||||
.catch((error: Error) => {
|
|
||||||
toast.error('Failed to check for upgrades: ' + error.message);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setInternetLive(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [latestVersion, latestDevVersion]);
|
|
||||||
|
|
||||||
const getBinURL = () => {
|
|
||||||
if (!latestVersion || !latestDevVersion) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
const filename =
|
|
||||||
'EMS-ESP-' +
|
|
||||||
(usingDevVersion ? latestDevVersion : latestVersion).replaceAll('.', '_') +
|
|
||||||
'-' +
|
|
||||||
getPlatform() +
|
|
||||||
'.bin';
|
|
||||||
return usingDevVersion
|
|
||||||
? DEV_URL + filename
|
|
||||||
: STABLE_URL + 'v' + latestVersion + '/' + filename;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getPlatform = () => {
|
|
||||||
return (
|
|
||||||
[data.esp_platform, data.flash_chip_size >= 16384 ? '16MB' : '4MB'].join('-') +
|
|
||||||
(data.psram ? '+' : '')
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const installFirmwareURL = async (url: string) => {
|
|
||||||
await sendUploadURL(url).catch((error: Error) => {
|
|
||||||
toast.error(error.message);
|
|
||||||
});
|
|
||||||
setRestarting(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
useLayoutTitle('EMS-ESP Firmware');
|
|
||||||
|
|
||||||
const renderInstallDialog = () => (
|
|
||||||
<Dialog
|
|
||||||
sx={dialogStyle}
|
|
||||||
open={openInstallDialog}
|
|
||||||
onClose={() => closeInstallDialog()}
|
|
||||||
>
|
|
||||||
<DialogTitle>
|
|
||||||
{LL.INSTALL() +
|
|
||||||
' ' +
|
|
||||||
(usingDevVersion ? LL.DEVELOPMENT() : LL.STABLE()) +
|
|
||||||
' Firmware'}
|
|
||||||
</DialogTitle>
|
|
||||||
<DialogContent dividers>
|
|
||||||
<Typography mb={2}>
|
|
||||||
{LL.INSTALL_VERSION(usingDevVersion ? latestDevVersion : latestVersion)}
|
|
||||||
</Typography>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Button
|
|
||||||
startIcon={<CancelIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => closeInstallDialog()}
|
|
||||||
color="secondary"
|
|
||||||
>
|
|
||||||
{LL.CANCEL()}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
startIcon={<DownloadIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => closeInstallDialog()}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<Link underline="none" target="_blank" href={getBinURL()} color="primary">
|
|
||||||
{LL.DOWNLOAD(1)}
|
|
||||||
</Link>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
startIcon={<WarningIcon color="warning" />}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => installFirmwareURL(getBinURL())}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
{LL.INSTALL()}
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
|
|
||||||
const showFirmwareDialog = (useDevVersion?: boolean) => {
|
|
||||||
setUsingDevVersion(useDevVersion || usingDevVersion);
|
|
||||||
setOpenInstallDialog(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const closeInstallDialog = () => {
|
|
||||||
setOpenInstallDialog(false);
|
|
||||||
setUsingDevVersion(data.emsesp_version.includes('dev'));
|
|
||||||
};
|
|
||||||
|
|
||||||
const switchToDev = () => {
|
|
||||||
setUsingDevVersion(true);
|
|
||||||
setUpgradeAvailable(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const showButtons = () => {
|
|
||||||
if (!upgradeAvailable) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (downloadOnly) {
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
startIcon={<DownloadIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => setOpenInstallDialog(false)}
|
|
||||||
color="warning"
|
|
||||||
size="small"
|
|
||||||
sx={{ ml: 2 }}
|
|
||||||
>
|
|
||||||
<Link underline="none" target="_blank" href={getBinURL()} color="warning">
|
|
||||||
{LL.DOWNLOAD(1)}
|
|
||||||
</Link>
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
sx={{ ml: 2 }}
|
|
||||||
variant="outlined"
|
|
||||||
color="warning"
|
|
||||||
size="small"
|
|
||||||
onClick={() => showFirmwareDialog()}
|
|
||||||
>
|
|
||||||
{LL.UPGRADE()}…
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const content = () => {
|
|
||||||
if (!data) {
|
|
||||||
return <FormLoader onRetry={loadData} errorMessage={error?.message} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Box p={2} border="1px solid grey" borderRadius={2}>
|
|
||||||
<Typography sx={{ pb: 2 }} variant="h6" color="primary">
|
|
||||||
Firmware Version
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Grid container spacing={4}>
|
|
||||||
<Grid mb={1}>
|
|
||||||
<Typography mb={1} color="secondary">
|
|
||||||
{LL.VERSION()}
|
|
||||||
</Typography>
|
|
||||||
<Typography mb={1} color="secondary">
|
|
||||||
Platform
|
|
||||||
</Typography>
|
|
||||||
<Typography mb={1} color="secondary">
|
|
||||||
Release Type
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid mb={1}>
|
|
||||||
<Typography mb={1}>
|
|
||||||
{data.emsesp_version}
|
|
||||||
{data.build_flags && (
|
|
||||||
<Typography variant="caption">
|
|
||||||
({data.build_flags})
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Typography>
|
|
||||||
<Typography mb={1}>{getPlatform()}</Typography>
|
|
||||||
<Typography mb={1}>
|
|
||||||
{data.emsesp_version.includes('dev')
|
|
||||||
? LL.DEVELOPMENT()
|
|
||||||
: LL.STABLE()}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Typography sx={{ pb: 2 }} variant="h6" color="primary">
|
|
||||||
{LL.AVAILABLE_VERSION()}
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
{internetLive ? (
|
|
||||||
<>
|
|
||||||
<Grid container spacing={4}>
|
|
||||||
<Grid mb={1}>
|
|
||||||
<Typography mb={1} color="secondary">
|
|
||||||
{LL.STABLE()}
|
|
||||||
</Typography>
|
|
||||||
<Typography mb={1} color="secondary">
|
|
||||||
{LL.DEVELOPMENT()}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid mb={1}>
|
|
||||||
<Typography mb={1}>
|
|
||||||
{latestVersion}
|
|
||||||
<Link target="_blank" href={STABLE_RELNOTES_URL} color="primary">
|
|
||||||
(changelog)
|
|
||||||
</Link>
|
|
||||||
{!usingDevVersion && showButtons()}
|
|
||||||
</Typography>
|
|
||||||
<Typography mb={1}>
|
|
||||||
{latestDevVersion}
|
|
||||||
<Link target="_blank" href={DEV_RELNOTES_URL} color="primary">
|
|
||||||
(changelog)
|
|
||||||
</Link>
|
|
||||||
{usingDevVersion && showButtons()}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
{upgradeAvailable ? (
|
|
||||||
<Typography color="warning">
|
|
||||||
<InfoOutlinedIcon
|
|
||||||
color="warning"
|
|
||||||
sx={{ verticalAlign: 'middle', mr: 2 }}
|
|
||||||
/>
|
|
||||||
{LL.UPGRADE_AVAILABLE()}
|
|
||||||
</Typography>
|
|
||||||
) : (
|
|
||||||
<Typography color="success">
|
|
||||||
<CheckIcon
|
|
||||||
color="success"
|
|
||||||
sx={{ verticalAlign: 'middle', mr: 2 }}
|
|
||||||
/>
|
|
||||||
{LL.LATEST_VERSION()}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!data.emsesp_version.includes('dev') && !usingDevVersion && (
|
|
||||||
<Typography variant="caption">
|
|
||||||
<Button
|
|
||||||
sx={{ mt: 2 }}
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
size="small"
|
|
||||||
onClick={() => switchToDev()}
|
|
||||||
>
|
|
||||||
{LL.SWITCH_DEV()}
|
|
||||||
</Button>
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Typography mb={1} color="warning">
|
|
||||||
<WarningIcon color="warning" sx={{ verticalAlign: 'middle', mr: 2 }} />
|
|
||||||
device cannot access internet
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{renderInstallDialog()}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Version;
|
|
||||||
@@ -1,9 +1,16 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import { Navigate, Route, Routes, useNavigate } from 'react-router';
|
import {
|
||||||
|
Navigate,
|
||||||
|
Route,
|
||||||
|
Routes,
|
||||||
|
matchRoutes,
|
||||||
|
useLocation,
|
||||||
|
useNavigate
|
||||||
|
} from 'react-router';
|
||||||
|
|
||||||
import { Tab } from '@mui/material';
|
import { Tab } from '@mui/material';
|
||||||
|
|
||||||
import { RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
import { RouterTabs, useLayoutTitle } from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import type { WiFiNetwork } from 'types';
|
import type { WiFiNetwork } from 'types';
|
||||||
|
|
||||||
@@ -15,7 +22,20 @@ const Network = () => {
|
|||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
useLayoutTitle(LL.NETWORK(0));
|
useLayoutTitle(LL.NETWORK(0));
|
||||||
|
|
||||||
const { routerTab } = useRouterTab();
|
// this also works!
|
||||||
|
// const routerTab = useMatch(`settings/network/:path/*`)?.pathname || false;
|
||||||
|
const matchedRoutes = matchRoutes(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
path: '/settings/network/settings',
|
||||||
|
element: <NetworkSettings />,
|
||||||
|
dog: 'woof'
|
||||||
|
},
|
||||||
|
{ path: '/settings/network/scan', element: <WiFiNetworkScanner /> }
|
||||||
|
],
|
||||||
|
useLocation()
|
||||||
|
);
|
||||||
|
const routerTab = matchedRoutes?.[0].route.path || false;
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@@ -24,7 +44,7 @@ const Network = () => {
|
|||||||
const selectNetwork = useCallback(
|
const selectNetwork = useCallback(
|
||||||
(network: WiFiNetwork) => {
|
(network: WiFiNetwork) => {
|
||||||
setSelectedNetwork(network);
|
setSelectedNetwork(network);
|
||||||
void navigate('/settings');
|
void navigate('/settings/network/settings');
|
||||||
},
|
},
|
||||||
[navigate]
|
[navigate]
|
||||||
);
|
);
|
||||||
@@ -42,13 +62,19 @@ const Network = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<RouterTabs value={routerTab}>
|
<RouterTabs value={routerTab}>
|
||||||
<Tab value="settings" label={LL.SETTINGS_OF(LL.NETWORK(1))} />
|
<Tab
|
||||||
<Tab value="scan" label={LL.NETWORK_SCAN()} />
|
value="/settings/network/settings"
|
||||||
|
label={LL.SETTINGS_OF(LL.NETWORK(1))}
|
||||||
|
/>
|
||||||
|
<Tab value="/settings/network/scan" label={LL.NETWORK_SCAN()} />
|
||||||
</RouterTabs>
|
</RouterTabs>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="scan" element={<WiFiNetworkScanner />} />
|
<Route path="scan" element={<WiFiNetworkScanner />} />
|
||||||
<Route path="settings" element={<NetworkSettings />} />
|
<Route path="settings" element={<NetworkSettings />} />
|
||||||
<Route path="*" element={<Navigate replace to="settings" />} />
|
<Route
|
||||||
|
path="*"
|
||||||
|
element={<Navigate replace to="/settings/network/settings" />}
|
||||||
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</WiFiConnectionContext.Provider>
|
</WiFiConnectionContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import { updateValueDirty, useRest } from 'utils';
|
|||||||
import { validate } from 'validators';
|
import { validate } from 'validators';
|
||||||
import { createNetworkSettingsValidator } from 'validators/network';
|
import { createNetworkSettingsValidator } from 'validators/network';
|
||||||
|
|
||||||
import RestartMonitor from '../../status/RestartMonitor';
|
import SystemMonitor from '../../status/SystemMonitor';
|
||||||
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
||||||
import { isNetworkOpen, networkSecurityMode } from './WiFiNetworkSelector';
|
import { isNetworkOpen, networkSecurityMode } from './WiFiNetworkSelector';
|
||||||
|
|
||||||
@@ -400,7 +400,7 @@ const NetworkSettings = () => {
|
|||||||
return (
|
return (
|
||||||
<SectionContent>
|
<SectionContent>
|
||||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||||
{restarting ? <RestartMonitor /> : content()}
|
{restarting ? <SystemMonitor /> : content()}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Navigate, Route, Routes } from 'react-router';
|
import { Navigate, Route, Routes, matchRoutes, useLocation } from 'react-router';
|
||||||
|
|
||||||
import { Tab } from '@mui/material';
|
import { Tab } from '@mui/material';
|
||||||
|
|
||||||
import { RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
import { RouterTabs, useLayoutTitle } from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
import ManageUsers from './ManageUsers';
|
import ManageUsers from './ManageUsers';
|
||||||
@@ -12,18 +12,31 @@ const Security = () => {
|
|||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
useLayoutTitle(LL.SECURITY(0));
|
useLayoutTitle(LL.SECURITY(0));
|
||||||
|
|
||||||
const { routerTab } = useRouterTab();
|
const matchedRoutes = matchRoutes(
|
||||||
|
[
|
||||||
|
{ path: '/settings/security/settings', element: <ManageUsers />, dog: 'woof' },
|
||||||
|
{ path: '/settings/security/users', element: <SecuritySettings /> }
|
||||||
|
],
|
||||||
|
useLocation()
|
||||||
|
);
|
||||||
|
const routerTab = matchedRoutes?.[0].route.path || false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RouterTabs value={routerTab}>
|
<RouterTabs value={routerTab}>
|
||||||
<Tab value="settings" label={LL.SETTINGS_OF(LL.SECURITY(1))} />
|
<Tab
|
||||||
<Tab value="users" label={LL.MANAGE_USERS()} />
|
value="/settings/security/settings"
|
||||||
|
label={LL.SETTINGS_OF(LL.SECURITY(1))}
|
||||||
|
/>
|
||||||
|
<Tab value="/settings/security/users" label={LL.MANAGE_USERS()} />
|
||||||
</RouterTabs>
|
</RouterTabs>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="users" element={<ManageUsers />} />
|
<Route path="users" element={<ManageUsers />} />
|
||||||
<Route path="settings" element={<SecuritySettings />} />
|
<Route path="settings" element={<SecuritySettings />} />
|
||||||
<Route path="*" element={<Navigate replace to="settings" />} />
|
<Route
|
||||||
|
path="*"
|
||||||
|
element={<Navigate replace to="/settings/security/settings" />}
|
||||||
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ import type { Theme } from '@mui/material';
|
|||||||
|
|
||||||
import * as APApi from 'api/ap';
|
import * as APApi from 'api/ap';
|
||||||
|
|
||||||
import { useAutoRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import type { APStatusType } from 'types';
|
import type { APStatusType } from 'types';
|
||||||
import { APNetworkStatus } from 'types';
|
import { APNetworkStatus } from 'types';
|
||||||
|
import { useInterval } from 'utils';
|
||||||
|
|
||||||
export const apStatusHighlight = ({ status }: APStatusType, theme: Theme) => {
|
export const apStatusHighlight = ({ status }: APStatusType, theme: Theme) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@@ -34,11 +35,11 @@ export const apStatusHighlight = ({ status }: APStatusType, theme: Theme) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const APStatus = () => {
|
const APStatus = () => {
|
||||||
const {
|
const { data, send: loadData, error } = useRequest(APApi.readAPStatus);
|
||||||
data,
|
|
||||||
send: loadData,
|
useInterval(() => {
|
||||||
error
|
void loadData();
|
||||||
} = useAutoRequest(APApi.readAPStatus, { pollingTime: 3000 });
|
});
|
||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
useLayoutTitle(LL.ACCESS_POINT(0));
|
useLayoutTitle(LL.ACCESS_POINT(0));
|
||||||
|
|||||||
@@ -8,20 +8,21 @@ import {
|
|||||||
Table
|
Table
|
||||||
} from '@table-library/react-table-library/table';
|
} from '@table-library/react-table-library/table';
|
||||||
import { useTheme as tableTheme } from '@table-library/react-table-library/theme';
|
import { useTheme as tableTheme } from '@table-library/react-table-library/theme';
|
||||||
import { useAutoRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import type { Translation } from 'i18n/i18n-types';
|
import type { Translation } from 'i18n/i18n-types';
|
||||||
|
import { useInterval } from 'utils';
|
||||||
|
|
||||||
import { readActivity } from '../../api/app';
|
import { readActivity } from '../../api/app';
|
||||||
import type { Stat } from '../main/types';
|
import type { Stat } from '../main/types';
|
||||||
|
|
||||||
const SystemActivity = () => {
|
const SystemActivity = () => {
|
||||||
const {
|
const { data, send: loadData, error } = useRequest(readActivity);
|
||||||
data,
|
|
||||||
send: loadData,
|
useInterval(() => {
|
||||||
error
|
void loadData();
|
||||||
} = useAutoRequest(readActivity, { pollingTime: 3000 });
|
});
|
||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ import {
|
|||||||
|
|
||||||
import * as SystemApi from 'api/system';
|
import * as SystemApi from 'api/system';
|
||||||
|
|
||||||
import { useAutoRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
import { useInterval } from 'utils';
|
||||||
|
|
||||||
import BBQKeesIcon from './bbqkees.svg';
|
import BBQKeesIcon from './bbqkees.svg';
|
||||||
|
|
||||||
@@ -32,11 +33,11 @@ const HardwareStatus = () => {
|
|||||||
|
|
||||||
useLayoutTitle(LL.HARDWARE());
|
useLayoutTitle(LL.HARDWARE());
|
||||||
|
|
||||||
const {
|
const { data, send: loadData, error } = useRequest(SystemApi.readSystemStatus);
|
||||||
data,
|
|
||||||
send: loadData,
|
useInterval(() => {
|
||||||
error
|
void loadData();
|
||||||
} = useAutoRequest(SystemApi.readSystemStatus, { pollingTime: 3000 });
|
});
|
||||||
|
|
||||||
const content = () => {
|
const content = () => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@@ -98,7 +99,13 @@ const HardwareStatus = () => {
|
|||||||
' @ ' +
|
' @ ' +
|
||||||
data.cpu_freq_mhz +
|
data.cpu_freq_mhz +
|
||||||
' Mhz' +
|
' Mhz' +
|
||||||
(data.temperature ? ', T: ' + data.temperature + ' °C' : '')
|
// bit of a hack : if the CPU temp is higher than 90 (=32 Fahrenheit if using Celsius), show F, otherwise C
|
||||||
|
(data.temperature
|
||||||
|
? ', T: ' +
|
||||||
|
data.temperature +
|
||||||
|
' °' +
|
||||||
|
(data.temperature > 90 ? 'F' : 'C')
|
||||||
|
: '')
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|||||||
@@ -15,11 +15,12 @@ import type { Theme } from '@mui/material';
|
|||||||
|
|
||||||
import * as MqttApi from 'api/mqtt';
|
import * as MqttApi from 'api/mqtt';
|
||||||
|
|
||||||
import { useAutoRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import type { MqttStatusType } from 'types';
|
import type { MqttStatusType } from 'types';
|
||||||
import { MqttDisconnectReason } from 'types';
|
import { MqttDisconnectReason } from 'types';
|
||||||
|
import { useInterval } from 'utils';
|
||||||
|
|
||||||
export const mqttStatusHighlight = (
|
export const mqttStatusHighlight = (
|
||||||
{ enabled, connected }: MqttStatusType,
|
{ enabled, connected }: MqttStatusType,
|
||||||
@@ -54,11 +55,11 @@ export const mqttQueueHighlight = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const MqttStatus = () => {
|
const MqttStatus = () => {
|
||||||
const {
|
const { data, send: loadData, error } = useRequest(MqttApi.readMqttStatus);
|
||||||
data,
|
|
||||||
send: loadData,
|
useInterval(() => {
|
||||||
error
|
void loadData();
|
||||||
} = useAutoRequest(MqttApi.readMqttStatus, { pollingTime: 3000 });
|
});
|
||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
useLayoutTitle('MQTT');
|
useLayoutTitle('MQTT');
|
||||||
|
|||||||
@@ -1,65 +1,40 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import { toast } from 'react-toastify';
|
|
||||||
|
|
||||||
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
|
||||||
import DnsIcon from '@mui/icons-material/Dns';
|
import DnsIcon from '@mui/icons-material/Dns';
|
||||||
import SwapVerticalCircleIcon from '@mui/icons-material/SwapVerticalCircle';
|
import SwapVerticalCircleIcon from '@mui/icons-material/SwapVerticalCircle';
|
||||||
import UpdateIcon from '@mui/icons-material/Update';
|
import UpdateIcon from '@mui/icons-material/Update';
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
Dialog,
|
|
||||||
DialogActions,
|
|
||||||
DialogContent,
|
|
||||||
DialogTitle,
|
|
||||||
Divider,
|
Divider,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
TextField,
|
|
||||||
Typography,
|
|
||||||
useTheme
|
useTheme
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import type { Theme } from '@mui/material';
|
import type { Theme } from '@mui/material';
|
||||||
|
|
||||||
import * as NTPApi from 'api/ntp';
|
import * as NTPApi from 'api/ntp';
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { useRequest } from 'alova/client';
|
||||||
import { useAutoRequest, useRequest } from 'alova/client';
|
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
||||||
import { ButtonRow, FormLoader, SectionContent, useLayoutTitle } from 'components';
|
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import type { NTPStatusType, Time } from 'types';
|
import type { NTPStatusType } from 'types';
|
||||||
import { NTPSyncStatus } from 'types';
|
import { NTPSyncStatus } from 'types';
|
||||||
import { formatDateTime, formatLocalDateTime } from 'utils';
|
import { useInterval } from 'utils';
|
||||||
|
import { formatDateTime } from 'utils';
|
||||||
|
|
||||||
const NTPStatus = () => {
|
const NTPStatus = () => {
|
||||||
const {
|
const { data, send: loadData, error } = useRequest(NTPApi.readNTPStatus);
|
||||||
data,
|
|
||||||
send: loadData,
|
|
||||||
error
|
|
||||||
} = useAutoRequest(NTPApi.readNTPStatus, { pollingTime: 3000 });
|
|
||||||
|
|
||||||
const [localTime, setLocalTime] = useState<string>('');
|
useInterval(() => {
|
||||||
const [settingTime, setSettingTime] = useState<boolean>(false);
|
void loadData();
|
||||||
const [processing, setProcessing] = useState<boolean>(false);
|
});
|
||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
useLayoutTitle('NTP');
|
useLayoutTitle('NTP');
|
||||||
|
|
||||||
const { send: updateTime } = useRequest(
|
|
||||||
(local_time: Time) => NTPApi.updateTime(local_time),
|
|
||||||
{
|
|
||||||
immediate: false
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
NTPApi.updateTime;
|
NTPApi.updateTime;
|
||||||
|
|
||||||
const isNtpActive = ({ status }: NTPStatusType) =>
|
|
||||||
status === NTPSyncStatus.NTP_ACTIVE;
|
|
||||||
const isNtpEnabled = ({ status }: NTPStatusType) =>
|
const isNtpEnabled = ({ status }: NTPStatusType) =>
|
||||||
status !== NTPSyncStatus.NTP_DISABLED;
|
status !== NTPSyncStatus.NTP_DISABLED;
|
||||||
|
|
||||||
@@ -76,14 +51,6 @@ const NTPStatus = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateLocalTime = (event: React.ChangeEvent<HTMLInputElement>) =>
|
|
||||||
setLocalTime(event.target.value);
|
|
||||||
|
|
||||||
const openSetTime = () => {
|
|
||||||
setLocalTime(formatLocalDateTime(new Date()));
|
|
||||||
setSettingTime(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const ntpStatus = ({ status }: NTPStatusType) => {
|
const ntpStatus = ({ status }: NTPStatusType) => {
|
||||||
@@ -99,70 +66,6 @@ const NTPStatus = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const configureTime = async () => {
|
|
||||||
setProcessing(true);
|
|
||||||
|
|
||||||
await updateTime({ local_time: formatLocalDateTime(new Date(localTime)) })
|
|
||||||
.then(async () => {
|
|
||||||
toast.success(LL.TIME_SET());
|
|
||||||
setSettingTime(false);
|
|
||||||
await loadData();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
toast.error(LL.PROBLEM_UPDATING());
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setProcessing(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderSetTimeDialog = () => (
|
|
||||||
<Dialog
|
|
||||||
sx={dialogStyle}
|
|
||||||
open={settingTime}
|
|
||||||
onClose={() => setSettingTime(false)}
|
|
||||||
>
|
|
||||||
<DialogTitle>{LL.SET_TIME(1)}</DialogTitle>
|
|
||||||
<DialogContent dividers>
|
|
||||||
<Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}>
|
|
||||||
<Typography variant="body2">{LL.SET_TIME_TEXT()}</Typography>
|
|
||||||
</Box>
|
|
||||||
<TextField
|
|
||||||
label={LL.LOCAL_TIME(0)}
|
|
||||||
type="datetime-local"
|
|
||||||
value={localTime}
|
|
||||||
onChange={updateLocalTime}
|
|
||||||
disabled={processing}
|
|
||||||
fullWidth
|
|
||||||
slotProps={{
|
|
||||||
inputLabel: {
|
|
||||||
shrink: true
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Button
|
|
||||||
startIcon={<CancelIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => setSettingTime(false)}
|
|
||||||
color="secondary"
|
|
||||||
>
|
|
||||||
{LL.CANCEL()}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
startIcon={<AccessTimeIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={configureTime}
|
|
||||||
disabled={processing}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
{LL.UPDATE()}
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
|
|
||||||
const content = () => {
|
const content = () => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return <FormLoader onRetry={loadData} errorMessage={error?.message} />;
|
return <FormLoader onRetry={loadData} errorMessage={error?.message} />;
|
||||||
@@ -218,23 +121,6 @@ const NTPStatus = () => {
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
</List>
|
</List>
|
||||||
<Box display="flex" flexWrap="wrap">
|
|
||||||
{data && !isNtpActive(data) && (
|
|
||||||
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
|
||||||
<ButtonRow>
|
|
||||||
<Button
|
|
||||||
onClick={openSetTime}
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
startIcon={<AccessTimeIcon />}
|
|
||||||
>
|
|
||||||
{LL.SET_TIME(0)}
|
|
||||||
</Button>
|
|
||||||
</ButtonRow>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
{renderSetTimeDialog()}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,11 +18,12 @@ import type { Theme } from '@mui/material';
|
|||||||
|
|
||||||
import * as NetworkApi from 'api/network';
|
import * as NetworkApi from 'api/network';
|
||||||
|
|
||||||
import { useAutoRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import type { NetworkStatusType } from 'types';
|
import type { NetworkStatusType } from 'types';
|
||||||
import { NetworkConnectionStatus } from 'types';
|
import { NetworkConnectionStatus } from 'types';
|
||||||
|
import { useInterval } from 'utils';
|
||||||
|
|
||||||
const isConnected = ({ status }: NetworkStatusType) =>
|
const isConnected = ({ status }: NetworkStatusType) =>
|
||||||
status === NetworkConnectionStatus.WIFI_STATUS_CONNECTED ||
|
status === NetworkConnectionStatus.WIFI_STATUS_CONNECTED ||
|
||||||
@@ -81,11 +82,11 @@ const IPs = (status: NetworkStatusType) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const NetworkStatus = () => {
|
const NetworkStatus = () => {
|
||||||
const {
|
const { data, send: loadData, error } = useRequest(NetworkApi.readNetworkStatus);
|
||||||
data,
|
|
||||||
send: loadData,
|
useInterval(() => {
|
||||||
error
|
void loadData();
|
||||||
} = useAutoRequest(NetworkApi.readNetworkStatus, { pollingTime: 3000 });
|
});
|
||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
useLayoutTitle(LL.NETWORK(1));
|
useLayoutTitle(LL.NETWORK(1));
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
CircularProgress,
|
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
Typography
|
|
||||||
} from '@mui/material';
|
|
||||||
|
|
||||||
import { readSystemStatus } from 'api/system';
|
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
|
||||||
import { useAutoRequest } from 'alova/client';
|
|
||||||
import MessageBox from 'components/MessageBox';
|
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
|
||||||
|
|
||||||
const RestartMonitor = () => {
|
|
||||||
const [errorMessage, setErrorMessage] = useState<string>();
|
|
||||||
|
|
||||||
const { LL } = useI18nContext();
|
|
||||||
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
const { data } = useAutoRequest(readSystemStatus, {
|
|
||||||
pollingTime: 1000,
|
|
||||||
force: true,
|
|
||||||
initialData: { status: 'Getting ready...' },
|
|
||||||
async middleware(_, next) {
|
|
||||||
if (count++ >= 1) {
|
|
||||||
// skip first request (1 second) to allow AsyncWS to send its response
|
|
||||||
await next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.onSuccess((event) => {
|
|
||||||
if (event.data.status === 'ready' || event.data.status === undefined) {
|
|
||||||
document.location.href = '/';
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.onError((error) => {
|
|
||||||
setErrorMessage(error.message);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog fullWidth={true} sx={dialogStyle} open={true}>
|
|
||||||
<DialogContent dividers>
|
|
||||||
<Box m={0} py={0} display="flex" alignItems="center" flexDirection="column">
|
|
||||||
<Typography
|
|
||||||
color="secondary"
|
|
||||||
variant="h6"
|
|
||||||
fontWeight={400}
|
|
||||||
textAlign="center"
|
|
||||||
>
|
|
||||||
{data?.status === 'uploading'
|
|
||||||
? LL.WAIT_FIRMWARE()
|
|
||||||
: data?.status === 'restarting'
|
|
||||||
? LL.APPLICATION_RESTARTING()
|
|
||||||
: data?.status === 'ready'
|
|
||||||
? LL.RESTARTING_PRE()
|
|
||||||
: LL.RESTARTING_POST()}
|
|
||||||
…
|
|
||||||
</Typography>
|
|
||||||
<Typography mt={2} variant="h6" fontWeight={400} textAlign="center">
|
|
||||||
{LL.PLEASE_WAIT()}
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
{errorMessage ? (
|
|
||||||
<MessageBox my={2} level="error" message={errorMessage} />
|
|
||||||
) : (
|
|
||||||
<Box py={2}>
|
|
||||||
<CircularProgress size={32} />
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default RestartMonitor;
|
|
||||||
@@ -2,6 +2,7 @@ import { useContext, useState } from 'react';
|
|||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||||
|
import BuildIcon from '@mui/icons-material/Build';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||||
import DirectionsBusIcon from '@mui/icons-material/DirectionsBus';
|
import DirectionsBusIcon from '@mui/icons-material/DirectionsBus';
|
||||||
@@ -30,15 +31,17 @@ import { API } from 'api/app';
|
|||||||
import { readSystemStatus } from 'api/system';
|
import { readSystemStatus } from 'api/system';
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import { useAutoRequest, useRequest } from 'alova/client';
|
import { useRequest } from 'alova/client';
|
||||||
import { type APIcall, busConnectionStatus } from 'app/main/types';
|
import { type APIcall, busConnectionStatus } from 'app/main/types';
|
||||||
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
||||||
import ListMenuItem from 'components/layout/ListMenuItem';
|
import ListMenuItem from 'components/layout/ListMenuItem';
|
||||||
import { AuthenticatedContext } from 'contexts/authentication';
|
import { AuthenticatedContext } from 'contexts/authentication';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import { NTPSyncStatus, NetworkConnectionStatus } from 'types';
|
import { NTPSyncStatus, NetworkConnectionStatus } from 'types';
|
||||||
|
import { useInterval } from 'utils';
|
||||||
|
import { formatDateTime } from 'utils/time';
|
||||||
|
|
||||||
import RestartMonitor from './RestartMonitor';
|
import SystemMonitor from './SystemMonitor';
|
||||||
|
|
||||||
const SystemStatus = () => {
|
const SystemStatus = () => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
@@ -58,9 +61,8 @@ const SystemStatus = () => {
|
|||||||
data,
|
data,
|
||||||
send: loadData,
|
send: loadData,
|
||||||
error
|
error
|
||||||
} = useAutoRequest(readSystemStatus, {
|
} = useRequest(readSystemStatus, {
|
||||||
initialData: [],
|
initialData: [],
|
||||||
pollingTime: 3000,
|
|
||||||
async middleware(_, next) {
|
async middleware(_, next) {
|
||||||
if (!restarting) {
|
if (!restarting) {
|
||||||
await next();
|
await next();
|
||||||
@@ -68,6 +70,10 @@ const SystemStatus = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useInterval(() => {
|
||||||
|
void loadData();
|
||||||
|
});
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const formatDurationSec = (duration_sec: number) => {
|
const formatDurationSec = (duration_sec: number) => {
|
||||||
@@ -134,7 +140,12 @@ const SystemStatus = () => {
|
|||||||
case NTPSyncStatus.NTP_INACTIVE:
|
case NTPSyncStatus.NTP_INACTIVE:
|
||||||
return LL.INACTIVE(0);
|
return LL.INACTIVE(0);
|
||||||
case NTPSyncStatus.NTP_ACTIVE:
|
case NTPSyncStatus.NTP_ACTIVE:
|
||||||
return LL.ACTIVE();
|
return (
|
||||||
|
LL.ACTIVE() +
|
||||||
|
(data.ntp_time !== undefined
|
||||||
|
? ' (' + formatDateTime(data.ntp_time) + ')'
|
||||||
|
: '')
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return LL.UNKNOWN();
|
return LL.UNKNOWN();
|
||||||
}
|
}
|
||||||
@@ -243,6 +254,14 @@ const SystemStatus = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<List sx={{ borderRadius: 3, border: '2px solid grey' }}>
|
<List sx={{ borderRadius: 3, border: '2px solid grey' }}>
|
||||||
|
<ListMenuItem
|
||||||
|
icon={BuildIcon}
|
||||||
|
bgcolor="#72caf9"
|
||||||
|
label="EMS-ESP Firmware"
|
||||||
|
text={'v' + data.emsesp_version}
|
||||||
|
to="version"
|
||||||
|
/>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<Avatar sx={{ bgcolor: '#c5572c', color: 'white' }}>
|
<Avatar sx={{ bgcolor: '#c5572c', color: 'white' }}>
|
||||||
@@ -301,7 +320,7 @@ const SystemStatus = () => {
|
|||||||
icon={DeviceHubIcon}
|
icon={DeviceHubIcon}
|
||||||
bgcolor={activeHighlight(data.mqtt_status)}
|
bgcolor={activeHighlight(data.mqtt_status)}
|
||||||
label="MQTT"
|
label="MQTT"
|
||||||
text={data.mqtt_status ? LL.ACTIVE() : LL.INACTIVE(0)}
|
text={data.mqtt_status ? LL.CONNECTED(0) : LL.INACTIVE(0)}
|
||||||
to="/status/mqtt"
|
to="/status/mqtt"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -339,7 +358,7 @@ const SystemStatus = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
|
<SectionContent>{restarting ? <SystemMonitor /> : content()}</SectionContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import {
|
|||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
|
Grid,
|
||||||
IconButton,
|
IconButton,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
TextField,
|
TextField,
|
||||||
styled
|
styled
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Grid from '@mui/material/Grid2';
|
|
||||||
|
|
||||||
import { API } from 'api/app';
|
import { API } from 'api/app';
|
||||||
import { fetchLogES, readLogSettings, updateLogSettings } from 'api/system';
|
import { fetchLogES, readLogSettings, updateLogSettings } from 'api/system';
|
||||||
@@ -101,6 +101,7 @@ const SystemLog = () => {
|
|||||||
const [readOpen, setReadOpen] = useState(false);
|
const [readOpen, setReadOpen] = useState(false);
|
||||||
const [logEntries, setLogEntries] = useState<LogEntry[]>([]);
|
const [logEntries, setLogEntries] = useState<LogEntry[]>([]);
|
||||||
const [autoscroll, setAutoscroll] = useState(true);
|
const [autoscroll, setAutoscroll] = useState(true);
|
||||||
|
const [lastId, setLastId] = useState<number>(-1);
|
||||||
|
|
||||||
const ALPHA_NUMERIC_DASH_REGEX = /^[a-fA-F0-9 ]+$/;
|
const ALPHA_NUMERIC_DASH_REGEX = /^[a-fA-F0-9 ]+$/;
|
||||||
|
|
||||||
@@ -115,10 +116,13 @@ const SystemLog = () => {
|
|||||||
immediate: true,
|
immediate: true,
|
||||||
interceptByGlobalResponded: false
|
interceptByGlobalResponded: false
|
||||||
})
|
})
|
||||||
.onMessage((message: { id: number; data: string }) => {
|
.onMessage((message: { data: string }) => {
|
||||||
const rawData = message.data;
|
const rawData = message.data;
|
||||||
const logentry = JSON.parse(rawData) as LogEntry;
|
const logentry = JSON.parse(rawData) as LogEntry;
|
||||||
setLogEntries((log) => [...log, logentry]);
|
if (lastId < logentry.i) {
|
||||||
|
setLogEntries((log) => [...log, logentry]);
|
||||||
|
setLastId(logentry.i);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.onError(() => {
|
.onError(() => {
|
||||||
toast.error('No connection to Log service');
|
toast.error('No connection to Log service');
|
||||||
@@ -197,7 +201,7 @@ const SystemLog = () => {
|
|||||||
name="level"
|
name="level"
|
||||||
label={LL.LOG_LEVEL()}
|
label={LL.LOG_LEVEL()}
|
||||||
value={data.level}
|
value={data.level}
|
||||||
sx={{ width: '10ch' }}
|
sx={{ width: '14ch' }}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
|
|||||||
125
interface/src/app/status/SystemMonitor.tsx
Normal file
125
interface/src/app/status/SystemMonitor.tsx
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import { Box, Button, Dialog, DialogContent, Typography } from '@mui/material';
|
||||||
|
|
||||||
|
import { callAction } from 'api/app';
|
||||||
|
import { readSystemStatus } from 'api/system';
|
||||||
|
|
||||||
|
import { dialogStyle } from 'CustomTheme';
|
||||||
|
import { useRequest } from 'alova/client';
|
||||||
|
import MessageBox from 'components/MessageBox';
|
||||||
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
import { SystemStatusCodes } from 'types';
|
||||||
|
import { useInterval } from 'utils';
|
||||||
|
|
||||||
|
import { LinearProgressWithLabel } from '../../components/upload/LinearProgressWithLabel';
|
||||||
|
|
||||||
|
const SystemMonitor = () => {
|
||||||
|
const [errorMessage, setErrorMessage] = useState<string>();
|
||||||
|
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
const { send: setSystemStatus } = useRequest(
|
||||||
|
(status: string) => callAction({ action: 'systemStatus', param: status }),
|
||||||
|
{
|
||||||
|
immediate: false
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data, send } = useRequest(readSystemStatus, {
|
||||||
|
force: true,
|
||||||
|
async middleware(_, next) {
|
||||||
|
if (count++ >= 1) {
|
||||||
|
// skip first request (1 second) to allow AsyncWS to send its response
|
||||||
|
await next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.onSuccess((event) => {
|
||||||
|
if (
|
||||||
|
event.data.status === SystemStatusCodes.SYSTEM_STATUS_NORMAL ||
|
||||||
|
event.data.status === undefined
|
||||||
|
) {
|
||||||
|
document.location.href = '/';
|
||||||
|
} else if (
|
||||||
|
event.data.status === SystemStatusCodes.SYSTEM_STATUS_ERROR_UPLOAD
|
||||||
|
) {
|
||||||
|
setErrorMessage('Please check system logs for possible causes');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.onError((error) => {
|
||||||
|
setErrorMessage(String(error.error?.message || 'An error occurred'));
|
||||||
|
});
|
||||||
|
|
||||||
|
useInterval(() => {
|
||||||
|
void send();
|
||||||
|
}, 1000); // check every 1 second
|
||||||
|
|
||||||
|
const onCancel = async () => {
|
||||||
|
setErrorMessage(undefined);
|
||||||
|
await setSystemStatus(
|
||||||
|
SystemStatusCodes.SYSTEM_STATUS_NORMAL as unknown as string
|
||||||
|
);
|
||||||
|
document.location.href = '/';
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog fullWidth={true} sx={dialogStyle} open={true}>
|
||||||
|
<DialogContent dividers>
|
||||||
|
<Box m={0} py={0} display="flex" alignItems="center" flexDirection="column">
|
||||||
|
<Typography
|
||||||
|
color="secondary"
|
||||||
|
variant="h6"
|
||||||
|
fontWeight={400}
|
||||||
|
textAlign="center"
|
||||||
|
>
|
||||||
|
{data?.status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING
|
||||||
|
? LL.WAIT_FIRMWARE()
|
||||||
|
: data?.status === SystemStatusCodes.SYSTEM_STATUS_PENDING_RESTART
|
||||||
|
? LL.APPLICATION_RESTARTING()
|
||||||
|
: data?.status === SystemStatusCodes.SYSTEM_STATUS_NORMAL
|
||||||
|
? LL.RESTARTING_PRE()
|
||||||
|
: data?.status === SystemStatusCodes.SYSTEM_STATUS_ERROR_UPLOAD
|
||||||
|
? 'Upload Failed'
|
||||||
|
: LL.RESTARTING_POST()}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{errorMessage ? (
|
||||||
|
<MessageBox my={2} level="error" message={errorMessage}>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
sx={{ ml: 2 }}
|
||||||
|
startIcon={<CancelIcon />}
|
||||||
|
variant="contained"
|
||||||
|
color="error"
|
||||||
|
onClick={onCancel}
|
||||||
|
>
|
||||||
|
{LL.RESTART()}
|
||||||
|
</Button>
|
||||||
|
</MessageBox>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Typography mt={2} variant="h6" fontWeight={400} textAlign="center">
|
||||||
|
{LL.PLEASE_WAIT()}…
|
||||||
|
</Typography>
|
||||||
|
{data && data.status >= SystemStatusCodes.SYSTEM_STATUS_UPLOADING && (
|
||||||
|
<Box width="100%" pl={2} pr={2} py={2}>
|
||||||
|
<LinearProgressWithLabel
|
||||||
|
value={Math.round(
|
||||||
|
data?.status - SystemStatusCodes.SYSTEM_STATUS_UPLOADING
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SystemMonitor;
|
||||||
485
interface/src/app/status/Version.tsx
Normal file
485
interface/src/app/status/Version.tsx
Normal file
@@ -0,0 +1,485 @@
|
|||||||
|
import { useContext, useEffect, useState } from 'react';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
|
import CheckIcon from '@mui/icons-material/Done';
|
||||||
|
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||||
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
FormControlLabel,
|
||||||
|
Grid,
|
||||||
|
Link,
|
||||||
|
Typography
|
||||||
|
} from '@mui/material';
|
||||||
|
|
||||||
|
import * as SystemApi from 'api/system';
|
||||||
|
import { API, callAction } from 'api/app';
|
||||||
|
import { getDevVersion, getStableVersion } from 'api/system';
|
||||||
|
|
||||||
|
import { dialogStyle } from 'CustomTheme';
|
||||||
|
import { useRequest } from 'alova/client';
|
||||||
|
import type { APIcall } from 'app/main/types';
|
||||||
|
import SystemMonitor from 'app/status/SystemMonitor';
|
||||||
|
import {
|
||||||
|
FormLoader,
|
||||||
|
SectionContent,
|
||||||
|
SingleUpload,
|
||||||
|
useLayoutTitle
|
||||||
|
} from 'components';
|
||||||
|
import { AuthenticatedContext } from 'contexts/authentication';
|
||||||
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
|
const Version = () => {
|
||||||
|
const { LL, locale } = useI18nContext();
|
||||||
|
const { me } = useContext(AuthenticatedContext);
|
||||||
|
|
||||||
|
const [restarting, setRestarting] = useState<boolean>(false);
|
||||||
|
const [openInstallDialog, setOpenInstallDialog] = useState<boolean>(false);
|
||||||
|
const [usingDevVersion, setUsingDevVersion] = useState<boolean>(false);
|
||||||
|
const [fetchDevVersion, setFetchDevVersion] = useState<boolean>(false);
|
||||||
|
const [devUpgradeAvailable, setDevUpgradeAvailable] = useState<boolean>(false);
|
||||||
|
const [stableUpgradeAvailable, setStableUpgradeAvailable] =
|
||||||
|
useState<boolean>(false);
|
||||||
|
const [internetLive, setInternetLive] = useState<boolean>(false);
|
||||||
|
const [downloadOnly, setDownloadOnly] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const STABLE_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/';
|
||||||
|
const STABLE_RELNOTES_URL =
|
||||||
|
'https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md';
|
||||||
|
|
||||||
|
const DEV_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/latest/';
|
||||||
|
const DEV_RELNOTES_URL =
|
||||||
|
'https://github.com/emsesp/EMS-ESP32/blob/dev/CHANGELOG_LATEST.md';
|
||||||
|
|
||||||
|
const { send: sendCheckUpgrade } = useRequest(
|
||||||
|
(versions: string) => callAction({ action: 'checkUpgrade', param: versions }),
|
||||||
|
{
|
||||||
|
immediate: false
|
||||||
|
}
|
||||||
|
).onSuccess((event) => {
|
||||||
|
const data = event.data as {
|
||||||
|
emsesp_version: string;
|
||||||
|
dev_upgradeable: boolean;
|
||||||
|
stable_upgradeable: boolean;
|
||||||
|
};
|
||||||
|
setDevUpgradeAvailable(data.dev_upgradeable);
|
||||||
|
setStableUpgradeAvailable(data.stable_upgradeable);
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: data,
|
||||||
|
send: loadData,
|
||||||
|
error
|
||||||
|
} = useRequest(SystemApi.readSystemStatus).onSuccess((event) => {
|
||||||
|
// older version of EMS-ESP using ESP32 (not S3) and no PSRAM, can't use OTA because of SSL support in HttpClient
|
||||||
|
if (event.data.arduino_version.startsWith('Tasmota')) {
|
||||||
|
setDownloadOnly(true);
|
||||||
|
}
|
||||||
|
setUsingDevVersion(event.data.emsesp_version.includes('dev'));
|
||||||
|
});
|
||||||
|
|
||||||
|
const { send: sendUploadURL } = useRequest(
|
||||||
|
(url: string) => callAction({ action: 'uploadURL', param: url }),
|
||||||
|
{
|
||||||
|
immediate: false
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// called immediately to get the latest versions on page load
|
||||||
|
const { data: latestVersion } = useRequest(getStableVersion);
|
||||||
|
const { data: latestDevVersion } = useRequest(getDevVersion);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (latestVersion && latestDevVersion) {
|
||||||
|
sendCheckUpgrade(latestDevVersion.name + ',' + latestVersion.name)
|
||||||
|
.catch((error: Error) => {
|
||||||
|
toast.error('Failed to check for upgrades: ' + error.message);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setInternetLive(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [latestVersion, latestDevVersion]);
|
||||||
|
|
||||||
|
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
|
||||||
|
const DIVISIONS = [
|
||||||
|
{ amount: 60, name: 'seconds' },
|
||||||
|
{ amount: 60, name: 'minutes' },
|
||||||
|
{ amount: 24, name: 'hours' },
|
||||||
|
{ amount: 7, name: 'days' },
|
||||||
|
{ amount: 4.34524, name: 'weeks' },
|
||||||
|
{ amount: 12, name: 'months' },
|
||||||
|
{ amount: Number.POSITIVE_INFINITY, name: 'years' }
|
||||||
|
];
|
||||||
|
function formatTimeAgo(date) {
|
||||||
|
let duration = (date.getTime() - new Date().getTime()) / 1000;
|
||||||
|
for (let i = 0; i < DIVISIONS.length; i++) {
|
||||||
|
const division = DIVISIONS[i];
|
||||||
|
if (Math.abs(duration) < division.amount) {
|
||||||
|
return rtf.format(
|
||||||
|
Math.round(duration),
|
||||||
|
division.name as Intl.RelativeTimeFormatUnit
|
||||||
|
);
|
||||||
|
}
|
||||||
|
duration /= division.amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
|
||||||
|
immediate: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const doRestart = async () => {
|
||||||
|
setRestarting(true);
|
||||||
|
await sendAPI({ device: 'system', cmd: 'restart', id: 0 }).catch(
|
||||||
|
(error: Error) => {
|
||||||
|
toast.error(error.message);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBinURL = (showingDev: boolean) => {
|
||||||
|
if (!internetLive) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const filename =
|
||||||
|
'EMS-ESP-' +
|
||||||
|
(showingDev ? latestDevVersion.name : latestVersion.name).replaceAll(
|
||||||
|
'.',
|
||||||
|
'_'
|
||||||
|
) +
|
||||||
|
'-' +
|
||||||
|
getPlatform() +
|
||||||
|
'.bin';
|
||||||
|
return showingDev
|
||||||
|
? DEV_URL + filename
|
||||||
|
: STABLE_URL + 'v' + latestVersion.name + '/' + filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPlatform = () => {
|
||||||
|
return (
|
||||||
|
[data.esp_platform, data.flash_chip_size >= 16384 ? '16MB' : '4MB'].join('-') +
|
||||||
|
(data.psram ? '+' : '')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const installFirmwareURL = async (url: string) => {
|
||||||
|
await sendUploadURL(url).catch((error: Error) => {
|
||||||
|
toast.error(error.message);
|
||||||
|
});
|
||||||
|
setRestarting(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
useLayoutTitle('EMS-ESP Firmware');
|
||||||
|
|
||||||
|
const renderInstallDialog = () => {
|
||||||
|
const binURL = getBinURL(fetchDevVersion);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
sx={dialogStyle}
|
||||||
|
open={openInstallDialog}
|
||||||
|
onClose={() => closeInstallDialog()}
|
||||||
|
>
|
||||||
|
<DialogTitle>
|
||||||
|
{LL.UPDATE() +
|
||||||
|
' ' +
|
||||||
|
(fetchDevVersion ? LL.DEVELOPMENT() : LL.STABLE()) +
|
||||||
|
' Firmware'}
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent dividers>
|
||||||
|
<Typography mb={2}>
|
||||||
|
{LL.INSTALL_VERSION(
|
||||||
|
downloadOnly ? LL.DOWNLOAD(1) : LL.INSTALL(),
|
||||||
|
fetchDevVersion ? latestDevVersion?.name : latestVersion?.name
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button
|
||||||
|
startIcon={<CancelIcon />}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => closeInstallDialog()}
|
||||||
|
color="secondary"
|
||||||
|
>
|
||||||
|
{LL.CANCEL()}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
startIcon={<DownloadIcon />}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => closeInstallDialog()}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<Link underline="none" target="_blank" href={binURL} color="primary">
|
||||||
|
{LL.DOWNLOAD(0)}
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
{!downloadOnly && (
|
||||||
|
<Button
|
||||||
|
startIcon={<WarningIcon color="warning" />}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => installFirmwareURL(binURL)}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
{LL.INSTALL()}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showFirmwareDialog = (useDevVersion: boolean) => {
|
||||||
|
setFetchDevVersion(useDevVersion);
|
||||||
|
setOpenInstallDialog(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeInstallDialog = () => {
|
||||||
|
setOpenInstallDialog(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showButtons = (showingDev: boolean) => {
|
||||||
|
const choice = showingDev
|
||||||
|
? !usingDevVersion
|
||||||
|
? LL.SWITCH_RELEASE_TYPE(LL.DEVELOPMENT())
|
||||||
|
: devUpgradeAvailable
|
||||||
|
? LL.UPDATE_AVAILABLE()
|
||||||
|
: undefined
|
||||||
|
: usingDevVersion
|
||||||
|
? LL.SWITCH_RELEASE_TYPE(LL.STABLE())
|
||||||
|
: stableUpgradeAvailable
|
||||||
|
? LL.UPDATE_AVAILABLE()
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (!choice) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CheckIcon
|
||||||
|
color="success"
|
||||||
|
sx={{ verticalAlign: 'middle', ml: 0.5, mr: 0.5 }}
|
||||||
|
/>
|
||||||
|
<span style={{ color: '#66bb6a', fontSize: '0.8em' }}>
|
||||||
|
{LL.LATEST_VERSION(usingDevVersion ? LL.DEVELOPMENT() : LL.STABLE())}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!me.admin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
sx={{ ml: 2 }}
|
||||||
|
variant="outlined"
|
||||||
|
color={choice === LL.UPDATE_AVAILABLE() ? 'success' : 'warning'}
|
||||||
|
size="small"
|
||||||
|
onClick={() => showFirmwareDialog(showingDev)}
|
||||||
|
>
|
||||||
|
{choice}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const content = () => {
|
||||||
|
if (!data) {
|
||||||
|
return <FormLoader onRetry={loadData} errorMessage={error?.message} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDev = data.emsesp_version.includes('dev');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box p={2} border="1px solid grey" borderRadius={2}>
|
||||||
|
<Typography mb={2} variant="h6" color="primary">
|
||||||
|
{LL.THIS_VERSION()}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
direction="row"
|
||||||
|
rowSpacing={1}
|
||||||
|
sx={{
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
alignItems: 'baseline'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Grid size={{ xs: 4, md: 2 }}>
|
||||||
|
<Typography color="secondary">{LL.VERSION()}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 8, md: 10 }}>
|
||||||
|
<Typography>
|
||||||
|
{data.emsesp_version}
|
||||||
|
{data.build_flags && (
|
||||||
|
<Typography variant="caption">
|
||||||
|
({data.build_flags})
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4, md: 2 }}>
|
||||||
|
<Typography color="secondary">{LL.PLATFORM()}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 8, md: 10 }}>
|
||||||
|
<Typography>
|
||||||
|
{getPlatform()}
|
||||||
|
<Typography variant="caption">
|
||||||
|
(
|
||||||
|
{data.psram ? (
|
||||||
|
<CheckIcon
|
||||||
|
color="success"
|
||||||
|
sx={{
|
||||||
|
fontSize: '1.5em',
|
||||||
|
verticalAlign: 'middle'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<CloseIcon
|
||||||
|
color="error"
|
||||||
|
sx={{
|
||||||
|
fontSize: '1.5em',
|
||||||
|
verticalAlign: 'middle'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
PSRAM)
|
||||||
|
</Typography>
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4, md: 2 }}>
|
||||||
|
<Typography color="secondary">{LL.RELEASE_TYPE()}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 8, md: 10 }}>
|
||||||
|
<FormControlLabel
|
||||||
|
disabled={!isDev}
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
sx={{
|
||||||
|
'&.Mui-checked': {
|
||||||
|
color: 'lightblue'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
slotProps={{
|
||||||
|
typography: {
|
||||||
|
color: 'grey'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
checked={!isDev}
|
||||||
|
label={LL.STABLE()}
|
||||||
|
sx={{ '& .MuiSvgIcon-root': { fontSize: 16 } }}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
disabled={isDev}
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
sx={{
|
||||||
|
'&.Mui-checked': {
|
||||||
|
color: 'lightblue'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
slotProps={{
|
||||||
|
typography: {
|
||||||
|
color: 'grey'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
checked={isDev}
|
||||||
|
label={LL.DEVELOPMENT()}
|
||||||
|
sx={{ '& .MuiSvgIcon-root': { fontSize: 16 } }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{internetLive ? (
|
||||||
|
<>
|
||||||
|
<Typography mt={2} mb={2} variant="h6" color="primary">
|
||||||
|
{LL.AVAILABLE_VERSION()}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
direction="row"
|
||||||
|
rowSpacing={1}
|
||||||
|
sx={{
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
alignItems: 'baseline'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Grid size={{ xs: 4, md: 2 }}>
|
||||||
|
<Typography color="secondary">{LL.STABLE()}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 8, md: 10 }}>
|
||||||
|
<Typography>
|
||||||
|
<Link target="_blank" href={STABLE_RELNOTES_URL} color="primary">
|
||||||
|
{latestVersion.name}
|
||||||
|
</Link>
|
||||||
|
{latestVersion.published_at && (
|
||||||
|
<Typography component="span" variant="caption">
|
||||||
|
(
|
||||||
|
{formatTimeAgo(new Date(latestVersion.published_at))})
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
{showButtons(false)}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid size={{ xs: 4, md: 2 }}>
|
||||||
|
<Typography color="secondary">{LL.DEVELOPMENT()}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid size={{ xs: 8, md: 10 }}>
|
||||||
|
<Typography>
|
||||||
|
<Link target="_blank" href={DEV_RELNOTES_URL} color="primary">
|
||||||
|
{latestDevVersion.name}
|
||||||
|
</Link>
|
||||||
|
{latestDevVersion.published_at && (
|
||||||
|
<Typography component="span" variant="caption">
|
||||||
|
(
|
||||||
|
{formatTimeAgo(new Date(latestDevVersion.published_at))})
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
{showButtons(true)}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Typography mt={2} color="warning">
|
||||||
|
<WarningIcon color="warning" sx={{ verticalAlign: 'middle', mr: 2 }} />
|
||||||
|
{LL.INTERNET_CONNECTION_REQUIRED()}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
{me.admin && (
|
||||||
|
<>
|
||||||
|
{renderInstallDialog()}
|
||||||
|
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||||
|
{LL.UPLOAD()}
|
||||||
|
</Typography>
|
||||||
|
<SingleUpload text={LL.UPLOAD_DROP_TEXT()} doRestart={doRestart} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SectionContent>{restarting ? <SystemMonitor /> : content()}</SectionContent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Version;
|
||||||
17
interface/src/components/ButtonTooltip.tsx
Normal file
17
interface/src/components/ButtonTooltip.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Tooltip, type TooltipProps, styled, tooltipClasses } from '@mui/material';
|
||||||
|
|
||||||
|
export const ButtonTooltip = styled(({ className, ...props }: TooltipProps) => (
|
||||||
|
<Tooltip {...props} placement="top" arrow classes={{ popper: className }} />
|
||||||
|
))(({ theme }) => ({
|
||||||
|
[`& .${tooltipClasses.arrow}`]: {
|
||||||
|
color: theme.palette.success.main
|
||||||
|
},
|
||||||
|
[`& .${tooltipClasses.tooltip}`]: {
|
||||||
|
backgroundColor: theme.palette.success.main,
|
||||||
|
color: 'rgba(0, 0, 0, 0.87)',
|
||||||
|
boxShadow: theme.shadows[1],
|
||||||
|
fontSize: 10
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default ButtonTooltip;
|
||||||
@@ -11,7 +11,7 @@ type MessageBoxLevel = 'warning' | 'success' | 'info' | 'error';
|
|||||||
|
|
||||||
export interface MessageBoxProps extends BoxProps {
|
export interface MessageBoxProps extends BoxProps {
|
||||||
level: MessageBoxLevel;
|
level: MessageBoxLevel;
|
||||||
message: string;
|
message?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LEVEL_ICONS: {
|
const LEVEL_ICONS: {
|
||||||
@@ -53,8 +53,8 @@ const MessageBox: FC<MessageBoxProps> = ({
|
|||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Icon />
|
<Icon />
|
||||||
<Typography sx={{ ml: 2, flexGrow: 1 }} variant="body1">
|
<Typography sx={{ ml: 2 }} variant="body1">
|
||||||
{message}
|
{message ?? ''}
|
||||||
</Typography>
|
</Typography>
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ 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';
|
export { default as BlockNavigation } from './routing/BlockNavigation';
|
||||||
|
export { default as ButtonTooltip } from './ButtonTooltip';
|
||||||
|
|||||||
@@ -73,11 +73,6 @@ const LayoutMenu = () => {
|
|||||||
>
|
>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={LL.MODULES()}
|
primary={LL.MODULES()}
|
||||||
primaryTypographyProps={{
|
|
||||||
fontWeight: '600',
|
|
||||||
mb: '2px',
|
|
||||||
color: 'lightblue'
|
|
||||||
}}
|
|
||||||
// secondary={
|
// secondary={
|
||||||
// LL.CUSTOMIZATIONS() +
|
// LL.CUSTOMIZATIONS() +
|
||||||
// ', ' +
|
// ', ' +
|
||||||
@@ -92,6 +87,13 @@ const LayoutMenu = () => {
|
|||||||
// color: menuOpen ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0.5)'
|
// color: menuOpen ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0.5)'
|
||||||
// }}
|
// }}
|
||||||
sx={{ my: 0 }}
|
sx={{ my: 0 }}
|
||||||
|
slotProps={{
|
||||||
|
primary: {
|
||||||
|
fontWeight: '600',
|
||||||
|
mb: '2px',
|
||||||
|
color: 'lightblue'
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<KeyboardArrowDown
|
<KeyboardArrowDown
|
||||||
sx={{
|
sx={{
|
||||||
@@ -132,7 +134,6 @@ const LayoutMenu = () => {
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
<List style={{ marginTop: `auto` }}>
|
<List style={{ marginTop: `auto` }}>
|
||||||
<LayoutMenuItem
|
<LayoutMenuItem
|
||||||
icon={AssessmentIcon}
|
icon={AssessmentIcon}
|
||||||
@@ -158,7 +159,6 @@ const LayoutMenu = () => {
|
|||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
id={id}
|
id={id}
|
||||||
open={open}
|
open={open}
|
||||||
|
|||||||
@@ -1,20 +1,15 @@
|
|||||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||||
import { Box, Button, CircularProgress, Typography } from '@mui/material';
|
import { Box, Button, CircularProgress } from '@mui/material';
|
||||||
|
|
||||||
import { MessageBox } from 'components';
|
import { MessageBox } from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
interface FormLoaderProps {
|
interface FormLoaderProps {
|
||||||
message?: string;
|
|
||||||
errorMessage?: string;
|
errorMessage?: string;
|
||||||
onRetry?: () => void;
|
onRetry?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FormLoader = ({
|
const FormLoader = ({ errorMessage, onRetry }: FormLoaderProps) => {
|
||||||
errorMessage,
|
|
||||||
onRetry,
|
|
||||||
message = 'Loading…'
|
|
||||||
}: FormLoaderProps) => {
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
if (errorMessage) {
|
if (errorMessage) {
|
||||||
@@ -22,6 +17,7 @@ const FormLoader = ({
|
|||||||
<MessageBox my={2} level="error" message={errorMessage}>
|
<MessageBox my={2} level="error" message={errorMessage}>
|
||||||
{onRetry && (
|
{onRetry && (
|
||||||
<Button
|
<Button
|
||||||
|
sx={{ ml: 2 }}
|
||||||
startIcon={<RefreshIcon />}
|
startIcon={<RefreshIcon />}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="error"
|
color="error"
|
||||||
@@ -38,9 +34,6 @@ const FormLoader = ({
|
|||||||
<Box py={2}>
|
<Box py={2}>
|
||||||
<CircularProgress size={100} />
|
<CircularProgress size={100} />
|
||||||
</Box>
|
</Box>
|
||||||
<Typography variant="h6" fontWeight={400} textAlign="center">
|
|
||||||
{message}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
import { Box, CircularProgress, Typography } from '@mui/material';
|
import { Box, CircularProgress } from '@mui/material';
|
||||||
import type { Theme } from '@mui/material';
|
import type { Theme } from '@mui/material';
|
||||||
|
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
|
||||||
|
|
||||||
interface LoadingSpinnerProps {
|
interface LoadingSpinnerProps {
|
||||||
height?: number | string;
|
height?: number | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LoadingSpinner = ({ height = '100%' }: LoadingSpinnerProps) => {
|
const LoadingSpinner = ({ height = '100%' }: LoadingSpinnerProps) => {
|
||||||
const { LL } = useI18nContext();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
display="flex"
|
display="flex"
|
||||||
@@ -26,9 +22,6 @@ const LoadingSpinner = ({ height = '100%' }: LoadingSpinnerProps) => {
|
|||||||
})}
|
})}
|
||||||
size={100}
|
size={100}
|
||||||
/>
|
/>
|
||||||
<Typography variant="h4" color="textSecondary">
|
|
||||||
{LL.LOADING()}…
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ export function getStorage() {
|
|||||||
|
|
||||||
export function storeLoginRedirect(location?: H.Location) {
|
export function storeLoginRedirect(location?: H.Location) {
|
||||||
if (location) {
|
if (location) {
|
||||||
getStorage().setItem(SIGN_IN_PATHNAME, location.pathname);
|
getStorage().setItem(SIGN_IN_PATHNAME, location.pathname as string);
|
||||||
getStorage().setItem(SIGN_IN_SEARCH, location.search);
|
getStorage().setItem(SIGN_IN_SEARCH, location.search as string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,3 @@ export { default as RouterTabs } from './RouterTabs';
|
|||||||
export { default as RequireAdmin } from './RequireAdmin';
|
export { default as RequireAdmin } from './RequireAdmin';
|
||||||
export { default as RequireAuthenticated } from './RequireAuthenticated';
|
export { default as RequireAuthenticated } from './RequireAuthenticated';
|
||||||
export { default as RequireUnauthenticated } from './RequireUnauthenticated';
|
export { default as RequireUnauthenticated } from './RequireUnauthenticated';
|
||||||
|
|
||||||
export * from './useRouterTab';
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import { useMatch, useResolvedPath } from 'react-router';
|
|
||||||
|
|
||||||
export const useRouterTab = () => {
|
|
||||||
const routerTabPathMatch = useMatch(useResolvedPath(':tab').pathname);
|
|
||||||
const routerTab = routerTabPathMatch?.params?.tab || false;
|
|
||||||
|
|
||||||
return { routerTab } as const;
|
|
||||||
};
|
|
||||||
@@ -10,7 +10,7 @@ import { useI18nContext } from 'i18n/i18n-react';
|
|||||||
|
|
||||||
import './dragNdrop.css';
|
import './dragNdrop.css';
|
||||||
|
|
||||||
const DragNdrop = ({ onFileSelected }) => {
|
const DragNdrop = ({ text, onFileSelected }) => {
|
||||||
const [file, setFile] = useState<File>();
|
const [file, setFile] = useState<File>();
|
||||||
const [dragged, setDragged] = useState(false);
|
const [dragged, setDragged] = useState(false);
|
||||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||||
@@ -73,7 +73,7 @@ const DragNdrop = ({ onFileSelected }) => {
|
|||||||
>
|
>
|
||||||
<div className="upload-info">
|
<div className="upload-info">
|
||||||
<CloudUploadIcon sx={{ marginRight: 4 }} color="primary" fontSize="large" />
|
<CloudUploadIcon sx={{ marginRight: 4 }} color="primary" fontSize="large" />
|
||||||
<p>{LL.UPLOAD_DRAG()}</p>
|
<p>{text}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
|||||||
23
interface/src/components/upload/LinearProgressWithLabel.tsx
Normal file
23
interface/src/components/upload/LinearProgressWithLabel.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
LinearProgress,
|
||||||
|
type LinearProgressProps,
|
||||||
|
Typography
|
||||||
|
} from '@mui/material';
|
||||||
|
|
||||||
|
export function LinearProgressWithLabel(
|
||||||
|
props: LinearProgressProps & { value: number }
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||||
|
<Box sx={{ width: '100%', mr: 1 }}>
|
||||||
|
<LinearProgress variant="determinate" {...props} />
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ minWidth: 35 }}>
|
||||||
|
<Typography variant="body2" color="text.secondary">{`${Math.round(
|
||||||
|
props.value
|
||||||
|
)}%`}</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,13 +2,7 @@ import { useEffect, useState } from 'react';
|
|||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
import {
|
import { Box, Button, Typography } from '@mui/material';
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
LinearProgress,
|
|
||||||
type LinearProgressProps,
|
|
||||||
Typography
|
|
||||||
} from '@mui/material';
|
|
||||||
|
|
||||||
import * as SystemApi from 'api/system';
|
import * as SystemApi from 'api/system';
|
||||||
|
|
||||||
@@ -16,23 +10,9 @@ import { useRequest } from 'alova/client';
|
|||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
import DragNdrop from './DragNdrop';
|
import DragNdrop from './DragNdrop';
|
||||||
|
import { LinearProgressWithLabel } from './LinearProgressWithLabel';
|
||||||
|
|
||||||
function LinearProgressWithLabel(props: LinearProgressProps & { value: number }) {
|
const SingleUpload = ({ text, doRestart }) => {
|
||||||
return (
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
||||||
<Box sx={{ width: '100%', mr: 1 }}>
|
|
||||||
<LinearProgress variant="determinate" {...props} />
|
|
||||||
</Box>
|
|
||||||
<Box sx={{ minWidth: 35 }}>
|
|
||||||
<Typography variant="body2" color="text.secondary">{`${Math.round(
|
|
||||||
props.value
|
|
||||||
)}%`}</Typography>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const SingleUpload = ({ doRestart }) => {
|
|
||||||
const [md5, setMd5] = useState<string>();
|
const [md5, setMd5] = useState<string>();
|
||||||
const [file, setFile] = useState<File>();
|
const [file, setFile] = useState<File>();
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
@@ -93,7 +73,7 @@ const SingleUpload = ({ doRestart }) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<DragNdrop onFileSelected={setFile} />
|
<DragNdrop text={text} onFileSelected={setFile} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{md5 && (
|
{md5 && (
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ const cz: Translation = {
|
|||||||
COMPACT: 'Kompaktní',
|
COMPACT: 'Kompaktní',
|
||||||
DOWNLOAD_SETTINGS_TEXT: 'Vytvořte zálohu svého nastavení a konfigurace',
|
DOWNLOAD_SETTINGS_TEXT: 'Vytvořte zálohu svého nastavení a konfigurace',
|
||||||
UPLOAD_TEXT: 'Nahrajte nový soubor firmwaru (.bin) nebo záložní soubor (.json)',
|
UPLOAD_TEXT: 'Nahrajte nový soubor firmwaru (.bin) nebo záložní soubor (.json)',
|
||||||
UPLOAD_DROP_TEXT: 'Přetáhněte soubor nebo klikněte sem',
|
UPLOAD_DROP_TEXT: 'Přetáhněte soubor sem nebo klikněte pro výběr',
|
||||||
ERROR: 'Neočekávaná chyba, zkuste to prosím znovu',
|
ERROR: 'Neočekávaná chyba, zkuste to prosím znovu',
|
||||||
TIME_SET: 'Čas nastaven',
|
TIME_SET: 'Čas nastaven',
|
||||||
MANAGE_USERS: 'Spravovat uživatele',
|
MANAGE_USERS: 'Spravovat uživatele',
|
||||||
@@ -331,19 +331,27 @@ const cz: Translation = {
|
|||||||
ALLVALUES: 'Všechny hodnoty',
|
ALLVALUES: 'Všechny hodnoty',
|
||||||
SPECIAL_FUNCTIONS: 'Speciální funkce',
|
SPECIAL_FUNCTIONS: 'Speciální funkce',
|
||||||
WAIT_FIRMWARE: 'Firmware se nahrává a instaluje',
|
WAIT_FIRMWARE: 'Firmware se nahrává a instaluje',
|
||||||
INSTALL_VERSION: 'Tímto se instalovat verze {0}. Jste si jistí?',
|
INSTALL_VERSION: 'Tímto se {0} verze {1}. Jste si jistí?',
|
||||||
SWITCH_DEV: 'přepnout na vývojovou verzi',
|
UPDATE_AVAILABLE: 'aktualizace dostupná',
|
||||||
UPGRADE_AVAILABLE: 'Je k dispozici aktualizace firmwaru!',
|
LATEST_VERSION: 'Používáte nejnovější verzi {0}firmwaru',
|
||||||
LATEST_VERSION: 'Používáte nejnovější verzi firmwaru.',
|
|
||||||
PLEASE_WAIT: 'Prosím čekejte',
|
PLEASE_WAIT: 'Prosím čekejte',
|
||||||
RESTARTING_PRE: 'Inicializace',
|
RESTARTING_PRE: 'Inicializace',
|
||||||
RESTARTING_POST: 'Příprava',
|
RESTARTING_POST: 'Příprava',
|
||||||
AUTO_SCROLL: 'Automatické rolování',
|
AUTO_SCROLL: 'Automatické rolování',
|
||||||
DASHBOARD: 'Dashboard',
|
DASHBOARD: 'Dashboard',
|
||||||
NO_DATA: 'Žádná data nejsou k dispozici',
|
|
||||||
DASHBOARD_1: 'Přizpůsobte si dashboard označením EMS entit jako Oblíbené pomocí modulu Přizpůsobení',
|
|
||||||
DEVELOPER_MODE: 'Režim vývojáře',
|
DEVELOPER_MODE: 'Režim vývojáře',
|
||||||
UPGRADE: 'Upgrade' // TODO translate
|
BYTES: 'Bajty',
|
||||||
|
BITMASK: 'Bit Mask',
|
||||||
|
DUPLICATE: 'Duplikát',
|
||||||
|
DASHBOARD_1: 'Všechny aktivní entity EMS jsou označené jako oblíbené. Všechny vlastní entity, harmonogramy a externí sensory jsou zobrazeny níže.',
|
||||||
|
NO_DATA_1: 'Nebyly nalezeny žádné oblíbené entity. Použijte modul',
|
||||||
|
NO_DATA_2: 'pro jejich výběr.',
|
||||||
|
NO_DATA_3: 'Pro zobrazení všech dostupných entit navštivte stránku',
|
||||||
|
THIS_VERSION: 'Tato verze',
|
||||||
|
PLATFORM: 'Platforma',
|
||||||
|
RELEASE_TYPE: 'Typ sestavení',
|
||||||
|
INTERNET_CONNECTION_REQUIRED: 'Pro automatickou kontrolu a instalaci aktualizací je třeba internetové připojení',
|
||||||
|
SWITCH_RELEASE_TYPE: 'Přepnout na {0} verzi'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default cz;
|
export default cz;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ const de: Translation = {
|
|||||||
CANCEL: 'Abbrechen',
|
CANCEL: 'Abbrechen',
|
||||||
RESET: 'Zurücksetzen',
|
RESET: 'Zurücksetzen',
|
||||||
APPLY_CHANGES: 'Änderungen anwenden ({0})',
|
APPLY_CHANGES: 'Änderungen anwenden ({0})',
|
||||||
UPDATE: 'Update',
|
UPDATE: 'Aktualisieren',
|
||||||
EXECUTE: 'Ausführen',
|
EXECUTE: 'Ausführen',
|
||||||
REMOVE: 'Entfernen',
|
REMOVE: 'Entfernen',
|
||||||
PROBLEM_UPDATING: 'Problem beim Aktualisieren',
|
PROBLEM_UPDATING: 'Problem beim Aktualisieren',
|
||||||
@@ -160,7 +160,7 @@ const de: Translation = {
|
|||||||
HELP_INFORMATION_3: 'Um neue Funktionen anzufragen oder Fehler zu melden, eröffnen Sie ein Issue auf GitHub',
|
HELP_INFORMATION_3: 'Um neue Funktionen anzufragen oder Fehler zu melden, eröffnen Sie ein Issue auf GitHub',
|
||||||
HELP_INFORMATION_4: 'Bitte laden Sie die Systemdetails und hängen Sie sie an das Support-Issue an',
|
HELP_INFORMATION_4: 'Bitte laden Sie die Systemdetails und hängen Sie sie an das Support-Issue an',
|
||||||
UPLOAD: 'Hochladen',
|
UPLOAD: 'Hochladen',
|
||||||
DOWNLOAD: '{{H|h|h}}erunterladen',
|
DOWNLOAD: '{{Herunterladen|heruntergeladen|}}',
|
||||||
INSTALL: 'Installieren',
|
INSTALL: 'Installieren',
|
||||||
ABORTED: 'abgebrochen',
|
ABORTED: 'abgebrochen',
|
||||||
FAILED: 'gescheitert',
|
FAILED: 'gescheitert',
|
||||||
@@ -187,7 +187,7 @@ const de: Translation = {
|
|||||||
COMPACT: 'Kompakte Darstellung',
|
COMPACT: 'Kompakte Darstellung',
|
||||||
DOWNLOAD_SETTINGS_TEXT: 'Erstellen Sie eine Sicherung Ihrer Konfigurationen und Einstellungen',
|
DOWNLOAD_SETTINGS_TEXT: 'Erstellen Sie eine Sicherung Ihrer Konfigurationen und Einstellungen',
|
||||||
UPLOAD_TEXT: 'Laden Sie eine neue Firmware-Datei (.bin) oder eine Sicherungsdatei (.json) hoch',
|
UPLOAD_TEXT: 'Laden Sie eine neue Firmware-Datei (.bin) oder eine Sicherungsdatei (.json) hoch',
|
||||||
UPLOAD_DROP_TEXT: 'Klicken Sie hier, oder ziehen Sie eine Datei hierher.',
|
UPLOAD_DROP_TEXT: 'Legen Sie eine Firmware-Datei (.bin) ab oder klicken Sie hier',
|
||||||
ERROR: 'Unerwarteter Fehler, bitte versuchen Sie es erneut.',
|
ERROR: 'Unerwarteter Fehler, bitte versuchen Sie es erneut.',
|
||||||
TIME_SET: 'Zeit gesetzt',
|
TIME_SET: 'Zeit gesetzt',
|
||||||
MANAGE_USERS: 'Nutzerverwaltung',
|
MANAGE_USERS: 'Nutzerverwaltung',
|
||||||
@@ -331,19 +331,27 @@ const de: Translation = {
|
|||||||
ALLVALUES: 'Alle Werte',
|
ALLVALUES: 'Alle Werte',
|
||||||
SPECIAL_FUNCTIONS: 'Sonderfunktionen',
|
SPECIAL_FUNCTIONS: 'Sonderfunktionen',
|
||||||
WAIT_FIRMWARE: 'Die Firmware wird hochgeladen und installiert.',
|
WAIT_FIRMWARE: 'Die Firmware wird hochgeladen und installiert.',
|
||||||
INSTALL_VERSION: 'Dadurch wird die Version {0} heruntergeladen. Sind Sie sicher?',
|
INSTALL_VERSION: 'Dadurch wird die Version {1} {0}. Sind Sie sicher?',
|
||||||
SWITCH_DEV: 'Wechseln Sie zur Entwicklungsversion!',
|
UPDATE_AVAILABLE: 'Firmware-Update verfügbar',
|
||||||
UPGRADE_AVAILABLE: 'Es ist ein Firmware-Upgrade verfügbar.',
|
LATEST_VERSION: 'Sie verwenden die neueste {0} Firmware-Version',
|
||||||
LATEST_VERSION: 'Sie verwenden die neueste Firmware-Version.',
|
|
||||||
PLEASE_WAIT: 'Bitte warten',
|
PLEASE_WAIT: 'Bitte warten',
|
||||||
RESTARTING_PRE: 'Initialisierung',
|
RESTARTING_PRE: 'Initialisierung',
|
||||||
RESTARTING_POST: 'Vorbereitung',
|
RESTARTING_POST: 'Vorbereitung',
|
||||||
AUTO_SCROLL: 'Automatisches Scrollen',
|
AUTO_SCROLL: 'Automatisches Scrollen',
|
||||||
DASHBOARD: 'Dashboard',
|
DASHBOARD: 'Dashboard',
|
||||||
NO_DATA: 'Keine Daten verfügbar',
|
|
||||||
DASHBOARD_1: 'Passen Sie Ihr Dashboard an, indem Sie EMS-Entitäten mithilfe des Moduls „Anpassungen“ als Favorit markieren',
|
|
||||||
DEVELOPER_MODE: 'Entwicklermodus',
|
DEVELOPER_MODE: 'Entwicklermodus',
|
||||||
UPGRADE: 'Upgrade' // TODO translate
|
BYTES: 'Bytes',
|
||||||
|
BITMASK: 'Bit Maske',
|
||||||
|
DUPLICATE: 'Kopieren',
|
||||||
|
DASHBOARD_1: 'Alle EMS-Entitäten, die aktiv und als Favorit markiert sind, sowie alle benutzerdefinierten Entitäten, Zeitpläne und externen Sensordaten werden unten angezeigt.',
|
||||||
|
NO_DATA_1: 'Keine favorisierten EMS-Entitäten gefunden! Verwenden Sie das Modul',
|
||||||
|
NO_DATA_2: ', um sie zu markieren.',
|
||||||
|
NO_DATA_3: 'Um alle verfügbaren Entitäten anzuzeigen, gehen Sie zu',
|
||||||
|
THIS_VERSION: 'Diese Version',
|
||||||
|
PLATFORM: 'Plattform',
|
||||||
|
RELEASE_TYPE: 'Release Typ',
|
||||||
|
INTERNET_CONNECTION_REQUIRED: 'Für die automatische Versionsprüfung und Aktualisierung ist eine Internetverbindung erforderlich',
|
||||||
|
SWITCH_RELEASE_TYPE: 'Zum {0}-Release wechseln'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default de;
|
export default de;
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ const en: Translation = {
|
|||||||
COMPACT: 'Compact',
|
COMPACT: 'Compact',
|
||||||
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings',
|
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings',
|
||||||
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)',
|
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)',
|
||||||
UPLOAD_DROP_TEXT: 'Drop file or click here',
|
UPLOAD_DROP_TEXT: 'Drop a firmware .bin file or click here',
|
||||||
ERROR: 'Unexpected Error, please try again',
|
ERROR: 'Unexpected Error, please try again',
|
||||||
TIME_SET: 'Time set',
|
TIME_SET: 'Time set',
|
||||||
MANAGE_USERS: 'Manage Users',
|
MANAGE_USERS: 'Manage Users',
|
||||||
@@ -331,19 +331,27 @@ const en: Translation = {
|
|||||||
ALLVALUES: 'All Values',
|
ALLVALUES: 'All Values',
|
||||||
SPECIAL_FUNCTIONS: 'Special Functions',
|
SPECIAL_FUNCTIONS: 'Special Functions',
|
||||||
WAIT_FIRMWARE: 'Firmware is uploading and installing',
|
WAIT_FIRMWARE: 'Firmware is uploading and installing',
|
||||||
INSTALL_VERSION: 'This will install version {0}. Are you sure?',
|
INSTALL_VERSION: 'This will {0} version {1}. Are you sure?',
|
||||||
SWITCH_DEV: 'switch to the development version',
|
UPDATE_AVAILABLE: 'update available',
|
||||||
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!',
|
LATEST_VERSION: 'You are using the latest {0} firmware version',
|
||||||
LATEST_VERSION: 'You are using the latest firmware version.',
|
|
||||||
PLEASE_WAIT: 'Please wait',
|
PLEASE_WAIT: 'Please wait',
|
||||||
RESTARTING_PRE: 'Initializing',
|
RESTARTING_PRE: 'Initializing',
|
||||||
RESTARTING_POST: 'Preparing',
|
RESTARTING_POST: 'Preparing',
|
||||||
AUTO_SCROLL: 'Auto Scroll',
|
AUTO_SCROLL: 'Auto Scroll',
|
||||||
DASHBOARD: 'Dashboard',
|
DASHBOARD: 'Dashboard',
|
||||||
NO_DATA: 'No data available',
|
DASHBOARD_1: 'All EMS entities that are active and marked as Favorite, plus all Custom Entities, Schedules and external Sensors data are displayed below.',
|
||||||
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module',
|
|
||||||
DEVELOPER_MODE: 'Developer Mode',
|
DEVELOPER_MODE: 'Developer Mode',
|
||||||
UPGRADE: 'Upgrade'
|
BYTES: 'Bytes',
|
||||||
|
BITMASK: 'Bit Mask',
|
||||||
|
DUPLICATE: 'Duplicate',
|
||||||
|
NO_DATA_1: 'No favorite EMS entities found yet. Use the',
|
||||||
|
NO_DATA_2: 'module to mark them.',
|
||||||
|
NO_DATA_3: 'To see all available entities go to',
|
||||||
|
THIS_VERSION: 'This Version',
|
||||||
|
PLATFORM: 'Platform',
|
||||||
|
RELEASE_TYPE: 'Release Type',
|
||||||
|
INTERNET_CONNECTION_REQUIRED: 'Internet connection required for automatic version checking and upgrading',
|
||||||
|
SWITCH_RELEASE_TYPE: 'Switch to {0} release'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default en;
|
export default en;
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ const fr: Translation = {
|
|||||||
CHANGE_VALUE: 'Changer la valeur',
|
CHANGE_VALUE: 'Changer la valeur',
|
||||||
CANCEL: 'Annuler',
|
CANCEL: 'Annuler',
|
||||||
RESET: 'Réinitialiser',
|
RESET: 'Réinitialiser',
|
||||||
APPLY_CHANGES: 'Apply Changes ({0})', // TODO translate
|
APPLY_CHANGES: 'Appliquer les changements ({0})',
|
||||||
UPDATE: 'Update', // TODO translate
|
UPDATE: 'Update',
|
||||||
EXECUTE: 'Execute', // TODO translate
|
EXECUTE: 'Execute',
|
||||||
REMOVE: 'Enlever',
|
REMOVE: 'Enlever',
|
||||||
PROBLEM_UPDATING: 'Problème lors de la mise à jour',
|
PROBLEM_UPDATING: 'Problème lors de la mise à jour',
|
||||||
PROBLEM_LOADING: 'Problème lors du chargement',
|
PROBLEM_LOADING: 'Problème lors du chargement',
|
||||||
@@ -66,13 +66,13 @@ const fr: Translation = {
|
|||||||
TEMP_SENSOR: 'Capteur de température',
|
TEMP_SENSOR: 'Capteur de température',
|
||||||
TEMP_SENSORS: 'Capteurs de température',
|
TEMP_SENSORS: 'Capteurs de température',
|
||||||
WRITE_CMD_SENT: 'Envoyer la commande sent',
|
WRITE_CMD_SENT: 'Envoyer la commande sent',
|
||||||
EMS_BUS_WARNING: 'Bus EMS déconnecté. Si ce message persiste après quelques secondes, vérifiez les paramètres et la configuration de la carte.',
|
EMS_BUS_WARNING: 'Bus EMS déconnecté. Si ce message persiste après quelques secondes, vérifiez les paramètres et la configuration de la carte.',
|
||||||
EMS_BUS_SCANNING: 'Scan des appareils EMS...',
|
EMS_BUS_SCANNING: 'Scan des appareils EMS...',
|
||||||
CONNECTED: 'Connecté',
|
CONNECTED: 'Connecté',
|
||||||
TX_ISSUES: 'Problèmes de transmission (Tx) - Essayez un autre mode Tx',
|
TX_ISSUES: 'Problèmes de transmission (Tx) - Essayez un autre mode Tx',
|
||||||
DISCONNECTED: 'Déconnecté',
|
DISCONNECTED: 'Déconnecté',
|
||||||
EMS_SCAN: 'Etes-vous sûr de vouloir lancer un scan complet du bus EMS ?',
|
EMS_SCAN: 'Etes-vous sûr de vouloir lancer un scan complet du bus EMS ?',
|
||||||
DATA_TRAFFIC: 'Data Traffic', // TODO translate
|
DATA_TRAFFIC: 'Traffic des données',
|
||||||
EMS_DEVICE: 'Appareils EMS',
|
EMS_DEVICE: 'Appareils EMS',
|
||||||
SUCCESS: 'SUCCÈS',
|
SUCCESS: 'SUCCÈS',
|
||||||
FAIL: 'ÉCHEC',
|
FAIL: 'ÉCHEC',
|
||||||
@@ -114,9 +114,9 @@ const fr: Translation = {
|
|||||||
BYPASS_TOKEN: "Contourner l'autorisation du jeton d'accès sur les appels API",
|
BYPASS_TOKEN: "Contourner l'autorisation du jeton d'accès sur les appels API",
|
||||||
READONLY: 'Activer le mode lecture uniquement (bloque toutes les commandes EMS sortantes en écriture Tx)',
|
READONLY: 'Activer le mode lecture uniquement (bloque toutes les commandes EMS sortantes en écriture Tx)',
|
||||||
UNDERCLOCK_CPU: 'Underclock du CPU',
|
UNDERCLOCK_CPU: 'Underclock du CPU',
|
||||||
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
|
HEATINGOFF: 'Démarrer le chauffage avec le chauffage forcé éteint',
|
||||||
REMOTE_TIMEOUT: 'Remote timeout',
|
REMOTE_TIMEOUT: 'Remote timeout',
|
||||||
REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
|
REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature',
|
||||||
MIN_DURATION: 'Wait time',
|
MIN_DURATION: 'Wait time',
|
||||||
ENABLE_SHOWER_TIMER: 'Activer la minuterie de la douche',
|
ENABLE_SHOWER_TIMER: 'Activer la minuterie de la douche',
|
||||||
ENABLE_SHOWER_ALERT: 'Activer les alertes de durée de douche',
|
ENABLE_SHOWER_ALERT: 'Activer les alertes de durée de douche',
|
||||||
@@ -148,7 +148,7 @@ const fr: Translation = {
|
|||||||
CUSTOMIZATIONS_HELP_3: "désactiver l'action d'écriture",
|
CUSTOMIZATIONS_HELP_3: "désactiver l'action d'écriture",
|
||||||
CUSTOMIZATIONS_HELP_4: "exclure de MQTT et de l'API",
|
CUSTOMIZATIONS_HELP_4: "exclure de MQTT et de l'API",
|
||||||
CUSTOMIZATIONS_HELP_5: 'cacher des appareils',
|
CUSTOMIZATIONS_HELP_5: 'cacher des appareils',
|
||||||
CUSTOMIZATIONS_HELP_6: 'remove from memory', // TODO translate
|
CUSTOMIZATIONS_HELP_6: 'supprimer de la mémoire',
|
||||||
SELECT_DEVICE: 'Sélectionnez un appareil',
|
SELECT_DEVICE: 'Sélectionnez un appareil',
|
||||||
SET_ALL: 'tout régler',
|
SET_ALL: 'tout régler',
|
||||||
OPTIONS: 'Options',
|
OPTIONS: 'Options',
|
||||||
@@ -168,14 +168,14 @@ const fr: Translation = {
|
|||||||
SYSTEM: 'Système',
|
SYSTEM: 'Système',
|
||||||
LOG_OF: '{0} Log',
|
LOG_OF: '{0} Log',
|
||||||
STATUS_OF: 'Statut {0}',
|
STATUS_OF: 'Statut {0}',
|
||||||
DOWNLOAD_UPLOAD: 'Download/Upload', // TODO translate
|
DOWNLOAD_UPLOAD: 'Télécharger/Mettre à jour',
|
||||||
CLOSE: 'Fermer',
|
CLOSE: 'Fermer',
|
||||||
USE: 'Utiliser',
|
USE: 'Utiliser',
|
||||||
FACTORY_RESET: 'Réinitialisation',
|
FACTORY_RESET: 'Réinitialisation',
|
||||||
SYSTEM_FACTORY_TEXT: "L'appareil a été réinitialisé et va maintenant redémarrer",
|
SYSTEM_FACTORY_TEXT: "L'appareil a été réinitialisé et va maintenant redémarrer",
|
||||||
SYSTEM_FACTORY_TEXT_DIALOG: "Êtes-vous sûr de vouloir réinitialiser l'appareil à ses paramètres d'usine ?",
|
SYSTEM_FACTORY_TEXT_DIALOG: "Êtes-vous sûr de vouloir réinitialiser l'appareil à ses paramètres d'usine ?",
|
||||||
AVAILABLE_VERSION: 'Latest Available Versions', // TODO translate
|
AVAILABLE_VERSION: 'Versions disponibles',
|
||||||
STABLE: 'Stable', // TODO translate
|
STABLE: 'Stable',
|
||||||
DEVELOPMENT: 'Développement',
|
DEVELOPMENT: 'Développement',
|
||||||
UPTIME: 'Durée de fonctionnement du système',
|
UPTIME: 'Durée de fonctionnement du système',
|
||||||
FREE_MEMORY: 'Libre Memory',
|
FREE_MEMORY: 'Libre Memory',
|
||||||
@@ -185,9 +185,9 @@ const fr: Translation = {
|
|||||||
FILESYSTEM: 'File System (Utilisée / Libre)',
|
FILESYSTEM: 'File System (Utilisée / Libre)',
|
||||||
BUFFER_SIZE: 'Max taille du buffer',
|
BUFFER_SIZE: 'Max taille du buffer',
|
||||||
COMPACT: 'Compact',
|
COMPACT: 'Compact',
|
||||||
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
|
DOWNLOAD_SETTINGS_TEXT: 'Créer une sauvegarde de vos paramètres et configurations',
|
||||||
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)', // TODO translate
|
UPLOAD_TEXT: 'Télécharger un nouveau fichier firmware (.bin) ou une sauvegarde (.json)',
|
||||||
UPLOAD_DROP_TEXT: 'Déposer le fichier ou cliquer ici',
|
UPLOAD_DROP_TEXT: 'Drop a firmware .bin file or click here',
|
||||||
ERROR: 'Erreur inattendue, veuillez réessayer',
|
ERROR: 'Erreur inattendue, veuillez réessayer',
|
||||||
TIME_SET: 'Time set',
|
TIME_SET: 'Time set',
|
||||||
MANAGE_USERS: 'Gérer les utilisateurs',
|
MANAGE_USERS: 'Gérer les utilisateurs',
|
||||||
@@ -217,7 +217,7 @@ const fr: Translation = {
|
|||||||
MQTT_PUBLISH_TEXT_2: 'Publier vers des topics de commande (ioBroker)',
|
MQTT_PUBLISH_TEXT_2: 'Publier vers des topics de commande (ioBroker)',
|
||||||
MQTT_PUBLISH_TEXT_3: 'Activer la découverte MQTT',
|
MQTT_PUBLISH_TEXT_3: 'Activer la découverte MQTT',
|
||||||
MQTT_PUBLISH_TEXT_4: 'Préfixe pour les topics découverte',
|
MQTT_PUBLISH_TEXT_4: 'Préfixe pour les topics découverte',
|
||||||
MQTT_PUBLISH_TEXT_5: 'Discovery type', // TODO translate
|
MQTT_PUBLISH_TEXT_5: 'Type de découverte',
|
||||||
MQTT_PUBLISH_INTERVALS: 'Intervalles de publication',
|
MQTT_PUBLISH_INTERVALS: 'Intervalles de publication',
|
||||||
MQTT_INT_BOILER: 'Chaudières et pompes à chaleur',
|
MQTT_INT_BOILER: 'Chaudières et pompes à chaleur',
|
||||||
MQTT_INT_THERMOSTATS: 'Thermostats',
|
MQTT_INT_THERMOSTATS: 'Thermostats',
|
||||||
@@ -226,10 +226,10 @@ const fr: Translation = {
|
|||||||
MQTT_INT_WATER: 'Modules eau',
|
MQTT_INT_WATER: 'Modules eau',
|
||||||
MQTT_QUEUE: 'Queue MQTT',
|
MQTT_QUEUE: 'Queue MQTT',
|
||||||
DEFAULT: 'Défaut',
|
DEFAULT: 'Défaut',
|
||||||
MQTT_ENTITY_FORMAT: 'Entity ID format', // TODO translate
|
MQTT_ENTITY_FORMAT: 'Format de l\'ID de l\'entité',
|
||||||
MQTT_ENTITY_FORMAT_0: 'Single instance, long name (v3.4)', // TODO translate
|
MQTT_ENTITY_FORMAT_0: 'Instance unique, nom long (v3.4)',
|
||||||
MQTT_ENTITY_FORMAT_1: 'Single instance, short name', // TODO translate
|
MQTT_ENTITY_FORMAT_1: 'Instance unique, nom court',
|
||||||
MQTT_ENTITY_FORMAT_2: 'Multiple instances, short name', // TODO translate
|
MQTT_ENTITY_FORMAT_2: 'Instances multiples, nom court',
|
||||||
MQTT_CLEAN_SESSION: 'Flag Clean Session',
|
MQTT_CLEAN_SESSION: 'Flag Clean Session',
|
||||||
MQTT_RETAIN_FLAG: 'Toujours activer le Retain Flag',
|
MQTT_RETAIN_FLAG: 'Toujours activer le Retain Flag',
|
||||||
INACTIVE: 'Inactif',
|
INACTIVE: 'Inactif',
|
||||||
@@ -260,7 +260,7 @@ const fr: Translation = {
|
|||||||
NETWORK_SCANNER: 'Scan réseau',
|
NETWORK_SCANNER: 'Scan réseau',
|
||||||
NETWORK_NO_WIFI: 'Pas de réseau WiFi trouvé',
|
NETWORK_NO_WIFI: 'Pas de réseau WiFi trouvé',
|
||||||
NETWORK_BLANK_SSID: 'laisser vide pour désactiver le WiFi',
|
NETWORK_BLANK_SSID: 'laisser vide pour désactiver le WiFi',
|
||||||
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
|
NETWORK_BLANK_BSSID: 'laisser vide pour utiliser uniquement le SSID',
|
||||||
TX_POWER: 'Puissance Tx',
|
TX_POWER: 'Puissance Tx',
|
||||||
HOSTNAME: "Nom d'hôte",
|
HOSTNAME: "Nom d'hôte",
|
||||||
NETWORK_DISABLE_SLEEP: 'Désactiver le mode veille du WiFi',
|
NETWORK_DISABLE_SLEEP: 'Désactiver le mode veille du WiFi',
|
||||||
@@ -280,70 +280,78 @@ const fr: Translation = {
|
|||||||
ENTITY: 'entité',
|
ENTITY: 'entité',
|
||||||
MIN: 'min',
|
MIN: 'min',
|
||||||
MAX: 'max',
|
MAX: 'max',
|
||||||
BLOCK_NAVIGATE_1: 'You have unsaved changes', // TODO translate
|
BLOCK_NAVIGATE_1: 'Vous avez des modifications non enregistrées',
|
||||||
BLOCK_NAVIGATE_2: 'If you navigate to a different page, your unsaved changes will be lost. Are you sure you want to leave this page?', // TODO translate
|
BLOCK_NAVIGATE_2: 'Si vous naviguez vers une autre page, vos modifications non enregistrées seront perdues. Êtes-vous sûr de vouloir quitter cette page ?',
|
||||||
STAY: 'Stay', // TODO translate
|
STAY: 'Rester',
|
||||||
LEAVE: 'Leave', // TODO translate
|
LEAVE: 'Quitter',
|
||||||
SCHEDULER: 'Scheduler', // TODO translate
|
SCHEDULER: 'Scheduler',
|
||||||
SCHEDULER_HELP_1: 'Automate commands by adding scheduled events below. Set a unique Name to enable/disable activation via API/MQTT', // TODO translate
|
SCHEDULER_HELP_1: 'Automatiser les commandes en ajoutant des événements programmés ci-dessous. Définissez un nom unique pour activer/désactiver l\'activation via API/MQTT',
|
||||||
SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate
|
SCHEDULER_HELP_2: 'Utiliser 00:00 pour déclencher une fois au démarrage',
|
||||||
SCHEDULE: 'Schedule', // TODO translate
|
SCHEDULE: 'Programme',
|
||||||
TIME: 'Time', // TODO translate
|
TIME: 'Temps',
|
||||||
TIMER: 'Timer', // TODO translate
|
TIMER: 'Minuteur',
|
||||||
ONCHANGE: 'Sur le changement', // TODO translate
|
ONCHANGE: 'Sur le changement',
|
||||||
CONDITION: 'Condition', // TODO translate
|
CONDITION: 'Condition',
|
||||||
IMMEDIATE: 'Immédiate', // TODO translate
|
IMMEDIATE: 'Immédiat',
|
||||||
SCHEDULE_UPDATED: 'Schedule updated', // TODO translate
|
SCHEDULE_UPDATED: 'Programme mis à jour',
|
||||||
SCHEDULE_TIMER_1: 'on startup', // TODO translate
|
SCHEDULE_TIMER_1: 'au démarrage',
|
||||||
SCHEDULE_TIMER_2: 'every minute', // TODO translate
|
SCHEDULE_TIMER_2: 'toutes les minutes',
|
||||||
SCHEDULE_TIMER_3: 'every hour', // TODO translate
|
SCHEDULE_TIMER_3: 'toutes les heures',
|
||||||
CUSTOM_ENTITIES: 'Custom Entities', // TODO translate
|
CUSTOM_ENTITIES: 'Entités personnalisées',
|
||||||
ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', // TODO translate
|
ENTITIES_HELP_1: 'Récupérer les entités personnalisées du bus EMS',
|
||||||
ENTITIES_UPDATED: 'Entities Updated', // TODO translate
|
ENTITIES_UPDATED: 'Entités mises à jour',
|
||||||
WRITEABLE: 'Writeable', // TODO translate
|
WRITEABLE: 'Écriture',
|
||||||
SHOWING: 'Showing', // TODO translate
|
SHOWING: 'Affichage',
|
||||||
SEARCH: 'Search', // TODO translate
|
SEARCH: 'Rechercher',
|
||||||
CERT: 'TLS root certificate (leave blank for insecure)', // TODO translate
|
CERT: 'Certificat racine TLS (laisser vide pour l\'insecurité)',
|
||||||
ENABLE_TLS: 'Activer TLS',
|
ENABLE_TLS: 'Activer TLS',
|
||||||
ON: 'On', // TODO translate
|
ON: 'On',
|
||||||
OFF: 'Off', // TODO translate
|
OFF: 'Off',
|
||||||
POLARITY: 'Polarity', // TODO translate
|
POLARITY: 'Polarity',
|
||||||
ACTIVEHIGH: 'Active High', // TODO translate
|
ACTIVEHIGH: 'Actif haut',
|
||||||
ACTIVELOW: 'Active Low', // TODO translate
|
ACTIVELOW: 'Actif bas',
|
||||||
UNCHANGED: 'Unchanged', // TODO translate
|
UNCHANGED: 'Inchangé',
|
||||||
ALWAYS: 'Always', // TODO translate
|
ALWAYS: 'Toujours',
|
||||||
ACTIVITY: 'Activity', // TODO translate
|
ACTIVITY: 'Activité',
|
||||||
CONFIGURE: 'Configure {0}', // TODO translate
|
CONFIGURE: 'Configurer {0}',
|
||||||
SYSTEM_MEMORY: 'System Memory', // TODO translate
|
SYSTEM_MEMORY: 'Mémoire système',
|
||||||
APPLICATION_SETTINGS_1: 'Modify EMS-ESP Application Settings', // TODO translate
|
APPLICATION_SETTINGS_1: 'Modifier les paramètres de l\'application EMS-ESP',
|
||||||
SECURITY_1: 'Add or remove users', // TODO translate
|
SECURITY_1: 'Ajouter ou supprimer des utilisateurs',
|
||||||
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate
|
DOWNLOAD_UPLOAD_1: 'Télécharger et mettre à jour les paramètres et le firmware',
|
||||||
MODULES: 'Module', // TODO translate
|
MODULES: 'Module',
|
||||||
MODULES_1: 'Activer ou désactiver les modules externes',
|
MODULES_1: 'Activer ou désactiver les modules externes',
|
||||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
MODULES_UPDATED: 'Modules mis à jour',
|
||||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
MODULES_DESCRIPTION: 'Cliquer sur le module pour activer ou désactiver les modules EMS-ESP',
|
||||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
MODULES_NONE: 'Aucun module externe détecté',
|
||||||
RENAME: 'Rename', // TODO translate
|
RENAME: 'Renommer',
|
||||||
ENABLE_MODBUS: 'Activer Modbus',
|
ENABLE_MODBUS: 'Activer Modbus',
|
||||||
VIEW_LOG: 'View log to diagnose issues', // TODO translate
|
VIEW_LOG: 'Voir le journal pour diagnostiquer les problèmes',
|
||||||
UPLOAD_DRAG: 'drag and drop a file here or click to select one', // TODO translate
|
UPLOAD_DRAG: 'glisser-déposer un fichier ici ou cliquer pour en sélectionner un',
|
||||||
SERVICES: 'Services', // TODO translate
|
SERVICES: 'Services',
|
||||||
ALLVALUES: 'All Values', // TODO translate
|
ALLVALUES: 'Toutes les valeurs',
|
||||||
SPECIAL_FUNCTIONS: 'Special Functions',
|
SPECIAL_FUNCTIONS: 'Fonctions spéciales',
|
||||||
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
|
WAIT_FIRMWARE: 'Firmware en cours de téléchargement et d\'installation',
|
||||||
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
|
INSTALL_VERSION: 'Cela va {0} la version {1}. Êtes-vous sûr ?',
|
||||||
SWITCH_DEV: 'switch to the development version', // TODO translate
|
UPDATE_AVAILABLE: 'mise à jour disponible',
|
||||||
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
|
LATEST_VERSION: 'Vous utilisez la dernière version {0} du firmware',
|
||||||
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
|
PLEASE_WAIT: 'Veuillez patienter',
|
||||||
PLEASE_WAIT: 'Please wait', // TODO translate
|
RESTARTING_PRE: 'Initialisation',
|
||||||
RESTARTING_PRE: 'Initializing', // TODO translate
|
RESTARTING_POST: 'Préparation',
|
||||||
RESTARTING_POST: 'Preparing', // TODO translate
|
AUTO_SCROLL: 'Défilement automatique',
|
||||||
AUTO_SCROLL: 'Auto Scroll', // TODO translate
|
DASHBOARD: 'Tableau de bord',
|
||||||
DASHBOARD: 'Dashboard', // TODO translate
|
DEVELOPER_MODE: 'Mode développeur',
|
||||||
NO_DATA: 'No data available', // TODO translate
|
BYTES: 'Octets',
|
||||||
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
|
BITMASK: 'Masque de bits',
|
||||||
DEVELOPER_MODE: 'Developer Mode', // TODO translate
|
DUPLICATE: 'Dupliquer',
|
||||||
UPGRADE: 'Upgrade' // TODO translate
|
DASHBOARD_1: 'Toutes les entités EMS actives et marquées comme favoris, plus toutes les entités personnalisées, les programmes et les données des capteurs externes sont affichées ci-dessous.',
|
||||||
|
NO_DATA_1: 'Aucune entité EMS favorite trouvée. Utilisez le',
|
||||||
|
NO_DATA_2: 'module pour les marquer.',
|
||||||
|
NO_DATA_3: 'Pour voir toutes les entités disponibles, aller à',
|
||||||
|
THIS_VERSION: 'Cette version',
|
||||||
|
PLATFORM: 'Plateforme',
|
||||||
|
RELEASE_TYPE: 'Type de version',
|
||||||
|
INTERNET_CONNECTION_REQUIRED: 'Connexion Internet requise pour la vérification automatique des versions et la mise à niveau',
|
||||||
|
SWITCH_RELEASE_TYPE: 'Passer à la version {0}'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default fr;
|
export default fr;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ const it: Translation = {
|
|||||||
TX_ISSUES: 'Problema di Tx - prova una modalità differente',
|
TX_ISSUES: 'Problema di Tx - prova una modalità differente',
|
||||||
DISCONNECTED: 'Disconnesso',
|
DISCONNECTED: 'Disconnesso',
|
||||||
EMS_SCAN: 'Sei sicuro di voler iniziare una scansione completa del bus EMS ?',
|
EMS_SCAN: 'Sei sicuro di voler iniziare una scansione completa del bus EMS ?',
|
||||||
DATA_TRAFFIC: 'Data Traffic', // TODO translate
|
DATA_TRAFFIC: 'Traffico dati',
|
||||||
EMS_DEVICE: 'Dispositivo EMS ',
|
EMS_DEVICE: 'Dispositivo EMS ',
|
||||||
SUCCESS: 'SUCCESSO',
|
SUCCESS: 'SUCCESSO',
|
||||||
FAIL: 'FALLITO',
|
FAIL: 'FALLITO',
|
||||||
@@ -115,7 +115,7 @@ const it: Translation = {
|
|||||||
READONLY: 'Abilita modalità sola-lettura (blocca tutti i comandi di scrittura EMS Tx in uscita)',
|
READONLY: 'Abilita modalità sola-lettura (blocca tutti i comandi di scrittura EMS Tx in uscita)',
|
||||||
UNDERCLOCK_CPU: 'Abbassa velocità della CPU',
|
UNDERCLOCK_CPU: 'Abbassa velocità della CPU',
|
||||||
REMOTE_TIMEOUT: 'Remote timeout',
|
REMOTE_TIMEOUT: 'Remote timeout',
|
||||||
REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
|
REMOTE_TIMEOUT_EN: 'Disabilitare il telecomando in caso di temperatura ambiente mancante',
|
||||||
HEATINGOFF: 'Avviamento caldaia con riscaldamento forzato spento',
|
HEATINGOFF: 'Avviamento caldaia con riscaldamento forzato spento',
|
||||||
MIN_DURATION: 'Wait time',
|
MIN_DURATION: 'Wait time',
|
||||||
ENABLE_SHOWER_TIMER: 'Abilita timer doccia',
|
ENABLE_SHOWER_TIMER: 'Abilita timer doccia',
|
||||||
@@ -174,8 +174,8 @@ const it: Translation = {
|
|||||||
FACTORY_RESET: 'Impostazioni di fabbrica',
|
FACTORY_RESET: 'Impostazioni di fabbrica',
|
||||||
SYSTEM_FACTORY_TEXT: 'Il dispositivo è stato ripristinato alle impostazioni di fabbrica e ora verrà riavviato',
|
SYSTEM_FACTORY_TEXT: 'Il dispositivo è stato ripristinato alle impostazioni di fabbrica e ora verrà riavviato',
|
||||||
SYSTEM_FACTORY_TEXT_DIALOG: 'Sei sicuro di voler ripristinare il dispositivo alle impostazioni di fabbrica??',
|
SYSTEM_FACTORY_TEXT_DIALOG: 'Sei sicuro di voler ripristinare il dispositivo alle impostazioni di fabbrica??',
|
||||||
AVAILABLE_VERSION: 'Latest Available Versions', // TODO translate
|
AVAILABLE_VERSION: 'Versioni disponibili',
|
||||||
STABLE: 'Stable', // TODO translate
|
STABLE: 'Stabile',
|
||||||
DEVELOPMENT: 'Sviluppo',
|
DEVELOPMENT: 'Sviluppo',
|
||||||
UPTIME: 'Tempo di attività del sistema',
|
UPTIME: 'Tempo di attività del sistema',
|
||||||
FREE_MEMORY: 'Free Memory',
|
FREE_MEMORY: 'Free Memory',
|
||||||
@@ -184,10 +184,10 @@ const it: Translation = {
|
|||||||
APPSIZE: 'Applicazione (Partizione: Usata / Libera)',
|
APPSIZE: 'Applicazione (Partizione: Usata / Libera)',
|
||||||
FILESYSTEM: 'Memoria Sistema (Usata / Libera)',
|
FILESYSTEM: 'Memoria Sistema (Usata / Libera)',
|
||||||
BUFFER_SIZE: 'Max Buffer Size',
|
BUFFER_SIZE: 'Max Buffer Size',
|
||||||
COMPACT: 'Compact',
|
COMPACT: 'Compatto',
|
||||||
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
|
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings',
|
||||||
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)', // TODO translate
|
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)',
|
||||||
UPLOAD_DROP_TEXT: 'Trascina il file o clicca qui',
|
UPLOAD_DROP_TEXT: 'Drop a firmware .bin file or click here',
|
||||||
ERROR: 'Errore Inaspettato, prego tenta ancora',
|
ERROR: 'Errore Inaspettato, prego tenta ancora',
|
||||||
TIME_SET: 'Imposta Ora',
|
TIME_SET: 'Imposta Ora',
|
||||||
MANAGE_USERS: 'Gestione Utenti',
|
MANAGE_USERS: 'Gestione Utenti',
|
||||||
@@ -260,7 +260,7 @@ const it: Translation = {
|
|||||||
NETWORK_SCANNER: 'Scansione Rete',
|
NETWORK_SCANNER: 'Scansione Rete',
|
||||||
NETWORK_NO_WIFI: 'Nessuana rete WiFi trovata',
|
NETWORK_NO_WIFI: 'Nessuana rete WiFi trovata',
|
||||||
NETWORK_BLANK_SSID: 'lasciare vuoto per disattivare WiFi',
|
NETWORK_BLANK_SSID: 'lasciare vuoto per disattivare WiFi',
|
||||||
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
|
NETWORK_BLANK_BSSID: 'lasciare vuoto per usare solo SSID',
|
||||||
TX_POWER: 'Potenza Tx',
|
TX_POWER: 'Potenza Tx',
|
||||||
HOSTNAME: 'Nome ospite',
|
HOSTNAME: 'Nome ospite',
|
||||||
NETWORK_DISABLE_SLEEP: 'Disabilita la modalità sospensione Wi-Fi',
|
NETWORK_DISABLE_SLEEP: 'Disabilita la modalità sospensione Wi-Fi',
|
||||||
@@ -303,47 +303,55 @@ const it: Translation = {
|
|||||||
WRITEABLE: 'Scrivibile',
|
WRITEABLE: 'Scrivibile',
|
||||||
SHOWING: 'Visualizza',
|
SHOWING: 'Visualizza',
|
||||||
SEARCH: 'Ricerca',
|
SEARCH: 'Ricerca',
|
||||||
CERT: 'TLS root certificate (leave blank for insecure)', // TODO translate
|
CERT: 'Certificato radice TLS (lasciare vuoto per l\'insecure)',
|
||||||
ENABLE_TLS: 'Abilita TLS',
|
ENABLE_TLS: 'Abilita TLS',
|
||||||
ON: 'On', // TODO translate
|
ON: 'On',
|
||||||
OFF: 'Off', // TODO translate
|
OFF: 'Off',
|
||||||
POLARITY: 'Polarity', // TODO translate
|
POLARITY: 'Polarity',
|
||||||
ACTIVEHIGH: 'Active High', // TODO translate
|
ACTIVEHIGH: 'Active High',
|
||||||
ACTIVELOW: 'Active Low', // TODO translate
|
ACTIVELOW: 'Active Low',
|
||||||
UNCHANGED: 'Unchanged', // TODO translate
|
UNCHANGED: 'Unchanged',
|
||||||
ALWAYS: 'Always', // TODO translate
|
ALWAYS: 'Always',
|
||||||
ACTIVITY: 'Activity', // TODO translate
|
ACTIVITY: 'Activity',
|
||||||
CONFIGURE: 'Configure {0}', // TODO translate
|
CONFIGURE: 'Configure {0}',
|
||||||
SYSTEM_MEMORY: 'System Memory', // TODO translate
|
SYSTEM_MEMORY: 'System Memory',
|
||||||
APPLICATION_SETTINGS_1: 'Modify EMS-ESP Application Settings', // TODO translate
|
APPLICATION_SETTINGS_1: 'Modify EMS-ESP Application Settings',
|
||||||
SECURITY_1: 'Add or remove users', // TODO translate
|
SECURITY_1: 'Add or remove users',
|
||||||
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate
|
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware',
|
||||||
MODULES: 'Module', // TODO translate
|
MODULES: 'Module',
|
||||||
MODULES_1: 'Attiva o disattiva i moduli esterni', // TODO translate
|
MODULES_1: 'Attiva o disattiva i moduli esterni',
|
||||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
MODULES_UPDATED: 'Modules updated',
|
||||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules',
|
||||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
MODULES_NONE: 'No external modules detected',
|
||||||
RENAME: 'Rename', // TODO translate
|
RENAME: 'Rename',
|
||||||
ENABLE_MODBUS: 'Abilita Modbus',
|
ENABLE_MODBUS: 'Abilita Modbus',
|
||||||
VIEW_LOG: 'View log to diagnose issues', // TODO translate
|
VIEW_LOG: 'Visualizza log per diagnosticare problemi',
|
||||||
UPLOAD_DRAG: 'drag and drop a file here or click to select one', // TODO translate
|
UPLOAD_DRAG: 'trascina e rilascia un file qui o clicca per selezionare uno',
|
||||||
SERVICES: 'Services', // TODO translate
|
SERVICES: 'Servizi',
|
||||||
ALLVALUES: 'All Values', // TODO translate
|
ALLVALUES: 'Tutti i valori',
|
||||||
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
|
SPECIAL_FUNCTIONS: 'Funzioni speciali',
|
||||||
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
|
WAIT_FIRMWARE: 'Firmware è in upload e installazione',
|
||||||
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
|
INSTALL_VERSION: 'Questo installerà la versione {1} {0}. Sei sicuro?',
|
||||||
SWITCH_DEV: 'switch to the development version', // TODO translate
|
UPDATE_AVAILABLE: 'aggiornamento disponibile',
|
||||||
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
|
LATEST_VERSION: 'Stai usando la versione più recente del firmware {0}',
|
||||||
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
|
PLEASE_WAIT: 'Attendere',
|
||||||
PLEASE_WAIT: 'Please wait', // TODO translate
|
RESTARTING_PRE: 'Inizializzazione',
|
||||||
RESTARTING_PRE: 'Initializing', // TODO translate
|
RESTARTING_POST: 'Preparazione',
|
||||||
RESTARTING_POST: 'Preparing', // TODO translate
|
AUTO_SCROLL: 'Scorrimento automatico',
|
||||||
AUTO_SCROLL: 'Auto Scroll', // TODO translate
|
DASHBOARD: 'Pannello di controllo',
|
||||||
DASHBOARD: 'Dashboard', // TODO translate
|
DEVELOPER_MODE: 'Modalità sviluppatore',
|
||||||
NO_DATA: 'No data available', // TODO translate
|
BYTES: 'Byte',
|
||||||
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
|
BITMASK: 'Bitmask',
|
||||||
DEVELOPER_MODE: 'Developer Mode', // TODO translate
|
DUPLICATE: 'Duplicato',
|
||||||
UPGRADE: 'Upgrade' // TODO translate
|
DASHBOARD_1: 'Tutte le entità EMS che sono attive e marcate come preferite, più tutte le entità personalizzate, piani di programmazione e dati dei sensori esterni sono visualizzati di seguito.',
|
||||||
|
NO_DATA_1: 'Nessuna entità EMS preferita trovata. Usa il',
|
||||||
|
NO_DATA_2: 'modulo per marcarle.',
|
||||||
|
NO_DATA_3: 'Per vedere tutte le entità disponibili vai a',
|
||||||
|
THIS_VERSION: 'Questa versione',
|
||||||
|
PLATFORM: 'Piattaforma',
|
||||||
|
RELEASE_TYPE: 'Tipo di rilascio',
|
||||||
|
INTERNET_CONNECTION_REQUIRED: 'Connessione internet richiesta per il controllo automatico delle versioni e l\'aggiornamento',
|
||||||
|
SWITCH_RELEASE_TYPE: 'Cambia in {0} rilascio'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default it;
|
export default it;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ const nl: Translation = {
|
|||||||
TX_ISSUES: 'Tx bus probleem. Probeer een andere Tx verzendmodus',
|
TX_ISSUES: 'Tx bus probleem. Probeer een andere Tx verzendmodus',
|
||||||
DISCONNECTED: 'Niet verbonden',
|
DISCONNECTED: 'Niet verbonden',
|
||||||
EMS_SCAN: 'Weet je zeker dat je een volledige EMS bus scan uit wilt voeren?',
|
EMS_SCAN: 'Weet je zeker dat je een volledige EMS bus scan uit wilt voeren?',
|
||||||
DATA_TRAFFIC: 'Data Traffic', // TODO translate
|
DATA_TRAFFIC: 'Dataverkeer',
|
||||||
EMS_DEVICE: 'EMS Apparaat',
|
EMS_DEVICE: 'EMS Apparaat',
|
||||||
SUCCESS: 'SUCCESS',
|
SUCCESS: 'SUCCESS',
|
||||||
FAIL: 'MISLUKT',
|
FAIL: 'MISLUKT',
|
||||||
@@ -115,7 +115,7 @@ const nl: Translation = {
|
|||||||
READONLY: 'Activeer read-only modus (blokkeert alle outgaande EMS Tx schrijf commandos)',
|
READONLY: 'Activeer read-only modus (blokkeert alle outgaande EMS Tx schrijf commandos)',
|
||||||
UNDERCLOCK_CPU: 'Underclock CPU snelheid',
|
UNDERCLOCK_CPU: 'Underclock CPU snelheid',
|
||||||
REMOTE_TIMEOUT: 'Remote timeout',
|
REMOTE_TIMEOUT: 'Remote timeout',
|
||||||
REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
|
REMOTE_TIMEOUT_EN: 'Schakel de afstandsbediening uit bij ontbrekende kamertemperatuur',
|
||||||
HEATINGOFF: 'Start ketel met geforceerde verwarming uit',
|
HEATINGOFF: 'Start ketel met geforceerde verwarming uit',
|
||||||
MIN_DURATION: 'Wait time',
|
MIN_DURATION: 'Wait time',
|
||||||
ENABLE_SHOWER_TIMER: 'Activeer Douche Timer (tijdmeting)',
|
ENABLE_SHOWER_TIMER: 'Activeer Douche Timer (tijdmeting)',
|
||||||
@@ -174,7 +174,7 @@ const nl: Translation = {
|
|||||||
FACTORY_RESET: 'Fabrieksinstellingen',
|
FACTORY_RESET: 'Fabrieksinstellingen',
|
||||||
SYSTEM_FACTORY_TEXT: 'Gateway is gereset en start nu weer op met fabrieksinstellingen',
|
SYSTEM_FACTORY_TEXT: 'Gateway is gereset en start nu weer op met fabrieksinstellingen',
|
||||||
SYSTEM_FACTORY_TEXT_DIALOG: 'Weet je zeker dat je een reset naar fabrieksinstellingen uit wilt voeren?',
|
SYSTEM_FACTORY_TEXT_DIALOG: 'Weet je zeker dat je een reset naar fabrieksinstellingen uit wilt voeren?',
|
||||||
AVAILABLE_VERSION: 'Latest Available Versions', // TODO translate
|
AVAILABLE_VERSION: 'Nieuwste beschikbare versies',
|
||||||
STABLE: 'Stable',
|
STABLE: 'Stable',
|
||||||
DEVELOPMENT: 'Development',
|
DEVELOPMENT: 'Development',
|
||||||
UPTIME: 'Systeem Uptime',
|
UPTIME: 'Systeem Uptime',
|
||||||
@@ -185,9 +185,9 @@ const nl: Translation = {
|
|||||||
FILESYSTEM: 'File System (Used / Free)',
|
FILESYSTEM: 'File System (Used / Free)',
|
||||||
BUFFER_SIZE: 'Max Buffer Size',
|
BUFFER_SIZE: 'Max Buffer Size',
|
||||||
COMPACT: 'Compact',
|
COMPACT: 'Compact',
|
||||||
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
|
DOWNLOAD_SETTINGS_TEXT: 'Maak een back-up van uw configuratie en instellingen',
|
||||||
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)', // TODO translate
|
UPLOAD_TEXT: 'Upload een nieuw firmwarebestand (.bin) of een back-upbestand (.json)',
|
||||||
UPLOAD_DROP_TEXT: 'Sleep bestand hierheen of klik hier',
|
UPLOAD_DROP_TEXT: 'Sleep en firmware .bin bestand hierheen of klik hier',
|
||||||
ERROR: 'Onverwachte fout, probeer opnieuw',
|
ERROR: 'Onverwachte fout, probeer opnieuw',
|
||||||
TIME_SET: 'Tijd ingesteld',
|
TIME_SET: 'Tijd ingesteld',
|
||||||
MANAGE_USERS: 'Beheer Gebruikers',
|
MANAGE_USERS: 'Beheer Gebruikers',
|
||||||
@@ -273,7 +273,7 @@ const nl: Translation = {
|
|||||||
NETWORK_SUBNET: 'Subnetmasker',
|
NETWORK_SUBNET: 'Subnetmasker',
|
||||||
NETWORK_DNS: 'DNS Servers',
|
NETWORK_DNS: 'DNS Servers',
|
||||||
ADDRESS_OF: '{0} Address',
|
ADDRESS_OF: '{0} Address',
|
||||||
ADMINISTRATOR: 'Administrator',
|
ADMINISTRATOR: 'Administrator',
|
||||||
GUEST: 'Gast',
|
GUEST: 'Gast',
|
||||||
NEW: 'Nieuwe',
|
NEW: 'Nieuwe',
|
||||||
NEW_NAME_OF: 'Hernoem {0}',
|
NEW_NAME_OF: 'Hernoem {0}',
|
||||||
@@ -319,31 +319,39 @@ const nl: Translation = {
|
|||||||
SECURITY_1: 'Gebruikers toevoegen of verwijderen',
|
SECURITY_1: 'Gebruikers toevoegen of verwijderen',
|
||||||
DOWNLOAD_UPLOAD_1: 'Download en upload instellingen en firmware',
|
DOWNLOAD_UPLOAD_1: 'Download en upload instellingen en firmware',
|
||||||
MODULES: 'Module',
|
MODULES: 'Module',
|
||||||
MODULES_1: 'Externe modules activeren of deactiveren', // TODO translate
|
MODULES_1: 'Externe modules activeren of deactiveren',
|
||||||
MODULES_UPDATED: 'Modules geüpdatet',
|
MODULES_UPDATED: 'Modules geüpdatet',
|
||||||
MODULES_DESCRIPTION: 'Klik op de module om EMS-ESP library modules te activeren of te deactiveren',
|
MODULES_DESCRIPTION: 'Klik op de module om EMS-ESP library modules te activeren of te deactiveren',
|
||||||
MODULES_NONE: 'Geen externe modules gedetecteerd',
|
MODULES_NONE: 'Geen externe modules gedetecteerd',
|
||||||
RENAME: 'Hernoemen',
|
RENAME: 'Hernoemen',
|
||||||
ENABLE_MODBUS: 'Activeer Modbus',
|
ENABLE_MODBUS: 'Activeer Modbus',
|
||||||
VIEW_LOG: 'View log to diagnose issues', // TODO translate
|
VIEW_LOG: 'Log weergeven om problemen te diagnosticeren',
|
||||||
UPLOAD_DRAG: 'drag and drop a file here or click to select one', // TODO translate
|
UPLOAD_DRAG: 'sleep hier een bestand en zet het neer of klik om er een te selecteren',
|
||||||
SERVICES: 'Services', // TODO translate
|
SERVICES: 'Services',
|
||||||
ALLVALUES: 'All Values', // TODO translate
|
ALLVALUES: 'All waarden',
|
||||||
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
|
SPECIAL_FUNCTIONS: 'Speciale functies',
|
||||||
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
|
WAIT_FIRMWARE: 'Firmware wordt geüpload en geïnstalleerd',
|
||||||
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
|
INSTALL_VERSION: 'Hiermee wordt versie {1} {0}. Weet je het zeker?',
|
||||||
SWITCH_DEV: 'switch to the development version', // TODO translate
|
UPDATE_AVAILABLE: 'update beschikbaar',
|
||||||
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
|
LATEST_VERSION: 'U gebruikt de nieuwste {0} firmwareversie',
|
||||||
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
|
PLEASE_WAIT: 'Een ogenblik geduld',
|
||||||
PLEASE_WAIT: 'Please wait', // TODO translate
|
RESTARTING_PRE: 'Initialiseren',
|
||||||
RESTARTING_PRE: 'Initializing', // TODO translate
|
RESTARTING_POST: 'Voorbereiding',
|
||||||
RESTARTING_POST: 'Preparing', // TODO translate
|
AUTO_SCROLL: 'Automatisch Scrollen',
|
||||||
AUTO_SCROLL: 'Auto Scroll', // TODO translate
|
DASHBOARD: 'Dashboard',
|
||||||
DASHBOARD: 'Dashboard', // TODO translate
|
DEVELOPER_MODE: 'Ontwikkelaarsmodus',
|
||||||
NO_DATA: 'No data available', // TODO translate
|
BYTES: 'Bytes',
|
||||||
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
|
BITMASK: 'Bit Mask',
|
||||||
DEVELOPER_MODE: 'Developer Mode', // TODO translate
|
DUPLICATE: 'Duplicaat',
|
||||||
UPGRADE: 'Upgrade' // TODO translate
|
DASHBOARD_1: 'Alle EMS-entiteiten die actief zijn en als favoriet zijn gemarkeerd, plus alle aangepaste entiteiten en externe sensorgegevens worden hieronder weergegeven.',
|
||||||
|
NO_DATA_1: 'Er zijn nog geen favoriete EMS-entiteiten gevonden. Gebruik de',
|
||||||
|
NO_DATA_2: 'module om ze te markeren.',
|
||||||
|
NO_DATA_3: 'Om alle beschikbare entiteiten te zien, ga naar',
|
||||||
|
THIS_VERSION: 'Deze Versie',
|
||||||
|
PLATFORM: 'Platform',
|
||||||
|
RELEASE_TYPE: 'Release Typ',
|
||||||
|
INTERNET_CONNECTION_REQUIRED: 'Internetverbinding vereist voor automatische versiecontrole en -upgrade',
|
||||||
|
SWITCH_RELEASE_TYPE: 'Switch naar {0} release'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nl;
|
export default nl;
|
||||||
@@ -43,7 +43,7 @@ const no: Translation = {
|
|||||||
RESET: 'Nullstill',
|
RESET: 'Nullstill',
|
||||||
APPLY_CHANGES: 'Utfør endringer({0})',
|
APPLY_CHANGES: 'Utfør endringer({0})',
|
||||||
UPDATE: 'Oppdater',
|
UPDATE: 'Oppdater',
|
||||||
EXECUTE: 'Execute', // TODO translate
|
EXECUTE: 'Utfør',
|
||||||
REMOVE: 'Fjern',
|
REMOVE: 'Fjern',
|
||||||
PROBLEM_UPDATING: 'Problem med oppdatering',
|
PROBLEM_UPDATING: 'Problem med oppdatering',
|
||||||
PROBLEM_LOADING: 'Problem med opplasting',
|
PROBLEM_LOADING: 'Problem med opplasting',
|
||||||
@@ -72,7 +72,7 @@ const no: Translation = {
|
|||||||
TX_ISSUES: 'Tx problemer - prøv en annen Tx Modus',
|
TX_ISSUES: 'Tx problemer - prøv en annen Tx Modus',
|
||||||
DISCONNECTED: 'Frakoblet',
|
DISCONNECTED: 'Frakoblet',
|
||||||
EMS_SCAN: 'Er du sikker på du vil starte full søking av EMS bussen?',
|
EMS_SCAN: 'Er du sikker på du vil starte full søking av EMS bussen?',
|
||||||
DATA_TRAFFIC: 'Data Traffic', // TODO translate
|
DATA_TRAFFIC: 'Data trafikk',
|
||||||
EMS_DEVICE: 'EMS Enhet',
|
EMS_DEVICE: 'EMS Enhet',
|
||||||
SUCCESS: 'VELLYKKET',
|
SUCCESS: 'VELLYKKET',
|
||||||
FAIL: 'MISLYKKET',
|
FAIL: 'MISLYKKET',
|
||||||
@@ -115,9 +115,9 @@ const no: Translation = {
|
|||||||
READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)',
|
READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)',
|
||||||
UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet',
|
UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet',
|
||||||
REMOTE_TIMEOUT: 'Remote timeout',
|
REMOTE_TIMEOUT: 'Remote timeout',
|
||||||
REMOTE_TIMEOUT_EN: 'Disable remote control on missing room temperature', // TODO translate
|
REMOTE_TIMEOUT_EN: 'Deaktiver fjernstyring på manglende romtemperatur',
|
||||||
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
|
HEATINGOFF: 'Start kjele med tvingt oppvarming av',
|
||||||
MIN_DURATION: 'Wait time',
|
MIN_DURATION: 'Ventetid',
|
||||||
ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer',
|
ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer',
|
||||||
ENABLE_SHOWER_ALERT: 'Aktiver Dusj-varsling',
|
ENABLE_SHOWER_ALERT: 'Aktiver Dusj-varsling',
|
||||||
TRIGGER_TIME: 'Aktiveringstid',
|
TRIGGER_TIME: 'Aktiveringstid',
|
||||||
@@ -174,9 +174,9 @@ const no: Translation = {
|
|||||||
FACTORY_RESET: 'Sett tilbake til fabrikkinstilling',
|
FACTORY_RESET: 'Sett tilbake til fabrikkinstilling',
|
||||||
SYSTEM_FACTORY_TEXT: 'Enhet har blitt satt tilbake til fabrikkinstilling og vil restarte',
|
SYSTEM_FACTORY_TEXT: 'Enhet har blitt satt tilbake til fabrikkinstilling og vil restarte',
|
||||||
SYSTEM_FACTORY_TEXT_DIALOG: 'Er du sikker på at du vil resette enheten til fabrikkinstillinger?',
|
SYSTEM_FACTORY_TEXT_DIALOG: 'Er du sikker på at du vil resette enheten til fabrikkinstillinger?',
|
||||||
AVAILABLE_VERSION: 'Latest Available Versions', // TODO translate
|
AVAILABLE_VERSION: 'Tilgjengelige versjoner',
|
||||||
STABLE: 'Stable', // TODO translate
|
STABLE: 'Stabil',
|
||||||
DEVELOPMENT: 'Development',
|
DEVELOPMENT: 'Utvikling',
|
||||||
UPTIME: 'System Oppetid',
|
UPTIME: 'System Oppetid',
|
||||||
FREE_MEMORY: 'Ledig Memory',
|
FREE_MEMORY: 'Ledig Memory',
|
||||||
PSRAM: 'PSRAM (Størrelse / Ledig)',
|
PSRAM: 'PSRAM (Størrelse / Ledig)',
|
||||||
@@ -185,9 +185,9 @@ const no: Translation = {
|
|||||||
FILESYSTEM: 'File System (Brukt / Ledig)',
|
FILESYSTEM: 'File System (Brukt / Ledig)',
|
||||||
BUFFER_SIZE: 'Max Buffer Størrelse',
|
BUFFER_SIZE: 'Max Buffer Størrelse',
|
||||||
COMPACT: 'Komprimere',
|
COMPACT: 'Komprimere',
|
||||||
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
|
DOWNLOAD_SETTINGS_TEXT: 'Lag en sikkerhetskopi av dine konfigurasjon og innstillinger',
|
||||||
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)', // TODO translate
|
UPLOAD_TEXT: 'Last opp en ny firmware fil (.bin) eller en sikkerhetskopi fil (.json)',
|
||||||
UPLOAD_DROP_TEXT: 'Slipp fil eller klikk her',
|
UPLOAD_DROP_TEXT: 'Dropp en firmware fil (.bin) eller klikk her',
|
||||||
ERROR: 'Ukjent feil, prøv igjen',
|
ERROR: 'Ukjent feil, prøv igjen',
|
||||||
TIME_SET: 'Still in tid',
|
TIME_SET: 'Still in tid',
|
||||||
MANAGE_USERS: 'Administrer Brukere',
|
MANAGE_USERS: 'Administrer Brukere',
|
||||||
@@ -223,7 +223,7 @@ const no: Translation = {
|
|||||||
MQTT_INT_THERMOSTATS: 'Termostat',
|
MQTT_INT_THERMOSTATS: 'Termostat',
|
||||||
MQTT_INT_SOLAR: 'Solpaneler',
|
MQTT_INT_SOLAR: 'Solpaneler',
|
||||||
MQTT_INT_MIXER: 'Blandeventil',
|
MQTT_INT_MIXER: 'Blandeventil',
|
||||||
MQTT_INT_WATER: 'Water Modules', // TODO translate
|
MQTT_INT_WATER: 'Vannmoduler',
|
||||||
MQTT_QUEUE: 'MQTT Queue',
|
MQTT_QUEUE: 'MQTT Queue',
|
||||||
DEFAULT: 'Standard',
|
DEFAULT: 'Standard',
|
||||||
MQTT_ENTITY_FORMAT: 'Enhets ID format',
|
MQTT_ENTITY_FORMAT: 'Enhets ID format',
|
||||||
@@ -260,7 +260,7 @@ const no: Translation = {
|
|||||||
NETWORK_SCANNER: 'Nettverk Scanner',
|
NETWORK_SCANNER: 'Nettverk Scanner',
|
||||||
NETWORK_NO_WIFI: 'Ingen trådløse nett funnet',
|
NETWORK_NO_WIFI: 'Ingen trådløse nett funnet',
|
||||||
NETWORK_BLANK_SSID: 'la feltet være blankt for å deaktivisere trådløst nettverk',
|
NETWORK_BLANK_SSID: 'la feltet være blankt for å deaktivisere trådløst nettverk',
|
||||||
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
|
NETWORK_BLANK_BSSID: 'la feltet være blankt for å bruke kun SSID',
|
||||||
TX_POWER: 'Tx Effekt',
|
TX_POWER: 'Tx Effekt',
|
||||||
HOSTNAME: 'Hostname',
|
HOSTNAME: 'Hostname',
|
||||||
NETWORK_DISABLE_SLEEP: 'Hindre at trådløst nettverk går i Sleep Mode',
|
NETWORK_DISABLE_SLEEP: 'Hindre at trådløst nettverk går i Sleep Mode',
|
||||||
@@ -297,53 +297,61 @@ const no: Translation = {
|
|||||||
SCHEDULE_TIMER_1: 'ved oppstart',
|
SCHEDULE_TIMER_1: 'ved oppstart',
|
||||||
SCHEDULE_TIMER_2: 'hvert minutt',
|
SCHEDULE_TIMER_2: 'hvert minutt',
|
||||||
SCHEDULE_TIMER_3: 'hver time',
|
SCHEDULE_TIMER_3: 'hver time',
|
||||||
CUSTOM_ENTITIES: 'Custom Entities', // TODO translate
|
CUSTOM_ENTITIES: 'Personlige entiteter',
|
||||||
ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', // TODO translate
|
ENTITIES_HELP_1: 'Hent personlige entiteter fra EMS bussen',
|
||||||
ENTITIES_UPDATED: 'Entities Updated', // TODO translate
|
ENTITIES_UPDATED: 'Entiteter oppdatert',
|
||||||
WRITEABLE: 'Writeable', // TODO translate
|
WRITEABLE: 'Skrivbar',
|
||||||
SHOWING: 'Showing', // TODO translate
|
SHOWING: 'Viser',
|
||||||
SEARCH: 'Search', // TODO translate
|
SEARCH: 'Søk',
|
||||||
CERT: 'TLS root certificate (leave blank for insecure)', // TODO translate
|
CERT: 'TLS rot sertifikat (la feltet stå blankt for usikkert)',
|
||||||
ENABLE_TLS: 'Aktiviser TLS',
|
ENABLE_TLS: 'Aktiviser TLS',
|
||||||
ON: 'On', // TODO translate
|
ON: 'På',
|
||||||
OFF: 'Off', // TODO translate
|
OFF: 'Av',
|
||||||
POLARITY: 'Polarity', // TODO translate
|
POLARITY: 'Polarity',
|
||||||
ACTIVEHIGH: 'Active High', // TODO translate
|
ACTIVEHIGH: 'Active High',
|
||||||
ACTIVELOW: 'Active Low', // TODO translate
|
ACTIVELOW: 'Active Low',
|
||||||
UNCHANGED: 'Unchanged', // TODO translate
|
UNCHANGED: 'Unchanged',
|
||||||
ALWAYS: 'Always', // TODO translate
|
ALWAYS: 'Always',
|
||||||
ACTIVITY: 'Activity', // TODO translate
|
ACTIVITY: 'Aktivitet',
|
||||||
CONFIGURE: 'Configure {0}', // TODO translate
|
CONFIGURE: 'Konfigurer {0}',
|
||||||
SYSTEM_MEMORY: 'System Memory', // TODO translate
|
SYSTEM_MEMORY: 'System Memory',
|
||||||
APPLICATION_SETTINGS_1: 'Modify EMS-ESP Application Settings', // TODO translate
|
APPLICATION_SETTINGS_1: 'Modify EMS-ESP Application Settings',
|
||||||
SECURITY_1: 'Add or remove users', // TODO translate
|
SECURITY_1: 'Add or remove users',
|
||||||
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate
|
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware',
|
||||||
MODULES: 'Module', // TODO translate
|
MODULES: 'Modul',
|
||||||
MODULES_1: 'Aktiver eller deaktiver eksterne moduler',
|
MODULES_1: 'Aktiver eller deaktiver eksterne moduler',
|
||||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
MODULES_UPDATED: 'Moduler oppdatert',
|
||||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
MODULES_DESCRIPTION: 'Klikk på modulen for å aktivere eller deaktivere EMS-ESP biblioteksmoduler',
|
||||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
MODULES_NONE: 'Ingen eksterne moduler funnet',
|
||||||
RENAME: 'Rename', // TODO translate
|
RENAME: 'Gi nytt navn',
|
||||||
ENABLE_MODBUS: 'Aktiver Modbus',
|
ENABLE_MODBUS: 'Aktiver Modbus',
|
||||||
VIEW_LOG: 'View log to diagnose issues', // TODO translate
|
VIEW_LOG: 'Se logg for å diagnostisere problemer',
|
||||||
UPLOAD_DRAG: 'drag and drop a file here or click to select one', // TODO translate
|
UPLOAD_DRAG: 'dra og slippe en fil her eller klikk for å velge en',
|
||||||
SERVICES: 'Services', // TODO translate
|
SERVICES: 'Tjenester',
|
||||||
ALLVALUES: 'All Values', // TODO translate
|
ALLVALUES: 'Alle verdier',
|
||||||
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
|
SPECIAL_FUNCTIONS: 'Spesielle funksjoner',
|
||||||
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
|
WAIT_FIRMWARE: 'Firmware er i opplasting og installasjon',
|
||||||
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
|
INSTALL_VERSION: 'Dette vil {0} versjon {1}. Er du sikker?',
|
||||||
SWITCH_DEV: 'switch to the development version', // TODO translate
|
UPDATE_AVAILABLE: 'oppdatering tilgjengelig',
|
||||||
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
|
LATEST_VERSION: 'Du bruker den nyeste {0} firmware versjonen',
|
||||||
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
|
PLEASE_WAIT: 'Vennligst vent',
|
||||||
PLEASE_WAIT: 'Please wait', // TODO translate
|
RESTARTING_PRE: 'Initialiserer',
|
||||||
RESTARTING_PRE: 'Initializing', // TODO translate
|
RESTARTING_POST: 'Forbereder',
|
||||||
RESTARTING_POST: 'Preparing', // TODO translate
|
AUTO_SCROLL: 'Automatisk rulling',
|
||||||
AUTO_SCROLL: 'Auto Scroll', // TODO translate
|
DASHBOARD: 'Dashboard',
|
||||||
DASHBOARD: 'Dashboard', // TODO translate
|
DEVELOPER_MODE: 'Utvikler modus',
|
||||||
NO_DATA: 'No data available', // TODO translate
|
BYTES: 'Bytes',
|
||||||
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
|
BITMASK: 'Bitmask',
|
||||||
DEVELOPER_MODE: 'Developer Mode', // TODO translate
|
DUPLICATE: 'Duplikat',
|
||||||
UPGRADE: 'Upgrade' // TODO translate
|
DASHBOARD_1: 'Alle EMS enheter som er aktive og merket som favoritt, pluss alle personlige enheter, planlegg og eksterne sensor data er vist nedenfor.',
|
||||||
|
NO_DATA_1: 'Ingen favoritte EMS enheter funnet enda. Bruk',
|
||||||
|
NO_DATA_2: 'modul for å markere dem.',
|
||||||
|
NO_DATA_3: 'For å se alle tilgjengelige enheter, gå til',
|
||||||
|
THIS_VERSION: 'Denne versjonen',
|
||||||
|
PLATFORM: 'Plattform',
|
||||||
|
RELEASE_TYPE: 'Utgivelses type',
|
||||||
|
INTERNET_CONNECTION_REQUIRED: 'Internettilkobling kreves for automatisk versjonskontroll og oppgradering',
|
||||||
|
SWITCH_RELEASE_TYPE: 'Bytt til {0} utgivelse'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default no;
|
export default no;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ const pl: BaseTranslation = {
|
|||||||
TX_ISSUES: 'problem z zapisem na magistralę EMS, spróbuj wybrać inny "Tryb transmisji (Tx)"',
|
TX_ISSUES: 'problem z zapisem na magistralę EMS, spróbuj wybrać inny "Tryb transmisji (Tx)"',
|
||||||
DISCONNECTED: 'brak połączenia',
|
DISCONNECTED: 'brak połączenia',
|
||||||
EMS_SCAN: 'Czy na pewno wykonać pełne skanowanie magistrali EMS?',
|
EMS_SCAN: 'Czy na pewno wykonać pełne skanowanie magistrali EMS?',
|
||||||
DATA_TRAFFIC: 'Data Traffic', // TODO translate
|
DATA_TRAFFIC: 'Ruch Danych',
|
||||||
EMS_DEVICE: 'Urządzenie EMS',
|
EMS_DEVICE: 'Urządzenie EMS',
|
||||||
SUCCESS: 'Udane',
|
SUCCESS: 'Udane',
|
||||||
FAIL: 'Nieudane',
|
FAIL: 'Nieudane',
|
||||||
@@ -115,7 +115,7 @@ const pl: BaseTranslation = {
|
|||||||
READONLY: 'Tryb pracy "tylko do odczytu" (blokuje wszystkie komendy zapisu na magistralę EMS)',
|
READONLY: 'Tryb pracy "tylko do odczytu" (blokuje wszystkie komendy zapisu na magistralę EMS)',
|
||||||
UNDERCLOCK_CPU: 'Obniż taktowanie CPU',
|
UNDERCLOCK_CPU: 'Obniż taktowanie CPU',
|
||||||
REMOTE_TIMEOUT: 'Remote timeout',
|
REMOTE_TIMEOUT: 'Remote timeout',
|
||||||
REMOTE_TIMEOUT_EN: 'Disable remote control on missing room temperature', // TODO translate
|
REMOTE_TIMEOUT_EN: 'Wyłącz kontrolę zdalną przy braku temperatury pomieszczenia',
|
||||||
HEATINGOFF: 'Uruchom kocioł z wymuszonym wyłączonym grzaniem',
|
HEATINGOFF: 'Uruchom kocioł z wymuszonym wyłączonym grzaniem',
|
||||||
MIN_DURATION: 'Wait time',
|
MIN_DURATION: 'Wait time',
|
||||||
ENABLE_SHOWER_TIMER: 'Aktywuj minutnik prysznica',
|
ENABLE_SHOWER_TIMER: 'Aktywuj minutnik prysznica',
|
||||||
@@ -174,9 +174,9 @@ const pl: BaseTranslation = {
|
|||||||
FACTORY_RESET: 'Ustawienia fabryczne',
|
FACTORY_RESET: 'Ustawienia fabryczne',
|
||||||
SYSTEM_FACTORY_TEXT: 'Interfejs EMS-ESP został przywrócony do ustawień fabrycznych i zostanie teraz ponownie uruchomiony.',
|
SYSTEM_FACTORY_TEXT: 'Interfejs EMS-ESP został przywrócony do ustawień fabrycznych i zostanie teraz ponownie uruchomiony.',
|
||||||
SYSTEM_FACTORY_TEXT_DIALOG: 'Na pewno chcesz przywrócić ustawienia fabryczne interfejsu EMS-ESP?',
|
SYSTEM_FACTORY_TEXT_DIALOG: 'Na pewno chcesz przywrócić ustawienia fabryczne interfejsu EMS-ESP?',
|
||||||
AVAILABLE_VERSION: 'Latest Available Versions', // TODO translate
|
AVAILABLE_VERSION: 'Najnowsze dostępne wersje',
|
||||||
STABLE: 'Stable', // TODO translate
|
STABLE: 'Stabilna',
|
||||||
DEVELOPMENT: 'Testowe',
|
DEVELOPMENT: 'Testowa',
|
||||||
UPTIME: 'Czas działania systemu',
|
UPTIME: 'Czas działania systemu',
|
||||||
FREE_MEMORY: 'Wolne Memory',
|
FREE_MEMORY: 'Wolne Memory',
|
||||||
PSRAM: 'PSRAM (rozmiar / wolne)',
|
PSRAM: 'PSRAM (rozmiar / wolne)',
|
||||||
@@ -185,9 +185,9 @@ const pl: BaseTranslation = {
|
|||||||
FILESYSTEM: 'System plików (wykorzystane / wolne)',
|
FILESYSTEM: 'System plików (wykorzystane / wolne)',
|
||||||
BUFFER_SIZE: 'Maksymalna pojemność bufora (ilość wpisów)',
|
BUFFER_SIZE: 'Maksymalna pojemność bufora (ilość wpisów)',
|
||||||
COMPACT: 'Kompaktowy',
|
COMPACT: 'Kompaktowy',
|
||||||
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
|
DOWNLOAD_SETTINGS_TEXT: 'Utwórz kopię swoich ustawień i konfiguracji',
|
||||||
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)', // TODO translate
|
UPLOAD_TEXT: 'Wgraj nowy plik firmware (.bin) lub kopię ustawień (.json)',
|
||||||
UPLOAD_DROP_TEXT: 'Przeciągnij tutaj plik lub kliknij',
|
UPLOAD_DROP_TEXT: 'Upuść plik firmware .bin lub kliknij tutaj',
|
||||||
ERROR: 'Nieoczekiwany błąd, spróbuj ponownie!',
|
ERROR: 'Nieoczekiwany błąd, spróbuj ponownie!',
|
||||||
TIME_SET: 'Zegar został ustawiony.',
|
TIME_SET: 'Zegar został ustawiony.',
|
||||||
MANAGE_USERS: 'Zarządzanie użytkownikami',
|
MANAGE_USERS: 'Zarządzanie użytkownikami',
|
||||||
@@ -318,32 +318,40 @@ const pl: BaseTranslation = {
|
|||||||
APPLICATION_SETTINGS_1: 'Modyfikacja ustawień aplikacji EMS-ESP',
|
APPLICATION_SETTINGS_1: 'Modyfikacja ustawień aplikacji EMS-ESP',
|
||||||
SECURITY_1: 'Dodawanie i usuwanie użytkowników',
|
SECURITY_1: 'Dodawanie i usuwanie użytkowników',
|
||||||
DOWNLOAD_UPLOAD_1: 'Pobieranie/wysyłanie ustawień i firmware',
|
DOWNLOAD_UPLOAD_1: 'Pobieranie/wysyłanie ustawień i firmware',
|
||||||
MODULES: 'Module', // TODO translate
|
MODULES: 'Moduł',
|
||||||
MODULES_1: 'Aktywuj lub dezaktywuj moduły zewnętrzne',
|
MODULES_1: 'Aktywuj lub dezaktywuj moduły zewnętrzne',
|
||||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
MODULES_UPDATED: 'Zaktualizowano moduły',
|
||||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
MODULES_DESCRIPTION: 'Kliknij na moduł aby aktywować lub dezaktywować bibliotekę modułów EMS-ESP',
|
||||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
MODULES_NONE: 'Brak wykrytych modułów zewnętrznych',
|
||||||
RENAME: 'Rename', // TODO translate
|
RENAME: 'Zmień nazwę',
|
||||||
ENABLE_MODBUS: 'Aktywuj Modbus',
|
ENABLE_MODBUS: 'Aktywuj Modbus',
|
||||||
VIEW_LOG: 'View log to diagnose issues', // TODO translate
|
VIEW_LOG: 'Zdiagnozuj problemy',
|
||||||
UPLOAD_DRAG: 'drag and drop a file here or click to select one', // TODO translate
|
UPLOAD_DRAG: 'przeciągnij i upuść plik lub kliknij tutaj',
|
||||||
SERVICES: 'Services', // TODO translate
|
SERVICES: 'Usługi',
|
||||||
ALLVALUES: 'All Values', // TODO translate
|
ALLVALUES: 'Wszystkie wartości',
|
||||||
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
|
SPECIAL_FUNCTIONS: 'Specjalne funkcje',
|
||||||
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
|
WAIT_FIRMWARE: 'Firma jest wysyłana i instaluje się',
|
||||||
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
|
INSTALL_VERSION: 'To zainstaluje wersję {1} {0}. Jesteś pewny?',
|
||||||
SWITCH_DEV: 'switch to the development version', // TODO translate
|
UPDATE_AVAILABLE: 'aktualizacja dostępna',
|
||||||
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
|
LATEST_VERSION: 'Jesteś używając najnowszej wersji firmware {0}',
|
||||||
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
|
PLEASE_WAIT: 'Proszę czekać',
|
||||||
PLEASE_WAIT: 'Please wait', // TODO translate
|
RESTARTING_PRE: 'Inicjalizacja',
|
||||||
RESTARTING_PRE: 'Initializing', // TODO translate
|
RESTARTING_POST: 'Przygotowanie',
|
||||||
RESTARTING_POST: 'Preparing', // TODO translate
|
AUTO_SCROLL: 'Auto Scroll',
|
||||||
AUTO_SCROLL: 'Auto Scroll', // TODO translate
|
DASHBOARD: 'Pulpit',
|
||||||
DASHBOARD: 'Dashboard', // TODO translate
|
DEVELOPER_MODE: 'Tryb programisty',
|
||||||
NO_DATA: 'No data available', // TODO translate
|
BYTES: 'Bajty',
|
||||||
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
|
BITMASK: 'Bit Mask',
|
||||||
DEVELOPER_MODE: 'Developer Mode', // TODO translate
|
DUPLICATE: 'Duplicate',
|
||||||
UPGRADE: 'Upgrade' // TODO translate
|
DASHBOARD_1: 'All EMS entities that are active and marked as Favorite, plus all Custom Entities, Schedules and external Sensors data are displayed below.',
|
||||||
|
NO_DATA_1: 'Brak ulubionych encji EMS. Użyj',
|
||||||
|
NO_DATA_2: 'moduł do ich oznaczenia.',
|
||||||
|
NO_DATA_3: 'Aby zobaczyć wszystkie dostępne encje przejdź do',
|
||||||
|
THIS_VERSION: 'Ta wersja',
|
||||||
|
PLATFORM: 'Platforma',
|
||||||
|
RELEASE_TYPE: 'Typ wydania',
|
||||||
|
INTERNET_CONNECTION_REQUIRED: 'Połączenie internetowe jest wymagane do automatycznej kontroli wersji i aktualizacji',
|
||||||
|
SWITCH_RELEASE_TYPE: 'Zmień na {0} wydanie'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default pl;
|
export default pl;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const sk: Translation = {
|
|||||||
OFFSET: 'Ofset',
|
OFFSET: 'Ofset',
|
||||||
FACTOR: 'Faktor',
|
FACTOR: 'Faktor',
|
||||||
FREQ: 'Frekvencia',
|
FREQ: 'Frekvencia',
|
||||||
DUTY_CYCLE: 'Duty Cycle',
|
DUTY_CYCLE: 'Pracovný cyklus',
|
||||||
UNIT: 'UoM',
|
UNIT: 'UoM',
|
||||||
STARTVALUE: 'Počiatočná hodnota',
|
STARTVALUE: 'Počiatočná hodnota',
|
||||||
WARN_GPIO: 'Upozornenie: Buďte opatrní pri priraďovaní GPIO!',
|
WARN_GPIO: 'Upozornenie: Buďte opatrní pri priraďovaní GPIO!',
|
||||||
@@ -75,7 +75,7 @@ const sk: Translation = {
|
|||||||
DATA_TRAFFIC: 'Dátová prevádzka',
|
DATA_TRAFFIC: 'Dátová prevádzka',
|
||||||
EMS_DEVICE: 'EMS zariadenie',
|
EMS_DEVICE: 'EMS zariadenie',
|
||||||
SUCCESS: 'ÚSPEŠNÉ',
|
SUCCESS: 'ÚSPEŠNÉ',
|
||||||
FAIL: 'ZLÝHANIE',
|
FAIL: 'ZLYHANIE',
|
||||||
QUALITY: 'KVALITA',
|
QUALITY: 'KVALITA',
|
||||||
SCAN: 'Scan',
|
SCAN: 'Scan',
|
||||||
STATUS_NAMES: [
|
STATUS_NAMES: [
|
||||||
@@ -114,10 +114,10 @@ const sk: Translation = {
|
|||||||
BYPASS_TOKEN: 'Vynechajte autorizáciu prístupového tokenu pri volaniach API',
|
BYPASS_TOKEN: 'Vynechajte autorizáciu prístupového tokenu pri volaniach API',
|
||||||
READONLY: 'Povoliť režim len na čítanie (blokuje všetky odchádzajúce príkazy EMS Tx Write)',
|
READONLY: 'Povoliť režim len na čítanie (blokuje všetky odchádzajúce príkazy EMS Tx Write)',
|
||||||
UNDERCLOCK_CPU: 'Podtaktovanie rýchlosti procesora',
|
UNDERCLOCK_CPU: 'Podtaktovanie rýchlosti procesora',
|
||||||
REMOTE_TIMEOUT: 'Remote timeout',
|
REMOTE_TIMEOUT: 'Vzdialený časový limit',
|
||||||
REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
|
REMOTE_TIMEOUT_EN: 'Deaktivujte diaľkové ovládanie pri chýbajúcej teplote v miestnosti',
|
||||||
HEATINGOFF: 'Spustiť kotol s vynúteným vykurovaním',
|
HEATINGOFF: 'Spustiť kotol s vynúteným vykurovaním',
|
||||||
MIN_DURATION: 'Wait time',
|
MIN_DURATION: 'Čakacia doba',
|
||||||
ENABLE_SHOWER_TIMER: 'Povoliť časovač sprchovania',
|
ENABLE_SHOWER_TIMER: 'Povoliť časovač sprchovania',
|
||||||
ENABLE_SHOWER_ALERT: 'Povoliť upozornenie na sprchu',
|
ENABLE_SHOWER_ALERT: 'Povoliť upozornenie na sprchu',
|
||||||
TRIGGER_TIME: 'Čas spustenia',
|
TRIGGER_TIME: 'Čas spustenia',
|
||||||
@@ -127,7 +127,7 @@ const sk: Translation = {
|
|||||||
BOOLEAN_FORMAT_API: 'Boolean formát API/MQTT',
|
BOOLEAN_FORMAT_API: 'Boolean formát API/MQTT',
|
||||||
ENUM_FORMAT: 'Enum formát API/MQTT',
|
ENUM_FORMAT: 'Enum formát API/MQTT',
|
||||||
INDEX: 'Index',
|
INDEX: 'Index',
|
||||||
ENABLE_PARASITE: 'Povoliť 1-wire parazité napájanie DS18B20',
|
ENABLE_PARASITE: 'Povoliť 1-wire parazitné napájanie DS18B20',
|
||||||
LOGGING: 'Logovanie',
|
LOGGING: 'Logovanie',
|
||||||
LOG_HEX: 'Záznam telegramov EMS v hexadecimálnej sústave',
|
LOG_HEX: 'Záznam telegramov EMS v hexadecimálnej sústave',
|
||||||
ENABLE_SYSLOG: 'Povoliť Syslog',
|
ENABLE_SYSLOG: 'Povoliť Syslog',
|
||||||
@@ -155,7 +155,7 @@ const sk: Translation = {
|
|||||||
NAME: 'Názov',
|
NAME: 'Názov',
|
||||||
CUSTOMIZATIONS_RESET: 'Naozaj chcete odstrániť všetky prispôsobenia vrátane vlastných nastavení snímačov teploty a analógových snímačov?',
|
CUSTOMIZATIONS_RESET: 'Naozaj chcete odstrániť všetky prispôsobenia vrátane vlastných nastavení snímačov teploty a analógových snímačov?',
|
||||||
SUPPORT_INFORMATION: 'Informácie pre podporu',
|
SUPPORT_INFORMATION: 'Informácie pre podporu',
|
||||||
HELP_INFORMATION_1: 'Navštívte online wiki, kde nájdete pokyny na konfiguráciu EMS-ESP',
|
HELP_INFORMATION_1: 'Navštívte online wiki, kde nájdete pokyny na konfiguráciu EMS-ESP',
|
||||||
HELP_INFORMATION_2: 'Pre živý komunitný chat sa pripojte na náš Discord server',
|
HELP_INFORMATION_2: 'Pre živý komunitný chat sa pripojte na náš Discord server',
|
||||||
HELP_INFORMATION_3: 'Ak chcete požiadať o funkciu alebo nahlásiť chybu',
|
HELP_INFORMATION_3: 'Ak chcete požiadať o funkciu alebo nahlásiť chybu',
|
||||||
HELP_INFORMATION_4: 'nezabudnite si stiahnuť a pripojiť informácie o vašom systéme, aby ste mohli rýchlejšie reagovať pri nahlasovaní problému',
|
HELP_INFORMATION_4: 'nezabudnite si stiahnuť a pripojiť informácie o vašom systéme, aby ste mohli rýchlejšie reagovať pri nahlasovaní problému',
|
||||||
@@ -174,20 +174,20 @@ const sk: Translation = {
|
|||||||
FACTORY_RESET: 'Továrenské nastavenia',
|
FACTORY_RESET: 'Továrenské nastavenia',
|
||||||
SYSTEM_FACTORY_TEXT: 'Zariadenie bolo obnovené z výroby a teraz sa reštartuje',
|
SYSTEM_FACTORY_TEXT: 'Zariadenie bolo obnovené z výroby a teraz sa reštartuje',
|
||||||
SYSTEM_FACTORY_TEXT_DIALOG: 'Naozaj chcete resetovať EMS-ESP na predvolené výrobné nastavenia?',
|
SYSTEM_FACTORY_TEXT_DIALOG: 'Naozaj chcete resetovať EMS-ESP na predvolené výrobné nastavenia?',
|
||||||
AVAILABLE_VERSION: 'Latest Available Versions', // TODO translate
|
AVAILABLE_VERSION: 'Najnovšie dostupné verzie',
|
||||||
STABLE: 'Stabilná',
|
STABLE: 'Stabilná',
|
||||||
DEVELOPMENT: 'Vývojárska',
|
DEVELOPMENT: 'Vývojárska',
|
||||||
UPTIME: 'Beh systému',
|
UPTIME: 'Beh systému',
|
||||||
FREE_MEMORY: 'Voľné Memory',
|
FREE_MEMORY: 'Voľná pamäť',
|
||||||
PSRAM: 'PSRAM (Veľkosť / Voľné)',
|
PSRAM: 'PSRAM (Veľkosť / Voľné)',
|
||||||
FLASH: 'Flash chip (Veľkosť , Rýchlosť)',
|
FLASH: 'Flash chip (Veľkosť , Rýchlosť)',
|
||||||
APPSIZE: 'Applikácia (Oddiel: Použité / Voľné)',
|
APPSIZE: 'Aplikácia (Oddiel: Použité / Voľné)',
|
||||||
FILESYSTEM: 'Súborový systém (Použité / Voľné)',
|
FILESYSTEM: 'Súborový systém (Použité / Voľné)',
|
||||||
BUFFER_SIZE: 'Buffer-max.veľkosť',
|
BUFFER_SIZE: 'Buffer-max. veľkosť',
|
||||||
COMPACT: 'Kompaktné',
|
COMPACT: 'Kompaktné',
|
||||||
DOWNLOAD_SETTINGS_TEXT: 'Vytvorte zálohu svojej konfigurácie a nastavení',
|
DOWNLOAD_SETTINGS_TEXT: 'Vytvorte zálohu svojej konfigurácie a nastavení',
|
||||||
UPLOAD_TEXT: 'Nahrajte nový súbor firmvéru (.bin) alebo súbor zálohy (.json)',
|
UPLOAD_TEXT: 'Nahrajte nový súbor firmvéru (.bin) alebo súbor zálohy (.json)',
|
||||||
UPLOAD_DROP_TEXT: 'Potiahnúť a pripnúť súbor alebo kliknúť sem',
|
UPLOAD_DROP_TEXT: 'Presuňte súbor .bin firmvéru alebo kliknite sem',
|
||||||
ERROR: 'Neočakávaná chyba, prosím skúste to znova',
|
ERROR: 'Neočakávaná chyba, prosím skúste to znova',
|
||||||
TIME_SET: 'Nastavený čas',
|
TIME_SET: 'Nastavený čas',
|
||||||
MANAGE_USERS: 'Správa používateľov',
|
MANAGE_USERS: 'Správa používateľov',
|
||||||
@@ -313,17 +313,17 @@ const sk: Translation = {
|
|||||||
UNCHANGED: 'Nezmenené',
|
UNCHANGED: 'Nezmenené',
|
||||||
ALWAYS: 'Vždy',
|
ALWAYS: 'Vždy',
|
||||||
ACTIVITY: 'Aktivita',
|
ACTIVITY: 'Aktivita',
|
||||||
CONFIGURE: 'Konfiguracia {0}',
|
CONFIGURE: 'Konfigurácia {0}',
|
||||||
SYSTEM_MEMORY: 'Systémová pamäť',
|
SYSTEM_MEMORY: 'Systémová pamäť',
|
||||||
APPLICATION_SETTINGS_1: 'Zmeniť nastavenia aplikácie EMS-ESP',
|
APPLICATION_SETTINGS_1: 'Zmeniť nastavenia aplikácie EMS-ESP',
|
||||||
SECURITY_1: 'Pridať, alebo odstrániť použivateľov',
|
SECURITY_1: 'Pridať, alebo odstrániť používateľov',
|
||||||
DOWNLOAD_UPLOAD_1: 'Stiahnúť a nahrať nastavenia a firmware',
|
DOWNLOAD_UPLOAD_1: 'Stiahnuť a nahrať nastavenia a firmware',
|
||||||
MODULES: 'Moduly',
|
MODULES: 'Moduly',
|
||||||
MODULES_1: 'Aktivujte alebo deaktivujte externé moduly',
|
MODULES_1: 'Aktivujte alebo deaktivujte externé moduly',
|
||||||
MODULES_UPDATED: 'Aktualizované moduly',
|
MODULES_UPDATED: 'Aktualizované moduly',
|
||||||
MODULES_DESCRIPTION: 'Kliknutím na modul aktivujete alebo deaktivujete moduly knižnice EMS-ESP',
|
MODULES_DESCRIPTION: 'Kliknutím na modul aktivujete alebo deaktivujete moduly knižnice EMS-ESP',
|
||||||
MODULES_NONE: 'Neboli zistené žiadne externé moduly',
|
MODULES_NONE: 'Neboli zistené žiadne externé moduly',
|
||||||
RENAME: 'Premenovať',
|
RENAME: 'Premenovať',
|
||||||
ENABLE_MODBUS: 'Povoliť Modbus',
|
ENABLE_MODBUS: 'Povoliť Modbus',
|
||||||
VIEW_LOG: 'Zobrazte log na diagnostiku problémov',
|
VIEW_LOG: 'Zobrazte log na diagnostiku problémov',
|
||||||
UPLOAD_DRAG: 'presuňte sem súbor alebo ho kliknutím vyberte',
|
UPLOAD_DRAG: 'presuňte sem súbor alebo ho kliknutím vyberte',
|
||||||
@@ -331,19 +331,27 @@ const sk: Translation = {
|
|||||||
ALLVALUES: 'Všetky hodnoty',
|
ALLVALUES: 'Všetky hodnoty',
|
||||||
SPECIAL_FUNCTIONS: 'Špeciálne funkcie',
|
SPECIAL_FUNCTIONS: 'Špeciálne funkcie',
|
||||||
WAIT_FIRMWARE: 'Firmvér sa nahráva a inštaluje',
|
WAIT_FIRMWARE: 'Firmvér sa nahráva a inštaluje',
|
||||||
INSTALL_VERSION: 'Týmto sa inštalovať verzia {0}. Si si istý?',
|
INSTALL_VERSION: 'Týmto sa {0} verzia {1}. Si si istý?',
|
||||||
SWITCH_DEV: 'prejsť na vývojovú verziu',
|
UPDATE_AVAILABLE: 'dostupná aktualizácia',
|
||||||
UPGRADE_AVAILABLE: 'K dispozícii je aktualizácia firmvéru!',
|
LATEST_VERSION: 'Používate poslednú {0} verziu firmvéru',
|
||||||
LATEST_VERSION: 'Používate poslednú verziu firmvéru.',
|
|
||||||
PLEASE_WAIT: 'Čakajte prosím',
|
PLEASE_WAIT: 'Čakajte prosím',
|
||||||
RESTARTING_PRE: 'Prebieha inicializácia',
|
RESTARTING_PRE: 'Prebieha inicializácia',
|
||||||
RESTARTING_POST: 'Príprava',
|
RESTARTING_POST: 'Príprava',
|
||||||
AUTO_SCROLL: 'Automatické rolovanie',
|
AUTO_SCROLL: 'Automatické rolovanie',
|
||||||
DASHBOARD: 'Panel',
|
DASHBOARD: 'Panel',
|
||||||
NO_DATA: 'Nie sú k dispozícii žiadne údaje',
|
DEVELOPER_MODE: 'Režim vývojára',
|
||||||
DASHBOARD_1: 'Prispôsobte si svoj informačný panel tak, že označíte entity EMS ako Obľúbené pomocou modulu Prispôsobenia',
|
BYTES: 'Bytov',
|
||||||
DEVELOPER_MODE: 'Developer Mode', // TODO translate
|
BITMASK: 'Bitová maska',
|
||||||
UPGRADE: 'Upgrade' // TODO translate
|
DUPLICATE: 'Duplicitné',
|
||||||
|
DASHBOARD_1: 'Všetky entity EMS, ktoré sú aktívne a označené ako obľúbené, plus všetky vlastné entity, plány a údaje externých senzorov sú zobrazené nižšie.',
|
||||||
|
NO_DATA_1: 'Nenašli sa žiadne obľúbené entity EMS. Použite',
|
||||||
|
NO_DATA_2: 'modul na ich označenie.',
|
||||||
|
NO_DATA_3: 'Ak chcete zobraziť všetky dostupné entity, prejdite na',
|
||||||
|
THIS_VERSION: 'Táto verzia',
|
||||||
|
PLATFORM: 'Platforma',
|
||||||
|
RELEASE_TYPE: 'Typ vydania',
|
||||||
|
INTERNET_CONNECTION_REQUIRED: 'Internetové pripojenie je potrebné pre automatickú kontrolu a aktualizáciu',
|
||||||
|
SWITCH_RELEASE_TYPE: 'Prepnúť na {0} verziu'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default sk;
|
export default sk;
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ const sv: Translation = {
|
|||||||
RETRY: 'Försök igen',
|
RETRY: 'Försök igen',
|
||||||
LOADING: 'Laddar',
|
LOADING: 'Laddar',
|
||||||
IS_REQUIRED: '{0} Krävs',
|
IS_REQUIRED: '{0} Krävs',
|
||||||
SIGN_IN: 'Logga In',
|
SIGN_IN: 'Logga in',
|
||||||
SIGN_OUT: 'Logga Ut',
|
SIGN_OUT: 'Logga ut',
|
||||||
USERNAME: 'Användarnamn',
|
USERNAME: 'Användarnamn',
|
||||||
PASSWORD: 'Lösenord',
|
PASSWORD: 'Lösenord',
|
||||||
SU_PASSWORD: 'su Lösenord',
|
SU_PASSWORD: 'su Lösenord',
|
||||||
@@ -29,7 +29,7 @@ const sv: Translation = {
|
|||||||
FAVORITES: "Favoriter",
|
FAVORITES: "Favoriter",
|
||||||
DEVICE_DETAILS: 'Enhetsdetaljer',
|
DEVICE_DETAILS: 'Enhetsdetaljer',
|
||||||
ID_OF: '{0}-ID',
|
ID_OF: '{0}-ID',
|
||||||
DEVICE: 'Enhets',
|
DEVICE: 'Enhet',
|
||||||
PRODUCT: 'Produkt',
|
PRODUCT: 'Produkt',
|
||||||
VERSION: 'Version',
|
VERSION: 'Version',
|
||||||
BRAND: 'Fabrikat',
|
BRAND: 'Fabrikat',
|
||||||
@@ -37,28 +37,28 @@ const sv: Translation = {
|
|||||||
VALUE: '{{värde|Värde}}',
|
VALUE: '{{värde|Värde}}',
|
||||||
DEVICES: 'Enheter',
|
DEVICES: 'Enheter',
|
||||||
SENSORS: 'Sensorer',
|
SENSORS: 'Sensorer',
|
||||||
RUN_COMMAND: 'Kör Kommando',
|
RUN_COMMAND: 'Kör kommando',
|
||||||
CHANGE_VALUE: 'Ändra Värde',
|
CHANGE_VALUE: 'Ändra värde',
|
||||||
CANCEL: 'Avbryt',
|
CANCEL: 'Avbryt',
|
||||||
RESET: 'Nollställ',
|
RESET: 'Nollställ',
|
||||||
APPLY_CHANGES: 'Apply Changes ({0})', // TODO translate
|
APPLY_CHANGES: 'Utför ändringar ({0})',
|
||||||
UPDATE: 'Update', // TODO translate
|
UPDATE: 'Uppdatera',
|
||||||
EXECUTE: 'Execute', // TODO translate
|
EXECUTE: 'Utför',
|
||||||
REMOVE: 'Ta bort',
|
REMOVE: 'Ta bort',
|
||||||
PROBLEM_UPDATING: 'Problem vid uppdatering',
|
PROBLEM_UPDATING: 'Problem vid uppdatering',
|
||||||
PROBLEM_LOADING: 'Problem vid hämtning',
|
PROBLEM_LOADING: 'Problem vid hämtning',
|
||||||
ANALOG_SENSOR: 'Analog Sensor',
|
ANALOG_SENSOR: 'analog sensor',
|
||||||
ANALOG_SENSORS: 'Analoga Sensorer',
|
ANALOG_SENSORS: 'Analoga sensorer',
|
||||||
SETTINGS: 'Inställningar',
|
SETTINGS: 'Inställningar',
|
||||||
UPDATED_OF: '{0} Uppdaterad',
|
UPDATED_OF: '{0} Uppdaterad',
|
||||||
UPDATE_OF: '{0} Uppdatera',
|
UPDATE_OF: '{0} Uppdatera',
|
||||||
REMOVED_OF: '{0} Raderad',
|
REMOVED_OF: '{0} Raderad',
|
||||||
DELETION_OF: '{0} Radering',
|
DELETION_OF: '{0} Radering',
|
||||||
OFFSET: 'Kompensering',
|
OFFSET: 'Offset',
|
||||||
FACTOR: 'Faktor',
|
FACTOR: 'Faktor',
|
||||||
FREQ: 'Frekvens',
|
FREQ: 'Frekvens',
|
||||||
DUTY_CYCLE: 'Duty Cycle',
|
DUTY_CYCLE: 'Pulskvot',
|
||||||
UNIT: 'UoM',
|
UNIT: 'Måttenhet',
|
||||||
STARTVALUE: 'Startvärde',
|
STARTVALUE: 'Startvärde',
|
||||||
WARN_GPIO: 'Varning: Var försiktig vid aktivering av GPIO!',
|
WARN_GPIO: 'Varning: Var försiktig vid aktivering av GPIO!',
|
||||||
EDIT: 'Ändra',
|
EDIT: 'Ändra',
|
||||||
@@ -71,9 +71,9 @@ const sv: Translation = {
|
|||||||
CONNECTED: 'Ansluten',
|
CONNECTED: 'Ansluten',
|
||||||
TX_ISSUES: 'Sändfel - Prova ett annat TX-läge',
|
TX_ISSUES: 'Sändfel - Prova ett annat TX-läge',
|
||||||
DISCONNECTED: 'Nedkopplad',
|
DISCONNECTED: 'Nedkopplad',
|
||||||
EMS_SCAN: 'Är du säker att du vill initiera en full genomsökning av EMS-bussen?',
|
EMS_SCAN: 'Är du säker på att du vill starta en full genomsökning av EMS-bussen?',
|
||||||
DATA_TRAFFIC: 'Data Traffic', // TODO translate
|
DATA_TRAFFIC: 'Datatrafik',
|
||||||
EMS_DEVICE: 'EMS Enhet',
|
EMS_DEVICE: 'EMS enhet',
|
||||||
SUCCESS: 'Lyckades',
|
SUCCESS: 'Lyckades',
|
||||||
FAIL: 'Misslyckades',
|
FAIL: 'Misslyckades',
|
||||||
QUALITY: 'Kvalitet',
|
QUALITY: 'Kvalitet',
|
||||||
@@ -92,8 +92,8 @@ const sv: Translation = {
|
|||||||
NUM_SECONDS: '{num} sekund{{er}}',
|
NUM_SECONDS: '{num} sekund{{er}}',
|
||||||
NUM_HOURS: '{num} timmar',
|
NUM_HOURS: '{num} timmar',
|
||||||
NUM_MINUTES: '{num} minut{{er}}',
|
NUM_MINUTES: '{num} minut{{er}}',
|
||||||
APPLICATION: 'Apliká',
|
APPLICATION: 'Applikation',
|
||||||
CUSTOMIZATIONS: 'Anpassningr',
|
CUSTOMIZATIONS: 'Anpassningar',
|
||||||
APPLICATION_RESTARTING: 'EMS-ESP startar om',
|
APPLICATION_RESTARTING: 'EMS-ESP startar om',
|
||||||
BOARD_PROFILE: 'Hårdvarutyp',
|
BOARD_PROFILE: 'Hårdvarutyp',
|
||||||
CUSTOM: 'Anpassa',
|
CUSTOM: 'Anpassa',
|
||||||
@@ -105,34 +105,34 @@ const sv: Translation = {
|
|||||||
TX_MODE: 'EMS Tx-läge',
|
TX_MODE: 'EMS Tx-läge',
|
||||||
HARDWARE: 'Hårdvara',
|
HARDWARE: 'Hårdvara',
|
||||||
EMS_BUS: '{{BUSS|EMS-BUSS}}',
|
EMS_BUS: '{{BUSS|EMS-BUSS}}',
|
||||||
GENERAL_OPTIONS: 'Allmänna Inställningar',
|
GENERAL_OPTIONS: 'Allmänna inställningar',
|
||||||
LANGUAGE_ENTITIES: 'Språk (för entiteter)',
|
LANGUAGE_ENTITIES: 'Språk (för entiteter)',
|
||||||
HIDE_LED: 'Inaktivera LED',
|
HIDE_LED: 'Inaktivera LED',
|
||||||
ENABLE_TELNET: 'Aktivera Telnet',
|
ENABLE_TELNET: 'Aktivera Telnet',
|
||||||
ENABLE_ANALOG: 'Aktivera Analoga Sensorer',
|
ENABLE_ANALOG: 'Aktivera Analoga Sensorer',
|
||||||
CONVERT_FAHRENHEIT: 'Konvertera temperaturer till Fahrenheit',
|
CONVERT_FAHRENHEIT: 'Konvertera temperaturer till Fahrenheit',
|
||||||
BYPASS_TOKEN: 'Inaktivera Token-autensiering för API-anrop',
|
BYPASS_TOKEN: 'Inaktivera Token-autentisiering för API-anrop',
|
||||||
READONLY: 'Aktivera read-only (blockerar alla utgående skrivkommandon mot EMS-bussen)',
|
READONLY: 'Aktivera skrivskydd (blockerar alla utgående skrivkommandon mot EMS-bussen)',
|
||||||
UNDERCLOCK_CPU: 'Nedklocka Processorhastighet',
|
UNDERCLOCK_CPU: 'Nedklocka Processorhastighet',
|
||||||
REMOTE_TIMEOUT: 'Remote timeout',
|
REMOTE_TIMEOUT: 'Remote timeout',
|
||||||
REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
|
REMOTE_TIMEOUT_EN: 'Deaktivera remote vid missad rumstemperatur',
|
||||||
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
|
HEATINGOFF: 'Starta värmepump/panna med forcerad värme avstängd',
|
||||||
MIN_DURATION: 'Wait time',
|
MIN_DURATION: 'Väntetid',
|
||||||
ENABLE_SHOWER_TIMER: 'Aktivera Dusch-timer',
|
ENABLE_SHOWER_TIMER: 'Aktivera Dusch-timer',
|
||||||
ENABLE_SHOWER_ALERT: 'Aktivera Dusch-varning',
|
ENABLE_SHOWER_ALERT: 'Aktivera Dusch-varning',
|
||||||
TRIGGER_TIME: 'Aktiveringstid',
|
TRIGGER_TIME: 'Aktiveringstid',
|
||||||
COLD_SHOT_DURATION: 'Längd på kalldusch',
|
COLD_SHOT_DURATION: 'Längd på kalldusch',
|
||||||
FORMATTING_OPTIONS: 'Formatteringsalternativ',
|
FORMATTING_OPTIONS: 'Formateringsalternativ',
|
||||||
BOOLEAN_FORMAT_DASHBOARD: 'Bool-format Kontrollpanel',
|
BOOLEAN_FORMAT_DASHBOARD: 'Bool-format Kontrollpanel',
|
||||||
BOOLEAN_FORMAT_API: 'Bool-format API/MQTT',
|
BOOLEAN_FORMAT_API: 'Bool-format API/MQTT',
|
||||||
ENUM_FORMAT: 'Enum-format API/MQTT',
|
ENUM_FORMAT: 'Enum-format API/MQTT',
|
||||||
INDEX: 'Index',
|
INDEX: 'Index',
|
||||||
ENABLE_PARASITE: 'Aktivera 1-wire parasitström',
|
ENABLE_PARASITE: 'Aktivera 1-wire parasitström',
|
||||||
LOGGING: 'Loggning',
|
LOGGING: 'Loggning',
|
||||||
LOG_HEX: 'Logga EMS-telegram i hexadecimal',
|
LOG_HEX: 'Logga EMS-telegram i hexadecimalformat',
|
||||||
ENABLE_SYSLOG: 'Aktivera Syslog',
|
ENABLE_SYSLOG: 'Aktivera Syslog',
|
||||||
LOG_LEVEL: 'Loggnivå',
|
LOG_LEVEL: 'Loggnivå',
|
||||||
MARK_INTERVAL: 'Markerings-interval',
|
MARK_INTERVAL: 'Markeringsintervall',
|
||||||
SECONDS: 'sekunder',
|
SECONDS: 'sekunder',
|
||||||
MINUTES: 'minuter',
|
MINUTES: 'minuter',
|
||||||
HOURS: 'timmar',
|
HOURS: 'timmar',
|
||||||
@@ -140,25 +140,25 @@ const sv: Translation = {
|
|||||||
RESTART_TEXT: 'EMS-ESP kräver en omstart för att applicera förändrade systeminställningar',
|
RESTART_TEXT: 'EMS-ESP kräver en omstart för att applicera förändrade systeminställningar',
|
||||||
RESTART_CONFIRM: 'Är du säker på att du vill starta om EMS-ESP?',
|
RESTART_CONFIRM: 'Är du säker på att du vill starta om EMS-ESP?',
|
||||||
COMMAND: 'Kommando',
|
COMMAND: 'Kommando',
|
||||||
CUSTOMIZATIONS_RESTART: 'Alla anpassningr har raderats. Startar om...',
|
CUSTOMIZATIONS_RESTART: 'Alla anpassningar har raderats. Startar om...',
|
||||||
CUSTOMIZATIONS_FULL: 'Antal valda enheter för högt. Vänligen spara i mindre antal åt gången.',
|
CUSTOMIZATIONS_FULL: 'För många valda enheter. Vänligen spara ett mindre antal åt gången.',
|
||||||
CUSTOMIZATIONS_SAVED: 'Anpassningar sparade',
|
CUSTOMIZATIONS_SAVED: 'Anpassningarna är sparade',
|
||||||
CUSTOMIZATIONS_HELP_1: 'Välj en enhet och anpassa underenheter med hjälp av alternativen',
|
CUSTOMIZATIONS_HELP_1: 'Välj en enhet och anpassa entiteter med hjälp av alternativen',
|
||||||
CUSTOMIZATIONS_HELP_2: 'Favorit',
|
CUSTOMIZATIONS_HELP_2: 'Favorit',
|
||||||
CUSTOMIZATIONS_HELP_3: 'Inaktivera skrivningar',
|
CUSTOMIZATIONS_HELP_3: 'Skrivskyddad',
|
||||||
CUSTOMIZATIONS_HELP_4: 'Exkludera från MQTT & API',
|
CUSTOMIZATIONS_HELP_4: 'Exkludera från MQTT & API',
|
||||||
CUSTOMIZATIONS_HELP_5: 'dölj från enheter',
|
CUSTOMIZATIONS_HELP_5: 'Dölj under Enheter',
|
||||||
CUSTOMIZATIONS_HELP_6: 'remove from memory',
|
CUSTOMIZATIONS_HELP_6: 'Ta bort',
|
||||||
SELECT_DEVICE: 'Välj en enhet',
|
SELECT_DEVICE: 'Välj en enhet',
|
||||||
SET_ALL: 'ställ in alla',
|
SET_ALL: 'ställ in alla',
|
||||||
OPTIONS: 'Alternativ',
|
OPTIONS: 'Alternativ',
|
||||||
NAME: 'Namn',
|
NAME: 'Namn',
|
||||||
CUSTOMIZATIONS_RESET: 'Är du säker på att du vill ta bort alla anpassningar inklusive inställningar för Temperatur och Analoga sensorer?',
|
CUSTOMIZATIONS_RESET: 'Är du säker på att du vill ta bort alla anpassningar, inklusive inställningar för Temperatursensorer och Analoga sensorer?',
|
||||||
SUPPORT_INFORMATION: 'Supportinformation',
|
SUPPORT_INFORMATION: 'Supportinformation',
|
||||||
HELP_INFORMATION_1: 'Besök Wikin för instruktioner för hur du kan konfigurera EMS-ESP',
|
HELP_INFORMATION_1: 'Besök Wikin för instruktioner om hur du kan konfigurera EMS-ESP',
|
||||||
HELP_INFORMATION_2: 'För community-support besök vår Discord-server',
|
HELP_INFORMATION_2: 'För community-support besök vår Discord-server',
|
||||||
HELP_INFORMATION_3: 'Önska en ny funktion eller rapportera en bugg',
|
HELP_INFORMATION_3: 'Önska en ny funktion eller rapportera en bugg',
|
||||||
HELP_INFORMATION_4: 'Bifoga din systeminformation för snabbare hantering när du rapporterar ett problem',
|
HELP_INFORMATION_4: 'Bifoga din supportinformation för snabbare hantering när du rapporterar ett problem',
|
||||||
UPLOAD: 'Uppladdning',
|
UPLOAD: 'Uppladdning',
|
||||||
DOWNLOAD: '{{N|n|n}}edladdning',
|
DOWNLOAD: '{{N|n|n}}edladdning',
|
||||||
INSTALL: 'Installera',
|
INSTALL: 'Installera',
|
||||||
@@ -168,90 +168,90 @@ const sv: Translation = {
|
|||||||
SYSTEM: 'System',
|
SYSTEM: 'System',
|
||||||
LOG_OF: '{0} Logg',
|
LOG_OF: '{0} Logg',
|
||||||
STATUS_OF: '{0} Status',
|
STATUS_OF: '{0} Status',
|
||||||
DOWNLOAD_UPLOAD: 'Nedladdning/Upp',
|
DOWNLOAD_UPLOAD: 'Nedladdning/Uppladdning',
|
||||||
CLOSE: 'Stäng',
|
CLOSE: 'Stäng',
|
||||||
USE: 'Använd',
|
USE: 'Använd',
|
||||||
FACTORY_RESET: 'Fabriksåterställning',
|
FACTORY_RESET: 'Fabriksåterställning',
|
||||||
SYSTEM_FACTORY_TEXT: 'Enheten har blivit fabriksåterställd och startar nu om',
|
SYSTEM_FACTORY_TEXT: 'Enheten har blivit fabriksåterställd och startar nu om',
|
||||||
SYSTEM_FACTORY_TEXT_DIALOG: 'Är du säker att du vill fabriksåterställa enheten?',
|
SYSTEM_FACTORY_TEXT_DIALOG: 'Är du säker på att du vill fabriksåterställa enheten?',
|
||||||
AVAILABLE_VERSION: 'Latest Available Versions', // TODO translate
|
AVAILABLE_VERSION: 'Senaste tillgängliga versioner',
|
||||||
STABLE: 'Stable', // TODO translate
|
STABLE: 'Stabil',
|
||||||
DEVELOPMENT: 'Utveckling',
|
DEVELOPMENT: 'Utveckling',
|
||||||
UPTIME: 'Systemets Upptid',
|
UPTIME: 'Systemets upptid',
|
||||||
FREE_MEMORY: 'Ledigt Memory',
|
FREE_MEMORY: 'Ledigt minne',
|
||||||
PSRAM: 'PSRAM (Storlek / Ledigt)',
|
PSRAM: 'PSRAM (Storlek / Ledigt)',
|
||||||
FLASH: 'Flashminne (Storlek , Hastighet)',
|
FLASH: 'Flashminne (Storlek , Hastighet)',
|
||||||
APPSIZE: 'Applikationer (Partition: Använt / Ledigt)',
|
APPSIZE: 'Applikationer (Partition: Använt / Ledigt)',
|
||||||
FILESYSTEM: 'Filsystem (Använt / Ledigt)',
|
FILESYSTEM: 'Filsystem (Använt / Ledigt)',
|
||||||
BUFFER_SIZE: 'Max Bufferstorlek',
|
BUFFER_SIZE: 'Max bufferstorlek',
|
||||||
COMPACT: 'Komprimera',
|
COMPACT: 'Komprimerad',
|
||||||
DOWNLOAD_SETTINGS_TEXT: 'Create a backup of your configuration and settings', // TODO translate
|
DOWNLOAD_SETTINGS_TEXT: 'Skapa en säkerhetskopia av din konfiguration och inställningar',
|
||||||
UPLOAD_TEXT: 'Upload a new firmware file (.bin) or a backup file (.json)', // TODO translate
|
UPLOAD_TEXT: 'Ladda upp en ny firmwarefil (.bin) eller en säkerhetskopiafil (.json)',
|
||||||
UPLOAD_DROP_TEXT: 'Släpp fil eller klicka här',
|
UPLOAD_DROP_TEXT: 'Droppa en firmware .bin fil eller klicka här',
|
||||||
ERROR: 'Okänt Fel, var god försök igen',
|
ERROR: 'Okänt fel, var god försök igen',
|
||||||
TIME_SET: 'Ställ in tid',
|
TIME_SET: 'Ställ in tid',
|
||||||
MANAGE_USERS: 'Användare',
|
MANAGE_USERS: 'Användare',
|
||||||
IS_ADMIN: 'Admin',
|
IS_ADMIN: 'Administratör',
|
||||||
USER_WARNING: 'Du måste ha minst en admin konfigurerad',
|
USER_WARNING: 'Du måste ha minst en administratör konfigurerad',
|
||||||
ADD: 'Lägg till',
|
ADD: 'Lägg till',
|
||||||
ACCESS_TOKEN_FOR: 'Access Token för',
|
ACCESS_TOKEN_FOR: 'Access Token för',
|
||||||
ACCESS_TOKEN_TEXT: 'Nedan Token används med REST API-anrop som kräver auktorisering. Den kan skickas med antingen som en Bearer token i Authorization-headern eller i access_token URL query-parametern.',
|
ACCESS_TOKEN_TEXT: 'Nedan Token används med REST API-anrop som kräver auktorisering. Den kan skickas med antingen som en Bearer token i Authorization-headern eller i access_token URL query-parametern.',
|
||||||
GENERATING_TOKEN: 'Genererar token',
|
GENERATING_TOKEN: 'Genererar token',
|
||||||
USER: 'Användare',
|
USER: 'Användare',
|
||||||
MODIFY: 'Ändra',
|
MODIFY: 'Ändra',
|
||||||
SU_TEXT: 'SU-användarens (super user) lösenord används för att signera autensierings-tokens samt för att aktivera administratörsprivilegier i Console-läge',
|
SU_TEXT: 'SU-användarens (super user) lösenord används för att signera autentisierings-tokens samt för att aktivera administratörsprivilegier i Console-läge',
|
||||||
NOT_ENABLED: 'Ej aktiv',
|
NOT_ENABLED: 'Ej aktiv',
|
||||||
ERRORS_OF: '{0} fel',
|
ERRORS_OF: '{0} fel',
|
||||||
DISCONNECT_REASON: 'Anledning till nedkoppling',
|
DISCONNECT_REASON: 'Anledning till nedkoppling',
|
||||||
ENABLE_MQTT: 'Aktivera MQTT',
|
ENABLE_MQTT: 'Aktivera MQTT',
|
||||||
BROKER: 'Broker',
|
BROKER: 'Broker',
|
||||||
CLIENT: 'Client',
|
CLIENT: 'Klient',
|
||||||
BASE_TOPIC: 'Base',
|
BASE_TOPIC: 'Bas-topic',
|
||||||
OPTIONAL: 'valfritt',
|
OPTIONAL: 'valfritt',
|
||||||
FORMATTING: 'Formatering',
|
FORMATTING: 'Formatering',
|
||||||
MQTT_FORMAT: 'Topic/Payload Format',
|
MQTT_FORMAT: 'Topic/Payload format',
|
||||||
MQTT_NEST_1: 'Nestlat i en topic.',
|
MQTT_NEST_1: 'Nästlat i en topic.',
|
||||||
MQTT_NEST_2: 'Som individuella topics',
|
MQTT_NEST_2: 'Som individuella topics',
|
||||||
MQTT_RESPONSE: 'Publish-kommando som ett `response` topic',
|
MQTT_RESPONSE: 'Publish-kommando som ett `response` topic',
|
||||||
MQTT_PUBLISH_TEXT_1: 'Publicera single value topics vid värdeförändring',
|
MQTT_PUBLISH_TEXT_1: 'Publicera single value topics vid värdeförändring',
|
||||||
MQTT_PUBLISH_TEXT_2: 'Publicera till kommando-topics (ioBroker)',
|
MQTT_PUBLISH_TEXT_2: 'Publicera till kommando-topics (ioBroker)',
|
||||||
MQTT_PUBLISH_TEXT_3: 'Aktivera MQTT Discovery',
|
MQTT_PUBLISH_TEXT_3: 'Aktivera MQTT Discovery',
|
||||||
MQTT_PUBLISH_TEXT_4: 'Prefix för Discovery topics',
|
MQTT_PUBLISH_TEXT_4: 'Prefix för Discovery topics',
|
||||||
MQTT_PUBLISH_TEXT_5: 'Discovery type', // TODO translate
|
MQTT_PUBLISH_TEXT_5: 'Discoverytyp',
|
||||||
MQTT_PUBLISH_INTERVALS: 'Publiceringsintervall',
|
MQTT_PUBLISH_INTERVALS: 'Publiceringsintervall',
|
||||||
MQTT_INT_BOILER: 'Värmepump/panna',
|
MQTT_INT_BOILER: 'Värmepump/panna',
|
||||||
MQTT_INT_THERMOSTATS: 'Termostater',
|
MQTT_INT_THERMOSTATS: 'Termostater',
|
||||||
MQTT_INT_SOLAR: 'Solpaneler',
|
MQTT_INT_SOLAR: 'Solpaneler',
|
||||||
MQTT_INT_MIXER: 'Blandningsventiler',
|
MQTT_INT_MIXER: 'Blandningsventiler',
|
||||||
MQTT_INT_WATER: 'Water Modules', // TODO translate
|
MQTT_INT_WATER: 'Varmvattenmoduler',
|
||||||
MQTT_QUEUE: 'MQTT-kö',
|
MQTT_QUEUE: 'MQTT-kö',
|
||||||
DEFAULT: 'Standard',
|
DEFAULT: 'Standard',
|
||||||
MQTT_ENTITY_FORMAT: 'Entitets-ID format',
|
MQTT_ENTITY_FORMAT: 'Entitets-ID format',
|
||||||
MQTT_ENTITY_FORMAT_0: 'Singel-instans, långt namn(v3.4)',
|
MQTT_ENTITY_FORMAT_0: 'Singel-instans, långt namn(v3.4)',
|
||||||
MQTT_ENTITY_FORMAT_1: 'Singel-instans, kort name',
|
MQTT_ENTITY_FORMAT_1: 'Singel-instans, kort namn',
|
||||||
MQTT_ENTITY_FORMAT_2: 'Multi-instans, kort name',
|
MQTT_ENTITY_FORMAT_2: 'Multi-instans, kort namn',
|
||||||
MQTT_CLEAN_SESSION: 'Använd "Clean Session"-flaggan',
|
MQTT_CLEAN_SESSION: 'Använd "Clean Session"-flaggan',
|
||||||
MQTT_RETAIN_FLAG: 'Använd "Always Retain"-flaggan',
|
MQTT_RETAIN_FLAG: 'Använd "Always Retain"-flaggan',
|
||||||
INACTIVE: 'Inaktiv',
|
INACTIVE: 'Inaktiv',
|
||||||
ACTIVE: 'Aktiv',
|
ACTIVE: 'Aktiv',
|
||||||
UNKNOWN: 'Okänt',
|
UNKNOWN: 'Okänt',
|
||||||
SET_TIME: 'Ställ in klockan',
|
SET_TIME: 'Ställ in klockan',
|
||||||
SET_TIME_TEXT: 'Ange lokal datum och tid nedan för att ställa in klockan',
|
SET_TIME_TEXT: 'Ange lokalt datum och tid nedan för att ställa in klockan',
|
||||||
LOCAL_TIME: 'Tid (lokal)',
|
LOCAL_TIME: 'Tid (lokal)',
|
||||||
UTC_TIME: 'Tid (UTC)',
|
UTC_TIME: 'Tid (UTC)',
|
||||||
ENABLE_NTP: 'Aktivera NTP',
|
ENABLE_NTP: 'Aktivera NTP',
|
||||||
NTP_SERVER: 'NTP-server',
|
NTP_SERVER: 'NTP-server',
|
||||||
TIME_ZONE: 'Tidszon',
|
TIME_ZONE: 'Tidszon',
|
||||||
ACCESS_POINT: 'Accesspunkt',
|
ACCESS_POINT: 'Accesspunkt',
|
||||||
AP_PROVIDE: 'Aktivera Accesspunkt',
|
AP_PROVIDE: 'Aktivera accesspunkt',
|
||||||
AP_PROVIDE_TEXT_1: 'alltid',
|
AP_PROVIDE_TEXT_1: 'alltid',
|
||||||
AP_PROVIDE_TEXT_2: 'när WiFi är nedkopplat',
|
AP_PROVIDE_TEXT_2: 'när WiFi är nedkopplat',
|
||||||
AP_PROVIDE_TEXT_3: 'aldrig',
|
AP_PROVIDE_TEXT_3: 'aldrig',
|
||||||
AP_PREFERRED_CHANNEL: 'Kanal',
|
AP_PREFERRED_CHANNEL: 'Kanal',
|
||||||
AP_HIDE_SSID: 'Göm SSID',
|
AP_HIDE_SSID: 'Göm SSID',
|
||||||
AP_CLIENTS: 'AP-klienter',
|
AP_CLIENTS: 'AP-klienter',
|
||||||
AP_MAX_CLIENTS: 'Max Klienter',
|
AP_MAX_CLIENTS: 'Max antal klienter',
|
||||||
AP_LOCAL_IP: 'Lokalt IP',
|
AP_LOCAL_IP: 'Lokal IP-adress',
|
||||||
NETWORK_SCAN: 'Sök efter WiFi-nätverk',
|
NETWORK_SCAN: 'Sök efter WiFi-nätverk',
|
||||||
IDLE: 'Vilande',
|
IDLE: 'Vilande',
|
||||||
LOST: 'Förlorad',
|
LOST: 'Förlorad',
|
||||||
@@ -260,90 +260,98 @@ const sv: Translation = {
|
|||||||
NETWORK_SCANNER: 'Hittade nätverk',
|
NETWORK_SCANNER: 'Hittade nätverk',
|
||||||
NETWORK_NO_WIFI: 'Inga WiFi-nätverk hittades',
|
NETWORK_NO_WIFI: 'Inga WiFi-nätverk hittades',
|
||||||
NETWORK_BLANK_SSID: 'lämna blankt för att inaktivera WiFi',
|
NETWORK_BLANK_SSID: 'lämna blankt för att inaktivera WiFi',
|
||||||
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
|
NETWORK_BLANK_BSSID: 'lämna blankt för att bara använda SSID',
|
||||||
TX_POWER: 'Tx Effekt',
|
TX_POWER: 'Tx effekt',
|
||||||
HOSTNAME: 'Värdnamn',
|
HOSTNAME: 'Värdnamn',
|
||||||
NETWORK_DISABLE_SLEEP: 'Inaktivera sömnläge',
|
NETWORK_DISABLE_SLEEP: 'Inaktivera sovläge',
|
||||||
NETWORK_LOW_BAND: 'Använd lägre bandbredd',
|
NETWORK_LOW_BAND: 'Använd lägre bandbredd',
|
||||||
NETWORK_USE_DNS: 'Aktivera mDNS-tjänsten',
|
NETWORK_USE_DNS: 'Aktivera mDNS-tjänsten',
|
||||||
NETWORK_ENABLE_CORS: 'Aktivera CORS',
|
NETWORK_ENABLE_CORS: 'Aktivera CORS',
|
||||||
NETWORK_CORS_ORIGIN: 'CORS origin',
|
NETWORK_CORS_ORIGIN: 'CORS origin',
|
||||||
NETWORK_FIXED_IP: 'Använd statiskt IP',
|
NETWORK_FIXED_IP: 'Använd statisk IP-adress',
|
||||||
NETWORK_GATEWAY: 'Gateway',
|
NETWORK_GATEWAY: 'Gateway',
|
||||||
NETWORK_SUBNET: 'Subnätmask',
|
NETWORK_SUBNET: 'Subnätmask',
|
||||||
NETWORK_DNS: 'DNS-Server',
|
NETWORK_DNS: 'DNS-Server',
|
||||||
ADDRESS_OF: '{0} Adress',
|
ADDRESS_OF: '{0} Adress',
|
||||||
ADMINISTRATOR: 'Administrator',
|
ADMINISTRATOR: 'Administratör',
|
||||||
GUEST: 'Gäst',
|
GUEST: 'Gäst',
|
||||||
NEW: 'Ny',
|
NEW: 'ny',
|
||||||
NEW_NAME_OF: 'Byt namn {0}',
|
NEW_NAME_OF: 'Byt namn {0}',
|
||||||
ENTITY: 'Entitet',
|
ENTITY: 'Entitet',
|
||||||
MIN: 'min',
|
MIN: 'min',
|
||||||
MAX: 'max',
|
MAX: 'max',
|
||||||
BLOCK_NAVIGATE_1: 'You have unsaved changes', // TODO translate
|
BLOCK_NAVIGATE_1: 'Du har osparade ändringar',
|
||||||
BLOCK_NAVIGATE_2: 'If you navigate to a different page, your unsaved changes will be lost. Are you sure you want to leave this page?', // TODO translate
|
BLOCK_NAVIGATE_2: 'Om du navigerar till en annan sida, kommer dina osparade ändringar förloras. Är du säker på att du vill lämna den här sidan?',
|
||||||
STAY: 'Stay', // TODO translate
|
STAY: 'Stanna',
|
||||||
LEAVE: 'Leave', // TODO translate
|
LEAVE: 'Lämna',
|
||||||
SCHEDULER: 'Scheduler', // TODO translate
|
SCHEDULER: 'Schemaläggning',
|
||||||
SCHEDULER_HELP_1: 'Automate commands by adding scheduled events below. Set a unique Name to enable/disable activation via API/MQTT', // TODO translate
|
SCHEDULER_HELP_1: 'Automatisera kommandon genom att lägga till schemahändelser nedan. Ange ett unikt namn för att aktivera/avaktivera aktivering via API/MQTT',
|
||||||
SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate
|
SCHEDULER_HELP_2: 'Använd 00:00 för att trigga en gång vid uppstart',
|
||||||
SCHEDULE: 'Schedule', // TODO translate
|
SCHEDULE: 'schema',
|
||||||
TIME: 'Time', // TODO translate
|
TIME: 'Tid',
|
||||||
TIMER: 'Timer', // TODO translate
|
TIMER: 'Timer',
|
||||||
ONCHANGE: 'På förändring',
|
ONCHANGE: 'Vid förändring',
|
||||||
CONDITION: 'Skick',
|
CONDITION: 'Villkor',
|
||||||
IMMEDIATE: 'Omedelbar',
|
IMMEDIATE: 'Omedelbar',
|
||||||
SCHEDULE_UPDATED: 'Schedule updated', // TODO translate
|
SCHEDULE_UPDATED: 'Schema uppdaterat',
|
||||||
SCHEDULE_TIMER_1: 'on startup', // TODO translate
|
SCHEDULE_TIMER_1: 'vid uppstart',
|
||||||
SCHEDULE_TIMER_2: 'every minute', // TODO translate
|
SCHEDULE_TIMER_2: 'varje minut',
|
||||||
SCHEDULE_TIMER_3: 'every hour', // TODO translate
|
SCHEDULE_TIMER_3: 'varje timme',
|
||||||
CUSTOM_ENTITIES: 'Custom Entities', // TODO translate
|
CUSTOM_ENTITIES: 'Anpassade entiteter',
|
||||||
ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', // TODO translate
|
ENTITIES_HELP_1: 'Hämta anpassade entiteter från EMS bussen',
|
||||||
ENTITIES_UPDATED: 'Entities Updated', // TODO translate
|
ENTITIES_UPDATED: 'Entiteter uppdaterade',
|
||||||
WRITEABLE: 'Writeable', // TODO translate
|
WRITEABLE: 'Skrivbara',
|
||||||
SHOWING: 'Showing', // TODO translate
|
SHOWING: 'Visar',
|
||||||
SEARCH: 'Search', // TODO translate
|
SEARCH: 'Sök',
|
||||||
CERT: 'TLS root certificate (leave blank for insecure)', // TODO translate
|
CERT: 'TLS rotcertifikat (lämna blankt för ingen säkerhet)',
|
||||||
ENABLE_TLS: 'Aktivera TLS',
|
ENABLE_TLS: 'Aktivera TLS',
|
||||||
ON: 'On', // TODO translate
|
ON: 'På',
|
||||||
OFF: 'Off', // TODO translate
|
OFF: 'Av',
|
||||||
POLARITY: 'Polarity', // TODO translate
|
POLARITY: 'Polaritet',
|
||||||
ACTIVEHIGH: 'Active High', // TODO translate
|
ACTIVEHIGH: 'Aktivt hög',
|
||||||
ACTIVELOW: 'Active Low', // TODO translate
|
ACTIVELOW: 'Aktivt låg',
|
||||||
UNCHANGED: 'Unchanged', // TODO translate
|
UNCHANGED: 'Oändrad',
|
||||||
ALWAYS: 'Always', // TODO translate
|
ALWAYS: 'Alltid',
|
||||||
ACTIVITY: 'Activity', // TODO translate
|
ACTIVITY: 'Aktivitet',
|
||||||
CONFIGURE: 'Configure {0}', // TODO translate
|
CONFIGURE: 'Konfigurera {0}',
|
||||||
SYSTEM_MEMORY: 'System Memory', // TODO translate
|
SYSTEM_MEMORY: 'Systemminne',
|
||||||
APPLICATION_SETTINGS_1: 'Modify EMS-ESP Application Settings', // TODO translate
|
APPLICATION_SETTINGS_1: 'Ändra EMS-ESP Applikationsinställningar',
|
||||||
SECURITY_1: 'Add or remove users', // TODO translate
|
SECURITY_1: 'Lägg till eller ta bort användare',
|
||||||
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate
|
DOWNLOAD_UPLOAD_1: 'Ladda ner eller ladda upp inställningar och firmware',
|
||||||
MODULES: 'Module', // TODO translate
|
MODULES: 'Moduler',
|
||||||
MODULES_1: 'Aktivera eller avaktivera externa moduler',
|
MODULES_1: 'Aktivera eller avaktivera externa moduler',
|
||||||
MODULES_UPDATED: 'Modules updated', // TODO translate
|
MODULES_UPDATED: 'Moduler updaterade',
|
||||||
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
|
MODULES_DESCRIPTION: 'Klicka på modulen för att aktivera eller deaktivera EMS-ESP moduler',
|
||||||
MODULES_NONE: 'No external modules detected', // TODO translate
|
MODULES_NONE: 'Inga externa moduler upptäckta',
|
||||||
RENAME: 'Rename', // TODO translate
|
RENAME: 'Byt namn',
|
||||||
ENABLE_MODBUS: 'Aktivera Modbus',
|
ENABLE_MODBUS: 'Aktivera Modbus',
|
||||||
VIEW_LOG: 'View log to diagnose issues', // TODO translate
|
VIEW_LOG: 'Titta i loggen för att felsöka problem',
|
||||||
UPLOAD_DRAG: 'drag and drop a file here or click to select one', // TODO translate
|
UPLOAD_DRAG: 'dra och släpp en fil här eller klicka för att välja en',
|
||||||
SERVICES: 'Services', // TODO translate
|
SERVICES: 'Tjänster',
|
||||||
ALLVALUES: 'All Values', // TODO translate
|
ALLVALUES: 'Alla värden',
|
||||||
SPECIAL_FUNCTIONS: 'Special Functions', // TODO translate
|
SPECIAL_FUNCTIONS: 'Specialfunktioner',
|
||||||
WAIT_FIRMWARE: 'Firmware is uploading and installing', // TODO translate
|
WAIT_FIRMWARE: 'Firmware laddas upp och installeras',
|
||||||
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
|
INSTALL_VERSION: 'Det här kommer {0} version {1}. Är du säker?',
|
||||||
SWITCH_DEV: 'switch to the development version', // TODO translate
|
UPDATE_AVAILABLE: 'uppdatering tillgänglig',
|
||||||
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
|
LATEST_VERSION: 'Du använder den senaste {0} firmwareversionen.',
|
||||||
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
|
PLEASE_WAIT: 'Var god vänta',
|
||||||
PLEASE_WAIT: 'Please wait', // TODO translate
|
RESTARTING_PRE: 'Initialiserar',
|
||||||
RESTARTING_PRE: 'Initializing', // TODO translate
|
RESTARTING_POST: 'Förbereder',
|
||||||
RESTARTING_POST: 'Preparing', // TODO translate
|
AUTO_SCROLL: 'Autoskrolla',
|
||||||
AUTO_SCROLL: 'Auto Scroll', // TODO translate
|
DASHBOARD: 'Kontrollpanel',
|
||||||
DASHBOARD: 'Dashboard', // TODO translate
|
DEVELOPER_MODE: 'Utvecklarläge',
|
||||||
NO_DATA: 'No data available', // TODO translate
|
BYTES: 'Bytes',
|
||||||
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
|
BITMASK: 'Bitmask',
|
||||||
DEVELOPER_MODE: 'Developer Mode', // TODO translate
|
DUPLICATE: 'Dublett',
|
||||||
UPGRADE: 'Upgrade' // TODO translate
|
DASHBOARD_1: 'Alla EMS-enheter som är aktiva och markerade som favorit, plus alla anpassade entiteter, scheman och externa sensor-data visas nedan.',
|
||||||
|
NO_DATA_1: 'Inga favorit EMS enheter hittade än. Använd',
|
||||||
|
NO_DATA_2: 'modul för att markera dem.',
|
||||||
|
NO_DATA_3: 'För att se alla tillgängliga enheter, gå till',
|
||||||
|
THIS_VERSION: 'Denna version',
|
||||||
|
PLATFORM: 'Plattform',
|
||||||
|
RELEASE_TYPE: 'Utgivelsestyp',
|
||||||
|
INTERNET_CONNECTION_REQUIRED: 'Internetanslutning krävs för automatisk version kontroll och uppdatering',
|
||||||
|
SWITCH_RELEASE_TYPE: 'Byt till {0} utgåva'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default sv;
|
export default sv;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user