446 Commits

Author SHA1 Message Date
proddy
29110e96e5 Merge remote-tracking branch 'origin/dev' 2022-01-20 10:51:40 +01:00
Proddy
02e2b51814 Merge pull request #307 from MichaelDvP/dev
check received status before toggling fetch on empty telegram
2022-01-20 10:04:03 +01:00
MichaelDvP
e9588cc7a1 check received status before toggling fetch on empty telegram 2022-01-20 08:41:41 +01:00
Proddy
3d8e1b8f86 Merge pull request #245 from proddy:dev
Add back RC30 - #243
2021-12-14 20:23:34 +00:00
proddy
312f969364 add back RC30 - Setting mode on a RC30/Moduline400 via MQTT in HA doesn't work #243 2021-12-14 21:19:54 +01:00
Proddy
0f41079803 Merge pull request #235 from pswid:dev
fix overlapping 0xC2 and overflow of offset
2021-12-14 19:49:37 +00:00
pswid
7f30e8dadc fix overlaping while reading sequence of EMS1.0 telegrams 2021-12-14 10:32:31 +01:00
pswid
9cd20cfc05 fix overlaping while reading sequence of EMS1.0 telegrams 2021-12-14 10:29:15 +01:00
pswid
1343bbf6ea fix overlapping 0xC2 and overflow of offset 2021-12-03 11:50:52 +01:00
Proddy
90c39d1f85 Merge pull request #234 from pswid/dev 2021-12-03 09:38:40 +01:00
pswid
92da61376b Update boiler.cpp 2021-12-03 09:04:39 +01:00
pswid
69976c2caf Update CHANGELOG_LATEST.md 2021-12-03 09:02:36 +01:00
pswid
3c6fd0c83a Update boiler.cpp 2021-12-03 08:58:19 +01:00
proddy
b0a09747d4 3.3.1b0 2021-11-28 23:06:55 +01:00
proddy
b65866217a 3.4.0 2021-11-28 23:03:28 +01:00
proddy
611e3b1243 Merge remote-tracking branch 'origin/dev' 2021-11-28 23:03:15 +01:00
Proddy
84d3d42306 Merge pull request #220 from proddy:dev
minor updates
2021-11-25 09:16:03 +01:00
proddy
61e2739ef7 updated for b11 2021-11-25 09:13:48 +01:00
proddy
a3391afd27 bump to b11 2021-11-25 09:13:38 +01:00
proddy
ce9b7d1468 added test for lastcode 2021-11-25 09:13:31 +01:00
proddy
1b86314a14 formatting 2021-11-25 09:13:22 +01:00
proddy
b2a0519f83 change font type and size 2021-11-25 09:13:09 +01:00
proddy
3dec4bda8c fix double click 2021-11-25 09:12:57 +01:00
Proddy
5de529cbb2 Merge pull request #218 from pswid:dev
timestamp in boiler last error code
2021-11-25 08:49:44 +01:00
pswid
4fd1d8e08a Boiler last error code change 2021-11-23 19:11:35 +01:00
pswid
0847ccc602 Revert "fix boiler last error code timestamp"
This reverts commit 969803569e.
2021-11-23 19:09:46 +01:00
pswid
969803569e fix boiler last error code timestamp 2021-11-23 18:59:37 +01:00
Proddy
6532abd870 Merge pull request #217 from proddy:dev
text changes, renamed status to bus_status in heartbeat, improved WebUI table layout, added Ethernet phy to custom profile board
2021-11-22 09:11:41 +01:00
proddy
07dabb4ceb fix name of status -> bus_status in heartbeat 2021-11-22 08:49:53 +01:00
proddy
1c6a683015 rename bus to bus_status in info command 2021-11-22 08:49:33 +01:00
proddy
bb38458ac4 stripped table rows 2021-11-22 00:36:15 +01:00
proddy
53de2ca25b added ethernet phy type as an option in settings - #210 2021-11-21 13:51:02 +01:00
Proddy
5a9122f8be Merge pull request #215 from proddy/dev 2021-11-20 21:25:02 +01:00
proddy
dc84f91044 debug comments 2021-11-20 21:23:04 +01:00
proddy
4be6626470 fixed edge case in shower logic when state didn't change 2021-11-20 21:22:55 +01:00
proddy
7e4494aae1 rename status to bus_status in MQTT heartbeat 2021-11-20 21:22:28 +01:00
proddy
50e54e6a1c fix removing old HA config topics 2021-11-20 21:22:10 +01:00
Proddy
30b111b986 Merge pull request #208 from proddy:dev
fixes #207
2021-11-19 13:00:58 +01:00
proddy
a63f2e6131 fixes #207 - allow both data and value as MQTT keys 2021-11-19 12:59:52 +01:00
proddy
51d487b938 formatting 2021-11-19 12:57:48 +01:00
Proddy
96180c837d Merge pull request #203 from proddy:dev
Add Network to MQTT topic info and system/info command
2021-11-18 12:11:40 +01:00
proddy
da20cf1ed2 add Network to MQTT info topic and system/info command 2021-11-18 12:10:20 +01:00
proddy
bffad5e3c8 allow thermostat hc3 on device_id 0x1A - #200 2021-11-17 22:22:34 +01:00
Proddy
74287ebb99 Merge pull request #201 from proddy:dev
fixes #199 - change value validation fails
2021-11-17 19:03:27 +01:00
proddy
8b40c92f7e fixes #199 - change value formats degrees to strings 2021-11-17 19:01:29 +01:00
Proddy
5f6033cac1 Merge pull request #197 from proddy/dev
fixes #196 (HA missing entities), add row click to devices, change max limit on integer types to avoid NaN, refactored generation of device value JSON objects
2021-11-15 17:45:52 +01:00
proddy
24582407d4 b7 2021-11-15 15:27:25 +01:00
proddy
22c9e3ee1f tidy up generate_values_json_web 2021-11-15 15:23:01 +01:00
proddy
cb2c898b7e click row to edit 2021-11-15 15:22:46 +01:00
proddy
c0bf623266 rename publish_ha* functions 2021-11-15 14:28:14 +01:00
proddy
18f22d3951 add state to dv, using DeviceValueState 2021-11-15 14:27:53 +01:00
proddy
e2dad610b0 publish HA config topic after device values 2021-11-15 14:27:18 +01:00
proddy
5ed3cbee2e add days 2021-11-15 14:26:42 +01:00
proddy
27712badb6 allow empty payloads, refactor to also delete a HA topic 2021-11-15 14:26:30 +01:00
proddy
72c032adff replace read_flash_string 2021-11-15 14:25:49 +01:00
proddy
7197df9812 replace read_flash_string 2021-11-15 14:25:04 +01:00
proddy
898e2e5f21 bump b7 2021-11-15 14:24:33 +01:00
proddy
cde3b7541f update test for 196 2021-11-15 14:24:21 +01:00
proddy
822f55497e tidy up, mention HA enttity fix 2021-11-15 14:23:58 +01:00
Proddy
7c16870294 Merge pull request #194 from kpschaper/bugfix_settemp
bugfix revert auto mode -> the mode is hardcoded for the thermostat_ha_cmd #183
2021-11-14 18:17:18 +01:00
Proddy
e368f422f4 Merge pull request #195 from proddy/dev
Fix console UOM, set temperature to show 1 decimal place in web
2021-11-14 18:04:39 +01:00
proddy
9d9ac4ed9e force temperatures in degrees to always show 1 decimal place 2021-11-14 16:14:29 +01:00
proddy
d7576ebda1 fix bug showing UOM in Console 2021-11-14 16:14:04 +01:00
proddy
fd810ff01c add comments on format param 2021-11-14 16:10:32 +01:00
proddy
999a05f7ff bump to b6 2021-11-14 16:10:20 +01:00
proddy
a19f2f19c5 update test data 2021-11-14 16:10:10 +01:00
Koen Schaper
f54ccd40e6 revert auto mode -> the mode is hardcoded for the thermostat_ha_cmd #183 2021-11-14 15:32:12 +01:00
Proddy
5893487d4a Merge pull request #189 from proddy:dev
fix MQTT non-JSON payloads
2021-11-14 12:56:20 +01:00
Proddy
3c8e20d4e4 Merge pull request #193 from kpschaper/fix_rc10_mode
Mode update for #183
2021-11-14 12:55:37 +01:00
Koen Schaper
bf68a5523b Update changelog 2021-11-14 12:14:55 +01:00
Koen Schaper
9c5c27152c Allow mode "off" to be set from home assistant + remove non available "auto" mode from home assistant 2021-11-14 11:11:37 +01:00
proddy
c229371c68 fix typo 2021-11-14 10:26:13 +01:00
proddy
805cef68a2 fix handling on non json payloads - #173 2021-11-13 15:59:04 +01:00
proddy
09addcb975 with the release of espressif32 3.4.0 we don't need the delay anymore for telnet 2021-11-12 14:33:22 +01:00
Proddy
409d382ff9 Merge pull request #188 from MichaelDvP:dev
Mode update for #183
2021-11-11 20:04:25 +01:00
MichaelDvP
27bfc14438 set mode and heatingPID for RC10 #183 2021-11-11 17:30:17 +01:00
MichaelDvP
6c20a5f4f9 prevent double messages in weblog 2021-11-11 08:22:20 +01:00
MichaelDvP
ffd61a9f67 removed unused pragma 2021-11-11 08:21:12 +01:00
MichaelDvP
4f2da0347c add hc to console calls 2021-11-10 14:06:00 +01:00
MichaelDvP
3c13c144d5 fix wwc ids 2021-11-10 14:05:31 +01:00
proddy
d4eaedef3d text changes 2021-11-10 12:31:01 +01:00
proddy
a8f1892d48 rename system/info text, added MQTT status 2021-11-10 12:27:18 +01:00
proddy
e347ac5742 formatting and text changes 2021-11-10 12:26:59 +01:00
proddy
5f2a9b093d improve error handling, fix crash on empty /api URL 2021-11-10 12:26:29 +01:00
proddy
e821e8d082 update 2021-11-10 12:25:38 +01:00
proddy
05f56be2d8 bump version to 3.3.0b4 2021-11-09 21:59:44 +01:00
proddy
88f78f6541 fix authentication check for GET commands that need admin - Refactor MQTT subscriptions and API calls #173 2021-11-09 20:54:41 +01:00
MichaelDvP
234533f241 fix RC35 program no. #182 2021-11-09 15:44:41 +01:00
MichaelDvP
b1f72b0e3e fix crash on empty mqtt-payload 2021-11-08 18:30:33 +01:00
MichaelDvP
a3022f6f20 RC35 switchtime for prog 1 and prog 2 2021-11-08 18:29:25 +01:00
MichaelDvP
95f7583511 fix wrong RC10 tag 2021-11-08 07:57:08 +01:00
MichaelDvP
578ba386e6 add moduline200 values #183, RC35 holidays/vacations #182 2021-11-07 20:49:58 +01:00
proddy
df7be9d11e update to 3.3.0b3 2021-11-07 18:24:33 +01:00
Proddy
72a59917fb Merge pull request #185 from kpschaper/fix_shower_alert
Fix shower timer; doing_cold_shot is never being reset
2021-11-07 17:42:49 +01:00
Koen Schaper
9406c76e55 fix shower timer; doing_cold_shot is never being reset + remove unnecessary conditions 2021-11-07 16:34:40 +01:00
proddy
ea550b1656 read command checks device id - #184 2021-11-07 13:50:39 +01:00
proddy
d20741c0f0 add a little more buffer for concurrent web sockets 2021-11-07 13:49:55 +01:00
Proddy
91b7fd59d1 Merge pull request #181 from kpschaper/moduline200
Show mode (off / heat) in Home Assistant for Moduline 200
2021-11-06 20:56:57 +01:00
proddy
95e81ad824 auto-fetch 0x14 which is not broadcasted on all boilers - https://github.com/emsesp/EMS-ESP32/issues/160#issuecomment-962444738 2021-11-06 13:31:32 +01:00
Koen Schaper
316832fc4f Show mode (off / heat) in Home Assistant for Moduline 200 2021-11-06 10:07:04 +01:00
proddy
23b6d81c47 3.3.0b2 2021-11-05 21:48:11 +01:00
proddy
8284520733 increase tcp event queue from 32 to 64 - fixes Launching the WebUI from crashes EMS-ESP on some environments #177 2021-11-05 21:46:15 +01:00
MichaelDvP
57f53818e1 add RC20_N write extmintemp, formatting 2021-11-05 14:14:04 +01:00
proddy
7bca3fb2ed rename "name" to "entity" for API key - Refactor MQTT subscriptions and API calls #173 2021-11-05 13:22:39 +01:00
MichaelDvP
ae4a1358af show rf sensor temperature 2021-11-05 11:57:58 +01:00
MichaelDvP
95e3a11a11 add missing RC25 parameters 2021-11-05 11:53:41 +01:00
MichaelDvP
f1a859c650 show devices with product-id zero, m200 wait improved 2021-11-05 11:53:02 +01:00
MichaelDvP
8d9fd95e85 remove useless extra subscriptions #173 2021-11-04 13:13:41 +01:00
proddy
452921d198 MQTT subscribe to devices - Refactor MQTT subscriptions and API calls #173 2021-11-03 22:12:21 +01:00
proddy
3e0f6f55fb bump to 3.3.0b1 2021-11-03 22:11:44 +01:00
MichaelDvP
0e480bbd94 add known devices without product-id or version-info #174 2021-11-03 21:08:52 +01:00
proddy
7a079d866f put/# back - Refactor MQTT subscriptions and API calls #173 2021-11-03 19:22:42 +01:00
MichaelDvP
af2710125e mqtt subscriptions include device #173 2021-11-03 18:43:46 +01:00
MichaelDvP
fb3de2e36d add RC300 wwdisinfect #175 2021-11-03 12:17:00 +01:00
proddy
bf40222105 validate devices to see if they are present - Refactor MQTT subscriptions #173 2021-11-02 21:00:16 +01:00
proddy
e1419edb15 more fixes - Refactor MQTT subscriptions #173 2021-11-02 18:15:57 +01:00
proddy
131b936a69 siwtch info with list - #176 2021-11-02 16:02:49 +01:00
proddy
5850a82d80 error handling improvements - Refactor MQTT subscriptions #173 2021-11-02 13:59:36 +01:00
proddy
b76b6be3d1 logic cleanup 2021-11-02 10:50:29 +01:00
proddy
b8f69eeaa8 lint warning fix 2021-11-02 10:47:46 +01:00
proddy
d78fb53845 fix for mqtt base paths - Refactor MQTT subscriptions #173 2021-11-02 10:42:34 +01:00
proddy
54889fec41 fix issue where OK was not sent on successfull API call 2021-11-02 10:42:20 +01:00
proddy
2c5c4d6e04 update test for different mqtt base paths 2021-11-02 10:41:56 +01:00
proddy
e6a44c9c82 be able to set mqtt base 2021-11-02 10:41:39 +01:00
proddy
7cba52d77e bump to 3.3.0 2021-11-01 23:32:28 +01:00
proddy
a79a67e4b2 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2021-11-01 23:31:33 +01:00
proddy
01bace4048 Refactor MQTT subscriptions #173 2021-11-01 23:31:30 +01:00
MichaelDvP
d5f8419157 do not fetch CRF200 monitor #138 2021-10-30 20:31:49 +02:00
Proddy
40a7026d4c update example with ESP32 core debug levels 2021-10-26 13:06:29 +02:00
proddy
47cb296cc4 updates to #168 2021-10-25 13:01:56 +02:00
MichaelDvP
be27033d41 typo 2021-10-24 18:32:50 +02:00
MichaelDvP
3001a2d66f fix #169, prod-id:111 settings use telegram 0x179 2021-10-24 18:15:39 +02:00
proddy
becaff0711 updated with #168 2021-10-22 22:17:15 +02:00
proddy
aaab9f409f text change 2021-10-22 22:15:30 +02:00
proddy
068bb5cbeb fix obsolete JS in padding & justification 2021-10-22 22:15:23 +02:00
proddy
337c07d7bc firmware version checker in Web - #168 2021-10-22 22:14:39 +02:00
proddy
c387f65b4a some minor refactor 2021-10-21 22:56:56 +02:00
proddy
df13081f97 update URL 2021-10-21 22:56:45 +02:00
proddy
50f6d0ab26 fixes #166 2021-10-21 22:56:35 +02:00
proddy
fb7bafdb87 fix display of mqtt subscriptions 2021-10-20 09:34:50 +02:00
proddy
b3472c3919 add test for 'send' command 2021-10-20 09:21:12 +02:00
proddy
4f47712d52 minor formatting 2021-10-20 09:21:03 +02:00
MichaelDvP
547ccb96c9 Thermostat 0x65 to RC20_N, #160 2021-10-20 09:00:57 +02:00
proddy
7f3ff434ea add test for Dan "ems-esp/boiler/wwcircpump with payload off" 2021-10-19 18:36:35 +02:00
proddy
aad4b0ade3 change text about MQTT subscribe formats 2021-10-19 18:35:48 +02:00
proddy
d587f44ec9 updated 2021-10-19 18:35:33 +02:00
proddy
f30d3cf637 update test data for standalone 2021-10-19 18:35:24 +02:00
proddy
8fed47f39b fix case fall through for HA state_class 2021-10-19 17:40:46 +02:00
proddy
48cedbd0fb fix standalone building 2021-10-19 17:40:12 +02:00
proddy
752530a381 auto formatting 2021-10-19 17:39:44 +02:00
proddy
45fc6daa4a Add support for mDNS #161 2021-10-18 13:02:22 +02:00
MichaelDvP
e17ce9c3b5 Junkers modetype #163 2021-10-18 12:05:04 +02:00
MichaelDvP
2657b9d1a5 do not fetch broadcasted telegrams 0x14/0x19 (#160) 2021-10-18 11:29:50 +02:00
MichaelDvP
b77a56ade2 timeout 60s for KM200 wait #160, reset-reason to log 2021-10-18 11:28:43 +02:00
MichaelDvP
4d5f588748 reset reason to system info 2021-10-18 11:25:41 +02:00
Proddy
6582ba6317 added another Buderus RC10 - #160 2021-10-17 21:40:26 +02:00
Proddy
b3453d9d02 no need to recompile C++ code if Web code doesn't change 2021-10-16 12:50:56 +02:00
MichaelDvP
e4b73140c8 enlarge filesystem buffer 2021-10-14 18:55:50 +02:00
Proddy
235f789228 increase max dallas sensors from 10 to 20 - #157 2021-10-14 10:09:52 +02:00
Proddy
c029cf79f7 use smaller json key names, increase buffer size. fixes #157 2021-10-14 10:09:28 +02:00
Proddy
0b796a85a8 use DeviceValueUOM::TIMES for all 'starts' which count numerically 2021-10-12 15:00:42 +02:00
Proddy
d8191f79a4 removed # from comments 2021-10-12 15:00:16 +02:00
Proddy
6a259f7cca removed # from comments 2021-10-12 15:00:05 +02:00
Proddy
22a2b92022 added number formatting and pluralization for uom times and seconds 2021-10-12 14:59:53 +02:00
Proddy
25616ae3b4 added time to UOM and replaced seconds with second (pluralization handled in code) 2021-10-12 14:59:27 +02:00
Proddy
372aee30cd removed # in front of telegram count 2021-10-12 14:58:51 +02:00
Proddy
0c5023323a removed # (e.g in front of starts) 2021-10-12 14:58:30 +02:00
Proddy
2d1126b9e4 updated comment 2021-10-12 14:57:42 +02:00
Proddy
3ecf92fa41 add times as a new HA UOM - #156 2021-10-12 12:59:00 +02:00
Proddy
50befd8991 add HA device_class 2021-10-12 12:58:29 +02:00
Proddy
676268d7af rename rxread/txread to rxreads/txreads 2021-10-12 12:58:05 +02:00
Proddy
f2457a7050 auto-formatting 2021-10-11 16:53:00 +02:00
Proddy
ded90dc4ce minor text changes 2021-10-11 16:42:47 +02:00
Proddy
cddadcfae2 changes to allow restart command from API to complete before rebooting 2021-10-11 16:42:36 +02:00
Proddy
3113d392ac minor text changes 2021-10-11 16:41:44 +02:00
Proddy
6433d5f744 formatting 2021-10-11 16:41:24 +02:00
Proddy
f42c265714 minor text changes 2021-10-11 16:41:14 +02:00
Proddy
d6711ac850 always show a maintenancemessage even if there isn't one, so its not missing in the MQTT boiler_data payload 2021-10-10 20:29:03 +02:00
Proddy
9d7c2de1d5 rename HA icon mdi:flash-circle to mdi:lightning-bolt-circle 2021-10-10 20:11:52 +02:00
MichaelDvP
b1e1c44e77 add divider #136 2021-10-10 17:43:47 +02:00
MichaelDvP
85f54dd210 add current room influence #136 2021-10-10 09:18:52 +02:00
MichaelDvP
eea32ad134 add RC30 ww parameters, #117 2021-10-01 09:39:57 +02:00
MichaelDvP
4f24035082 add id to solar ww-circuit 2021-10-01 09:24:38 +02:00
MichaelDvP
0b0b1d9ca4 rename internal names wW/warmwater to ww 2021-09-29 14:42:34 +02:00
MichaelDvP
98828ed848 another typo 2021-09-29 12:55:51 +02:00
MichaelDvP
7b0f7cd32c fix typo wW->ww 2021-09-29 12:43:07 +02:00
Proddy
67cb778039 Merge pull request #135 from Sunbuzz/ft_add_connect
Added CONNECT device 0x236 "Wireless sensor base"
2021-09-29 12:11:25 +02:00
MichaelDvP
9f49afae0a read wwSelTemp/wwDisinfectionTemp from 0xEA, #96 2021-09-29 11:57:24 +02:00
sunbuzz
49c7c7aa2d Added CONNECT device 0x236 "Wireless sensor base" 2021-09-29 11:23:22 +02:00
Proddy
42d89d1d10 Merge pull request #134 from proddy/dev
Dev
2021-09-28 16:18:30 +02:00
proddy
24fae0d03e updated comment 2021-09-28 16:15:53 +02:00
proddy
2c337f1d03 fixed #129 2021-09-28 16:15:47 +02:00
MichaelDvP
fcc521d5ed enum thermostat programs, add junkers remote, program 2021-09-28 14:06:26 +02:00
MichaelDvP
91005876eb use device names from flash 2021-09-28 13:08:56 +02:00
proddy
da5b4aa79d add test for MQTT heatingactivated 2021-09-25 22:04:42 +02:00
proddy
ced440392b fix possible buffer overflow 2021-09-25 21:52:19 +02:00
proddy
33d7ba1fda reduce variable scope 2021-09-25 21:52:03 +02:00
proddy
a6095fc305 init poolShuntStatus__ as its not done in the constructor 2021-09-25 21:51:47 +02:00
proddy
84cc964a7a 3.2.2b8 2021-09-25 18:41:16 +02:00
Proddy
9e856b28a9 Merge pull request #130 from MichaelDvP/dev
use TAG_DEVICE_DATA_WW
2021-09-25 18:13:37 +02:00
MichaelDvP
9378fdf2b6 use TAG_DEVICE_DATA_WW 2021-09-25 10:00:06 +02:00
proddy
6a134dda1f Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2021-09-23 10:08:08 +02:00
MichaelDvP
4f927ee571 remove unused type from form 2021-09-23 08:48:59 +02:00
MichaelDvP
b111869422 remove invalid UOMs 2021-09-23 08:30:31 +02:00
proddy
89a249eae4 add breaking changes 2021-09-22 20:18:37 +02:00
MichaelDvP
7942d52843 npm audit fix 2021-09-22 15:13:11 +02:00
MichaelDvP
b6310302d2 add C2 error message, fix a uom 2021-09-22 15:12:58 +02:00
MichaelDvP
87774e73e1 fix some thermstat uoms 2021-09-22 15:12:05 +02:00
MichaelDvP
548b5ff4a1 remove unused check 2021-09-22 15:11:32 +02:00
proddy
80fedf3fa3 fix not showing dv is UOM is NONE 2021-09-22 14:53:50 +02:00
proddy
8523cdffa3 Merge branch 'ft_reacthooks' into dev 2021-09-21 18:11:55 +02:00
proddy
29f2335935 remove DeviceValueUOM::TEXT 2021-09-21 18:06:55 +02:00
proddy
eba6324d18 more API tests 2021-09-21 18:06:36 +02:00
proddy
c3874d7c95 remove DeviceValueUOM::TEXT 2021-09-21 18:06:25 +02:00
proddy
3086342d2b fix bug in nested json and added output targets 2021-09-21 18:05:36 +02:00
proddy
f836209249 added output target when rendering json 2021-09-21 18:04:48 +02:00
proddy
d4b06cf0c0 formatting 2021-09-21 18:04:25 +02:00
proddy
54199affc1 removed DeviceValueUOM::TEXT 2021-09-21 18:04:07 +02:00
proddy
4d88c6a90b add comments about nesting 2021-09-21 18:03:43 +02:00
proddy
906813b8f5 don't show handlers if there arn't any 2021-09-21 18:03:30 +02:00
proddy
30d1e7ecb4 bump version 2021-09-21 18:03:14 +02:00
proddy
8fab4e29bf use float instead of double 2021-09-21 18:03:05 +02:00
proddy
252554ea87 added comment about nesting 2021-09-21 18:02:52 +02:00
proddy
ba3d49172c updated packages 2021-09-21 18:02:40 +02:00
proddy
6ef8ff757a add check to prevent crash on null strings 2021-09-21 18:02:14 +02:00
MichaelDvP
fcc2c0b3de fastheatup as percent-value, enlarge parse-buffer #122 2021-09-21 08:04:11 +02:00
proddy
16e390f849 v3.3 2021-09-20 21:44:23 +02:00
proddy
a31cf53863 replace class components (HOCs) with React Hooks 2021-09-20 21:43:56 +02:00
proddy
09d8a6360b only use UOM of NONE for hidden Device Values 2021-09-20 21:43:05 +02:00
proddy
b1f59d4727 ignore UOM if its TEXT 2021-09-20 21:42:45 +02:00
proddy
d8add7edcb rename DeviceValueType::TEXT to STRING and ignore UOM if its NONE 2021-09-20 21:42:24 +02:00
proddy
1a71921fd6 remove debug 2021-09-20 21:41:48 +02:00
proddy
6d12fff4fe add API test 2021-09-20 21:41:29 +02:00
proddy
769301c804 rename boiltemp to 'actual boiler temperature' https://github.com/emsesp/EMS-ESP32/discussions/115 2021-09-20 13:52:37 +02:00
MichaelDvP
6a828e9ca5 Merge branch 'dev_' into dev 2021-09-20 09:04:57 +02:00
MichaelDvP
2516d2d6de add boiler disinfect command 2021-09-20 08:53:03 +02:00
MichaelDvP
e92a3ad025 add MM10 valvetime 2021-09-20 08:51:16 +02:00
MichaelDvP
5686094151 factor for charge duration 2021-09-20 08:49:57 +02:00
proddy
915749dd69 updated 2021-09-19 21:38:09 +02:00
proddy
258bc2b544 increase json before from 4KB to 16KB (EMSESP_JSON_SIZE_XXLARGE_DYN) 2021-09-19 21:33:49 +02:00
proddy
a9748f5b46 snprintf_P to snprintf() again 2021-09-19 21:33:15 +02:00
proddy
56f1c7946e snprintf_P rename 2021-09-19 21:32:51 +02:00
proddy
88a427578f rename snprintf_P, rename unit to uom 2021-09-19 21:32:35 +02:00
proddy
0ebd9e1fe1 make sure all std::strings are consts 2021-09-19 21:31:23 +02:00
proddy
bea0b4ba01 add entities command, only show master thermostat if >1 thermostats 2021-09-19 21:31:02 +02:00
proddy
f8bee9b5c5 formatting 2021-09-19 21:29:53 +02:00
proddy
500e089b97 for standalone ncrease mem due to compiler 2021-09-19 21:29:42 +02:00
proddy
2adef52abf add "entitied" as new command 2021-09-19 21:29:20 +02:00
proddy
e01bfe1bdf rename duplicate function publish_mqtt_ha_sensor 2021-09-19 21:29:03 +02:00
proddy
418b1b3d68 bump 2021-09-19 21:28:30 +02:00
proddy
401929d992 round2 use float instead of double (6 point precision is enough) 2021-09-19 21:28:21 +02:00
proddy
ee34dd72f7 rename snprintf_P to snprintf 2021-09-19 21:27:39 +02:00
proddy
b214d7a662 extended test for ha and entities command 2021-09-19 21:26:48 +02:00
proddy
079a40cd32 update to 16.18.4 2021-09-19 21:26:15 +02:00
proddy
adebea1561 add pseudo for snprintf_P 2021-09-19 21:25:54 +02:00
proddy
28bf7c3225 formatting 2021-09-19 11:21:01 +02:00
proddy
78b2efd148 add rounding test 2021-09-19 11:20:54 +02:00
MichaelDvP
11590061a3 fix wwcharge-command #112 2021-09-18 13:58:08 +02:00
proddy
09847ee33c fix: only set thermostat commands for master thermostat #110 2021-09-18 09:52:02 +02:00
MichaelDvP
db34785be0 add missing offset to telgram::to_string() 2021-09-16 17:14:22 +02:00
proddy
538a9cf642 mention RC25 support 2021-09-15 20:56:52 +02:00
proddy
d0346e436a remove PSTR() 2021-09-15 18:04:58 +02:00
Proddy
442202d978 Merge pull request #109 from MichaelDvP/dev
add RC300 second summermode telegram
2021-09-15 17:53:04 +02:00
MichaelDvP
3b2a89d9f4 solar turnOnOffDiff allow setting decimals #107 2021-09-15 10:54:57 +02:00
MichaelDvP
0bf366ac75 Divider for solar pumpOnOffDiff #107 2021-09-15 08:27:50 +02:00
proddy
c62e73d21e added HA state_class https://github.com/emsesp/EMS-ESP/issues/776 2021-09-13 20:45:56 +02:00
MichaelDvP
2889899bfd also add summertemp setting 2021-09-12 19:03:59 +02:00
MichaelDvP
f18ac2e48b add RC300 second summermode telegram 2021-09-12 18:48:33 +02:00
MichaelDvP
1d259d14c8 thermostat RC25 additions 2021-09-09 18:44:43 +02:00
MichaelDvP
b8c07e31cf mixer: add id to pool, sort registering, add commands 2021-09-09 11:33:57 +02:00
proddy
3f27ed7b18 auto-formatting 2021-09-08 19:53:07 +02:00
Proddy
d7678b340f Merge pull request #104 from Sunbuzz/pool
Pool
2021-09-08 12:18:21 +02:00
MichaelDvP
b697356465 add RC25, #106 2021-09-07 08:25:20 +02:00
sunbuzz
1b9a2f21d2 Increased EMSESP_JSON_SIZE_XXLARGE_DYN to 16384 (at 10635 right now) + small fixes 2021-09-03 15:01:05 +02:00
sunbuzz
e26451fcc0 reverted to TAG_NONE, added HP activities, added some json space 2021-09-02 15:25:37 +02:00
sunbuzz
17db542775 Fixed support for M P mixer i ha_config 2021-09-02 12:58:23 +02:00
sunbuzz
dd865a2db5 Fixed issues regarding pull request "Pool #104" 2021-09-02 12:40:39 +02:00
sunbuzz
834c7cb87f Added support for MP100 pool mixer (telegram 05BA), added brand IVT, added some parameters to telegram 0x48D & 0x48F 2021-09-01 22:06:50 +02:00
sunbuzz
a9a015cb5b Added support for MP100 pool mixer (telegram 05BA), added brand IVT, added some parameters to telegram 0x48D & 0x48F 2021-09-01 22:05:18 +02:00
MichaelDvP
94a71998a7 add some thermostat values 2021-08-30 14:11:55 +02:00
proddy
aa212924bc 3.2.2b2 2021-08-28 16:41:03 +02:00
Proddy
edef2f1bf6 Merge pull request #102 from Sunbuzz/pool
Added pool data to telegrams 0x494 & 0x495
2021-08-28 16:36:56 +02:00
proddy
912f53762e fix formatting (WARNING didnt fit) 2021-08-28 15:10:29 +02:00
proddy
02c04c8f41 updated images 2021-08-28 15:04:30 +02:00
sunbuzz
3ad90a6e34 Added pool data to telegrams 0x494 & 0x495 2021-08-28 12:03:05 +02:00
proddy
0f83870db0 auto-formatting 2021-08-26 10:42:40 +02:00
proddy
7529f3a73e minor text changes 2021-08-26 10:42:34 +02:00
MichaelDvP
77d559ac8c syslog re-add colon after message.id 2021-08-26 08:02:46 +02:00
MichaelDvP
1311cad913 add some boiler and thermostat parameters 2021-08-23 16:14:06 +02:00
MichaelDvP
4d1ba9bede remove tx-delay, wait for KM200 poll, v3.2.2b1 2021-08-23 13:43:32 +02:00
MichaelDvP
6b07651ed3 remove weblog download filter 2021-08-21 10:58:47 +02:00
MichaelDvP
50ddfc0437 store weblog settings, no log filtering, prevent double messages 2021-08-20 17:42:07 +02:00
MichaelDvP
c0ac485772 add date/time to Easy thermostat 2021-08-20 10:04:43 +02:00
MichaelDvP
8d4ae6971d fix #100 add missing hamode to EasyMonitor 2021-08-20 09:48:01 +02:00
Proddy
88d0dfee2d update changelog 2021-08-19 20:58:05 +02:00
Proddy
551a479c6b fix custom build options 2021-08-19 20:12:43 +02:00
MichaelDvP
3f85541c9a add system commands for syslog level and watch 2021-08-19 16:19:32 +02:00
MichaelDvP
74cdb610d8 fix#99, mqtt reconnect for IPv4 and IPv6 2021-08-19 15:27:41 +02:00
MichaelDvP
165dd3b418 fix #99, mqtt reconnect after wifi drop 2021-08-18 20:47:37 +02:00
MichaelDvP
7421f3e345 fix crash on response for empty telegrams 2021-08-17 16:06:20 +02:00
MichaelDvP
d00559bcd5 Fix compact weblog level-lable for trace 2021-08-16 07:32:35 +02:00
MichaelDvP
9774051fab Syslog BOM only for utf-8 messages, #91
Tested with extra message with udf-characters:
```
Aug 15 09:30:12 ems-esp32 emsesp 000+00:00:00.000 I 0 Starting Syslog
Aug 15 09:30:13 ems-esp32 emsesp 000+00:00:00.000 I 2 EMS Device library loaded with 79 records
Aug 15 09:30:13 ems-esp32 emsesp <BOM>000+00:00:00.000 I 3 Testing syslog with udf-8-chars: €öäü߀öäü߀öäüß
Aug 15 09:30:13 ems-esp32 emsesp 000+00:00:03.741 I 5 Starting NTP
```
2021-08-15 10:24:57 +02:00
proddy
c50692bae0 version 3.2.2b0 2021-08-14 13:45:26 +02:00
proddy
6348283001 fomatting 2021-08-14 13:41:35 +02:00
proddy
1cbd34d94e rename get_toggle_fetch -> is_fetch 2021-08-14 13:41:11 +02:00
proddy
f9d768a7a7 added clang-tidy 2021-08-14 13:40:21 +02:00
proddy
6c1bfccfaf text change 2021-08-10 09:23:04 +02:00
proddy
2ca0a0c634 v3.2.1 merged from dev 2021-08-08 14:46:14 +02:00
proddy
30ce3f1dc3 3.2.1 2021-08-08 14:45:24 +02:00
proddy
15541c52ce ww selected temperature sets the boilers target temp, not the wwSetTemp 2021-08-08 14:29:20 +02:00
proddy
20c3e8c7bd no need to set new temp in condition 2021-08-08 09:15:03 +02:00
proddy
59797fb89c comment cleanup 2021-08-07 21:47:38 +02:00
proddy
849cc85398 added FSTR_ and MAKE_STR for non-flash macros 2021-08-07 21:47:24 +02:00
proddy
dd318a1c8e always show tags, don't treat BOILER as a special case 2021-08-07 21:46:59 +02:00
proddy
2edf2a4231 disable mqtt function 2021-08-07 21:46:38 +02:00
proddy
d58ee1e693 renamed ww names 2021-08-07 21:46:22 +02:00
proddy
088cb7fe40 support for device in json body 2021-08-07 21:46:09 +02:00
proddy
38498a5587 updated API tests 2021-08-07 21:45:52 +02:00
proddy
6e3b30b03c renamed product ID, changed case for all ww names 2021-08-07 21:45:43 +02:00
proddy
4e9cf72816 3.2.1 2021-08-07 21:45:12 +02:00
proddy
7eb1f061b7 Merge remote-tracking branch 'origin/dev' for 3.2.0 release 2021-08-06 12:06:08 +02:00
proddy
5e4f5916f2 prep for 3.2.0 release 2021-08-06 12:01:42 +02:00
Proddy
1450737d94 make boiler id first in device registry, so it's first in MQTT payload 2021-08-03 13:28:04 +02:00
Proddy
bfd20e559e minor changes, make cppcheck happy 2021-08-03 13:23:33 +02:00
Proddy
98a7932dee optimizations 2021-08-03 13:23:09 +02:00
Proddy
19e26d0d64 don't show commands in web or console 2021-08-03 13:22:45 +02:00
Proddy
1715218864 update to b3 2021-08-03 13:22:13 +02:00
Proddy
e503c6cd79 remove msg moves 2021-08-03 13:22:02 +02:00
Proddy
9515e3d00b text changes 2021-08-03 13:21:43 +02:00
proddy
53e25ae213 lint warning changes 2021-08-01 23:44:40 +02:00
proddy
4863ecc329 add KB195i 2021-08-01 11:55:12 +02:00
proddy
b5892f5b5e text changes 2021-08-01 11:34:55 +02:00
proddy
d16502c872 auto-formatting 2021-08-01 11:34:48 +02:00
proddy
e29fb9ba8a updated 3.2.0b2 2021-07-29 16:55:36 +02:00
proddy
2ee0411582 text changes 2021-07-29 16:54:22 +02:00
proddy
f210466cb1 download buttons for settings 2021-07-29 16:54:08 +02:00
proddy
6af28b1c29 download button for log 2021-07-29 16:53:42 +02:00
proddy
049be2484e don't show dallas in system/info as its not an ems device 2021-07-29 16:53:06 +02:00
proddy
8f438e8045 rename add_json() 2021-07-29 16:52:33 +02:00
proddy
a8382dd6ce bump version 2021-07-29 16:52:06 +02:00
proddy
c55385d6d8 update mock data 2021-07-28 18:00:26 +02:00
proddy
87e6691433 remove comment 2021-07-28 18:00:14 +02:00
proddy
aa9ba65f70 comment changes 2021-07-28 10:40:17 +02:00
proddy
39fef48915 Update ArduinoJson to 6.18.3 2021-07-28 10:06:51 +02:00
proddy
362fead7e8 make standalone compile 2021-07-27 21:48:42 +02:00
proddy
e809ed3743 add max messages and make web log dynamic - #71 2021-07-27 21:44:12 +02:00
proddy
dc8c322b42 auto-formatting 2021-07-27 21:43:36 +02:00
proddy
c5688ab632 manually merge in official 0.9.0 version 2021-07-27 21:43:17 +02:00
proddy
d5d75eee63 remove comment 2021-07-27 21:42:37 +02:00
MichaelDvP
6ec16733c3 Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2021-07-26 11:55:06 +02:00
proddy
ce2b2658ad mention wwactivated fix 2021-07-26 11:49:42 +02:00
proddy
3a866b1aea fix browser warning 2021-07-26 11:46:26 +02:00
MichaelDvP
1cf938e16a Syslog host setting as ipv4 or hostname 2021-07-26 11:41:23 +02:00
MichaelDvP
1df427366f syslog add hostname, rename host_ to ip_, query status 2021-07-26 11:06:23 +02:00
MichaelDvP
f97cdcb4d6 fix #89
Also Norbert have 0xFF on his list.
2021-07-25 11:52:42 +02:00
proddy
15c682cd1e don't show CRC in log (irrelevant to most people) 2021-07-24 15:02:58 +02:00
proddy
008983be26 comment update 2021-07-24 15:02:12 +02:00
proddy
2f01000665 minor debug text changed 2021-07-24 15:01:53 +02:00
proddy
616955daef use system gpio adc 2021-07-24 12:02:45 +02:00
proddy
e22b191a48 comments, fix typos, prep for v3.2 2021-07-24 11:56:39 +02:00
MichaelDvP
8930c52ada analog input use calibrated mV 2021-07-23 12:09:41 +02:00
MichaelDvP
6d94335079 Fix crash on unknown commands (cf==nullptr) 2021-07-22 19:35:27 +02:00
proddy
f2e0b193af Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev 2021-07-22 13:52:09 +02:00
proddy
5b55902cd9 sync up with HA MQTT Discovery when dallas sensor changed #84 2021-07-22 13:51:59 +02:00
MichaelDvP
694f647a2c Command returns as enum 2021-07-22 13:00:16 +02:00
MichaelDvP
fc1cb00523 reload values after write and update 2021-07-22 12:54:02 +02:00
proddy
2fda59d7db latest asyncmqttclient dev changes - to safeguard against stuck connections 2021-07-21 16:25:42 +02:00
proddy
a95837404a valiadtion in sensor fields, auto refresh after change #84 2021-07-21 16:00:39 +02:00
proddy
c6db2a1adf label change 2021-07-21 15:59:44 +02:00
proddy
f6d22732a0 formatting 2021-07-21 15:59:29 +02:00
MichaelDvP
220a69938f fix mqtt individual subscriptions 2021-07-21 09:37:46 +02:00
proddy
d438866864 updated with log changes 2021-07-20 23:37:56 +02:00
proddy
2e0ed9ce9f fix error where eventsource wasn't flushed correctly & included the log ID 2021-07-20 23:36:49 +02:00
proddy
5de3b69e2c refresh sync changed from 200 to 300ms 2021-07-20 23:36:16 +02:00
proddy
dfd6798377 added log id and changed format layout 2021-07-20 23:35:52 +02:00
proddy
074ae2a5a1 some refactoring 2021-07-20 21:45:59 +02:00
proddy
77f6a18075 commands take a set of flags, like NEED_ADMIN or HIDDEN 2021-07-20 21:45:29 +02:00
proddy
0762d9e124 bump to b6 2021-07-20 21:43:03 +02:00
proddy
37dae04715 clean up ts 2021-07-20 13:01:56 +02:00
proddy
f299a7ad14 update calls to dallas library 2021-07-20 13:01:45 +02:00
proddy
ba295385ab rename allDevices endpoint to data. improve dallas sensor form 2021-07-20 13:01:22 +02:00
proddy
33adf518ae update 2021-07-20 13:00:01 +02:00
proddy
93885d0dd5 update 2021-07-20 12:59:48 +02:00
proddy
747cda79db rename add_name() to update(). show offset in log msg 2021-07-20 12:59:37 +02:00
proddy
f3cfc38adc update regex for ipv6 #83 2021-07-19 19:21:03 +02:00
proddy
dd3a0a706d auto-formatting 2021-07-19 16:55:41 +02:00
proddy
37d001e7b5 formatting 2021-07-19 16:44:53 +02:00
proddy
add09e5a1c update mock api to work with latest changes 2021-07-19 16:44:46 +02:00
Proddy
561d1c0e55 fix typo 2021-07-18 21:48:18 +02:00
proddy
239ba335b1 changes to make it compile standalone 2021-07-18 21:44:24 +02:00
proddy
ec83123090 rename Makefile 2021-07-18 21:43:25 +02:00
MichaelDvP
4f6d5164a4 Set sensornames from web 2021-07-18 20:42:02 +02:00
MichaelDvP
ae1e2eccd2 minExtTemp for RC300 2021-07-18 20:40:51 +02:00
MichaelDvP
d7bc821bbe calculate dallassensor offset 2021-07-17 06:50:13 +02:00
MichaelDvP
f8579f7c96 formatting 2021-07-16 16:45:38 +02:00
MichaelDvP
046a9ef6f2 show dallas-temperatures always with digit on web 2021-07-16 16:26:58 +02:00
MichaelDvP
64e15542a2 show api type of commands as command instead of unknown 2021-07-16 16:25:20 +02:00
MichaelDvP
7dec674452 moving dallas-setting, cleanup 2021-07-16 16:24:03 +02:00
MichaelDvP
0f48d3e72c add sensorname console command 2021-07-16 10:57:43 +02:00
MichaelDvP
1f793c49ae Move dallas/bool/enum formats to Settings #76 2021-07-16 10:16:32 +02:00
MichaelDvP
e581539cf9 Fix #78 2021-07-15 11:09:59 +02:00
MichaelDvP
736eee79df fix change-check 2021-07-14 18:10:04 +02:00
MichaelDvP
7a0fe3819b reset Settingsflags after update 2021-07-14 17:02:40 +02:00
MichaelDvP
65c9bf7e52 check bufferlength, add formatstrings 2021-07-14 17:00:14 +02:00
MichaelDvP
1e61b5670e delay in emsesp-loop as mentioned in #78 2021-07-11 15:50:15 +02:00
MichaelDvP
6c2bae6296 remove SM10 collector min/max wrong values 2021-07-11 15:19:51 +02:00
MichaelDvP
358d6010b0 Web selectbox for enum commands (like bool) 2021-07-11 15:02:24 +02:00
MichaelDvP
82978a25c5 show wwtapactivated as value 2021-07-11 14:42:12 +02:00
MichaelDvP
3519696bae add boiler ww-hysteresis, maintenance settings 2021-07-11 14:34:18 +02:00
MichaelDvP
bd33df2cc7 Junkers mode/set_mode synchronized 2021-07-11 14:15:39 +02:00
MichaelDvP
5f44eb14ad allow numbers for set_mode 2021-07-11 14:01:24 +02:00
MichaelDvP
fb94cf953a no enum numbers for "hamode" 2021-07-11 13:52:16 +02:00
MichaelDvP
d7486218bc enum start at zero 2021-07-11 13:50:56 +02:00
MichaelDvP
59913cdc4b disable bluetooth, show IPv6 in web, mqtt and console 2021-07-08 18:56:24 +02:00
MichaelDvP
2d7449aeba add network options, IPv6 for mqtt 2021-07-08 10:17:50 +02:00
proddy
3ea53a8012 updated doc and version 2021-07-07 09:19:01 +02:00
MichaelDvP
48cd12ec3d NTP time for weblog 2021-07-06 07:35:39 +02:00
MichaelDvP
7c71ed2dc6 fix mem leak 2021-07-06 07:35:15 +02:00
proddy
24d8ccc52f fix crash with IPv6 and ETH - #83 2021-07-05 22:55:39 +02:00
proddy
05cd96f2be IPv6 support by MichaelDvP - #83 2021-07-05 22:43:08 +02:00
proddy
75795ab1e9 fix shower on/off when using non-default MQTT booleans 2021-07-05 21:44:38 +02:00
proddy
bb1602f179 typo 2021-07-05 21:44:12 +02:00
proddy
ac268f0f73 lower WiFi tx when using -DEMSESP_WIFI_TWEAK 2021-07-05 21:44:04 +02:00
Proddy
d924567e5f include debug target 2021-07-05 16:55:23 +02:00
Proddy
109d8df782 don't show mem updates on EMSESP_DEBUG 2021-07-05 16:54:41 +02:00
Proddy
0aaa35098d remove obsolete scripts 2021-07-05 16:54:15 +02:00
Proddy
6f57beab28 cleanup build 2021-07-05 16:53:57 +02:00
Proddy
5b26e27834 Update to 16.8.1 2021-07-05 16:53:27 +02:00
Proddy
8429f650aa fix lint warnings 2021-07-03 20:32:46 +02:00
proddy
3eb2202117 add test to crash EMS-ESP 2021-07-03 20:20:56 +02:00
proddy
c217a40710 remove CRC in warning message 2021-07-03 20:20:43 +02:00
proddy
4a7308c5bb add linux commands 2021-07-03 20:20:27 +02:00
proddy
5fba51103e cleanup 2021-07-03 20:20:07 +02:00
proddy
95a9808f35 add debug target 2021-07-03 20:19:57 +02:00
proddy
c09e180c48 add linters 2021-07-03 20:19:43 +02:00
proddy
b09b650c1d remove # from dallas in api/system/info 2021-07-03 10:44:15 +02:00
proddy
44a41b963d add upload_sec to api/system/info and removed # from some names to keep consistent with MQTT heartbeat - #80 2021-07-02 16:24:50 +02:00
proddy
0510189f54 slow down MQTT reconnect to 2 seconds 2021-07-01 11:19:00 +02:00
MichaelDvP
16b3cf764d don't count wrong tx-echos as rx-errors 2021-07-01 09:34:34 +02:00
MichaelDvP
c634c39874 3. fix for mqtt enable (#79) 2021-06-30 14:26:46 +02:00
MichaelDvP
ae0846e877 mqtt connect on enable-change (#79) 2021-06-30 13:49:52 +02:00
MichaelDvP
40e7e1b418 always register subscriptions (#79) 2021-06-30 13:13:18 +02:00
proddy
e2a5853dde rename WIFI in System settings to Network 2021-06-29 22:57:21 +02:00
MichaelDvP
e419e67cb0 fix memory leak (#78) 2021-06-29 09:37:05 +02:00
proddy
3356a4ce14 fix v16 for nodejs 2021-06-26 11:14:45 +02:00
proddy
26a4347155 prep for 3.1.2 2021-06-26 11:05:04 +02:00
231 changed files with 10346 additions and 6037 deletions

152
.clang-tidy Normal file
View File

@@ -0,0 +1,152 @@
---
Checks: >-
*,
-abseil-*,
-android-*,
-boost-*,
-bugprone-branch-clone,
-bugprone-narrowing-conversions,
-bugprone-signed-char-misuse,
-bugprone-too-small-loop-variable,
-cert-dcl50-cpp,
-cert-err58-cpp,
-cert-oop57-cpp,
-cert-str34-c,
-clang-analyzer-optin.cplusplus.UninitializedObject,
-clang-analyzer-osx.*,
-clang-diagnostic-delete-abstract-non-virtual-dtor,
-clang-diagnostic-delete-non-abstract-non-virtual-dtor,
-clang-diagnostic-shadow-field,
-clang-diagnostic-sign-compare,
-clang-diagnostic-unused-variable,
-clang-diagnostic-unused-const-variable,
-cppcoreguidelines-avoid-c-arrays,
-cppcoreguidelines-avoid-goto,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-init-variables,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-narrowing-conversions,
-cppcoreguidelines-non-private-member-variables-in-classes,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-const-cast,
-cppcoreguidelines-pro-type-cstyle-cast,
-cppcoreguidelines-pro-type-member-init,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-static-cast-downcast,
-cppcoreguidelines-pro-type-union-access,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-special-member-functions,
-fuchsia-default-arguments,
-fuchsia-multiple-inheritance,
-fuchsia-overloaded-operator,
-fuchsia-statically-constructed-objects,
-fuchsia-default-arguments-declarations,
-fuchsia-default-arguments-calls,
-google-build-using-namespace,
-google-explicit-constructor,
-google-readability-braces-around-statements,
-google-readability-casting,
-google-readability-todo,
-google-runtime-references,
-hicpp-*,
-llvm-else-after-return,
-llvm-header-guard,
-llvm-include-order,
-llvm-qualified-auto,
-llvmlibc-*,
-misc-non-private-member-variables-in-classes,
-misc-no-recursion,
-misc-unused-parameters,
-modernize-avoid-c-arrays,
-modernize-return-braced-init-list,
-modernize-use-auto,
-modernize-use-default-member-init,
-modernize-use-equals-default,
-modernize-use-trailing-return-type,
-mpi-*,
-objc-*,
-readability-braces-around-statements,
-readability-const-return-type,
-readability-convert-member-functions-to-static,
-readability-else-after-return,
-readability-implicit-bool-conversion,
-readability-isolate-declaration,
-readability-magic-numbers,
-readability-make-member-function-const,
-readability-named-parameter,
-readability-qualified-auto,
-readability-redundant-access-specifiers,
-readability-redundant-member-init,
-readability-redundant-string-init,
-readability-uppercase-literal-suffix,
-readability-use-anyofallof,
-warnings-as-errors
WarningsAsErrors: '*'
AnalyzeTemporaryDtors: false
FormatStyle: google
CheckOptions:
- key: google-readability-braces-around-statements.ShortStatementLines
value: '1'
- key: google-readability-function-size.StatementThreshold
value: '800'
- key: google-readability-namespace-comments.ShortNamespaceLines
value: '10'
- key: google-readability-namespace-comments.SpacesBeforeComments
value: '2'
- key: modernize-loop-convert.MaxCopySize
value: '16'
- key: modernize-loop-convert.MinConfidence
value: reasonable
- key: modernize-loop-convert.NamingStyle
value: CamelCase
- key: modernize-pass-by-value.IncludeStyle
value: llvm
- key: modernize-replace-auto-ptr.IncludeStyle
value: llvm
- key: modernize-use-nullptr.NullMacros
value: 'NULL'
- key: readability-identifier-naming.LocalVariableCase
value: 'lower_case'
- key: readability-identifier-naming.ClassCase
value: 'CamelCase'
- key: readability-identifier-naming.StructCase
value: 'CamelCase'
- key: readability-identifier-naming.EnumCase
value: 'CamelCase'
- key: readability-identifier-naming.EnumConstantCase
value: 'UPPER_CASE'
- key: readability-identifier-naming.StaticConstantCase
value: 'UPPER_CASE'
- key: readability-identifier-naming.StaticVariableCase
value: 'UPPER_CASE'
- key: readability-identifier-naming.GlobalConstantCase
value: 'UPPER_CASE'
- key: readability-identifier-naming.ParameterCase
value: 'lower_case'
- key: readability-identifier-naming.PrivateMemberPrefix
value: 'NO_PRIVATE_MEMBERS_ALWAYS_USE_PROTECTED'
- key: readability-identifier-naming.PrivateMethodPrefix
value: 'NO_PRIVATE_METHODS_ALWAYS_USE_PROTECTED'
- key: readability-identifier-naming.ClassMemberCase
value: 'lower_case'
- key: readability-identifier-naming.ClassMemberCase
value: 'lower_case'
- key: readability-identifier-naming.ProtectedMemberCase
value: 'lower_case'
- key: readability-identifier-naming.ProtectedMemberSuffix
value: '_'
- key: readability-identifier-naming.FunctionCase
value: 'lower_case'
- key: readability-identifier-naming.ClassMethodCase
value: 'lower_case'
- key: readability-identifier-naming.ProtectedMethodCase
value: 'lower_case'
- key: readability-identifier-naming.ProtectedMethodSuffix
value: '_'
- key: readability-identifier-naming.VirtualMethodCase
value: 'lower_case'
- key: readability-identifier-naming.VirtualMethodSuffix
value: ''

View File

@@ -48,7 +48,7 @@ jobs:
uses: "marvinpinto/action-automatic-releases@latest" uses: "marvinpinto/action-automatic-releases@latest"
with: with:
repo_token: "${{ secrets.GITHUB_TOKEN }}" repo_token: "${{ secrets.GITHUB_TOKEN }}"
title: ESP32 Development Build v${{steps.build_info.outputs.version}} title: Development Build v${{steps.build_info.outputs.version}}
automatic_release_tag: "latest" automatic_release_tag: "latest"
prerelease: true prerelease: true
files: | files: |

4
.gitignore vendored
View File

@@ -27,4 +27,6 @@ emsesp
/interface/build /interface/build
node_modules node_modules
/interface/.eslintcache /interface/.eslintcache
test.sh
scripts/__pycache__
.temp

View File

@@ -5,10 +5,135 @@ 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.1.1] June 26 2021 # [3.3.1] January 20 2022
- lastcode broke MQTT JSON structure [#228](https://github.com/emsesp/EMS-ESP32/issues/228)
- overlapping while reading sequence of EMS1.0 telegrams
- redundant telegram readings (because of offset overflow)
- added missing RC30/Moduline400 [#243](https://github.com/emsesp/EMS-ESP32/issues/243)
- check received status before toggling fetch on empty telegram [#268][#282]
# [3.3.0] November 28 2021
## Added
- Add system commands for syslog level and watch [#98](https://github.com/emsesp/EMS-ESP32/issues/98)
- Added pool data to telegrams 0x494 & 0x495 [#102](https://github.com/emsesp/EMS-ESP32/issues/102)
- Add RC300 second summermode telegram [#108](https://github.com/emsesp/EMS-ESP32/issues/108)
- Add support for the RC25 thermostat [#106](https://github.com/emsesp/EMS-ESP32/issues/106)
- Add new command 'entities' for a device, e.g. http://ems-esp/api/boiler/entities to show the shortname, description and HA Entity name (if HA enabled) [#116](https://github.com/emsesp/EMS-ESP32/issues/116)
- Support for Junkers program and remote (fb10/fb110) temperature
- Home Assistant `state_class` attribute for Wh, kWh, W and KW [#129](https://github.com/emsesp/EMS-ESP32/issues/129)
- Add current room influence for RC300 [#136](https://github.com/emsesp/EMS-ESP32/issues/136)
- Added Home Assistant device_class to sensor entities
- Added another Buderus RC10 thermostat with Product ID 65 [#160](https://github.com/emsesp/EMS-ESP32/issues/160)
- Added support for mDNS [#161](https://github.com/emsesp/EMS-ESP32/issues/161)
- Added last system ESP32 reset code to log (and `system info` output)
- Firmware Checker in WebUI [#168](https://github.com/emsesp/EMS-ESP32/issues/168)
- Added new MQTT setting for enabling 'response' topic
- Support for non-standard Thermostats like Tado [#174](https://github.com/emsesp/EMS-ESP32/issues/174)
- Include MQTT connection status in 'api/system/info'
- Include Network status in 'api/system/info' and also the MQTT topic `info` [#202](https://github.com/emsesp/EMS-ESP32/issues/202)
- Added Ethernet PHY module as an option in the Board Profile [#210](https://github.com/emsesp/EMS-ESP32/issues/210)
## Fixed
- MQTT reconnecting after WiFi reconnect [#99](https://github.com/emsesp/EMS-ESP32/issues/99)
- Manually Controlling Solar Circuit [#107](https://github.com/emsesp/EMS-ESP32/issues/107)
- Fix thermostat commands not defaulting to the master thermostat [#110](https://github.com/emsesp/EMS-ESP32/issues/110)
- Enlarge parse-buffer for long names like `cylinderpumpmodulation`
- MQTT not subscribing to all device entities [#166](https://github.com/emsesp/EMS-ESP32/issues/166)
- Help fix issues with WebUI unable to fully load UI over Ethernet [#177](https://github.com/emsesp/EMS-ESP32/issues/177)
- Shower alert never reset after limit reached when enabled [(PR #185)]
- Remove HA entity entries when a device value goes dormant [#196](https://github.com/emsesp/EMS-ESP32/issues/196)
- deciphering last error code dates on 0xC2 telegram [#204](https://github.com/emsesp/EMS-ESP32/issues/204)
## Changed ## Changed
- Syslog BOM only for utf-8 messages [#91](https://github.com/emsesp/EMS-ESP32/issues/91)
- Check for KM200 by device-id 0x48, remove tx-delay [#90](https://github.com/emsesp/EMS-ESP32/issues/90)
- rename `fastheatupfactor` to `fastheatup` and add percent [#122](https://github.com/emsesp/EMS-ESP32/issues/122)
- "unit" renamed to "uom" in API call to recall a Device Value
- initial backend React changes to replace the class components (HOCs) with React Hooks
- Use program-names instead of numbers
- Boiler's maintenancemessage always published in MQTT (to prevent HA missing entity)
- Unit of Measure 'times' added to MQTT Fails, Rx fails, Rx received, Tx fails, Tx reads & Tx writes
- Improved API. Restful HTTP API works in the same way as MQTT calls
- Removed settings for MQTT subscribe format [#173](https://github.com/emsesp/EMS-ESP32/issues/173)
- Improve Nefit Moduline 200 functionality [#183](https://github.com/emsesp/EMS-ESP32/issues/183)
- `status` in the MQTT heartbeat renamed to `bus_status`
- Layout changes in the WebUI, showing stripped table rows in Dashboard
- Alternative font for log window [#219](https://github.com/emsesp/EMS-ESP32/issues/219)
## **BREAKING CHANGES**
- API: "unit" renamed to "uom" in API call to recall a Device Value
- HA: `sensor.boiler_boiler_temperature` renamed to `sensor.actual_boiler_temperature`
- HA: `binary_sensor.boiler_ww_disinfecting` renamed to `binary_sensor.boiler_ww_disinfection`
- HA: # removed from counts in MQTT Fails, Rx fails, Rx received, Tx fails, Tx reads & Tx writes
- `txread` renamed to `txreads` and `txwrite` renamed to `txwrites` in MQTT heartbeat payload
- 'dallas sensors' in api/system/info moved to the "System" section. Renamed "uptime (seconds)" and "reset reason"
- `status` in the MQTT heartbeat renamed to `bus_status`
# [3.2.1] August 8 2021
## Added
- json body in API can now take device, name, cmd, hc and id
- added example of how to use API directly to control values from Home Assistant
- API calls are shown in debug log (For troubleshooting)
## Fixed
- fixed issue with Home Assistant entity naming where boiler's ww was duplicated in entity name
- fixed issue where wwSetTemp was written too instead of wwSelTemp
## Changed
- fixed case on mqtt names, like 'wwtankmiddletemp'
- renamed Product ID to 'EMS Product ID' in Home Assistant
- removed brackets around tags, e.g. (hc1) selected room temperature" is now just "hc1 selected room temperature"
# [3.2.0] August 6 2021
## Added
- support for IPv6 (web/api/mqtt, not syslog yet) [#83](https://github.com/emsesp/EMS-ESP32/issues/83)
- System Log in Web UI will show current time if the NTP Service is enabled [#82](https://github.com/emsesp/EMS-ESP32/issues/82)
- Network settings for Tx-power, WiFi-bandwidth, WiFi-sleepmode [#83](https://github.com/emsesp/EMS-ESP32/issues/83)
- optional low CPU clockrate (160 MHz) [#83](https://github.com/emsesp/EMS-ESP32/issues/83)
- select format for enumerated values in web
- settings for water hysteresis on/off
- dallas sensor name editable. `sensorname` console-command, replace sensorid with a unique name [#84](https://github.com/emsesp/EMS-ESP32/issues/84)
- 'restart' system command. Can be invoked via API with authentication. [#87](https://github.com/emsesp/EMS-ESP32/issues/87)
- add Download button in Web UI for log
## Fixed
- set mode allow numbers
- Junkers thermostat shows mode as selected by set_mode
- HA thermostat mode if bool-format: numbers is selected
- Web UI System Log sometimes skipped a few log messages when watching real-time
- fix wwactivated [#89](https://github.com/emsesp/EMS-ESP32/issues/89)
- don't show commands (like reset) as Device values in the Web or Console
## Changed
- removed Rx echo failures counting as incomplete telegrams. Bad telegrams show as Warning and not Errors. [#80](https://github.com/emsesp/EMS-ESP32/issues/80)
- add upload_sec to `api/system/info` and removed # from some names to keep consistent with MQTT heartbeat
- added debug target to PlatformIO build to help hunt down system crashes
- enumerated values always start at zero
- maintenance settings for time/date as extra setting
- move api/mqtt formats to `settings`, add `enum format`
- UI improvements for editing Dallas Sensor details
- RESTful GET commands can also require authentication (via bearer access token) for better security
- Updated AsyncMqttClient to 0.9.0 and ArduinoJson to 6.18.3
- Download buttons for settings and info under the Help tab
# [3.1.1] June 26 2021
## Added
- new command called `commands` which lists all available commands. `ems-esp/api/{device}/commands` - new command called `commands` which lists all available commands. `ems-esp/api/{device}/commands`
- More Home Assistant icons to match the UOMs - More Home Assistant icons to match the UOMs
- new API. Using secure access tokens and OpenAPI standard. See `doc/EMS-ESP32 API.md` and [#50](https://github.com/emsesp/EMS-ESP32/issues/50) - new API. Using secure access tokens and OpenAPI standard. See `doc/EMS-ESP32 API.md` and [#50](https://github.com/emsesp/EMS-ESP32/issues/50)
@@ -29,7 +154,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# [3.1.0] May 4 2021 # [3.1.0] May 4 2021
## Changed ## Added
- Mock API to simulate an ESP, for testing web - Mock API to simulate an ESP, for testing web
- Able to write values from the Web UI - Able to write values from the Web UI

View File

@@ -1,9 +0,0 @@
# Changelog
## Added
## Fixed
## Changed
## Removed

View File

@@ -24,17 +24,17 @@ This document describes rules that are in effect for this repository, meant for
## Triaging of Issues/PR's ## Triaging of Issues/PR's
1. Any contributor to the project can participate in the triaging process, if he/she chooses to do so. 1. Any contributor to the project can participate in the triaging process, if he/she chooses to do so.
2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor. 2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor.
3. Issues that are accepted should be marked with appropriate labels. 3. Issues that are accepted should be marked with appropriate labels.
4. Issues that could impact functionality for many users should be considered severe. 4. Issues that could impact functionality for many users should be considered severe.
5. Issues caused by the SDK or chip should not be marked severe, as there usually isnt much to be done. Common sense should be applied when deciding. Such issues should be documented in the documentation, for reference by users. 5. Issues caused by the SDK or chip should not be marked severe, as there usually isnt much to be done. Common sense should be applied when deciding. Such issues should be documented in the documentation, for reference by users.
6. Issues with feature requests should be discussed for viability/desirability. 6. Issues with feature requests should be discussed for viability/desirability.
7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified. 7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified.
8. Feature requests that are not accompanied by a PR: 8. Feature requests that are not accompanied by a PR:
* could be closed immediately (denied). - could be closed immediately (denied).
* could be closed after some predetermined period of time (left as candidate for somebody to pick up). - could be closed after some predetermined period of time (left as candidate for somebody to pick up).
9. In some cases, feedback may be requested from the issue reporter, either as additional info for clarification, additional testing, or other. If no feedback is provided, the issue may be closed by a contributor or after 40 days by the STALE bot. 9. In some cases, feedback may be requested from the issue reporter, either as additional info for clarification, additional testing, or other. If no feedback is provided, the issue may be closed by a contributor or after 40 days by the STALE bot.
## Pull requests ## Pull requests
@@ -42,24 +42,24 @@ A Pull Request (PR) is the process where code modifications are managed in GitHu
The process is straight-forward. The process is straight-forward.
- Read [How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) by Kubernetes (but skip step 0) - Read [How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) by Kubernetes (but skip step 0)
- Fork the EMS-ESP Repository [git repository](https://github.com/emsesp/EMS-ESP32). - Fork the EMS-ESP Repository [git repository](https://github.com/emsesp/EMS-ESP32).
- Write/Change the code in your Fork for a new feature, bug fix, new sensor, optimization, etc. - Write/Change the code in your Fork for a new feature, bug fix, new sensor, optimization, etc.
- Ensure tests work. - Ensure tests work.
- Create a Pull Request against the [**dev**](https://github.com/emsesp/EMS-ESP32/tree/dev) branch of EMS-ESP. - Create a Pull Request against the [**dev**](https://github.com/emsesp/EMS-ESP32/tree/dev) branch of EMS-ESP.
1. All pull requests must be done against the dev branch. 1. All pull requests must be done against the dev branch.
2. Make sure code is formatting per the `.clang-format` 2. Make sure code is formatting per the `.clang-format`.
3. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled). 3. Make sure any new code is clearly commented explaining what the function/logic does.
4. Only one feature/fix should be added per PR. 4. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled).
5. PRs that don't compile (fail in CI Tests) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in dev - you might need to rebase and resolve conflicts. 5. Only one feature/fix should be added per PR.
6. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner. 6. PRs that don't compile (fail in CI Tests) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in dev - you might need to rebase and resolve conflicts.
7. All pull requests should consider updates to the documentation. 7. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner.
8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. 8. All pull requests should consider updates to the documentation.
9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. 9. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority.
10. By submitting a PR, it is needed to use the provided PR template and check all boxes, performing the required tasks and accepting the CLA. 10. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged.
11. Pull requests that don't meet the above will be denied and closed. 11. By submitting a PR, it is needed to use the provided PR template and check all boxes, performing the required tasks and accepting the CLA.
12. Pull requests that don't meet the above will be denied and closed.
## Semantic Commit Messages ## Semantic Commit Messages
@@ -92,7 +92,7 @@ More Examples:
References: References:
- https://www.conventionalcommits.org/ - <https://www.conventionalcommits.org/>
-------------------------------------- --------------------------------------

View File

@@ -33,7 +33,7 @@ CXX_STANDARD := -std=c++11
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Defined Symbols # Defined Symbols
#---------------------------------------------------------------------- #----------------------------------------------------------------------
DEFINES += -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_DEFAULT_BOARD_PROFILE=\"LOLIN\" DEFINES += -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_DEFAULT_BOARD_PROFILE=\"LOLIN\"
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Sources & Files # Sources & Files
@@ -72,9 +72,9 @@ CPPFLAGS += -g3
CPPFLAGS += -Os CPPFLAGS += -Os
CFLAGS += $(CPPFLAGS) CFLAGS += $(CPPFLAGS)
# CFLAGS += -Wall CFLAGS += -Wall
# CFLAGS += -Wno-unused -Wno-restrict CFLAGS += -Wno-unused -Wno-restrict
# CFLAGS += -Wextra CFLAGS += -Wextra
CXXFLAGS += $(CFLAGS) -MMD CXXFLAGS += $(CFLAGS) -MMD

View File

@@ -1,6 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags # Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000, nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000, otadata, data, ota, 0xE000, 0x2000,
app0, app, ota_0, 0x10000, 0x1F0000, app0, app, ota_0, 0x10000, 0x1F0000,
app1, app, ota_1, 0x200000, 0x1F0000, app1, app, ota_1, 0x200000, 0x1F0000,
spiffs, data, spiffs, 0x3F0000,0x10000, spiffs, data, spiffs, 0x3F0000, 0x10000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0xE000 0x2000
4 app0 app ota_0 0x10000 0x1F0000
5 app1 app ota_1 0x200000 0x1F0000
6 spiffs data spiffs 0x3F0000 0x10000

View File

@@ -0,0 +1,5 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xE000, 0x2000,
app0, app, ota_0, 0x10000, 0x210000,
spiffs, data, spiffs, 0x220000, 0x10000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xE000 0x2000
4 app0 app ota_0 0x10000 0x210000
5 spiffs data spiffs 0x220000 0x10000

View File

@@ -8,13 +8,13 @@
"name": "emsesp-react", "name": "emsesp-react",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@material-ui/core": "^4.11.4", "@material-ui/core": "^4.12.3",
"@material-ui/icons": "^4.11.2", "@material-ui/icons": "^4.11.2",
"@msgpack/msgpack": "^2.7.0", "@msgpack/msgpack": "^2.7.0",
"@types/lodash": "^4.14.168", "@types/lodash": "^4.14.172",
"@types/node": "^15.0.1", "@types/node": "^12.20.20",
"@types/react": "^17.0.4", "@types/react": "^17.0.19",
"@types/react-dom": "^17.0.3", "@types/react-dom": "^17.0.9",
"@types/react-material-ui-form-validator": "^2.1.0", "@types/react-material-ui-form-validator": "^2.1.0",
"@types/react-router": "^5.1.13", "@types/react-router": "^5.1.13",
"@types/react-router-dom": "^5.1.7", "@types/react-router-dom": "^5.1.7",
@@ -35,7 +35,7 @@
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
"sockette": "^2.0.6", "sockette": "^2.0.6",
"typescript": "4.2.4", "typescript": "4.3.5",
"zlib": "^1.0.5" "zlib": "^1.0.5"
}, },
"devDependencies": { "devDependencies": {
@@ -2050,13 +2050,13 @@
} }
}, },
"node_modules/@material-ui/core": { "node_modules/@material-ui/core": {
"version": "4.11.4", "version": "4.12.3",
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.4.tgz", "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz",
"integrity": "sha512-oqb+lJ2Dl9HXI9orc6/aN8ZIAMkeThufA5iZELf2LQeBn2NtjVilF5D2w7e9RpntAzDb4jK5DsVhkfOvFY/8fg==", "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.4.4", "@babel/runtime": "^7.4.4",
"@material-ui/styles": "^4.11.4", "@material-ui/styles": "^4.11.4",
"@material-ui/system": "^4.11.3", "@material-ui/system": "^4.12.1",
"@material-ui/types": "5.1.0", "@material-ui/types": "5.1.0",
"@material-ui/utils": "^4.11.2", "@material-ui/utils": "^4.11.2",
"@types/react-transition-group": "^4.2.0", "@types/react-transition-group": "^4.2.0",
@@ -2137,9 +2137,9 @@
} }
}, },
"node_modules/@material-ui/system": { "node_modules/@material-ui/system": {
"version": "4.11.3", "version": "4.12.1",
"resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.11.3.tgz", "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz",
"integrity": "sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw==", "integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.4.4", "@babel/runtime": "^7.4.4",
"@material-ui/utils": "^4.11.2", "@material-ui/utils": "^4.11.2",
@@ -2148,6 +2148,20 @@
}, },
"engines": { "engines": {
"node": ">=8.0.0" "node": ">=8.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/material-ui"
},
"peerDependencies": {
"@types/react": "^16.8.6 || ^17.0.0",
"react": "^16.8.0 || ^17.0.0",
"react-dom": "^16.8.0 || ^17.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
} }
}, },
"node_modules/@material-ui/types": { "node_modules/@material-ui/types": {
@@ -2639,9 +2653,9 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
}, },
"node_modules/@types/lodash": { "node_modules/@types/lodash": {
"version": "4.14.168", "version": "4.14.173",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.173.tgz",
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==" "integrity": "sha512-vv0CAYoaEjCw/mLy96GBTnRoZrSxkGE0BKzKimdR8P3OzrNYNvBgtW7p055A+E8C31vXNUhWKoFCbhq7gbyhFg=="
}, },
"node_modules/@types/material-ui": { "node_modules/@types/material-ui": {
"version": "0.21.8", "version": "0.21.8",
@@ -2658,9 +2672,9 @@
"integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==" "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA=="
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "15.0.1", "version": "12.20.25",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.25.tgz",
"integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==" "integrity": "sha512-hcTWqk7DR/HrN9Xe7AlJwuCaL13Vcd9/g/T54YrJz4Q3ESM5mr33YCzW2bOfzSIc3aZMeGBvbLGvgN6mIJ0I5Q=="
}, },
"node_modules/@types/normalize-package-data": { "node_modules/@types/normalize-package-data": {
"version": "2.4.0", "version": "2.4.0",
@@ -2688,9 +2702,9 @@
"integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==" "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "17.0.4", "version": "17.0.22",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.22.tgz",
"integrity": "sha512-onz2BqScSFMoTRdJUZUDD/7xrusM8hBA2Fktk2qgaTYPCgPvWnDEgkrOs8hhPUf2jfcIXkJ5yK6VfYormJS3Jw==", "integrity": "sha512-kq/BMeaAVLJM6Pynh8C2rnr/drCK+/5ksH0ch9asz+8FW3DscYCIEFtCeYTFeIx/ubvOsMXmRfy7qEJ76gM96A==",
"dependencies": { "dependencies": {
"@types/prop-types": "*", "@types/prop-types": "*",
"@types/scheduler": "*", "@types/scheduler": "*",
@@ -2706,9 +2720,9 @@
} }
}, },
"node_modules/@types/react-dom": { "node_modules/@types/react-dom": {
"version": "17.0.3", "version": "17.0.9",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.3.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz",
"integrity": "sha512-4NnJbCeWE+8YBzupn/YrJxZ8VnjcJq5iR1laqQ1vkpQgBiA7bwk0Rp24fxsdNinzJY2U+HHS4dJJDPdoMjdJ7w==", "integrity": "sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg==",
"dependencies": { "dependencies": {
"@types/react": "*" "@types/react": "*"
} }
@@ -4339,6 +4353,15 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"optional": true,
"dependencies": {
"file-uri-to-path": "1.0.0"
}
},
"node_modules/bluebird": { "node_modules/bluebird": {
"version": "3.7.2", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -4764,9 +4787,9 @@
} }
}, },
"node_modules/cacheable-request/node_modules/normalize-url": { "node_modules/cacheable-request/node_modules/normalize-url": {
"version": "4.5.0", "version": "4.5.1",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
"integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -8419,6 +8442,12 @@
"node": ">= 10" "node": ">= 10"
} }
}, },
"node_modules/file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"optional": true
},
"node_modules/filesize": { "node_modules/filesize": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz", "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz",
@@ -8860,6 +8889,19 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
}, },
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -13252,6 +13294,12 @@
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
}, },
"node_modules/nan": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
"optional": true
},
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.1.23", "version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
@@ -14247,9 +14295,9 @@
} }
}, },
"node_modules/path-parse": { "node_modules/path-parse": {
"version": "1.0.6", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
}, },
"node_modules/path-to-regexp": { "node_modules/path-to-regexp": {
"version": "0.1.7", "version": "0.1.7",
@@ -14499,9 +14547,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"dependencies": { "dependencies": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@@ -14509,6 +14557,10 @@
}, },
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
} }
}, },
"node_modules/postcss-attribute-case-insensitive": { "node_modules/postcss-attribute-case-insensitive": {
@@ -16948,9 +17000,9 @@
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
}, },
"node_modules/resolve-url-loader": { "node_modules/resolve-url-loader": {
"version": "3.1.3", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.3.tgz", "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.4.tgz",
"integrity": "sha512-WbDSNFiKPPLem1ln+EVTE+bFUBdTTytfQZWbmghroaFNFaAVmGq0Saqw6F/306CwgPXsGwXVxbODE+3xAo/YbA==", "integrity": "sha512-D3sQ04o0eeQEySLrcz4DsX3saHfsr8/N6tfhblxgZKXxMT2Louargg12oGNfoTRLV09GXhVUe5/qgA5vdgNigg==",
"dependencies": { "dependencies": {
"adjust-sourcemap-loader": "3.0.0", "adjust-sourcemap-loader": "3.0.0",
"camelcase": "5.3.1", "camelcase": "5.3.1",
@@ -16958,7 +17010,7 @@
"convert-source-map": "1.7.0", "convert-source-map": "1.7.0",
"es6-iterator": "2.0.3", "es6-iterator": "2.0.3",
"loader-utils": "1.2.3", "loader-utils": "1.2.3",
"postcss": "7.0.21", "postcss": "7.0.36",
"rework": "1.0.1", "rework": "1.0.1",
"rework-visit": "1.0.0", "rework-visit": "1.0.0",
"source-map": "0.6.1" "source-map": "0.6.1"
@@ -17007,19 +17059,6 @@
"node": ">=4.0.0" "node": ">=4.0.0"
} }
}, },
"node_modules/resolve-url-loader/node_modules/postcss": {
"version": "7.0.21",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz",
"integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==",
"dependencies": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
"supports-color": "^6.1.0"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/resolve-url-loader/node_modules/source-map": { "node_modules/resolve-url-loader/node_modules/source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -17028,17 +17067,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/resolve-url-loader/node_modules/supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/responselike": { "node_modules/responselike": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
@@ -18669,9 +18697,9 @@
} }
}, },
"node_modules/tar": { "node_modules/tar": {
"version": "6.1.0", "version": "6.1.11",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
"integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
"dependencies": { "dependencies": {
"chownr": "^2.0.0", "chownr": "^2.0.0",
"fs-minipass": "^2.0.0", "fs-minipass": "^2.0.0",
@@ -19249,9 +19277,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.2.4", "version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
"integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@@ -19570,9 +19598,9 @@
} }
}, },
"node_modules/url-parse": { "node_modules/url-parse": {
"version": "1.5.1", "version": "1.5.3",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz",
"integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==",
"dependencies": { "dependencies": {
"querystringify": "^2.1.1", "querystringify": "^2.1.1",
"requires-port": "^1.0.0" "requires-port": "^1.0.0"
@@ -20086,6 +20114,24 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/webpack-dev-server/node_modules/fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"dependencies": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
},
"engines": {
"node": ">= 4.0"
}
},
"node_modules/webpack-dev-server/node_modules/glob-parent": { "node_modules/webpack-dev-server/node_modules/glob-parent": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
@@ -23150,13 +23196,13 @@
} }
}, },
"@material-ui/core": { "@material-ui/core": {
"version": "4.11.4", "version": "4.12.3",
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.4.tgz", "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz",
"integrity": "sha512-oqb+lJ2Dl9HXI9orc6/aN8ZIAMkeThufA5iZELf2LQeBn2NtjVilF5D2w7e9RpntAzDb4jK5DsVhkfOvFY/8fg==", "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==",
"requires": { "requires": {
"@babel/runtime": "^7.4.4", "@babel/runtime": "^7.4.4",
"@material-ui/styles": "^4.11.4", "@material-ui/styles": "^4.11.4",
"@material-ui/system": "^4.11.3", "@material-ui/system": "^4.12.1",
"@material-ui/types": "5.1.0", "@material-ui/types": "5.1.0",
"@material-ui/utils": "^4.11.2", "@material-ui/utils": "^4.11.2",
"@types/react-transition-group": "^4.2.0", "@types/react-transition-group": "^4.2.0",
@@ -23200,9 +23246,9 @@
} }
}, },
"@material-ui/system": { "@material-ui/system": {
"version": "4.11.3", "version": "4.12.1",
"resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.11.3.tgz", "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz",
"integrity": "sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw==", "integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==",
"requires": { "requires": {
"@babel/runtime": "^7.4.4", "@babel/runtime": "^7.4.4",
"@material-ui/utils": "^4.11.2", "@material-ui/utils": "^4.11.2",
@@ -23611,9 +23657,9 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
}, },
"@types/lodash": { "@types/lodash": {
"version": "4.14.168", "version": "4.14.173",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.173.tgz",
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==" "integrity": "sha512-vv0CAYoaEjCw/mLy96GBTnRoZrSxkGE0BKzKimdR8P3OzrNYNvBgtW7p055A+E8C31vXNUhWKoFCbhq7gbyhFg=="
}, },
"@types/material-ui": { "@types/material-ui": {
"version": "0.21.8", "version": "0.21.8",
@@ -23630,9 +23676,9 @@
"integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==" "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA=="
}, },
"@types/node": { "@types/node": {
"version": "15.0.1", "version": "12.20.25",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.25.tgz",
"integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==" "integrity": "sha512-hcTWqk7DR/HrN9Xe7AlJwuCaL13Vcd9/g/T54YrJz4Q3ESM5mr33YCzW2bOfzSIc3aZMeGBvbLGvgN6mIJ0I5Q=="
}, },
"@types/normalize-package-data": { "@types/normalize-package-data": {
"version": "2.4.0", "version": "2.4.0",
@@ -23660,9 +23706,9 @@
"integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==" "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
}, },
"@types/react": { "@types/react": {
"version": "17.0.4", "version": "17.0.22",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.22.tgz",
"integrity": "sha512-onz2BqScSFMoTRdJUZUDD/7xrusM8hBA2Fktk2qgaTYPCgPvWnDEgkrOs8hhPUf2jfcIXkJ5yK6VfYormJS3Jw==", "integrity": "sha512-kq/BMeaAVLJM6Pynh8C2rnr/drCK+/5ksH0ch9asz+8FW3DscYCIEFtCeYTFeIx/ubvOsMXmRfy7qEJ76gM96A==",
"requires": { "requires": {
"@types/prop-types": "*", "@types/prop-types": "*",
"@types/scheduler": "*", "@types/scheduler": "*",
@@ -23685,9 +23731,9 @@
} }
}, },
"@types/react-dom": { "@types/react-dom": {
"version": "17.0.3", "version": "17.0.9",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.3.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.9.tgz",
"integrity": "sha512-4NnJbCeWE+8YBzupn/YrJxZ8VnjcJq5iR1laqQ1vkpQgBiA7bwk0Rp24fxsdNinzJY2U+HHS4dJJDPdoMjdJ7w==", "integrity": "sha512-wIvGxLfgpVDSAMH5utdL9Ngm5Owu0VsGmldro3ORLXV8CShrL8awVj06NuEXFQ5xyaYfdca7Sgbk/50Ri1GdPg==",
"requires": { "requires": {
"@types/react": "*" "@types/react": "*"
} }
@@ -25105,6 +25151,15 @@
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
}, },
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bluebird": { "bluebird": {
"version": "3.7.2", "version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -25476,9 +25531,9 @@
"dev": true "dev": true
}, },
"normalize-url": { "normalize-url": {
"version": "4.5.0", "version": "4.5.1",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
"integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
"dev": true "dev": true
} }
} }
@@ -28464,6 +28519,12 @@
"tslib": "^2.0.3" "tslib": "^2.0.3"
} }
}, },
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"optional": true
},
"filesize": { "filesize": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz", "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz",
@@ -28843,6 +28904,12 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
}, },
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"optional": true
},
"function-bind": { "function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -32383,6 +32450,12 @@
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
}, },
"nan": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
"optional": true
},
"nanoid": { "nanoid": {
"version": "3.1.23", "version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
@@ -33197,9 +33270,9 @@
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
}, },
"path-parse": { "path-parse": {
"version": "1.0.6", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
}, },
"path-to-regexp": { "path-to-regexp": {
"version": "0.1.7", "version": "0.1.7",
@@ -33389,9 +33462,9 @@
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
}, },
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
"source-map": "^0.6.1", "source-map": "^0.6.1",
@@ -35421,9 +35494,9 @@
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
}, },
"resolve-url-loader": { "resolve-url-loader": {
"version": "3.1.3", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.3.tgz", "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.4.tgz",
"integrity": "sha512-WbDSNFiKPPLem1ln+EVTE+bFUBdTTytfQZWbmghroaFNFaAVmGq0Saqw6F/306CwgPXsGwXVxbODE+3xAo/YbA==", "integrity": "sha512-D3sQ04o0eeQEySLrcz4DsX3saHfsr8/N6tfhblxgZKXxMT2Louargg12oGNfoTRLV09GXhVUe5/qgA5vdgNigg==",
"requires": { "requires": {
"adjust-sourcemap-loader": "3.0.0", "adjust-sourcemap-loader": "3.0.0",
"camelcase": "5.3.1", "camelcase": "5.3.1",
@@ -35431,7 +35504,7 @@
"convert-source-map": "1.7.0", "convert-source-map": "1.7.0",
"es6-iterator": "2.0.3", "es6-iterator": "2.0.3",
"loader-utils": "1.2.3", "loader-utils": "1.2.3",
"postcss": "7.0.21", "postcss": "7.0.36",
"rework": "1.0.1", "rework": "1.0.1",
"rework-visit": "1.0.0", "rework-visit": "1.0.0",
"source-map": "0.6.1" "source-map": "0.6.1"
@@ -35465,28 +35538,10 @@
"json5": "^1.0.1" "json5": "^1.0.1"
} }
}, },
"postcss": {
"version": "7.0.21",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz",
"integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==",
"requires": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
"supports-color": "^6.1.0"
}
},
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"requires": {
"has-flag": "^3.0.0"
}
} }
} }
}, },
@@ -36905,9 +36960,9 @@
"integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA=="
}, },
"tar": { "tar": {
"version": "6.1.0", "version": "6.1.11",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
"integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
"requires": { "requires": {
"chownr": "^2.0.0", "chownr": "^2.0.0",
"fs-minipass": "^2.0.0", "fs-minipass": "^2.0.0",
@@ -37376,9 +37431,9 @@
} }
}, },
"typescript": { "typescript": {
"version": "4.2.4", "version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
"integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==" "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA=="
}, },
"unbox-primitive": { "unbox-primitive": {
"version": "1.0.1", "version": "1.0.1",
@@ -37647,9 +37702,9 @@
} }
}, },
"url-parse": { "url-parse": {
"version": "1.5.1", "version": "1.5.3",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz",
"integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==",
"requires": { "requires": {
"querystringify": "^2.1.1", "querystringify": "^2.1.1",
"requires-port": "^1.0.0" "requires-port": "^1.0.0"
@@ -38299,6 +38354,16 @@
"locate-path": "^3.0.0" "locate-path": "^3.0.0"
} }
}, },
"fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
},
"glob-parent": { "glob-parent": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",

View File

@@ -3,13 +3,13 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@material-ui/core": "^4.11.4", "@material-ui/core": "^4.12.3",
"@material-ui/icons": "^4.11.2", "@material-ui/icons": "^4.11.2",
"@msgpack/msgpack": "^2.7.0", "@msgpack/msgpack": "^2.7.0",
"@types/lodash": "^4.14.168", "@types/lodash": "^4.14.172",
"@types/node": "^15.0.1", "@types/node": "^12.20.20",
"@types/react": "^17.0.4", "@types/react": "^17.0.19",
"@types/react-dom": "^17.0.3", "@types/react-dom": "^17.0.9",
"@types/react-material-ui-form-validator": "^2.1.0", "@types/react-material-ui-form-validator": "^2.1.0",
"@types/react-router": "^5.1.13", "@types/react-router": "^5.1.13",
"@types/react-router-dom": "^5.1.7", "@types/react-router-dom": "^5.1.7",
@@ -30,7 +30,7 @@
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
"sockette": "^2.0.6", "sockette": "^2.0.6",
"typescript": "4.2.4", "typescript": "4.3.5",
"zlib": "^1.0.5" "zlib": "^1.0.5"
}, },
"scripts": { "scripts": {

View File

@@ -3,12 +3,12 @@ import { Component } from 'react';
import { CssBaseline } from '@material-ui/core'; import { CssBaseline } from '@material-ui/core';
import { import {
MuiThemeProvider, MuiThemeProvider,
createMuiTheme, createTheme,
StylesProvider StylesProvider
} from '@material-ui/core/styles'; } from '@material-ui/core/styles';
import { blueGrey, orange, red, green } from '@material-ui/core/colors'; import { blueGrey, orange, red, green } from '@material-ui/core/colors';
const theme = createMuiTheme({ const theme = createTheme({
palette: { palette: {
type: 'dark', type: 'dark',
primary: { primary: {

View File

@@ -4,6 +4,7 @@ export const PROJECT_PATH = process.env.REACT_APP_PROJECT_PATH!;
export const ENDPOINT_ROOT = calculateEndpointRoot('/rest/'); export const ENDPOINT_ROOT = calculateEndpointRoot('/rest/');
export const WEB_SOCKET_ROOT = calculateWebSocketRoot('/ws/'); export const WEB_SOCKET_ROOT = calculateWebSocketRoot('/ws/');
export const EVENT_SOURCE_ROOT = calculateEndpointRoot('/es/'); export const EVENT_SOURCE_ROOT = calculateEndpointRoot('/es/');
export const API_ENDPOINT_ROOT = calculateEndpointRoot('/api/');
function calculateEndpointRoot(endpointPath: string) { function calculateEndpointRoot(endpointPath: string) {
const httpRoot = process.env.REACT_APP_HTTP_ROOT; const httpRoot = process.env.REACT_APP_HTTP_ROOT;

View File

@@ -22,25 +22,13 @@ interface UnauthenticatedRouteProps
| React.ComponentType<any>; | React.ComponentType<any>;
} }
type RenderComponent = (props: RouteComponentProps<any>) => React.ReactNode;
class UnauthenticatedRoute extends Route<UnauthenticatedRouteProps> { class UnauthenticatedRoute extends Route<UnauthenticatedRouteProps> {
public render() { public render() {
const { const { authenticationContext, features, ...rest } = this.props;
authenticationContext, if (authenticationContext.me) {
component: Component, return <Redirect to={Authentication.fetchLoginRedirect(features)} />;
features, }
...rest return <Route {...rest} />;
} = this.props;
const renderComponent: RenderComponent = (props) => {
if (authenticationContext.me) {
return <Redirect to={Authentication.fetchLoginRedirect(features)} />;
}
if (Component) {
return <Component {...props} />;
}
};
return <Route {...rest} render={renderComponent} />;
} }
} }

View File

@@ -0,0 +1,56 @@
import { FC } from 'react';
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles';
import { Button, LinearProgress, Typography } from '@material-ui/core';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
loadingSettings: {
margin: theme.spacing(0.5)
},
loadingSettingsDetails: {
margin: theme.spacing(4),
textAlign: 'center'
},
button: {
marginRight: theme.spacing(2),
marginTop: theme.spacing(2)
}
})
);
interface FormLoaderProps {
errorMessage?: string;
loadData: () => void;
}
const FormLoader: FC<FormLoaderProps> = ({ errorMessage, loadData }) => {
const classes = useStyles();
if (errorMessage) {
return (
<div className={classes.loadingSettings}>
<Typography variant="h6" className={classes.loadingSettingsDetails}>
{errorMessage}
</Typography>
<Button
variant="contained"
color="secondary"
className={classes.button}
onClick={loadData}
>
Retry
</Button>
</div>
);
}
return (
<div className={classes.loadingSettings}>
<LinearProgress className={classes.loadingSettingsDetails} />
<Typography variant="h6" className={classes.loadingSettingsDetails}>
Loading&hellip;
</Typography>
</div>
);
};
export default FormLoader;

View File

@@ -5,6 +5,7 @@ export { default as HighlightAvatar } from './HighlightAvatar';
export { default as MenuAppBar } from './MenuAppBar'; export { default as MenuAppBar } from './MenuAppBar';
export { default as PasswordValidator } from './PasswordValidator'; export { default as PasswordValidator } from './PasswordValidator';
export { default as RestFormLoader } from './RestFormLoader'; export { default as RestFormLoader } from './RestFormLoader';
export { default as FormLoader } from './FormLoader';
export { default as SectionContent } from './SectionContent'; export { default as SectionContent } from './SectionContent';
export { default as WebSocketFormLoader } from './WebSocketFormLoader'; export { default as WebSocketFormLoader } from './WebSocketFormLoader';
export { default as ErrorButton } from './ErrorButton'; export { default as ErrorButton } from './ErrorButton';

View File

@@ -1,58 +1,31 @@
import { Component } from 'react'; import { FC } from 'react';
import { Features } from './types';
import { FeaturesContext } from './FeaturesContext';
import FullScreenLoading from '../components/FullScreenLoading'; import FullScreenLoading from '../components/FullScreenLoading';
import ApplicationError from '../components/ApplicationError'; import ApplicationError from '../components/ApplicationError';
import { FEATURES_ENDPOINT } from '../api'; import { FEATURES_ENDPOINT } from '../api';
import { useRest } from '../hooks';
interface FeaturesWrapperState { import { Features } from './types';
features?: Features; import { FeaturesContext } from './FeaturesContext';
error?: string;
}
class FeaturesWrapper extends Component<{}, FeaturesWrapperState> { const FeaturesWrapper: FC = ({ children }) => {
state: FeaturesWrapperState = {}; const { data: features, errorMessage: error } = useRest<Features>({
endpoint: FEATURES_ENDPOINT
});
componentDidMount() { if (features) {
this.fetchFeaturesDetails(); return (
<FeaturesContext.Provider value={{ features }}>
{children}
</FeaturesContext.Provider>
);
} }
fetchFeaturesDetails = () => { if (error) {
fetch(FEATURES_ENDPOINT) return <ApplicationError error={error} />;
.then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw Error('Unexpected status code: ' + response.status);
}
})
.then((features) => {
this.setState({ features });
})
.catch((error) => {
this.setState({ error: error.message });
});
};
render() {
const { features, error } = this.state;
if (features) {
return (
<FeaturesContext.Provider
value={{
features
}}
>
{this.props.children}
</FeaturesContext.Provider>
);
}
if (error) {
return <ApplicationError error={error} />;
}
return <FullScreenLoading />;
} }
}
return <FullScreenLoading />;
};
export default FeaturesWrapper; export default FeaturesWrapper;

View File

@@ -0,0 +1,2 @@
export { default as useRest } from './useRest';
export { default as useAuthorizedRest } from './useAuthorizedRest';

View File

@@ -0,0 +1,12 @@
import { redirectingAuthorizedFetch } from '../authentication';
import useRest, { RestRequestOptions } from './useRest';
const useAuthorizedRest = <D>({
endpoint
}: Omit<RestRequestOptions, 'fetchFunction'>) =>
useRest<D>({
endpoint,
fetchFunction: redirectingAuthorizedFetch
});
export default useAuthorizedRest;

View File

@@ -0,0 +1,79 @@
import { useCallback, useEffect, useState } from 'react';
import { useSnackbar } from 'notistack';
export interface RestRequestOptions {
endpoint: string;
fetchFunction?: typeof fetch;
}
const useRest = <D>({
endpoint,
fetchFunction = fetch
}: RestRequestOptions) => {
const { enqueueSnackbar } = useSnackbar();
const [saving, setSaving] = useState<boolean>(false);
const [data, setData] = useState<D>();
const [errorMessage, setErrorMessage] = useState<string>();
const handleError = useCallback(
(error: any) => {
const errorMessage = error.message || 'Unknown error';
enqueueSnackbar('Problem fetching: ' + errorMessage, {
variant: 'error'
});
setErrorMessage(errorMessage);
},
[enqueueSnackbar]
);
const loadData = useCallback(async () => {
setData(undefined);
setErrorMessage(undefined);
try {
const response = await fetchFunction(endpoint);
if (response.status !== 200) {
throw Error('Invalid status code: ' + response.status);
}
setData(await response.json());
} catch (error) {
handleError(error);
}
}, [handleError, fetchFunction, endpoint]);
const save = useCallback(
async (data: D) => {
setSaving(true);
setErrorMessage(undefined);
try {
const response = await fetchFunction(endpoint, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
});
if (response.status !== 200) {
throw Error('Invalid status code: ' + response.status);
}
enqueueSnackbar('Update successful.', { variant: 'success' });
setData(await response.json());
} catch (error) {
handleError(error);
} finally {
setSaving(false);
}
},
[enqueueSnackbar, handleError, fetchFunction, endpoint]
);
const saveData = () => data && save(data);
useEffect(() => {
loadData();
}, [loadData]);
return { loadData, saveData, saving, setData, data, errorMessage } as const;
};
export default useRest;

View File

@@ -109,7 +109,7 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
/> />
<TextField <TextField
name="client_id" name="client_id"
label="Client ID (optional)" label="Client ID"
fullWidth fullWidth
variant="outlined" variant="outlined"
value={data.client_id} value={data.client_id}
@@ -159,7 +159,7 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
value="clean_session" value="clean_session"
/> />
} }
label="Clean Session" label="Set Clean Session"
/> />
<BlockFormControlLabel <BlockFormControlLabel
control={ control={
@@ -169,7 +169,7 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
value="mqtt_retain" value="mqtt_retain"
/> />
} }
label="Retain Flag" label="Use Retain Flag"
/> />
<br></br> <br></br>
<Typography variant="h6" color="primary"> <Typography variant="h6" color="primary">
@@ -184,48 +184,19 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
onChange={handleValueChange('nested_format')} onChange={handleValueChange('nested_format')}
margin="normal" margin="normal"
> >
<MenuItem value={1}>nested on a single topic</MenuItem> <MenuItem value={1}>Nested on a single topic</MenuItem>
<MenuItem value={2}>as individual topics</MenuItem> <MenuItem value={2}>As individual topics</MenuItem>
</SelectValidator>
<SelectValidator
name="dallas_format"
label="Dallas Sensor Payload Grouping"
value={data.dallas_format}
fullWidth
variant="outlined"
onChange={handleValueChange('dallas_format')}
margin="normal"
>
<MenuItem value={1}>by Sensor ID</MenuItem>
<MenuItem value={2}>by Number</MenuItem>
</SelectValidator>
<SelectValidator
name="bool_format"
label="Boolean Format"
value={data.bool_format}
fullWidth
variant="outlined"
onChange={handleValueChange('bool_format')}
margin="normal"
>
<MenuItem value={1}>"on"/"off"</MenuItem>
<MenuItem value={2}>true/false</MenuItem>
<MenuItem value={3}>1/0</MenuItem>
<MenuItem value={4}>"ON"/"OFF"</MenuItem>
</SelectValidator>
<SelectValidator
name="subscribe_format"
label="Subscribe Format"
value={data.subscribe_format}
fullWidth
variant="outlined"
onChange={handleValueChange('subscribe_format')}
margin="normal"
>
<MenuItem value={0}>general device topic</MenuItem>
<MenuItem value={1}>individual topics, main heating circuit</MenuItem>
<MenuItem value={2}>individual topics, all heating circuits</MenuItem>
</SelectValidator> </SelectValidator>
<BlockFormControlLabel
control={
<Checkbox
checked={data.send_response}
onChange={handleValueChange('send_response')}
value="send_response"
/>
}
label="Publish command output to a 'response' topic"
/>
<BlockFormControlLabel <BlockFormControlLabel
control={ control={
<Checkbox <Checkbox
@@ -246,9 +217,9 @@ class MqttSettingsForm extends React.Component<MqttSettingsFormProps> {
onChange={handleValueChange('ha_climate_format')} onChange={handleValueChange('ha_climate_format')}
margin="normal" margin="normal"
> >
<MenuItem value={1}>use Current temperature (default)</MenuItem> <MenuItem value={1}>Use Current temperature</MenuItem>
<MenuItem value={2}>use Setpoint temperature</MenuItem> <MenuItem value={2}>Use Setpoint temperature</MenuItem>
<MenuItem value={3}>Fix to 0</MenuItem> <MenuItem value={3}>Always set to 0</MenuItem>
</SelectValidator> </SelectValidator>
)} )}
<br></br> <br></br>

