mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f8581f989 | ||
|
|
4c60a88221 | ||
|
|
d093886571 | ||
|
|
9e251fd3de | ||
|
|
89fd16d48f | ||
|
|
75fc8c201a | ||
|
|
f1a3bf0e6a | ||
|
|
86afa20470 | ||
|
|
32e3f69961 | ||
|
|
1b7d999fc4 | ||
|
|
6e6023cfd1 | ||
|
|
e64a374174 | ||
|
|
400100759a | ||
|
|
3e49dc113e | ||
|
|
7b96baa9b8 | ||
|
|
8bdd01f73f | ||
|
|
b36477cc8a | ||
|
|
ebfc4a64e2 | ||
|
|
fd48fb63d8 | ||
|
|
20d747330c | ||
|
|
781fb67a4e | ||
|
|
2b44155869 | ||
|
|
9ca0782ae7 | ||
|
|
4b831e864c | ||
|
|
16dc82da1c | ||
|
|
8cd0a9a761 | ||
|
|
b928ad89d9 | ||
|
|
12671f7ed3 | ||
|
|
22184f13f2 | ||
|
|
778bbe3b81 | ||
|
|
23d4f608c5 | ||
|
|
73a51ae4ad |
@@ -1,7 +1,6 @@
|
|||||||
name: 'github-releases-to-discord'
|
name: 'github-releases-to-discord'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/pre_release.yml
vendored
4
.github/workflows/pre_release.yml
vendored
@@ -48,10 +48,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
platformio run -e ci_s3
|
platformio run -e ci_s3
|
||||||
|
|
||||||
- name: Build E32V2 firmware
|
|
||||||
run: |
|
|
||||||
platformio run -e ci_16M
|
|
||||||
|
|
||||||
- name: Create a GH Release
|
- name: Create a GH Release
|
||||||
id: 'automatic_releases'
|
id: 'automatic_releases'
|
||||||
uses: 'marvinpinto/action-automatic-releases@latest'
|
uses: 'marvinpinto/action-automatic-releases@latest'
|
||||||
|
|||||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -1,5 +1,8 @@
|
|||||||
# vscode
|
# vscode
|
||||||
.vscode/*
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/extensions.json
|
||||||
|
.vscode/launch.json
|
||||||
|
# .vscode/settings.json
|
||||||
|
|
||||||
# c++ compiling
|
# c++ compiling
|
||||||
.clang_complete
|
.clang_complete
|
||||||
@@ -9,11 +12,11 @@ cppcheck.out.xml
|
|||||||
# platformio
|
# platformio
|
||||||
.pio
|
.pio
|
||||||
pio_local.ini
|
pio_local.ini
|
||||||
*_old
|
|
||||||
|
|
||||||
# OS specific
|
# OS specific
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*Thumbs.db
|
*Thumbs.db
|
||||||
|
emsesp
|
||||||
|
|
||||||
# web specfic
|
# web specfic
|
||||||
build/
|
build/
|
||||||
@@ -35,13 +38,12 @@ stats.html
|
|||||||
!.yarn/versions
|
!.yarn/versions
|
||||||
yarn.lock
|
yarn.lock
|
||||||
interface/analyse.html
|
interface/analyse.html
|
||||||
interface/vite.config.ts.timestamp*
|
|
||||||
|
|
||||||
# scripts
|
# scripts
|
||||||
test.sh
|
test.sh
|
||||||
scripts/run.sh
|
scripts/run.sh
|
||||||
scripts/__pycache__
|
scripts/__pycache__
|
||||||
scripts/stackdmp.txt
|
/scripts/stackdmp.txt
|
||||||
|
|
||||||
# i18n generated files
|
# i18n generated files
|
||||||
interface/src/i18n/i18n-react.tsx
|
interface/src/i18n/i18n-react.tsx
|
||||||
@@ -55,6 +57,8 @@ interface/src/i18n/i18n-util.async.ts
|
|||||||
sonar/
|
sonar/
|
||||||
bw-output/
|
bw-output/
|
||||||
|
|
||||||
# testing
|
# entity dump results
|
||||||
emsesp
|
# dump_entities.csv
|
||||||
|
# dump_entities.xls*
|
||||||
|
|
||||||
|
benchmark/*.log
|
||||||
|
|||||||
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
@@ -2,6 +2,8 @@
|
|||||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||||
// for the documentation about the extensions.json format
|
// for the documentation about the extensions.json format
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
"platformio.platformio-ide"
|
"platformio.platformio-ide"
|
||||||
],
|
],
|
||||||
"unwantedRecommendations": [
|
"unwantedRecommendations": [
|
||||||
|
|||||||
88
.vscode/settings.json
vendored
Normal file
88
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"search.exclude": {
|
||||||
|
"**/.yarn": true,
|
||||||
|
"**/.pnp.*": true
|
||||||
|
},
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll": "explicit"
|
||||||
|
},
|
||||||
|
"eslint.nodePath": "interface/.yarn/sdks",
|
||||||
|
"eslint.workingDirectories": ["interface"],
|
||||||
|
"prettier.prettierPath": "",
|
||||||
|
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||||
|
"files.associations": {
|
||||||
|
"*.tsx": "typescriptreact",
|
||||||
|
"*.tcc": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"regex": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bitset": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"unordered_set": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"cinttypes": "cpp",
|
||||||
|
"typeinfo": "cpp"
|
||||||
|
},
|
||||||
|
"todo-tree.filtering.excludeGlobs": [
|
||||||
|
"**/vendor/**",
|
||||||
|
"**/node_modules/**",
|
||||||
|
"**/dist/**",
|
||||||
|
"**/bower_components/**",
|
||||||
|
"**/build/**",
|
||||||
|
"**/.vscode/**",
|
||||||
|
"**/.github/**",
|
||||||
|
"**/_output/**",
|
||||||
|
"**/*.min.*",
|
||||||
|
"**/*.map",
|
||||||
|
"**/ArduinoJson/**"
|
||||||
|
],
|
||||||
|
"cSpell.enableFiletypes": ["!cpp"]
|
||||||
|
}
|
||||||
18
.vscode/tasks.json
vendored
Normal file
18
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"label": "build standalone emsesp",
|
||||||
|
"command": "make",
|
||||||
|
"args": [],
|
||||||
|
"problemMatcher": ["$gcc"],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
54
CHANGELOG.md
54
CHANGELOG.md
@@ -5,61 +5,11 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [3.6.5] March 23 2024
|
|
||||||
|
|
||||||
## **IMPORTANT! BREAKING CHANGES**
|
|
||||||
|
|
||||||
- The Wifi Tx Power setting in Network Settings will be reset to Auto
|
|
||||||
|
|
||||||
## Added
|
|
||||||
|
|
||||||
- thermostat boost mode and boost time [#1446](https://github.com/emsesp/EMS-ESP32/issues/1446)
|
|
||||||
- heatpump energy meters [#1463](https://github.com/emsesp/EMS-ESP32/issues/1463)
|
|
||||||
- heatpump max power [#1475](https://github.com/emsesp/EMS-ESP32/issues/1475)
|
|
||||||
- checkbox for MQTT-TLS enable [#1474](https://github.com/emsesp/EMS-ESP32/issues/1474)
|
|
||||||
- added SK (Slovak) language. Thanks @misa1515
|
|
||||||
- CPU info [#1497](https://github.com/emsesp/EMS-ESP32/pull/1497)
|
|
||||||
- Show network hostname in Web UI under Network Status
|
|
||||||
- Improved HA Discovery so each section (EMS device, Scheduler, Analog, Temperature, Custom, Shower) have their own section
|
|
||||||
- boiler Bosch C1200W, id 12, [#1536](https://github.com/emsesp/EMS-ESP32/issues/1536)
|
|
||||||
- mixer MM100 telegram 0x2CC [#1554](https://github.com/emsesp/EMS-ESP32/issues/1554)
|
|
||||||
- boiler hpSetDiffPressure [#1563](https://github.com/emsesp/EMS-ESP32/issues/1563)
|
|
||||||
- custom variables [#1423](https://github.com/emsesp/EMS-ESP32/issues/1423)
|
|
||||||
- weather compensation [#1642](https://github.com/emsesp/EMS-ESP32/issues/1642)
|
|
||||||
- env and partitions for DevKitC-1-N32R8 [#1635](https://github.com/emsesp/EMS-ESP32/discussions/1635)
|
|
||||||
- command `restart partitionname` and button long press to start with other partition [#1657](https://github.com/emsesp/EMS-ESP32/issues/1657)
|
|
||||||
- command `set service <mqtt|ota|ntp|ap> <enable|disable>` [#1663](https://github.com/emsesp/EMS-ESP32/issues/1663)
|
|
||||||
|
|
||||||
## Fixed
|
|
||||||
|
|
||||||
- exhaust temperature for some boilers
|
|
||||||
- add back boil2hyst [#1477](https://github.com/emsesp/EMS-ESP32/issues/1477)
|
|
||||||
- subscribed MQTT topics not detecting changes by EMS-ESP [#1494](https://github.com/emsesp/EMS-ESP32/issues/1494)
|
|
||||||
- changed HA name and grouping to be consistent [#1528](https://github.com/emsesp/EMS-ESP32/issues/1528)
|
|
||||||
- MQTT autodiscovery in Domoticz not working [#1360](https://github.com/emsesp/EMS-ESP32/issues/1528)
|
|
||||||
- dhw comfort for new ems+, [#1495](https://github.com/emsesp/EMS-ESP32/issues/1495)
|
|
||||||
- added writeable icon to Web's Custom Entity page for each entity shown in the table
|
|
||||||
- Wifi Tx Power not adjusted [#1614](https://github.com/emsesp/EMS-ESP32/issues/1614)
|
|
||||||
- MQTT discovery of custom entity doesn't consider type of data [#1587](https://github.com/emsesp/EMS-ESP32/issues/1587)
|
|
||||||
- WiFi TxPower wasn't correctly used. Added an 'Auto' setting, which is the default.
|
|
||||||
- dns w/wo IPv6 [#1644](https://github.com/emsesp/EMS-ESP32/issues/1644)
|
|
||||||
|
|
||||||
## Changed
|
|
||||||
|
|
||||||
- HA don't set entity_category to Diagnostic/Configuration for EMS entities [#1459](https://github.com/emsesp/EMS-ESP32/discussions/1459)
|
|
||||||
- upgraded ArduinoJson to 7.0.0 #1538 and then 7.0.2
|
|
||||||
- small changes to the API for analog and temperature sensors
|
|
||||||
- Length of mqtt Broker adress [#1619](https://github.com/emsesp/EMS-ESP32/issues/1619)
|
|
||||||
- C++ optimizations - see <https://github.com/emsesp/EMS-ESP32/pull/1615>
|
|
||||||
- Send MQTT heartbeat immediately after connection [#1628](https://github.com/emsesp/EMS-ESP32/issues/1628)
|
|
||||||
- 16MB partitions with second nvs, larger FS, Coredump, optional factory partition
|
|
||||||
- stop fetching empty telegrams after 5 min
|
|
||||||
|
|
||||||
## [3.6.4] November 24 2023
|
## [3.6.4] November 24 2023
|
||||||
|
|
||||||
## **IMPORTANT! BREAKING CHANGES**
|
## **IMPORTANT! BREAKING CHANGES**
|
||||||
|
|
||||||
Writeable Text entities have moved from type `sensor` to `text` in Home Assistant to make them also editable within an HA dashboard. Examples are `datetime`, `holidays`, `switchtime`, `vacations`, `maintenancedate`. You will need to manually remove any old discovery topics from your MQTT broker using an application like MQTT Explorer.
|
Writeable Text entities have moved from type `sensor` to `text` in Home Assistant to make them also editable within an HA dashboard. Examples are `datetime`, `holidays`, `switchtime`, `vacations`, `maintenancedate`... You will need to manually remove any old discovery topics from your MQTT broker using an application like MQTT Explorer.
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
@@ -286,7 +236,7 @@ There are breaking changes between 3.5.x and earlier versions of 3.6.0. Please r
|
|||||||
|
|
||||||
- fix Table resizing in WebUI [#519](https://github.com/emsesp/EMS-ESP32/issues/519)
|
- fix Table resizing in WebUI [#519](https://github.com/emsesp/EMS-ESP32/issues/519)
|
||||||
- allow larger customization files [#570](https://github.com/emsesp/EMS-ESP32/issues/570)
|
- allow larger customization files [#570](https://github.com/emsesp/EMS-ESP32/issues/570)
|
||||||
- losing entity wwcomfort [#581](https://github.com/emsesp/EMS-ESP32/issues/581)
|
- losing entitiy wwcomfort [#581](https://github.com/emsesp/EMS-ESP32/issues/581)
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,24 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [3.x]
|
## [3.6.5]
|
||||||
|
|
||||||
## **IMPORTANT! BREAKING CHANGES**
|
## **IMPORTANT! BREAKING CHANGES**
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
|
- thermostat boost mode and boost time [#1446](https://github.com/emsesp/EMS-ESP32/issues/1446)
|
||||||
|
- heatpump energy meters [#1463](https://github.com/emsesp/EMS-ESP32/issues/1463)
|
||||||
|
- heatpump max power [#1475](https://github.com/emsesp/EMS-ESP32/issues/1475)
|
||||||
|
- checkbox for MQTT-TLS enable [#1474](https://github.com/emsesp/EMS-ESP32/issues/1474)
|
||||||
|
- added SK (Slovencina) language. Thanks @misa1515
|
||||||
|
- CPU info [#1497](https://github.com/emsesp/EMS-ESP32/pull/1497)
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
- exhaust temperature for some boilers
|
||||||
|
- add back boil2hyst [#1477](https://github.com/emsesp/EMS-ESP32/issues/1477)
|
||||||
|
- subscribed MQTT topics not detecting changes by EMS-ESP [#1494](https://github.com/emsesp/EMS-ESP32/issues/1494)
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
|
- HA don't set entity_category to Diagnostic/Configuration for EMS entities [#1459](https://github.com/emsesp/EMS-ESP32/discussions/1459)
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -42,7 +42,7 @@ DEFINES += -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DAR
|
|||||||
DEFINES += -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_TEST -D__linux__ -DEMC_RX_BUFFER_SIZE=1500
|
DEFINES += -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_TEST -D__linux__ -DEMC_RX_BUFFER_SIZE=1500
|
||||||
DEFINES += $(ARGS)
|
DEFINES += $(ARGS)
|
||||||
|
|
||||||
DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.5-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\"
|
DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.4-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\"
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# Sources & Files
|
# Sources & Files
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ EMS-ESP is a project owned and maintained by [proddy](https://github.com/proddy)
|
|||||||
- [uuid-\*](https://github.com/nomis/mcu-uuid-console) from @nomis. The console, syslog, telnet and logging are based off these open source libraries
|
- [uuid-\*](https://github.com/nomis/mcu-uuid-console) from @nomis. The console, syslog, telnet and logging are based off these open source libraries
|
||||||
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson) for all the JSON
|
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson) for all the JSON
|
||||||
- [espMqttClient](https://github.com/bertmelis/espMqttClient) for the MQTT client, with custom modifications from @MichaelDvP and @proddy
|
- [espMqttClient](https://github.com/bertmelis/espMqttClient) for the MQTT client, with custom modifications from @MichaelDvP and @proddy
|
||||||
- ESPAsyncWebServer and AsyncTCP for the Web server and TCP backends, with custom modifications for performance
|
|
||||||
|
|
||||||
## **License**
|
## **License**
|
||||||
|
|
||||||
|
|||||||
39
benchmark/http-client-test.js
Executable file
39
benchmark/http-client-test.js
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const axios = require('axios');
|
||||||
|
|
||||||
|
const url = 'http://10.10.10.135/api/system/commands';
|
||||||
|
const queryParams = {
|
||||||
|
entity: 'commands',
|
||||||
|
id: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalRequests = 1000000;
|
||||||
|
const requestsPerCount = 100;
|
||||||
|
|
||||||
|
let requestCount = 0;
|
||||||
|
|
||||||
|
function fetchData() {
|
||||||
|
axios
|
||||||
|
.get(url, { params: queryParams })
|
||||||
|
.then((response) => {
|
||||||
|
requestCount++;
|
||||||
|
|
||||||
|
if (requestCount % requestsPerCount === 0) {
|
||||||
|
console.log(`Requests completed: ${requestCount}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestCount < totalRequests) {
|
||||||
|
fetchData();
|
||||||
|
} else {
|
||||||
|
console.log('All requests completed.');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error making request:', error.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start making requests
|
||||||
|
console.log(`Starting test`);
|
||||||
|
fetchData();
|
||||||
38
benchmark/loadtest-http.sh
Executable file
38
benchmark/loadtest-http.sh
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Install:
|
||||||
|
# npm install -g autocannon
|
||||||
|
# yarn global add autocannon
|
||||||
|
#
|
||||||
|
# or run https://github.com/nearform/autocannon-ui
|
||||||
|
|
||||||
|
TEST_IP="10.10.10.135"
|
||||||
|
TEST_TIME=60
|
||||||
|
LOG_FILE=http-loadtest.log
|
||||||
|
TIMEOUT=10000
|
||||||
|
PROTOCOL=http
|
||||||
|
#PROTOCOL=https
|
||||||
|
|
||||||
|
if test -f "$LOG_FILE"; then
|
||||||
|
rm $LOG_FILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
# for CONCURRENCY in 1 2 3 4 5 6 7 8 9 10 15 20
|
||||||
|
for CONCURRENCY in 1
|
||||||
|
#for CONCURRENCY in 20
|
||||||
|
do
|
||||||
|
printf "\n\nCLIENTS: *** $CONCURRENCY ***\n\n" >> $LOG_FILE
|
||||||
|
echo "Testing $CONCURRENCY clients on $PROTOCOL://$TEST_IP/"
|
||||||
|
autocannon -c $CONCURRENCY -w 1 -d $TEST_TIME --renderStatusCodes "$PROTOCOL://$TEST_IP/" >> $LOG_FILE 2>&1
|
||||||
|
printf "\n\n----------------\n\n" >> $LOG_FILE
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
echo "Testing $CONCURRENCY clients on $PROTOCOL://$TEST_IP/api/system/commands"
|
||||||
|
autocannon -c $CONCURRENCY -w 1 -d $TEST_TIME --renderStatusCodes "$PROTOCOL://$TEST_IP/api/system/commands" >> $LOG_FILE 2>&1
|
||||||
|
printf "\n\n----------------\n\n" >> $LOG_FILE
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
echo "Testing $CONCURRENCY clients on $PROTOCOL://$TEST_IP/app/icon.png"
|
||||||
|
autocannon -c $CONCURRENCY -w 1 -d $TEST_TIME --renderStatusCodes "$PROTOCOL://$TEST_IP/app/icon.png" >> $LOG_FILE 2>&1
|
||||||
|
printf "\n\n----------------\n\n" >> $LOG_FILE
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
8
benchmark/package.json
Normal file
8
benchmark/package.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"autocannon": "^7.14.0",
|
||||||
|
"axios": "^1.6.2",
|
||||||
|
"eventsource": "^2.0.2",
|
||||||
|
"ws": "^8.14.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
nvs, data, nvs, 0x9000, 0x005000,
|
nvs, data, nvs, 0x9000, 0x5000,
|
||||||
otadata, data, ota, , 0x002000,
|
otadata, data, ota, , 0x2000,
|
||||||
app0, app, ota_0, , 0x5D0000,
|
app0, app, ota_0, , 0x7F0000,
|
||||||
app1, app, ota_1, , 0x5D0000,
|
app1, app, ota_1, , 0x7F0000,
|
||||||
nvs1, data, nvs, , 0x040000,
|
spiffs, data, spiffs, , 64K,
|
||||||
spiffs, data, spiffs, , 0x400000,
|
|
||||||
coredump, data, coredump,, 0x010000,
|
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
# Name, Type, SubType, Offset, Size, Flags
|
|
||||||
nvs, data, nvs, 0x9000, 0x005000,
|
|
||||||
otadata, data, ota, , 0x002000,
|
|
||||||
boot, app, factory, , 0x280000,
|
|
||||||
app0, app, ota_0, , 0x590000,
|
|
||||||
app1, app, ota_1, , 0x590000,
|
|
||||||
nvs1, data, nvs, , 0x040000,
|
|
||||||
spiffs, data, spiffs, , 0x200000,
|
|
||||||
coredump, data, coredump,, 0x010000,
|
|
||||||
|
@@ -1,8 +0,0 @@
|
|||||||
# Name, Type, SubType, Offset, Size, Flags
|
|
||||||
nvs, data, nvs, 0x9000, 0x005000,
|
|
||||||
otadata, data, ota, , 0x002000,
|
|
||||||
app0, app, ota_0, , 0xDD0000,
|
|
||||||
app1, app, ota_1, , 0xDD0000,
|
|
||||||
nvs1, data, nvs, , 0x040000,
|
|
||||||
spiffs, data, spiffs, , 0x400000,
|
|
||||||
coredump, data, coredump,, 0x010000,
|
|
||||||
|
@@ -36,6 +36,7 @@ build_flags =
|
|||||||
-D FACTORY_MQTT_PORT=1883
|
-D FACTORY_MQTT_PORT=1883
|
||||||
-D FACTORY_MQTT_USERNAME=\"\"
|
-D FACTORY_MQTT_USERNAME=\"\"
|
||||||
-D FACTORY_MQTT_PASSWORD=\"\"
|
-D FACTORY_MQTT_PASSWORD=\"\"
|
||||||
|
-D FACTORY_MQTT_CLIENT_ID=\"ems-esp\"
|
||||||
-D FACTORY_MQTT_KEEP_ALIVE=60
|
-D FACTORY_MQTT_KEEP_ALIVE=60
|
||||||
-D FACTORY_MQTT_CLEAN_SESSION=false
|
-D FACTORY_MQTT_CLEAN_SESSION=false
|
||||||
-D FACTORY_MQTT_MAX_TOPIC_LENGTH=128
|
-D FACTORY_MQTT_MAX_TOPIC_LENGTH=128
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
},
|
},
|
||||||
"extends": [
|
"extends": [
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
// "airbnb/hooks",
|
"airbnb/hooks",
|
||||||
// "airbnb-typescript",
|
"airbnb-typescript",
|
||||||
"plugin:react/recommended",
|
"plugin:react/recommended",
|
||||||
"plugin:react/jsx-runtime",
|
"plugin:react/jsx-runtime",
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -4,4 +4,4 @@ enableGlobalCache: false
|
|||||||
|
|
||||||
nodeLinker: node-modules
|
nodeLinker: node-modules
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-4.1.1.cjs
|
yarnPath: .yarn/releases/yarn-4.0.2.cjs
|
||||||
|
|||||||
@@ -13,29 +13,27 @@
|
|||||||
"build-hosted": "typesafe-i18n --no-watch && vite build --mode hosted",
|
"build-hosted": "typesafe-i18n --no-watch && vite build --mode hosted",
|
||||||
"preview-standalone": "typesafe-i18n --no-watch && vite build && concurrently -c \"auto\" \"npm:mock-api\" \"vite preview\"",
|
"preview-standalone": "typesafe-i18n --no-watch && vite build && concurrently -c \"auto\" \"npm:mock-api\" \"vite preview\"",
|
||||||
"mock-api": "bun --watch ../mock-api/server.ts",
|
"mock-api": "bun --watch ../mock-api/server.ts",
|
||||||
"old_mock-api": "bun --watch ../mock-api/server.js",
|
|
||||||
"standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:mock-api\" \"vite\"",
|
"standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:mock-api\" \"vite\"",
|
||||||
"old_standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:old_mock-api\" \"vite\"",
|
|
||||||
"typesafe-i18n": "typesafe-i18n --no-watch",
|
"typesafe-i18n": "typesafe-i18n --no-watch",
|
||||||
"webUI": "node progmem-generator.js",
|
"webUI": "node progmem-generator.js",
|
||||||
"format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'",
|
"format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'",
|
||||||
"lint": "eslint . --cache --fix"
|
"lint": "eslint . --cache --fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alova/adapter-xhr": "^1.0.3",
|
"@alova/adapter-xhr": "^1.0.2",
|
||||||
"@babel/core": "^7.24.3",
|
"@babel/core": "^7.23.7",
|
||||||
"@emotion/react": "^11.11.4",
|
"@emotion/react": "^11.11.3",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@mui/icons-material": "^5.15.14",
|
"@mui/icons-material": "^5.15.2",
|
||||||
"@mui/material": "^5.15.14",
|
"@mui/material": "^5.15.2",
|
||||||
"@table-library/react-table-library": "4.1.7",
|
"@table-library/react-table-library": "4.1.7",
|
||||||
"@types/imagemin": "^8.0.5",
|
"@types/imagemin": "^8.0.5",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^20.11.30",
|
"@types/node": "^20.10.6",
|
||||||
"@types/react": "^18.2.69",
|
"@types/react": "^18.2.46",
|
||||||
"@types/react-dom": "^18.2.22",
|
"@types/react-dom": "^18.2.18",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"alova": "^2.18.0",
|
"alova": "^2.16.2",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
@@ -44,35 +42,37 @@
|
|||||||
"react": "latest",
|
"react": "latest",
|
||||||
"react-dom": "latest",
|
"react-dom": "latest",
|
||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
"react-icons": "^5.0.1",
|
"react-icons": "^4.12.0",
|
||||||
"react-router-dom": "^6.22.3",
|
"react-router-dom": "^6.21.1",
|
||||||
"react-toastify": "^10.0.5",
|
"react-toastify": "^9.1.3",
|
||||||
"sockette": "^2.0.6",
|
"sockette": "^2.0.6",
|
||||||
"typesafe-i18n": "^5.26.2",
|
"typesafe-i18n": "^5.26.2",
|
||||||
"typescript": "^5.4.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@preact/compat": "^17.1.2",
|
"@preact/compat": "^17.1.2",
|
||||||
"@preact/preset-vite": "^2.8.2",
|
"@preact/preset-vite": "^2.7.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
"@typescript-eslint/eslint-plugin": "^6.17.0",
|
||||||
"@typescript-eslint/parser": "^7.3.1",
|
"@typescript-eslint/parser": "^6.17.0",
|
||||||
"concurrently": "^8.2.2",
|
"concurrently": "^8.2.2",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.56.0",
|
||||||
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
|
"eslint-config-airbnb-typescript": "^17.1.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-import-resolver-typescript": "^3.6.1",
|
"eslint-import-resolver-typescript": "^3.6.1",
|
||||||
"eslint-plugin-autofix": "^1.1.0",
|
"eslint-plugin-autofix": "^1.1.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||||
"eslint-plugin-prettier": "alpha",
|
"eslint-plugin-prettier": "alpha",
|
||||||
"eslint-plugin-react": "^7.34.1",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"preact": "^10.20.1",
|
"preact": "^10.19.3",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.1.1",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
"terser": "^5.29.2",
|
"terser": "^5.26.0",
|
||||||
"vite": "^5.2.4",
|
"vite": "^5.0.10",
|
||||||
"vite-plugin-imagemin": "^0.6.1",
|
"vite-plugin-imagemin": "^0.6.1",
|
||||||
"vite-tsconfig-paths": "^4.3.2"
|
"vite-tsconfig-paths": "^4.2.3"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@4.1.1"
|
"packageManager": "yarn@4.0.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { readdirSync, existsSync, unlinkSync, readFileSync, createWriteStream }
|
|||||||
import { resolve, relative, sep } from 'path';
|
import { resolve, relative, sep } from 'path';
|
||||||
import zlib from 'zlib';
|
import zlib from 'zlib';
|
||||||
import mime from 'mime-types';
|
import mime from 'mime-types';
|
||||||
import crypto from 'crypto';
|
|
||||||
|
|
||||||
const ARDUINO_INCLUDES = '#include <Arduino.h>\n\n';
|
const ARDUINO_INCLUDES = '#include <Arduino.h>\n\n';
|
||||||
const INDENT = ' ';
|
const INDENT = ' ';
|
||||||
@@ -12,17 +11,14 @@ const bytesPerLine = 20;
|
|||||||
var totalSize = 0;
|
var totalSize = 0;
|
||||||
|
|
||||||
const generateWWWClass = () =>
|
const generateWWWClass = () =>
|
||||||
`typedef std::function<void(const char * uri, const String & contentType, const uint8_t * content, size_t len, const String & hash)> RouteRegistrationHandler;
|
`typedef std::function<void(const String &, const String & contentType, const uint8_t * content, size_t len)> RouteRegistrationHandler;
|
||||||
// Total size is ${totalSize} bytes
|
// Total size is ${totalSize} bytes
|
||||||
|
|
||||||
class WWWData {
|
class WWWData {
|
||||||
${indent}public:
|
${indent}public:
|
||||||
${indent.repeat(2)}static void registerRoutes(RouteRegistrationHandler handler) {
|
${indent.repeat(2)}static void registerRoutes(RouteRegistrationHandler handler) {
|
||||||
${fileInfo
|
${fileInfo
|
||||||
.map(
|
.map((file) => `${indent.repeat(3)}handler("${file.uri}", "${file.mimeType}", ${file.variable}, ${file.size});`)
|
||||||
(file) =>
|
|
||||||
`${indent.repeat(3)}handler("${file.uri}", "${file.mimeType}", ${file.variable}, ${file.size}, "${file.hash}");`
|
|
||||||
)
|
|
||||||
.join('\n')}
|
.join('\n')}
|
||||||
${indent.repeat(2)}}
|
${indent.repeat(2)}}
|
||||||
};
|
};
|
||||||
@@ -54,12 +50,6 @@ const writeFile = (relativeFilePath, buffer) => {
|
|||||||
writeStream.write('const uint8_t ' + variable + '[] = {');
|
writeStream.write('const uint8_t ' + variable + '[] = {');
|
||||||
// const zipBuffer = zlib.brotliCompressSync(buffer, { quality: 1 });
|
// const zipBuffer = zlib.brotliCompressSync(buffer, { quality: 1 });
|
||||||
const zipBuffer = zlib.gzipSync(buffer, { level: 9 });
|
const zipBuffer = zlib.gzipSync(buffer, { level: 9 });
|
||||||
|
|
||||||
// create sha
|
|
||||||
const hashSum = crypto.createHash('sha256');
|
|
||||||
hashSum.update(zipBuffer);
|
|
||||||
const hash = hashSum.digest('hex');
|
|
||||||
|
|
||||||
zipBuffer.forEach((b) => {
|
zipBuffer.forEach((b) => {
|
||||||
if (!(size % bytesPerLine)) {
|
if (!(size % bytesPerLine)) {
|
||||||
writeStream.write('\n');
|
writeStream.write('\n');
|
||||||
@@ -68,19 +58,15 @@ const writeFile = (relativeFilePath, buffer) => {
|
|||||||
writeStream.write('0x' + ('00' + b.toString(16).toUpperCase()).slice(-2) + ',');
|
writeStream.write('0x' + ('00' + b.toString(16).toUpperCase()).slice(-2) + ',');
|
||||||
size++;
|
size++;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (size % bytesPerLine) {
|
if (size % bytesPerLine) {
|
||||||
writeStream.write('\n');
|
writeStream.write('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
writeStream.write('};\n\n');
|
writeStream.write('};\n\n');
|
||||||
|
|
||||||
fileInfo.push({
|
fileInfo.push({
|
||||||
uri: '/' + relativeFilePath.replace(sep, '/'),
|
uri: '/' + relativeFilePath.replace(sep, '/'),
|
||||||
mimeType,
|
mimeType,
|
||||||
variable,
|
variable,
|
||||||
size,
|
size
|
||||||
hash
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// console.log(relativeFilePath + ' (size ' + size + ' bytes)');
|
// console.log(relativeFilePath + ' (size ' + size + ' bytes)');
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { ToastContainer, Slide } from 'react-toastify';
|
|||||||
import 'react-toastify/dist/ReactToastify.min.css';
|
import 'react-toastify/dist/ReactToastify.min.css';
|
||||||
|
|
||||||
import { localStorageDetector } from 'typesafe-i18n/detectors';
|
import { localStorageDetector } from 'typesafe-i18n/detectors';
|
||||||
|
import { FeaturesLoader } from './contexts/features';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import AppRouting from 'AppRouting';
|
import AppRouting from 'AppRouting';
|
||||||
import CustomTheme from 'CustomTheme';
|
import CustomTheme from 'CustomTheme';
|
||||||
@@ -26,7 +27,9 @@ const App: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<TypesafeI18n locale={detectedLocale}>
|
<TypesafeI18n locale={detectedLocale}>
|
||||||
<CustomTheme>
|
<CustomTheme>
|
||||||
<AppRouting />
|
<FeaturesLoader>
|
||||||
|
<AppRouting />
|
||||||
|
</FeaturesLoader>
|
||||||
<ToastContainer
|
<ToastContainer
|
||||||
position="bottom-left"
|
position="bottom-left"
|
||||||
autoClose={3000}
|
autoClose={3000}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Box, Paper, Typography, MenuItem, TextField, Button } from '@mui/materi
|
|||||||
import { useRequest } from 'alova';
|
import { useRequest } from 'alova';
|
||||||
import { useContext, useState } from 'react';
|
import { useContext, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
import { FeaturesContext } from './contexts/features';
|
||||||
import type { ValidateFieldsError } from 'async-validator';
|
import type { ValidateFieldsError } from 'async-validator';
|
||||||
|
|
||||||
import type { Locales } from 'i18n/i18n-types';
|
import type { Locales } from 'i18n/i18n-types';
|
||||||
@@ -34,6 +35,8 @@ const SignIn: FC = () => {
|
|||||||
|
|
||||||
const { LL, setLocale, locale } = useContext(I18nContext);
|
const { LL, setLocale, locale } = useContext(I18nContext);
|
||||||
|
|
||||||
|
const { features } = useContext(FeaturesContext);
|
||||||
|
|
||||||
const [signInRequest, setSignInRequest] = useState<SignInRequest>({
|
const [signInRequest, setSignInRequest] = useState<SignInRequest>({
|
||||||
username: '',
|
username: '',
|
||||||
password: ''
|
password: ''
|
||||||
@@ -109,6 +112,7 @@ const SignIn: FC = () => {
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Typography variant="h4">{PROJECT_NAME}</Typography>
|
<Typography variant="h4">{PROJECT_NAME}</Typography>
|
||||||
|
<Typography variant="subtitle2">{features.version}</Typography>
|
||||||
|
|
||||||
<TextField name="locale" variant="outlined" value={locale} onChange={onLocaleSelected} size="small" select>
|
<TextField name="locale" variant="outlined" value={locale} onChange={onLocaleSelected} size="small" select>
|
||||||
<MenuItem key="de" value="de">
|
<MenuItem key="de" value="de">
|
||||||
|
|||||||
5
interface/src/api/features.ts
Normal file
5
interface/src/api/features.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { alovaInstance } from './endpoints';
|
||||||
|
|
||||||
|
import type { Features } from 'types';
|
||||||
|
|
||||||
|
export const readFeatures = () => alovaInstance.Get<Features>('/rest/features');
|
||||||
@@ -50,10 +50,8 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, isUploading, pr
|
|||||||
|
|
||||||
const progressText = () => {
|
const progressText = () => {
|
||||||
if (uploading) {
|
if (uploading) {
|
||||||
if (progress.total && progress.loaded) {
|
if (progress.total) {
|
||||||
return progress.loaded <= progress.total
|
return LL.UPLOADING() + ': ' + Math.round((progress.loaded * 100) / progress.total) + '%';
|
||||||
? LL.UPLOADING() + ': ' + Math.round((progress.loaded * 100) / progress.total) + '%'
|
|
||||||
: LL.UPLOADING() + ': ' + Math.round((progress.total * 100) / progress.loaded) + '%';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return LL.UPLOAD_DROP_TEXT();
|
return LL.UPLOAD_DROP_TEXT();
|
||||||
@@ -85,13 +83,7 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, isUploading, pr
|
|||||||
<Box width="100%" p={2}>
|
<Box width="100%" p={2}>
|
||||||
<LinearProgress
|
<LinearProgress
|
||||||
variant="determinate"
|
variant="determinate"
|
||||||
value={
|
value={progress.total === 0 ? 0 : Math.round((progress.loaded * 100) / progress.total)}
|
||||||
progress.total === 0 || progress.loaded === 0
|
|
||||||
? 0
|
|
||||||
: progress.loaded <= progress.total
|
|
||||||
? Math.round((progress.loaded * 100) / progress.total)
|
|
||||||
: Math.round((progress.total * 100) / progress.loaded)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Button startIcon={<CancelIcon />} variant="outlined" color="secondary" onClick={onCancel}>
|
<Button startIcon={<CancelIcon />} variant="outlined" color="secondary" onClick={onCancel}>
|
||||||
|
|||||||
25
interface/src/contexts/features/FeaturesLoader.tsx
Normal file
25
interface/src/contexts/features/FeaturesLoader.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { useRequest } from 'alova';
|
||||||
|
|
||||||
|
import { FeaturesContext } from '.';
|
||||||
|
import type { FC } from 'react';
|
||||||
|
|
||||||
|
import type { RequiredChildrenProps } from 'utils';
|
||||||
|
import * as FeaturesApi from 'api/features';
|
||||||
|
|
||||||
|
const FeaturesLoader: FC<RequiredChildrenProps> = (props) => {
|
||||||
|
const { data: features } = useRequest(FeaturesApi.readFeatures);
|
||||||
|
|
||||||
|
if (features) {
|
||||||
|
return (
|
||||||
|
<FeaturesContext.Provider
|
||||||
|
value={{
|
||||||
|
features
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</FeaturesContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FeaturesLoader;
|
||||||
10
interface/src/contexts/features/context.ts
Normal file
10
interface/src/contexts/features/context.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
import type { Features } from 'types';
|
||||||
|
|
||||||
|
export interface FeaturesContextValue {
|
||||||
|
features: Features;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FeaturesContextDefaultValue = {} as FeaturesContextValue;
|
||||||
|
export const FeaturesContext = createContext(FeaturesContextDefaultValue);
|
||||||
2
interface/src/contexts/features/index.ts
Normal file
2
interface/src/contexts/features/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './context';
|
||||||
|
export { default as FeaturesLoader } from './FeaturesLoader';
|
||||||
@@ -72,7 +72,6 @@ const MqttSettingsForm: FC = () => {
|
|||||||
name="host"
|
name="host"
|
||||||
label={LL.ADDRESS_OF(LL.BROKER())}
|
label={LL.ADDRESS_OF(LL.BROKER())}
|
||||||
fullWidth
|
fullWidth
|
||||||
multiline
|
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.host}
|
value={data.host}
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
@@ -274,7 +273,6 @@ const MqttSettingsForm: FC = () => {
|
|||||||
>
|
>
|
||||||
<MenuItem value={0}>Home Assistant</MenuItem>
|
<MenuItem value={0}>Home Assistant</MenuItem>
|
||||||
<MenuItem value={1}>Domoticz</MenuItem>
|
<MenuItem value={1}>Domoticz</MenuItem>
|
||||||
<MenuItem value={2}>Domoticz (latest)</MenuItem>
|
|
||||||
</TextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import {
|
|||||||
ListItemSecondaryAction,
|
ListItemSecondaryAction,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
Typography,
|
Typography,
|
||||||
TextField,
|
InputAdornment,
|
||||||
MenuItem
|
TextField
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
// eslint-disable-next-line import/named
|
// eslint-disable-next-line import/named
|
||||||
import { updateState, useRequest } from 'alova';
|
import { updateState, useRequest } from 'alova';
|
||||||
@@ -43,7 +43,7 @@ import {
|
|||||||
} from 'components';
|
} from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
import { updateValueDirty, useRest } from 'utils';
|
import { numberValue, updateValueDirty, useRest } from 'utils';
|
||||||
|
|
||||||
import { validate } from 'validators';
|
import { validate } from 'validators';
|
||||||
import { createNetworkSettingsValidator } from 'validators/network';
|
import { createNetworkSettingsValidator } from 'validators/network';
|
||||||
@@ -88,7 +88,7 @@ const WiFiSettingsForm: FC = () => {
|
|||||||
static_ip_config: false,
|
static_ip_config: false,
|
||||||
enableIPv6: false,
|
enableIPv6: false,
|
||||||
bandwidth20: false,
|
bandwidth20: false,
|
||||||
tx_power: 0,
|
tx_power: 20,
|
||||||
nosleep: false,
|
nosleep: false,
|
||||||
enableMDNS: true,
|
enableMDNS: true,
|
||||||
enableCORS: false,
|
enableCORS: false,
|
||||||
@@ -196,29 +196,20 @@ const WiFiSettingsForm: FC = () => {
|
|||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<TextField
|
<ValidatedTextField
|
||||||
|
fieldErrors={fieldErrors}
|
||||||
name="tx_power"
|
name="tx_power"
|
||||||
label={LL.TX_POWER()}
|
label={LL.TX_POWER()}
|
||||||
|
InputProps={{
|
||||||
|
endAdornment: <InputAdornment position="end">dBm</InputAdornment>
|
||||||
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.tx_power}
|
value={numberValue(data.tx_power)}
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
type="number"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
select
|
/>
|
||||||
>
|
|
||||||
<MenuItem value={0}>Auto</MenuItem>
|
|
||||||
<MenuItem value={78}>19.5 dBm</MenuItem>
|
|
||||||
<MenuItem value={76}>19 dBm</MenuItem>
|
|
||||||
<MenuItem value={74}>18.5 dBm</MenuItem>
|
|
||||||
<MenuItem value={68}>17 dBm</MenuItem>
|
|
||||||
<MenuItem value={60}>15 dBm</MenuItem>
|
|
||||||
<MenuItem value={52}>13 dBm</MenuItem>
|
|
||||||
<MenuItem value={44}>11 dBm</MenuItem>
|
|
||||||
<MenuItem value={34}>8.5 dBm</MenuItem>
|
|
||||||
<MenuItem value={28}>7 dBm</MenuItem>
|
|
||||||
<MenuItem value={20}>5 dBm</MenuItem>
|
|
||||||
<MenuItem value={8}>2 dBm</MenuItem>
|
|
||||||
</TextField>
|
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="nosleep" checked={data.nosleep} onChange={updateFormValue} />}
|
control={<Checkbox name="nosleep" checked={data.nosleep} onChange={updateFormValue} />}
|
||||||
label={LL.NETWORK_DISABLE_SLEEP()}
|
label={LL.NETWORK_DISABLE_SLEEP()}
|
||||||
@@ -259,12 +250,10 @@ const WiFiSettingsForm: FC = () => {
|
|||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{data.enableIPv6 !== undefined && (
|
<BlockFormControlLabel
|
||||||
<BlockFormControlLabel
|
control={<Checkbox name="enableIPv6" checked={data.enableIPv6} onChange={updateFormValue} />}
|
||||||
control={<Checkbox name="enableIPv6" checked={data.enableIPv6} onChange={updateFormValue} />}
|
label={LL.NETWORK_ENABLE_IPV6()}
|
||||||
label={LL.NETWORK_ENABLE_IPV6()}
|
/>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="static_ip_config" checked={data.static_ip_config} onChange={updateFormValue} />}
|
control={<Checkbox name="static_ip_config" checked={data.static_ip_config} onChange={updateFormValue} />}
|
||||||
label={LL.NETWORK_FIXED_IP()}
|
label={LL.NETWORK_FIXED_IP()}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||||
import DnsIcon from '@mui/icons-material/Dns';
|
import DnsIcon from '@mui/icons-material/Dns';
|
||||||
import GiteIcon from '@mui/icons-material/Gite';
|
|
||||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||||
import RouterIcon from '@mui/icons-material/Router';
|
import RouterIcon from '@mui/icons-material/Router';
|
||||||
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
|
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
|
||||||
@@ -116,15 +115,6 @@ const NetworkStatusForm: FC = () => {
|
|||||||
<ListItemText primary="Status" secondary={networkStatus(data)} />
|
<ListItemText primary="Status" secondary={networkStatus(data)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
<ListItem>
|
|
||||||
<ListItemAvatar>
|
|
||||||
<Avatar sx={{ bgcolor: networkStatusHighlight(data, theme) }}>
|
|
||||||
<GiteIcon />
|
|
||||||
</Avatar>
|
|
||||||
</ListItemAvatar>
|
|
||||||
<ListItemText primary="Hostname" secondary={data.hostname} />
|
|
||||||
</ListItem>
|
|
||||||
<Divider variant="inset" component="li" />
|
|
||||||
{isWiFi(data) && (
|
{isWiFi(data) && (
|
||||||
<>
|
<>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
|
|||||||
@@ -37,8 +37,7 @@ const GenerateToken: FC<GenerateTokenProps> = ({ username, onClose }) => {
|
|||||||
if (open) {
|
if (open) {
|
||||||
void generateToken();
|
void generateToken();
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
}, [open, generateToken]);
|
||||||
}, [open]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog sx={dialogStyle} onClose={onClose} open={!!username} fullWidth maxWidth="sm">
|
<Dialog sx={dialogStyle} onClose={onClose} open={!!username} fullWidth maxWidth="sm">
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
import { useRequest } from 'alova';
|
import { useRequest } from 'alova';
|
||||||
import { useContext, useState } from 'react';
|
import { useContext, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
import { FeaturesContext } from '../../contexts/features';
|
||||||
import RestartMonitor from './RestartMonitor';
|
import RestartMonitor from './RestartMonitor';
|
||||||
import SystemStatusVersionDialog from './SystemStatusVersionDialog';
|
import SystemStatusVersionDialog from './SystemStatusVersionDialog';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
@@ -53,6 +54,8 @@ const SystemStatusForm: FC = () => {
|
|||||||
const [restarting, setRestarting] = useState<boolean>();
|
const [restarting, setRestarting] = useState<boolean>();
|
||||||
const [versionDialogOpen, setVersionDialogOpen] = useState<boolean>(false);
|
const [versionDialogOpen, setVersionDialogOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const { features } = useContext(FeaturesContext);
|
||||||
|
|
||||||
const { send: restartCommand } = useRequest(SystemApi.restart(), {
|
const { send: restartCommand } = useRequest(SystemApi.restart(), {
|
||||||
immediate: false
|
immediate: false
|
||||||
});
|
});
|
||||||
@@ -212,7 +215,7 @@ const SystemStatusForm: FC = () => {
|
|||||||
<DevicesIcon />
|
<DevicesIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="SDK" secondary={data.arduino_version + ' / ESP-IDF ' + data.sdk_version} />
|
<ListItemText primary="SDK" secondary={data.arduino_version + ' / ESP-IDF v' + data.sdk_version} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
<ListItem>
|
<ListItem>
|
||||||
@@ -224,8 +227,6 @@ const SystemStatusForm: FC = () => {
|
|||||||
<ListItemText
|
<ListItemText
|
||||||
primary="CPU"
|
primary="CPU"
|
||||||
secondary={
|
secondary={
|
||||||
data.esp_platform +
|
|
||||||
'/' +
|
|
||||||
data.cpu_type +
|
data.cpu_type +
|
||||||
' (rev.' +
|
' (rev.' +
|
||||||
data.cpu_rev +
|
data.cpu_rev +
|
||||||
@@ -352,7 +353,7 @@ const SystemStatusForm: FC = () => {
|
|||||||
open={versionDialogOpen}
|
open={versionDialogOpen}
|
||||||
onClose={() => setVersionDialogOpen(false)}
|
onClose={() => setVersionDialogOpen(false)}
|
||||||
version={data.emsesp_version}
|
version={data.emsesp_version}
|
||||||
platform={data.esp_platform}
|
platform={features.platform}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const UploadFileForm: FC = () => {
|
|||||||
const { send: getSettings, onSuccess: onSuccessGetSettings } = useRequest(EMSESP.getSettings(), {
|
const { send: getSettings, onSuccess: onSuccessGetSettings } = useRequest(EMSESP.getSettings(), {
|
||||||
immediate: false
|
immediate: false
|
||||||
});
|
});
|
||||||
const { send: getCustomizations, onSuccess: onSuccessGetCustomizations } = useRequest(EMSESP.getCustomizations(), {
|
const { send: getCustomizations, onSuccess: onSuccessgetCustomizations } = useRequest(EMSESP.getCustomizations(), {
|
||||||
immediate: false
|
immediate: false
|
||||||
});
|
});
|
||||||
const { send: getEntities, onSuccess: onSuccessGetEntities } = useRequest(EMSESP.getEntities(), {
|
const { send: getEntities, onSuccess: onSuccessGetEntities } = useRequest(EMSESP.getEntities(), {
|
||||||
@@ -28,7 +28,7 @@ const UploadFileForm: FC = () => {
|
|||||||
const { send: getSchedule, onSuccess: onSuccessGetSchedule } = useRequest(EMSESP.getSchedule(), {
|
const { send: getSchedule, onSuccess: onSuccessGetSchedule } = useRequest(EMSESP.getSchedule(), {
|
||||||
immediate: false
|
immediate: false
|
||||||
});
|
});
|
||||||
const { send: getAPI, onSuccess: onGetAPI } = useRequest((data) => EMSESP.API(data), {
|
const { send: getSystemAPI, onSuccess: onSystemAPI } = useRequest((data) => EMSESP.APIcall('system', data), {
|
||||||
immediate: false
|
immediate: false
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ const UploadFileForm: FC = () => {
|
|||||||
onSuccessGetSettings((event) => {
|
onSuccessGetSettings((event) => {
|
||||||
saveFile(event.data, 'settings.json');
|
saveFile(event.data, 'settings.json');
|
||||||
});
|
});
|
||||||
onSuccessGetCustomizations((event) => {
|
onSuccessgetCustomizations((event) => {
|
||||||
saveFile(event.data, 'customizations.json');
|
saveFile(event.data, 'customizations.json');
|
||||||
});
|
});
|
||||||
onSuccessGetEntities((event) => {
|
onSuccessGetEntities((event) => {
|
||||||
@@ -89,8 +89,8 @@ const UploadFileForm: FC = () => {
|
|||||||
onSuccessGetSchedule((event) => {
|
onSuccessGetSchedule((event) => {
|
||||||
saveFile(event.data, 'schedule.json');
|
saveFile(event.data, 'schedule.json');
|
||||||
});
|
});
|
||||||
onGetAPI((event) => {
|
onSystemAPI((event) => {
|
||||||
saveFile(event.data, event.sendArgs[0].device + '_' + event.sendArgs[0].entity + '.txt');
|
saveFile(event.data, event.sendArgs[0].entity + '.txt');
|
||||||
});
|
});
|
||||||
|
|
||||||
const downloadSettings = async () => {
|
const downloadSettings = async () => {
|
||||||
@@ -121,8 +121,8 @@ const UploadFileForm: FC = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const callAPI = async (device: string, entity: string) => {
|
const callSystemAPI = async (entity: string) => {
|
||||||
await getAPI({ device, entity, id: 0 }).catch((error) => {
|
await getSystemAPI({ entity, id: 0 }).catch((error) => {
|
||||||
toast.error(error.message);
|
toast.error(error.message);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -134,7 +134,7 @@ const UploadFileForm: FC = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<Box mb={2} color="warning.main">
|
<Box mb={2} color="warning.main">
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
{LL.UPLOAD_TEXT()}
|
{LL.UPLOAD_TEXT()}.
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
{LL.RESTART_TEXT(1)}.
|
{LL.RESTART_TEXT(1)}.
|
||||||
@@ -156,12 +156,7 @@ const UploadFileForm: FC = () => {
|
|||||||
{LL.HELP_INFORMATION_4()}
|
{LL.HELP_INFORMATION_4()}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Button
|
<Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={() => callSystemAPI('info')}>
|
||||||
startIcon={<DownloadIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
onClick={() => callAPI('system', 'info')}
|
|
||||||
>
|
|
||||||
{LL.SUPPORT_INFORMATION(0)}
|
{LL.SUPPORT_INFORMATION(0)}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@@ -169,7 +164,7 @@ const UploadFileForm: FC = () => {
|
|||||||
startIcon={<DownloadIcon />}
|
startIcon={<DownloadIcon />}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => callAPI('system', 'allvalues')}
|
onClick={() => callSystemAPI('allvalues')}
|
||||||
>
|
>
|
||||||
All Values
|
All Values
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ const de: Translation = {
|
|||||||
THE_LATEST: 'Die neueste',
|
THE_LATEST: 'Die neueste',
|
||||||
OFFICIAL: 'offizielle',
|
OFFICIAL: 'offizielle',
|
||||||
DEVELOPMENT: 'Entwicklungs',
|
DEVELOPMENT: 'Entwicklungs',
|
||||||
RELEASE_IS: 'Release ist',
|
RELEASE_IS: 'release ist', // TODO translate
|
||||||
RELEASE_NOTES: 'Versionshinweise',
|
RELEASE_NOTES: 'Versionshinweise',
|
||||||
EMS_ESP_VER: 'EMS-ESP Version',
|
EMS_ESP_VER: 'EMS-ESP Version',
|
||||||
UPTIME: 'System Betriebszeit',
|
UPTIME: 'System Betriebszeit',
|
||||||
@@ -228,7 +228,7 @@ const de: Translation = {
|
|||||||
BROKER: 'Broker',
|
BROKER: 'Broker',
|
||||||
CLIENT: 'Client',
|
CLIENT: 'Client',
|
||||||
BASE_TOPIC: 'Base',
|
BASE_TOPIC: 'Base',
|
||||||
OPTIONAL: 'Optional',
|
OPTIONAL: 'Optional', // TODO translate
|
||||||
FORMATTING: 'Formattierung',
|
FORMATTING: 'Formattierung',
|
||||||
MQTT_FORMAT: 'Topic/Payload Format',
|
MQTT_FORMAT: 'Topic/Payload Format',
|
||||||
MQTT_NEST_1: 'Eingebettet in einem Gesamttopic',
|
MQTT_NEST_1: 'Eingebettet in einem Gesamttopic',
|
||||||
@@ -307,7 +307,7 @@ const de: Translation = {
|
|||||||
LEAVE: 'Verlassen',
|
LEAVE: 'Verlassen',
|
||||||
SCHEDULER: 'Planer',
|
SCHEDULER: 'Planer',
|
||||||
SCHEDULER_HELP_1: 'Fügen Sie eigene, geplante Befehle zur Automatisierung hinzu. Vergeben Sie einen Entitätsnamen um die Aktivierung über API/Mqtt zu steuern',
|
SCHEDULER_HELP_1: 'Fügen Sie eigene, geplante Befehle zur Automatisierung hinzu. Vergeben Sie einen Entitätsnamen um die Aktivierung über API/Mqtt zu steuern',
|
||||||
SCHEDULER_HELP_2: '00:00 aktiviert einmalige Ausführung am Start',
|
SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate
|
||||||
SCHEDULE: 'Zeitplan',
|
SCHEDULE: 'Zeitplan',
|
||||||
TIME: 'Zeit',
|
TIME: 'Zeit',
|
||||||
TIMER: 'Timer',
|
TIMER: 'Timer',
|
||||||
@@ -316,7 +316,7 @@ const de: Translation = {
|
|||||||
SCHEDULE_TIMER_2: 'jede Minute',
|
SCHEDULE_TIMER_2: 'jede Minute',
|
||||||
SCHEDULE_TIMER_3: 'jede Stunde',
|
SCHEDULE_TIMER_3: 'jede Stunde',
|
||||||
CUSTOM_ENTITIES: 'Individuelle Entitäten',
|
CUSTOM_ENTITIES: 'Individuelle Entitäten',
|
||||||
ENTITIES_HELP_1: 'Definition eigener EMS-Werte oder dynamischer Variablen',
|
ENTITIES_HELP_1: 'Abfrage von Werten auf dem EMS-Bus',
|
||||||
ENTITIES_UPDATED: 'Entitäten gespeichert',
|
ENTITIES_UPDATED: 'Entitäten gespeichert',
|
||||||
WRITEABLE: 'Schreibbar',
|
WRITEABLE: 'Schreibbar',
|
||||||
SHOWING: 'Anzeigen von',
|
SHOWING: 'Anzeigen von',
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ const en: Translation = {
|
|||||||
FREQ: 'Frequency',
|
FREQ: 'Frequency',
|
||||||
DUTY_CYCLE: 'Duty Cycle',
|
DUTY_CYCLE: 'Duty Cycle',
|
||||||
UNIT: 'UoM',
|
UNIT: 'UoM',
|
||||||
STARTVALUE: 'Start Value',
|
STARTVALUE: 'Start value',
|
||||||
WARN_GPIO: 'Warning: be careful when assigning a GPIO!',
|
WARN_GPIO: 'Warning: be careful when assigning a GPIO!',
|
||||||
EDIT: 'Edit',
|
EDIT: 'Edit',
|
||||||
SENSOR: 'Sensor',
|
SENSOR: 'Sensor',
|
||||||
@@ -317,7 +317,7 @@ const en: Translation = {
|
|||||||
SCHEDULE_TIMER_2: 'every minute',
|
SCHEDULE_TIMER_2: 'every minute',
|
||||||
SCHEDULE_TIMER_3: 'every hour',
|
SCHEDULE_TIMER_3: 'every hour',
|
||||||
CUSTOM_ENTITIES: 'Custom Entities',
|
CUSTOM_ENTITIES: 'Custom Entities',
|
||||||
ENTITIES_HELP_1: 'Define custom EMS entities or dynamic user variables',
|
ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus',
|
||||||
ENTITIES_UPDATED: 'Entities Updated',
|
ENTITIES_UPDATED: 'Entities Updated',
|
||||||
WRITEABLE: 'Writeable',
|
WRITEABLE: 'Writeable',
|
||||||
SHOWING: 'Showing',
|
SHOWING: 'Showing',
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ const it: Translation = {
|
|||||||
SCHEDULE_TIMER_2: 'Ogni minuto',
|
SCHEDULE_TIMER_2: 'Ogni minuto',
|
||||||
SCHEDULE_TIMER_3: 'Ogni ora',
|
SCHEDULE_TIMER_3: 'Ogni ora',
|
||||||
CUSTOM_ENTITIES: 'Entità personalizzate',
|
CUSTOM_ENTITIES: 'Entità personalizzate',
|
||||||
ENTITIES_HELP_1: 'Recupera entità personalizzate dal BUS EMS', // TODO translate
|
ENTITIES_HELP_1: 'Recupera entità personalizzate dal BUS EMS',
|
||||||
ENTITIES_UPDATED: 'Entità aggiornate',
|
ENTITIES_UPDATED: 'Entità aggiornate',
|
||||||
WRITEABLE: 'Scrivibile',
|
WRITEABLE: 'Scrivibile',
|
||||||
SHOWING: 'Visualizza',
|
SHOWING: 'Visualizza',
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ const nl: Translation = {
|
|||||||
SCHEDULE_TIMER_2: 'elke minuut',
|
SCHEDULE_TIMER_2: 'elke minuut',
|
||||||
SCHEDULE_TIMER_3: 'elke huur',
|
SCHEDULE_TIMER_3: 'elke huur',
|
||||||
CUSTOM_ENTITIES: 'Aangepaste Entiteiten',
|
CUSTOM_ENTITIES: 'Aangepaste Entiteiten',
|
||||||
ENTITIES_HELP_1: 'Aangepaste entiteiten ophalen uit de EMS-bus', // TODO translate
|
ENTITIES_HELP_1: 'Aangepaste entiteiten ophalen uit de EMS-bus',
|
||||||
ENTITIES_UPDATED: 'Entiteiten bijgewerkt',
|
ENTITIES_UPDATED: 'Entiteiten bijgewerkt',
|
||||||
WRITEABLE: 'Beschrijfbare',
|
WRITEABLE: 'Beschrijfbare',
|
||||||
SHOWING: 'Tonen',
|
SHOWING: 'Tonen',
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ const pl: BaseTranslation = {
|
|||||||
SCHEDULE_TIMER_2: 'co minutę',
|
SCHEDULE_TIMER_2: 'co minutę',
|
||||||
SCHEDULE_TIMER_3: 'co godzinę',
|
SCHEDULE_TIMER_3: 'co godzinę',
|
||||||
CUSTOM_ENTITIES: '{{N|n|}}iestandardowe{{|j|}} encj{{e|i|}}',
|
CUSTOM_ENTITIES: '{{N|n|}}iestandardowe{{|j|}} encj{{e|i|}}',
|
||||||
ENTITIES_HELP_1: 'Zdefiniuj niestandardowe encje dla magistrali EMS.', // TODO translate
|
ENTITIES_HELP_1: 'Zdefiniuj niestandardowe encje dla magistrali EMS.',
|
||||||
ENTITIES_UPDATED: 'Niestandardowe encje zostały uaktualnione.',
|
ENTITIES_UPDATED: 'Niestandardowe encje zostały uaktualnione.',
|
||||||
WRITEABLE: 'Zapisywalna',
|
WRITEABLE: 'Zapisywalna',
|
||||||
SHOWING: 'Wyświetlane',
|
SHOWING: 'Wyświetlane',
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ const sk: Translation = {
|
|||||||
SCHEDULE_TIMER_2: 'každú minútu',
|
SCHEDULE_TIMER_2: 'každú minútu',
|
||||||
SCHEDULE_TIMER_3: 'každú hodinu',
|
SCHEDULE_TIMER_3: 'každú hodinu',
|
||||||
CUSTOM_ENTITIES: 'Vlastné entity',
|
CUSTOM_ENTITIES: 'Vlastné entity',
|
||||||
ENTITIES_HELP_1: 'Získavanie vlastných entít zo zbernice EMS', // TODO translate
|
ENTITIES_HELP_1: 'Získavanie vlastných entít zo zbernice EMS',
|
||||||
ENTITIES_UPDATED: 'Aktualizované entity',
|
ENTITIES_UPDATED: 'Aktualizované entity',
|
||||||
WRITEABLE: 'Zapísateľný',
|
WRITEABLE: 'Zapísateľný',
|
||||||
SHOWING: 'Zobrazenie',
|
SHOWING: 'Zobrazenie',
|
||||||
|
|||||||
@@ -94,14 +94,8 @@ const DashboardDevices: FC = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const leftOffset = () => {
|
const leftOffset = () => {
|
||||||
const devicesWindow = document.getElementById('devices-window');
|
const left = document.getElementById('devices-window')?.getBoundingClientRect().left;
|
||||||
if (!devicesWindow) {
|
const right = document.getElementById('devices-window')?.getBoundingClientRect().right;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const clientRect = devicesWindow.getBoundingClientRect();
|
|
||||||
const left = clientRect.left;
|
|
||||||
const right = clientRect.right;
|
|
||||||
|
|
||||||
if (!left || !right) {
|
if (!left || !right) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -422,9 +416,9 @@ const DashboardDevices: FC = () => {
|
|||||||
const renderCoreData = () => (
|
const renderCoreData = () => (
|
||||||
<IconContext.Provider value={{ color: 'lightblue', size: '24', style: { verticalAlign: 'middle' } }}>
|
<IconContext.Provider value={{ color: 'lightblue', size: '24', style: { verticalAlign: 'middle' } }}>
|
||||||
{!coreData.connected && <MessageBox my={2} level="error" message={LL.EMS_BUS_WARNING()} />}
|
{!coreData.connected && <MessageBox my={2} level="error" message={LL.EMS_BUS_WARNING()} />}
|
||||||
{/* {coreData.connected && coreData.devices.length === 0 && (
|
{coreData.connected && coreData.devices.length === 0 && (
|
||||||
<MessageBox my={2} level="warning" message={LL.EMS_BUS_SCANNING()} />
|
<MessageBox my={2} level="warning" message={LL.EMS_BUS_SCANNING()} />
|
||||||
)} */}
|
)}
|
||||||
|
|
||||||
{coreData.connected && (
|
{coreData.connected && (
|
||||||
<Table data={{ nodes: coreData.devices }} select={device_select} theme={device_theme} layout={{ custom: true }}>
|
<Table data={{ nodes: coreData.devices }} select={device_select} theme={device_theme} layout={{ custom: true }}>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import type { ValidateFieldsError } from 'async-validator';
|
|||||||
import { dialogStyle } from 'CustomTheme';
|
import { dialogStyle } from 'CustomTheme';
|
||||||
import { ValidatedTextField } from 'components';
|
import { ValidatedTextField } from 'components';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import { updateValue, numberValue } from 'utils';
|
import { updateValue } from 'utils';
|
||||||
|
|
||||||
import { validate } from 'validators';
|
import { validate } from 'validators';
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ const DashboardDevicesDialog = ({
|
|||||||
return (
|
return (
|
||||||
<Dialog sx={dialogStyle} open={open} onClose={close}>
|
<Dialog sx={dialogStyle} open={open} onClose={close}>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
{selectedItem.v === '' && selectedItem.c ? LL.RUN_COMMAND() : writeable ? LL.CHANGE_VALUE() : LL.VALUE(1)}
|
{selectedItem.v === '' && selectedItem.c ? LL.RUN_COMMAND() : writeable ? LL.CHANGE_VALUE() : LL.VALUE(0)}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}>
|
<Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}>
|
||||||
@@ -133,7 +133,7 @@ const DashboardDevicesDialog = ({
|
|||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="v"
|
name="v"
|
||||||
label={LL.VALUE(1)}
|
label={LL.VALUE(1)}
|
||||||
value={numberValue(Math.round(editItem.v * 10) / 10)}
|
value={Math.round(editItem.v * 10) / 10}
|
||||||
autoFocus
|
autoFocus
|
||||||
disabled={!writeable}
|
disabled={!writeable}
|
||||||
type="number"
|
type="number"
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ const DashboardSensors: FC = () => {
|
|||||||
setSelectedAnalogSensor({
|
setSelectedAnalogSensor({
|
||||||
id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100),
|
id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100),
|
||||||
n: '',
|
n: '',
|
||||||
g: 21, // default GPIO 21 which is safe for all platforms
|
g: 40,
|
||||||
u: 0,
|
u: 0,
|
||||||
v: 0,
|
v: 0,
|
||||||
o: 0,
|
o: 0,
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ const DashboardSensorsAnalogDialog = ({
|
|||||||
<Grid item xs={4}>
|
<Grid item xs={4}>
|
||||||
<TextField
|
<TextField
|
||||||
name="o"
|
name="o"
|
||||||
label={LL.VALUE(1)}
|
label={LL.VALUE(0)}
|
||||||
value={numberValue(editItem.o)}
|
value={numberValue(editItem.o)}
|
||||||
fullWidth
|
fullWidth
|
||||||
type="number"
|
type="number"
|
||||||
@@ -197,7 +197,7 @@ const DashboardSensorsAnalogDialog = ({
|
|||||||
<Grid item xs={4}>
|
<Grid item xs={4}>
|
||||||
<TextField
|
<TextField
|
||||||
name="o"
|
name="o"
|
||||||
label={LL.VALUE(1)}
|
label={LL.VALUE(0)}
|
||||||
value={numberValue(editItem.o)}
|
value={numberValue(editItem.o)}
|
||||||
fullWidth
|
fullWidth
|
||||||
select
|
select
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const Help: FC = () => {
|
|||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
useLayoutTitle(LL.HELP_OF(''));
|
useLayoutTitle(LL.HELP_OF(''));
|
||||||
|
|
||||||
const { send: getAPI, onSuccess: onGetAPI } = useRequest((data) => EMSESP.API(data), {
|
const { send: getSystemAPI, onSuccess: onGetAPI } = useRequest((data) => EMSESP.APIcall('system', data), {
|
||||||
immediate: false
|
immediate: false
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -26,14 +26,14 @@ const Help: FC = () => {
|
|||||||
type: 'text/plain'
|
type: 'text/plain'
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
anchor.download = 'emsesp_' + event.sendArgs[0].device + '_' + event.sendArgs[0].entity + '.txt';
|
anchor.download = 'emsesp_' + event.sendArgs[0].entity + '.txt';
|
||||||
anchor.click();
|
anchor.click();
|
||||||
URL.revokeObjectURL(anchor.href);
|
URL.revokeObjectURL(anchor.href);
|
||||||
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
||||||
});
|
});
|
||||||
|
|
||||||
const callAPI = async (device: string, entity: string) => {
|
const callSystemAPI = async (entity: string) => {
|
||||||
await getAPI({ device, entity, id: 0 }).catch((error) => {
|
await getSystemAPI({ entity, id: 0 }).catch((error) => {
|
||||||
toast.error(error.message);
|
toast.error(error.message);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -89,7 +89,7 @@ const Help: FC = () => {
|
|||||||
{LL.HELP_INFORMATION_4()}
|
{LL.HELP_INFORMATION_4()}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={() => callAPI('system', 'info')}>
|
<Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={() => callSystemAPI('info')}>
|
||||||
{LL.SUPPORT_INFORMATION(0)}
|
{LL.SUPPORT_INFORMATION(0)}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@@ -97,7 +97,7 @@ const Help: FC = () => {
|
|||||||
startIcon={<DownloadIcon />}
|
startIcon={<DownloadIcon />}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => callAPI('system', 'allvalues')}
|
onClick={() => callSystemAPI('allvalues')}
|
||||||
>
|
>
|
||||||
All Values
|
All Values
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { Tab } from '@mui/material';
|
|||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||||
|
|
||||||
import SettingsApplication from './SettingsApplication';
|
import SettingsApplication from './SettingsApplication';
|
||||||
import SettingsCustomEntities from './SettingsCustomEntities';
|
|
||||||
import SettingsCustomization from './SettingsCustomization';
|
import SettingsCustomization from './SettingsCustomization';
|
||||||
|
import SettingsEntities from './SettingsEntities';
|
||||||
import SettingsScheduler from './SettingsScheduler';
|
import SettingsScheduler from './SettingsScheduler';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { RouterTabs, useRouterTab, useLayoutTitle } from 'components';
|
import { RouterTabs, useRouterTab, useLayoutTitle } from 'components';
|
||||||
@@ -27,7 +27,7 @@ const Settings: FC = () => {
|
|||||||
<Route path="application" element={<SettingsApplication />} />
|
<Route path="application" element={<SettingsApplication />} />
|
||||||
<Route path="customization" element={<SettingsCustomization />} />
|
<Route path="customization" element={<SettingsCustomization />} />
|
||||||
<Route path="scheduler" element={<SettingsScheduler />} />
|
<Route path="scheduler" element={<SettingsScheduler />} />
|
||||||
<Route path="customentities" element={<SettingsCustomEntities />} />
|
<Route path="customentities" element={<SettingsEntities />} />
|
||||||
<Route path="*" element={<Navigate replace to="/settings/application" />} />
|
<Route path="*" element={<Navigate replace to="/settings/application" />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,284 +0,0 @@
|
|||||||
import AddIcon from '@mui/icons-material/Add';
|
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
|
||||||
import DoneIcon from '@mui/icons-material/Done';
|
|
||||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
Checkbox,
|
|
||||||
Dialog,
|
|
||||||
DialogActions,
|
|
||||||
DialogContent,
|
|
||||||
DialogTitle,
|
|
||||||
Grid,
|
|
||||||
InputAdornment,
|
|
||||||
MenuItem,
|
|
||||||
TextField
|
|
||||||
} from '@mui/material';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
import { DeviceValueUOM_s, DeviceValueType } from './types';
|
|
||||||
import type { EntityItem } from './types';
|
|
||||||
import type Schema from 'async-validator';
|
|
||||||
import type { ValidateFieldsError } from 'async-validator';
|
|
||||||
|
|
||||||
import { dialogStyle } from 'CustomTheme';
|
|
||||||
import { BlockFormControlLabel, ValidatedTextField } from 'components';
|
|
||||||
|
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
|
||||||
|
|
||||||
import { numberValue, updateValue } from 'utils';
|
|
||||||
import { validate } from 'validators';
|
|
||||||
|
|
||||||
type SettingsCustomEntitiesDialogProps = {
|
|
||||||
open: boolean;
|
|
||||||
creating: boolean;
|
|
||||||
onClose: () => void;
|
|
||||||
onSave: (ei: EntityItem) => void;
|
|
||||||
selectedItem: EntityItem;
|
|
||||||
validator: Schema;
|
|
||||||
};
|
|
||||||
|
|
||||||
const SettingsCustomEntitiesDialog = ({
|
|
||||||
open,
|
|
||||||
creating,
|
|
||||||
onClose,
|
|
||||||
onSave,
|
|
||||||
selectedItem,
|
|
||||||
validator
|
|
||||||
}: SettingsCustomEntitiesDialogProps) => {
|
|
||||||
const { LL } = useI18nContext();
|
|
||||||
const [editItem, setEditItem] = useState<EntityItem>(selectedItem);
|
|
||||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
|
||||||
const updateFormValue = updateValue(setEditItem);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (open) {
|
|
||||||
setFieldErrors(undefined);
|
|
||||||
setEditItem(selectedItem);
|
|
||||||
// convert to hex strings straight away
|
|
||||||
setEditItem({
|
|
||||||
...selectedItem,
|
|
||||||
device_id: selectedItem.device_id.toString(16).toUpperCase(),
|
|
||||||
type_id: selectedItem.type_id.toString(16).toUpperCase()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [open, selectedItem]);
|
|
||||||
|
|
||||||
const close = () => {
|
|
||||||
onClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
const save = async () => {
|
|
||||||
try {
|
|
||||||
setFieldErrors(undefined);
|
|
||||||
await validate(validator, editItem);
|
|
||||||
if (typeof editItem.device_id === 'string') {
|
|
||||||
editItem.device_id = parseInt(editItem.device_id, 16);
|
|
||||||
}
|
|
||||||
if (typeof editItem.type_id === 'string') {
|
|
||||||
editItem.type_id = parseInt(editItem.type_id, 16);
|
|
||||||
}
|
|
||||||
onSave(editItem);
|
|
||||||
} catch (errors: any) {
|
|
||||||
setFieldErrors(errors);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const remove = () => {
|
|
||||||
editItem.deleted = true;
|
|
||||||
onSave(editItem);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog sx={dialogStyle} open={open} onClose={close}>
|
|
||||||
<DialogTitle>
|
|
||||||
{creating ? LL.ADD(1) + ' ' + LL.NEW(1) : LL.EDIT()} {LL.ENTITY()}
|
|
||||||
</DialogTitle>
|
|
||||||
<DialogContent dividers>
|
|
||||||
<Box display="flex" flexWrap="wrap" mb={1}>
|
|
||||||
<Box flexWrap="nowrap" whiteSpace="nowrap" />
|
|
||||||
</Box>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="name"
|
|
||||||
label={LL.NAME(0)}
|
|
||||||
value={editItem.name}
|
|
||||||
margin="normal"
|
|
||||||
fullWidth
|
|
||||||
onChange={updateFormValue}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextField
|
|
||||||
name="ram"
|
|
||||||
label={LL.VALUE(1) + ' ' + LL.TYPE(1)}
|
|
||||||
value={editItem.ram}
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
fullWidth
|
|
||||||
select
|
|
||||||
>
|
|
||||||
<MenuItem value={0}>EMS-{LL.VALUE(1)}</MenuItem>
|
|
||||||
<MenuItem value={1}>RAM-{LL.VALUE(1)}</MenuItem>
|
|
||||||
</TextField>
|
|
||||||
</Grid>
|
|
||||||
{editItem.ram === 1 && (
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextField
|
|
||||||
name="value"
|
|
||||||
label={LL.DEFAULT(0) + ' ' + LL.VALUE(1)}
|
|
||||||
value={editItem.value}
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateFormValue}
|
|
||||||
fullWidth
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
{editItem.ram === 0 && (
|
|
||||||
<>
|
|
||||||
<Grid item xs={4} mt={3}>
|
|
||||||
<BlockFormControlLabel
|
|
||||||
control={<Checkbox checked={editItem.writeable} onChange={updateFormValue} name="writeable" />}
|
|
||||||
label={LL.WRITEABLE()}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="device_id"
|
|
||||||
label={LL.ID_OF(LL.DEVICE())}
|
|
||||||
margin="normal"
|
|
||||||
type="string"
|
|
||||||
fullWidth
|
|
||||||
value={editItem.device_id as string}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
inputProps={{ style: { textTransform: 'uppercase' } }}
|
|
||||||
InputProps={{ startAdornment: <InputAdornment position="start">0x</InputAdornment> }}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="type_id"
|
|
||||||
label={LL.ID_OF(LL.TYPE(1))}
|
|
||||||
margin="normal"
|
|
||||||
fullWidth
|
|
||||||
value={editItem.type_id}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
inputProps={{ style: { textTransform: 'uppercase' } }}
|
|
||||||
InputProps={{ startAdornment: <InputAdornment position="start">0x</InputAdornment> }}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="offset"
|
|
||||||
label={LL.OFFSET()}
|
|
||||||
margin="normal"
|
|
||||||
fullWidth
|
|
||||||
type="number"
|
|
||||||
value={editItem.offset}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextField
|
|
||||||
name="value_type"
|
|
||||||
label={LL.VALUE(1) + ' ' + LL.TYPE(1)}
|
|
||||||
value={editItem.value_type}
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
fullWidth
|
|
||||||
select
|
|
||||||
>
|
|
||||||
<MenuItem value={DeviceValueType.BOOL}>BOOL</MenuItem>
|
|
||||||
<MenuItem value={DeviceValueType.INT}>INT</MenuItem>
|
|
||||||
<MenuItem value={DeviceValueType.UINT}>UINT</MenuItem>
|
|
||||||
<MenuItem value={DeviceValueType.SHORT}>SHORT</MenuItem>
|
|
||||||
<MenuItem value={DeviceValueType.USHORT}>USHORT</MenuItem>
|
|
||||||
<MenuItem value={DeviceValueType.ULONG}>ULONG</MenuItem>
|
|
||||||
<MenuItem value={DeviceValueType.TIME}>TIME</MenuItem>
|
|
||||||
<MenuItem value={DeviceValueType.STRING}>RAW</MenuItem>
|
|
||||||
</TextField>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
{editItem.value_type !== DeviceValueType.BOOL && editItem.value_type !== DeviceValueType.STRING && (
|
|
||||||
<>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextField
|
|
||||||
name="factor"
|
|
||||||
label={LL.FACTOR()}
|
|
||||||
value={numberValue(editItem.factor)}
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateFormValue}
|
|
||||||
fullWidth
|
|
||||||
margin="normal"
|
|
||||||
type="number"
|
|
||||||
inputProps={{ step: '0.001' }}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextField
|
|
||||||
name="uom"
|
|
||||||
label={LL.UNIT()}
|
|
||||||
value={editItem.uom}
|
|
||||||
margin="normal"
|
|
||||||
fullWidth
|
|
||||||
onChange={updateFormValue}
|
|
||||||
select
|
|
||||||
>
|
|
||||||
{DeviceValueUOM_s.map((val, i) => (
|
|
||||||
<MenuItem key={i} value={i}>
|
|
||||||
{val}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</TextField>
|
|
||||||
</Grid>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{editItem.value_type === DeviceValueType.STRING && editItem.device_id !== '0' && (
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<TextField
|
|
||||||
name="factor"
|
|
||||||
label="Bytes"
|
|
||||||
value={editItem.factor}
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateFormValue}
|
|
||||||
fullWidth
|
|
||||||
margin="normal"
|
|
||||||
type="number"
|
|
||||||
inputProps={{ min: '1', max: '27', step: '1' }}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
</DialogContent>
|
|
||||||
|
|
||||||
<DialogActions>
|
|
||||||
{!creating && (
|
|
||||||
<Box flexGrow={1}>
|
|
||||||
<Button startIcon={<RemoveIcon />} variant="outlined" color="warning" onClick={remove}>
|
|
||||||
{LL.REMOVE()}
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
<Button startIcon={<CancelIcon />} variant="outlined" onClick={close} color="secondary">
|
|
||||||
{LL.CANCEL()}
|
|
||||||
</Button>
|
|
||||||
<Button startIcon={creating ? <AddIcon /> : <DoneIcon />} variant="outlined" onClick={save} color="primary">
|
|
||||||
{creating ? LL.ADD(0) : LL.UPDATE()}
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SettingsCustomEntitiesDialog;
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
|
|
||||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import { Button, Typography, Box } from '@mui/material';
|
import { Button, Typography, Box } from '@mui/material';
|
||||||
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
|
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
|
||||||
@@ -13,7 +11,7 @@ import { useBlocker } from 'react-router-dom';
|
|||||||
|
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import SettingsCustomEntitiesDialog from './SettingsCustomEntitiesDialog';
|
import SettingsEntitiesDialog from './SettingsEntitiesDialog';
|
||||||
import * as EMSESP from './api';
|
import * as EMSESP from './api';
|
||||||
import { DeviceValueTypeNames, DeviceValueUOM_s } from './types';
|
import { DeviceValueTypeNames, DeviceValueUOM_s } from './types';
|
||||||
import { entityItemValidation } from './validators';
|
import { entityItemValidation } from './validators';
|
||||||
@@ -23,7 +21,7 @@ import { ButtonRow, FormLoader, SectionContent, BlockNavigation } from 'componen
|
|||||||
|
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
const SettingsCustomEntities: FC = () => {
|
const SettingsEntities: FC = () => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
const [numChanges, setNumChanges] = useState<number>(0);
|
const [numChanges, setNumChanges] = useState<number>(0);
|
||||||
const blocker = useBlocker(numChanges !== 0);
|
const blocker = useBlocker(numChanges !== 0);
|
||||||
@@ -45,7 +43,6 @@ const SettingsCustomEntities: FC = () => {
|
|||||||
function hasEntityChanged(ei: EntityItem) {
|
function hasEntityChanged(ei: EntityItem) {
|
||||||
return (
|
return (
|
||||||
ei.id !== ei.o_id ||
|
ei.id !== ei.o_id ||
|
||||||
ei.ram !== ei.o_ram ||
|
|
||||||
(ei?.name || '') !== (ei?.o_name || '') ||
|
(ei?.name || '') !== (ei?.o_name || '') ||
|
||||||
ei.device_id !== ei.o_device_id ||
|
ei.device_id !== ei.o_device_id ||
|
||||||
ei.type_id !== ei.o_type_id ||
|
ei.type_id !== ei.o_type_id ||
|
||||||
@@ -54,8 +51,7 @@ const SettingsCustomEntities: FC = () => {
|
|||||||
ei.factor !== ei.o_factor ||
|
ei.factor !== ei.o_factor ||
|
||||||
ei.value_type !== ei.o_value_type ||
|
ei.value_type !== ei.o_value_type ||
|
||||||
ei.writeable !== ei.o_writeable ||
|
ei.writeable !== ei.o_writeable ||
|
||||||
ei.deleted !== ei.o_deleted ||
|
ei.deleted !== ei.o_deleted
|
||||||
(ei.value || '') !== (ei.o_value || '')
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +118,6 @@ const SettingsCustomEntities: FC = () => {
|
|||||||
.filter((ei) => !ei.deleted)
|
.filter((ei) => !ei.deleted)
|
||||||
.map((condensed_ei) => ({
|
.map((condensed_ei) => ({
|
||||||
id: condensed_ei.id,
|
id: condensed_ei.id,
|
||||||
ram: condensed_ei.ram,
|
|
||||||
name: condensed_ei.name,
|
name: condensed_ei.name,
|
||||||
device_id: condensed_ei.device_id,
|
device_id: condensed_ei.device_id,
|
||||||
type_id: condensed_ei.type_id,
|
type_id: condensed_ei.type_id,
|
||||||
@@ -130,8 +125,7 @@ const SettingsCustomEntities: FC = () => {
|
|||||||
factor: condensed_ei.factor,
|
factor: condensed_ei.factor,
|
||||||
uom: condensed_ei.uom,
|
uom: condensed_ei.uom,
|
||||||
writeable: condensed_ei.writeable,
|
writeable: condensed_ei.writeable,
|
||||||
value_type: condensed_ei.value_type,
|
value_type: condensed_ei.value_type
|
||||||
value: condensed_ei.value
|
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -179,16 +173,14 @@ const SettingsCustomEntities: FC = () => {
|
|||||||
setSelectedEntityItem({
|
setSelectedEntityItem({
|
||||||
id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100),
|
id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100),
|
||||||
name: '',
|
name: '',
|
||||||
ram: 0,
|
device_id: '',
|
||||||
device_id: '0',
|
type_id: '',
|
||||||
type_id: '0',
|
|
||||||
offset: 0,
|
offset: 0,
|
||||||
factor: 1,
|
factor: 1,
|
||||||
uom: 0,
|
uom: 0,
|
||||||
value_type: 0,
|
value_type: 0,
|
||||||
writeable: false,
|
writeable: false,
|
||||||
deleted: false,
|
deleted: false
|
||||||
value: ''
|
|
||||||
});
|
});
|
||||||
setDialogOpen(true);
|
setDialogOpen(true);
|
||||||
};
|
};
|
||||||
@@ -220,21 +212,18 @@ const SettingsCustomEntities: FC = () => {
|
|||||||
<HeaderCell stiff>{LL.ID_OF(LL.DEVICE())}</HeaderCell>
|
<HeaderCell stiff>{LL.ID_OF(LL.DEVICE())}</HeaderCell>
|
||||||
<HeaderCell stiff>{LL.ID_OF(LL.TYPE(1))}</HeaderCell>
|
<HeaderCell stiff>{LL.ID_OF(LL.TYPE(1))}</HeaderCell>
|
||||||
<HeaderCell stiff>{LL.OFFSET()}</HeaderCell>
|
<HeaderCell stiff>{LL.OFFSET()}</HeaderCell>
|
||||||
<HeaderCell stiff>{LL.TYPE(1)}</HeaderCell>
|
<HeaderCell stiff>{LL.VALUE(1) + ' ' + LL.TYPE(1)}</HeaderCell>
|
||||||
<HeaderCell stiff>{LL.VALUE(1)}</HeaderCell>
|
<HeaderCell stiff>{LL.VALUE(1)}</HeaderCell>
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
{tableList.map((ei: EntityItem) => (
|
{tableList.map((ei: EntityItem) => (
|
||||||
<Row key={ei.name} item={ei} onClick={() => editEntityItem(ei)}>
|
<Row key={ei.name} item={ei} onClick={() => editEntityItem(ei)}>
|
||||||
<Cell>
|
<Cell>{ei.name}</Cell>
|
||||||
{ei.name}
|
<Cell>{showHex(ei.device_id as number, 2)}</Cell>
|
||||||
{ei.writeable && <EditOutlinedIcon color="primary" sx={{ fontSize: 12 }} />}
|
<Cell>{showHex(ei.type_id as number, 3)}</Cell>
|
||||||
</Cell>
|
<Cell>{ei.offset}</Cell>
|
||||||
<Cell>{ei.ram === 1 ? '' : showHex(ei.device_id as number, 2)}</Cell>
|
<Cell>{DeviceValueTypeNames[ei.value_type]}</Cell>
|
||||||
<Cell>{ei.ram === 1 ? '' : showHex(ei.type_id as number, 3)}</Cell>
|
|
||||||
<Cell>{ei.ram === 1 ? '' : ei.offset}</Cell>
|
|
||||||
<Cell>{ei.ram === 1 ? 'RAM' : DeviceValueTypeNames[ei.value_type]}</Cell>
|
|
||||||
<Cell>{formatValue(ei.value, ei.uom)}</Cell>
|
<Cell>{formatValue(ei.value, ei.uom)}</Cell>
|
||||||
</Row>
|
</Row>
|
||||||
))}
|
))}
|
||||||
@@ -255,7 +244,7 @@ const SettingsCustomEntities: FC = () => {
|
|||||||
{renderEntity()}
|
{renderEntity()}
|
||||||
|
|
||||||
{selectedEntityItem && (
|
{selectedEntityItem && (
|
||||||
<SettingsCustomEntitiesDialog
|
<SettingsEntitiesDialog
|
||||||
open={dialogOpen}
|
open={dialogOpen}
|
||||||
creating={creating}
|
creating={creating}
|
||||||
onClose={onDialogClose}
|
onClose={onDialogClose}
|
||||||
@@ -285,10 +274,7 @@ const SettingsCustomEntities: FC = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
<Box flexWrap="nowrap" whiteSpace="nowrap">
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={fetchEntities}>
|
<Button startIcon={<AddIcon />} variant="outlined" color="secondary" onClick={addEntityItem}>
|
||||||
{LL.REFRESH()}
|
|
||||||
</Button>
|
|
||||||
<Button startIcon={<AddIcon />} variant="outlined" color="primary" onClick={addEntityItem}>
|
|
||||||
{LL.ADD(0)}
|
{LL.ADD(0)}
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
@@ -298,4 +284,4 @@ const SettingsCustomEntities: FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SettingsCustomEntities;
|
export default SettingsEntities;
|
||||||
252
interface/src/project/SettingsEntitiesDialog.tsx
Normal file
252
interface/src/project/SettingsEntitiesDialog.tsx
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import DoneIcon from '@mui/icons-material/Done';
|
||||||
|
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
Grid,
|
||||||
|
InputAdornment,
|
||||||
|
MenuItem,
|
||||||
|
TextField
|
||||||
|
} from '@mui/material';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { DeviceValueUOM_s, DeviceValueType } from './types';
|
||||||
|
import type { EntityItem } from './types';
|
||||||
|
import type Schema from 'async-validator';
|
||||||
|
import type { ValidateFieldsError } from 'async-validator';
|
||||||
|
|
||||||
|
import { dialogStyle } from 'CustomTheme';
|
||||||
|
import { BlockFormControlLabel, ValidatedTextField } from 'components';
|
||||||
|
|
||||||
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
|
import { updateValue } from 'utils';
|
||||||
|
import { validate } from 'validators';
|
||||||
|
|
||||||
|
type SettingsEntitiesDialogProps = {
|
||||||
|
open: boolean;
|
||||||
|
creating: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onSave: (ei: EntityItem) => void;
|
||||||
|
selectedItem: EntityItem;
|
||||||
|
validator: Schema;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SettingsEntitiesDialog = ({
|
||||||
|
open,
|
||||||
|
creating,
|
||||||
|
onClose,
|
||||||
|
onSave,
|
||||||
|
selectedItem,
|
||||||
|
validator
|
||||||
|
}: SettingsEntitiesDialogProps) => {
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
const [editItem, setEditItem] = useState<EntityItem>(selectedItem);
|
||||||
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
|
const updateFormValue = updateValue(setEditItem);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
setFieldErrors(undefined);
|
||||||
|
setEditItem(selectedItem);
|
||||||
|
// convert to hex strings straight away
|
||||||
|
setEditItem({
|
||||||
|
...selectedItem,
|
||||||
|
device_id: selectedItem.device_id.toString(16).toUpperCase(),
|
||||||
|
type_id: selectedItem.type_id.toString(16).toUpperCase()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [open, selectedItem]);
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const save = async () => {
|
||||||
|
try {
|
||||||
|
setFieldErrors(undefined);
|
||||||
|
await validate(validator, editItem);
|
||||||
|
if (typeof editItem.device_id === 'string') {
|
||||||
|
editItem.device_id = parseInt(editItem.device_id, 16);
|
||||||
|
}
|
||||||
|
if (typeof editItem.type_id === 'string') {
|
||||||
|
editItem.type_id = parseInt(editItem.type_id, 16);
|
||||||
|
}
|
||||||
|
onSave(editItem);
|
||||||
|
} catch (errors: any) {
|
||||||
|
setFieldErrors(errors);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remove = () => {
|
||||||
|
editItem.deleted = true;
|
||||||
|
onSave(editItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog sx={dialogStyle} open={open} onClose={close}>
|
||||||
|
<DialogTitle>
|
||||||
|
{creating ? LL.ADD(1) + ' ' + LL.NEW(1) : LL.EDIT()} {LL.ENTITY()}
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent dividers>
|
||||||
|
<Box display="flex" flexWrap="wrap" mb={1}>
|
||||||
|
<Box flexWrap="nowrap" whiteSpace="nowrap" />
|
||||||
|
</Box>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={8}>
|
||||||
|
<ValidatedTextField
|
||||||
|
fieldErrors={fieldErrors}
|
||||||
|
name="name"
|
||||||
|
label={LL.NAME(0)}
|
||||||
|
value={editItem.name}
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
onChange={updateFormValue}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4} mt={3}>
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={<Checkbox checked={editItem.writeable} onChange={updateFormValue} name="writeable" />}
|
||||||
|
label={LL.WRITEABLE()}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<ValidatedTextField
|
||||||
|
fieldErrors={fieldErrors}
|
||||||
|
name="device_id"
|
||||||
|
label={LL.ID_OF(LL.DEVICE())}
|
||||||
|
margin="normal"
|
||||||
|
type="string"
|
||||||
|
fullWidth
|
||||||
|
value={editItem.device_id as string}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={{ style: { textTransform: 'uppercase' } }}
|
||||||
|
InputProps={{ startAdornment: <InputAdornment position="start">0x</InputAdornment> }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<ValidatedTextField
|
||||||
|
fieldErrors={fieldErrors}
|
||||||
|
name="type_id"
|
||||||
|
label={LL.ID_OF(LL.TYPE(1))}
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
value={editItem.type_id}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={{ style: { textTransform: 'uppercase' } }}
|
||||||
|
InputProps={{ startAdornment: <InputAdornment position="start">0x</InputAdornment> }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<ValidatedTextField
|
||||||
|
fieldErrors={fieldErrors}
|
||||||
|
name="offset"
|
||||||
|
label={LL.OFFSET()}
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
value={editItem.offset}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="value_type"
|
||||||
|
label={LL.VALUE(1) + ' ' + LL.TYPE(1)}
|
||||||
|
value={editItem.value_type}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
select
|
||||||
|
>
|
||||||
|
<MenuItem value={DeviceValueType.BOOL}>BOOL</MenuItem>
|
||||||
|
<MenuItem value={DeviceValueType.INT}>INT</MenuItem>
|
||||||
|
<MenuItem value={DeviceValueType.UINT}>UINT</MenuItem>
|
||||||
|
<MenuItem value={DeviceValueType.SHORT}>SHORT</MenuItem>
|
||||||
|
<MenuItem value={DeviceValueType.USHORT}>USHORT</MenuItem>
|
||||||
|
<MenuItem value={DeviceValueType.ULONG}>ULONG</MenuItem>
|
||||||
|
<MenuItem value={DeviceValueType.TIME}>TIME</MenuItem>
|
||||||
|
<MenuItem value={DeviceValueType.STRING}>RAW</MenuItem>
|
||||||
|
</TextField>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{editItem.value_type !== DeviceValueType.BOOL && editItem.value_type !== DeviceValueType.STRING && (
|
||||||
|
<>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="factor"
|
||||||
|
label={LL.FACTOR()}
|
||||||
|
value={editItem.factor}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
fullWidth
|
||||||
|
margin="normal"
|
||||||
|
type="number"
|
||||||
|
inputProps={{ step: '0.001' }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="uom"
|
||||||
|
label={LL.UNIT()}
|
||||||
|
value={editItem.uom}
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
onChange={updateFormValue}
|
||||||
|
select
|
||||||
|
>
|
||||||
|
{DeviceValueUOM_s.map((val, i) => (
|
||||||
|
<MenuItem key={i} value={i}>
|
||||||
|
{val}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{editItem.value_type === DeviceValueType.STRING && (
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="factor"
|
||||||
|
label="Bytes"
|
||||||
|
value={editItem.factor}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
fullWidth
|
||||||
|
margin="normal"
|
||||||
|
type="number"
|
||||||
|
inputProps={{ min: '1', max: '27', step: '1' }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</DialogContent>
|
||||||
|
|
||||||
|
<DialogActions>
|
||||||
|
{!creating && (
|
||||||
|
<Box flexGrow={1}>
|
||||||
|
<Button startIcon={<RemoveIcon />} variant="outlined" color="warning" onClick={remove}>
|
||||||
|
{LL.REMOVE()}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<Button startIcon={<CancelIcon />} variant="outlined" onClick={close} color="secondary">
|
||||||
|
{LL.CANCEL()}
|
||||||
|
</Button>
|
||||||
|
<Button startIcon={creating ? <AddIcon /> : <DoneIcon />} variant="outlined" onClick={save} color="primary">
|
||||||
|
{creating ? LL.ADD(0) : LL.UPDATE()}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SettingsEntitiesDialog;
|
||||||
@@ -210,7 +210,7 @@ const SettingsSchedulerDialog = ({
|
|||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
name="value"
|
name="value"
|
||||||
label={LL.VALUE(1)}
|
label={LL.VALUE(0)}
|
||||||
multiline
|
multiline
|
||||||
margin="normal"
|
margin="normal"
|
||||||
fullWidth
|
fullWidth
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type {
|
import type {
|
||||||
APIcall,
|
APIdata,
|
||||||
Settings,
|
Settings,
|
||||||
Status,
|
Status,
|
||||||
CoreData,
|
CoreData,
|
||||||
@@ -20,7 +20,7 @@ export const readCoreData = () => alovaInstance.Get<CoreData>(`/rest/coreData`);
|
|||||||
export const readDeviceData = (id: number) =>
|
export const readDeviceData = (id: number) =>
|
||||||
alovaInstance.Get<DeviceData>('/rest/deviceData', {
|
alovaInstance.Get<DeviceData>('/rest/deviceData', {
|
||||||
// alovaInstance.Get<DeviceData>(`/rest/deviceData/${id}`, {
|
// alovaInstance.Get<DeviceData>(`/rest/deviceData/${id}`, {
|
||||||
params: { id }, // TODO replace later with id
|
params: { id }, // TODO replace params later
|
||||||
responseType: 'arraybuffer' // uses msgpack
|
responseType: 'arraybuffer' // uses msgpack
|
||||||
});
|
});
|
||||||
export const writeDeviceValue = (data: any) => alovaInstance.Post('/rest/writeDeviceValue', data);
|
export const writeDeviceValue = (data: any) => alovaInstance.Post('/rest/writeDeviceValue', data);
|
||||||
@@ -44,7 +44,7 @@ export const readStatus = () => alovaInstance.Get<Status>('/rest/status');
|
|||||||
export const scanDevices = () => alovaInstance.Post('/rest/scanDevices');
|
export const scanDevices = () => alovaInstance.Post('/rest/scanDevices');
|
||||||
|
|
||||||
// HelpInformation
|
// HelpInformation
|
||||||
export const API = (apiCall: APIcall) => alovaInstance.Post('/api', apiCall);
|
export const APIcall = (device: string, apiData: APIdata) => alovaInstance.Post(`/api/${device}`, apiData);
|
||||||
|
|
||||||
// UploadFileForm
|
// UploadFileForm
|
||||||
export const getSettings = () => alovaInstance.Get('/rest/getSettings');
|
export const getSettings = () => alovaInstance.Get('/rest/getSettings');
|
||||||
@@ -56,7 +56,7 @@ export const getSchedule = () => alovaInstance.Get('/rest/getSchedule');
|
|||||||
export const readDeviceEntities = (id: number) =>
|
export const readDeviceEntities = (id: number) =>
|
||||||
// alovaInstance.Get<DeviceEntity[]>(`/rest/deviceEntities/${id}`, {
|
// alovaInstance.Get<DeviceEntity[]>(`/rest/deviceEntities/${id}`, {
|
||||||
alovaInstance.Get<DeviceEntity[]>(`/rest/deviceEntities`, {
|
alovaInstance.Get<DeviceEntity[]>(`/rest/deviceEntities`, {
|
||||||
params: { id }, // TODO replace later with id
|
params: { id }, // TODO replace params later
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
transformData(data: any) {
|
transformData(data: any) {
|
||||||
return data.map((de: DeviceEntity) => ({ ...de, o_m: de.m, o_cn: de.cn, o_mi: de.mi, o_ma: de.ma }));
|
return data.map((de: DeviceEntity) => ({ ...de, o_m: de.m, o_cn: de.cn, o_mi: de.mi, o_ma: de.ma }));
|
||||||
@@ -88,7 +88,7 @@ export const writeSchedule = (data: any) => alovaInstance.Post('/rest/schedule',
|
|||||||
|
|
||||||
// SettingsEntities
|
// SettingsEntities
|
||||||
export const readCustomEntities = () =>
|
export const readCustomEntities = () =>
|
||||||
alovaInstance.Get<EntityItem[]>('/rest/customEntities', {
|
alovaInstance.Get<EntityItem[]>('/rest/customentities', {
|
||||||
name: 'entities',
|
name: 'entities',
|
||||||
transformData(data: any) {
|
transformData(data: any) {
|
||||||
return data.entities.map((ei: EntityItem) => ({
|
return data.entities.map((ei: EntityItem) => ({
|
||||||
@@ -106,4 +106,4 @@ export const readCustomEntities = () =>
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
export const writeCustomEntities = (data: any) => alovaInstance.Post('/rest/customEntities', data);
|
export const writeCustomEntities = (data: any) => alovaInstance.Post('/rest/customentities', data);
|
||||||
|
|||||||
@@ -177,8 +177,7 @@ export enum DeviceValueUOM {
|
|||||||
L,
|
L,
|
||||||
KMIN,
|
KMIN,
|
||||||
K,
|
K,
|
||||||
VOLTS,
|
VOLTS
|
||||||
MBAR
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DeviceValueUOM_s = [
|
export const DeviceValueUOM_s = [
|
||||||
@@ -205,8 +204,7 @@ export const DeviceValueUOM_s = [
|
|||||||
'l',
|
'l',
|
||||||
'K*min',
|
'K*min',
|
||||||
'K',
|
'K',
|
||||||
'V',
|
'V'
|
||||||
'mbar'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export enum AnalogType {
|
export enum AnalogType {
|
||||||
@@ -225,12 +223,12 @@ export enum AnalogType {
|
|||||||
|
|
||||||
export const AnalogTypeNames = [
|
export const AnalogTypeNames = [
|
||||||
'(disabled)',
|
'(disabled)',
|
||||||
'Digital In',
|
'Digital in',
|
||||||
'Counter',
|
'Counter',
|
||||||
'ADC',
|
'ADC',
|
||||||
'Timer',
|
'Timer',
|
||||||
'Rate',
|
'Rate',
|
||||||
'Digital Out',
|
'Digital out',
|
||||||
'PWM 0',
|
'PWM 0',
|
||||||
'PWM 1',
|
'PWM 1',
|
||||||
'PWM 2'
|
'PWM 2'
|
||||||
@@ -268,8 +266,7 @@ export interface BoardProfile {
|
|||||||
eth_clock_mode: number;
|
eth_clock_mode: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface APIcall {
|
export interface APIdata {
|
||||||
device: string;
|
|
||||||
entity: string;
|
entity: string;
|
||||||
id: any;
|
id: any;
|
||||||
}
|
}
|
||||||
@@ -325,7 +322,6 @@ export enum ScheduleFlag {
|
|||||||
|
|
||||||
export interface EntityItem {
|
export interface EntityItem {
|
||||||
id: number; // unique number
|
id: number; // unique number
|
||||||
ram: number;
|
|
||||||
name: string;
|
name: string;
|
||||||
device_id: number | string;
|
device_id: number | string;
|
||||||
type_id: number | string;
|
type_id: number | string;
|
||||||
@@ -337,7 +333,6 @@ export interface EntityItem {
|
|||||||
writeable: boolean;
|
writeable: boolean;
|
||||||
deleted?: boolean;
|
deleted?: boolean;
|
||||||
o_id?: number;
|
o_id?: number;
|
||||||
o_ram?: number;
|
|
||||||
o_name?: string;
|
o_name?: string;
|
||||||
o_device_id?: number | string;
|
o_device_id?: number | string;
|
||||||
o_type_id?: number | string;
|
o_type_id?: number | string;
|
||||||
@@ -347,7 +342,6 @@ export interface EntityItem {
|
|||||||
o_value_type?: number;
|
o_value_type?: number;
|
||||||
o_deleted?: boolean;
|
o_deleted?: boolean;
|
||||||
o_writeable?: boolean;
|
o_writeable?: boolean;
|
||||||
o_value?: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Entities {
|
export interface Entities {
|
||||||
@@ -392,7 +386,6 @@ export const enum DeviceValueType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const DeviceValueTypeNames = [
|
export const DeviceValueTypeNames = [
|
||||||
//
|
|
||||||
'BOOL',
|
'BOOL',
|
||||||
'INT',
|
'INT',
|
||||||
'UINT',
|
'UINT',
|
||||||
@@ -401,6 +394,6 @@ export const DeviceValueTypeNames = [
|
|||||||
'ULONG',
|
'ULONG',
|
||||||
'TIME',
|
'TIME',
|
||||||
'ENUM',
|
'ENUM',
|
||||||
'RAW',
|
'STRING',
|
||||||
'CMD'
|
'CMD'
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from './ap';
|
export * from './ap';
|
||||||
|
export * from './features';
|
||||||
export * from './me';
|
export * from './me';
|
||||||
export * from './mqtt';
|
export * from './mqtt';
|
||||||
export * from './ntp';
|
export * from './ntp';
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ export interface NetworkStatus {
|
|||||||
gateway_ip: string;
|
gateway_ip: string;
|
||||||
dns_ip_1: string;
|
dns_ip_1: string;
|
||||||
dns_ip_2: string;
|
dns_ip_2: string;
|
||||||
hostname: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NetworkSettings {
|
export interface NetworkSettings {
|
||||||
@@ -42,7 +41,7 @@ export interface NetworkSettings {
|
|||||||
password: string;
|
password: string;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
static_ip_config: boolean;
|
static_ip_config: boolean;
|
||||||
enableIPv6?: boolean;
|
enableIPv6: boolean;
|
||||||
bandwidth20: boolean;
|
bandwidth20: boolean;
|
||||||
nosleep: boolean;
|
nosleep: boolean;
|
||||||
tx_power: number;
|
tx_power: number;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export interface NTPStatus {
|
|||||||
utc_time: string;
|
utc_time: string;
|
||||||
local_time: string;
|
local_time: string;
|
||||||
server: string;
|
server: string;
|
||||||
|
uptime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NTPSettings {
|
export interface NTPSettings {
|
||||||
|
|||||||
93
interface/src/utils/useWs.ts
Normal file
93
interface/src/utils/useWs.ts
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
import { debounce } from 'lodash-es';
|
||||||
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
import Sockette from 'sockette';
|
||||||
|
|
||||||
|
import { addAccessTokenParameter } from 'api/authentication';
|
||||||
|
|
||||||
|
interface WebSocketIdMessage {
|
||||||
|
type: 'id';
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WebSocketPayloadMessage<D> {
|
||||||
|
type: 'payload';
|
||||||
|
origin_id: string;
|
||||||
|
payload: D;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type WebSocketMessage<D> = WebSocketIdMessage | WebSocketPayloadMessage<D>;
|
||||||
|
|
||||||
|
export const useWs = <D>(wsUrl: string, wsThrottle = 100) => {
|
||||||
|
const ws = useRef<Sockette>();
|
||||||
|
const clientId = useRef<string>();
|
||||||
|
|
||||||
|
const [connected, setConnected] = useState<boolean>(false);
|
||||||
|
const [data, setData] = useState<D>();
|
||||||
|
const [transmit, setTransmit] = useState<boolean>();
|
||||||
|
const [clear, setClear] = useState<boolean>();
|
||||||
|
|
||||||
|
const onMessage = useCallback((event: MessageEvent) => {
|
||||||
|
const rawData = event.data;
|
||||||
|
if (typeof rawData === 'string' || rawData instanceof String) {
|
||||||
|
const message = JSON.parse(rawData as string) as WebSocketMessage<D>;
|
||||||
|
switch (message.type) {
|
||||||
|
case 'id':
|
||||||
|
clientId.current = message.id;
|
||||||
|
break;
|
||||||
|
case 'payload':
|
||||||
|
if (clientId.current) {
|
||||||
|
setData((existingData) => (clientId.current === message.origin_id && existingData) || message.payload);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const doSaveData = useCallback((newData: D, clearData = false) => {
|
||||||
|
if (!ws.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (clearData) {
|
||||||
|
setData(undefined);
|
||||||
|
}
|
||||||
|
ws.current.json(newData);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const saveData = useRef(debounce(doSaveData, wsThrottle));
|
||||||
|
|
||||||
|
const updateData = (newData: React.SetStateAction<D | undefined>, transmitData: true, clearData: false) => {
|
||||||
|
setData(newData);
|
||||||
|
setTransmit(transmitData);
|
||||||
|
setClear(clearData);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!transmit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data && saveData.current(data, clear);
|
||||||
|
setTransmit(false);
|
||||||
|
setClear(false);
|
||||||
|
}, [doSaveData, data, transmit, clear]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const instance = new Sockette(addAccessTokenParameter(wsUrl), {
|
||||||
|
onmessage: onMessage,
|
||||||
|
onopen: () => {
|
||||||
|
setConnected(true);
|
||||||
|
},
|
||||||
|
onclose: () => {
|
||||||
|
clientId.current = undefined;
|
||||||
|
setConnected(false);
|
||||||
|
setData(undefined);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ws.current = instance;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
return instance.close;
|
||||||
|
}, [wsUrl, onMessage]);
|
||||||
|
|
||||||
|
return { connected, data, updateData } as const;
|
||||||
|
};
|
||||||
|
*/
|
||||||
@@ -14,5 +14,9 @@ export const createNetworkSettingsValidator = (networkSettings: NetworkSettings)
|
|||||||
subnet_mask: [{ required: true, message: 'Subnet mask is required' }, IP_ADDRESS_VALIDATOR],
|
subnet_mask: [{ required: true, message: 'Subnet mask is required' }, IP_ADDRESS_VALIDATOR],
|
||||||
dns_ip_1: IP_ADDRESS_VALIDATOR,
|
dns_ip_1: IP_ADDRESS_VALIDATOR,
|
||||||
dns_ip_2: IP_ADDRESS_VALIDATOR
|
dns_ip_2: IP_ADDRESS_VALIDATOR
|
||||||
})
|
}),
|
||||||
|
tx_power: [
|
||||||
|
{ required: true, message: 'Tx Power is required' },
|
||||||
|
{ type: 'number', min: 0, max: 20, message: 'Tx Power must be between 0 and 20dBm' }
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const IP_ADDRESS_VALIDATOR = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const HOSTNAME_LENGTH_REGEXP = /^.{0,200}$/;
|
const HOSTNAME_LENGTH_REGEXP = /^.{0,63}$/;
|
||||||
const HOSTNAME_PATTERN_REGEXP =
|
const HOSTNAME_PATTERN_REGEXP =
|
||||||
/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$/;
|
/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$/;
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ const isValidHostname = (value: string) => HOSTNAME_LENGTH_REGEXP.test(value) &&
|
|||||||
export const HOSTNAME_VALIDATOR = {
|
export const HOSTNAME_VALIDATOR = {
|
||||||
validator(rule: InternalRuleItem, value: string, callback: (error?: string) => void) {
|
validator(rule: InternalRuleItem, value: string, callback: (error?: string) => void) {
|
||||||
if (value && !isValidHostname(value)) {
|
if (value && !isValidHostname(value)) {
|
||||||
callback('Must be a valid hostname');
|
callback('Must be a valid hostname of up to 63 characters');
|
||||||
} else {
|
} else {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ export const HOSTNAME_VALIDATOR = {
|
|||||||
export const IP_OR_HOSTNAME_VALIDATOR = {
|
export const IP_OR_HOSTNAME_VALIDATOR = {
|
||||||
validator(rule: InternalRuleItem, value: string, callback: (error?: string) => void) {
|
validator(rule: InternalRuleItem, value: string, callback: (error?: string) => void) {
|
||||||
if (value && !(isValidIpAddress(value) || isValidHostname(value))) {
|
if (value && !(isValidIpAddress(value) || isValidHostname(value))) {
|
||||||
callback('Must be a valid IP address or hostname');
|
callback('Must be a valid IP address or hostname of up to 63 characters');
|
||||||
} else {
|
} else {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|||||||
4418
interface/yarn.lock
4418
interface/yarn.lock
File diff suppressed because it is too large
Load Diff
2
lib/ArduinoJson/ArduinoJson.h
Executable file → Normal file
2
lib/ArduinoJson/ArduinoJson.h
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include "src/ArduinoJson.h"
|
#include "src/ArduinoJson.h"
|
||||||
|
|||||||
922
lib/ArduinoJson/CHANGELOG.md
Executable file → Normal file
922
lib/ArduinoJson/CHANGELOG.md
Executable file → Normal file
@@ -1,130 +1,854 @@
|
|||||||
ArduinoJson: change log
|
ArduinoJson: change log
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
v7.0.3 (2024-02-05)
|
v6.21.3 (2023-07-23)
|
||||||
------
|
-------
|
||||||
|
|
||||||
* Improve error messages when using `char` or `char*` (issue #2043)
|
* Fix compatibility with the Blynk libary (issue #1914)
|
||||||
* Reduce stack consumption (issue #2046)
|
|
||||||
* Fix compatibility with GCC 4.8 (issue #2045)
|
|
||||||
|
|
||||||
v7.0.2 (2024-01-19)
|
|
||||||
------
|
|
||||||
|
|
||||||
* Fix assertion `poolIndex < count_` after `JsonDocument::clear()` (issue #2034)
|
|
||||||
|
|
||||||
v7.0.1 (2024-01-10)
|
|
||||||
------
|
|
||||||
|
|
||||||
* Fix "no matching function" with `JsonObjectConst::operator[]` (issue #2019)
|
|
||||||
* Remove unused files in the PlatformIO package
|
|
||||||
* Fix `volatile bool` serialized as `1` or `0` instead of `true` or `false` (issue #2029)
|
|
||||||
|
|
||||||
v7.0.0 (2024-01-03)
|
|
||||||
------
|
|
||||||
|
|
||||||
* Remove `BasicJsonDocument`
|
|
||||||
* Remove `StaticJsonDocument`
|
|
||||||
* Add abstract `Allocator` class
|
|
||||||
* Merge `DynamicJsonDocument` with `JsonDocument`
|
|
||||||
* Remove `JSON_ARRAY_SIZE()`, `JSON_OBJECT_SIZE()`, and `JSON_STRING_SIZE()`
|
|
||||||
* Remove `ARDUINOJSON_ENABLE_STRING_DEDUPLICATION` (string deduplication cannot be disabled anymore)
|
|
||||||
* Remove `JsonDocument::capacity()`
|
|
||||||
* Store the strings in the heap
|
|
||||||
* Reference-count shared strings
|
|
||||||
* Always store `serialized("string")` by copy (#1915)
|
|
||||||
* Remove the zero-copy mode of `deserializeJson()` and `deserializeMsgPack()`
|
|
||||||
* Fix double lookup in `to<JsonVariant>()`
|
* Fix double lookup in `to<JsonVariant>()`
|
||||||
* Fix double call to `size()` in `serializeMsgPack()`
|
* Fix double call to `size()` in `serializeMsgPack()`
|
||||||
* Include `ARDUINOJSON_SLOT_OFFSET_SIZE` in the namespace name
|
* Include `ARDUINOJSON_SLOT_OFFSET_SIZE` in the namespace name
|
||||||
* Remove `JsonVariant::shallowCopy()`
|
|
||||||
* `JsonDocument`'s capacity grows as needed, no need to pass it to the constructor anymore
|
|
||||||
* `JsonDocument`'s allocator is not monotonic anymore, removed values get recycled
|
|
||||||
* Show a link to the documentation when user passes an unsupported input type
|
* Show a link to the documentation when user passes an unsupported input type
|
||||||
* Remove `JsonDocument::memoryUsage()`
|
|
||||||
* Remove `JsonDocument::garbageCollect()`
|
v6.21.2 (2023-04-12)
|
||||||
* Add `deserializeJson(JsonVariant, ...)` and `deserializeMsgPack(JsonVariant, ...)` (#1226)
|
-------
|
||||||
* Call `shrinkToFit()` in `deserializeJson()` and `deserializeMsgPack()`
|
|
||||||
* `serializeJson()` and `serializeMsgPack()` replace the content of `std::string` and `String` instead of appending to it
|
* Fix compatibility with the Zephyr Project (issue #1905)
|
||||||
* Replace `add()` with `add<T>()` (`add(T)` is still supported)
|
* Allow using PROGMEM outside of Arduino (issue #1903)
|
||||||
* Remove `createNestedArray()` and `createNestedObject()` (use `to<JsonArray>()` and `to<JsonObject>()` instead)
|
* Set default for `ARDUINOJSON_ENABLE_PROGMEM` to `1` on AVR
|
||||||
|
|
||||||
|
v6.21.1 (2023-03-27)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Double speed of `DynamicJsonDocument::garbageCollect()`
|
||||||
|
* Fix compatibility with GCC 5.2 (issue #1897)
|
||||||
|
|
||||||
|
v6.21.0 (2023-03-14)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Drop support for C++98/C++03. Minimum required is C++11.
|
||||||
|
* Remove `ARDUINOJSON_NAMESPACE`; use `ArduinoJson` instead.
|
||||||
|
* Make string support generic (issue #1807)
|
||||||
|
|
||||||
|
v6.20.1 (2023-02-08)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Remove explicit exclusion of `as<char*>()` and `as<char>()` (issue #1860)
|
||||||
|
If you try to call them, you'll now get the same error message as any unsupported type.
|
||||||
|
You could also add a custom converter for `char*` and `char`.
|
||||||
|
|
||||||
|
v6.20.0 (2022-12-26)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Add `JsonVariant::shallowCopy()` (issue #1343)
|
||||||
|
* Fix `9.22337e+18 is outside the range of representable values of type 'long'`
|
||||||
|
* Fix comparison operators for `JsonArray`, `JsonArrayConst`, `JsonObject`, and `JsonObjectConst`
|
||||||
|
* Fix lax parsing of `true`, `false`, and `null` (issue #1781)
|
||||||
|
* Remove undocumented `accept()` functions
|
||||||
|
* Rename `addElement()` to `add()`
|
||||||
|
* Remove `getElement()`, `getOrAddElement()`, `getMember()`, and `getOrAddMember()`
|
||||||
|
* Remove undocumented `JsonDocument::data()` and `JsonDocument::memoryPool()`
|
||||||
|
* Remove undocumented `JsonArrayIterator::internal()` and `JsonObjectIterator::internal()`
|
||||||
|
* Rename things in `ARDUINOJSON_NAMESPACE` to match the public names
|
||||||
|
* Add documentation to most public symbols
|
||||||
|
* Remove support for naked `char` (was deprecated since 6.18.0)
|
||||||
|
|
||||||
> ### BREAKING CHANGES
|
> ### BREAKING CHANGES
|
||||||
>
|
>
|
||||||
> As every major release, ArduinoJson 7 introduces several breaking changes.
|
> This release hides `JsonVariant`'s functions that were only intended for internal use.
|
||||||
> I added some stubs so that most existing programs should compile, but I highty recommend you upgrade your code.
|
> If you were using them in your programs, you must replace with `operator[]` and `to<JsonVariant>()`, like so:
|
||||||
>
|
|
||||||
> #### `JsonDocument`
|
|
||||||
>
|
|
||||||
> In ArduinoJson 6, you could allocate the memory pool on the stack (with `StaticJsonDocument`) or in the heap (with `DynamicJsonDocument`).
|
|
||||||
> In ArduinoJson 7, the memory pool is always allocated in the heap, so `StaticJsonDocument` and `DynamicJsonDocument` have been merged into `JsonDocument`.
|
|
||||||
>
|
|
||||||
> In ArduinoJson 6, `JsonDocument` had a fixed capacity; in ArduinoJson 7, it has an elastic capacity that grows as needed.
|
|
||||||
> Therefore, you don't need to specify the capacity anymore, so the macros `JSON_ARRAY_SIZE()`, `JSON_OBJECT_SIZE()`, and `JSON_STRING_SIZE()` have been removed.
|
|
||||||
>
|
>
|
||||||
> ```c++
|
> ```c++
|
||||||
> // ArduinoJson 6
|
> // before
|
||||||
> StaticJsonDocument<256> doc;
|
> JsonVariant a = variant.getElement(idx);
|
||||||
> // or
|
> JsonVariant b = variant.getOrAddElement(idx);
|
||||||
> DynamicJsonDocument doc(256);
|
> JsonVariant c = variant.getMember(key);
|
||||||
|
> JsonVariant d = variant.getOrAddMember(key);
|
||||||
>
|
>
|
||||||
> // ArduinoJson 7
|
> // after
|
||||||
> JsonDocument doc;
|
> JsonVariant a = variant[idx];
|
||||||
|
> JsonVariant b = idx < variant.size() ? variant[idx] : variant[idx].to<JsonVariant>();
|
||||||
|
> JsonVariant c = variant[key];
|
||||||
|
> JsonVariant d = variant.containsKey(key) ? variant[key] : variant[key].to<JsonVariant>();
|
||||||
|
> ```
|
||||||
|
|
||||||
|
v6.19.4 (2022-04-05)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Add `ElementProxy::memoryUsage()`
|
||||||
|
* Add `MemberProxy::memoryUsage()` (issue #1730)
|
||||||
|
* Add implicit conversion from `JsonDocument` to `JsonVariant`
|
||||||
|
* Fix comparisons operators with `const JsonDocument&`
|
||||||
|
|
||||||
|
v6.19.3 (2022-03-08)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fix `call of overloaded 'String(const char*, int)' is ambiguous`
|
||||||
|
* Fix `JsonString` operator `==` and `!=` for non-zero-terminated string
|
||||||
|
* Fix `-Wsign-conversion` on GCC 8 (issue #1715)
|
||||||
|
* MessagePack: serialize round floats as integers (issue #1718)
|
||||||
|
|
||||||
|
v6.19.2 (2022-02-14)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fix `cannot convert 'pgm_p' to 'const void*'` (issue #1707)
|
||||||
|
|
||||||
|
v6.19.1 (2022-01-14)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fix crash when adding an object member in a too small `JsonDocument`
|
||||||
|
* Fix filter not working in zero-copy mode (issue #1697)
|
||||||
|
|
||||||
|
v6.19.0 (2022-01-08)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Remove `ARDUINOJSON_EMBEDDED_MODE` and assume we run on an embedded platform.
|
||||||
|
Dependent settings (like `ARDUINOJSON_DEFAULT_NESTING_LIMIT`) must be set individually.
|
||||||
|
* Change the default of `ARDUINOJSON_USE_DOUBLE` to `1`
|
||||||
|
* Change the default of `ARDUINOJSON_USE_LONG_LONG` to `1` on 32-bit platforms
|
||||||
|
* Add `as<JsonString>()` and `is<JsonString>()`
|
||||||
|
* Add safe bool idiom in `JsonString`
|
||||||
|
* Add support for NUL in string values (issue #1646)
|
||||||
|
* Add support for arbitrary array rank in `copyArray()`
|
||||||
|
* Add support for `char[][]` in `copyArray()`
|
||||||
|
* Remove `DeserializationError == bool` and `DeserializationError != bool`
|
||||||
|
* Renamed undocumented function `isUndefined()` to `isUnbound()`
|
||||||
|
* Fix `JsonVariant::memoryUsage()` for raw strings
|
||||||
|
* Fix `call of overloaded 'swap(BasicJsonDocument&, BasicJsonDocument&)' is ambiguous` (issue #1678)
|
||||||
|
* Fix inconsistent pool capacity between `BasicJsonDocument`'s copy and move constructors
|
||||||
|
* Fix inconsistent pool capacity between `BasicJsonDocument`'s copy and move assignments
|
||||||
|
* Fix return type of `StaticJsonDocument::operator=`
|
||||||
|
* Avoid pool reallocation in `BasicJsonDocument`'s copy assignment if capacity is the same
|
||||||
|
* Avoid including `Arduino.h` when all its features are disabled (issue #1692, PR #1693 by @paulocsanz)
|
||||||
|
* Assume `PROGMEM` is available as soon as `ARDUINO` is defined (consequence of #1693)
|
||||||
|
|
||||||
|
v6.18.5 (2021-09-28)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Set `ARDUINOJSON_EMBEDDED_MODE` to `1` on Nios II (issue #1657)
|
||||||
|
|
||||||
|
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)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Added support for custom converters (issue #687)
|
||||||
|
* Added support for `Printable` (issue #1444)
|
||||||
|
* Removed support for `char` values, see below (issue #1498)
|
||||||
|
* `deserializeJson()` leaves `\uXXXX` unchanged instead of returning `NotSupported`
|
||||||
|
* `deserializeMsgPack()` inserts `null` instead of returning `NotSupported`
|
||||||
|
* Removed `DeserializationError::NotSupported`
|
||||||
|
* Added `JsonVariant::is<JsonArrayConst/JsonObjectConst>()` (issue #1412)
|
||||||
|
* Added `JsonVariant::is<JsonVariant/JsonVariantConst>()` (issue #1412)
|
||||||
|
* Changed `JsonVariantConst::is<JsonArray/JsonObject>()` to return `false` (issue #1412)
|
||||||
|
* Simplified `JsonVariant::as<T>()` to always return `T` (see below)
|
||||||
|
* Updated folders list in `.mbedignore` (PR #1515 by @AGlass0fMilk)
|
||||||
|
* Fixed member-call-on-null-pointer in `getMember()` when array is empty
|
||||||
|
* `serializeMsgPack(doc, buffer, size)` doesn't add null-terminator anymore (issue #1545)
|
||||||
|
* `serializeJson(doc, buffer, size)` adds null-terminator only if there is enough room
|
||||||
|
* PlatformIO: set `build.libArchive` to `false` (PR #1550 by @askreet)
|
||||||
|
|
||||||
|
> ### BREAKING CHANGES
|
||||||
|
>
|
||||||
|
> #### Support for `char` removed
|
||||||
|
>
|
||||||
|
> We cannot cast a `JsonVariant` to a `char` anymore, so the following will break:
|
||||||
|
> ```c++
|
||||||
|
> char age = doc["age"]; // error: no matching function for call to 'variantAs(VariantData*&)'
|
||||||
|
> ```
|
||||||
|
> Instead, you must use another integral type, such as `int8_t`:
|
||||||
|
> ```c++
|
||||||
|
> int8_t age = doc["age"]; // OK
|
||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
> In ArduinoJson 7, `JsonDocument` reuses released memory, so `garbageCollect()` has been removed.
|
> Similarly, we cannot assign from a `char` anymore, so the following will break:
|
||||||
> `shrinkToFit()` is still available and releases the over-allocated memory.
|
> ```c++
|
||||||
|
> char age;
|
||||||
|
> doc["age"] = age; // error: no matching function for call to 'VariantRef::set(const char&)'
|
||||||
|
> ```
|
||||||
|
> Instead, you must use another integral type, such as `int8_t`:
|
||||||
|
> ```c++
|
||||||
|
> int8_t age;
|
||||||
|
> doc["age"] = age; // OK
|
||||||
|
> ```
|
||||||
|
> A deprecation warning with the message "Support for `char` is deprecated, use `int8_t` or `uint8_t` instead" was added to allow a smooth transition.
|
||||||
>
|
>
|
||||||
> Due to a change in the implementation, it's not possible to store a pointer to a variant from another `JsonDocument`, so `shallowCopy()` has been removed.
|
> #### `as<T>()` always returns `T`
|
||||||
>
|
>
|
||||||
> In ArduinoJson 6, the meaning of `memoryUsage()` was clear: it returned the number of bytes used in the memory pool.
|
> Previously, `JsonVariant::as<T>()` could return a type different from `T`.
|
||||||
> In ArduinoJson 7, the meaning of `memoryUsage()` would be ambiguous, so it has been removed.
|
> The most common example is `as<char*>()` that returned a `const char*`.
|
||||||
|
> While this feature simplified a few use cases, it was confusing and complicated the
|
||||||
|
> implementation of custom converters.
|
||||||
>
|
>
|
||||||
> #### Custom allocators
|
> Starting from this version, `as<T>` doesn't try to auto-correct the return type and always return `T`,
|
||||||
>
|
> which means that you cannot write this anymore:
|
||||||
> In ArduinoJson 6, you could specify a custom allocator class as a template parameter of `BasicJsonDocument`.
|
|
||||||
> In ArduinoJson 7, you must inherit from `ArduinoJson::Allocator` and pass a pointer to an instance of your class to the constructor of `JsonDocument`.
|
|
||||||
>
|
>
|
||||||
> ```c++
|
> ```c++
|
||||||
> // ArduinoJson 6
|
> Serial.println(doc["sensor"].as<char*>()); // error: invalid conversion from 'const char*' to 'char*' [-fpermissive]
|
||||||
> class MyAllocator {
|
|
||||||
> // ...
|
|
||||||
> };
|
|
||||||
> BasicJsonDocument<MyAllocator> doc(256);
|
|
||||||
>
|
|
||||||
> // ArduinoJson 7
|
|
||||||
> class MyAllocator : public ArduinoJson::Allocator {
|
|
||||||
> // ...
|
|
||||||
> };
|
|
||||||
> MyAllocator myAllocator;
|
|
||||||
> JsonDocument doc(&myAllocator);
|
|
||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
> #### `createNestedArray()` and `createNestedObject()`
|
> Instead, you must write:
|
||||||
>
|
|
||||||
> In ArduinoJson 6, you could create a nested array or object with `createNestedArray()` and `createNestedObject()`.
|
|
||||||
> In ArduinoJson 7, you must use `add<T>()` or `to<T>()` instead.
|
|
||||||
>
|
|
||||||
> For example, to create `[[],{}]`, you would write:
|
|
||||||
>
|
>
|
||||||
> ```c++
|
> ```c++
|
||||||
> // ArduinoJson 6
|
> Serial.println(doc["sensor"].as<const char*>()); // OK
|
||||||
> arr.createNestedArray();
|
|
||||||
> arr.createNestedObject();
|
|
||||||
>
|
|
||||||
> // ArduinoJson 7
|
|
||||||
> arr.add<JsonArray>();
|
|
||||||
> arr.add<JsonObject>();
|
|
||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
> And to create `{"array":[],"object":{}}`, you would write:
|
> A deprecation warning with the message "Replace `as<char*>()` with `as<const char*>()`" was added to allow a smooth transition.
|
||||||
|
>
|
||||||
|
> #### `DeserializationError::NotSupported` removed
|
||||||
|
>
|
||||||
|
> On a different topic, `DeserializationError::NotSupported` has been removed.
|
||||||
|
> Instead of returning this error:
|
||||||
|
>
|
||||||
|
> * `deserializeJson()` leaves `\uXXXX` unchanged (only when `ARDUINOJSON_DECODE_UNICODE` is `0`)
|
||||||
|
> * `deserializeMsgPack()` replaces unsupported values with `null`s
|
||||||
|
>
|
||||||
|
> #### Const-aware `is<T>()`
|
||||||
|
>
|
||||||
|
> Lastly, a very minor change concerns `JsonVariantConst::is<T>()`.
|
||||||
|
> It used to return `true` for `JsonArray` and `JsonOject`, but now it returns `false`.
|
||||||
|
> Instead, you must use `JsonArrayConst` and `JsonObjectConst`.
|
||||||
|
|
||||||
|
v6.17.3 (2021-02-15)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Made `JsonDocument`'s destructor protected (issue #1480)
|
||||||
|
* Added missing calls to `client.stop()` in `JsonHttpClient.ino` (issue #1485)
|
||||||
|
* Fixed error `expected ')' before 'char'` when `isdigit()` is a macro (issue #1487)
|
||||||
|
* Fixed error `definition of implicit copy constructor is deprecated` on Clang 10
|
||||||
|
* PlatformIO: set framework compatibility to `*` (PR #1490 by @maxgerhardt)
|
||||||
|
|
||||||
|
v6.17.2 (2020-11-14)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed invalid conversion error in `operator|(JsonVariant, char*)` (issue #1432)
|
||||||
|
* Changed the default value of `ARDUINOJSON_ENABLE_PROGMEM` (issue #1433).
|
||||||
|
It now checks that the `pgm_read_XXX` macros are defined before enabling `PROGMEM`.
|
||||||
|
|
||||||
|
v6.17.1 (2020-11-07)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed error `ambiguous overload for 'operator|'` (issue #1411)
|
||||||
|
* Fixed `operator|(MemberProxy, JsonObject)` (issue #1415)
|
||||||
|
* Allowed more than 32767 values in non-embedded mode (issue #1414)
|
||||||
|
|
||||||
|
v6.17.0 (2020-10-19)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Added a build failure when nullptr is defined as a macro (issue #1355)
|
||||||
|
* Added `JsonDocument::overflowed()` which tells if the memory pool was too small (issue #1358)
|
||||||
|
* Added `DeserializationError::EmptyInput` which tells if the input was empty
|
||||||
|
* Added `DeserializationError::f_str()` which returns a `const __FlashStringHelper*` (issue #846)
|
||||||
|
* Added `operator|(JsonVariantConst, JsonVariantConst)`
|
||||||
|
* Added filtering for MessagePack (issue #1298, PR #1394 by Luca Passarella)
|
||||||
|
* Moved float convertion tables to PROGMEM
|
||||||
|
* Fixed `JsonVariant::set((char*)0)` which returned false instead of true (issue #1368)
|
||||||
|
* Fixed error `No such file or directory #include <WString.h>` (issue #1381)
|
||||||
|
|
||||||
|
v6.16.1 (2020-08-04)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed `deserializeJson()` that stopped reading after `{}` (issue #1335)
|
||||||
|
|
||||||
|
v6.16.0 (2020-08-01)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Added comparisons (`>`, `>=`, `==`, `!=`, `<`, and `<=`) between `JsonVariant`s
|
||||||
|
* Added string deduplication (issue #1303)
|
||||||
|
* Added `JsonString::operator!=`
|
||||||
|
* Added wildcard key (`*`) for filters (issue #1309)
|
||||||
|
* Set `ARDUINOJSON_DECODE_UNICODE` to `1` by default
|
||||||
|
* Fixed `copyArray()` not working with `String`, `ElementProxy`, and `MemberProxy`
|
||||||
|
* Fixed error `getOrAddElement is not a member of ElementProxy` (issue #1311)
|
||||||
|
* Fixed excessive stack usage when compiled with `-Og` (issues #1210 and #1314)
|
||||||
|
* Fixed `Warning[Pa093]: implicit conversion from floating point to integer` on IAR compiler (PR #1328 by @stawiski)
|
||||||
|
|
||||||
|
v6.15.2 (2020-05-15)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* CMake: don't build tests when imported in another project
|
||||||
|
* CMake: made project arch-independent
|
||||||
|
* Visual Studio: fixed error C2766 with flag `/Zc:__cplusplus` (issue #1250)
|
||||||
|
* Added support for `JsonDocument` to `copyArray()` (issue #1255)
|
||||||
|
* Added support for `enum`s in `as<T>()` and `is<T>()` (issue #1256)
|
||||||
|
* Added `JsonVariant` as an input type for `deserializeXxx()`
|
||||||
|
For example, you can do: `deserializeJson(doc2, doc1["payload"])`
|
||||||
|
* Break the build if using 64-bit integers with ARDUINOJSON_USE_LONG_LONG==0
|
||||||
|
|
||||||
|
v6.15.1 (2020-04-08)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed "maybe-uninitialized" warning (issue #1217)
|
||||||
|
* Fixed "statement is unreachable" warning on IAR (issue #1233)
|
||||||
|
* Fixed "pointless integer comparison" warning on IAR (issue #1233)
|
||||||
|
* Added CMake "install" target (issue #1209)
|
||||||
|
* Disabled alignment on AVR (issue #1231)
|
||||||
|
|
||||||
|
v6.15.0 (2020-03-22)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Added `DeserializationOption::Filter` (issue #959)
|
||||||
|
* Added example `JsonFilterExample.ino`
|
||||||
|
* Changed the array subscript operator to automatically add missing elements
|
||||||
|
* Fixed "deprecated-copy" warning on GCC 9 (fixes #1184)
|
||||||
|
* Fixed `MemberProxy::set(char[])` not duplicating the string (issue #1191)
|
||||||
|
* Fixed enums serialized as booleans (issue #1197)
|
||||||
|
* Fixed incorrect string comparison on some platforms (issue #1198)
|
||||||
|
* Added move-constructor and move-assignment to `BasicJsonDocument`
|
||||||
|
* Added `BasicJsonDocument::garbageCollect()` (issue #1195)
|
||||||
|
* Added `StaticJsonDocument::garbageCollect()`
|
||||||
|
* Changed copy-constructor of `BasicJsonDocument` to preserve the capacity of the source.
|
||||||
|
* Removed copy-constructor of `JsonDocument` (issue #1189)
|
||||||
|
|
||||||
|
> ### BREAKING CHANGES
|
||||||
|
>
|
||||||
|
> #### Copy-constructor of `BasicJsonDocument`
|
||||||
|
>
|
||||||
|
> In previous versions, the copy constructor of `BasicJsonDocument` looked at the source's `memoryUsage()` to choose its capacity.
|
||||||
|
> Now, the copy constructor of `BasicJsonDocument` uses the same capacity as the source.
|
||||||
|
>
|
||||||
|
> Example:
|
||||||
>
|
>
|
||||||
> ```c++
|
> ```c++
|
||||||
> // ArduinoJson 6
|
> DynamicJsonDocument doc1(64);
|
||||||
> obj.createNestedArray("array");
|
> doc1.set(String("example"));
|
||||||
> obj.createNestedObject("object");
|
|
||||||
>
|
>
|
||||||
> // ArduinoJson 7
|
> DynamicJsonDocument doc2 = doc1;
|
||||||
> obj["array"].to<JsonArray>();
|
> Serial.print(doc2.capacity()); // 8 with ArduinoJson 6.14
|
||||||
> obj["object"].to<JsonObject>();
|
> // 64 with ArduinoJson 6.15
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> I made this change to get consistent results between copy-constructor and move-constructor, and whether RVO applies or not.
|
||||||
|
>
|
||||||
|
> If you use the copy-constructor to optimize your documents, you can use `garbageCollect()` or `shrinkToFit()` instead.
|
||||||
|
>
|
||||||
|
> #### Copy-constructor of `JsonDocument`
|
||||||
|
>
|
||||||
|
> In previous versions, it was possible to create a function that take a `JsonDocument` by value.
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> void myFunction(JsonDocument doc) {}
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> This function gives the wrong clues because it doesn't receive a copy of the `JsonDocument`, only a sliced version.
|
||||||
|
> It worked because the copy constructor copied the internal pointers, but it was an accident.
|
||||||
|
>
|
||||||
|
> From now, if you need to pass a `JsonDocument` to a function, you must use a reference:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> void myFunction(JsonDocument& doc) {}
|
||||||
|
> ```
|
||||||
|
|
||||||
|
v6.14.1 (2020-01-27)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed regression in UTF16 decoding (issue #1173)
|
||||||
|
* Fixed `containsKey()` on `JsonVariantConst`
|
||||||
|
* Added `getElement()` and `getMember()` to `JsonVariantConst`
|
||||||
|
|
||||||
|
v6.14.0 (2020-01-16)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Added `BasicJsonDocument::shrinkToFit()`
|
||||||
|
* Added support of `uint8_t` for `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` (issue #1142)
|
||||||
|
* Added `ARDUINOJSON_ENABLE_COMMENTS` to enable support for comments (defaults to 0)
|
||||||
|
* Auto enable support for `std::string` and `std::stream` on modern compilers (issue #1156)
|
||||||
|
(No need to define `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_STD_STREAM` anymore)
|
||||||
|
* Improved decoding of UTF-16 surrogate pairs (PR #1157 by @kaysievers)
|
||||||
|
(ArduinoJson now produces standard UTF-8 instead of CESU-8)
|
||||||
|
* Added `measureJson`, `measureJsonPretty`, and `measureMsgPack` to `keywords.txt`
|
||||||
|
(This file is used for syntax highlighting in the Arduino IDE)
|
||||||
|
* Fixed `variant.is<nullptr_t>()`
|
||||||
|
* Fixed value returned by `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` when writing to a `String`
|
||||||
|
* Improved speed of `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` when writing to a `String`
|
||||||
|
|
||||||
|
> ### BREAKING CHANGES
|
||||||
|
>
|
||||||
|
> #### Comments
|
||||||
|
>
|
||||||
|
> Support for comments in input is now optional and disabled by default.
|
||||||
|
>
|
||||||
|
> If you need support for comments, you must defined `ARDUINOJSON_ENABLE_COMMENTS` to `1`; otherwise, you'll receive `InvalidInput` errors.
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> #define ARDUINOJSON_ENABLE_COMMENTS 1
|
||||||
|
> #include <ArduinoJson.h>
|
||||||
|
> ```
|
||||||
|
|
||||||
|
v6.13.0 (2019-11-01)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Added support for custom writer/reader classes (issue #1088)
|
||||||
|
* Added conversion from `JsonArray` and `JsonObject` to `bool`, to be consistent with `JsonVariant`
|
||||||
|
* Fixed `deserializeJson()` when input contains duplicate keys (issue #1095)
|
||||||
|
* Improved `deserializeMsgPack()` speed by reading several bytes at once
|
||||||
|
* Added detection of Atmel AVR8/GNU C Compiler (issue #1112)
|
||||||
|
* Fixed deserializer that stopped reading at the first `0xFF` (PR #1118 by @mikee47)
|
||||||
|
* Fixed dangling reference in copies of `MemberProxy` and `ElementProxy` (issue #1120)
|
||||||
|
|
||||||
|
v6.12.0 (2019-09-05)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Use absolute instead of relative includes (issue #1072)
|
||||||
|
* Changed `JsonVariant::as<bool>()` to return `true` for any non-null value (issue #1005)
|
||||||
|
* Moved ancillary files to `extras/` (issue #1011)
|
||||||
|
|
||||||
|
v6.11.5 (2019-08-23)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Added fallback implementations of `strlen_P()`, `strncmp_P()`, `strcmp_P()`, and `memcpy_P()` (issue #1073)
|
||||||
|
|
||||||
|
v6.11.4 (2019-08-12)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Added `measureJson()` to the `ArduinoJson` namespace (PR #1069 by @nomis)
|
||||||
|
* Added support for `basic_string<char, traits, allocator>` (issue #1045)
|
||||||
|
* Fixed example `JsonConfigFile.ino` for ESP8266
|
||||||
|
* Include `Arduino.h` if `ARDUINO` is defined (PR #1071 by @nomis)
|
||||||
|
|
||||||
|
v6.11.3 (2019-07-22)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Added operators `==` and `!=` for `JsonDocument`, `ElementProxy`, and `MemberProxy`
|
||||||
|
* Fixed comparison of `JsonVariant` when one contains a linked string and the other contains an owned string (issue #1051)
|
||||||
|
|
||||||
|
v6.11.2 (2019-07-08)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed assignment of `JsonDocument` to `JsonVariant` (issue #1023)
|
||||||
|
* Fix invalid conversion error on Particle Argon (issue #1035)
|
||||||
|
|
||||||
|
v6.11.1 (2019-06-21)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed `serialized()` not working with Flash strings (issue #1030)
|
||||||
|
|
||||||
|
v6.11.0 (2019-05-26)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed `deserializeJson()` silently accepting a `Stream*` (issue #978)
|
||||||
|
* Fixed invalid result from `operator|` (issue #981)
|
||||||
|
* Made `deserializeJson()` more picky about trailing characters (issue #980)
|
||||||
|
* Added `ARDUINOJSON_ENABLE_NAN` (default=0) to enable NaN in JSON (issue #973)
|
||||||
|
* Added `ARDUINOJSON_ENABLE_INFINITY` (default=0) to enable Infinity in JSON
|
||||||
|
* Removed implicit conversion in comparison operators (issue #998)
|
||||||
|
* Added lexicographical comparison for `JsonVariant`
|
||||||
|
* Added support for `nullptr` (issue #998)
|
||||||
|
|
||||||
|
> ### BREAKING CHANGES
|
||||||
|
>
|
||||||
|
> #### NaN and Infinity
|
||||||
|
>
|
||||||
|
> The JSON specification allows neither NaN not Infinity, but previous
|
||||||
|
> versions of ArduinoJson supported it. Now, ArduinoJson behaves like most
|
||||||
|
> other libraries: a NaN or and Infinity in the `JsonDocument`, becomes
|
||||||
|
> a `null` in the output JSON. Also, `deserializeJson()` returns
|
||||||
|
> `InvalidInput` if the JSON document contains NaN or Infinity.
|
||||||
|
>
|
||||||
|
> This version still supports NaN and Infinity in JSON documents, but
|
||||||
|
> it's disabled by default to be compatible with other JSON parsers.
|
||||||
|
> If you need the old behavior back, define `ARDUINOJSON_ENABLE_NAN` and
|
||||||
|
> `ARDUINOJSON_ENABLE_INFINITY` to `1`;:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> #define ARDUINOJSON_ENABLE_NAN 1
|
||||||
|
> #define ARDUINOJSON_ENABLE_INFINITY 1
|
||||||
|
> #include <ArduinoJson.h>
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> #### The "or" operator
|
||||||
|
>
|
||||||
|
> This version slightly changes the behavior of the | operator when the
|
||||||
|
> variant contains a float and the user requests an integer.
|
||||||
|
>
|
||||||
|
> Older versions returned the floating point value truncated.
|
||||||
|
> Now, it returns the default value.
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> // suppose variant contains 1.2
|
||||||
|
> int value = variant | 3;
|
||||||
|
>
|
||||||
|
> // old behavior:
|
||||||
|
> value == 1
|
||||||
|
>
|
||||||
|
> // new behavior
|
||||||
|
> value == 3
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> If you need the old behavior, you must add `if (variant.is<float>())`.
|
||||||
|
|
||||||
|
v6.10.1 (2019-04-23)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed error "attributes are not allowed on a function-definition"
|
||||||
|
* Fixed `deserializeJson()` not being picky enough (issue #969)
|
||||||
|
* Fixed error "no matching function for call to write(uint8_t)" (issue #972)
|
||||||
|
|
||||||
|
v6.10.0 (2019-03-22)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed an integer overflow in the JSON deserializer
|
||||||
|
* Added overflow handling in `JsonVariant::as<T>()` and `JsonVariant::is<T>()`.
|
||||||
|
- `as<T>()` returns `0` if the integer `T` overflows
|
||||||
|
- `is<T>()` returns `false` if the integer `T` overflows
|
||||||
|
* Added `BasicJsonDocument` to support custom allocator (issue #876)
|
||||||
|
* Added `JsonDocument::containsKey()` (issue #938)
|
||||||
|
* Added `JsonVariant::containsKey()`
|
||||||
|
|
||||||
|
v6.9.1 (2019-03-01)
|
||||||
|
------
|
||||||
|
|
||||||
|
* Fixed warning "unused variable" with GCC 4.4 (issue #912)
|
||||||
|
* Fixed warning "cast increases required alignment" (issue #914)
|
||||||
|
* Fixed warning "conversion may alter value" (issue #914)
|
||||||
|
* Fixed naming conflict with "CAPACITY" (issue #839)
|
||||||
|
* Muted warning "will change in GCC 7.1" (issue #914)
|
||||||
|
* Added a clear error message for `StaticJsonBuffer` and `DynamicJsonBuffer`
|
||||||
|
* Marked ArduinoJson.h as a "system header"
|
||||||
|
|
||||||
|
v6.9.0 (2019-02-26)
|
||||||
|
------
|
||||||
|
|
||||||
|
* Decode escaped Unicode characters like \u00DE (issue #304, PR #791)
|
||||||
|
Many thanks to Daniel Schulte (aka @trilader) who implemented this feature.
|
||||||
|
* Added option ARDUINOJSON_DECODE_UNICODE to enable it
|
||||||
|
* Converted `JsonArray::copyFrom()/copyTo()` to free functions `copyArray()`
|
||||||
|
* Renamed `JsonArray::copyFrom()` and `JsonObject::copyFrom()` to `set()`
|
||||||
|
* Renamed `JsonArray::get()` to `getElement()`
|
||||||
|
* Renamed `JsonArray::add()` (without arg) to `addElement()`
|
||||||
|
* Renamed `JsonObject::get()` to `getMember()`
|
||||||
|
* Renamed `JsonObject::getOrCreate()` to `getOrAddMember()`
|
||||||
|
* Fixed `JsonVariant::isNull()` not returning `true` after `set((char*)0)`
|
||||||
|
* Fixed segfault after `variant.set(serialized((char*)0))`
|
||||||
|
* Detect `IncompleteInput` in `false`, `true`, and `null`
|
||||||
|
* Added `JsonDocument::size()`
|
||||||
|
* Added `JsonDocument::remove()`
|
||||||
|
* Added `JsonVariant::clear()`
|
||||||
|
* Added `JsonVariant::remove()`
|
||||||
|
|
||||||
|
v6.8.0-beta (2019-01-30)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Import functions in the ArduinoJson namespace to get clearer errors
|
||||||
|
* Improved syntax highlighting in Arduino IDE
|
||||||
|
* Removed default capacity of `DynamicJsonDocument`
|
||||||
|
* `JsonArray::copyFrom()` accepts `JsonArrayConst`
|
||||||
|
* `JsonVariant::set()` accepts `JsonArrayConst` and `JsonObjectConst`
|
||||||
|
* `JsonDocument` was missing in the ArduinoJson namespace
|
||||||
|
* Added `memoryUsage()` to `JsonArray`, `JsonObject`, and `JsonVariant`
|
||||||
|
* Added `nesting()` to `JsonArray`, `JsonDocument`, `JsonObject`, and `JsonVariant`
|
||||||
|
* Replaced `JsonDocument::nestingLimit` with an additional parameter
|
||||||
|
to `deserializeJson()` and `deserializeMsgPack()`
|
||||||
|
* Fixed uninitialized variant in `JsonDocument`
|
||||||
|
* Fixed `StaticJsonDocument` copy constructor and copy assignment
|
||||||
|
* The copy constructor of `DynamicJsonDocument` chooses the capacity according to the memory usage of the source, not from the capacity of the source.
|
||||||
|
* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant`
|
||||||
|
* Added `JsonDocument::isNull()`
|
||||||
|
* Added `JsonDocument::operator[]`
|
||||||
|
* Added `ARDUINOJSON_TAB` to configure the indentation character
|
||||||
|
* Reduced the size of the pretty JSON serializer
|
||||||
|
* Added `add()`, `createNestedArray()` and `createNestedObject()` to `JsonVariant`
|
||||||
|
* `JsonVariant` automatically promotes to `JsonObject` or `JsonArray` on write.
|
||||||
|
Calling `JsonVariant::to<T>()` is not required anymore.
|
||||||
|
* `JsonDocument` now support the same operations as `JsonVariant`.
|
||||||
|
Calling `JsonDocument::as<T>()` is not required anymore.
|
||||||
|
* Fixed example `JsonHttpClient.ino`
|
||||||
|
* User can now use a `JsonString` as a key or a value
|
||||||
|
|
||||||
|
> ### BREAKING CHANGES
|
||||||
|
>
|
||||||
|
> #### `DynamicJsonDocument`'s constructor
|
||||||
|
>
|
||||||
|
> The parameter to the constructor of `DynamicJsonDocument` is now mandatory
|
||||||
|
>
|
||||||
|
> Old code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> DynamicJsonDocument doc;
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> New code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> DynamicJsonDocument doc(1024);
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> #### Nesting limit
|
||||||
|
>
|
||||||
|
> `JsonDocument::nestingLimit` was replaced with a new parameter to `deserializeJson()` and `deserializeMsgPack()`.
|
||||||
|
>
|
||||||
|
> Old code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> doc.nestingLimit = 15;
|
||||||
|
> deserializeJson(doc, input);
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> New code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> deserializeJson(doc, input, DeserializationOption::NestingLimit(15));
|
||||||
|
> ```
|
||||||
|
|
||||||
|
v6.7.0-beta (2018-12-07)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity.
|
||||||
|
* Restored the monotonic allocator because the code was getting too big
|
||||||
|
* Reduced the memory usage
|
||||||
|
* Reduced the code size
|
||||||
|
* Renamed `JsonKey` to `JsonString`
|
||||||
|
* Removed spurious files in the Particle library
|
||||||
|
|
||||||
|
v6.6.0-beta (2018-11-13)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Removed `JsonArray::is<T>(i)` and `JsonArray::set(i,v)`
|
||||||
|
* Removed `JsonObject::is<T>(k)` and `JsonObject::set(k,v)`
|
||||||
|
* Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)`
|
||||||
|
* Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)`
|
||||||
|
* Added `JSON_STRING_SIZE()`
|
||||||
|
* ~~Replacing or removing a value now releases the memory~~
|
||||||
|
* Added `DeserializationError::code()` to be used in switch statements (issue #846)
|
||||||
|
|
||||||
|
v6.5.0-beta (2018-10-13)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Added implicit conversion from `JsonArray` and `JsonObject` to `JsonVariant`
|
||||||
|
* Allow mixed configuration in compilation units (issue #809)
|
||||||
|
* Fixed object keys not being duplicated
|
||||||
|
* `JsonPair::key()` now returns a `JsonKey`
|
||||||
|
* Increased the default capacity of `DynamicJsonDocument`
|
||||||
|
* Fixed `JsonVariant::is<String>()` (closes #763)
|
||||||
|
* Added `JsonArrayConst`, `JsonObjectConst`, and `JsonVariantConst`
|
||||||
|
* Added copy-constructor and copy-assignment-operator for `JsonDocument` (issue #827)
|
||||||
|
|
||||||
|
v6.4.0-beta (2018-09-11)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Copy `JsonArray` and `JsonObject`, instead of storing pointers (issue #780)
|
||||||
|
* Added `JsonVariant::to<JsonArray>()` and `JsonVariant::to<JsonObject>()`
|
||||||
|
|
||||||
|
v6.3.0-beta (2018-08-31)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Implemented reference semantics for `JsonVariant`
|
||||||
|
* Replaced `JsonPair`'s `key` and `value` with `key()` and `value()`
|
||||||
|
* Fixed `serializeJson(obj[key], dst)` (issue #794)
|
||||||
|
|
||||||
|
> ### BREAKING CHANGES
|
||||||
|
>
|
||||||
|
> #### JsonVariant
|
||||||
|
>
|
||||||
|
> `JsonVariant` now has a semantic similar to `JsonObject` and `JsonArray`.
|
||||||
|
> It's a reference to a value stored in the `JsonDocument`.
|
||||||
|
> As a consequence, a `JsonVariant` cannot be used as a standalone variable anymore.
|
||||||
|
>
|
||||||
|
> Old code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> JsonVariant myValue = 42;
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> New code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> DynamicJsonDocument doc;
|
||||||
|
> JsonVariant myValue = doc.to<JsonVariant>();
|
||||||
|
> myValue.set(42);
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> #### JsonPair
|
||||||
|
>
|
||||||
|
> Old code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> for(JsonPair p : myObject) {
|
||||||
|
> Serial.println(p.key);
|
||||||
|
> Serial.println(p.value.as<int>());
|
||||||
|
> }
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> New code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> for(JsonPair p : myObject) {
|
||||||
|
> Serial.println(p.key());
|
||||||
|
> Serial.println(p.value().as<int>());
|
||||||
|
> }
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> CAUTION: the key is now read only!
|
||||||
|
|
||||||
|
v6.2.3-beta (2018-07-19)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Fixed exception when using Flash strings as object keys (issue #784)
|
||||||
|
|
||||||
|
v6.2.2-beta (2018-07-18)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Fixed `invalid application of 'sizeof' to incomplete type '__FlashStringHelper'` (issue #783)
|
||||||
|
* Fixed `char[]` not duplicated when passed to `JsonVariant::operator[]`
|
||||||
|
|
||||||
|
v6.2.1-beta (2018-07-17)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Fixed `JsonObject` not inserting keys of type `String` (issue #782)
|
||||||
|
|
||||||
|
v6.2.0-beta (2018-07-12)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Disabled lazy number deserialization (issue #772)
|
||||||
|
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
|
||||||
|
* Improved float serialization when `-fsingle-precision-constant` is used
|
||||||
|
* Renamed function `RawJson()` to `serialized()`
|
||||||
|
* `serializeMsgPack()` now supports values marked with `serialized()`
|
||||||
|
|
||||||
|
> ### BREAKING CHANGES
|
||||||
|
>
|
||||||
|
> #### Non quoted strings
|
||||||
|
>
|
||||||
|
> Non quoted strings are now forbidden in values, but they are still allowed in keys.
|
||||||
|
> For example, `{key:"value"}` is accepted, but `{key:value}` is not.
|
||||||
|
>
|
||||||
|
> #### Preformatted values
|
||||||
|
>
|
||||||
|
> Old code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> object["values"] = RawJson("[1,2,3,4]");
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> New code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> object["values"] = serialized("[1,2,3,4]");
|
||||||
|
> ```
|
||||||
|
|
||||||
|
v6.1.0-beta (2018-07-02)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Return `JsonArray` and `JsonObject` by value instead of reference (issue #309)
|
||||||
|
* Replaced `success()` with `isNull()`
|
||||||
|
|
||||||
|
> ### BREAKING CHANGES
|
||||||
|
>
|
||||||
|
> Old code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> JsonObject& obj = doc.to<JsonObject>();
|
||||||
|
> JsonArray& arr = obj.createNestedArray("key");
|
||||||
|
> if (!arr.success()) {
|
||||||
|
> Serial.println("Not enough memory");
|
||||||
|
> return;
|
||||||
|
> }
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> New code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> JsonObject obj = doc.to<JsonObject>();
|
||||||
|
> JsonArray arr = obj.createNestedArray("key");
|
||||||
|
> if (arr.isNull()) {
|
||||||
|
> Serial.println("Not enough memory");
|
||||||
|
> return;
|
||||||
|
> }
|
||||||
|
> ```
|
||||||
|
|
||||||
|
v6.0.1-beta (2018-06-11)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Fixed conflicts with `isnan()` and `isinf()` macros (issue #752)
|
||||||
|
|
||||||
|
v6.0.0-beta (2018-06-07)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Added `DynamicJsonDocument` and `StaticJsonDocument`
|
||||||
|
* Added `deserializeJson()`
|
||||||
|
* Added `serializeJson()` and `serializeJsonPretty()`
|
||||||
|
* Added `measureJson()` and `measureJsonPretty()`
|
||||||
|
* Added `serializeMsgPack()`, `deserializeMsgPack()` and `measureMsgPack()` (issue #358)
|
||||||
|
* Added example `MsgPackParser.ino` (issue #358)
|
||||||
|
* Added support for non zero-terminated strings (issue #704)
|
||||||
|
* Removed `JsonBuffer::parseArray()`, `parseObject()` and `parse()`
|
||||||
|
* Removed `JsonBuffer::createArray()` and `createObject()`
|
||||||
|
* Removed `printTo()` and `prettyPrintTo()`
|
||||||
|
* Removed `measureLength()` and `measurePrettyLength()`
|
||||||
|
* Removed all deprecated features
|
||||||
|
|
||||||
|
> ### BREAKING CHANGES
|
||||||
|
>
|
||||||
|
> #### Deserialization
|
||||||
|
>
|
||||||
|
> Old code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> DynamicJsonBuffer jb;
|
||||||
|
> JsonObject& obj = jb.parseObject(json);
|
||||||
|
> if (obj.success()) {
|
||||||
|
>
|
||||||
|
> }
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> New code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> DynamicJsonDocument doc;
|
||||||
|
> DeserializationError error = deserializeJson(doc, json);
|
||||||
|
> if (error) {
|
||||||
|
>
|
||||||
|
> }
|
||||||
|
> JsonObject& obj = doc.as<JsonObject>();
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> #### Serialization
|
||||||
|
>
|
||||||
|
> Old code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> DynamicJsonBuffer jb;
|
||||||
|
> JsonObject& obj = jb.createObject();
|
||||||
|
> obj["key"] = "value";
|
||||||
|
> obj.printTo(Serial);
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> New code:
|
||||||
|
>
|
||||||
|
> ```c++
|
||||||
|
> DynamicJsonDocument obj;
|
||||||
|
> JsonObject& obj = doc.to<JsonObject>();
|
||||||
|
> obj["key"] = "value";
|
||||||
|
> serializeJson(doc, Serial);
|
||||||
> ```
|
> ```
|
||||||
|
|||||||
2
lib/ArduinoJson/LICENSE.txt
Executable file → Normal file
2
lib/ArduinoJson/LICENSE.txt
Executable file → Normal file
@@ -1,7 +1,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
Copyright © 2014-2024, Benoit BLANCHON
|
Copyright © 2014-2023, Benoit BLANCHON
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|||||||
76
lib/ArduinoJson/README.md
Executable file → Normal file
76
lib/ArduinoJson/README.md
Executable file → Normal file
@@ -4,10 +4,13 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A7.x)
|
[](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A6.x)
|
||||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/7.x)
|
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
|
||||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
|
||||||
[](https://coveralls.io/github/bblanchon/ArduinoJson?branch=7.x)
|
[](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
|
||||||
|
[](https://www.ardu-badge.com/ArduinoJson/6.21.3)
|
||||||
|
[](https://registry.platformio.org/packages/libraries/bblanchon/ArduinoJson?version=6.21.3)
|
||||||
|
[](https://components.espressif.com/components/bblanchon/arduinojson)
|
||||||
[](https://github.com/bblanchon/ArduinoJson/stargazers)
|
[](https://github.com/bblanchon/ArduinoJson/stargazers)
|
||||||
[](https://github.com/sponsors/bblanchon)
|
[](https://github.com/sponsors/bblanchon)
|
||||||
|
|
||||||
@@ -15,28 +18,31 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* [JSON deserialization](https://arduinojson.org/v7/api/json/deserializejson/)
|
* [JSON deserialization](https://arduinojson.org/v6/api/json/deserializejson/)
|
||||||
* [Optionally decodes UTF-16 escape sequences to UTF-8](https://arduinojson.org/v7/api/config/decode_unicode/)
|
* [Optionally decodes UTF-16 escape sequences to UTF-8](https://arduinojson.org/v6/api/config/decode_unicode/)
|
||||||
* [Optionally supports comments in the input](https://arduinojson.org/v7/api/config/enable_comments/)
|
* [Optionally stores links to the input buffer (zero-copy)](https://arduinojson.org/v6/api/json/deserializejson/)
|
||||||
* [Optionally filters the input to keep only desired values](https://arduinojson.org/v7/api/json/deserializejson/#filtering)
|
* [Optionally supports comments in the input](https://arduinojson.org/v6/api/config/enable_comments/)
|
||||||
|
* [Optionally filters the input to keep only desired values](https://arduinojson.org/v6/api/json/deserializejson/#filtering)
|
||||||
* Supports single quotes as a string delimiter
|
* Supports single quotes as a string delimiter
|
||||||
* Compatible with [NDJSON](http://ndjson.org/) and [JSON Lines](https://jsonlines.org/)
|
* Compatible with [NDJSON](http://ndjson.org/) and [JSON Lines](https://jsonlines.org/)
|
||||||
* [JSON serialization](https://arduinojson.org/v7/api/json/serializejson/)
|
* [JSON serialization](https://arduinojson.org/v6/api/json/serializejson/)
|
||||||
* [Can write to a buffer or a stream](https://arduinojson.org/v7/api/json/serializejson/)
|
* [Can write to a buffer or a stream](https://arduinojson.org/v6/api/json/serializejson/)
|
||||||
* [Optionally indents the document (prettified JSON)](https://arduinojson.org/v7/api/json/serializejsonpretty/)
|
* [Optionally indents the document (prettified JSON)](https://arduinojson.org/v6/api/json/serializejsonpretty/)
|
||||||
* [MessagePack serialization](https://arduinojson.org/v7/api/msgpack/serializemsgpack/)
|
* [MessagePack serialization](https://arduinojson.org/v6/api/msgpack/serializemsgpack/)
|
||||||
* [MessagePack deserialization](https://arduinojson.org/v7/api/msgpack/deserializemsgpack/)
|
* [MessagePack deserialization](https://arduinojson.org/v6/api/msgpack/deserializemsgpack/)
|
||||||
* Efficient
|
* Efficient
|
||||||
* [Twice smaller than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/)
|
* [Twice smaller than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/)
|
||||||
* [Almost 10% faster than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/)
|
* [Almost 10% faster than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/)
|
||||||
* [Consumes roughly 10% less RAM than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/)
|
* [Consumes roughly 10% less RAM than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/)
|
||||||
|
* [Fixed memory allocation, no heap fragmentation](https://arduinojson.org/v6/api/jsondocument/)
|
||||||
|
* [Optionally works without heap memory (zero malloc)](https://arduinojson.org/v6/api/staticjsondocument/)
|
||||||
* [Deduplicates strings](https://arduinojson.org/news/2020/08/01/version-6-16-0/)
|
* [Deduplicates strings](https://arduinojson.org/news/2020/08/01/version-6-16-0/)
|
||||||
* Versatile
|
* Versatile
|
||||||
* Supports [custom allocators (to use external RAM chip, for example)](https://arduinojson.org/v7/how-to/use-external-ram-on-esp32/)
|
* Supports [custom allocators (to use external RAM chip, for example)](https://arduinojson.org/v6/how-to/use-external-ram-on-esp32/)
|
||||||
* Supports [`String`](https://arduinojson.org/v7/api/config/enable_arduino_string/), [`std::string`](https://arduinojson.org/v7/api/config/enable_std_string/), and [`std::string_view`](https://arduinojson.org/v7/api/config/enable_string_view/)
|
* Supports [`String`](https://arduinojson.org/v6/api/config/enable_arduino_string/), [`std::string`](https://arduinojson.org/v6/api/config/enable_std_string/), and [`std::string_view`](https://arduinojson.org/v6/api/config/enable_string_view/)
|
||||||
* Supports [`Stream`](https://arduinojson.org/v7/api/config/enable_arduino_stream/) and [`std::istream`/`std::ostream`](https://arduinojson.org/v7/api/config/enable_std_stream/)
|
* Supports [`Stream`](https://arduinojson.org/v6/api/config/enable_arduino_stream/) and [`std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/)
|
||||||
* Supports [Flash strings](https://arduinojson.org/v7/api/config/enable_progmem/)
|
* Supports [Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/)
|
||||||
* Supports [custom readers](https://arduinojson.org/v7/api/json/deserializejson/#custom-reader) and [custom writers](https://arduinojson.org/v7/api/json/serializejson/#custom-writer)
|
* Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/#custom-writer)
|
||||||
* Supports [custom converters](https://arduinojson.org/news/2021/05/04/version-6-18-0/)
|
* Supports [custom converters](https://arduinojson.org/news/2021/05/04/version-6-18-0/)
|
||||||
* Portable
|
* Portable
|
||||||
* Usable on any C++ project (not limited to Arduino)
|
* Usable on any C++ project (not limited to Arduino)
|
||||||
@@ -66,29 +72,29 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
|||||||
* [Visual Micro](http://www.visualmicro.com/)
|
* [Visual Micro](http://www.visualmicro.com/)
|
||||||
* [Visual Studio](https://www.visualstudio.com/)
|
* [Visual Studio](https://www.visualstudio.com/)
|
||||||
* [Even works with online compilers like wandbox.org](https://wandbox.org/permlink/RlZSKy17DjJ6HcdN)
|
* [Even works with online compilers like wandbox.org](https://wandbox.org/permlink/RlZSKy17DjJ6HcdN)
|
||||||
* [CMake friendly](https://arduinojson.org/v7/how-to/use-arduinojson-with-cmake/)
|
* [CMake friendly](https://arduinojson.org/v6/how-to/use-arduinojson-with-cmake/)
|
||||||
* Well designed
|
* Well designed
|
||||||
* [Elegant API](http://arduinojson.org/v7/example/)
|
* [Elegant API](http://arduinojson.org/v6/example/)
|
||||||
* [Thread-safe](https://en.wikipedia.org/wiki/Thread_safety)
|
* [Thread-safe](https://en.wikipedia.org/wiki/Thread_safety)
|
||||||
* Self-contained (no external dependency)
|
* Self-contained (no external dependency)
|
||||||
* `const` friendly
|
* `const` friendly
|
||||||
* [`for` friendly](https://arduinojson.org/v7/api/jsonobject/begin_end/)
|
* [`for` friendly](https://arduinojson.org/v6/api/jsonobject/begin_end/)
|
||||||
* [TMP friendly](https://en.wikipedia.org/wiki/Template_metaprogramming)
|
* [TMP friendly](https://en.wikipedia.org/wiki/Template_metaprogramming)
|
||||||
* Handles [integer overflows](https://arduinojson.org/v7/api/jsonvariant/as/#integer-overflows)
|
* Handles [integer overflows](https://arduinojson.org/v6/api/jsonvariant/as/#integer-overflows)
|
||||||
* Well tested
|
* Well tested
|
||||||
* [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=7.x)
|
* [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
|
||||||
* Continuously tested on
|
* Continuously tested on
|
||||||
* [Visual Studio 2017, 2019, 2022](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/7.x)
|
* [Visual Studio 2017, 2019, 2022](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
|
||||||
* [GCC 4.8, 5, 6, 7, 8, 9, 10, 11, 12](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22)
|
* [GCC 5, 6, 7, 8, 9, 10, 11](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22)
|
||||||
* [Clang 3.9, 4.0, 5.0, 6.0, 7, 8, 9, 10, 11, 12, 13, 14, 15](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22)
|
* [Clang 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/)
|
* 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/v7/doc/deserialization/)
|
* [Tutorials](https://arduinojson.org/v6/doc/deserialization/)
|
||||||
* [Examples](https://arduinojson.org/v7/example/)
|
* [Examples](https://arduinojson.org/v6/example/)
|
||||||
* [How-tos](https://arduinojson.org/v7/example/)
|
* [How-tos](https://arduinojson.org/v6/example/)
|
||||||
* [FAQ](https://arduinojson.org/v7/faq/)
|
* [FAQ](https://arduinojson.org/v6/faq/)
|
||||||
* [Troubleshooter](https://arduinojson.org/v7/troubleshooter/)
|
* [Troubleshooter](https://arduinojson.org/v6/troubleshooter/)
|
||||||
* [Book](https://arduinojson.org/book/)
|
* [Book](https://arduinojson.org/book/)
|
||||||
* [Changelog](CHANGELOG.md)
|
* [Changelog](CHANGELOG.md)
|
||||||
* Vibrant user community
|
* Vibrant user community
|
||||||
@@ -103,9 +109,9 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
|||||||
Here is a program that parses a JSON document with ArduinoJson.
|
Here is a program that parses a JSON document with ArduinoJson.
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
const char* json = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||||
|
|
||||||
JsonDocument doc;
|
DynamicJsonDocument doc(1024);
|
||||||
deserializeJson(doc, json);
|
deserializeJson(doc, json);
|
||||||
|
|
||||||
const char* sensor = doc["sensor"];
|
const char* sensor = doc["sensor"];
|
||||||
@@ -114,14 +120,14 @@ double latitude = doc["data"][0];
|
|||||||
double longitude = doc["data"][1];
|
double longitude = doc["data"][1];
|
||||||
```
|
```
|
||||||
|
|
||||||
See the [tutorial on arduinojson.org](https://arduinojson.org/v7/doc/deserialization/)
|
See the [tutorial on arduinojson.org](https://arduinojson.org/v6/doc/deserialization/)
|
||||||
|
|
||||||
### Serialization
|
### Serialization
|
||||||
|
|
||||||
Here is a program that generates a JSON document with ArduinoJson:
|
Here is a program that generates a JSON document with ArduinoJson:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
JsonDocument doc;
|
DynamicJsonDocument doc(1024);
|
||||||
|
|
||||||
doc["sensor"] = "gps";
|
doc["sensor"] = "gps";
|
||||||
doc["time"] = 1351824120;
|
doc["time"] = 1351824120;
|
||||||
@@ -133,7 +139,7 @@ serializeJson(doc, Serial);
|
|||||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||||
```
|
```
|
||||||
|
|
||||||
See the [tutorial on arduinojson.org](https://arduinojson.org/v7/doc/serialization/)
|
See the [tutorial on arduinojson.org](https://arduinojson.org/v6/doc/serialization/)
|
||||||
|
|
||||||
## Sponsors
|
## Sponsors
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
# ArduinoJson Support
|
|
||||||
|
|
||||||
First off, thank you very much for using ArduinoJson.
|
|
||||||
|
|
||||||
We'll be very happy to help you, but first please read the following.
|
|
||||||
|
|
||||||
## Before asking for help
|
|
||||||
|
|
||||||
1. Read the [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=support)
|
|
||||||
2. Search in the [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=support)
|
|
||||||
|
|
||||||
If you did not find the answer, please create a [new issue on GitHub](https://github.com/bblanchon/ArduinoJson/issues/new).
|
|
||||||
|
|
||||||
It is OK to add a comment to a currently opened issue, but please avoid adding comments to a closed issue.
|
|
||||||
|
|
||||||
## Before hitting the Submit button
|
|
||||||
|
|
||||||
Please provide all the relevant information:
|
|
||||||
|
|
||||||
* Good title
|
|
||||||
* Short description of the problem
|
|
||||||
* Target platform
|
|
||||||
* Compiler model and version
|
|
||||||
* [MVCE](https://stackoverflow.com/help/mcve)
|
|
||||||
* Compiler output
|
|
||||||
|
|
||||||
Good questions get fast answers!
|
|
||||||
40
lib/ArduinoJson/keywords.txt
Normal file
40
lib/ArduinoJson/keywords.txt
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Macros
|
||||||
|
JSON_ARRAY_SIZE KEYWORD2
|
||||||
|
JSON_OBJECT_SIZE KEYWORD2
|
||||||
|
JSON_STRING_SIZE KEYWORD2
|
||||||
|
|
||||||
|
# Free functions
|
||||||
|
deserializeJson KEYWORD2
|
||||||
|
deserializeMsgPack KEYWORD2
|
||||||
|
serialized KEYWORD2
|
||||||
|
serializeJson KEYWORD2
|
||||||
|
serializeJsonPretty KEYWORD2
|
||||||
|
serializeMsgPack KEYWORD2
|
||||||
|
measureJson KEYWORD2
|
||||||
|
measureJsonPretty KEYWORD2
|
||||||
|
measureMsgPack KEYWORD2
|
||||||
|
|
||||||
|
# Methods
|
||||||
|
add KEYWORD2
|
||||||
|
as KEYWORD2
|
||||||
|
createNestedArray KEYWORD2
|
||||||
|
createNestedObject KEYWORD2
|
||||||
|
get KEYWORD2
|
||||||
|
set KEYWORD2
|
||||||
|
to KEYWORD2
|
||||||
|
|
||||||
|
# Type names
|
||||||
|
DeserializationError KEYWORD1 DATA_TYPE
|
||||||
|
DynamicJsonDocument KEYWORD1 DATA_TYPE
|
||||||
|
JsonArray KEYWORD1 DATA_TYPE
|
||||||
|
JsonArrayConst KEYWORD1 DATA_TYPE
|
||||||
|
JsonDocument KEYWORD1 DATA_TYPE
|
||||||
|
JsonFloat KEYWORD1 DATA_TYPE
|
||||||
|
JsonInteger KEYWORD1 DATA_TYPE
|
||||||
|
JsonObject KEYWORD1 DATA_TYPE
|
||||||
|
JsonObjectConst KEYWORD1 DATA_TYPE
|
||||||
|
JsonString KEYWORD1 DATA_TYPE
|
||||||
|
JsonUInt KEYWORD1 DATA_TYPE
|
||||||
|
JsonVariant KEYWORD1 DATA_TYPE
|
||||||
|
JsonVariantConst KEYWORD1 DATA_TYPE
|
||||||
|
StaticJsonDocument KEYWORD1 DATA_TYPE
|
||||||
11
lib/ArduinoJson/library.properties
Normal file
11
lib/ArduinoJson/library.properties
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
name=ArduinoJson
|
||||||
|
version=6.21.3
|
||||||
|
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||||
|
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||||
|
sentence=A simple and efficient JSON library for embedded C++.
|
||||||
|
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ MessagePack, ✔ fixed allocation, ✔ zero-copy, ✔ streams, ✔ filtering, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
|
||||||
|
category=Data Processing
|
||||||
|
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
|
||||||
|
architectures=*
|
||||||
|
repository=https://github.com/bblanchon/ArduinoJson.git
|
||||||
|
license=MIT
|
||||||
2
lib/ArduinoJson/src/ArduinoJson.h
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson.h
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
13
lib/ArduinoJson/src/ArduinoJson.hpp
Executable file → Normal file
13
lib/ArduinoJson/src/ArduinoJson.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -30,19 +30,18 @@
|
|||||||
#include "ArduinoJson/Object/JsonObject.hpp"
|
#include "ArduinoJson/Object/JsonObject.hpp"
|
||||||
#include "ArduinoJson/Variant/JsonVariantConst.hpp"
|
#include "ArduinoJson/Variant/JsonVariantConst.hpp"
|
||||||
|
|
||||||
#include "ArduinoJson/Document/JsonDocument.hpp"
|
#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
|
||||||
|
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
|
||||||
|
|
||||||
#include "ArduinoJson/Array/ArrayImpl.hpp"
|
|
||||||
#include "ArduinoJson/Array/ElementProxy.hpp"
|
#include "ArduinoJson/Array/ElementProxy.hpp"
|
||||||
|
#include "ArduinoJson/Array/JsonArrayImpl.hpp"
|
||||||
#include "ArduinoJson/Array/Utilities.hpp"
|
#include "ArduinoJson/Array/Utilities.hpp"
|
||||||
#include "ArduinoJson/Collection/CollectionImpl.hpp"
|
#include "ArduinoJson/Collection/CollectionImpl.hpp"
|
||||||
#include "ArduinoJson/Memory/VariantPoolImpl.hpp"
|
#include "ArduinoJson/Object/JsonObjectImpl.hpp"
|
||||||
#include "ArduinoJson/Object/MemberProxy.hpp"
|
#include "ArduinoJson/Object/MemberProxy.hpp"
|
||||||
#include "ArduinoJson/Object/ObjectImpl.hpp"
|
|
||||||
#include "ArduinoJson/Variant/ConverterImpl.hpp"
|
#include "ArduinoJson/Variant/ConverterImpl.hpp"
|
||||||
#include "ArduinoJson/Variant/JsonVariantCopier.hpp"
|
|
||||||
#include "ArduinoJson/Variant/VariantCompare.hpp"
|
#include "ArduinoJson/Variant/VariantCompare.hpp"
|
||||||
#include "ArduinoJson/Variant/VariantRefBaseImpl.hpp"
|
#include "ArduinoJson/Variant/VariantImpl.hpp"
|
||||||
|
|
||||||
#include "ArduinoJson/Json/JsonDeserializer.hpp"
|
#include "ArduinoJson/Json/JsonDeserializer.hpp"
|
||||||
#include "ArduinoJson/Json/JsonSerializer.hpp"
|
#include "ArduinoJson/Json/JsonSerializer.hpp"
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Collection/CollectionData.hpp>
|
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|
||||||
|
|
||||||
class ArrayData : public CollectionData {
|
|
||||||
public:
|
|
||||||
VariantData* addElement(ResourceManager* resources) {
|
|
||||||
return addSlot(resources).data();
|
|
||||||
}
|
|
||||||
|
|
||||||
static VariantData* addElement(ArrayData* array, ResourceManager* resources) {
|
|
||||||
if (!array)
|
|
||||||
return nullptr;
|
|
||||||
return array->addElement(resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantData* getOrAddElement(size_t index, ResourceManager* resources);
|
|
||||||
|
|
||||||
VariantData* getElement(size_t index, const ResourceManager* resources) const;
|
|
||||||
|
|
||||||
static VariantData* getElement(const ArrayData* array, size_t index,
|
|
||||||
const ResourceManager* resources) {
|
|
||||||
if (!array)
|
|
||||||
return nullptr;
|
|
||||||
return array->getElement(index, resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeElement(size_t index, ResourceManager* resources);
|
|
||||||
|
|
||||||
static void removeElement(ArrayData* array, size_t index,
|
|
||||||
ResourceManager* resources) {
|
|
||||||
if (!array)
|
|
||||||
return;
|
|
||||||
array->removeElement(index, resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool copyFrom(const ArrayData& src, ResourceManager* resources);
|
|
||||||
|
|
||||||
static bool copy(ArrayData* dst, const ArrayData* src,
|
|
||||||
ResourceManager* resources) {
|
|
||||||
if (!dst || !src)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return dst->copyFrom(*src, resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
iterator at(size_t index, const ResourceManager* resources) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Array/ArrayData.hpp>
|
|
||||||
#include <ArduinoJson/Variant/VariantCompare.hpp>
|
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|
||||||
|
|
||||||
inline ArrayData::iterator ArrayData::at(
|
|
||||||
size_t index, const ResourceManager* resources) const {
|
|
||||||
auto it = createIterator(resources);
|
|
||||||
while (!it.done() && index) {
|
|
||||||
it.next(resources);
|
|
||||||
--index;
|
|
||||||
}
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline VariantData* ArrayData::getOrAddElement(size_t index,
|
|
||||||
ResourceManager* resources) {
|
|
||||||
auto it = createIterator(resources);
|
|
||||||
while (!it.done() && index > 0) {
|
|
||||||
it.next(resources);
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
if (it.done())
|
|
||||||
index++;
|
|
||||||
VariantData* element = it.data();
|
|
||||||
while (index > 0) {
|
|
||||||
element = addElement(resources);
|
|
||||||
if (!element)
|
|
||||||
return nullptr;
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline VariantData* ArrayData::getElement(
|
|
||||||
size_t index, const ResourceManager* resources) const {
|
|
||||||
return at(index, resources).data();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ArrayData::removeElement(size_t index, ResourceManager* resources) {
|
|
||||||
remove(at(index, resources), resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
|
||||||
27
lib/ArduinoJson/src/ArduinoJson/Array/ElementProxy.hpp
Executable file → Normal file
27
lib/ArduinoJson/src/ArduinoJson/Array/ElementProxy.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
// A proxy class to get or set an element of an array.
|
// A proxy class to get or set an element of an array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/subscript/
|
// https://arduinojson.org/v6/api/jsonarray/subscript/
|
||||||
template <typename TUpstream>
|
template <typename TUpstream>
|
||||||
class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
|
class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
|
||||||
public VariantOperators<ElementProxy<TUpstream>> {
|
public VariantOperators<ElementProxy<TUpstream>> {
|
||||||
@@ -22,40 +22,35 @@ class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
|
|||||||
ElementProxy(const ElementProxy& src)
|
ElementProxy(const ElementProxy& src)
|
||||||
: upstream_(src.upstream_), index_(src.index_) {}
|
: upstream_(src.upstream_), index_(src.index_) {}
|
||||||
|
|
||||||
ElementProxy& operator=(const ElementProxy& src) {
|
FORCE_INLINE ElementProxy& operator=(const ElementProxy& src) {
|
||||||
this->set(src);
|
this->set(src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
ElementProxy& operator=(const T& src) {
|
FORCE_INLINE ElementProxy& operator=(const T& src) {
|
||||||
this->set(src);
|
this->set(src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
ElementProxy& operator=(T* src) {
|
FORCE_INLINE ElementProxy& operator=(T* src) {
|
||||||
this->set(src);
|
this->set(src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResourceManager* getResourceManager() const {
|
FORCE_INLINE MemoryPool* getPool() const {
|
||||||
return VariantAttorney::getResourceManager(upstream_);
|
return VariantAttorney::getPool(upstream_);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE VariantData* getData() const {
|
FORCE_INLINE VariantData* getData() const {
|
||||||
return VariantData::getElement(
|
return variantGetElement(VariantAttorney::getData(upstream_), index_);
|
||||||
VariantAttorney::getData(upstream_), index_,
|
|
||||||
VariantAttorney::getResourceManager(upstream_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantData* getOrCreateData() const {
|
FORCE_INLINE VariantData* getOrCreateData() const {
|
||||||
auto data = VariantAttorney::getOrCreateData(upstream_);
|
return variantGetOrAddElement(VariantAttorney::getOrCreateData(upstream_),
|
||||||
if (!data)
|
index_, VariantAttorney::getPool(upstream_));
|
||||||
return nullptr;
|
|
||||||
return data->getOrAddElement(
|
|
||||||
index_, VariantAttorney::getResourceManager(upstream_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TUpstream upstream_;
|
TUpstream upstream_;
|
||||||
|
|||||||
201
lib/ArduinoJson/src/ArduinoJson/Array/JsonArray.hpp
Executable file → Normal file
201
lib/ArduinoJson/src/ArduinoJson/Array/JsonArray.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -12,7 +12,7 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
class JsonObject;
|
class JsonObject;
|
||||||
|
|
||||||
// A reference to an array in a JsonDocument
|
// A reference to an array in a JsonDocument
|
||||||
// https://arduinojson.org/v7/api/jsonarray/
|
// https://arduinojson.org/v6/api/jsonarray/
|
||||||
class JsonArray : public detail::VariantOperators<JsonArray> {
|
class JsonArray : public detail::VariantOperators<JsonArray> {
|
||||||
friend class detail::VariantAttorney;
|
friend class detail::VariantAttorney;
|
||||||
|
|
||||||
@@ -20,165 +20,155 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
typedef JsonArrayIterator iterator;
|
typedef JsonArrayIterator iterator;
|
||||||
|
|
||||||
// Constructs an unbound reference.
|
// Constructs an unbound reference.
|
||||||
JsonArray() : data_(0), resources_(0) {}
|
FORCE_INLINE JsonArray() : data_(0), pool_(0) {}
|
||||||
|
|
||||||
// INTERNAL USE ONLY
|
// INTERNAL USE ONLY
|
||||||
JsonArray(detail::ArrayData* data, detail::ResourceManager* resources)
|
FORCE_INLINE JsonArray(detail::MemoryPool* pool, detail::CollectionData* data)
|
||||||
: data_(data), resources_(resources) {}
|
: data_(data), pool_(pool) {}
|
||||||
|
|
||||||
// Returns a JsonVariant pointing to the array.
|
// Returns a JsonVariant pointing to the array.
|
||||||
// https://arduinojson.org/v7/api/jsonvariant/
|
// https://arduinojson.org/v6/api/jsonvariant/
|
||||||
operator JsonVariant() {
|
operator JsonVariant() {
|
||||||
void* data = data_; // prevent warning cast-align
|
void* data = data_; // prevent warning cast-align
|
||||||
return JsonVariant(reinterpret_cast<detail::VariantData*>(data),
|
return JsonVariant(pool_, reinterpret_cast<detail::VariantData*>(data));
|
||||||
resources_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a read-only reference to the array.
|
// Returns a read-only reference to the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarrayconst/
|
// https://arduinojson.org/v6/api/jsonarrayconst/
|
||||||
operator JsonArrayConst() const {
|
operator JsonArrayConst() const {
|
||||||
return JsonArrayConst(data_, resources_);
|
return JsonArrayConst(data_);
|
||||||
}
|
|
||||||
|
|
||||||
// Appends a new (empty) element to the array.
|
|
||||||
// Returns a reference to the new element.
|
|
||||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
|
||||||
template <typename T>
|
|
||||||
typename detail::enable_if<!detail::is_same<T, JsonVariant>::value, T>::type
|
|
||||||
add() const {
|
|
||||||
return add<JsonVariant>().to<T>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a new (null) element to the array.
|
// Appends a new (null) element to the array.
|
||||||
// Returns a reference to the new element.
|
// Returns a reference to the new element.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
// https://arduinojson.org/v6/api/jsonarray/add/
|
||||||
template <typename T>
|
JsonVariant add() const {
|
||||||
typename detail::enable_if<detail::is_same<T, JsonVariant>::value, T>::type
|
if (!data_)
|
||||||
add() const {
|
return JsonVariant();
|
||||||
return JsonVariant(detail::ArrayData::addElement(data_, resources_),
|
return JsonVariant(pool_, data_->addElement(pool_));
|
||||||
resources_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a value to the array.
|
// Appends a value to the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
// https://arduinojson.org/v6/api/jsonarray/add/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool add(const T& value) const {
|
FORCE_INLINE bool add(const T& value) const {
|
||||||
return add<JsonVariant>().set(value);
|
return add().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a value to the array.
|
// Appends a value to the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/add/
|
// https://arduinojson.org/v6/api/jsonarray/add/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool add(T* value) const {
|
FORCE_INLINE bool add(T* value) const {
|
||||||
return add<JsonVariant>().set(value);
|
return add().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an iterator to the first element of the array.
|
// Returns an iterator to the first element of the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/begin/
|
// https://arduinojson.org/v6/api/jsonarray/begin/
|
||||||
iterator begin() const {
|
FORCE_INLINE iterator begin() const {
|
||||||
if (!data_)
|
if (!data_)
|
||||||
return iterator();
|
return iterator();
|
||||||
return iterator(data_->createIterator(resources_), resources_);
|
return iterator(pool_, data_->head());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an iterator following the last element of the array.
|
// Returns an iterator following the last element of the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/end/
|
// https://arduinojson.org/v6/api/jsonarray/end/
|
||||||
iterator end() const {
|
FORCE_INLINE iterator end() const {
|
||||||
return iterator();
|
return iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies an array.
|
// Copies an array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/set/
|
// https://arduinojson.org/v6/api/jsonarray/set/
|
||||||
bool set(JsonArrayConst src) const {
|
FORCE_INLINE bool set(JsonArrayConst src) const {
|
||||||
if (!data_)
|
if (!data_ || !src.data_)
|
||||||
return false;
|
return false;
|
||||||
|
return data_->copyFrom(*src.data_, pool_);
|
||||||
|
}
|
||||||
|
|
||||||
clear();
|
// Compares the content of two arrays.
|
||||||
for (auto element : src) {
|
FORCE_INLINE bool operator==(JsonArray rhs) const {
|
||||||
if (!add(element))
|
return JsonArrayConst(data_) == JsonArrayConst(rhs.data_);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the element at the specified iterator.
|
// Removes the element at the specified iterator.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/remove/
|
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||||
void remove(iterator it) const {
|
// https://arduinojson.org/v6/api/jsonarray/remove/
|
||||||
detail::ArrayData::remove(data_, it.iterator_, resources_);
|
FORCE_INLINE void remove(iterator it) const {
|
||||||
|
if (!data_)
|
||||||
|
return;
|
||||||
|
data_->removeSlot(it.slot_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the element at the specified index.
|
// Removes the element at the specified index.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/remove/
|
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||||
void remove(size_t index) const {
|
// https://arduinojson.org/v6/api/jsonarray/remove/
|
||||||
detail::ArrayData::removeElement(data_, index, resources_);
|
FORCE_INLINE void remove(size_t index) const {
|
||||||
|
if (!data_)
|
||||||
|
return;
|
||||||
|
data_->removeElement(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes all the elements of the array.
|
// Removes all the elements of the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/clear/
|
// ⚠️ Doesn't release the memory associated with the removed elements.
|
||||||
|
// https://arduinojson.org/v6/api/jsonarray/clear/
|
||||||
void clear() const {
|
void clear() const {
|
||||||
detail::ArrayData::clear(data_, resources_);
|
if (!data_)
|
||||||
|
return;
|
||||||
|
data_->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets or sets the element at the specified index.
|
// Gets or sets the element at the specified index.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/subscript/
|
// https://arduinojson.org/v6/api/jsonarray/subscript/
|
||||||
detail::ElementProxy<JsonArray> operator[](size_t index) const {
|
FORCE_INLINE detail::ElementProxy<JsonArray> operator[](size_t index) const {
|
||||||
return {*this, index};
|
return {*this, index};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Creates an object and appends it to the array.
|
||||||
|
// https://arduinojson.org/v6/api/jsonarray/createnestedobject/
|
||||||
|
FORCE_INLINE JsonObject createNestedObject() const;
|
||||||
|
|
||||||
|
// Creates an array and appends it to the array.
|
||||||
|
// https://arduinojson.org/v6/api/jsonarray/createnestedarray/
|
||||||
|
FORCE_INLINE JsonArray createNestedArray() const {
|
||||||
|
return add().to<JsonArray>();
|
||||||
|
}
|
||||||
|
|
||||||
operator JsonVariantConst() const {
|
operator JsonVariantConst() const {
|
||||||
return JsonVariantConst(collectionToVariant(data_), resources_);
|
return JsonVariantConst(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is unbound.
|
// Returns true if the reference is unbound.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/isnull/
|
// https://arduinojson.org/v6/api/jsonarray/isnull/
|
||||||
bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
return data_ == 0;
|
return data_ == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is bound.
|
// Returns true if the reference is bound.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/isnull/
|
// https://arduinojson.org/v6/api/jsonarray/isnull/
|
||||||
operator bool() const {
|
FORCE_INLINE operator bool() const {
|
||||||
return data_ != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the number of bytes occupied by the array.
|
||||||
|
// https://arduinojson.org/v6/api/jsonarray/memoryusage/
|
||||||
|
FORCE_INLINE size_t memoryUsage() const {
|
||||||
|
return data_ ? data_->memoryUsage() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the array.
|
// Returns the depth (nesting level) of the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/nesting/
|
// https://arduinojson.org/v6/api/jsonarray/nesting/
|
||||||
size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
return detail::VariantData::nesting(collectionToVariant(data_), resources_);
|
return variantNesting(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of elements in the array.
|
// Returns the number of elements in the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarray/size/
|
// https://arduinojson.org/v6/api/jsonarray/size/
|
||||||
size_t size() const {
|
FORCE_INLINE size_t size() const {
|
||||||
return data_ ? data_->size(resources_) : 0;
|
return data_ ? data_->size() : 0;
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: use add<JsonVariant>() instead
|
|
||||||
ARDUINOJSON_DEPRECATED("use add<JsonVariant>() instead")
|
|
||||||
JsonVariant add() const {
|
|
||||||
return add<JsonVariant>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: use add<JsonArray>() instead
|
|
||||||
ARDUINOJSON_DEPRECATED("use add<JsonArray>() instead")
|
|
||||||
JsonArray createNestedArray() const {
|
|
||||||
return add<JsonArray>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: use add<JsonObject>() instead
|
|
||||||
ARDUINOJSON_DEPRECATED("use add<JsonObject>() instead")
|
|
||||||
JsonObject createNestedObject() const;
|
|
||||||
|
|
||||||
// DEPRECATED: always returns zero
|
|
||||||
ARDUINOJSON_DEPRECATED("always returns zero")
|
|
||||||
size_t memoryUsage() const {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::ResourceManager* getResourceManager() const {
|
detail::MemoryPool* getPool() const {
|
||||||
return resources_;
|
return pool_;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::VariantData* getData() const {
|
detail::VariantData* getData() const {
|
||||||
@@ -189,8 +179,33 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
return collectionToVariant(data_);
|
return collectionToVariant(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::ArrayData* data_;
|
detail::CollectionData* data_;
|
||||||
detail::ResourceManager* resources_;
|
detail::MemoryPool* pool_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Converter<JsonArray> : private detail::VariantAttorney {
|
||||||
|
static void toJson(JsonVariantConst src, JsonVariant dst) {
|
||||||
|
variantCopyFrom(getData(dst), getData(src), getPool(dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
static JsonArray fromJson(JsonVariant src) {
|
||||||
|
auto data = getData(src);
|
||||||
|
auto pool = getPool(src);
|
||||||
|
return JsonArray(pool, data != 0 ? data->asArray() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static detail::InvalidConversion<JsonVariantConst, JsonArray> fromJson(
|
||||||
|
JsonVariantConst);
|
||||||
|
|
||||||
|
static bool checkJson(JsonVariantConst) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool checkJson(JsonVariant src) {
|
||||||
|
auto data = getData(src);
|
||||||
|
return data && data->isArray();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
126
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayConst.hpp
Executable file → Normal file
126
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayConst.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -13,7 +13,7 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
class JsonObject;
|
class JsonObject;
|
||||||
|
|
||||||
// A read-only reference to an array in a JsonDocument
|
// A read-only reference to an array in a JsonDocument
|
||||||
// https://arduinojson.org/v7/api/jsonarrayconst/
|
// https://arduinojson.org/v6/api/jsonarrayconst/
|
||||||
class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
||||||
friend class JsonArray;
|
friend class JsonArray;
|
||||||
friend class detail::VariantAttorney;
|
friend class detail::VariantAttorney;
|
||||||
@@ -22,66 +22,89 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
|||||||
typedef JsonArrayConstIterator iterator;
|
typedef JsonArrayConstIterator iterator;
|
||||||
|
|
||||||
// Returns an iterator to the first element of the array.
|
// Returns an iterator to the first element of the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarrayconst/begin/
|
// https://arduinojson.org/v6/api/jsonarrayconst/begin/
|
||||||
iterator begin() const {
|
FORCE_INLINE iterator begin() const {
|
||||||
if (!data_)
|
if (!data_)
|
||||||
return iterator();
|
return iterator();
|
||||||
return iterator(data_->createIterator(resources_), resources_);
|
return iterator(data_->head());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an iterator to the element following the last element of the array.
|
// Returns an iterator to the element following the last element of the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarrayconst/end/
|
// https://arduinojson.org/v6/api/jsonarrayconst/end/
|
||||||
iterator end() const {
|
FORCE_INLINE iterator end() const {
|
||||||
return iterator();
|
return iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an unbound reference.
|
// Creates an unbound reference.
|
||||||
JsonArrayConst() : data_(0) {}
|
FORCE_INLINE JsonArrayConst() : data_(0) {}
|
||||||
|
|
||||||
// INTERNAL USE ONLY
|
// INTERNAL USE ONLY
|
||||||
JsonArrayConst(const detail::ArrayData* data,
|
FORCE_INLINE JsonArrayConst(const detail::CollectionData* data)
|
||||||
const detail::ResourceManager* resources)
|
: data_(data) {}
|
||||||
: data_(data), resources_(resources) {}
|
|
||||||
|
// Compares the content of two arrays.
|
||||||
|
// Returns true if the two arrays are equal.
|
||||||
|
FORCE_INLINE bool operator==(JsonArrayConst rhs) const {
|
||||||
|
if (data_ == rhs.data_)
|
||||||
|
return true;
|
||||||
|
if (!data_ || !rhs.data_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
iterator it1 = begin();
|
||||||
|
iterator it2 = rhs.begin();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
bool end1 = it1 == end();
|
||||||
|
bool end2 = it2 == rhs.end();
|
||||||
|
if (end1 && end2)
|
||||||
|
return true;
|
||||||
|
if (end1 || end2)
|
||||||
|
return false;
|
||||||
|
if (*it1 != *it2)
|
||||||
|
return false;
|
||||||
|
++it1;
|
||||||
|
++it2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the element at the specified index.
|
// Returns the element at the specified index.
|
||||||
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/
|
// https://arduinojson.org/v6/api/jsonarrayconst/subscript/
|
||||||
JsonVariantConst operator[](size_t index) const {
|
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
||||||
return JsonVariantConst(
|
return JsonVariantConst(data_ ? data_->getElement(index) : 0);
|
||||||
detail::ArrayData::getElement(data_, index, resources_), resources_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
operator JsonVariantConst() const {
|
operator JsonVariantConst() const {
|
||||||
return JsonVariantConst(getData(), resources_);
|
return JsonVariantConst(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is unbound.
|
// Returns true if the reference is unbound.
|
||||||
// https://arduinojson.org/v7/api/jsonarrayconst/isnull/
|
// https://arduinojson.org/v6/api/jsonarrayconst/isnull/
|
||||||
bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
return data_ == 0;
|
return data_ == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is bound.
|
// Returns true if the reference is bound.
|
||||||
// https://arduinojson.org/v7/api/jsonarrayconst/isnull/
|
// https://arduinojson.org/v6/api/jsonarrayconst/isnull/
|
||||||
operator bool() const {
|
FORCE_INLINE operator bool() const {
|
||||||
return data_ != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the number of bytes occupied by the array.
|
||||||
|
// https://arduinojson.org/v6/api/jsonarrayconst/memoryusage/
|
||||||
|
FORCE_INLINE size_t memoryUsage() const {
|
||||||
|
return data_ ? data_->memoryUsage() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the array.
|
// Returns the depth (nesting level) of the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarrayconst/nesting/
|
// https://arduinojson.org/v6/api/jsonarrayconst/nesting/
|
||||||
size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
return detail::VariantData::nesting(getData(), resources_);
|
return variantNesting(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of elements in the array.
|
// Returns the number of elements in the array.
|
||||||
// https://arduinojson.org/v7/api/jsonarrayconst/size/
|
// https://arduinojson.org/v6/api/jsonarrayconst/size/
|
||||||
size_t size() const {
|
FORCE_INLINE size_t size() const {
|
||||||
return data_ ? data_->size(resources_) : 0;
|
return data_ ? data_->size() : 0;
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: always returns zero
|
|
||||||
ARDUINOJSON_DEPRECATED("always returns zero")
|
|
||||||
size_t memoryUsage() const {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -89,31 +112,24 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
|||||||
return collectionToVariant(data_);
|
return collectionToVariant(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const detail::ArrayData* data_;
|
const detail::CollectionData* data_;
|
||||||
const detail::ResourceManager* resources_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compares the content of two arrays.
|
template <>
|
||||||
// Returns true if the two arrays are equal.
|
struct Converter<JsonArrayConst> : private detail::VariantAttorney {
|
||||||
inline bool operator==(JsonArrayConst lhs, JsonArrayConst rhs) {
|
static void toJson(JsonVariantConst src, JsonVariant dst) {
|
||||||
if (!lhs && !rhs)
|
variantCopyFrom(getData(dst), getData(src), getPool(dst));
|
||||||
return true;
|
|
||||||
if (!lhs || !rhs)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto a = lhs.begin();
|
|
||||||
auto b = rhs.begin();
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (a == b) // same pointer or both null
|
|
||||||
return true;
|
|
||||||
if (a == lhs.end() || b == rhs.end())
|
|
||||||
return false;
|
|
||||||
if (*a != *b)
|
|
||||||
return false;
|
|
||||||
++a;
|
|
||||||
++b;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
static JsonArrayConst fromJson(JsonVariantConst src) {
|
||||||
|
auto data = getData(src);
|
||||||
|
return data ? data->asArray() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool checkJson(JsonVariantConst src) {
|
||||||
|
auto data = getData(src);
|
||||||
|
return data && data->isArray();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
36
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayImpl.hpp
Normal file
36
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayImpl.hpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Array/JsonArray.hpp>
|
||||||
|
#include <ArduinoJson/Object/JsonObject.hpp>
|
||||||
|
|
||||||
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
|
inline JsonObject JsonArray::createNestedObject() const {
|
||||||
|
return add().to<JsonObject>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
|
template <typename TDerived>
|
||||||
|
inline JsonArray VariantRefBase<TDerived>::createNestedArray() const {
|
||||||
|
return add().template to<JsonArray>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TDerived>
|
||||||
|
inline JsonObject VariantRefBase<TDerived>::createNestedObject() const {
|
||||||
|
return add().template to<JsonObject>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TDerived>
|
||||||
|
inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
|
||||||
|
size_t index) const {
|
||||||
|
return ElementProxy<TDerived>(derived(), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
93
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayIterator.hpp
Executable file → Normal file
93
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayIterator.hpp
Executable file → Normal file
@@ -1,96 +1,121 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Variant/JsonVariant.hpp>
|
#include <ArduinoJson/Variant/JsonVariant.hpp>
|
||||||
|
#include <ArduinoJson/Variant/SlotFunctions.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
template <typename T>
|
class VariantPtr {
|
||||||
class Ptr {
|
|
||||||
public:
|
public:
|
||||||
Ptr(T value) : value_(value) {}
|
VariantPtr(detail::MemoryPool* pool, detail::VariantData* data)
|
||||||
|
: variant_(pool, data) {}
|
||||||
|
|
||||||
T* operator->() {
|
JsonVariant* operator->() {
|
||||||
return &value_;
|
return &variant_;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator*() {
|
JsonVariant& operator*() {
|
||||||
return value_;
|
return variant_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T value_;
|
JsonVariant variant_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonArrayIterator {
|
class JsonArrayIterator {
|
||||||
friend class JsonArray;
|
friend class JsonArray;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JsonArrayIterator() {}
|
JsonArrayIterator() : slot_(0) {}
|
||||||
explicit JsonArrayIterator(detail::ArrayData::iterator iterator,
|
explicit JsonArrayIterator(detail::MemoryPool* pool,
|
||||||
detail::ResourceManager* resources)
|
detail::VariantSlot* slot)
|
||||||
: iterator_(iterator), resources_(resources) {}
|
: pool_(pool), slot_(slot) {}
|
||||||
|
|
||||||
JsonVariant operator*() {
|
JsonVariant operator*() const {
|
||||||
return JsonVariant(iterator_.data(), resources_);
|
return JsonVariant(pool_, slot_->data());
|
||||||
}
|
}
|
||||||
Ptr<JsonVariant> operator->() {
|
VariantPtr operator->() {
|
||||||
return operator*();
|
return VariantPtr(pool_, slot_->data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const JsonArrayIterator& other) const {
|
bool operator==(const JsonArrayIterator& other) const {
|
||||||
return iterator_ == other.iterator_;
|
return slot_ == other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const JsonArrayIterator& other) const {
|
bool operator!=(const JsonArrayIterator& other) const {
|
||||||
return iterator_ != other.iterator_;
|
return slot_ != other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArrayIterator& operator++() {
|
JsonArrayIterator& operator++() {
|
||||||
iterator_.next(resources_);
|
slot_ = slot_->next();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonArrayIterator& operator+=(size_t distance) {
|
||||||
|
slot_ = slot_->next(distance);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::ArrayData::iterator iterator_;
|
detail::MemoryPool* pool_;
|
||||||
detail::ResourceManager* resources_;
|
detail::VariantSlot* slot_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VariantConstPtr {
|
||||||
|
public:
|
||||||
|
VariantConstPtr(const detail::VariantData* data) : variant_(data) {}
|
||||||
|
|
||||||
|
JsonVariantConst* operator->() {
|
||||||
|
return &variant_;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonVariantConst& operator*() {
|
||||||
|
return variant_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
JsonVariantConst variant_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonArrayConstIterator {
|
class JsonArrayConstIterator {
|
||||||
friend class JsonArray;
|
friend class JsonArray;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JsonArrayConstIterator() {}
|
JsonArrayConstIterator() : slot_(0) {}
|
||||||
explicit JsonArrayConstIterator(detail::ArrayData::iterator iterator,
|
explicit JsonArrayConstIterator(const detail::VariantSlot* slot)
|
||||||
const detail::ResourceManager* resources)
|
: slot_(slot) {}
|
||||||
: iterator_(iterator), resources_(resources) {}
|
|
||||||
|
|
||||||
JsonVariantConst operator*() const {
|
JsonVariantConst operator*() const {
|
||||||
return JsonVariantConst(iterator_.data(), resources_);
|
return JsonVariantConst(slot_->data());
|
||||||
}
|
}
|
||||||
Ptr<JsonVariantConst> operator->() {
|
VariantConstPtr operator->() {
|
||||||
return operator*();
|
return VariantConstPtr(slot_->data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const JsonArrayConstIterator& other) const {
|
bool operator==(const JsonArrayConstIterator& other) const {
|
||||||
return iterator_ == other.iterator_;
|
return slot_ == other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const JsonArrayConstIterator& other) const {
|
bool operator!=(const JsonArrayConstIterator& other) const {
|
||||||
return iterator_ != other.iterator_;
|
return slot_ != other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArrayConstIterator& operator++() {
|
JsonArrayConstIterator& operator++() {
|
||||||
iterator_.next(resources_);
|
slot_ = slot_->next();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonArrayConstIterator& operator+=(size_t distance) {
|
||||||
|
slot_ = slot_->next(distance);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::ArrayData::iterator iterator_;
|
const detail::VariantSlot* slot_;
|
||||||
const detail::ResourceManager* resources_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
18
lib/ArduinoJson/src/ArduinoJson/Array/Utilities.hpp
Executable file → Normal file
18
lib/ArduinoJson/src/ArduinoJson/Array/Utilities.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -18,7 +18,7 @@ copyArray(const T& src, JsonVariant dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copies values from an array to a JsonArray or a JsonVariant.
|
// Copies values from an array to a JsonArray or a JsonVariant.
|
||||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||||
template <typename T, size_t N, typename TDestination>
|
template <typename T, size_t N, typename TDestination>
|
||||||
inline typename detail::enable_if<
|
inline typename detail::enable_if<
|
||||||
!detail::is_base_of<JsonDocument, TDestination>::value, bool>::type
|
!detail::is_base_of<JsonDocument, TDestination>::value, bool>::type
|
||||||
@@ -27,14 +27,14 @@ copyArray(T (&src)[N], const TDestination& dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copies values from an array to a JsonArray or a JsonVariant.
|
// Copies values from an array to a JsonArray or a JsonVariant.
|
||||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||||
template <typename T, typename TDestination>
|
template <typename T, typename TDestination>
|
||||||
inline typename detail::enable_if<
|
inline typename detail::enable_if<
|
||||||
!detail::is_base_of<JsonDocument, TDestination>::value, bool>::type
|
!detail::is_base_of<JsonDocument, TDestination>::value, bool>::type
|
||||||
copyArray(const T* src, size_t len, const TDestination& dst) {
|
copyArray(const T* src, size_t len, const TDestination& dst) {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
ok &= copyArray(src[i], dst.template add<JsonVariant>());
|
ok &= copyArray(src[i], dst.add());
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -47,14 +47,14 @@ inline bool copyArray(const char* src, size_t, const TDestination& dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copies values from an array to a JsonDocument.
|
// Copies values from an array to a JsonDocument.
|
||||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool copyArray(const T& src, JsonDocument& dst) {
|
inline bool copyArray(const T& src, JsonDocument& dst) {
|
||||||
return copyArray(src, dst.to<JsonArray>());
|
return copyArray(src, dst.to<JsonArray>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies an array to a JsonDocument.
|
// Copies an array to a JsonDocument.
|
||||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool copyArray(const T* src, size_t len, JsonDocument& dst) {
|
inline bool copyArray(const T* src, size_t len, JsonDocument& dst) {
|
||||||
return copyArray(src, len, dst.to<JsonArray>());
|
return copyArray(src, len, dst.to<JsonArray>());
|
||||||
@@ -70,14 +70,14 @@ copyArray(JsonVariantConst src, T& dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copies values from a JsonArray or JsonVariant to an array.
|
// Copies values from a JsonArray or JsonVariant to an array.
|
||||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
inline size_t copyArray(JsonArrayConst src, T (&dst)[N]) {
|
inline size_t copyArray(JsonArrayConst src, T (&dst)[N]) {
|
||||||
return copyArray(src, dst, N);
|
return copyArray(src, dst, N);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies values from a JsonArray or JsonVariant to an array.
|
// Copies values from a JsonArray or JsonVariant to an array.
|
||||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline size_t copyArray(JsonArrayConst src, T* dst, size_t len) {
|
inline size_t copyArray(JsonArrayConst src, T* dst, size_t len) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
@@ -101,7 +101,7 @@ inline size_t copyArray(JsonVariantConst src, char (&dst)[N]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copies values from a JsonDocument to an array.
|
// Copies values from a JsonDocument to an array.
|
||||||
// https://arduinojson.org/v7/api/misc/copyarray/
|
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||||
template <typename TSource, typename T>
|
template <typename TSource, typename T>
|
||||||
inline typename detail::enable_if<
|
inline typename detail::enable_if<
|
||||||
detail::is_array<T>::value &&
|
detail::is_array<T>::value &&
|
||||||
|
|||||||
140
lib/ArduinoJson/src/ArduinoJson/Collection/CollectionData.hpp
Executable file → Normal file
140
lib/ArduinoJson/src/ArduinoJson/Collection/CollectionData.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -11,112 +11,74 @@
|
|||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
|
class MemoryPool;
|
||||||
class VariantData;
|
class VariantData;
|
||||||
class VariantSlot;
|
class VariantSlot;
|
||||||
|
|
||||||
class CollectionIterator {
|
|
||||||
friend class CollectionData;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CollectionIterator() : slot_(nullptr), currentId_(NULL_SLOT) {}
|
|
||||||
|
|
||||||
void next(const ResourceManager* resources);
|
|
||||||
|
|
||||||
bool done() const {
|
|
||||||
return slot_ == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const CollectionIterator& other) const {
|
|
||||||
return slot_ == other.slot_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const CollectionIterator& other) const {
|
|
||||||
return slot_ != other.slot_;
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantData* operator->() {
|
|
||||||
ARDUINOJSON_ASSERT(slot_ != nullptr);
|
|
||||||
return data();
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantData& operator*() {
|
|
||||||
ARDUINOJSON_ASSERT(slot_ != nullptr);
|
|
||||||
return *data();
|
|
||||||
}
|
|
||||||
|
|
||||||
const VariantData& operator*() const {
|
|
||||||
ARDUINOJSON_ASSERT(slot_ != nullptr);
|
|
||||||
return *data();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* key() const;
|
|
||||||
bool ownsKey() const;
|
|
||||||
|
|
||||||
void setKey(StringNode*);
|
|
||||||
void setKey(const char*);
|
|
||||||
|
|
||||||
VariantData* data() {
|
|
||||||
return reinterpret_cast<VariantData*>(slot_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const VariantData* data() const {
|
|
||||||
return reinterpret_cast<const VariantData*>(slot_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
CollectionIterator(VariantSlot* slot, SlotId slotId);
|
|
||||||
|
|
||||||
VariantSlot* slot_;
|
|
||||||
SlotId currentId_, nextId_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CollectionData {
|
class CollectionData {
|
||||||
SlotId head_ = NULL_SLOT;
|
VariantSlot* head_;
|
||||||
SlotId tail_ = NULL_SLOT;
|
VariantSlot* tail_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Placement new
|
// Must be a POD!
|
||||||
static void* operator new(size_t, void* p) noexcept {
|
// - no constructor
|
||||||
return p;
|
// - no destructor
|
||||||
|
// - no virtual
|
||||||
|
// - no inheritance
|
||||||
|
|
||||||
|
// Array only
|
||||||
|
|
||||||
|
VariantData* addElement(MemoryPool* pool);
|
||||||
|
|
||||||
|
VariantData* getElement(size_t index) const;
|
||||||
|
|
||||||
|
VariantData* getOrAddElement(size_t index, MemoryPool* pool);
|
||||||
|
|
||||||
|
void removeElement(size_t index);
|
||||||
|
|
||||||
|
// Object only
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
VariantData* addMember(TAdaptedString key, MemoryPool* pool);
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
VariantData* getMember(TAdaptedString key) const;
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool);
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
void removeMember(TAdaptedString key) {
|
||||||
|
removeSlot(getSlot(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void operator delete(void*, void*) noexcept {}
|
template <typename TAdaptedString>
|
||||||
|
bool containsKey(const TAdaptedString& key) const;
|
||||||
|
|
||||||
using iterator = CollectionIterator;
|
// Generic
|
||||||
|
|
||||||
iterator createIterator(const ResourceManager* resources) const {
|
void clear();
|
||||||
return iterator(resources->getSlot(head_), head_);
|
size_t memoryUsage() const;
|
||||||
}
|
size_t size() const;
|
||||||
|
|
||||||
size_t size(const ResourceManager*) const;
|
VariantSlot* addSlot(MemoryPool*);
|
||||||
size_t nesting(const ResourceManager*) const;
|
void removeSlot(VariantSlot* slot);
|
||||||
|
|
||||||
void clear(ResourceManager* resources);
|
bool copyFrom(const CollectionData& src, MemoryPool* pool);
|
||||||
|
|
||||||
static void clear(CollectionData* collection, ResourceManager* resources) {
|
VariantSlot* head() const {
|
||||||
if (!collection)
|
|
||||||
return;
|
|
||||||
collection->clear(resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove(iterator it, ResourceManager* resources);
|
|
||||||
|
|
||||||
static void remove(CollectionData* collection, iterator it,
|
|
||||||
ResourceManager* resources) {
|
|
||||||
if (collection)
|
|
||||||
return collection->remove(it, resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
SlotId head() const {
|
|
||||||
return head_;
|
return head_;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance);
|
||||||
iterator addSlot(ResourceManager*);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SlotWithId getPreviousSlot(VariantSlot*, const ResourceManager*) const;
|
VariantSlot* getSlot(size_t index) const;
|
||||||
void releaseSlot(SlotWithId, ResourceManager*);
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
VariantSlot* getSlot(TAdaptedString key) const;
|
||||||
|
|
||||||
|
VariantSlot* getPreviousSlot(VariantSlot*) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const VariantData* collectionToVariant(
|
inline const VariantData* collectionToVariant(
|
||||||
|
|||||||
260
lib/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp
Executable file → Normal file
260
lib/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp
Executable file → Normal file
@@ -1,133 +1,197 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Collection/CollectionData.hpp>
|
#include <ArduinoJson/Collection/CollectionData.hpp>
|
||||||
#include <ArduinoJson/Memory/Alignment.hpp>
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantCompare.hpp>
|
|
||||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
inline CollectionIterator::CollectionIterator(VariantSlot* slot, SlotId slotId)
|
inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
|
||||||
: slot_(slot), currentId_(slotId) {
|
VariantSlot* slot = pool->allocVariant();
|
||||||
nextId_ = slot_ ? slot_->next() : NULL_SLOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char* CollectionIterator::key() const {
|
|
||||||
ARDUINOJSON_ASSERT(slot_ != nullptr);
|
|
||||||
return slot_->key();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void CollectionIterator::setKey(const char* s) {
|
|
||||||
ARDUINOJSON_ASSERT(slot_ != nullptr);
|
|
||||||
ARDUINOJSON_ASSERT(s != nullptr);
|
|
||||||
return slot_->setKey(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void CollectionIterator::setKey(StringNode* s) {
|
|
||||||
ARDUINOJSON_ASSERT(slot_ != nullptr);
|
|
||||||
ARDUINOJSON_ASSERT(s != nullptr);
|
|
||||||
return slot_->setKey(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool CollectionIterator::ownsKey() const {
|
|
||||||
ARDUINOJSON_ASSERT(slot_ != nullptr);
|
|
||||||
return slot_->ownsKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void CollectionIterator::next(const ResourceManager* resources) {
|
|
||||||
ARDUINOJSON_ASSERT(currentId_ != NULL_SLOT);
|
|
||||||
slot_ = resources->getSlot(nextId_);
|
|
||||||
currentId_ = nextId_;
|
|
||||||
if (slot_)
|
|
||||||
nextId_ = slot_->next();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline CollectionData::iterator CollectionData::addSlot(
|
|
||||||
ResourceManager* resources) {
|
|
||||||
auto slot = resources->allocSlot();
|
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return {};
|
return 0;
|
||||||
if (tail_ != NULL_SLOT) {
|
|
||||||
auto tail = resources->getSlot(tail_);
|
if (tail_) {
|
||||||
tail->setNext(slot.id());
|
ARDUINOJSON_ASSERT(pool->owns(tail_)); // Can't alter a linked array/object
|
||||||
tail_ = slot.id();
|
tail_->setNextNotNull(slot);
|
||||||
|
tail_ = slot;
|
||||||
} else {
|
} else {
|
||||||
head_ = slot.id();
|
head_ = slot;
|
||||||
tail_ = slot.id();
|
tail_ = slot;
|
||||||
}
|
|
||||||
return iterator(slot, slot.id());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void CollectionData::clear(ResourceManager* resources) {
|
|
||||||
auto next = head_;
|
|
||||||
while (next != NULL_SLOT) {
|
|
||||||
auto currId = next;
|
|
||||||
auto slot = resources->getSlot(next);
|
|
||||||
next = slot->next();
|
|
||||||
releaseSlot(SlotWithId(slot, currId), resources);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
head_ = NULL_SLOT;
|
slot->clear();
|
||||||
tail_ = NULL_SLOT;
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline SlotWithId CollectionData::getPreviousSlot(
|
inline VariantData* CollectionData::addElement(MemoryPool* pool) {
|
||||||
VariantSlot* target, const ResourceManager* resources) const {
|
return slotData(addSlot(pool));
|
||||||
auto prev = SlotWithId();
|
}
|
||||||
auto currentId = head_;
|
|
||||||
while (currentId != NULL_SLOT) {
|
template <typename TAdaptedString>
|
||||||
auto currentSlot = resources->getSlot(currentId);
|
inline VariantData* CollectionData::addMember(TAdaptedString key,
|
||||||
if (currentSlot == target)
|
MemoryPool* pool) {
|
||||||
return prev;
|
VariantSlot* slot = addSlot(pool);
|
||||||
prev = SlotWithId(currentSlot, currentId);
|
if (!slotSetKey(slot, key, pool)) {
|
||||||
currentId = currentSlot->next();
|
removeSlot(slot);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return SlotWithId();
|
return slot->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CollectionData::remove(iterator it, ResourceManager* resources) {
|
inline void CollectionData::clear() {
|
||||||
if (it.done())
|
head_ = 0;
|
||||||
|
tail_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
inline bool CollectionData::containsKey(const TAdaptedString& key) const {
|
||||||
|
return getSlot(key) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool CollectionData::copyFrom(const CollectionData& src,
|
||||||
|
MemoryPool* pool) {
|
||||||
|
clear();
|
||||||
|
for (VariantSlot* s = src.head_; s; s = s->next()) {
|
||||||
|
VariantData* var;
|
||||||
|
if (s->key() != 0) {
|
||||||
|
JsonString key(s->key(),
|
||||||
|
s->ownsKey() ? JsonString::Copied : JsonString::Linked);
|
||||||
|
var = addMember(adaptString(key), pool);
|
||||||
|
} else {
|
||||||
|
var = addElement(pool);
|
||||||
|
}
|
||||||
|
if (!var)
|
||||||
|
return false;
|
||||||
|
if (!var->copyFrom(*s->data(), pool))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
|
||||||
|
if (key.isNull())
|
||||||
|
return 0;
|
||||||
|
VariantSlot* slot = head_;
|
||||||
|
while (slot) {
|
||||||
|
if (stringEquals(key, adaptString(slot->key())))
|
||||||
|
break;
|
||||||
|
slot = slot->next();
|
||||||
|
}
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VariantSlot* CollectionData::getSlot(size_t index) const {
|
||||||
|
if (!head_)
|
||||||
|
return 0;
|
||||||
|
return head_->next(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
|
||||||
|
VariantSlot* current = head_;
|
||||||
|
while (current) {
|
||||||
|
VariantSlot* next = current->next();
|
||||||
|
if (next == target)
|
||||||
|
return current;
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
inline VariantData* CollectionData::getMember(TAdaptedString key) const {
|
||||||
|
VariantSlot* slot = getSlot(key);
|
||||||
|
return slot ? slot->data() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
|
||||||
|
MemoryPool* pool) {
|
||||||
|
// ignore null key
|
||||||
|
if (key.isNull())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// search a matching key
|
||||||
|
VariantSlot* slot = getSlot(key);
|
||||||
|
if (slot)
|
||||||
|
return slot->data();
|
||||||
|
|
||||||
|
return addMember(key, pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VariantData* CollectionData::getElement(size_t index) const {
|
||||||
|
VariantSlot* slot = getSlot(index);
|
||||||
|
return slot ? slot->data() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VariantData* CollectionData::getOrAddElement(size_t index,
|
||||||
|
MemoryPool* pool) {
|
||||||
|
VariantSlot* slot = head_;
|
||||||
|
while (slot && index > 0) {
|
||||||
|
slot = slot->next();
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
if (!slot)
|
||||||
|
index++;
|
||||||
|
while (index > 0) {
|
||||||
|
slot = addSlot(pool);
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
return slotData(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CollectionData::removeSlot(VariantSlot* slot) {
|
||||||
|
if (!slot)
|
||||||
return;
|
return;
|
||||||
auto curr = it.slot_;
|
VariantSlot* prev = getPreviousSlot(slot);
|
||||||
auto prev = getPreviousSlot(curr, resources);
|
VariantSlot* next = slot->next();
|
||||||
auto next = curr->next();
|
|
||||||
if (prev)
|
if (prev)
|
||||||
prev->setNext(next);
|
prev->setNext(next);
|
||||||
else
|
else
|
||||||
head_ = next;
|
head_ = next;
|
||||||
if (next == NULL_SLOT)
|
if (!next)
|
||||||
tail_ = prev.id();
|
tail_ = prev;
|
||||||
releaseSlot({it.slot_, it.currentId_}, resources);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t CollectionData::nesting(const ResourceManager* resources) const {
|
inline void CollectionData::removeElement(size_t index) {
|
||||||
size_t maxChildNesting = 0;
|
removeSlot(getSlot(index));
|
||||||
for (auto it = createIterator(resources); !it.done(); it.next(resources)) {
|
}
|
||||||
size_t childNesting = it->nesting(resources);
|
|
||||||
if (childNesting > maxChildNesting)
|
inline size_t CollectionData::memoryUsage() const {
|
||||||
maxChildNesting = childNesting;
|
size_t total = 0;
|
||||||
|
for (VariantSlot* s = head_; s; s = s->next()) {
|
||||||
|
total += sizeof(VariantSlot) + s->data()->memoryUsage();
|
||||||
|
if (s->ownsKey())
|
||||||
|
total += strlen(s->key()) + 1;
|
||||||
}
|
}
|
||||||
return maxChildNesting + 1;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t CollectionData::size(const ResourceManager* resources) const {
|
inline size_t CollectionData::size() const {
|
||||||
size_t count = 0;
|
return slotSize(head_);
|
||||||
for (auto it = createIterator(resources); !it.done(); it.next(resources))
|
|
||||||
count++;
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CollectionData::releaseSlot(SlotWithId slot,
|
template <typename T>
|
||||||
ResourceManager* resources) {
|
inline void movePointer(T*& p, ptrdiff_t offset) {
|
||||||
if (slot->ownsKey())
|
if (!p)
|
||||||
resources->dereferenceString(slot->key());
|
return;
|
||||||
slot->data()->setNull(resources);
|
p = reinterpret_cast<T*>(
|
||||||
resources->freeSlot(slot);
|
reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset));
|
||||||
|
ARDUINOJSON_ASSERT(isAligned(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CollectionData::movePointers(ptrdiff_t stringDistance,
|
||||||
|
ptrdiff_t variantDistance) {
|
||||||
|
movePointer(head_, variantDistance);
|
||||||
|
movePointer(tail_, variantDistance);
|
||||||
|
for (VariantSlot* slot = head_; slot; slot = slot->next())
|
||||||
|
slot->movePointers(stringDistance, variantDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
80
lib/ArduinoJson/src/ArduinoJson/Configuration.hpp
Executable file → Normal file
80
lib/ArduinoJson/src/ArduinoJson/Configuration.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -59,75 +59,35 @@
|
|||||||
# define ARDUINOJSON_USE_DOUBLE 1
|
# define ARDUINOJSON_USE_DOUBLE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Pointer size: a heuristic to set sensible defaults
|
|
||||||
#ifndef ARDUINOJSON_SIZEOF_POINTER
|
|
||||||
# if defined(__SIZEOF_POINTER__)
|
|
||||||
# define ARDUINOJSON_SIZEOF_POINTER __SIZEOF_POINTER__
|
|
||||||
# elif defined(_WIN64) && _WIN64
|
|
||||||
# define ARDUINOJSON_SIZEOF_POINTER 8 // 64 bits
|
|
||||||
# else
|
|
||||||
# define ARDUINOJSON_SIZEOF_POINTER 4 // assume 32 bits otherwise
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Store integral values with long (0) or long long (1)
|
// Store integral values with long (0) or long long (1)
|
||||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||||
# if ARDUINOJSON_SIZEOF_POINTER >= 4 // 32 & 64 bits systems
|
# if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ >= 4 || \
|
||||||
|
defined(_MSC_VER)
|
||||||
# define ARDUINOJSON_USE_LONG_LONG 1
|
# define ARDUINOJSON_USE_LONG_LONG 1
|
||||||
# else
|
|
||||||
# define ARDUINOJSON_USE_LONG_LONG 0
|
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||||
|
# define ARDUINOJSON_USE_LONG_LONG 0
|
||||||
|
#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 bytes to store the variant identifier
|
// Number of bits to store the pointer to next node
|
||||||
#ifndef ARDUINOJSON_SLOT_ID_SIZE
|
// (saves RAM but limits the number of values in a document)
|
||||||
# if ARDUINOJSON_SIZEOF_POINTER <= 2
|
#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE
|
||||||
# define ARDUINOJSON_SLOT_ID_SIZE 1 // up to 255 slots
|
# if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ <= 2
|
||||||
# elif ARDUINOJSON_SIZEOF_POINTER == 4
|
// Address space == 16-bit => max 127 values
|
||||||
# define ARDUINOJSON_SLOT_ID_SIZE 2 // up to 65535 slots
|
# define ARDUINOJSON_SLOT_OFFSET_SIZE 1
|
||||||
|
# elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ >= 8 || \
|
||||||
|
defined(_WIN64) && _WIN64
|
||||||
|
// Address space == 64-bit => max 2147483647 values
|
||||||
|
# define ARDUINOJSON_SLOT_OFFSET_SIZE 4
|
||||||
# else
|
# else
|
||||||
# define ARDUINOJSON_SLOT_ID_SIZE 4 // up to 4294967295 slots
|
// Address space == 32-bit => max 32767 values
|
||||||
# endif
|
# define ARDUINOJSON_SLOT_OFFSET_SIZE 2
|
||||||
#endif
|
|
||||||
|
|
||||||
// Capacity of each variant pool (in slots)
|
|
||||||
#ifndef ARDUINOJSON_POOL_CAPACITY
|
|
||||||
# if ARDUINOJSON_SIZEOF_POINTER <= 2
|
|
||||||
# define ARDUINOJSON_POOL_CAPACITY 16 // 128 bytes
|
|
||||||
# elif ARDUINOJSON_SIZEOF_POINTER == 4
|
|
||||||
# define ARDUINOJSON_POOL_CAPACITY 64 // 1024 bytes
|
|
||||||
# else
|
|
||||||
# define ARDUINOJSON_POOL_CAPACITY 128 // 3072 bytes
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Initial capacity of the pool list
|
|
||||||
#ifndef ARDUINOJSON_INITIAL_POOL_COUNT
|
|
||||||
# define ARDUINOJSON_INITIAL_POOL_COUNT 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Automatically call shrinkToFit() from deserializeXxx()
|
|
||||||
// Disabled by default on 8-bit platforms because it's not worth the increase in
|
|
||||||
// code size
|
|
||||||
#ifndef ARDUINOJSON_AUTO_SHRINK
|
|
||||||
# if ARDUINOJSON_SIZEOF_POINTER <= 2
|
|
||||||
# define ARDUINOJSON_AUTO_SHRINK 0
|
|
||||||
# else
|
|
||||||
# define ARDUINOJSON_AUTO_SHRINK 1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Number of bytes to store the length of a string
|
|
||||||
#ifndef ARDUINOJSON_STRING_LENGTH_SIZE
|
|
||||||
# if ARDUINOJSON_SIZEOF_POINTER <= 2
|
|
||||||
# define ARDUINOJSON_STRING_LENGTH_SIZE 1 // up to 255 characters
|
|
||||||
# else
|
|
||||||
# define ARDUINOJSON_STRING_LENGTH_SIZE 2 // up to 65535 characters
|
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -235,6 +195,10 @@
|
|||||||
# define ARDUINOJSON_TAB " "
|
# define ARDUINOJSON_TAB " "
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
|
||||||
|
# define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1
|
||||||
|
#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
|
||||||
|
|||||||
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/DeserializationError.hpp
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/DeserializationError.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/DeserializationOptions.hpp
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/DeserializationOptions.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
13
lib/ArduinoJson/src/ArduinoJson/Deserialization/Filter.hpp
Executable file → Normal file
13
lib/ArduinoJson/src/ArduinoJson/Deserialization/Filter.hpp
Executable file → Normal file
@@ -1,24 +1,17 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Variant/JsonVariant.hpp>
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantAttorney.hpp>
|
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
namespace DeserializationOption {
|
namespace DeserializationOption {
|
||||||
class Filter {
|
class Filter {
|
||||||
public:
|
public:
|
||||||
#if ARDUINOJSON_AUTO_SHRINK
|
explicit Filter(JsonVariantConst v) : variant_(v) {}
|
||||||
explicit Filter(JsonDocument& doc) : variant_(doc) {
|
|
||||||
doc.shrinkToFit();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
explicit Filter(JsonVariantConst variant) : variant_(variant) {}
|
|
||||||
|
|
||||||
bool allow() const {
|
bool allow() const {
|
||||||
return variant_;
|
return variant_;
|
||||||
|
|||||||
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/NestingLimit.hpp
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/NestingLimit.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
4
lib/ArduinoJson/src/ArduinoJson/Deserialization/Reader.hpp
Executable file → Normal file
4
lib/ArduinoJson/src/ArduinoJson/Deserialization/Reader.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -19,7 +19,7 @@ struct Reader {
|
|||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
return source_->read(); // Error here? See https://arduinojson.org/v7/invalid-input/
|
return source_->read(); // Error here? See https://arduinojson.org/v6/invalid-input/
|
||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp
Executable file → Normal file
4
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -15,7 +15,7 @@ struct Reader<TSource,
|
|||||||
explicit Reader(Stream& stream) : stream_(&stream) {}
|
explicit Reader(Stream& stream) : stream_(&stream) {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
// don't use stream_->read() as it ignores the timeout
|
// don't use stream_.read() as it ignores the timeout
|
||||||
char c;
|
char c;
|
||||||
return stream_->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1;
|
return stream_->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1;
|
||||||
}
|
}
|
||||||
|
|||||||
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/FlashReader.hpp
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/FlashReader.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/IteratorReader.hpp
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/IteratorReader.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/RamReader.hpp
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/RamReader.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/VariantReader.hpp
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/VariantReader.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
79
lib/ArduinoJson/src/ArduinoJson/Deserialization/deserialize.hpp
Executable file → Normal file
79
lib/ArduinoJson/src/ArduinoJson/Deserialization/deserialize.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <ArduinoJson/Deserialization/DeserializationOptions.hpp>
|
#include <ArduinoJson/Deserialization/DeserializationOptions.hpp>
|
||||||
#include <ArduinoJson/Deserialization/Reader.hpp>
|
#include <ArduinoJson/Deserialization/Reader.hpp>
|
||||||
#include <ArduinoJson/Polyfills/utility.hpp>
|
#include <ArduinoJson/Polyfills/utility.hpp>
|
||||||
|
#include <ArduinoJson/StringStorage/StringStorage.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
@@ -22,62 +23,44 @@ struct first_or_void<T, Rest...> {
|
|||||||
using type = T;
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A meta-function that returns true if T is a valid destination type for
|
template <template <typename, typename> class TDeserializer, typename TReader,
|
||||||
// deserialize()
|
typename TWriter>
|
||||||
template <class T, class = void>
|
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool* pool,
|
||||||
struct is_deserialize_destination : false_type {};
|
TReader reader,
|
||||||
|
TWriter writer) {
|
||||||
template <class T>
|
ARDUINOJSON_ASSERT(pool != 0);
|
||||||
struct is_deserialize_destination<
|
return TDeserializer<TReader, TWriter>(pool, reader, writer);
|
||||||
T, typename enable_if<is_same<decltype(VariantAttorney::getResourceManager(
|
|
||||||
detail::declval<T&>())),
|
|
||||||
ResourceManager*>::value>::type> : true_type {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TDestination>
|
|
||||||
inline void shrinkJsonDocument(TDestination&) {
|
|
||||||
// no-op by default
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_AUTO_SHRINK
|
template <template <typename, typename> class TDeserializer, typename TStream,
|
||||||
inline void shrinkJsonDocument(JsonDocument& doc) {
|
typename... Args,
|
||||||
doc.shrinkToFit();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <template <typename> class TDeserializer, typename TDestination,
|
|
||||||
typename TReader, typename TOptions>
|
|
||||||
DeserializationError doDeserialize(TDestination&& dst, TReader reader,
|
|
||||||
TOptions options) {
|
|
||||||
auto data = VariantAttorney::getOrCreateData(dst);
|
|
||||||
if (!data)
|
|
||||||
return DeserializationError::NoMemory;
|
|
||||||
auto resources = VariantAttorney::getResourceManager(dst);
|
|
||||||
dst.clear();
|
|
||||||
auto err = TDeserializer<TReader>(resources, reader)
|
|
||||||
.parse(*data, options.filter, options.nestingLimit);
|
|
||||||
shrinkJsonDocument(dst);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <template <typename> class TDeserializer, typename TDestination,
|
|
||||||
typename TStream, typename... Args,
|
|
||||||
typename = typename enable_if< // issue #1897
|
typename = typename enable_if< // issue #1897
|
||||||
!is_integral<typename first_or_void<Args...>::type>::value>::type>
|
!is_integral<typename first_or_void<Args...>::type>::value>::type>
|
||||||
DeserializationError deserialize(TDestination&& dst, TStream&& input,
|
DeserializationError deserialize(JsonDocument& doc, TStream&& input,
|
||||||
Args... args) {
|
Args... args) {
|
||||||
return doDeserialize<TDeserializer>(
|
auto reader = makeReader(detail::forward<TStream>(input));
|
||||||
dst, makeReader(detail::forward<TStream>(input)),
|
auto data = VariantAttorney::getData(doc);
|
||||||
makeDeserializationOptions(args...));
|
auto pool = VariantAttorney::getPool(doc);
|
||||||
|
auto options = makeDeserializationOptions(args...);
|
||||||
|
doc.clear();
|
||||||
|
return makeDeserializer<TDeserializer>(pool, reader,
|
||||||
|
makeStringStorage(input, pool))
|
||||||
|
.parse(*data, options.filter, options.nestingLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <template <typename> class TDeserializer, typename TDestination,
|
template <template <typename, typename> class TDeserializer, typename TChar,
|
||||||
typename TChar, typename Size, typename... Args,
|
typename Size, typename... Args,
|
||||||
typename = typename enable_if<is_integral<Size>::value>::type>
|
typename = typename enable_if<is_integral<Size>::value>::type>
|
||||||
DeserializationError deserialize(TDestination&& dst, TChar* input,
|
DeserializationError deserialize(JsonDocument& doc, TChar* input,
|
||||||
Size inputSize, Args... args) {
|
Size inputSize, Args... args) {
|
||||||
return doDeserialize<TDeserializer>(dst, makeReader(input, size_t(inputSize)),
|
auto reader = makeReader(input, size_t(inputSize));
|
||||||
makeDeserializationOptions(args...));
|
auto data = VariantAttorney::getData(doc);
|
||||||
|
auto pool = VariantAttorney::getPool(doc);
|
||||||
|
auto options = makeDeserializationOptions(args...);
|
||||||
|
doc.clear();
|
||||||
|
return makeDeserializer<TDeserializer>(pool, reader,
|
||||||
|
makeStringStorage(input, pool))
|
||||||
|
.parse(*data, options.filter, options.nestingLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
168
lib/ArduinoJson/src/ArduinoJson/Document/BasicJsonDocument.hpp
Normal file
168
lib/ArduinoJson/src/ArduinoJson/Document/BasicJsonDocument.hpp
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Document/JsonDocument.hpp>
|
||||||
|
|
||||||
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
|
// Helper to implement the "base-from-member" idiom
|
||||||
|
// (we need to store the allocator before constructing JsonDocument)
|
||||||
|
template <typename TAllocator>
|
||||||
|
class AllocatorOwner {
|
||||||
|
public:
|
||||||
|
AllocatorOwner() {}
|
||||||
|
AllocatorOwner(TAllocator a) : allocator_(a) {}
|
||||||
|
|
||||||
|
void* allocate(size_t size) {
|
||||||
|
return allocator_.allocate(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(void* ptr) {
|
||||||
|
if (ptr)
|
||||||
|
allocator_.deallocate(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* reallocate(void* ptr, size_t new_size) {
|
||||||
|
return allocator_.reallocate(ptr, new_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
TAllocator& allocator() {
|
||||||
|
return allocator_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TAllocator allocator_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A JsonDocument that uses the provided allocator to allocate its memory pool.
|
||||||
|
// https://arduinojson.org/v6/api/basicjsondocument/
|
||||||
|
template <typename TAllocator>
|
||||||
|
class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
||||||
|
public:
|
||||||
|
explicit BasicJsonDocument(size_t capa, TAllocator alloc = TAllocator())
|
||||||
|
: AllocatorOwner<TAllocator>(alloc), JsonDocument(allocPool(capa)) {}
|
||||||
|
|
||||||
|
// Copy-constructor
|
||||||
|
BasicJsonDocument(const BasicJsonDocument& src)
|
||||||
|
: AllocatorOwner<TAllocator>(src), JsonDocument() {
|
||||||
|
copyAssignFrom(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move-constructor
|
||||||
|
BasicJsonDocument(BasicJsonDocument&& src) : AllocatorOwner<TAllocator>(src) {
|
||||||
|
moveAssignFrom(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicJsonDocument(const JsonDocument& src) {
|
||||||
|
copyAssignFrom(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct from variant, array, or object
|
||||||
|
template <typename T>
|
||||||
|
BasicJsonDocument(const T& src,
|
||||||
|
typename detail::enable_if<
|
||||||
|
detail::is_same<T, JsonVariant>::value ||
|
||||||
|
detail::is_same<T, JsonVariantConst>::value ||
|
||||||
|
detail::is_same<T, JsonArray>::value ||
|
||||||
|
detail::is_same<T, JsonArrayConst>::value ||
|
||||||
|
detail::is_same<T, JsonObject>::value ||
|
||||||
|
detail::is_same<T, JsonObjectConst>::value>::type* = 0)
|
||||||
|
: JsonDocument(allocPool(src.memoryUsage())) {
|
||||||
|
set(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
// disambiguate
|
||||||
|
BasicJsonDocument(JsonVariant src)
|
||||||
|
: JsonDocument(allocPool(src.memoryUsage())) {
|
||||||
|
set(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
~BasicJsonDocument() {
|
||||||
|
freePool();
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicJsonDocument& operator=(const BasicJsonDocument& src) {
|
||||||
|
copyAssignFrom(src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicJsonDocument& operator=(BasicJsonDocument&& src) {
|
||||||
|
moveAssignFrom(src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
BasicJsonDocument& operator=(const T& src) {
|
||||||
|
size_t requiredSize = src.memoryUsage();
|
||||||
|
if (requiredSize > capacity())
|
||||||
|
reallocPool(requiredSize);
|
||||||
|
set(src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduces the capacity of the memory pool to match the current usage.
|
||||||
|
// https://arduinojson.org/v6/api/basicjsondocument/shrinktofit/
|
||||||
|
void shrinkToFit() {
|
||||||
|
ptrdiff_t bytes_reclaimed = pool_.squash();
|
||||||
|
if (bytes_reclaimed == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
void* old_ptr = pool_.buffer();
|
||||||
|
void* new_ptr = this->reallocate(old_ptr, pool_.capacity());
|
||||||
|
|
||||||
|
ptrdiff_t ptr_offset =
|
||||||
|
static_cast<char*>(new_ptr) - static_cast<char*>(old_ptr);
|
||||||
|
|
||||||
|
pool_.movePointers(ptr_offset);
|
||||||
|
data_.movePointers(ptr_offset, ptr_offset - bytes_reclaimed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reclaims the memory leaked when removing and replacing values.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/garbagecollect/
|
||||||
|
bool garbageCollect() {
|
||||||
|
// make a temporary clone and move assign
|
||||||
|
BasicJsonDocument tmp(*this);
|
||||||
|
if (!tmp.capacity())
|
||||||
|
return false;
|
||||||
|
moveAssignFrom(tmp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
using AllocatorOwner<TAllocator>::allocator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
detail::MemoryPool allocPool(size_t requiredSize) {
|
||||||
|
size_t capa = detail::addPadding(requiredSize);
|
||||||
|
return {reinterpret_cast<char*>(this->allocate(capa)), capa};
|
||||||
|
}
|
||||||
|
|
||||||
|
void reallocPool(size_t requiredSize) {
|
||||||
|
size_t capa = detail::addPadding(requiredSize);
|
||||||
|
if (capa == pool_.capacity())
|
||||||
|
return;
|
||||||
|
freePool();
|
||||||
|
replacePool(allocPool(detail::addPadding(requiredSize)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void freePool() {
|
||||||
|
this->deallocate(getPool()->buffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyAssignFrom(const JsonDocument& src) {
|
||||||
|
reallocPool(src.capacity());
|
||||||
|
set(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveAssignFrom(BasicJsonDocument& src) {
|
||||||
|
freePool();
|
||||||
|
data_ = src.data_;
|
||||||
|
pool_ = src.pool_;
|
||||||
|
src.data_.setNull();
|
||||||
|
src.pool_ = {0, 0};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Document/BasicJsonDocument.hpp>
|
||||||
|
|
||||||
|
#include <stdlib.h> // malloc, free
|
||||||
|
|
||||||
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
|
// The allocator of DynamicJsonDocument.
|
||||||
|
struct DefaultAllocator {
|
||||||
|
void* allocate(size_t size) {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(void* ptr) {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* reallocate(void* ptr, size_t new_size) {
|
||||||
|
return realloc(ptr, new_size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A JsonDocument with a memory pool in the heap.
|
||||||
|
// https://arduinojson.org/v6/api/dynamicjsondocument/
|
||||||
|
typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
|
||||||
|
|
||||||
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
344
lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp
Executable file → Normal file
344
lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp
Executable file → Normal file
@@ -1,143 +1,107 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Array/ElementProxy.hpp>
|
#include <ArduinoJson/Array/ElementProxy.hpp>
|
||||||
#include <ArduinoJson/Memory/Allocator.hpp>
|
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
|
||||||
#include <ArduinoJson/Object/JsonObject.hpp>
|
#include <ArduinoJson/Object/JsonObject.hpp>
|
||||||
#include <ArduinoJson/Object/MemberProxy.hpp>
|
#include <ArduinoJson/Object/MemberProxy.hpp>
|
||||||
#include <ArduinoJson/Polyfills/utility.hpp>
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
|
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantTo.hpp>
|
#include <ArduinoJson/Variant/VariantTo.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
// A JSON document.
|
// A JSON document.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/
|
// https://arduinojson.org/v6/api/jsondocument/
|
||||||
class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
||||||
friend class detail::VariantAttorney;
|
friend class detail::VariantAttorney;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JsonDocument(Allocator* alloc = detail::DefaultAllocator::instance())
|
JsonDocument(const JsonDocument&) = delete;
|
||||||
: resources_(alloc) {}
|
JsonDocument& operator=(const JsonDocument&) = delete;
|
||||||
|
|
||||||
// Copy-constructor
|
|
||||||
JsonDocument(const JsonDocument& src) : JsonDocument(src.allocator()) {
|
|
||||||
set(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move-constructor
|
|
||||||
JsonDocument(JsonDocument&& src)
|
|
||||||
: JsonDocument(detail::DefaultAllocator::instance()) {
|
|
||||||
swap(*this, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct from variant, array, or object
|
|
||||||
template <typename T>
|
|
||||||
JsonDocument(const T& src,
|
|
||||||
Allocator* alloc = detail::DefaultAllocator::instance(),
|
|
||||||
typename detail::enable_if<
|
|
||||||
detail::is_same<T, JsonVariant>::value ||
|
|
||||||
detail::is_same<T, JsonVariantConst>::value ||
|
|
||||||
detail::is_same<T, JsonArray>::value ||
|
|
||||||
detail::is_same<T, JsonArrayConst>::value ||
|
|
||||||
detail::is_same<T, JsonObject>::value ||
|
|
||||||
detail::is_same<T, JsonObjectConst>::value>::type* = 0)
|
|
||||||
: JsonDocument(alloc) {
|
|
||||||
set(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonDocument& operator=(JsonDocument src) {
|
|
||||||
swap(*this, src);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
JsonDocument& operator=(const T& src) {
|
|
||||||
set(src);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Allocator* allocator() const {
|
|
||||||
return resources_.allocator();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reduces the capacity of the memory pool to match the current usage.
|
|
||||||
// https://arduinojson.org/v7/api/jsondocument/shrinktofit/
|
|
||||||
void shrinkToFit() {
|
|
||||||
resources_.shrinkToFit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Casts the root to the specified type.
|
// Casts the root to the specified type.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/as/
|
// https://arduinojson.org/v6/api/jsondocument/as/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T as() {
|
T as() {
|
||||||
return getVariant().template as<T>();
|
return getVariant().template as<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Casts the root to the specified type.
|
// Casts the root to the specified type.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/as/
|
// https://arduinojson.org/v6/api/jsondocument/as/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T as() const {
|
T as() const {
|
||||||
return getVariant().template as<T>();
|
return getVariant().template as<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empties the document and resets the memory pool
|
// Empties the document and resets the memory pool
|
||||||
// https://arduinojson.org/v7/api/jsondocument/clear/
|
// https://arduinojson.org/v6/api/jsondocument/clear/
|
||||||
void clear() {
|
void clear() {
|
||||||
resources_.clear();
|
pool_.clear();
|
||||||
data_.reset();
|
data_.setNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the root is of the specified type.
|
// Returns true if the root is of the specified type.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/is/
|
// https://arduinojson.org/v6/api/jsondocument/is/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool is() {
|
bool is() {
|
||||||
return getVariant().template is<T>();
|
return getVariant().template is<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the root is of the specified type.
|
// Returns true if the root is of the specified type.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/is/
|
// https://arduinojson.org/v6/api/jsondocument/is/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool is() const {
|
bool is() const {
|
||||||
return getVariant().template is<T>();
|
return getVariant().template is<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the root is null.
|
// Returns true if the root is null.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/isnull/
|
// https://arduinojson.org/v6/api/jsondocument/isnull/
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
return getVariant().isNull();
|
return getVariant().isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the number of used bytes in the memory pool.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/memoryusage/
|
||||||
|
size_t memoryUsage() const {
|
||||||
|
return pool_.size();
|
||||||
|
}
|
||||||
|
|
||||||
// Returns trues if the memory pool was too small.
|
// Returns trues if the memory pool was too small.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/overflowed/
|
// https://arduinojson.org/v6/api/jsondocument/overflowed/
|
||||||
bool overflowed() const {
|
bool overflowed() const {
|
||||||
return resources_.overflowed();
|
return pool_.overflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the array.
|
// Returns the depth (nesting level) of the array.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/nesting/
|
// https://arduinojson.org/v6/api/jsondocument/nesting/
|
||||||
size_t nesting() const {
|
size_t nesting() const {
|
||||||
return data_.nesting(&resources_);
|
return variantNesting(&data_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the capacity of the memory pool.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/capacity/
|
||||||
|
size_t capacity() const {
|
||||||
|
return pool_.capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of elements in the root array or object.
|
// Returns the number of elements in the root array or object.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/size/
|
// https://arduinojson.org/v6/api/jsondocument/size/
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return data_.size(&resources_);
|
return data_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies the specified document.
|
// Copies the specified document.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/set/
|
// https://arduinojson.org/v6/api/jsondocument/set/
|
||||||
bool set(const JsonDocument& src) {
|
bool set(const JsonDocument& src) {
|
||||||
return to<JsonVariant>().set(src.as<JsonVariantConst>());
|
return to<JsonVariant>().set(src.as<JsonVariantConst>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces the root with the specified value.
|
// Replaces the root with the specified value.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/set/
|
// https://arduinojson.org/v6/api/jsondocument/set/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename detail::enable_if<!detail::is_base_of<JsonDocument, T>::value,
|
typename detail::enable_if<!detail::is_base_of<JsonDocument, T>::value,
|
||||||
bool>::type
|
bool>::type
|
||||||
@@ -146,210 +110,199 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clears the document and converts it to the specified type.
|
// Clears the document and converts it to the specified type.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/to/
|
// https://arduinojson.org/v6/api/jsondocument/to/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename detail::VariantTo<T>::type to() {
|
typename detail::VariantTo<T>::type to() {
|
||||||
clear();
|
clear();
|
||||||
return getVariant().template to<T>();
|
return getVariant().template to<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the root object contains the specified key.
|
// Creates an array and appends it to the root array.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/containskey/
|
// https://arduinojson.org/v6/api/jsondocument/createnestedarray/
|
||||||
|
JsonArray createNestedArray() {
|
||||||
|
return add().to<JsonArray>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an array and adds it to the root object.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/createnestedarray/
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
bool containsKey(TChar* key) const {
|
JsonArray createNestedArray(TChar* key) {
|
||||||
return data_.getMember(detail::adaptString(key), &resources_) != 0;
|
return operator[](key).template to<JsonArray>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an array and adds it to the root object.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/createnestedarray/
|
||||||
|
template <typename TString>
|
||||||
|
JsonArray createNestedArray(const TString& key) {
|
||||||
|
return operator[](key).template to<JsonArray>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an object and appends it to the root array.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/createnestedobject/
|
||||||
|
JsonObject createNestedObject() {
|
||||||
|
return add().to<JsonObject>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an object and adds it to the root object.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/createnestedobject/
|
||||||
|
template <typename TChar>
|
||||||
|
JsonObject createNestedObject(TChar* key) {
|
||||||
|
return operator[](key).template to<JsonObject>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an object and adds it to the root object.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/createnestedobject/
|
||||||
|
template <typename TString>
|
||||||
|
JsonObject createNestedObject(const TString& key) {
|
||||||
|
return operator[](key).template to<JsonObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the root object contains the specified key.
|
// Returns true if the root object contains the specified key.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/containskey/
|
// https://arduinojson.org/v6/api/jsondocument/containskey/
|
||||||
|
template <typename TChar>
|
||||||
|
bool containsKey(TChar* key) const {
|
||||||
|
return data_.getMember(detail::adaptString(key)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the root object contains the specified key.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/containskey/
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
bool containsKey(const TString& key) const {
|
bool containsKey(const TString& key) const {
|
||||||
return data_.getMember(detail::adaptString(key), &resources_) != 0;
|
return data_.getMember(detail::adaptString(key)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets or sets a root object's member.
|
// Gets or sets a root object's member.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
typename detail::enable_if<detail::IsString<TString>::value,
|
FORCE_INLINE typename detail::enable_if<
|
||||||
detail::MemberProxy<JsonDocument&, TString>>::type
|
detail::IsString<TString>::value,
|
||||||
|
detail::MemberProxy<JsonDocument&, TString>>::type
|
||||||
operator[](const TString& key) {
|
operator[](const TString& key) {
|
||||||
return {*this, key};
|
return {*this, key};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets or sets a root object's member.
|
// Gets or sets a root object's member.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
typename detail::enable_if<detail::IsString<TChar*>::value,
|
FORCE_INLINE typename detail::enable_if<
|
||||||
detail::MemberProxy<JsonDocument&, TChar*>>::type
|
detail::IsString<TChar*>::value,
|
||||||
|
detail::MemberProxy<JsonDocument&, TChar*>>::type
|
||||||
operator[](TChar* key) {
|
operator[](TChar* key) {
|
||||||
return {*this, key};
|
return {*this, key};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a root object's member.
|
// Gets a root object's member.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
typename detail::enable_if<detail::IsString<TString>::value,
|
FORCE_INLINE typename detail::enable_if<detail::IsString<TString>::value,
|
||||||
JsonVariantConst>::type
|
JsonVariantConst>::type
|
||||||
operator[](const TString& key) const {
|
operator[](const TString& key) const {
|
||||||
return JsonVariantConst(
|
return JsonVariantConst(data_.getMember(detail::adaptString(key)));
|
||||||
data_.getMember(detail::adaptString(key), &resources_), &resources_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a root object's member.
|
// Gets a root object's member.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
typename detail::enable_if<detail::IsString<TChar*>::value,
|
FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value,
|
||||||
JsonVariantConst>::type
|
JsonVariantConst>::type
|
||||||
operator[](TChar* key) const {
|
operator[](TChar* key) const {
|
||||||
return JsonVariantConst(
|
return JsonVariantConst(data_.getMember(detail::adaptString(key)));
|
||||||
data_.getMember(detail::adaptString(key), &resources_), &resources_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets or sets a root array's element.
|
// Gets or sets a root array's element.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||||
detail::ElementProxy<JsonDocument&> operator[](size_t index) {
|
FORCE_INLINE detail::ElementProxy<JsonDocument&> operator[](size_t index) {
|
||||||
return {*this, index};
|
return {*this, index};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a root array's member.
|
// Gets a root array's member.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/subscript/
|
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||||
JsonVariantConst operator[](size_t index) const {
|
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
||||||
return JsonVariantConst(data_.getElement(index, &resources_), &resources_);
|
return JsonVariantConst(data_.getElement(index));
|
||||||
}
|
|
||||||
|
|
||||||
// Appends a new (empty) element to the root array.
|
|
||||||
// Returns a reference to the new element.
|
|
||||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
|
||||||
template <typename T>
|
|
||||||
typename detail::enable_if<!detail::is_same<T, JsonVariant>::value, T>::type
|
|
||||||
add() {
|
|
||||||
return add<JsonVariant>().to<T>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a new (null) element to the root array.
|
// Appends a new (null) element to the root array.
|
||||||
// Returns a reference to the new element.
|
// Returns a reference to the new element.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
// https://arduinojson.org/v6/api/jsondocument/add/
|
||||||
template <typename T>
|
FORCE_INLINE JsonVariant add() {
|
||||||
typename detail::enable_if<detail::is_same<T, JsonVariant>::value, T>::type
|
return JsonVariant(&pool_, data_.addElement(&pool_));
|
||||||
add() {
|
|
||||||
return JsonVariant(data_.addElement(&resources_), &resources_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a value to the root array.
|
// Appends a value to the root array.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
// https://arduinojson.org/v6/api/jsondocument/add/
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
bool add(const TValue& value) {
|
FORCE_INLINE bool add(const TValue& value) {
|
||||||
return add<JsonVariant>().set(value);
|
return add().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a value to the root array.
|
// Appends a value to the root array.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/add/
|
// https://arduinojson.org/v6/api/jsondocument/add/
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
bool add(TChar* value) {
|
FORCE_INLINE bool add(TChar* value) {
|
||||||
return add<JsonVariant>().set(value);
|
return add().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes an element of the root array.
|
// Removes an element of the root array.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/remove/
|
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||||
void remove(size_t index) {
|
// https://arduinojson.org/v6/api/jsondocument/remove/
|
||||||
detail::VariantData::removeElement(getData(), index, getResourceManager());
|
FORCE_INLINE void remove(size_t index) {
|
||||||
|
data_.remove(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes a member of the root object.
|
// Removes a member of the root object.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/remove/
|
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/remove/
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
typename detail::enable_if<detail::IsString<TChar*>::value>::type remove(
|
FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value>::type
|
||||||
TChar* key) {
|
remove(TChar* key) {
|
||||||
detail::VariantData::removeMember(getData(), detail::adaptString(key),
|
data_.remove(detail::adaptString(key));
|
||||||
getResourceManager());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes a member of the root object.
|
// Removes a member of the root object.
|
||||||
// https://arduinojson.org/v7/api/jsondocument/remove/
|
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/remove/
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
|
FORCE_INLINE
|
||||||
typename detail::enable_if<detail::IsString<TString>::value>::type remove(
|
typename detail::enable_if<detail::IsString<TString>::value>::type
|
||||||
const TString& key) {
|
remove(const TString& key) {
|
||||||
detail::VariantData::removeMember(getData(), detail::adaptString(key),
|
data_.remove(detail::adaptString(key));
|
||||||
getResourceManager());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
operator JsonVariant() {
|
FORCE_INLINE operator JsonVariant() {
|
||||||
return getVariant();
|
return getVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
operator JsonVariantConst() const {
|
FORCE_INLINE operator JsonVariantConst() const {
|
||||||
return getVariant();
|
return getVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
friend void swap(JsonDocument& a, JsonDocument& b) {
|
protected:
|
||||||
swap(a.resources_, b.resources_);
|
JsonDocument() : pool_(0, 0) {}
|
||||||
swap_(a.data_, b.data_);
|
|
||||||
|
JsonDocument(detail::MemoryPool pool) : pool_(pool) {}
|
||||||
|
|
||||||
|
JsonDocument(char* buf, size_t capa) : pool_(buf, capa) {}
|
||||||
|
|
||||||
|
~JsonDocument() {}
|
||||||
|
|
||||||
|
void replacePool(detail::MemoryPool pool) {
|
||||||
|
pool_ = pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEPRECATED: use add<JsonVariant>() instead
|
|
||||||
ARDUINOJSON_DEPRECATED("use add<JsonVariant>() instead")
|
|
||||||
JsonVariant add() {
|
|
||||||
return add<JsonVariant>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: use add<JsonArray>() instead
|
|
||||||
ARDUINOJSON_DEPRECATED("use add<JsonArray>() instead")
|
|
||||||
JsonArray createNestedArray() {
|
|
||||||
return add<JsonArray>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: use doc[key].to<JsonArray>() instead
|
|
||||||
template <typename TChar>
|
|
||||||
ARDUINOJSON_DEPRECATED("use doc[key].to<JsonArray>() instead")
|
|
||||||
JsonArray createNestedArray(TChar* key) {
|
|
||||||
return operator[](key).template to<JsonArray>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: use doc[key].to<JsonArray>() instead
|
|
||||||
template <typename TString>
|
|
||||||
ARDUINOJSON_DEPRECATED("use doc[key].to<JsonArray>() instead")
|
|
||||||
JsonArray createNestedArray(const TString& key) {
|
|
||||||
return operator[](key).template to<JsonArray>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: use add<JsonObject>() instead
|
|
||||||
ARDUINOJSON_DEPRECATED("use add<JsonObject>() instead")
|
|
||||||
JsonObject createNestedObject() {
|
|
||||||
return add<JsonObject>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: use doc[key].to<JsonObject>() instead
|
|
||||||
template <typename TChar>
|
|
||||||
ARDUINOJSON_DEPRECATED("use doc[key].to<JsonObject>() instead")
|
|
||||||
JsonObject createNestedObject(TChar* key) {
|
|
||||||
return operator[](key).template to<JsonObject>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: use doc[key].to<JsonObject>() instead
|
|
||||||
template <typename TString>
|
|
||||||
ARDUINOJSON_DEPRECATED("use doc[key].to<JsonObject>() instead")
|
|
||||||
JsonObject createNestedObject(const TString& key) {
|
|
||||||
return operator[](key).template to<JsonObject>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: always returns zero
|
|
||||||
ARDUINOJSON_DEPRECATED("always returns zero")
|
|
||||||
size_t memoryUsage() const {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
JsonVariant getVariant() {
|
JsonVariant getVariant() {
|
||||||
return JsonVariant(&data_, &resources_);
|
return JsonVariant(&pool_, &data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonVariantConst getVariant() const {
|
JsonVariantConst getVariant() const {
|
||||||
return JsonVariantConst(&data_, &resources_);
|
return JsonVariantConst(&data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::ResourceManager* getResourceManager() {
|
detail::MemoryPool pool_;
|
||||||
return &resources_;
|
detail::VariantData data_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
detail::MemoryPool* getPool() {
|
||||||
|
return &pool_;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::VariantData* getData() {
|
detail::VariantData* getData() {
|
||||||
@@ -363,9 +316,6 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
detail::VariantData* getOrCreateData() {
|
detail::VariantData* getOrCreateData() {
|
||||||
return &data_;
|
return &data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::ResourceManager resources_;
|
|
||||||
detail::VariantData data_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void convertToJson(const JsonDocument& src, JsonVariant dst) {
|
inline void convertToJson(const JsonDocument& src, JsonVariant dst) {
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Document/JsonDocument.hpp>
|
||||||
|
|
||||||
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
|
// A JsonDocument with a memory pool on the stack.
|
||||||
|
template <size_t desiredCapacity>
|
||||||
|
class StaticJsonDocument : public JsonDocument {
|
||||||
|
static const size_t capacity_ =
|
||||||
|
detail::AddPadding<detail::Max<1, desiredCapacity>::value>::value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StaticJsonDocument() : JsonDocument(buffer_, capacity_) {}
|
||||||
|
|
||||||
|
StaticJsonDocument(const StaticJsonDocument& src)
|
||||||
|
: JsonDocument(buffer_, capacity_) {
|
||||||
|
set(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
StaticJsonDocument(
|
||||||
|
const T& src,
|
||||||
|
typename detail::enable_if<
|
||||||
|
detail::is_convertible<T, JsonVariantConst>::value>::type* = 0)
|
||||||
|
: JsonDocument(buffer_, capacity_) {
|
||||||
|
set(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
// disambiguate
|
||||||
|
StaticJsonDocument(JsonVariant src) : JsonDocument(buffer_, capacity_) {
|
||||||
|
set(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticJsonDocument& operator=(const StaticJsonDocument& src) {
|
||||||
|
set(src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
StaticJsonDocument& operator=(const T& src) {
|
||||||
|
set(src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reclaims the memory leaked when removing and replacing values.
|
||||||
|
// https://arduinojson.org/v6/api/jsondocument/garbagecollect/
|
||||||
|
void garbageCollect() {
|
||||||
|
StaticJsonDocument tmp(*this);
|
||||||
|
set(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char buffer_[capacity_];
|
||||||
|
};
|
||||||
|
|
||||||
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
2
lib/ArduinoJson/src/ArduinoJson/Json/EscapeSequence.hpp
Executable file → Normal file
2
lib/ArduinoJson/src/ArduinoJson/Json/EscapeSequence.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
96
lib/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp
Executable file → Normal file
96
lib/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <ArduinoJson/Json/Latch.hpp>
|
#include <ArduinoJson/Json/Latch.hpp>
|
||||||
#include <ArduinoJson/Json/Utf16.hpp>
|
#include <ArduinoJson/Json/Utf16.hpp>
|
||||||
#include <ArduinoJson/Json/Utf8.hpp>
|
#include <ArduinoJson/Json/Utf8.hpp>
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||||
#include <ArduinoJson/Numbers/parseNumber.hpp>
|
#include <ArduinoJson/Numbers/parseNumber.hpp>
|
||||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
@@ -18,14 +18,15 @@
|
|||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
template <typename TReader>
|
template <typename TReader, typename TStringStorage>
|
||||||
class JsonDeserializer {
|
class JsonDeserializer {
|
||||||
public:
|
public:
|
||||||
JsonDeserializer(ResourceManager* resources, TReader reader)
|
JsonDeserializer(MemoryPool* pool, TReader reader,
|
||||||
: stringBuilder_(resources),
|
TStringStorage stringStorage)
|
||||||
|
: stringStorage_(stringStorage),
|
||||||
foundSomething_(false),
|
foundSomething_(false),
|
||||||
latch_(reader),
|
latch_(reader),
|
||||||
resources_(resources) {}
|
pool_(pool) {}
|
||||||
|
|
||||||
template <typename TFilter>
|
template <typename TFilter>
|
||||||
DeserializationError parse(VariantData& variant, TFilter filter,
|
DeserializationError parse(VariantData& variant, TFilter filter,
|
||||||
@@ -34,7 +35,7 @@ class JsonDeserializer {
|
|||||||
|
|
||||||
err = parseVariant(variant, filter, nestingLimit);
|
err = parseVariant(variant, filter, nestingLimit);
|
||||||
|
|
||||||
if (!err && latch_.last() != 0 && variant.isFloat()) {
|
if (!err && latch_.last() != 0 && !variant.isEnclosed()) {
|
||||||
// We don't detect trailing characters earlier, so we need to check now
|
// We don't detect trailing characters earlier, so we need to check now
|
||||||
return DeserializationError::InvalidInput;
|
return DeserializationError::InvalidInput;
|
||||||
}
|
}
|
||||||
@@ -146,7 +147,7 @@ class JsonDeserializer {
|
|||||||
|
|
||||||
template <typename TFilter>
|
template <typename TFilter>
|
||||||
DeserializationError::Code parseArray(
|
DeserializationError::Code parseArray(
|
||||||
ArrayData& array, TFilter filter,
|
CollectionData& array, TFilter filter,
|
||||||
DeserializationOption::NestingLimit nestingLimit) {
|
DeserializationOption::NestingLimit nestingLimit) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
@@ -166,18 +167,18 @@ class JsonDeserializer {
|
|||||||
if (eat(']'))
|
if (eat(']'))
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
|
|
||||||
TFilter elementFilter = filter[0UL];
|
TFilter memberFilter = filter[0UL];
|
||||||
|
|
||||||
// Read each value
|
// Read each value
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (elementFilter.allow()) {
|
if (memberFilter.allow()) {
|
||||||
// Allocate slot in array
|
// Allocate slot in array
|
||||||
VariantData* value = array.addElement(resources_);
|
VariantData* value = array.addElement(pool_);
|
||||||
if (!value)
|
if (!value)
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
// 1 - Parse value
|
// 1 - Parse value
|
||||||
err = parseVariant(*value, elementFilter, nestingLimit.decrement());
|
err = parseVariant(*value, memberFilter, nestingLimit.decrement());
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
} else {
|
} else {
|
||||||
@@ -232,7 +233,7 @@ class JsonDeserializer {
|
|||||||
|
|
||||||
template <typename TFilter>
|
template <typename TFilter>
|
||||||
DeserializationError::Code parseObject(
|
DeserializationError::Code parseObject(
|
||||||
ObjectData& object, TFilter filter,
|
CollectionData& object, TFilter filter,
|
||||||
DeserializationOption::NestingLimit nestingLimit) {
|
DeserializationOption::NestingLimit nestingLimit) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
@@ -268,26 +269,29 @@ class JsonDeserializer {
|
|||||||
if (!eat(':'))
|
if (!eat(':'))
|
||||||
return DeserializationError::InvalidInput;
|
return DeserializationError::InvalidInput;
|
||||||
|
|
||||||
JsonString key = stringBuilder_.str();
|
JsonString key = stringStorage_.str();
|
||||||
|
|
||||||
TFilter memberFilter = filter[key.c_str()];
|
TFilter memberFilter = filter[key.c_str()];
|
||||||
|
|
||||||
if (memberFilter.allow()) {
|
if (memberFilter.allow()) {
|
||||||
auto member = object.getMember(adaptString(key.c_str()), resources_);
|
VariantData* variant = object.getMember(adaptString(key.c_str()));
|
||||||
if (!member) {
|
if (!variant) {
|
||||||
// Save key in memory pool.
|
// Save key in memory pool.
|
||||||
auto savedKey = stringBuilder_.save();
|
// This MUST be done before adding the slot.
|
||||||
|
key = stringStorage_.save();
|
||||||
|
|
||||||
// Allocate slot in object
|
// Allocate slot in object
|
||||||
member = object.addMember(savedKey, resources_);
|
VariantSlot* slot = object.addSlot(pool_);
|
||||||
if (!member)
|
if (!slot)
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
} else {
|
|
||||||
member->setNull(resources_);
|
slot->setKey(key);
|
||||||
|
|
||||||
|
variant = slot->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse value
|
// Parse value
|
||||||
err = parseVariant(*member, memberFilter, nestingLimit.decrement());
|
err = parseVariant(*variant, memberFilter, nestingLimit.decrement());
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
} else {
|
} else {
|
||||||
@@ -373,7 +377,7 @@ class JsonDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DeserializationError::Code parseKey() {
|
DeserializationError::Code parseKey() {
|
||||||
stringBuilder_.startString();
|
stringStorage_.startString();
|
||||||
if (isQuote(current())) {
|
if (isQuote(current())) {
|
||||||
return parseQuotedString();
|
return parseQuotedString();
|
||||||
} else {
|
} else {
|
||||||
@@ -384,13 +388,13 @@ class JsonDeserializer {
|
|||||||
DeserializationError::Code parseStringValue(VariantData& variant) {
|
DeserializationError::Code parseStringValue(VariantData& variant) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
stringBuilder_.startString();
|
stringStorage_.startString();
|
||||||
|
|
||||||
err = parseQuotedString();
|
err = parseQuotedString();
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
variant.setOwnedString(stringBuilder_.save());
|
variant.setString(stringStorage_.save());
|
||||||
|
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
}
|
}
|
||||||
@@ -426,9 +430,9 @@ class JsonDeserializer {
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
if (codepoint.append(codeunit))
|
if (codepoint.append(codeunit))
|
||||||
Utf8::encodeCodepoint(codepoint.value(), stringBuilder_);
|
Utf8::encodeCodepoint(codepoint.value(), stringStorage_);
|
||||||
#else
|
#else
|
||||||
stringBuilder_.append('\\');
|
stringStorage_.append('\\');
|
||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -440,10 +444,10 @@ class JsonDeserializer {
|
|||||||
move();
|
move();
|
||||||
}
|
}
|
||||||
|
|
||||||
stringBuilder_.append(c);
|
stringStorage_.append(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stringBuilder_.isValid())
|
if (!stringStorage_.isValid())
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
@@ -456,14 +460,14 @@ class JsonDeserializer {
|
|||||||
if (canBeInNonQuotedString(c)) { // no quotes
|
if (canBeInNonQuotedString(c)) { // no quotes
|
||||||
do {
|
do {
|
||||||
move();
|
move();
|
||||||
stringBuilder_.append(c);
|
stringStorage_.append(c);
|
||||||
c = current();
|
c = current();
|
||||||
} while (canBeInNonQuotedString(c));
|
} while (canBeInNonQuotedString(c));
|
||||||
} else {
|
} else {
|
||||||
return DeserializationError::InvalidInput;
|
return DeserializationError::InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stringBuilder_.isValid())
|
if (!stringStorage_.isValid())
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
@@ -655,10 +659,10 @@ class JsonDeserializer {
|
|||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder stringBuilder_;
|
TStringStorage stringStorage_;
|
||||||
bool foundSomething_;
|
bool foundSomething_;
|
||||||
Latch<TReader> latch_;
|
Latch<TReader> latch_;
|
||||||
ResourceManager* resources_;
|
MemoryPool* pool_;
|
||||||
char buffer_[64]; // using a member instead of a local variable because it
|
char buffer_[64]; // using a member instead of a local variable because it
|
||||||
// ended in the recursive path after compiler inlined the
|
// ended in the recursive path after compiler inlined the
|
||||||
// code
|
// code
|
||||||
@@ -669,27 +673,21 @@ ARDUINOJSON_END_PRIVATE_NAMESPACE
|
|||||||
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||||
// https://arduinojson.org/v7/api/json/deserializejson/
|
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||||
template <typename TDestination, typename... Args>
|
template <typename... Args>
|
||||||
typename detail::enable_if<
|
DeserializationError deserializeJson(JsonDocument& doc, Args&&... args) {
|
||||||
detail::is_deserialize_destination<TDestination>::value,
|
|
||||||
DeserializationError>::type
|
|
||||||
deserializeJson(TDestination&& dst, Args&&... args) {
|
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
|
return deserialize<JsonDeserializer>(doc, detail::forward<Args>(args)...);
|
||||||
detail::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||||
// https://arduinojson.org/v7/api/json/deserializejson/
|
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||||
template <typename TDestination, typename TChar, typename... Args>
|
template <typename TChar, typename... Args>
|
||||||
typename detail::enable_if<
|
DeserializationError deserializeJson(JsonDocument& doc, TChar* input,
|
||||||
detail::is_deserialize_destination<TDestination>::value,
|
Args&&... args) {
|
||||||
DeserializationError>::type
|
|
||||||
deserializeJson(TDestination&& dst, TChar* input, Args&&... args) {
|
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
|
return deserialize<JsonDeserializer>(doc, input,
|
||||||
input, detail::forward<Args>(args)...);
|
detail::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
68
lib/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp
Executable file → Normal file
68
lib/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
// ArduinoJson - https://arduinojson.org
|
||||||
// Copyright © 2014-2024, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -7,96 +7,93 @@
|
|||||||
#include <ArduinoJson/Json/TextFormatter.hpp>
|
#include <ArduinoJson/Json/TextFormatter.hpp>
|
||||||
#include <ArduinoJson/Serialization/measure.hpp>
|
#include <ArduinoJson/Serialization/measure.hpp>
|
||||||
#include <ArduinoJson/Serialization/serialize.hpp>
|
#include <ArduinoJson/Serialization/serialize.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantDataVisitor.hpp>
|
#include <ArduinoJson/Variant/Visitor.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
template <typename TWriter>
|
template <typename TWriter>
|
||||||
class JsonSerializer : public VariantDataVisitor<size_t> {
|
class JsonSerializer : public Visitor<size_t> {
|
||||||
public:
|
public:
|
||||||
static const bool producesText = true;
|
static const bool producesText = true;
|
||||||
|
|
||||||
JsonSerializer(TWriter writer, const ResourceManager* resources)
|
JsonSerializer(TWriter writer) : formatter_(writer) {}
|
||||||
: formatter_(writer), resources_(resources) {}
|
|
||||||
|
|
||||||
size_t visit(const ArrayData& array) {
|
FORCE_INLINE size_t visitArray(const CollectionData& array) {
|
||||||
write('[');
|
write('[');
|
||||||
|
|
||||||
auto slotId = array.head();
|
const VariantSlot* slot = array.head();
|
||||||
|
|
||||||
while (slotId != NULL_SLOT) {
|
|
||||||
auto slot = resources_->getSlot(slotId);
|
|
||||||
|
|
||||||
|
while (slot != 0) {
|
||||||
slot->data()->accept(*this);
|
slot->data()->accept(*this);
|
||||||
|
|
||||||
slotId = slot->next();
|
slot = slot->next();
|
||||||
|
if (slot == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
if (slotId != NULL_SLOT)
|
write(',');
|
||||||
write(',');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write(']');
|
write(']');
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visit(const ObjectData& object) {
|
size_t visitObject(const CollectionData& object) {
|
||||||
write('{');
|
write('{');
|
||||||
|
|
||||||
auto slotId = object.head();
|
const VariantSlot* slot = object.head();
|
||||||
|
|
||||||
while (slotId != NULL_SLOT) {
|
|
||||||
auto slot = resources_->getSlot(slotId);
|
|
||||||
|
|
||||||
|
while (slot != 0) {
|
||||||
formatter_.writeString(slot->key());
|
formatter_.writeString(slot->key());
|
||||||
write(':');
|
write(':');
|
||||||
slot->data()->accept(*this);
|
slot->data()->accept(*this);
|
||||||
|
|
||||||
slotId = slot->next();
|
slot = slot->next();
|
||||||
|
if (slot == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
if (slotId != NULL_SLOT)
|
write(',');
|
||||||
write(',');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write('}');
|
write('}');
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visit(JsonFloat value) {
|
size_t visitFloat(JsonFloat value) {
|
||||||
formatter_.writeFloat(value);
|
formatter_.writeFloat(value);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visit(const char* value) {
|
size_t visitString(const char* value) {
|
||||||
formatter_.writeString(value);
|
formatter_.writeString(value);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visit(JsonString value) {
|
size_t visitString(const char* value, size_t n) {
|
||||||
formatter_.writeString(value.c_str(), value.size());
|
formatter_.writeString(value, n);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visit(RawString value) {
|
size_t visitRawJson(const char* data, size_t n) {
|
||||||
formatter_.writeRaw(value.data(), value.size());
|
formatter_.writeRaw(data, n);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visit(JsonInteger value) {
|
size_t visitSignedInteger(JsonInteger value) {
|
||||||
formatter_.writeInteger(value);
|
formatter_.writeInteger(value);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visit(JsonUInt value) {
|
size_t visitUnsignedInteger(JsonUInt value) {
|
||||||
formatter_.writeInteger(value);
|
formatter_.writeInteger(value);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visit(bool value) {
|
size_t visitBoolean(bool value) {
|
||||||
formatter_.writeBoolean(value);
|
formatter_.writeBoolean(value);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visit(nullptr_t) {
|
size_t visitNull() {
|
||||||
formatter_.writeRaw("null");
|
formatter_.writeRaw("null");
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
@@ -116,9 +113,6 @@ class JsonSerializer : public VariantDataVisitor<size_t> {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
TextFormatter<TWriter> formatter_;
|
TextFormatter<TWriter> formatter_;
|
||||||
|
|
||||||
protected:
|
|
||||||
const ResourceManager* resources_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
@@ -126,7 +120,7 @@ ARDUINOJSON_END_PRIVATE_NAMESPACE
|
|||||||
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
// Produces a minified JSON document.
|
// Produces a minified JSON document.
|
||||||
// https://arduinojson.org/v7/api/json/serializejson/
|
// https://arduinojson.org/v6/api/json/serializejson/
|
||||||
template <typename TDestination>
|
template <typename TDestination>
|
||||||
size_t serializeJson(JsonVariantConst source, TDestination& destination) {
|
size_t serializeJson(JsonVariantConst source, TDestination& destination) {
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
@@ -134,7 +128,7 @@ size_t serializeJson(JsonVariantConst source, TDestination& destination) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Produces a minified JSON document.
|
// Produces a minified JSON document.
|
||||||
// https://arduinojson.org/v7/api/json/serializejson/
|
// https://arduinojson.org/v6/api/json/serializejson/
|
||||||
inline size_t serializeJson(JsonVariantConst source, void* buffer,
|
inline size_t serializeJson(JsonVariantConst source, void* buffer,
|
||||||
size_t bufferSize) {
|
size_t bufferSize) {
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
@@ -142,7 +136,7 @@ inline size_t serializeJson(JsonVariantConst source, void* buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Computes the length of the document that serializeJson() produces.
|
// Computes the length of the document that serializeJson() produces.
|
||||||
// https://arduinojson.org/v7/api/json/measurejson/
|
// https://arduinojson.org/v6/api/json/measurejson/
|
||||||
inline size_t measureJson(JsonVariantConst source) {
|
inline size_t measureJson(JsonVariantConst source) {
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
return measure<JsonSerializer>(source);
|
return measure<JsonSerializer>(source);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user