View File

@@ -34,12 +34,10 @@ export interface MqttSettings {
publish_time_mixer: number; publish_time_mixer: number;
publish_time_other: number; publish_time_other: number;
publish_time_sensor: number; publish_time_sensor: number;
dallas_format: number;
bool_format: number;
mqtt_qos: number; mqtt_qos: number;
mqtt_retain: boolean; mqtt_retain: boolean;
ha_enabled: boolean; ha_enabled: boolean;
ha_climate_format: number; ha_climate_format: number;
nested_format: number; nested_format: number;
subscribe_format: number; send_response: boolean;
} }

View File

@@ -51,7 +51,11 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
ssid: selectedNetwork.ssid, ssid: selectedNetwork.ssid,
password: '', password: '',
hostname: props.data.hostname, hostname: props.data.hostname,
static_ip_config: false static_ip_config: false,
enableIPv6: false,
bandwidth20: false,
tx_power: 20,
nosleep: false
}; };
props.setData(networkSettings); props.setData(networkSettings);
} }
@@ -145,6 +149,53 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
onChange={handleValueChange('hostname')} onChange={handleValueChange('hostname')}
margin="normal" margin="normal"
/> />
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:20']}
errorMessages={[
'Tx Power is required',
'Must be a number',
'Must be greater than 0dBm ',
'Max value is 20dBm'
]}
name="tx_power"
label="WiFi Tx Power (dBm)"
fullWidth
variant="outlined"
value={data.tx_power}
type="number"
onChange={handleValueChange('tx_power')}
margin="normal"
/>
<BlockFormControlLabel
control={
<Checkbox
value="enableIPv6"
checked={data.enableIPv6}
onChange={handleValueChange('enableIPv6')}
/>
}
label="Enable IPv6 support"
/>
<BlockFormControlLabel
control={
<Checkbox
value="bandwidth20"
checked={data.bandwidth20}
onChange={handleValueChange('bandwidth20')}
/>
}
label="Use Lower WiFi Bandwidth"
/>
<BlockFormControlLabel
control={
<Checkbox
value="nosleep"
checked={data.nosleep}
onChange={handleValueChange('nosleep')}
/>
}
label="Disable WiFi Sleep Mode"
/>
<BlockFormControlLabel <BlockFormControlLabel
control={ control={
<Checkbox <Checkbox
@@ -153,7 +204,7 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
onChange={handleValueChange('static_ip_config')} onChange={handleValueChange('static_ip_config')}
/> />
} }
label="Static IP Config" label="Use Static IPs"
/> />
{data.static_ip_config && ( {data.static_ip_config && (
<Fragment> <Fragment>

View File

@@ -40,7 +40,22 @@ class NetworkStatusForm extends Component<NetworkStatusFormProps> {
if (!status.dns_ip_1) { if (!status.dns_ip_1) {
return 'none'; return 'none';
} }
return status.dns_ip_1 + (status.dns_ip_2 ? ',' + status.dns_ip_2 : ''); if (!status.dns_ip_2 || status.dns_ip_2 === '0.0.0.0') {
return status.dns_ip_1;
}
return status.dns_ip_1 + ', ' + status.dns_ip_2;
}
IPs(status: NetworkStatus) {
if (
!status.local_ipv6 ||
status.local_ipv6 === '0000:0000:0000:0000:0000:0000:0000:0000'
) {
return status.local_ip;
}
if (!status.local_ip || status.local_ip === '0.0.0.0') {
return status.local_ipv6;
}
return status.local_ip + ', ' + status.local_ipv6;
} }
createListItems() { createListItems() {
@@ -77,7 +92,7 @@ class NetworkStatusForm extends Component<NetworkStatusFormProps> {
<ListItemAvatar> <ListItemAvatar>
<Avatar>IP</Avatar> <Avatar>IP</Avatar>
</ListItemAvatar> </ListItemAvatar>
<ListItemText primary="IP Address" secondary={data.local_ip} /> <ListItemText primary="IP Address" secondary={this.IPs(data)} />
</ListItem> </ListItem>
<Divider variant="inset" component="li" /> <Divider variant="inset" component="li" />
<ListItem> <ListItem>

View File

@@ -21,6 +21,7 @@ export enum WiFiEncryptionType {
export interface NetworkStatus { export interface NetworkStatus {
status: NetworkConnectionStatus; status: NetworkConnectionStatus;
local_ip: string; local_ip: string;
local_ipv6: string;
mac_address: string; mac_address: string;
rssi: number; rssi: number;
ssid: string; ssid: string;
@@ -37,6 +38,10 @@ export interface NetworkSettings {
password: string; password: string;
hostname: string; hostname: string;
static_ip_config: boolean; static_ip_config: boolean;
enableIPv6: boolean;
bandwidth20: boolean;
nosleep: boolean;
tx_power: number;
local_ip?: string; local_ip?: string;
gateway_ip?: string; gateway_ip?: string;
subnet_mask?: string; subnet_mask?: string;

View File

@@ -10,9 +10,7 @@ export const BOARD_PROFILES: BoardProfiles = {
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',
OLIMEX: 'Olimex ESP32-EVB', OLIMEX: 'Olimex ESP32-EVB'
TLK110: 'Generic Ethernet (TLK110)',
LAN8720: 'Generic Ethernet (LAN8720)'
}; };
export function boardProfileSelectItems() { export function boardProfileSelectItems() {

View File

@@ -8,7 +8,7 @@ import { MenuAppBar } from '../components';
import { AuthenticatedRoute } from '../authentication'; import { AuthenticatedRoute } from '../authentication';
import EMSESPStatusController from './EMSESPStatusController'; import EMSESPStatusController from './EMSESPStatusController';
import EMSESPDevicesController from './EMSESPDevicesController'; import EMSESPDataController from './EMSESPDataController';
import EMSESPHelp from './EMSESPHelp'; import EMSESPHelp from './EMSESPHelp';
class EMSESP extends Component<RouteComponentProps> { class EMSESP extends Component<RouteComponentProps> {
@@ -24,18 +24,15 @@ class EMSESP extends Component<RouteComponentProps> {
onChange={(e, path) => this.handleTabChange(path)} onChange={(e, path) => this.handleTabChange(path)}
variant="fullWidth" variant="fullWidth"
> >
<Tab <Tab value={`/${PROJECT_PATH}/data`} label="Devices &amp; Sensors" />
value={`/${PROJECT_PATH}/devices`}
label="Devices &amp; Sensors"
/>
<Tab value={`/${PROJECT_PATH}/status`} label="EMS Status" /> <Tab value={`/${PROJECT_PATH}/status`} label="EMS Status" />
<Tab value={`/${PROJECT_PATH}/help`} label="EMS-ESP Help" /> <Tab value={`/${PROJECT_PATH}/help`} label="EMS-ESP Help" />
</Tabs> </Tabs>
<Switch> <Switch>
<AuthenticatedRoute <AuthenticatedRoute
exact exact
path={`/${PROJECT_PATH}/devices`} path={`/${PROJECT_PATH}/data`}
component={EMSESPDevicesController} component={EMSESPDataController}
/> />
<AuthenticatedRoute <AuthenticatedRoute
exact exact
@@ -47,7 +44,7 @@ class EMSESP extends Component<RouteComponentProps> {
path={`/${PROJECT_PATH}/help`} path={`/${PROJECT_PATH}/help`}
component={EMSESPHelp} component={EMSESPHelp}
/> />
<Redirect to={`/${PROJECT_PATH}/devices`} /> <Redirect to={`/${PROJECT_PATH}/data`} />
</Switch> </Switch>
</MenuAppBar> </MenuAppBar>
); );

View File

@@ -0,0 +1,35 @@
import React, { Component } from 'react';
import {
restController,
RestControllerProps,
RestFormLoader,
SectionContent
} from '../components';
import { ENDPOINT_ROOT } from '../api';
import EMSESPDataForm from './EMSESPDataForm';
import { EMSESPData } from './EMSESPtypes';
export const EMSESP_DATA_ENDPOINT = ENDPOINT_ROOT + 'data';
type EMSESPDataControllerProps = RestControllerProps<EMSESPData>;
class EMSESPDataController extends Component<EMSESPDataControllerProps> {
componentDidMount() {
this.props.loadData();
}
render() {
return (
<SectionContent title="Devices &amp; Sensors">
<RestFormLoader
{...this.props}
render={(formProps) => <EMSESPDataForm {...formProps} />}
/>
</SectionContent>
);
}
}
export default restController(EMSESP_DATA_ENDPOINT, EMSESPDataController);

View File

@@ -40,35 +40,51 @@ import {
import { RestFormProps, FormButton, extractEventValue } from '../components'; import { RestFormProps, FormButton, extractEventValue } from '../components';
import { import {
EMSESPDevices, EMSESPData,
EMSESPDeviceData, EMSESPDeviceData,
Device, Device,
DeviceValue, DeviceValue,
DeviceValueUOM, DeviceValueUOM,
DeviceValueUOM_s DeviceValueUOM_s,
Sensor
} from './EMSESPtypes'; } from './EMSESPtypes';
import ValueForm from './ValueForm'; import ValueForm from './ValueForm';
import SensorForm from './SensorForm';
import { ENDPOINT_ROOT } from '../api'; import { ENDPOINT_ROOT } from '../api';
export const SCANDEVICES_ENDPOINT = ENDPOINT_ROOT + 'scanDevices'; export const SCANDEVICES_ENDPOINT = ENDPOINT_ROOT + 'scanDevices';
export const DEVICE_DATA_ENDPOINT = ENDPOINT_ROOT + 'deviceData'; export const DEVICE_DATA_ENDPOINT = ENDPOINT_ROOT + 'deviceData';
export const WRITE_VALUE_ENDPOINT = ENDPOINT_ROOT + 'writeValue'; export const WRITE_VALUE_ENDPOINT = ENDPOINT_ROOT + 'writeValue';
export const WRITE_SENSOR_ENDPOINT = ENDPOINT_ROOT + 'writeSensor';
const StyledTableCell = withStyles((theme: Theme) => const StyledTableRow = withStyles((theme: Theme) =>
createStyles({ createStyles({
head: { root: {
backgroundColor: theme.palette.common.black, '&:nth-child(even)': {
color: theme.palette.common.white backgroundColor: '#4e4e4e'
},
'&:hover': {
backgroundColor: theme.palette.info.light
}
}, },
body: {
fontSize: 14 selected: {
backgroundColor: theme.palette.common.white
} }
}) })
)(TableCell); )(TableRow);
const CustomTooltip = withStyles((theme: Theme) => ({ const StyledTableRowHeader = withStyles((theme: Theme) =>
createStyles({
head: {
backgroundColor: theme.palette.common.black
}
})
)(TableRow);
const StyledTooltip = withStyles((theme: Theme) => ({
tooltip: { tooltip: {
backgroundColor: theme.palette.secondary.main, backgroundColor: theme.palette.secondary.main,
color: 'white', color: 'white',
@@ -79,27 +95,31 @@ const CustomTooltip = withStyles((theme: Theme) => ({
}))(Tooltip); }))(Tooltip);
function compareDevices(a: Device, b: Device) { function compareDevices(a: Device, b: Device) {
if (a.type < b.type) { if (a.t < b.t) {
return -1; return -1;
} }
if (a.type > b.type) { if (a.t > b.t) {
return 1; return 1;
} }
return 0; return 0;
} }
interface EMSESPDevicesFormState { interface EMSESPDataFormState {
confirmScanDevices: boolean; confirmScanDevices: boolean;
processing: boolean; processing: boolean;
deviceData?: EMSESPDeviceData; deviceData?: EMSESPDeviceData;
selectedDevice?: number; selectedDevice?: number;
edit_devicevalue?: DeviceValue; edit_devicevalue?: DeviceValue;
edit_Sensor?: Sensor;
} }
type EMSESPDevicesFormProps = RestFormProps<EMSESPDevices> & type EMSESPDataFormProps = RestFormProps<EMSESPData> &
AuthenticatedContextProps & AuthenticatedContextProps &
WithWidthProps; WithWidthProps;
const pluralize = (count: number, noun: string, suffix = 's') =>
` ${Intl.NumberFormat().format(count)} ${noun}${count !== 1 ? suffix : ''} `;
export const formatDuration = (duration_min: number) => { export const formatDuration = (duration_min: number) => {
const { days, hours, minutes } = parseMilliseconds(duration_min * 60000); const { days, hours, minutes } = parseMilliseconds(duration_min * 60000);
let formatted = ''; let formatted = '';
@@ -115,9 +135,6 @@ export const formatDuration = (duration_min: number) => {
return formatted; return formatted;
}; };
const pluralize = (count: number, noun: string, suffix = 's') =>
` ${count} ${noun}${count !== 1 ? suffix : ''} `;
function formatValue(value: any, uom: number) { function formatValue(value: any, uom: number) {
switch (uom) { switch (uom) {
case DeviceValueUOM.HOURS: case DeviceValueUOM.HOURS:
@@ -125,11 +142,22 @@ function formatValue(value: any, uom: number) {
case DeviceValueUOM.MINUTES: case DeviceValueUOM.MINUTES:
return value ? formatDuration(value) : '0 minutes'; return value ? formatDuration(value) : '0 minutes';
case DeviceValueUOM.NONE: case DeviceValueUOM.NONE:
if (typeof value === 'number') {
return new Intl.NumberFormat().format(value);
}
return value; return value;
case DeviceValueUOM.NUM: case DeviceValueUOM.DEGREES:
return new Intl.NumberFormat().format(value); // always show with one decimal place
case DeviceValueUOM.BOOLEAN: return (
return value ? 'on' : 'off'; new Intl.NumberFormat(undefined, {
minimumFractionDigits: 1
}).format(value) +
' ' +
DeviceValueUOM_s[uom]
);
case DeviceValueUOM.TIMES:
case DeviceValueUOM.SECONDS:
return pluralize(value, DeviceValueUOM_s[uom]);
default: default:
return ( return (
new Intl.NumberFormat().format(value) + ' ' + DeviceValueUOM_s[uom] new Intl.NumberFormat().format(value) + ' ' + DeviceValueUOM_s[uom]
@@ -137,16 +165,16 @@ function formatValue(value: any, uom: number) {
} }
} }
class EMSESPDevicesForm extends Component< class EMSESPDataForm extends Component<
EMSESPDevicesFormProps, EMSESPDataFormProps,
EMSESPDevicesFormState EMSESPDataFormState
> { > {
state: EMSESPDevicesFormState = { state: EMSESPDataFormState = {
confirmScanDevices: false, confirmScanDevices: false,
processing: false processing: false
}; };
handleValueChange = (name: keyof DeviceValue) => ( handleDeviceValueChange = (name: keyof DeviceValue) => (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ) => {
this.setState({ this.setState({
@@ -157,11 +185,11 @@ class EMSESPDevicesForm extends Component<
}); });
}; };
cancelEditingValue = () => { cancelEditingDeviceValue = () => {
this.setState({ edit_devicevalue: undefined }); this.setState({ edit_devicevalue: undefined });
}; };
doneEditingValue = () => { doneEditingDeviceValue = () => {
const { edit_devicevalue, selectedDevice } = this.state; const { edit_devicevalue, selectedDevice } = this.state;
redirectingAuthorizedFetch(WRITE_VALUE_ENDPOINT, { redirectingAuthorizedFetch(WRITE_VALUE_ENDPOINT, {
@@ -179,6 +207,7 @@ class EMSESPDevicesForm extends Component<
this.props.enqueueSnackbar('Write command sent to device', { this.props.enqueueSnackbar('Write command sent to device', {
variant: 'success' variant: 'success'
}); });
this.handleRowClick(selectedDevice);
} else if (response.status === 204) { } else if (response.status === 204) {
this.props.enqueueSnackbar('Write command failed', { this.props.enqueueSnackbar('Write command failed', {
variant: 'error' variant: 'error'
@@ -203,7 +232,77 @@ class EMSESPDevicesForm extends Component<
}; };
sendCommand = (dv: DeviceValue) => { sendCommand = (dv: DeviceValue) => {
this.setState({ edit_devicevalue: dv }); if (dv.c && this.props.authenticatedContext.me.admin) {
this.setState({ edit_devicevalue: dv });
}
};
handleSensorChange = (name: keyof Sensor) => (
event: React.ChangeEvent<HTMLInputElement>
) => {
this.setState({
edit_Sensor: {
...this.state.edit_Sensor!,
[name]: extractEventValue(event)
}
});
};
cancelEditingSensor = () => {
this.setState({ edit_Sensor: undefined });
};
doneEditingSensor = () => {
const { edit_Sensor } = this.state;
redirectingAuthorizedFetch(WRITE_SENSOR_ENDPOINT, {
method: 'POST',
body: JSON.stringify({
// because input field with type=number doens't like negative values, force it here
sensor: {
no: edit_Sensor?.n, // no
id: edit_Sensor?.i, // id
temp: edit_Sensor?.t, // temp
offset: Number(edit_Sensor?.o) // offset
}
}),
headers: {
'Content-Type': 'application/json'
}
})
.then((response) => {
if (response.status === 200) {
this.props.enqueueSnackbar('Sensor updated', {
variant: 'success'
});
this.props.loadData();
} else if (response.status === 204) {
this.props.enqueueSnackbar('Sensor change failed', {
variant: 'error'
});
} else if (response.status === 403) {
this.props.enqueueSnackbar('Write access denied', {
variant: 'error'
});
} else {
throw Error('Unexpected response code: ' + response.status);
}
})
.catch((error) => {
this.props.enqueueSnackbar(error.message || 'Problem writing value', {
variant: 'error'
});
});
if (edit_Sensor) {
this.setState({ edit_Sensor: undefined });
}
};
sendSensor = (sn: Sensor) => {
if (this.props.authenticatedContext.me.admin) {
this.setState({ edit_Sensor: sn });
}
}; };
noDevices = () => { noDevices = () => {
@@ -218,7 +317,7 @@ class EMSESPDevicesForm extends Component<
return (this.state.deviceData?.data || []).length === 0; return (this.state.deviceData?.data || []).length === 0;
}; };
renderDeviceItems() { renderDevices() {
const { width, data } = this.props; const { width, data } = this.props;
return ( return (
<TableContainer> <TableContainer>
@@ -229,26 +328,24 @@ class EMSESPDevicesForm extends Component<
{!this.noDevices() && ( {!this.noDevices() && (
<Table <Table
size="small" size="small"
padding={isWidthDown('xs', width!) ? 'none' : 'default'} padding={isWidthDown('xs', width!) ? 'none' : 'normal'}
> >
<TableBody> <TableBody>
{data.devices.sort(compareDevices).map((device) => ( {data.devices.sort(compareDevices).map((device) => (
<TableRow <TableRow
hover hover
key={device.id} key={device.i}
onClick={() => this.handleRowClick(device)} onClick={() => this.handleRowClick(device.i)}
> >
<TableCell> <TableCell>
<CustomTooltip <StyledTooltip
title={ title={
'DeviceID:0x' + 'DeviceID:0x' +
( ('00' + device.d.toString(16).toUpperCase()).slice(-2) +
'00' + device.deviceid.toString(16).toUpperCase()
).slice(-2) +
' ProductID:' + ' ProductID:' +
device.productid + device.p +
' Version:' + ' Version:' +
device.version device.v
} }
placement="right-end" placement="right-end"
> >
@@ -257,12 +354,12 @@ class EMSESPDevicesForm extends Component<
size="small" size="small"
variant="outlined" variant="outlined"
> >
{device.type} {device.t}
</Button> </Button>
</CustomTooltip> </StyledTooltip>
</TableCell> </TableCell>
<TableCell align="right"> <TableCell align="right">
{device.brand + ' ' + device.name}{' '} {device.b + ' ' + device.n}{' '}
</TableCell> </TableCell>
</TableRow> </TableRow>
))} ))}
@@ -287,34 +384,48 @@ class EMSESPDevicesForm extends Component<
); );
} }
renderSensorItems() { renderSensorData() {
const { data } = this.props; const { data } = this.props;
const me = this.props.authenticatedContext.me;
return ( return (
<TableContainer> <TableContainer>
<p></p> <p></p>
<Typography variant="h6" color="primary" paragraph> <Typography variant="h6" color="primary" paragraph>
Dallas Sensors Sensors
</Typography> </Typography>
{!this.noSensors() && ( {!this.noSensors() && (
<Table size="small" padding="default"> <Table size="small" padding="normal">
<TableHead> <TableHead>
<TableRow> <StyledTableRowHeader>
<StyledTableCell>Sensor #</StyledTableCell> <TableCell padding="checkbox" style={{ width: 18 }}></TableCell>
<StyledTableCell align="center">ID</StyledTableCell> <TableCell>Dallas Sensor #</TableCell>
<StyledTableCell align="right">Temperature</StyledTableCell> <TableCell align="left">ID / Name</TableCell>
</TableRow> <TableCell align="right">Temperature</TableCell>
</StyledTableRowHeader>
</TableHead> </TableHead>
<TableBody> <TableBody>
{data.sensors.map((sensorData) => ( {data.sensors.map((sensorData) => (
<TableRow key={sensorData.no}> <StyledTableRow
key={sensorData.n}
onClick={() => this.sendSensor(sensorData)}
>
<TableCell padding="checkbox">
{me.admin && (
<StyledTooltip title="edit" placement="left-end">
<IconButton edge="start" size="small" aria-label="Edit">
<EditIcon color="primary" fontSize="small" />
</IconButton>
</StyledTooltip>
)}
</TableCell>
<TableCell component="th" scope="row"> <TableCell component="th" scope="row">
{sensorData.no} {sensorData.n}
</TableCell> </TableCell>
<TableCell align="center">{sensorData.id}</TableCell> <TableCell align="left">{sensorData.i}</TableCell>
<TableCell align="right"> <TableCell align="right">
{formatValue(sensorData.temp, DeviceValueUOM.DEGREES)} {formatValue(sensorData.t, DeviceValueUOM.DEGREES)}
</TableCell> </TableCell>
</TableRow> </StyledTableRow>
))} ))}
</TableBody> </TableBody>
</Table> </Table>
@@ -322,7 +433,7 @@ class EMSESPDevicesForm extends Component<
{this.noSensors() && ( {this.noSensors() && (
<Box color="warning.main" p={0} mt={0} mb={0}> <Box color="warning.main" p={0} mt={0} mb={0}>
<Typography variant="body1"> <Typography variant="body1">
<i>no external temperature sensors were detected</i> <i>no Dallas temperature sensors were detected</i>
</Typography> </Typography>
</Box> </Box>
)} )}
@@ -330,6 +441,37 @@ class EMSESPDevicesForm extends Component<
); );
} }
renderAnalogData() {
const { data } = this.props;
return (
<TableContainer>
<p></p>
{data.analog > 0 && (
<Table size="small" padding="normal">
<TableHead>
<StyledTableRowHeader>
<TableCell padding="normal" style={{ width: 18 }}></TableCell>
<TableCell>Sensor Type</TableCell>
<TableCell align="right">Value</TableCell>
</StyledTableRowHeader>
</TableHead>
<TableBody>
<TableRow>
<TableCell padding="normal">&nbsp;&nbsp;</TableCell>
<TableCell component="th" scope="row">
Analog Input
</TableCell>
<TableCell align="right">
{formatValue(data.analog, DeviceValueUOM.MV)}
</TableCell>
</TableRow>
</TableBody>
</Table>
)}
</TableContainer>
);
}
renderScanDevicesDialog() { renderScanDevicesDialog() {
return ( return (
<Dialog <Dialog
@@ -396,10 +538,10 @@ class EMSESPDevicesForm extends Component<
}; };
handleRowClick = (device: any) => { handleRowClick = (device: any) => {
this.setState({ selectedDevice: device.id, deviceData: undefined }); this.setState({ selectedDevice: device, deviceData: undefined });
redirectingAuthorizedFetch(DEVICE_DATA_ENDPOINT, { redirectingAuthorizedFetch(DEVICE_DATA_ENDPOINT, {
method: 'POST', method: 'POST',
body: JSON.stringify({ id: device.id }), body: JSON.stringify({ id: device }),
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
} }
@@ -426,7 +568,6 @@ class EMSESPDevicesForm extends Component<
renderDeviceData() { renderDeviceData() {
const { deviceData } = this.state; const { deviceData } = this.state;
const { width } = this.props; const { width } = this.props;
const me = this.props.authenticatedContext.me;
if (this.noDevices()) { if (this.noDevices()) {
return; return;
@@ -441,22 +582,24 @@ class EMSESPDevicesForm extends Component<
<p></p> <p></p>
<Box bgcolor="info.main" p={1} mt={1} mb={1}> <Box bgcolor="info.main" p={1} mt={1} mb={1}>
<Typography variant="body1" color="initial"> <Typography variant="body1" color="initial">
{deviceData.name} {deviceData.type}&nbsp;Data
</Typography> </Typography>
</Box> </Box>
{!this.noDeviceData() && ( {!this.noDeviceData() && (
<TableContainer> <TableContainer>
<Table <Table
size="small" size="small"
padding={isWidthDown('xs', width!) ? 'none' : 'default'} padding={isWidthDown('xs', width!) ? 'none' : 'normal'}
> >
<TableHead></TableHead>
<TableBody> <TableBody>
{deviceData.data.map((item, i) => ( {deviceData.data.map((item, i) => (
<TableRow hover key={i}> <StyledTableRow
key={i}
onClick={() => this.sendCommand(item)}
>
<TableCell padding="checkbox" style={{ width: 18 }}> <TableCell padding="checkbox" style={{ width: 18 }}>
{item.c && me.admin && ( {item.c && this.props.authenticatedContext.me.admin && (
<CustomTooltip <StyledTooltip
title="change value" title="change value"
placement="left-end" placement="left-end"
> >
@@ -464,11 +607,10 @@ class EMSESPDevicesForm extends Component<
edge="start" edge="start"
size="small" size="small"
aria-label="Edit" aria-label="Edit"
onClick={() => this.sendCommand(item)}
> >
<EditIcon color="primary" fontSize="small" /> <EditIcon color="primary" fontSize="small" />
</IconButton> </IconButton>
</CustomTooltip> </StyledTooltip>
)} )}
</TableCell> </TableCell>
<TableCell padding="none" component="th" scope="row"> <TableCell padding="none" component="th" scope="row">
@@ -477,7 +619,7 @@ class EMSESPDevicesForm extends Component<
<TableCell padding="none" align="right"> <TableCell padding="none" align="right">
{formatValue(item.v, item.u)} {formatValue(item.v, item.u)}
</TableCell> </TableCell>
</TableRow> </StyledTableRow>
))} ))}
</TableBody> </TableBody>
</Table> </Table>
@@ -486,7 +628,7 @@ class EMSESPDevicesForm extends Component<
{this.noDeviceData() && ( {this.noDeviceData() && (
<Box color="warning.main" p={0} mt={0} mb={0}> <Box color="warning.main" p={0} mt={0} mb={0}>
<Typography variant="body1"> <Typography variant="body1">
<i>No data available for this device</i> <i>no data available for this device</i>
</Typography> </Typography>
</Box> </Box>
)} )}
@@ -495,13 +637,14 @@ class EMSESPDevicesForm extends Component<
} }
render() { render() {
const { edit_devicevalue } = this.state; const { edit_devicevalue, edit_Sensor } = this.state;
return ( return (
<Fragment> <Fragment>
<br></br> <br></br>
{this.renderDeviceItems()} {this.renderDevices()}
{this.renderDeviceData()} {this.renderDeviceData()}
{this.renderSensorItems()} {this.renderSensorData()}
{this.renderAnalogData()}
<br></br> <br></br>
<Box display="flex" flexWrap="wrap"> <Box display="flex" flexWrap="wrap">
<Box flexGrow={1} padding={1}> <Box flexGrow={1} padding={1}>
@@ -528,9 +671,17 @@ class EMSESPDevicesForm extends Component<
{edit_devicevalue && ( {edit_devicevalue && (
<ValueForm <ValueForm
devicevalue={edit_devicevalue} devicevalue={edit_devicevalue}
onDoneEditing={this.doneEditingValue} onDoneEditing={this.doneEditingDeviceValue}
onCancelEditing={this.cancelEditingValue} onCancelEditing={this.cancelEditingDeviceValue}
handleValueChange={this.handleValueChange} handleValueChange={this.handleDeviceValueChange}
/>
)}
{edit_Sensor && (
<SensorForm
sensor={edit_Sensor}
onDoneEditing={this.doneEditingSensor}
onCancelEditing={this.cancelEditingSensor}
handleSensorChange={this.handleSensorChange}
/> />
)} )}
</Fragment> </Fragment>
@@ -538,4 +689,4 @@ class EMSESPDevicesForm extends Component<
} }
} }
export default withAuthenticatedContext(withWidth()(EMSESPDevicesForm)); export default withAuthenticatedContext(withWidth()(EMSESPDataForm));

View File

@@ -1,35 +0,0 @@
import React, { Component } from 'react';
import {
restController,
RestControllerProps,
RestFormLoader,
SectionContent
} from '../components';
import { ENDPOINT_ROOT } from '../api';
import EMSESPDevicesForm from './EMSESPDevicesForm';
import { EMSESPDevices } from './EMSESPtypes';
export const EMSESP_DEVICES_ENDPOINT = ENDPOINT_ROOT + 'allDevices';
type EMSESPDevicesControllerProps = RestControllerProps<EMSESPDevices>;
class EMSESPDevicesController extends Component<EMSESPDevicesControllerProps> {
componentDidMount() {
this.props.loadData();
}
render() {
return (
<SectionContent title="Devices &amp; Sensors">
<RestFormLoader
{...this.props}
render={(formProps) => <EMSESPDevicesForm {...formProps} />}
/>
</SectionContent>
);
}
}
export default restController(EMSESP_DEVICES_ENDPOINT, EMSESPDevicesController);

View File

@@ -1,4 +1,4 @@
import React, { Component } from 'react'; import { Component } from 'react';
import { import {
Typography, Typography,
Box, Box,
@@ -14,14 +14,40 @@ import CommentIcon from '@material-ui/icons/CommentTwoTone';
import MenuBookIcon from '@material-ui/icons/MenuBookTwoTone'; import MenuBookIcon from '@material-ui/icons/MenuBookTwoTone';
import GitHubIcon from '@material-ui/icons/GitHub'; import GitHubIcon from '@material-ui/icons/GitHub';
import StarIcon from '@material-ui/icons/Star'; import StarIcon from '@material-ui/icons/Star';
import ImportExportIcon from '@material-ui/icons/ImportExport'; import DownloadIcon from '@material-ui/icons/GetApp';
import BugReportIcon from '@material-ui/icons/BugReportTwoTone';
export const WebAPISystemSettings = import { FormButton } from '../components';
window.location.origin + '/api/system/settings';
export const WebAPISystemInfo = window.location.origin + '/api/system/info'; import { API_ENDPOINT_ROOT } from '../api';
import { redirectingAuthorizedFetch } from '../authentication';
class EMSESPHelp extends Component { class EMSESPHelp extends Component {
onDownload = (endpoint: string) => {
redirectingAuthorizedFetch(API_ENDPOINT_ROOT + 'system/' + endpoint)
.then((response) => {
if (response.status === 200) {
return response.json();
}
throw Error(
'Device returned unexpected response code: ' + response.status
);
})
.then((json) => {
const a = document.createElement('a');
const filename = 'emsesp_system_' + endpoint + '.txt';
a.href = URL.createObjectURL(
new Blob([JSON.stringify(json, null, 2)], {
type: 'text/plain'
})
);
a.setAttribute('download', filename);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
};
render() { render() {
return ( return (
<SectionContent title="EMS-ESP Help" titleGutter> <SectionContent title="EMS-ESP Help" titleGutter>
@@ -31,9 +57,9 @@ class EMSESPHelp extends Component {
<MenuBookIcon /> <MenuBookIcon />
</ListItemAvatar> </ListItemAvatar>
<ListItemText> <ListItemText>
For the latest news and updates go to the{' '} For help and information on the latest updates visit the{' '}
<Link href="https://emsesp.github.io/docs" color="primary"> <Link href="https://emsesp.github.io/docs" color="primary">
{'official documentation'}&nbsp;website {'online documentation'}
</Link> </Link>
</ListItemText> </ListItemText>
</ListItem> </ListItem>
@@ -55,41 +81,36 @@ class EMSESPHelp extends Component {
<GitHubIcon /> <GitHubIcon />
</ListItemAvatar> </ListItemAvatar>
<ListItemText> <ListItemText>
To report an issue or feature request go to{' '} To report an issue or request a feature go to{' '}
<Link <Link
href="https://github.com/emsesp/EMS-ESP32/issues/new/choose" href="https://github.com/emsesp/EMS-ESP32/issues/new/choose"
color="primary" color="primary"
> >
{'click here'} {'GitHub'}
</Link>
</ListItemText>
</ListItem>
<ListItem>
<ListItemAvatar>
<ImportExportIcon />
</ListItemAvatar>
<ListItemText>
To export your system settings{' '}
<Link target="_blank" href={WebAPISystemSettings} color="primary">
{'click here'}
</Link>
</ListItemText>
</ListItem>
<ListItem>
<ListItemAvatar>
<BugReportIcon />
</ListItemAvatar>
<ListItemText>
To export the current status of EMS-ESP{' '}
<Link target="_blank" href={WebAPISystemInfo} color="primary">
{'click here'}
</Link> </Link>
</ListItemText> </ListItemText>
</ListItem> </ListItem>
</List> </List>
<Box flexWrap="none" padding={1} whiteSpace="nowrap">
<FormButton
startIcon={<DownloadIcon />}
variant="contained"
color="primary"
onClick={() => this.onDownload('info')}
>
download system info
</FormButton>
<FormButton
startIcon={<DownloadIcon />}
variant="contained"
color="primary"
onClick={() => this.onDownload('settings')}
>
download all settings
</FormButton>
</Box>
<Box bgcolor="info.main" border={1} p={3} mt={1} mb={0}> <Box bgcolor="info.main" border={1} p={3} mt={1} mb={0}>
<Typography variant="h6"> <Typography variant="h6">
EMS-ESP is free and open-source. EMS-ESP is free and open-source.

View File

@@ -32,7 +32,7 @@ import {
BlockFormControlLabel BlockFormControlLabel
} from '../components'; } from '../components';
import { isIP, optional } from '../validators'; import { isIPv4, optional, isHostname, or } from '../validators';
import { EMSESPSettings } from './EMSESPtypes'; import { EMSESPSettings } from './EMSESPtypes';
@@ -55,7 +55,10 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
}; };
componentDidMount() { componentDidMount() {
ValidatorForm.addValidationRule('isOptionalIP', optional(isIP)); ValidatorForm.addValidationRule(
'isOptionalIPorHost',
optional(or(isIPv4, isHostname))
);
} }
changeBoardProfile = (event: React.ChangeEvent<HTMLSelectElement>) => { changeBoardProfile = (event: React.ChangeEvent<HTMLSelectElement>) => {
@@ -90,6 +93,7 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
rx_gpio: json.rx_gpio, rx_gpio: json.rx_gpio,
tx_gpio: json.tx_gpio, tx_gpio: json.tx_gpio,
pbutton_gpio: json.pbutton_gpio, pbutton_gpio: json.pbutton_gpio,
phy_type: json.phy_type,
board_profile: event.target.value board_profile: event.target.value
}); });
this.setState({ processing: false }); this.setState({ processing: false });
@@ -109,15 +113,17 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
<ValidatorForm onSubmit={saveData}> <ValidatorForm onSubmit={saveData}>
<Box bgcolor="info.main" p={2} mt={2} mb={2}> <Box bgcolor="info.main" p={2} mt={2} mb={2}>
<Typography variant="body1"> <Typography variant="body1">
Adjust any of the EMS-ESP settings here. For help refer to the{' '} <i>
<Link visit the&nbsp;
target="_blank" <Link
href="https://emsesp.github.io/docs/#/Configure-firmware32?id=ems-esp-settings" target="_blank"
color="primary" href="https://emsesp.github.io/docs/#/Configure-firmware?id=ems-esp-settings"
> color="primary"
{'online documentation'} >
</Link> {'online documentation'}
. </Link>
&nbsp;for details explaining each setting
</i>
</Typography> </Typography>
</Box> </Box>
@@ -130,7 +136,7 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
container container
spacing={1} spacing={1}
direction="row" direction="row"
justify="flex-start" justifyContent="flex-start"
alignItems="flex-start" alignItems="flex-start"
> >
<Grid item xs={5}> <Grid item xs={5}>
@@ -167,30 +173,6 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
<MenuItem value={0x12}>Alarm Module (0x12)</MenuItem> <MenuItem value={0x12}>Alarm Module (0x12)</MenuItem>
</SelectValidator> </SelectValidator>
</Grid> </Grid>
<Grid item xs={6}>
<TextValidator
validators={[
'required',
'isNumber',
'minNumber:0',
'maxNumber:120'
]}
errorMessages={[
'Tx delay is required',
'Must be a number',
'Must be 0 or higher',
'Max value is 120'
]}
name="tx_delay"
label="Tx start delay (seconds)"
fullWidth
variant="outlined"
value={data.tx_delay}
type="number"
onChange={handleValueChange('tx_delay')}
margin="normal"
/>
</Grid>
</Grid> </Grid>
<br></br> <br></br>
@@ -202,7 +184,7 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
<Typography variant="body2"> <Typography variant="body2">
<i> <i>
Select a pre-configured board layout to automatically set the GPIO Select a pre-configured board layout to automatically set the GPIO
pins, or set your own custom configuration pins. Select "Custom..." to view or manually edit the values.
</i> </i>
</Typography> </Typography>
</Box> </Box>
@@ -227,7 +209,7 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
container container
spacing={1} spacing={1}
direction="row" direction="row"
justify="flex-start" justifyContent="flex-start"
alignItems="flex-start" alignItems="flex-start"
> >
<Grid item xs={4}> <Grid item xs={4}>
@@ -325,7 +307,7 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
'Not a valid GPIO' 'Not a valid GPIO'
]} ]}
name="dallas_gpio" name="dallas_gpio"
label="Dallas GPIO (0=none)" label="Dallas GPIO (0=disabled)"
fullWidth fullWidth
variant="outlined" variant="outlined"
value={data.dallas_gpio} value={data.dallas_gpio}
@@ -351,7 +333,7 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
'Not a valid GPIO' 'Not a valid GPIO'
]} ]}
name="led_gpio" name="led_gpio"
label="LED GPIO (0=none)" label="LED GPIO (0=disabled)"
fullWidth fullWidth
variant="outlined" variant="outlined"
value={data.led_gpio} value={data.led_gpio}
@@ -360,12 +342,27 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
margin="normal" margin="normal"
/> />
</Grid> </Grid>
<Grid item xs={4}>
<SelectValidator
name="phy_type"
label="PHY Module Type"
value={data.phy_type}
fullWidth
variant="outlined"
onChange={handleValueChange('phy_type')}
margin="normal"
>
<MenuItem value={0}>No Ethernet</MenuItem>
<MenuItem value={1}>LAN8720</MenuItem>
<MenuItem value={2}>TLK110</MenuItem>
</SelectValidator>
</Grid>
</Grid> </Grid>
)} )}
<br></br> <br></br>
<Typography variant="h6" color="primary"> <Typography variant="h6" color="primary">
Options General Options
</Typography> </Typography>
{data.led_gpio !== 0 && ( {data.led_gpio !== 0 && (
@@ -390,20 +387,10 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
value="dallas_parasite" value="dallas_parasite"
/> />
} }
label="Enable Dallas parasite mode" label="Use Dallas Sensor parasite power"
/> />
)} )}
<BlockFormControlLabel
control={
<Checkbox
checked={data.notoken_api}
onChange={handleValueChange('notoken_api')}
value="notoken_api"
/>
}
label="Bypass Access Token authorization on API calls"
/>
<BlockFormControlLabel <BlockFormControlLabel
control={ control={
<Checkbox <Checkbox
@@ -414,11 +401,31 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
} }
label="Enable ADC" label="Enable ADC"
/> />
<BlockFormControlLabel
control={
<Checkbox
checked={data.low_clock}
onChange={handleValueChange('low_clock')}
value="low_clock"
/>
}
label="Run at a lower CPU clock speed"
/>
<BlockFormControlLabel
control={
<Checkbox
checked={data.notoken_api}
onChange={handleValueChange('notoken_api')}
value="notoken_api"
/>
}
label="Bypass Access Token authorization on API calls"
/>
<Grid <Grid
container container
spacing={0} spacing={0}
direction="row" direction="row"
justify="flex-start" justifyContent="flex-start"
alignItems="flex-start" alignItems="flex-start"
> >
<BlockFormControlLabel <BlockFormControlLabel
@@ -443,6 +450,65 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
/> />
</Grid> </Grid>
<br></br>
<Typography variant="h6" color="primary">
Formatting Options
</Typography>
<Grid
container
spacing={1}
direction="row"
justifyContent="flex-start"
alignItems="flex-start"
>
<Grid item xs={4}>
<SelectValidator
name="bool_format"
label="Boolean Format"
value={data.bool_format}
fullWidth
variant="outlined"
onChange={handleValueChange('bool_format')}
margin="normal"
>
<MenuItem value={1}>"on"/"off"</MenuItem>
<MenuItem value={2}>"ON"/"OFF"</MenuItem>
<MenuItem value={3}>true/false</MenuItem>
<MenuItem value={4}>1/0</MenuItem>
</SelectValidator>
</Grid>
<Grid item xs={4}>
<SelectValidator
name="enum_format"
label="Enum Format"
value={data.enum_format}
fullWidth
variant="outlined"
onChange={handleValueChange('enum_format')}
margin="normal"
>
<MenuItem value={1}>Text</MenuItem>
<MenuItem value={2}>Number</MenuItem>
</SelectValidator>
</Grid>
<Grid item xs={4}>
<SelectValidator
name="dallas_format"
label="Dallas Sensor Format"
value={data.dallas_format}
fullWidth
variant="outlined"
onChange={handleValueChange('dallas_format')}
margin="normal"
>
<MenuItem value={1}>ID</MenuItem>
<MenuItem value={2}>Number</MenuItem>
<MenuItem value={3}>Name</MenuItem>
</SelectValidator>
</Grid>
</Grid>
<br></br> <br></br>
<Typography variant="h6" color="primary"> <Typography variant="h6" color="primary">
Syslog Syslog
@@ -464,15 +530,15 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
container container
spacing={1} spacing={1}
direction="row" direction="row"
justify="flex-start" justifyContent="flex-start"
alignItems="flex-start" alignItems="flex-start"
> >
<Grid item xs={5}> <Grid item xs={5}>
<TextValidator <TextValidator
validators={['isOptionalIP']} validators={['isOptionalIPorHost']}
errorMessages={['Not a valid IP address']} errorMessages={['Not a valid IPv4 address or hostname']}
name="syslog_host" name="syslog_host"
label="IP" label="Host"
fullWidth fullWidth
variant="outlined" variant="outlined"
value={data.syslog_host} value={data.syslog_host}
@@ -537,7 +603,7 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
'Max value is 10' 'Max value is 10'
]} ]}
name="syslog_mark_interval" name="syslog_mark_interval"
label="Mark Interval seconds (0=off)" label="Mark Interval (seconds, 0=off)"
fullWidth fullWidth
variant="outlined" variant="outlined"
value={data.syslog_mark_interval} value={data.syslog_mark_interval}
@@ -554,7 +620,7 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
value="trace_raw" value="trace_raw"
/> />
} }
label="Output EMS telegrams in raw format" label="Output EMS telegrams as hexadecimal bytes"
/> />
</Grid> </Grid>
)} )}

View File

@@ -58,18 +58,18 @@ class EMSESPStatusForm extends Component<EMSESPStatusFormProps> {
<TableContainer> <TableContainer>
<Table <Table
size="small" size="small"
padding={isWidthDown('xs', width!) ? 'none' : 'default'} padding={isWidthDown('xs', width!) ? 'none' : 'normal'}
> >
<TableBody> <TableBody>
<TableRow> <TableRow>
<TableCell># Telegrams Received</TableCell> <TableCell>Telegrams Received</TableCell>
<TableCell align="right"> <TableCell align="right">
{formatNumber(data.rx_received)}&nbsp;(quality{' '} {formatNumber(data.rx_received)}&nbsp;(quality{' '}
{data.rx_quality}%) {data.rx_quality}%)
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell># Telegrams Sent</TableCell> <TableCell>Telegrams Sent</TableCell>
<TableCell align="right"> <TableCell align="right">
{formatNumber(data.tx_sent)}&nbsp;(quality {data.tx_quality} {formatNumber(data.tx_sent)}&nbsp;(quality {data.tx_quality}
%) %)

View File

@@ -1,6 +1,5 @@
export interface EMSESPSettings { export interface EMSESPSettings {
tx_mode: number; tx_mode: number;
tx_delay: number;
ems_bus_id: number; ems_bus_id: number;
syslog_enabled: boolean; syslog_enabled: boolean;
syslog_level: number; syslog_level: number;
@@ -12,15 +11,20 @@ export interface EMSESPSettings {
shower_alert: boolean; shower_alert: boolean;
rx_gpio: number; rx_gpio: number;
tx_gpio: number; tx_gpio: number;
phy_type: number;
dallas_gpio: number; dallas_gpio: number;
dallas_parasite: boolean; dallas_parasite: boolean;
led_gpio: number; led_gpio: number;
hide_led: boolean; hide_led: boolean;
low_clock: boolean;
notoken_api: boolean; notoken_api: boolean;
analog_enabled: boolean; analog_enabled: boolean;
pbutton_gpio: number; pbutton_gpio: number;
trace_raw: boolean; trace_raw: boolean;
board_profile: string; board_profile: string;
bool_format: number;
dallas_format: number;
enum_format: number;
} }
export enum busConnectionStatus { export enum busConnectionStatus {
@@ -38,35 +42,38 @@ export interface EMSESPStatus {
} }
export interface Device { export interface Device {
id: number; i: number; // id
type: string; t: string; // type
brand: string; b: string; // brand
name: string; n: string; // name
deviceid: number; d: number; // deviceid
productid: number; p: number; // productid
version: string; v: string; // version
} }
export interface Sensor { export interface Sensor {
no: number; n: number; // np
id: string; i: string; // id
temp: string; t: number; // temp
o: number; // offset
} }
export interface EMSESPDevices { export interface EMSESPData {
devices: Device[]; devices: Device[];
sensors: Sensor[]; sensors: Sensor[];
analog: number;
} }
export interface DeviceValue { export interface DeviceValue {
v: any; v: any; // value, in any format
u: number; u: number; // uom
n: string; n: string; // name
c: string; c: string; // command
l: string[]; // list
} }
export interface EMSESPDeviceData { export interface EMSESPDeviceData {
name: string; type: string;
data: DeviceValue[]; data: DeviceValue[];
} }
@@ -86,8 +93,9 @@ export enum DeviceValueUOM {
KB, KB,
SECONDS, SECONDS,
DBM, DBM,
NUM, MV,
BOOLEAN TIMES,
OCLOCK
} }
export const DeviceValueUOM_s = [ export const DeviceValueUOM_s = [
@@ -104,8 +112,9 @@ export const DeviceValueUOM_s = [
'kW', 'kW',
'W', 'W',
'KB', 'KB',
'seconds', 'second',
'dBm', 'dBm',
'number', 'mV',
'on/off' 'time',
"o'clock"
]; ];

View File

@@ -23,7 +23,7 @@ class ProjectMenu extends Component<ProjectProps> {
to="/ems-esp/" to="/ems-esp/"
selected={ selected={
path.startsWith('/ems-esp/status') || path.startsWith('/ems-esp/status') ||
path.startsWith('/ems-esp/devices') || path.startsWith('/ems-esp/data') ||
path.startsWith('/ems-esp/help') path.startsWith('/ems-esp/help')
} }
button button

View File

@@ -0,0 +1,101 @@
import React, { RefObject } from 'react';
import { ValidatorForm, TextValidator } from 'react-material-ui-form-validator';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions
} from '@material-ui/core';
import { FormButton } from '../components';
import { Sensor } from './EMSESPtypes';
interface SensorFormProps {
sensor: Sensor;
onDoneEditing: () => void;
onCancelEditing: () => void;
handleSensorChange: (
data: keyof Sensor
) => (event: React.ChangeEvent<HTMLInputElement>) => void;
}
class SensorForm extends React.Component<SensorFormProps> {
formRef: RefObject<any> = React.createRef();
submit = () => {
this.formRef.current.submit();
};
render() {
const {
sensor,
handleSensorChange,
onDoneEditing,
onCancelEditing
} = this.props;
return (
<ValidatorForm onSubmit={onDoneEditing} ref={this.formRef}>
<Dialog
maxWidth="xs"
onClose={onCancelEditing}
aria-labelledby="user-form-dialog-title"
open
>
<DialogTitle id="user-form-dialog-title">
Editing Sensor #{sensor.n}
</DialogTitle>
<DialogContent dividers>
<TextValidator
validators={['matchRegexp:^([a-zA-Z0-9_.-]{0,19})$']}
errorMessages={['Not a valid name']}
fullWidth
variant="outlined"
value={sensor.i}
onChange={handleSensorChange('i')}
margin="normal"
label="Name"
name="id"
/>
<TextValidator
validators={['isFloat', 'minFloat:-5', 'maxFloat:5']}
errorMessages={[
'Must be a number',
'Must be greater than -5',
'Max value is +5'
]}
label="Custom Offset (°C)"
name="offset"
type="number"
value={sensor.o}
fullWidth
variant="outlined"
InputProps={{ inputProps: { min: '-5', max: '5', step: '0.1' } }}
margin="normal"
onChange={handleSensorChange('o')}
/>
</DialogContent>
<DialogActions>
<FormButton
variant="contained"
color="secondary"
onClick={onCancelEditing}
>
Cancel
</FormButton>
<FormButton
variant="contained"
color="primary"
type="submit"
onClick={this.submit}
>
Done
</FormButton>
</DialogActions>
</Dialog>
</ValidatorForm>
);
}
}
export default SensorForm;

View File

@@ -15,7 +15,7 @@ import {
} from '@material-ui/core'; } from '@material-ui/core';
import { FormButton } from '../components'; import { FormButton } from '../components';
import { DeviceValue, DeviceValueUOM, DeviceValueUOM_s } from './EMSESPtypes'; import { DeviceValue, DeviceValueUOM_s } from './EMSESPtypes';
interface ValueFormProps { interface ValueFormProps {
devicevalue: DeviceValue; devicevalue: DeviceValue;
@@ -25,7 +25,6 @@ interface ValueFormProps {
data: keyof DeviceValue data: keyof DeviceValue
) => (event: React.ChangeEvent<HTMLInputElement>) => void; ) => (event: React.ChangeEvent<HTMLInputElement>) => void;
} }
class ValueForm extends React.Component<ValueFormProps> { class ValueForm extends React.Component<ValueFormProps> {
formRef: RefObject<any> = React.createRef(); formRef: RefObject<any> = React.createRef();
@@ -51,25 +50,7 @@ class ValueForm extends React.Component<ValueFormProps> {
> >
<DialogTitle id="user-form-dialog-title">Change Value</DialogTitle> <DialogTitle id="user-form-dialog-title">Change Value</DialogTitle>
<DialogContent dividers> <DialogContent dividers>
{devicevalue.u !== DeviceValueUOM.BOOLEAN && ( {devicevalue.l && (
<OutlinedInput
id="outlined-adornment-value"
value={devicevalue.v}
autoFocus
fullWidth
onChange={handleValueChange('v')}
endAdornment={
<InputAdornment position="end">
{DeviceValueUOM_s[devicevalue.u]}
</InputAdornment>
}
aria-describedby="outlined-value-helper-text"
inputProps={{
'aria-label': 'value'
}}
/>
)}
{devicevalue.u === DeviceValueUOM.BOOLEAN && (
<TextField <TextField
id="outlined-select-value" id="outlined-select-value"
select select
@@ -79,13 +60,26 @@ class ValueForm extends React.Component<ValueFormProps> {
onChange={handleValueChange('v')} onChange={handleValueChange('v')}
variant="outlined" variant="outlined"
> >
<MenuItem value="true">on</MenuItem> {devicevalue.l.map((val) => (
<MenuItem value="false">off</MenuItem> <MenuItem value={val}>{val}</MenuItem>
))}
</TextField> </TextField>
)} )}
<FormHelperText id="outlined-value-helper-text"> {!devicevalue.l && (
{devicevalue.n} <OutlinedInput
</FormHelperText> id="value"
value={devicevalue.v}
autoFocus
fullWidth
onChange={handleValueChange('v')}
endAdornment={
<InputAdornment position="end">
{DeviceValueUOM_s[devicevalue.u]}
</InputAdornment>
}
/>
)}
<FormHelperText>{devicevalue.n}</FormHelperText>
<Box color="warning.main" p={0} pl={0} pr={0} mt={4} mb={0}> <Box color="warning.main" p={0} pl={0} pr={0} mt={4} mb={0}>
<Typography variant="body2"> <Typography variant="body2">
<i> <i>

View File

@@ -44,7 +44,6 @@ class GenerateToken extends React.Component<
} }
}) })
.then((generatedToken) => { .then((generatedToken) => {
// console.log(generatedToken);
this.setState({ token: generatedToken.token }); this.setState({ token: generatedToken.token });
}) })
.catch((error) => { .catch((error) => {

View File

@@ -150,7 +150,7 @@ class ManageUsersForm extends React.Component<
<ValidatorForm onSubmit={this.onSubmit}> <ValidatorForm onSubmit={this.onSubmit}>
<Table <Table
size="small" size="small"
padding={isWidthDown('xs', width!) ? 'none' : 'default'} padding={isWidthDown('xs', width!) ? 'none' : 'normal'}
> >
<TableHead> <TableHead>
<TableRow> <TableRow>
@@ -197,7 +197,7 @@ class ManageUsersForm extends React.Component<
<TableFooter> <TableFooter>
<TableRow> <TableRow>
<TableCell colSpan={2} /> <TableCell colSpan={2} />
<TableCell align="center" padding="default"> <TableCell align="center" padding="normal">
<Button <Button
startIcon={<PersonAddIcon />} startIcon={<PersonAddIcon />}
variant="contained" variant="contained"

View File

@@ -6,6 +6,8 @@ import { useWindowSize } from '../components';
interface LogEventConsoleProps { interface LogEventConsoleProps {
events: LogEvent[]; events: LogEvent[];
compact: boolean;
level: number;
} }
interface Offsets { interface Offsets {
@@ -32,8 +34,8 @@ const useStyles = makeStyles((theme: Theme) => ({
}, },
entry: { entry: {
color: '#bbbbbb', color: '#bbbbbb',
fontFamily: 'Courier New, monospace', fontFamily: 'monospace',
fontSize: '13px', fontSize: '14px',
letterSpacing: 'normal', letterSpacing: 'normal',
whiteSpace: 'nowrap' whiteSpace: 'nowrap'
}, },
@@ -63,7 +65,7 @@ const useStyles = makeStyles((theme: Theme) => ({
const LogEventConsole: FC<LogEventConsoleProps> = (props) => { const LogEventConsole: FC<LogEventConsoleProps> = (props) => {
useWindowSize(); useWindowSize();
const classes = useStyles({ topOffset, leftOffset }); const classes = useStyles({ topOffset, leftOffset });
const { events } = props; const { events, compact } = props;
const styleLevel = (level: LogLevel) => { const styleLevel = (level: LogLevel) => {
switch (level) { switch (level) {
@@ -103,23 +105,34 @@ const LogEventConsole: FC<LogEventConsoleProps> = (props) => {
} }
}; };
const paddedLevelLabel = (level: LogLevel) => { const paddedLevelLabel = (level: LogLevel, compact: boolean) => {
const label = levelLabel(level); const label = levelLabel(level);
return label.padStart(8, '\xa0'); return compact ? ' ' + label[0] : label.padStart(8, '\xa0');
}; };
const paddedNameLabel = (name: string) => { const paddedNameLabel = (name: string, compact: boolean) => {
const label = '[' + name + ']'; const label = '[' + name + ']';
return label.padStart(8, '\xa0'); return compact ? label : label.padEnd(12, '\xa0');
};
const paddedIDLabel = (id: number, compact: boolean) => {
const label = id + ':';
return compact ? label : label.padEnd(7, '\xa0');
}; };
return ( return (
<Box id="log-window" className={classes.console}> <Box id="log-window" className={classes.console}>
{events.map((e) => ( {events.map((e) => (
<div className={classes.entry}> <div className={classes.entry} key={e.i}>
<span>{e.t}</span> <span>{e.t}</span>
<span className={styleLevel(e.l)}>{paddedLevelLabel(e.l)} </span> {compact && <span>{paddedLevelLabel(e.l, compact)} </span>}
<span>{paddedNameLabel(e.n)} </span> {!compact && (
<span className={styleLevel(e.l)}>
{paddedLevelLabel(e.l, compact)}{' '}
</span>
)}
<span>{paddedIDLabel(e.i, compact)} </span>
<span>{paddedNameLabel(e.n, compact)} </span>
<span>{e.m}</span> <span>{e.m}</span>
</div> </div>
))} ))}

View File

@@ -3,22 +3,38 @@ import { Component } from 'react';
import { import {
restController, restController,
RestControllerProps, RestControllerProps,
RestFormLoader, SectionContent,
SectionContent BlockFormControlLabel
} from '../components'; } from '../components';
import { addAccessTokenParameter } from '../authentication'; import {
ValidatorForm,
SelectValidator
} from 'react-material-ui-form-validator';
import {
Grid,
Slider,
FormLabel,
Checkbox,
MenuItem,
Button
} from '@material-ui/core';
import {
addAccessTokenParameter,
redirectingAuthorizedFetch
} from '../authentication';
import DownloadIcon from '@material-ui/icons/GetApp';
import { ENDPOINT_ROOT, EVENT_SOURCE_ROOT } from '../api'; import { ENDPOINT_ROOT, EVENT_SOURCE_ROOT } from '../api';
export const FETCH_LOG_ENDPOINT = ENDPOINT_ROOT + 'fetchLog'; export const FETCH_LOG_ENDPOINT = ENDPOINT_ROOT + 'fetchLog';
export const LOG_SETTINGS_ENDPOINT = ENDPOINT_ROOT + 'logSettings'; export const LOG_SETTINGS_ENDPOINT = ENDPOINT_ROOT + 'logSettings';
export const LOG_EVENT_EVENT_SOURCE_URL = EVENT_SOURCE_ROOT + 'log'; export const LOG_EVENT_EVENT_SOURCE_URL = EVENT_SOURCE_ROOT + 'log';
import LogEventForm from './LogEventForm';
import LogEventConsole from './LogEventConsole'; import LogEventConsole from './LogEventConsole';
import { LogEvent, LogSettings, LogLevel } from './types';
import { LogEvent, LogSettings } from './types';
import { Decoder } from '@msgpack/msgpack'; import { Decoder } from '@msgpack/msgpack';
const decoder = new Decoder(); const decoder = new Decoder();
@@ -26,6 +42,10 @@ const decoder = new Decoder();
interface LogEventControllerState { interface LogEventControllerState {
eventSource?: EventSource; eventSource?: EventSource;
events: LogEvent[]; events: LogEvent[];
compact: boolean;
level: number;
max_messages: number;
last_id: number;
} }
type LogEventControllerProps = RestControllerProps<LogSettings>; type LogEventControllerProps = RestControllerProps<LogSettings>;
@@ -40,12 +60,16 @@ class LogEventController extends Component<
constructor(props: LogEventControllerProps) { constructor(props: LogEventControllerProps) {
super(props); super(props);
this.state = { this.state = {
events: [] events: [],
compact: false,
level: 6,
max_messages: 25,
last_id: 0
}; };
} }
componentDidMount() { componentDidMount() {
this.props.loadData(); this.fetchValues();
this.fetchLog(); this.fetchLog();
this.configureEventSource(); this.configureEventSource();
} }
@@ -59,6 +83,20 @@ class LogEventController extends Component<
} }
} }
changeCompact = (
event: React.ChangeEvent<HTMLInputElement>,
checked: boolean
) => {
this.setState({
compact: checked
});
this.send_data(
this.state.level,
this.state.max_messages,
checked as boolean
);
};
fetchLog = () => { fetchLog = () => {
fetch(FETCH_LOG_ENDPOINT) fetch(FETCH_LOG_ENDPOINT)
.then((response) => { .then((response) => {
@@ -78,6 +116,29 @@ class LogEventController extends Component<
}); });
}; };
fetchValues = () => {
redirectingAuthorizedFetch(LOG_SETTINGS_ENDPOINT)
.then((response) => {
if (response.status === 200) {
return response.json();
}
throw Error('Unexpected status code: ' + response.status);
})
.then((json) => {
this.setState({
level: json.level,
max_messages: json.max_messages,
compact: json.compact
});
})
.catch((error) => {
const errorMessage = error.message || 'Unknown error';
this.props.enqueueSnackbar('Problem fetching: ' + errorMessage, {
variant: 'error'
});
});
};
configureEventSource = () => { configureEventSource = () => {
this.eventSource = new EventSource( this.eventSource = new EventSource(
addAccessTokenParameter(LOG_EVENT_EVENT_SOURCE_URL) addAccessTokenParameter(LOG_EVENT_EVENT_SOURCE_URL)
@@ -98,18 +159,183 @@ class LogEventController extends Component<
const rawData = event.data; const rawData = event.data;
if (typeof rawData === 'string' || rawData instanceof String) { if (typeof rawData === 'string' || rawData instanceof String) {
const event = JSON.parse(rawData as string) as LogEvent; const event = JSON.parse(rawData as string) as LogEvent;
this.setState((state) => ({ events: [...state.events, event] })); if (event.i > this.state.last_id) {
this.setState({ last_id: event.i });
this.setState((state) => ({ events: [...state.events, event] }));
}
} }
}; };
changeMaxMessages = (
event: React.ChangeEvent<{}>,
value: number | number[]
) => {
this.setState({
max_messages: value as number
});
this.send_data(this.state.level, value as number, this.state.compact);
};
changeLevel = (event: React.ChangeEvent<HTMLSelectElement>) => {
this.setState({
level: parseInt(event.target.value)
});
this.send_data(
parseInt(event.target.value),
this.state.max_messages,
this.state.compact
);
};
send_data = (level: number, max_messages: number, compact: boolean) => {
redirectingAuthorizedFetch(LOG_SETTINGS_ENDPOINT, {
method: 'POST',
body: JSON.stringify({
level: level,
max_messages: max_messages,
compact: compact
}),
headers: {
'Content-Type': 'application/json'
}
})
.then((response) => {
if (response.status !== 200) {
throw Error('Unexpected response code: ' + response.status);
}
})
.catch((error) => {
this.props.enqueueSnackbar(
error.message || 'Problem applying log settings',
{ variant: 'warning' }
);
});
};
levelLabel = (level: LogLevel) => {
switch (level) {
case LogLevel.ERROR:
return 'E';
case LogLevel.WARNING:
return 'W';
case LogLevel.NOTICE:
return 'N';
case LogLevel.INFO:
return 'I';
case LogLevel.DEBUG:
return 'D';
case LogLevel.TRACE:
return 'T';
default:
return '';
}
};
onDownload = () => {
const { events } = this.state;
let result = '';
for (const i in events) {
result +=
events[i].t +
' ' +
this.levelLabel(events[i].l) +
' ' +
events[i].i +
': [' +
events[i].n +
'] ' +
events[i].m +
'\n';
}
const a = document.createElement('a');
a.setAttribute(
'href',
'data:text/plain;charset=utf-8,' + encodeURIComponent(result)
);
a.setAttribute('download', 'log.txt');
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
render() { render() {
const { saveData } = this.props;
return ( return (
<SectionContent title="System Log" id="log-window"> <SectionContent title="System Log" id="log-window">
<RestFormLoader <ValidatorForm onSubmit={saveData}>
{...this.props} <Grid
render={(formProps) => <LogEventForm {...formProps} />} container
spacing={3}
direction="row"
justifyContent="flex-start"
alignItems="center"
>
<Grid item xs={2}>
<SelectValidator
name="level"
label="Log Level"
value={this.state.level}
fullWidth
variant="outlined"
onChange={this.changeLevel}
margin="normal"
>
<MenuItem value={3}>ERROR</MenuItem>
<MenuItem value={4}>WARNING</MenuItem>
<MenuItem value={5}>NOTICE</MenuItem>
<MenuItem value={6}>INFO</MenuItem>
<MenuItem value={7}>DEBUG</MenuItem>
<MenuItem value={8}>ALL</MenuItem>
</SelectValidator>
</Grid>
<Grid item xs={2}>
<FormLabel>Buffer size</FormLabel>
<Slider
value={this.state.max_messages}
valueLabelDisplay="auto"
name="max_messages"
marks={[
{ value: 25, label: '25' },
{ value: 50, label: '50' },
{ value: 75, label: '75' },
{ value: 100, label: '100' }
]}
step={25}
min={25}
max={100}
onChange={this.changeMaxMessages}
/>
</Grid>
<Grid item xs={4}>
<BlockFormControlLabel
control={
<Checkbox
checked={this.state.compact}
onChange={this.changeCompact}
value="compact"
/>
}
label="Compact Layout"
/>
</Grid>
<Grid item md>
<Button
startIcon={<DownloadIcon />}
variant="contained"
color="primary"
onClick={this.onDownload}
>
Download
</Button>
</Grid>
</Grid>
</ValidatorForm>
<LogEventConsole
level={this.state.level}
compact={this.state.compact}
events={this.state.events}
/> />
<LogEventConsole events={this.state.events} />
</SectionContent> </SectionContent>
); );
} }

View File

@@ -1,107 +0,0 @@
import { Component } from 'react';
import {
ValidatorForm,
SelectValidator
} from 'react-material-ui-form-validator';
import { Typography, Grid } from '@material-ui/core';
import MenuItem from '@material-ui/core/MenuItem';
import {
redirectingAuthorizedFetch,
withAuthenticatedContext,
AuthenticatedContextProps
} from '../authentication';
import { RestFormProps } from '../components';
import { LogSettings } from './types';
import { ENDPOINT_ROOT } from '../api';
export const LOG_SETTINGS_ENDPOINT = ENDPOINT_ROOT + 'logSettings';
type LogEventFormProps = AuthenticatedContextProps & RestFormProps<LogSettings>;
class LogEventForm extends Component<LogEventFormProps> {
changeLevel = (event: React.ChangeEvent<HTMLSelectElement>) => {
const { data, setData } = this.props;
setData({
...data,
level: parseInt(event.target.value)
});
redirectingAuthorizedFetch(LOG_SETTINGS_ENDPOINT, {
method: 'POST',
body: JSON.stringify({ level: event.target.value }),
headers: {
'Content-Type': 'application/json'
}
})
.then((response) => {
if (response.status === 200) {
return response.json();
}
throw Error('Unexpected response code: ' + response.status);
})
.then((json) => {
this.props.enqueueSnackbar('Log settings changed', {
variant: 'success'
});
setData({
...data,
level: json.level
});
})
.catch((error) => {
this.props.enqueueSnackbar(
error.message || 'Problem changing log settings',
{ variant: 'warning' }
);
});
};
render() {
const { data, saveData } = this.props;
return (
<ValidatorForm onSubmit={saveData}>
<Grid
container
spacing={0}
direction="row"
justify="flex-start"
alignItems="center"
>
<Grid item xs={2}>
<SelectValidator
name="level"
label="Log Level"
value={data.level}
variant="outlined"
onChange={this.changeLevel}
margin="normal"
>
<MenuItem value={-1}>OFF</MenuItem>
<MenuItem value={3}>ERROR</MenuItem>
<MenuItem value={4}>WARNING</MenuItem>
<MenuItem value={5}>NOTICE</MenuItem>
<MenuItem value={6}>INFO</MenuItem>
<MenuItem value={7}>DEBUG</MenuItem>
<MenuItem value={8}>ALL</MenuItem>
</SelectValidator>
</Grid>
<Grid item md>
<Typography color="primary" variant="body2">
<i>
(the last {data.max_messages} messages are buffered and new log
events are shown in real time)
</i>
</Typography>
</Grid>
</Grid>
</ValidatorForm>
);
}
}
export default withAuthenticatedContext(LogEventForm);

View File

@@ -33,15 +33,19 @@ import {
AuthenticatedContextProps, AuthenticatedContextProps,
withAuthenticatedContext withAuthenticatedContext
} from '../authentication'; } from '../authentication';
import { RestFormProps, FormButton, ErrorButton } from '../components'; import { RestFormProps, FormButton, ErrorButton } from '../components';
import { FACTORY_RESET_ENDPOINT, RESTART_ENDPOINT } from '../api'; import { FACTORY_RESET_ENDPOINT, RESTART_ENDPOINT } from '../api';
import { SystemStatus, EspPlatform } from './types'; import { SystemStatus, EspPlatform } from './types';
import VersionCheck from './VersionCheck';
interface SystemStatusFormState { interface SystemStatusFormState {
confirmRestart: boolean; confirmRestart: boolean;
confirmFactoryReset: boolean; confirmFactoryReset: boolean;
processing: boolean; processing: boolean;
currentVersion?: string;
} }
type SystemStatusFormProps = AuthenticatedContextProps & type SystemStatusFormProps = AuthenticatedContextProps &
@@ -61,6 +65,16 @@ class SystemStatusForm extends Component<
processing: false processing: false
}; };
onVersionCheck = (version: string) => {
this.setState({ currentVersion: version });
};
closeVersionCheck = () => {
this.setState({
currentVersion: undefined
});
};
createListItems() { createListItems() {
const { data } = this.props; const { data } = this.props;
return ( return (
@@ -75,7 +89,14 @@ class SystemStatusForm extends Component<
primary="EMS-ESP Version" primary="EMS-ESP Version"
secondary={'v' + data.emsesp_version} secondary={'v' + data.emsesp_version}
/> />
<Button
color="primary"
onClick={() => this.onVersionCheck(data.emsesp_version)}
>
Check for updates
</Button>
</ListItem> </ListItem>
<Divider variant="inset" component="li" />
<ListItem> <ListItem>
<ListItemAvatar> <ListItemAvatar>
<Avatar> <Avatar>
@@ -304,9 +325,16 @@ class SystemStatusForm extends Component<
render() { render() {
const me = this.props.authenticatedContext.me; const me = this.props.authenticatedContext.me;
const { currentVersion } = this.state;
return ( return (
<Fragment> <Fragment>
<List>{this.createListItems()}</List> <List>{this.createListItems()}</List>
{currentVersion && (
<VersionCheck
currentVersion={currentVersion}
onClose={this.closeVersionCheck}
/>
)}
<Box display="flex" flexWrap="wrap"> <Box display="flex" flexWrap="wrap">
<Box flexGrow={1} padding={1}> <Box flexGrow={1} padding={1}>
<FormButton <FormButton

View File

@@ -0,0 +1,211 @@
import React, { Fragment } from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Box,
Link,
LinearProgress,
Typography
} from '@material-ui/core';
import { FormButton } from '../components';
import { withSnackbar, WithSnackbarProps } from 'notistack';
export const VERSIONCHECK_ENDPOINT =
'https://api.github.com/repos/emsesp/EMS-ESP32/releases/latest';
export const VERSIONCHECK_DEV_ENDPOINT =
'https://api.github.com/repos/emsesp/EMS-ESP32/releases/tags/latest';
export const uploadURL = window.location.origin + '/system/upload';
interface VersionCheckProps extends WithSnackbarProps {
currentVersion: string;
onClose: () => void;
}
interface VersionCheckState {
latestVersion?: string;
latestVersionUrl?: string;
latestVersionChangelog?: string;
latestDevVersion?: string;
latestDevVersionUrl?: string;
latestDevVersionChangelog?: string;
}
class VersionCheck extends React.Component<
VersionCheckProps,
VersionCheckState
> {
state: VersionCheckState = {};
componentDidMount() {
fetch(VERSIONCHECK_ENDPOINT)
.then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw Error(
'Unable to get version information. Check internet connection. (' +
response.status +
')'
);
}
})
.then((data) => {
this.setState({
latestVersion: data.name,
latestVersionUrl: data.assets[1].browser_download_url,
latestVersionChangelog: data.html_url
});
})
.catch((error) => {
this.props.enqueueSnackbar(
error.message || 'Problem getting response',
{ variant: 'error' }
);
this.setState({ latestVersion: undefined });
this.props.onClose();
});
fetch(VERSIONCHECK_DEV_ENDPOINT)
.then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw Error(
'Unable to get version information. Check internet connection. (' +
response.status +
')'
);
}
})
.then((data) => {
this.setState({
latestDevVersion: data.name.split(/\s+/).splice(-1),
latestDevVersionUrl: data.assets[1].browser_download_url,
latestDevVersionChangelog: data.assets[0].browser_download_url
});
})
.catch((error) => {
this.props.enqueueSnackbar(
error.message || 'Problem getting response',
{ variant: 'error' }
);
this.setState({ latestDevVersion: undefined });
this.props.onClose();
});
}
render() {
const { onClose, currentVersion } = this.props;
const {
latestVersion,
latestVersionUrl,
latestDevVersion,
latestDevVersionUrl,
latestVersionChangelog,
latestDevVersionChangelog
} = this.state;
return (
<Dialog
onClose={onClose}
aria-labelledby="version-check-dialog-title"
open
fullWidth
maxWidth="sm"
>
<DialogTitle id="version-check-dialog-title">
Firmware Update Check
</DialogTitle>
<DialogContent dividers>
{latestVersion ? (
<Fragment>
<Box
bgcolor="primary.main"
color="primary.contrastText"
p={2}
mt={2}
mb={2}
>
<Typography variant="body1">
You are currently running EMS-ESP version{' '}
<b>v{currentVersion}</b>
</Typography>
</Box>
<Box mt={2} mb={2}>
The latest <u>stable</u> version is <b>{latestVersion}</b>
&nbsp;(
<Link
target="_blank"
href={latestVersionChangelog}
color="primary"
>
{'release notes'}
</Link>
)&nbsp;(
<Link target="_blank" href={latestVersionUrl} color="primary">
{'download'}
</Link>
)
</Box>
<Box mt={2} mb={2}>
The latest <u>development</u> version is&nbsp;
<b>{latestDevVersion}</b>
&nbsp;(
<Link
target="_blank"
href={latestDevVersionChangelog}
color="primary"
>
{'release notes'}
</Link>
)&nbsp;(
<Link
target="_blank"
href={latestDevVersionUrl}
color="primary"
>
{'download'}
</Link>
)
</Box>
<Box color="warning.main" p={0} pl={0} pr={0} mt={4} mb={0}>
<Typography variant="body2">
<i>
Use&nbsp;
<Link target="_blank" href={uploadURL} color="primary">
{'UPLOAD FIRMWARE'}
</Link>
&nbsp;to install any new firmware versions.
</i>
</Typography>
</Box>
</Fragment>
) : (
<Box m={4} textAlign="center">
<LinearProgress />
<Typography variant="h6">
Fetching version details&hellip;
</Typography>
</Box>
)}
</DialogContent>
<DialogActions>
<FormButton
variant="contained"
color="primary"
type="submit"
onClick={onClose}
>
Close
</FormButton>
</DialogActions>
</Dialog>
);
}
}
export default withSnackbar(VersionCheck);

View File

@@ -50,6 +50,7 @@ export enum LogLevel {
export interface LogEvent { export interface LogEvent {
t: string; t: string;
l: LogLevel; l: LogLevel;
i: number;
n: string; n: string;
m: string; m: string;
} }
@@ -57,4 +58,5 @@ export interface LogEvent {
export interface LogSettings { export interface LogSettings {
level: LogLevel; level: LogLevel;
max_messages: number; max_messages: number;
compact: boolean;
} }

View File

@@ -0,0 +1,33 @@
type UpdateEntity<S> = (state: (prevState: Readonly<S>) => S) => void;
export const extractEventValue = (
event: React.ChangeEvent<HTMLInputElement>
) => {
switch (event.target.type) {
case 'number':
return event.target.valueAsNumber;
case 'checkbox':
return event.target.checked;
default:
return event.target.value;
}
};
export const updateValue = <S>(updateEntity: UpdateEntity<S>) => (
event: React.ChangeEvent<HTMLInputElement>
) => {
updateEntity((prevState) => ({
...prevState,
[event.target.name]: extractEventValue(event)
}));
};
export const updateBooleanValue = <S>(updateEntity: UpdateEntity<S>) => (
name: string,
value?: boolean
) => {
updateEntity((prevState) => ({
...prevState,
[name]: value
}));
};

View File

@@ -0,0 +1 @@
export * from './binding';

View File

@@ -3,3 +3,4 @@ export { default as isIP } from './isIP';
export { default as optional } from './optional'; export { default as optional } from './optional';
export { default as or } from './or'; export { default as or } from './or';
export { default as isPath } from './isPath'; export { default as isPath } from './isPath';
export { default as isIPv4 } from './isIPv4';

View File

@@ -1,4 +1,4 @@
const ipAddressRegexp = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; const ipAddressRegexp = /((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))/;
export default function isIp(ipAddress: string) { export default function isIp(ipAddress: string) {
return ipAddressRegexp.test(ipAddress); return ipAddressRegexp.test(ipAddress);

View File

@@ -0,0 +1,5 @@
const ipv4AddressRegexp = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
export default function isIpv4(ipAddress: string) {
return ipv4AddressRegexp.test(ipAddress);
}

View File

@@ -1,6 +1,39 @@
ArduinoJson: change log ArduinoJson: change log
======================= =======================
v6.18.4 (2021-09-06)
-------
* Fixed error `'dummy' may be used uninitialized` on GCC 11
* Fixed error `expected unqualified-id before 'const'` on GCC 11 (issue #1622)
* Filter: exact match takes precedence over wildcard (issue #1628)
* Fixed deserialization of `\u0000` (issue #1646)
v6.18.3 (2021-07-27)
-------
* Changed return type of `convertToJson()` and `Converter<T>::toJson()` to `void`
* Added `as<std::string_view>()` and `is<std::string_view>()`
v6.18.2 (2021-07-19)
-------
* Removed a symlink because the Arduino Library Specification forbids it
v6.18.1 (2021-07-03)
-------
* Fixed support for `volatile float` and `volatile double` (issue #1557)
* Fixed error `[Pe070]: incomplete type is not allowed` on IAR (issue #1560)
* Fixed `serializeJson(doc, String)` when allocation fails (issue #1572)
* Fixed clang-tidy warnings (issue #1574, PR #1577 by @armandas)
* Added fake class `InvalidConversion<T1,T2>` to easily identify invalid conversions (issue #1585)
* Added support for `std::string_view` (issue #1578, PR #1554 by @0xFEEDC0DE64)
* Fixed warning `definition of implicit copy constructor for 'MsgPackDeserializer' is deprecated because it has a user-declared copy assignment operator`
* Added `JsonArray::clear()` (issue #1597)
* Fixed `JsonVariant::as<unsigned>()` (issue #1601)
* Added support for ESP-IDF component build (PR #1562 by @qt1, PR #1599 by @andreaskuster)
v6.18.0 (2021-05-05) v6.18.0 (2021-05-05)
------- -------

View File

@@ -2,7 +2,7 @@
--- ---
[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.18.0)](https://www.ardu-badge.com/ArduinoJson/6.18.0) [![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.18.4)](https://www.ardu-badge.com/ArduinoJson/6.18.4)
[![Continuous Integration](https://github.com/bblanchon/ArduinoJson/workflows/Continuous%20Integration/badge.svg?branch=6.x)](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A6.x) [![Continuous Integration](https://github.com/bblanchon/ArduinoJson/workflows/Continuous%20Integration/badge.svg?branch=6.x)](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A6.x)
[![Continuous Integration](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [![Continuous Integration](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
@@ -33,15 +33,15 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
* [Optionally works without heap memory (zero malloc)](https://arduinojson.org/v6/api/staticjsondocument/?utm_source=github&utm_medium=readme) * [Optionally works without heap memory (zero malloc)](https://arduinojson.org/v6/api/staticjsondocument/?utm_source=github&utm_medium=readme)
* Deduplicates strings * Deduplicates strings
* Versatile * Versatile
* [Supports custom allocators (to use external RAM chip, for example)](https://arduinojson.org/v6/how-to/use-external-ram-on-esp32/?utm_source=github&utm_medium=readme) * Supports [custom allocators (to use external RAM chip, for example)](https://arduinojson.org/v6/how-to/use-external-ram-on-esp32/?utm_source=github&utm_medium=readme)
* Supports [Arduino's `String`](https://arduinojson.org/v6/api/config/enable_arduino_string/?utm_source=github&utm_medium=readme) and [STL's `std::string`](https://arduinojson.org/v6/api/config/enable_std_string/?utm_source=github&utm_medium=readme) * Supports [`String`](https://arduinojson.org/v6/api/config/enable_arduino_string/?utm_source=github&utm_medium=readme), [`std::string`](https://arduinojson.org/v6/api/config/enable_std_string/?utm_source=github&utm_medium=readme) and [`std::string_view`](https://arduinojson.org/v6/api/config/enable_string_view/?utm_source=github&utm_medium=readme)
* Supports [Arduino's `Stream`](https://arduinojson.org/v6/api/config/enable_arduino_stream/?utm_source=github&utm_medium=readme) and [STL's `std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/?utm_source=github&utm_medium=readme) * Supports [`Stream`](https://arduinojson.org/v6/api/config/enable_arduino_stream/?utm_source=github&utm_medium=readme) and [`std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/?utm_source=github&utm_medium=readme)
* [Supports Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/?utm_source=github&utm_medium=readme) * Supports [Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/?utm_source=github&utm_medium=readme)
* Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme#custom-writer) * Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme#custom-writer)
* Supports custom converters * Supports [custom converters](https://arduinojson.org/news/2021/05/04/version-6-18-0/?utm_source=github&utm_medium=readme)
* Portable * Portable
* Usable on any C++ project (not limited to Arduino) * Usable on any C++ project (not limited to Arduino)
* Compatible with C++98 * Compatible with C++98, C++11, C++14 and C++17
* Zero warnings with `-Wall -Wextra -pedantic` and `/W4` * Zero warnings with `-Wall -Wextra -pedantic` and `/W4`
* [Header-only library](https://en.wikipedia.org/wiki/Header-only) * [Header-only library](https://en.wikipedia.org/wiki/Header-only)
* Works with virtually any board * Works with virtually any board
@@ -78,18 +78,20 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
* [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x) * [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
* Continuously tested on * Continuously tested on
* [Visual Studio 2010, 2012, 2013, 2015, 2017, 2019](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) * [Visual Studio 2010, 2012, 2013, 2015, 2017, 2019](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
* [GCC 4.4, 4.6, 4.7, 4.8, 4.9, 5, 6, 7, 8, 9, 10](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) * [GCC 4.4, 4.6, 4.7, 4.8, 4.9, 5, 6, 7, 8, 9, 10, 11](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22)
* [Clang 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 5.0, 6.0, 7, 8, 9, 10](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) * [Clang 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 5.0, 6.0, 7, 8, 9, 10](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22)
* [Continuously fuzzed with Google OSS Fuzz](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) * [Continuously fuzzed with Google OSS Fuzz](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
* Passes all default checks of [clang-tidy](https://releases.llvm.org/10.0.0/tools/clang/tools/extra/docs/clang-tidy/)
* Well documented * Well documented
* [Tutorials](https://arduinojson.org/v6/doc/deserialization/?utm_source=github&utm_medium=readme) * [Tutorials](https://arduinojson.org/v6/doc/deserialization/?utm_source=github&utm_medium=readme)
* [Examples](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme) * [Examples](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme)
* [How-tos](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme) * [How-tos](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme)
* [FAQ](https://arduinojson.org/v6/faq/?utm_source=github&utm_medium=readme) * [FAQ](https://arduinojson.org/v6/faq/?utm_source=github&utm_medium=readme)
* [Troubleshooter](https://arduinojson.org/v6/troubleshooter/?utm_source=github&utm_medium=readme)
* [Book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme) * [Book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme)
* [Changelog](CHANGELOG.md) * [Changelog](CHANGELOG.md)
* Vibrant user community * Vibrant user community
* Most popular of all Arduino libraries on [GitHub](https://github.com/search?o=desc&q=arduino+library&s=stars&type=Repositories) and [PlatformIO](https://platformio.org/lib/search) * Most popular of all Arduino libraries on [GitHub](https://github.com/search?o=desc&q=arduino+library&s=stars&type=Repositories)
* [Used in hundreds of projects](https://www.hackster.io/search?i=projects&q=arduinojson) * [Used in hundreds of projects](https://www.hackster.io/search?i=projects&q=arduinojson)
* [Responsive support](https://github.com/bblanchon/ArduinoJson/issues?q=is%3Aissue+is%3Aclosed) * [Responsive support](https://github.com/bblanchon/ArduinoJson/issues?q=is%3Aissue+is%3Aclosed)
@@ -132,9 +134,11 @@ serializeJson(doc, Serial);
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/encoding/?utm_source=github&utm_medium=readme) See the [tutorial on arduinojson.org](https://arduinojson.org/doc/encoding/?utm_source=github&utm_medium=readme)
## Support the project ## Support the project ❤️
Do you like this library? Please [star this project on GitHub](https://github.com/bblanchon/ArduinoJson/stargazers)! Do you like this library?
Please [star this project on GitHub](https://github.com/bblanchon/ArduinoJson/stargazers)!
What? You don't like it but you *love* it? What? You don't like it but you *love* it?
We don't take donations anymore, but [we sell a book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme), so you can help and learn at the same time. You can support the project by [purchasing my book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme).
Alternatively, you can make a recurring donation via [GitHub Sponsors](https://github.com/sponsors/bblanchon).

View File

@@ -7,11 +7,11 @@
#include "ArduinoJson/Configuration.hpp" #include "ArduinoJson/Configuration.hpp"
#if !ARDUINOJSON_DEBUG #if !ARDUINOJSON_DEBUG
#ifdef __clang__ # ifdef __clang__
#pragma clang system_header # pragma clang system_header
#elif defined __GNUC__ # elif defined __GNUC__
#pragma GCC system_header # pragma GCC system_header
#endif # endif
#endif #endif
#include "ArduinoJson/Array/ArrayRef.hpp" #include "ArduinoJson/Array/ArrayRef.hpp"

View File

@@ -161,14 +161,20 @@ class ArrayRef : public ArrayRefBase<CollectionData>,
_data->removeElement(index); _data->removeElement(index);
} }
void clear() const {
if (!_data)
return;
_data->clear();
}
private: private:
MemoryPool* _pool; MemoryPool* _pool;
}; };
template <> template <>
struct Converter<ArrayConstRef> { struct Converter<ArrayConstRef> {
static bool toJson(VariantConstRef src, VariantRef dst) { static void toJson(VariantConstRef src, VariantRef dst) {
return variantCopyFrom(getData(dst), getData(src), getPool(dst)); variantCopyFrom(getData(dst), getData(src), getPool(dst));
} }
static ArrayConstRef fromJson(VariantConstRef src) { static ArrayConstRef fromJson(VariantConstRef src) {
@@ -183,8 +189,8 @@ struct Converter<ArrayConstRef> {
template <> template <>
struct Converter<ArrayRef> { struct Converter<ArrayRef> {
static bool toJson(VariantConstRef src, VariantRef dst) { static void toJson(VariantConstRef src, VariantRef dst) {
return variantCopyFrom(getData(dst), getData(src), getPool(dst)); variantCopyFrom(getData(dst), getData(src), getPool(dst));
} }
static ArrayRef fromJson(VariantRef src) { static ArrayRef fromJson(VariantRef src) {
@@ -193,6 +199,8 @@ struct Converter<ArrayRef> {
return ArrayRef(pool, data != 0 ? data->asArray() : 0); return ArrayRef(pool, data != 0 ? data->asArray() : 0);
} }
static InvalidConversion<VariantConstRef, ArrayRef> fromJson(VariantConstRef);
static bool checkJson(VariantConstRef) { static bool checkJson(VariantConstRef) {
return false; return false;
} }

View File

@@ -10,8 +10,8 @@
#include <ArduinoJson/Variant/VariantTo.hpp> #include <ArduinoJson/Variant/VariantTo.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) # pragma warning(push)
#pragma warning(disable : 4522) # pragma warning(disable : 4522)
#endif #endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
@@ -178,8 +178,8 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
return _array.getOrAddElement(_index); return _array.getOrAddElement(_index);
} }
friend bool convertToJson(const this_type& src, VariantRef dst) { friend void convertToJson(const this_type& src, VariantRef dst) {
return dst.set(src.getUpstreamElement()); dst.set(src.getUpstreamElement());
} }
TArray _array; TArray _array;
@@ -189,5 +189,5 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) # pragma warning(pop)
#endif #endif

View File

@@ -62,9 +62,9 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
VariantData* var; VariantData* var;
if (s->key() != 0) { if (s->key() != 0) {
if (s->ownsKey()) if (s->ownsKey())
var = addMember(RamStringAdapter(s->key()), pool); var = addMember(adaptString(const_cast<char*>(s->key())), pool);
else else
var = addMember(ConstRamStringAdapter(s->key()), pool); var = addMember(adaptString(s->key()), pool);
} else { } else {
var = addElement(pool); var = addElement(pool);
} }
@@ -107,7 +107,7 @@ template <typename TAdaptedString>
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const { inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
VariantSlot* slot = _head; VariantSlot* slot = _head;
while (slot) { while (slot) {
if (key.equals(slot->key())) if (key.compare(slot->key()) == 0)
break; break;
slot = slot->next(); slot = slot->next();
} }

View File

@@ -5,251 +5,269 @@
#pragma once #pragma once
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
#define ARDUINOJSON_HAS_LONG_LONG 1 # define ARDUINOJSON_HAS_LONG_LONG 1
#define ARDUINOJSON_HAS_NULLPTR 1 # define ARDUINOJSON_HAS_RVALUE_REFERENCES 1
#define ARDUINOJSON_HAS_RVALUE_REFERENCES 1
#else #else
#define ARDUINOJSON_HAS_LONG_LONG 0 # define ARDUINOJSON_HAS_LONG_LONG 0
#define ARDUINOJSON_HAS_NULLPTR 0 # define ARDUINOJSON_HAS_RVALUE_REFERENCES 0
#define ARDUINOJSON_HAS_RVALUE_REFERENCES 0 #endif
#ifndef ARDUINOJSON_HAS_NULLPTR
# if __cplusplus >= 201103L
# define ARDUINOJSON_HAS_NULLPTR 1
# else
# define ARDUINOJSON_HAS_NULLPTR 0
# endif
#endif #endif
#if defined(_MSC_VER) && !ARDUINOJSON_HAS_LONG_LONG #if defined(_MSC_VER) && !ARDUINOJSON_HAS_LONG_LONG
#define ARDUINOJSON_HAS_INT64 1 # define ARDUINOJSON_HAS_INT64 1
#else #else
#define ARDUINOJSON_HAS_INT64 0 # define ARDUINOJSON_HAS_INT64 0
#endif #endif
// Small or big machine? // Small or big machine?
#ifndef ARDUINOJSON_EMBEDDED_MODE #ifndef ARDUINOJSON_EMBEDDED_MODE
#if defined(ARDUINO) /* Arduino*/ \ # if defined(ARDUINO) /* Arduino*/ \
|| defined(__IAR_SYSTEMS_ICC__) /* IAR Embedded Workbench */ \ || defined(__IAR_SYSTEMS_ICC__) /* IAR Embedded Workbench */ \
|| defined(__XC) /* MPLAB XC compiler */ \ || defined(__XC) /* MPLAB XC compiler */ \
|| defined(__ARMCC_VERSION) /* Keil ARM Compiler */ \ || defined(__ARMCC_VERSION) /* Keil ARM Compiler */ \
|| defined(__AVR) /* Atmel AVR8/GNU C Compiler */ || defined(__AVR) /* Atmel AVR8/GNU C Compiler */
#define ARDUINOJSON_EMBEDDED_MODE 1 # define ARDUINOJSON_EMBEDDED_MODE 1
#else # else
#define ARDUINOJSON_EMBEDDED_MODE 0 # define ARDUINOJSON_EMBEDDED_MODE 0
#endif # endif
#endif #endif
// Auto enable std::stream if the right headers are here and no conflicting // Auto enable std::stream if the right headers are here and no conflicting
// macro is defined // macro is defined
#if !defined(ARDUINOJSON_ENABLE_STD_STREAM) && defined(__has_include) #if !defined(ARDUINOJSON_ENABLE_STD_STREAM) && defined(__has_include)
#if __has_include(<istream>) && \ # if __has_include(<istream>) && \
__has_include(<ostream>) && \ __has_include(<ostream>) && \
!defined(min) && \ !defined(min) && \
!defined(max) !defined(max)
#define ARDUINOJSON_ENABLE_STD_STREAM 1 # define ARDUINOJSON_ENABLE_STD_STREAM 1
#else # else
#define ARDUINOJSON_ENABLE_STD_STREAM 0 # define ARDUINOJSON_ENABLE_STD_STREAM 0
#endif # endif
#endif #endif
// Auto enable std::string if the right header is here and no conflicting // Auto enable std::string if the right header is here and no conflicting
// macro is defined // macro is defined
#if !defined(ARDUINOJSON_ENABLE_STD_STRING) && defined(__has_include) #if !defined(ARDUINOJSON_ENABLE_STD_STRING) && defined(__has_include)
#if __has_include(<string>) && !defined(min) && !defined(max) # if __has_include(<string>) && !defined(min) && !defined(max)
#define ARDUINOJSON_ENABLE_STD_STRING 1 # define ARDUINOJSON_ENABLE_STD_STRING 1
#else # else
#define ARDUINOJSON_ENABLE_STD_STRING 0 # define ARDUINOJSON_ENABLE_STD_STRING 0
# endif
#endif #endif
#ifndef ARDUINOJSON_ENABLE_STRING_VIEW
# ifdef __has_include
# if __has_include(<string_view>) && __cplusplus >= 201703L
# define ARDUINOJSON_ENABLE_STRING_VIEW 1
# endif
# endif
#endif
#ifndef ARDUINOJSON_ENABLE_STRING_VIEW
# define ARDUINOJSON_ENABLE_STRING_VIEW 0
#endif #endif
#if ARDUINOJSON_EMBEDDED_MODE #if ARDUINOJSON_EMBEDDED_MODE
// Store floats by default to reduce the memory usage (issue #134) // Store floats by default to reduce the memory usage (issue #134)
#ifndef ARDUINOJSON_USE_DOUBLE # ifndef ARDUINOJSON_USE_DOUBLE
#define ARDUINOJSON_USE_DOUBLE 0 # define ARDUINOJSON_USE_DOUBLE 0
#endif # endif
// Store longs by default, because they usually match the size of a float. // Store longs by default, because they usually match the size of a float.
#ifndef ARDUINOJSON_USE_LONG_LONG # ifndef ARDUINOJSON_USE_LONG_LONG
#define ARDUINOJSON_USE_LONG_LONG 0 # define ARDUINOJSON_USE_LONG_LONG 0
#endif # endif
// Embedded systems usually don't have std::string // Embedded systems usually don't have std::string
#ifndef ARDUINOJSON_ENABLE_STD_STRING # ifndef ARDUINOJSON_ENABLE_STD_STRING
#define ARDUINOJSON_ENABLE_STD_STRING 0 # define ARDUINOJSON_ENABLE_STD_STRING 0
#endif # endif
// Embedded systems usually don't have std::stream // Embedded systems usually don't have std::stream
#ifndef ARDUINOJSON_ENABLE_STD_STREAM # ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 0 # define ARDUINOJSON_ENABLE_STD_STREAM 0
#endif # endif
// Limit nesting as the stack is likely to be small // Limit nesting as the stack is likely to be small
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT # ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 # define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
#endif # endif
// Number of bits to store the pointer to next node // Number of bits to store the pointer to next node
// (saves RAM but limits the number of values in a document) // (saves RAM but limits the number of values in a document)
#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE # ifndef ARDUINOJSON_SLOT_OFFSET_SIZE
#if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 2 # if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 2
// Address space == 16-bit => max 127 values // Address space == 16-bit => max 127 values
#define ARDUINOJSON_SLOT_OFFSET_SIZE 1 # define ARDUINOJSON_SLOT_OFFSET_SIZE 1
#else # else
// Address space > 16-bit => max 32767 values // Address space > 16-bit => max 32767 values
#define ARDUINOJSON_SLOT_OFFSET_SIZE 2 # define ARDUINOJSON_SLOT_OFFSET_SIZE 2
#endif # endif
#endif # endif
#else // ARDUINOJSON_EMBEDDED_MODE #else // ARDUINOJSON_EMBEDDED_MODE
// On a computer we have plenty of memory so we can use doubles // On a computer we have plenty of memory so we can use doubles
#ifndef ARDUINOJSON_USE_DOUBLE # ifndef ARDUINOJSON_USE_DOUBLE
#define ARDUINOJSON_USE_DOUBLE 1 # define ARDUINOJSON_USE_DOUBLE 1
#endif # endif
// Use long long when available // Use long long when available
#ifndef ARDUINOJSON_USE_LONG_LONG # ifndef ARDUINOJSON_USE_LONG_LONG
#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64 # if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64
#define ARDUINOJSON_USE_LONG_LONG 1 # define ARDUINOJSON_USE_LONG_LONG 1
#else # else
#define ARDUINOJSON_USE_LONG_LONG 0 # define ARDUINOJSON_USE_LONG_LONG 0
#endif # endif
#endif # endif
// On a computer, we can use std::string // On a computer, we can use std::string
#ifndef ARDUINOJSON_ENABLE_STD_STRING # ifndef ARDUINOJSON_ENABLE_STD_STRING
#define ARDUINOJSON_ENABLE_STD_STRING 1 # define ARDUINOJSON_ENABLE_STD_STRING 1
#endif # endif
// On a computer, we can assume std::stream // On a computer, we can assume std::stream
#ifndef ARDUINOJSON_ENABLE_STD_STREAM # ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 1 # define ARDUINOJSON_ENABLE_STD_STREAM 1
#endif # endif
// On a computer, the stack is large so we can increase nesting limit // On a computer, the stack is large so we can increase nesting limit
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT # ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50 # define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
#endif # endif
// Number of bits to store the pointer to next node // Number of bits to store the pointer to next node
#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE # ifndef ARDUINOJSON_SLOT_OFFSET_SIZE
#define ARDUINOJSON_SLOT_OFFSET_SIZE 4 # define ARDUINOJSON_SLOT_OFFSET_SIZE 4
#endif # endif
#endif // ARDUINOJSON_EMBEDDED_MODE #endif // ARDUINOJSON_EMBEDDED_MODE
#ifdef ARDUINO #ifdef ARDUINO
#include <Arduino.h> # include <Arduino.h>
// Enable support for Arduino's String class // Enable support for Arduino's String class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING # ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 # define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
#endif # endif
// Enable support for Arduino's Stream class // Enable support for Arduino's Stream class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM # ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1 # define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
#endif # endif
// Enable support for Arduino's Print class // Enable support for Arduino's Print class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT # ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1 # define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1
#endif # endif
#else // ARDUINO #else // ARDUINO
// Disable support for Arduino's String class // Disable support for Arduino's String class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING # ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 # define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
#endif # endif
// Disable support for Arduino's Stream class // Disable support for Arduino's Stream class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM # ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0 # define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
#endif # endif
// Disable support for Arduino's Print class // Disable support for Arduino's Print class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT # ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0 # define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
#endif # endif
#endif // ARDUINO #endif // ARDUINO
#ifndef ARDUINOJSON_ENABLE_PROGMEM #ifndef ARDUINOJSON_ENABLE_PROGMEM
#if defined(PROGMEM) && defined(pgm_read_byte) && defined(pgm_read_dword) && \ # if defined(PROGMEM) && defined(pgm_read_byte) && defined(pgm_read_dword) && \
defined(pgm_read_ptr) && defined(pgm_read_float) defined(pgm_read_ptr) && defined(pgm_read_float)
#define ARDUINOJSON_ENABLE_PROGMEM 1 # define ARDUINOJSON_ENABLE_PROGMEM 1
#else # else
#define ARDUINOJSON_ENABLE_PROGMEM 0 # define ARDUINOJSON_ENABLE_PROGMEM 0
#endif # endif
#endif #endif
// Convert unicode escape sequence (\u0123) to UTF-8 // Convert unicode escape sequence (\u0123) to UTF-8
#ifndef ARDUINOJSON_DECODE_UNICODE #ifndef ARDUINOJSON_DECODE_UNICODE
#define ARDUINOJSON_DECODE_UNICODE 1 # define ARDUINOJSON_DECODE_UNICODE 1
#endif #endif
// Ignore comments in input // Ignore comments in input
#ifndef ARDUINOJSON_ENABLE_COMMENTS #ifndef ARDUINOJSON_ENABLE_COMMENTS
#define ARDUINOJSON_ENABLE_COMMENTS 0 # define ARDUINOJSON_ENABLE_COMMENTS 0
#endif #endif
// Support NaN in JSON // Support NaN in JSON
#ifndef ARDUINOJSON_ENABLE_NAN #ifndef ARDUINOJSON_ENABLE_NAN
#define ARDUINOJSON_ENABLE_NAN 0 # define ARDUINOJSON_ENABLE_NAN 0
#endif #endif
// Support Infinity in JSON // Support Infinity in JSON
#ifndef ARDUINOJSON_ENABLE_INFINITY #ifndef ARDUINOJSON_ENABLE_INFINITY
#define ARDUINOJSON_ENABLE_INFINITY 0 # define ARDUINOJSON_ENABLE_INFINITY 0
#endif #endif
// Control the exponentiation threshold for big numbers // Control the exponentiation threshold for big numbers
// CAUTION: cannot be more that 1e9 !!!! // CAUTION: cannot be more that 1e9 !!!!
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD #ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7 # define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7
#endif #endif
// Control the exponentiation threshold for small numbers // Control the exponentiation threshold for small numbers
#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD #ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5 # define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
#endif #endif
#ifndef ARDUINOJSON_LITTLE_ENDIAN #ifndef ARDUINOJSON_LITTLE_ENDIAN
#if defined(_MSC_VER) || \ # if defined(_MSC_VER) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ (defined(__BYTE_ORDER__) && \
defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64) __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
#define ARDUINOJSON_LITTLE_ENDIAN 1 defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64)
#else # define ARDUINOJSON_LITTLE_ENDIAN 1
#define ARDUINOJSON_LITTLE_ENDIAN 0 # else
#endif # define ARDUINOJSON_LITTLE_ENDIAN 0
# endif
#endif #endif
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT #ifndef ARDUINOJSON_ENABLE_ALIGNMENT
#if defined(__AVR) # if defined(__AVR)
#define ARDUINOJSON_ENABLE_ALIGNMENT 0 # define ARDUINOJSON_ENABLE_ALIGNMENT 0
#else # else
#define ARDUINOJSON_ENABLE_ALIGNMENT 1 # define ARDUINOJSON_ENABLE_ALIGNMENT 1
#endif # endif
#endif #endif
#ifndef ARDUINOJSON_TAB #ifndef ARDUINOJSON_TAB
#define ARDUINOJSON_TAB " " # define ARDUINOJSON_TAB " "
#endif #endif
#ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION #ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
#define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1 # define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1
#endif #endif
#ifndef ARDUINOJSON_STRING_BUFFER_SIZE #ifndef ARDUINOJSON_STRING_BUFFER_SIZE
#define ARDUINOJSON_STRING_BUFFER_SIZE 32 # define ARDUINOJSON_STRING_BUFFER_SIZE 32
#endif #endif
#ifndef ARDUINOJSON_DEBUG #ifndef ARDUINOJSON_DEBUG
#ifdef __PLATFORMIO_BUILD_DEBUG__ # ifdef __PLATFORMIO_BUILD_DEBUG__
#define ARDUINOJSON_DEBUG 1 # define ARDUINOJSON_DEBUG 1
#else # else
#define ARDUINOJSON_DEBUG 0 # define ARDUINOJSON_DEBUG 0
#endif # endif
#endif #endif
#if ARDUINOJSON_HAS_NULLPTR && defined(nullptr) #if ARDUINOJSON_HAS_NULLPTR && defined(nullptr)
#error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr # error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
// See https://github.com/bblanchon/ArduinoJson/issues/1355 // See https://github.com/bblanchon/ArduinoJson/issues/1355
#endif #endif

View File

@@ -9,7 +9,7 @@
#include <ArduinoJson/Polyfills/static_array.hpp> #include <ArduinoJson/Polyfills/static_array.hpp>
#if ARDUINOJSON_ENABLE_STD_STREAM #if ARDUINOJSON_ENABLE_STD_STREAM
#include <ostream> # include <ostream>
#endif #endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {

View File

@@ -32,8 +32,8 @@ class Filter {
Filter operator[](const TKey& key) const { Filter operator[](const TKey& key) const {
if (_variant == true) // "true" means "allow recursively" if (_variant == true) // "true" means "allow recursively"
return *this; return *this;
else VariantConstRef member = _variant[key];
return Filter(_variant[key] | _variant["*"]); return Filter(member.isNull() ? _variant["*"] : member);
} }
private: private:

View File

@@ -17,7 +17,7 @@ struct Reader {
Reader(TSource& source) : _source(&source) {} Reader(TSource& source) : _source(&source) {}
int read() { int read() {
return _source->read(); return _source->read(); // Error here? You passed an unsupported input type
} }
size_t readBytes(char* buffer, size_t length) { size_t readBytes(char* buffer, size_t length) {
@@ -40,17 +40,17 @@ struct BoundedReader {
#include <ArduinoJson/Deserialization/Readers/VariantReader.hpp> #include <ArduinoJson/Deserialization/Readers/VariantReader.hpp>
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM #if ARDUINOJSON_ENABLE_ARDUINO_STREAM
#include <ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp> # include <ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp>
#endif #endif
#if ARDUINOJSON_ENABLE_ARDUINO_STRING #if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include <ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp> # include <ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp>
#endif #endif
#if ARDUINOJSON_ENABLE_PROGMEM #if ARDUINOJSON_ENABLE_PROGMEM
#include <ArduinoJson/Deserialization/Readers/FlashReader.hpp> # include <ArduinoJson/Deserialization/Readers/FlashReader.hpp>
#endif #endif
#if ARDUINOJSON_ENABLE_STD_STREAM #if ARDUINOJSON_ENABLE_STD_STREAM
#include <ArduinoJson/Deserialization/Readers/StdStreamReader.hpp> # include <ArduinoJson/Deserialization/Readers/StdStreamReader.hpp>
#endif #endif

View File

@@ -32,7 +32,7 @@ class JsonDocument : public Visitable {
void clear() { void clear() {
_pool.clear(); _pool.clear();
_data.setNull(); _data.init();
} }
template <typename T> template <typename T>
@@ -304,15 +304,15 @@ class JsonDocument : public Visitable {
protected: protected:
JsonDocument() : _pool(0, 0) { JsonDocument() : _pool(0, 0) {
_data.setNull(); _data.init();
} }
JsonDocument(MemoryPool pool) : _pool(pool) { JsonDocument(MemoryPool pool) : _pool(pool) {
_data.setNull(); _data.init();
} }
JsonDocument(char* buf, size_t capa) : _pool(buf, capa) { JsonDocument(char* buf, size_t capa) : _pool(buf, capa) {
_data.setNull(); _data.init();
} }
~JsonDocument() {} ~JsonDocument() {}
@@ -337,8 +337,8 @@ class JsonDocument : public Visitable {
JsonDocument& operator=(const JsonDocument&); JsonDocument& operator=(const JsonDocument&);
}; };
inline bool convertToJson(const JsonDocument& src, VariantRef dst) { inline void convertToJson(const JsonDocument& src, VariantRef dst) {
return dst.set(src.as<VariantConstRef>()); dst.set(src.as<VariantConstRef>());
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -45,7 +45,8 @@ class Latch {
} }
TReader _reader; TReader _reader;
char _current; char _current; // NOLINT(clang-analyzer-optin.cplusplus.UninitializedObject)
// Not initialized in constructor (+10 bytes on AVR)
bool _loaded; bool _loaded;
#if ARDUINOJSON_DEBUG #if ARDUINOJSON_DEBUG
bool _ended; bool _ended;

View File

@@ -155,7 +155,6 @@ class TextFormatter {
protected: protected:
CountingDecorator<TWriter> _writer; CountingDecorator<TWriter> _writer;
size_t _length;
private: private:
TextFormatter &operator=(const TextFormatter &); // cannot be assigned TextFormatter &operator=(const TextFormatter &); // cannot be assigned

View File

@@ -12,10 +12,10 @@
// we choose to ignore the problem to reduce the size of the code // we choose to ignore the problem to reduce the size of the code
// Garbage in => Garbage out // Garbage in => Garbage out
#if defined(__GNUC__) #if defined(__GNUC__)
#if __GNUC__ >= 7 # if __GNUC__ >= 7
#pragma GCC diagnostic push # pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif # endif
#endif #endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
@@ -31,7 +31,7 @@ inline bool isLowSurrogate(uint16_t codeunit) {
class Codepoint { class Codepoint {
public: public:
Codepoint() : _highSurrogate(0) {} Codepoint() : _highSurrogate(0), _codepoint(0) {}
bool append(uint16_t codeunit) { bool append(uint16_t codeunit) {
if (isHighSurrogate(codeunit)) { if (isHighSurrogate(codeunit)) {
@@ -61,7 +61,7 @@ class Codepoint {
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#if defined(__GNUC__) #if defined(__GNUC__)
#if __GNUC__ >= 8 # if __GNUC__ >= 8
#pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif # endif
#endif #endif

View File

@@ -13,14 +13,14 @@ template <typename TStringBuilder>
inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) { inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) {
// this function was optimize for code size on AVR // this function was optimize for code size on AVR
// a buffer to store the string in reverse
char buf[5];
char* p = buf;
*(p++) = 0;
if (codepoint32 < 0x80) { if (codepoint32 < 0x80) {
*(p++) = char((codepoint32)); str.append(char(codepoint32));
} else { } else {
// a buffer to store the string in reverse
char buf[5];
char* p = buf;
*(p++) = 0;
*(p++) = char((codepoint32 | 0x80) & 0xBF); *(p++) = char((codepoint32 | 0x80) & 0xBF);
uint16_t codepoint16 = uint16_t(codepoint32 >> 6); uint16_t codepoint16 = uint16_t(codepoint32 >> 6);
if (codepoint16 < 0x20) { // 0x800 if (codepoint16 < 0x20) { // 0x800
@@ -36,10 +36,10 @@ inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) {
*(p++) = char(codepoint16 | 0xF0); *(p++) = char(codepoint16 | 0xF0);
} }
} }
}
while (*(--p)) { while (*(--p)) {
str.append(*p); str.append(*p);
}
} }
} }
} // namespace Utf8 } // namespace Utf8

View File

@@ -7,6 +7,7 @@
#include <ArduinoJson/Memory/Alignment.hpp> #include <ArduinoJson/Memory/Alignment.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/mpl/max.hpp> #include <ArduinoJson/Polyfills/mpl/max.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp> #include <ArduinoJson/Variant/VariantSlot.hpp>
#include <string.h> // memmove #include <string.h> // memmove
@@ -37,7 +38,8 @@ class MemoryPool {
} }
void* buffer() { void* buffer() {
return _begin; return _begin; // NOLINT(clang-analyzer-unix.Malloc)
// movePointers() alters this pointer
} }
// Gets the capacity of the memoryPool in bytes // Gets the capacity of the memoryPool in bytes
@@ -63,7 +65,7 @@ class MemoryPool {
return 0; return 0;
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION #if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
const char* existingCopy = findString(str.begin()); const char* existingCopy = findString(str);
if (existingCopy) if (existingCopy)
return existingCopy; return existingCopy;
#endif #endif
@@ -85,7 +87,7 @@ class MemoryPool {
const char* saveStringFromFreeZone(size_t len) { const char* saveStringFromFreeZone(size_t len) {
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION #if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
const char* dup = findString(_left); const char* dup = findString(adaptString(_left));
if (dup) if (dup)
return dup; return dup;
#endif #endif
@@ -162,16 +164,11 @@ class MemoryPool {
} }
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION #if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
template <typename TIterator> template <typename TAdaptedString>
const char* findString(TIterator str) { const char* findString(const TAdaptedString& str) {
for (char* next = _begin; next < _left; ++next) { for (char* next = _begin; next < _left; ++next) {
char* begin = next; if (str.compare(next) == 0)
return next;
// try to match
for (TIterator it = str; *it == *next; ++it) {
if (*next++ == 0)
return begin;
}
// jump to next terminator // jump to next terminator
while (*next) ++next; while (*next) ++next;

View File

@@ -10,17 +10,17 @@
#ifndef ARDUINOJSON_NAMESPACE #ifndef ARDUINOJSON_NAMESPACE
#define ARDUINOJSON_NAMESPACE \ # define ARDUINOJSON_NAMESPACE \
ARDUINOJSON_CONCAT4( \ ARDUINOJSON_CONCAT4( \
ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \ ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \
ARDUINOJSON_VERSION_MINOR, \ ARDUINOJSON_VERSION_MINOR, \
ARDUINOJSON_VERSION_REVISION), \ ARDUINOJSON_VERSION_REVISION), \
_, \ _, \
ARDUINOJSON_HEX_DIGIT(ARDUINOJSON_ENABLE_PROGMEM, \ ARDUINOJSON_HEX_DIGIT( \
ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, \ ARDUINOJSON_ENABLE_PROGMEM, ARDUINOJSON_USE_LONG_LONG, \
ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \ ARDUINOJSON_USE_DOUBLE, ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \
ARDUINOJSON_HEX_DIGIT( \ ARDUINOJSON_HEX_DIGIT( \
ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \ ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \
ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE)) ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE))
#endif #endif

View File

@@ -22,11 +22,11 @@ typedef unsigned long UInt;
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG #if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG
#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \ # define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \
static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer), \ static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer), \
"To use 64-bit integers with ArduinoJson, you must set " \ "To use 64-bit integers with ArduinoJson, you must set " \
"ARDUINOJSON_USE_LONG_LONG to 1. See " \ "ARDUINOJSON_USE_LONG_LONG to 1. See " \
"https://arduinojson.org/v6/api/config/use_long_long/"); "https://arduinojson.org/v6/api/config/use_long_long/");
#else #else
#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) # define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T)
#endif #endif

View File

@@ -5,13 +5,13 @@
#pragma once #pragma once
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic push # pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion" # pragma clang diagnostic ignored "-Wconversion"
#elif defined(__GNUC__) #elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push # pragma GCC diagnostic push
#endif # endif
#pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wconversion"
#endif #endif
#include <ArduinoJson/Numbers/Float.hpp> #include <ArduinoJson/Numbers/Float.hpp>
@@ -71,9 +71,23 @@ canConvertNumber(TIn) {
} }
// int32 -> uint32 // int32 -> uint32
// int32 -> uint64
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value && typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
is_integral<TOut>::value && is_unsigned<TOut>::value, is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) >= sizeof(TIn),
bool>::type
canConvertNumber(TIn value) {
if (value < 0)
return false;
return TOut(value) <= numeric_limits<TOut>::highest();
}
// int32 -> uint16
template <typename TOut, typename TIn>
typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) < sizeof(TIn),
bool>::type bool>::type
canConvertNumber(TIn value) { canConvertNumber(TIn value) {
if (value < 0) if (value < 0)
@@ -99,9 +113,9 @@ TOut convertNumber(TIn value) {
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic pop # pragma clang diagnostic pop
#elif defined(__GNUC__) #elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif # endif
#endif #endif

View File

@@ -12,8 +12,8 @@
#include <ArduinoJson/Variant/VariantTo.hpp> #include <ArduinoJson/Variant/VariantTo.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) # pragma warning(push)
#pragma warning(disable : 4522) # pragma warning(disable : 4522)
#endif #endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
@@ -187,8 +187,8 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
return _object.getOrAddMember(_key); return _object.getOrAddMember(_key);
} }
friend bool convertToJson(const this_type &src, VariantRef dst) { friend void convertToJson(const this_type &src, VariantRef dst) {
return dst.set(src.getUpstreamMember()); dst.set(src.getUpstreamMember());
} }
TObject _object; TObject _object;
@@ -198,5 +198,5 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) # pragma warning(pop)
#endif #endif

View File

@@ -239,8 +239,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
template <> template <>
struct Converter<ObjectConstRef> { struct Converter<ObjectConstRef> {
static bool toJson(VariantConstRef src, VariantRef dst) { static void toJson(VariantConstRef src, VariantRef dst) {
return variantCopyFrom(getData(dst), getData(src), getPool(dst)); variantCopyFrom(getData(dst), getData(src), getPool(dst));
} }
static ObjectConstRef fromJson(VariantConstRef src) { static ObjectConstRef fromJson(VariantConstRef src) {
@@ -255,8 +255,8 @@ struct Converter<ObjectConstRef> {
template <> template <>
struct Converter<ObjectRef> { struct Converter<ObjectRef> {
static bool toJson(VariantConstRef src, VariantRef dst) { static void toJson(VariantConstRef src, VariantRef dst) {
return variantCopyFrom(getData(dst), getData(src), getPool(dst)); variantCopyFrom(getData(dst), getData(src), getPool(dst));
} }
static ObjectRef fromJson(VariantRef src) { static ObjectRef fromJson(VariantRef src) {
@@ -265,6 +265,9 @@ struct Converter<ObjectRef> {
return ObjectRef(pool, data != 0 ? data->asObject() : 0); return ObjectRef(pool, data != 0 ? data->asObject() : 0);
} }
static InvalidConversion<VariantConstRef, ObjectRef> fromJson(
VariantConstRef);
static bool checkJson(VariantConstRef) { static bool checkJson(VariantConstRef) {
return false; return false;
} }

View File

@@ -7,8 +7,8 @@
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#if ARDUINOJSON_DEBUG #if ARDUINOJSON_DEBUG
#include <assert.h> # include <assert.h>
#define ARDUINOJSON_ASSERT(X) assert(X) # define ARDUINOJSON_ASSERT(X) assert(X)
#else #else
#define ARDUINOJSON_ASSERT(X) ((void)0) # define ARDUINOJSON_ASSERT(X) ((void)0)
#endif #endif

View File

@@ -6,49 +6,49 @@
#ifdef _MSC_VER // Visual Studio #ifdef _MSC_VER // Visual Studio
#define FORCE_INLINE // __forceinline causes C4714 when returning std::string # define FORCE_INLINE // __forceinline causes C4714 when returning std::string
#define NO_INLINE __declspec(noinline) # define NO_INLINE __declspec(noinline)
#ifndef ARDUINOJSON_DEPRECATED # ifndef ARDUINOJSON_DEPRECATED
#define ARDUINOJSON_DEPRECATED(msg) __declspec(deprecated(msg)) # define ARDUINOJSON_DEPRECATED(msg) __declspec(deprecated(msg))
#endif # endif
#elif defined(__GNUC__) // GCC or Clang #elif defined(__GNUC__) // GCC or Clang
#define FORCE_INLINE __attribute__((always_inline)) # define FORCE_INLINE __attribute__((always_inline))
#define NO_INLINE __attribute__((noinline)) # define NO_INLINE __attribute__((noinline))
#ifndef ARDUINOJSON_DEPRECATED # ifndef ARDUINOJSON_DEPRECATED
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated(msg))) # define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated(msg)))
#else # else
#define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated)) # define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated))
#endif # endif
#endif # endif
#else // Other compilers #else // Other compilers
#define FORCE_INLINE # define FORCE_INLINE
#define NO_INLINE # define NO_INLINE
#ifndef ARDUINOJSON_DEPRECATED # ifndef ARDUINOJSON_DEPRECATED
#define ARDUINOJSON_DEPRECATED(msg) # define ARDUINOJSON_DEPRECATED(msg)
#endif # endif
#endif #endif
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
#define NOEXCEPT noexcept # define NOEXCEPT noexcept
#else #else
#define NOEXCEPT throw() # define NOEXCEPT throw()
#endif #endif
#if defined(__has_attribute) #if defined(__has_attribute)
#if __has_attribute(no_sanitize) # if __has_attribute(no_sanitize)
#define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check))) # define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check)))
# else
# define ARDUINOJSON_NO_SANITIZE(check)
# endif
#else #else
#define ARDUINOJSON_NO_SANITIZE(check) # define ARDUINOJSON_NO_SANITIZE(check)
#endif
#else
#define ARDUINOJSON_NO_SANITIZE(check)
#endif #endif

View File

@@ -7,8 +7,8 @@
#include "type_traits.hpp" #include "type_traits.hpp"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) # pragma warning(push)
#pragma warning(disable : 4310) # pragma warning(disable : 4310)
#endif #endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
@@ -41,5 +41,5 @@ struct numeric_limits<
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) # pragma warning(pop)
#endif #endif

View File

@@ -8,27 +8,27 @@
#if ARDUINOJSON_ENABLE_PROGMEM #if ARDUINOJSON_ENABLE_PROGMEM
#include <ArduinoJson/Polyfills/pgmspace_generic.hpp> # include <ArduinoJson/Polyfills/pgmspace_generic.hpp>
#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY # ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY
#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ # define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \
static type const name[] PROGMEM = value; static type const name[] PROGMEM = value;
#endif # endif
#ifndef ARDUINOJSON_READ_STATIC_ARRAY # ifndef ARDUINOJSON_READ_STATIC_ARRAY
#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \ # define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \
pgm_read<type>(name + index) pgm_read<type>(name + index)
#endif # endif
#else // i.e. ARDUINOJSON_ENABLE_PROGMEM == 0 #else // i.e. ARDUINOJSON_ENABLE_PROGMEM == 0
#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY # ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY
#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ # define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \
static type const name[] = value; static type const name[] = value;
#endif # endif
#ifndef ARDUINOJSON_READ_STATIC_ARRAY # ifndef ARDUINOJSON_READ_STATIC_ARRAY
#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index] # define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index]
#endif # endif
#endif #endif

View File

@@ -20,5 +20,6 @@
#include "type_traits/is_signed.hpp" #include "type_traits/is_signed.hpp"
#include "type_traits/is_unsigned.hpp" #include "type_traits/is_unsigned.hpp"
#include "type_traits/make_unsigned.hpp" #include "type_traits/make_unsigned.hpp"
#include "type_traits/make_void.hpp"
#include "type_traits/remove_const.hpp" #include "type_traits/remove_const.hpp"
#include "type_traits/remove_reference.hpp" #include "type_traits/remove_reference.hpp"

View File

@@ -7,9 +7,9 @@
#include "declval.hpp" #include "declval.hpp"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) # pragma warning(push)
// conversion from 'T' to 'To', possible loss of data // conversion from 'T' to 'To', possible loss of data
#pragma warning(disable : 4244) # pragma warning(disable : 4244)
#endif #endif
// clang-format off // clang-format off
@@ -37,7 +37,7 @@ struct is_convertible {
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) # pragma warning(pop)
#endif #endif
// clang-format off // clang-format off

View File

@@ -5,15 +5,16 @@
#pragma once #pragma once
#include "integral_constant.hpp" #include "integral_constant.hpp"
#include "is_same.hpp"
#include "remove_cv.hpp"
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename> template <class T>
struct is_floating_point : false_type {}; struct is_floating_point
: integral_constant<
bool, //
is_same<float, typename remove_cv<T>::type>::value ||
is_same<double, typename remove_cv<T>::type>::value> {};
template <>
struct is_floating_point<float> : true_type {};
template <>
struct is_floating_point<double> : true_type {};
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,29 +5,33 @@
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#include "integral_constant.hpp"
#include "is_same.hpp" #include "is_same.hpp"
#include "remove_cv.hpp"
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// A meta-function that returns true if T is an integral type. // clang-format off
template <typename T> template <typename T>
struct is_integral { struct is_integral : integral_constant<bool,
static const bool value = is_same<typename remove_cv<T>::type, signed char>::value ||
is_same<T, signed char>::value || is_same<T, unsigned char>::value || is_same<typename remove_cv<T>::type, unsigned char>::value ||
is_same<T, signed short>::value || is_same<T, unsigned short>::value || is_same<typename remove_cv<T>::type, signed short>::value ||
is_same<T, signed int>::value || is_same<T, unsigned int>::value || is_same<typename remove_cv<T>::type, unsigned short>::value ||
is_same<T, signed long>::value || is_same<T, unsigned long>::value || is_same<typename remove_cv<T>::type, signed int>::value ||
is_same<typename remove_cv<T>::type, unsigned int>::value ||
is_same<typename remove_cv<T>::type, signed long>::value ||
is_same<typename remove_cv<T>::type, unsigned long>::value ||
#if ARDUINOJSON_HAS_LONG_LONG #if ARDUINOJSON_HAS_LONG_LONG
is_same<T, signed long long>::value || is_same<typename remove_cv<T>::type, signed long long>::value ||
is_same<T, unsigned long long>::value || is_same<typename remove_cv<T>::type, unsigned long long>::value ||
#endif #endif
#if ARDUINOJSON_HAS_INT64 #if ARDUINOJSON_HAS_INT64
is_same<T, signed __int64>::value || is_same<typename remove_cv<T>::type, signed __int64>::value ||
is_same<T, unsigned __int64>::value || is_same<typename remove_cv<T>::type, unsigned __int64>::value ||
#endif #endif
is_same<T, char>::value || is_same<T, bool>::value; is_same<typename remove_cv<T>::type, char>::value ||
}; is_same<typename remove_cv<T>::type, bool>::value> {};
// clang-format on
template <typename T>
struct is_integral<const T> : is_integral<T> {};
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,39 +5,26 @@
#pragma once #pragma once
#include "integral_constant.hpp" #include "integral_constant.hpp"
#include "is_same.hpp"
#include "remove_cv.hpp"
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename> // clang-format off
struct is_signed : false_type {}; template <typename T>
struct is_signed : integral_constant<bool,
template <> is_same<typename remove_cv<T>::type, char>::value ||
struct is_signed<char> : true_type {}; is_same<typename remove_cv<T>::type, signed char>::value ||
is_same<typename remove_cv<T>::type, signed short>::value ||
template <> is_same<typename remove_cv<T>::type, signed int>::value ||
struct is_signed<signed char> : true_type {}; is_same<typename remove_cv<T>::type, signed long>::value ||
template <>
struct is_signed<signed short> : true_type {};
template <>
struct is_signed<signed int> : true_type {};
template <>
struct is_signed<signed long> : true_type {};
template <>
struct is_signed<float> : true_type {};
template <>
struct is_signed<double> : true_type {};
#if ARDUINOJSON_HAS_LONG_LONG #if ARDUINOJSON_HAS_LONG_LONG
template <> is_same<typename remove_cv<T>::type, signed long long>::value ||
struct is_signed<signed long long> : true_type {};
#endif #endif
#if ARDUINOJSON_HAS_INT64 #if ARDUINOJSON_HAS_INT64
template <> is_same<typename remove_cv<T>::type, signed __int64>::value ||
struct is_signed<signed __int64> : true_type {};
#endif #endif
is_same<typename remove_cv<T>::type, float>::value ||
is_same<typename remove_cv<T>::type, double>::value> {};
// clang-format on
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,33 +5,24 @@
#pragma once #pragma once
#include "integral_constant.hpp" #include "integral_constant.hpp"
#include "is_same.hpp"
#include "remove_cv.hpp"
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename> // clang-format off
struct is_unsigned : false_type {}; template <typename T>
struct is_unsigned : integral_constant<bool,
template <> is_same<typename remove_cv<T>::type, unsigned char>::value ||
struct is_unsigned<bool> : true_type {}; is_same<typename remove_cv<T>::type, unsigned short>::value ||
is_same<typename remove_cv<T>::type, unsigned int>::value ||
template <> is_same<typename remove_cv<T>::type, unsigned long>::value ||
struct is_unsigned<unsigned char> : true_type {};
template <>
struct is_unsigned<unsigned short> : true_type {};
template <>
struct is_unsigned<unsigned int> : true_type {};
template <>
struct is_unsigned<unsigned long> : true_type {};
#if ARDUINOJSON_HAS_INT64 #if ARDUINOJSON_HAS_INT64
template <> is_same<typename remove_cv<T>::type, unsigned __int64>::value ||
struct is_unsigned<unsigned __int64> : true_type {};
#endif #endif
#if ARDUINOJSON_HAS_LONG_LONG #if ARDUINOJSON_HAS_LONG_LONG
template <> is_same<typename remove_cv<T>::type, unsigned long long>::value ||
struct is_unsigned<unsigned long long> : true_type {};
#endif #endif
is_same<typename remove_cv<T>::type, bool>::value> {};
// clang-format on
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,14 @@
// ArduinoJson - https://arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <class = void>
struct make_void {
typedef void type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,27 @@
// ArduinoJson - https://arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
struct remove_cv {
typedef T type;
};
template <typename T>
struct remove_cv<const T> {
typedef T type;
};
template <typename T>
struct remove_cv<volatile T> {
typedef T type;
};
template <typename T>
struct remove_cv<const volatile T> {
typedef T type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -31,17 +31,17 @@ class Writer {
#include <ArduinoJson/Serialization/Writers/StaticStringWriter.hpp> #include <ArduinoJson/Serialization/Writers/StaticStringWriter.hpp>
#if ARDUINOJSON_ENABLE_STD_STRING #if ARDUINOJSON_ENABLE_STD_STRING
#include <ArduinoJson/Serialization/Writers/StdStringWriter.hpp> # include <ArduinoJson/Serialization/Writers/StdStringWriter.hpp>
#endif #endif
#if ARDUINOJSON_ENABLE_ARDUINO_STRING #if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include <ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp> # include <ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp>
#endif #endif
#if ARDUINOJSON_ENABLE_STD_STREAM #if ARDUINOJSON_ENABLE_STD_STREAM
#include <ArduinoJson/Serialization/Writers/StdStreamWriter.hpp> # include <ArduinoJson/Serialization/Writers/StdStreamWriter.hpp>
#endif #endif
#if ARDUINOJSON_ENABLE_ARDUINO_PRINT #if ARDUINOJSON_ENABLE_ARDUINO_PRINT
#include <ArduinoJson/Serialization/Writers/PrintWriter.hpp> # include <ArduinoJson/Serialization/Writers/PrintWriter.hpp>
#endif #endif

View File

@@ -22,10 +22,10 @@ class Writer< ::String, void> {
} }
size_t write(uint8_t c) { size_t write(uint8_t c) {
ARDUINOJSON_ASSERT(_size < bufferCapacity);
_buffer[_size++] = static_cast<char>(c);
if (_size + 1 >= bufferCapacity) if (_size + 1 >= bufferCapacity)
flush(); if (flush() != 0)
return 0;
_buffer[_size++] = static_cast<char>(c);
return 1; return 1;
} }
@@ -36,14 +36,15 @@ class Writer< ::String, void> {
return n; return n;
} }
private: size_t flush() {
void flush() {
ARDUINOJSON_ASSERT(_size < bufferCapacity); ARDUINOJSON_ASSERT(_size < bufferCapacity);
_buffer[_size] = 0; _buffer[_size] = 0;
*_destination += _buffer; if (_destination->concat(_buffer))
_size = 0; _size = 0;
return _size;
} }
private:
::String *_destination; ::String *_destination;
char _buffer[bufferCapacity]; char _buffer[bufferCapacity];
size_t _size; size_t _size;

View File

@@ -55,8 +55,12 @@ class StringCopier {
private: private:
MemoryPool* _pool; MemoryPool* _pool;
// These fields aren't initialized by the constructor but startString()
//
// NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.UninitializedObject)
char* _ptr; char* _ptr;
size_t _size; // NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.UninitializedObject)
size_t _capacity; size_t _size, _capacity;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -7,14 +7,15 @@
#include <Arduino.h> #include <Arduino.h>
#include <ArduinoJson/Polyfills/safe_strcmp.hpp> #include <ArduinoJson/Polyfills/safe_strcmp.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp> #include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class ArduinoStringAdapter { template <>
class StringAdapter< ::String> {
public: public:
ArduinoStringAdapter(const ::String& str) : _str(&str) {} StringAdapter(const ::String& str) : _str(&str) {}
void copyTo(char* p, size_t n) const { void copyTo(char* p, size_t n) const {
memcpy(p, _str->c_str(), n); memcpy(p, _str->c_str(), n);
@@ -31,18 +32,10 @@ class ArduinoStringAdapter {
return safe_strcmp(me, other); return safe_strcmp(me, other);
} }
bool equals(const char* expected) const {
return compare(expected) == 0;
}
size_t size() const { size_t size() const {
return _str->length(); return _str->length();
} }
const char* begin() const {
return _str->c_str();
}
typedef storage_policies::store_by_copy storage_policy; typedef storage_policies::store_by_copy storage_policy;
private: private:
@@ -50,13 +43,9 @@ class ArduinoStringAdapter {
}; };
template <> template <>
struct IsString< ::String> : true_type {}; class StringAdapter< ::StringSumHelper> : public StringAdapter< ::String> {
public:
template <> StringAdapter(const ::String& s) : StringAdapter< ::String>(s) {}
struct IsString< ::StringSumHelper> : true_type {}; };
inline ArduinoStringAdapter adaptString(const ::String& str) {
return ArduinoStringAdapter(str);
}
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -8,23 +8,20 @@
#include <string.h> // strcmp #include <string.h> // strcmp
#include <ArduinoJson/Polyfills/safe_strcmp.hpp> #include <ArduinoJson/Polyfills/safe_strcmp.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp> #include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class ConstRamStringAdapter { template <>
class StringAdapter<const char*> {
public: public:
ConstRamStringAdapter(const char* str = 0) : _str(str) {} StringAdapter(const char* str = 0) : _str(str) {}
int compare(const char* other) const { int compare(const char* other) const {
return safe_strcmp(_str, other); return safe_strcmp(_str, other);
} }
bool equals(const char* expected) const {
return compare(expected) == 0;
}
bool isNull() const { bool isNull() const {
return !_str; return !_str;
} }
@@ -39,24 +36,16 @@ class ConstRamStringAdapter {
return _str; return _str;
} }
const char* begin() const {
return _str;
}
typedef storage_policies::store_by_address storage_policy; typedef storage_policies::store_by_address storage_policy;
protected: protected:
const char* _str; const char* _str;
}; };
template <>
struct IsString<const char*> : true_type {};
template <int N> template <int N>
struct IsString<const char[N]> : true_type {}; class StringAdapter<const char[N]> : public StringAdapter<const char*> {
public:
inline ConstRamStringAdapter adaptString(const char* str) { StringAdapter(const char* s) : StringAdapter<const char*>(s) {}
return ConstRamStringAdapter(str); };
}
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,15 +5,15 @@
#pragma once #pragma once
#include <ArduinoJson/Polyfills/pgmspace.hpp> #include <ArduinoJson/Polyfills/pgmspace.hpp>
#include <ArduinoJson/Strings/FlashStringIterator.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp> #include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class FlashStringAdapter { template <>
class StringAdapter<const __FlashStringHelper*> {
public: public:
FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {} StringAdapter(const __FlashStringHelper* str) : _str(str) {}
int compare(const char* other) const { int compare(const char* other) const {
if (!other && !_str) if (!other && !_str)
@@ -25,10 +25,6 @@ class FlashStringAdapter {
return -strcmp_P(other, reinterpret_cast<const char*>(_str)); return -strcmp_P(other, reinterpret_cast<const char*>(_str));
} }
bool equals(const char* expected) const {
return compare(expected) == 0;
}
bool isNull() const { bool isNull() const {
return !_str; return !_str;
} }
@@ -43,20 +39,10 @@ class FlashStringAdapter {
return strlen_P(reinterpret_cast<const char*>(_str)); return strlen_P(reinterpret_cast<const char*>(_str));
} }
FlashStringIterator begin() const {
return FlashStringIterator(_str);
}
typedef storage_policies::store_by_copy storage_policy; typedef storage_policies::store_by_copy storage_policy;
private: private:
const __FlashStringHelper* _str; const __FlashStringHelper* _str;
}; };
inline FlashStringAdapter adaptString(const __FlashStringHelper* str) {
return FlashStringAdapter(str);
}
template <>
struct IsString<const __FlashStringHelper*> : true_type {};
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,27 @@
// ArduinoJson - https://arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License
#pragma once
#include <ArduinoJson/Strings/Adapters/RamStringAdapter.hpp>
#include <ArduinoJson/Strings/String.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <>
class StringAdapter<String> : public StringAdapter<char*> {
public:
StringAdapter(const String& str)
: StringAdapter<char*>(str.c_str()), _isStatic(str.isStatic()) {}
bool isStatic() const {
return _isStatic;
}
typedef storage_policies::decide_at_runtime storage_policy;
private:
bool _isStatic;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,29 @@
// ArduinoJson - https://arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TChar>
class StringAdapter<TChar*, false,
typename enable_if<sizeof(TChar) == 1 &&
!is_same<TChar, void>::value>::type>
: public StringAdapter<const char*> {
public:
StringAdapter(const TChar* str)
: StringAdapter<const char*>(reinterpret_cast<const char*>(str)) {}
void copyTo(char* p, size_t n) const {
memcpy(p, _str, n);
}
typedef ARDUINOJSON_NAMESPACE::storage_policies::store_by_copy storage_policy;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,15 +5,15 @@
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Strings/FlashStringIterator.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp> #include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class SizedFlashStringAdapter { template <>
class StringAdapter<const __FlashStringHelper*, true> {
public: public:
SizedFlashStringAdapter(const __FlashStringHelper* str, size_t sz) StringAdapter(const __FlashStringHelper* str, size_t sz)
: _str(str), _size(sz) {} : _str(str), _size(sz) {}
int compare(const char* other) const { int compare(const char* other) const {
@@ -26,10 +26,6 @@ class SizedFlashStringAdapter {
return -strncmp_P(other, reinterpret_cast<const char*>(_str), _size); return -strncmp_P(other, reinterpret_cast<const char*>(_str), _size);
} }
bool equals(const char* expected) const {
return compare(expected) == 0;
}
bool isNull() const { bool isNull() const {
return !_str; return !_str;
} }
@@ -42,10 +38,6 @@ class SizedFlashStringAdapter {
return _size; return _size;
} }
FlashStringIterator begin() const {
return FlashStringIterator(_str);
}
typedef storage_policies::store_by_copy storage_policy; typedef storage_policies::store_by_copy storage_policy;
private: private:
@@ -53,8 +45,4 @@ class SizedFlashStringAdapter {
size_t _size; size_t _size;
}; };
inline SizedFlashStringAdapter adaptString(const __FlashStringHelper* str,
size_t sz) {
return SizedFlashStringAdapter(str, sz);
}
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,25 +5,22 @@
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp> #include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
#include <string.h> // strcmp #include <string.h> // strcmp
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class SizedRamStringAdapter { template <typename TChar>
class StringAdapter<TChar*, true> {
public: public:
SizedRamStringAdapter(const char* str, size_t n) : _str(str), _size(n) {} StringAdapter(const char* str, size_t n) : _str(str), _size(n) {}
int compare(const char* other) const { int compare(const char* other) const {
return safe_strncmp(_str, other, _size); return safe_strncmp(_str, other, _size);
} }
bool equals(const char* expected) const {
return compare(expected) == 0;
}
bool isNull() const { bool isNull() const {
return !_str; return !_str;
} }
@@ -36,10 +33,6 @@ class SizedRamStringAdapter {
return _size; return _size;
} }
const char* begin() const {
return _str;
}
typedef storage_policies::store_by_copy storage_policy; typedef storage_policies::store_by_copy storage_policy;
private: private:
@@ -47,9 +40,4 @@ class SizedRamStringAdapter {
size_t _size; size_t _size;
}; };
template <typename TChar>
inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) {
return SizedRamStringAdapter(reinterpret_cast<const char*>(str), size);
}
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,46 @@
// ArduinoJson - https://arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
#include <string>
namespace ARDUINOJSON_NAMESPACE {
template <typename TCharTraits, typename TAllocator>
class StringAdapter<std::basic_string<char, TCharTraits, TAllocator> > {
public:
typedef std::basic_string<char, TCharTraits, TAllocator> string_type;
StringAdapter(const string_type& str) : _str(&str) {}
void copyTo(char* p, size_t n) const {
memcpy(p, _str->c_str(), n);
}
bool isNull() const {
return false;
}
int compare(const char* other) const {
if (!other)
return 1;
return _str->compare(other);
}
size_t size() const {
return _str->size();
}
typedef storage_policies::store_by_copy storage_policy;
private:
const string_type* _str;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,44 @@
// ArduinoJson - https://arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
#include <string_view>
namespace ARDUINOJSON_NAMESPACE {
template <>
class StringAdapter<std::string_view> {
public:
StringAdapter(std::string_view str) : _str(str) {}
void copyTo(char* p, size_t n) const {
memcpy(p, _str.data(), n);
}
bool isNull() const {
return false;
}
int compare(const char* other) const {
if (!other)
return 1;
return _str.compare(other);
}
size_t size() const {
return _str.size();
}
typedef storage_policies::store_by_copy storage_policy;
private:
std::string_view _str;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,44 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class FlashStringIterator {
public:
explicit FlashStringIterator(const __FlashStringHelper* ptr)
: _ptr(reinterpret_cast<const char*>(ptr)) {}
explicit FlashStringIterator(const char* ptr) : _ptr(ptr) {}
FlashStringIterator operator+(ptrdiff_t d) const {
return FlashStringIterator(_ptr + d);
}
ptrdiff_t operator-(FlashStringIterator other) const {
return _ptr - other._ptr;
}
FlashStringIterator operator++(int) {
return FlashStringIterator(_ptr++);
}
FlashStringIterator operator++() {
return FlashStringIterator(++_ptr);
}
bool operator!=(FlashStringIterator other) const {
return _ptr != other._ptr;
}
char operator*() const {
return char(pgm_read_byte(_ptr));
}
private:
const char* _ptr;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,18 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename>
struct IsString : false_type {};
template <typename T>
struct IsString<const T> : IsString<T> {};
template <typename T>
struct IsString<T&> : IsString<T> {};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -8,11 +8,11 @@
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
#if ARDUINOJSON_ENABLE_ARDUINO_STRING #if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include <Arduino.h> # include <Arduino.h>
#endif #endif
#if ARDUINOJSON_ENABLE_STD_STRING #if ARDUINOJSON_ENABLE_STD_STRING
#include <string> # include <string>
#endif #endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {

View File

@@ -1,43 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright Benoit Blanchon 2014-2021
// MIT License
#pragma once
#include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp>
namespace ARDUINOJSON_NAMESPACE {
class RamStringAdapter : public ConstRamStringAdapter {
public:
RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {}
void copyTo(char* p, size_t n) const {
memcpy(p, _str, n);
}
typedef ARDUINOJSON_NAMESPACE::storage_policies::store_by_copy storage_policy;
};
template <typename TChar>
inline RamStringAdapter adaptString(const TChar* str) {
return RamStringAdapter(reinterpret_cast<const char*>(str));
}
inline RamStringAdapter adaptString(char* str) {
return RamStringAdapter(str);
}
template <typename TChar>
struct IsString<TChar*> {
static const bool value = sizeof(TChar) == 1;
};
template <>
struct IsString<void*> {
static const bool value = false;
};
} // namespace ARDUINOJSON_NAMESPACE

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