diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index b4f83fdf..41f32efa 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -10,7 +10,7 @@ assignees: '' *Before creating a new issue please check that you have:* * *searched the existing [issues](https://github.com/proddy/EMS-ESP/issues) (both open and closed)* -* *searched the [wiki help pages](https://bbqkees-electronics.nl/wiki/gateway/troubleshooting.html)* +* *searched the [documentation help section](https://emsesp.github.io/docs)* *Completing this template will help developers and contributors to address the issue. Try to be as specific and extensive as possible. If the information provided is not enough the issue will likely be closed.* @@ -29,7 +29,7 @@ assignees: '' *If applicable, add screenshots to help explain your problem.* **Device information** -*Copy-paste here the information as it is outputted by the device. You can get this information by from the telnet session using the `system` command and `info`.* +*Copy-paste here the information as it is outputted by the device. You can get this information by from http://ems-esp.local/api?device=system&cmd=report.* **Additional context** *Add any other context about the problem here.* diff --git a/.github/ISSUE_TEMPLATE/questions---troubleshooting.md b/.github/ISSUE_TEMPLATE/questions---troubleshooting.md index d7899796..2f608d24 100644 --- a/.github/ISSUE_TEMPLATE/questions---troubleshooting.md +++ b/.github/ISSUE_TEMPLATE/questions---troubleshooting.md @@ -10,7 +10,7 @@ assignees: '' *Before creating a new issue please check that you have:* * *searched the existing [issues](https://github.com/proddy/EMS-ESP/issues) (both open and closed)* -* *searched the [wiki help pages](https://bbqkees-electronics.nl/wiki/gateway/troubleshooting.html)* +* *searched the [documentation help section](https://emsesp.github.io/docs)* *Completing this template will help developers and contributors help you. Try to be as specific and extensive as possible. If the information provided is not enough the issue will likely be closed.* @@ -23,7 +23,7 @@ assignees: '' *If applicable, add screenshots to help explain your problem.* **Device information** -*Copy-paste here the information as it is outputted by the device. You can get this information by from the telnet session with the logging set to Verbose mode.* +*Copy-paste here the information as it is outputted by the device. You can get this information from http://ems-esp.local/api?device=system&cmd=report.* **Additional context** *Add any other context about the problem here.* diff --git a/.github/workflows/build_firmware.yml b/.github/workflows/build_firmware.yml new file mode 100644 index 00000000..4444e531 --- /dev/null +++ b/.github/workflows/build_firmware.yml @@ -0,0 +1,71 @@ +name: Build Firmware + +on: + push: + branches: + - dev + tags: + # - '*.*.*' + paths: + - 'CHANGELOG_LATEST.md' + +jobs: + + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Version + id: fetch_version + run: | + version=`grep -E '^#define EMSESP_APP_VERSION' ./src/version.h | awk '{print $3}' | sed 's/"//g'` + echo "::set-output name=s::$version" + + - name: Setup Python + uses: actions/setup-python@v1 + + - name: Install + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade + platformio update + + - name: Build web + run: | + cd interface + npm install + npm run build + + - name: Build images + run: | + platformio run -e esp8266 + platformio run -e esp32 + + - name: Delete + uses: dev-drprasad/delete-tag-and-release@v0.1.2 + # if: startsWith(github.ref, 'refs/tags/') + with: + delete_release: true + tag_name: dev + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Changelog + run: cat RELEASENOTES_DEV.md CHANGELOG_LATEST.md > BODY.txt + + - name: Release + uses: softprops/action-gh-release@v1 + # if: startsWith(github.ref, 'refs/tags/') + with: + body_path: BODY.txt + name: Development Build v${{steps.fetch_version.outputs.s}} + tag_name: dev + prerelease: true + files: | + ./build/firmware/*.* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + \ No newline at end of file diff --git a/.github/workflows/check_code.yml b/.github/workflows/check_code.yml new file mode 100644 index 00000000..a6bb1544 --- /dev/null +++ b/.github/workflows/check_code.yml @@ -0,0 +1,64 @@ +name: Code Check + +on: + push: + branches: [dev] + paths: + - 'src/**' + pull_request: + # The branches below must be a subset of the branches above + branches: [dev] + schedule: + - cron: '0 11 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + # Override automatic language detection by changing the below list + # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] + language: ['cpp'] + # Learn more... + # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/release_main.yml b/.github/workflows/release_main.yml new file mode 100644 index 00000000..d89e2f30 --- /dev/null +++ b/.github/workflows/release_main.yml @@ -0,0 +1,56 @@ +name: Release Main + +on: + workflow_dispatch: + branches: [ main ] + +jobs: + + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Version + id: fetch_version + run: | + version=`grep -E '^#define EMSESP_APP_VERSION' ./src/version.h | awk '{print $3}' | sed 's/"//g'` + echo "::set-output name=s::$version" + + - name: Setup Python + uses: actions/setup-python@v1 + + - name: Install + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade + platformio update + + - name: Build web + run: | + cd interface + npm install + npm run build + + - name: Build images + run: | + platformio run -e esp8266 + platformio run -e esp32 + + - name: Changelog + run: cat RELEASENOTES.md CHANGELOG_LATEST.md > BODY.txt + + - name: Release + uses: softprops/action-gh-release@v1 + with: + body_path: BODY.txt + name: EMS-ESP v${{steps.fetch_version.outputs.s}} + tag_name: v${{steps.fetch_version.outputs.s}} + prerelease: false + files: | + ./build/firmware/*.* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + \ No newline at end of file diff --git a/.github/workflows/standalone_build.yml b/.github/workflows/standalone_build.yml new file mode 100644 index 00000000..0b537939 --- /dev/null +++ b/.github/workflows/standalone_build.yml @@ -0,0 +1,22 @@ +name: Standalone Build + +on: + push: + branches: [ dev ] + paths: + - 'src/**' + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: make clean + run: make clean + + - name: make + run: make + \ No newline at end of file diff --git a/.gitignore b/.gitignore index b85d4d54..1176cfd0 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ pio_local.ini # project specfic /scripts/stackdmp.txt emsesp +firmware /data/www/ /lib/framework/WWWData.h /interface/build/ diff --git a/CHANGELOG.md b/CHANGELOG.md index e68eb1cf..260ead5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,11 @@ -# EMS-ESP Changelog +# Changelog 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/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.0.1] +## [2.0.1] September 13 2020 ### Added - Able to set individual MQTT publish intervals per device @@ -47,7 +47,7 @@ First version of v2 with - Support for Home Assistant MQTT Discovery (https://www.home-assistant.io/docs/mqtt/discovery/) - Can be run standalone as an independent Access Point or join an existing WiFi network - Easier first-time configuration via a web Captive Portal -- Supporting over 70 EMS devices (boilers, thermostats, solar modules, mixing modules, heat pumps, gateways) +- Supporting over 70 EMS devices (boilers, thermostats, solar modules, mixer modules, heat pumps, gateways) See README.me for more details. @@ -105,7 +105,7 @@ There are breaking changes in this release. See `publish_time` below and make su - Added `kick` command to reset core services like NTP, Web, Web Sockets - Added WiFi static IP (setting done in WebUI only) - `log w ` for watching a specific telegram type ID -- initial support for EMS+ GB125s and MC110's (https://github.com/proddy/EMS-ESP/wiki/MC110-controller) +- initial support for EMS+ GB125s and MC110's - Buderus RFM200 receiver ### Fixed @@ -149,7 +149,7 @@ There are breaking changes in this release. See `publish_time` below and make su ## [1.9.2] 2019-10-19 #### Important! This build has breaking changes: - - MQTT topics have changed. Use the `mqttlog` command to see the names of the subscriptions and the format of the payload data. Also reference the [Wiki page](https://github.com/proddy/EMS-ESP/wiki/MQTT). + - MQTT topics have changed. Use the `mqttlog` command to see the names of the subscriptions and the format of the payload data. - Home Assistant `.yaml` files need updating to reflect the recent MQTT changes - The web builder has been upgraded to use Gulp 4. Remove `tools/webfilesbuilder/node_modules` and re-install the libraries using `npm ci` from within the `tools/webfilesbuilder` folder @@ -199,7 +199,7 @@ There are breaking changes in this release. See `publish_time` below and make su - Web login password is now mandatory - Faster detection of EMS devices on bus by using the 0x07 telegram instead of the brute-force scan - Fixes to the default HA climate component .yaml file to support latest Home Assistance ('heat' added) -- Update documentation in Wiki on MQTT and troubleshooting +- Update documentation on MQTT and troubleshooting - Slowed down firmware upload via the Web to prevent users rebooting too early - Change way WiFi is initialized to prevent dual AP and Client @@ -212,7 +212,7 @@ There are breaking changes in this release. See `publish_time` below and make su ### Changed -- New web interface with more features showing Boiler, Thermostat, Solar Module and Heat Pump. See https://github.com/proddy/EMS-ESP/wiki/Running-and-Monitoring +- New web interface with more features showing Boiler, Thermostat, Solar Module and Heat Pump. - Merged with @susisstrolch's TxMode2 branch for improved support for sending EMS packages. This is the default tx mode. - Upgraded MyESP library optimizations for WiFi, AP and error handling - `reboot` command renamed to `restart` to keep consistent with web interface @@ -228,12 +228,12 @@ There are breaking changes in this release. See `publish_time` below and make su ### Added - Added back -DCRASH in Debug build target for capturing any ESP8266 stack dumps during crashes -- Web Interface, for checking stats and setting wifi credentials. See wiki for more details. +- Web Interface, for checking stats and setting wifi credentials. See documentation for more details. - reset firmware option. If the reset button on the ESP is pressed during boot up sequence (the LED is flashing very fast) all settings are erased and goes into AP mode. - Added tx_mode back with options 0,1 and 2 until we've fixed option 2 that works for everyone and doesn't reset ESP - More solar module data captured, thanks to @Vuego123 - Detect thermostat mode for EMS+ RC300/Moduline 3000 -- MQTT message to set boiler flowtemp (`boiler_cmd_flowtemp`). See [wiki](https://github.com/proddy/EMS-ESP/wiki/MQTT). +- MQTT message to set boiler flowtemp (`boiler_cmd_flowtemp`). ### Fixed diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md new file mode 100644 index 00000000..aaa46ae5 --- /dev/null +++ b/CHANGELOG_LATEST.md @@ -0,0 +1,51 @@ +# Changelog + +### Added +- boiler `heatingactivated`, automatic select parameter telegrams for write +- boiler `wWType` parameter, in Console and MQTT +- support for uploading compressed firmware binaries in web UI +- setting to manually override the MQTT retain flag +- New API via HTTP REST API to read and set values. See https://emsesp.github.io/docs/#/API +- `show commands` command +- exporting of system settings using the `system info` command in Web and Console. Added link into the Web's Settings page. +- setting to change how booleans are rendered in MQTT (on/off, true/false, 1/0) +- enable ADC setting, add boiler circulation commands, add thermostat RC300 summermodes +- Added all device info to web UI for Thermostat and Boiler +- Added all device values to Home Assistant MQTT Discovery under separate devices and entities +- Show Rx and Tx quality in Console and Web UI +- Added button and tooltip to EMS Devices in Web +- wwtemp and wwtemplow to MQTT, Console and Web +- summer, winter modes for the CW400 thermostat +- new command under system called `report`. http://ems-esp/api?device=system&cmd=report to generate a report log for troubleshooting +- thermostat error codes +- Console command `publish ha` to also force the creation of the Home Assistant MQTT Discovery topics +- Heat pump values (dew temperature and relative air humidity) +- Console up key to repeat last command +- added RC300 floordrying, building, damped temperature + +### Fixed +- fix wwontime readback +- fixed support for RC300 via MQTT commands (#505) +- Some minor optimizations to memory handling in the MQTT service +- Prevent MQTT from publishing empty json payloads +- Accurate detection of warm water and heating (#515) +- Fix writing to the Junkers FR120 thermostat +- support for changing summermode +- added missing `heatingtype` to thermostat data +- handle incomming ems+ read requests, ignore F7 telegrams with 3byte-id +- fix month for setting clock from NTP + +### Changed +- renamed wWCircPumpType to wWChargeType +- Installation and Configuration notes moved to the official EMS-ESP documentation site +- `call` commands can be done from the Console root for all devices +- Updated EMS-ESP official documentation (https://emsesp.github.io/docs/#/) +- JWT Secret renamed to Super User Password +- EMS Devices in Web UI shows button and tooltip to remind users they can click on a device +- MQTT topic name changes (see doc) +- Mixing renamed to Mixer + +### Removed +- Console contexts for thermostat and boiler +- Removed option to enable/disable the MQTT Heartbeat. It's always on. + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b357c928..8cf6e4d6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,5 @@ Logo - # Contributing **Any contribution helps EMS-ESP get better for the entire community!** @@ -9,7 +8,7 @@ Everybody is welcome and invited to contribute to the EMS-ESP Project by: - providing Pull Requests (Features, Fixes, suggestions) - testing new released features and report issues on your EMS equipment -- contributing missing [documentation](https://emsesp.github.io/docs) for features and devices +- contributing to missing [documentation](https://emsesp.github.io/docs) This document describes rules that are in effect for this repository, meant for handling issues by contributors in the issue tracker and PRs. @@ -29,7 +28,7 @@ This document describes rules that are in effect for this repository, meant for 2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor. 3. Issues that are accepted should be marked with appropriate labels. 4. Issues that could impact functionality for many users should be considered severe. -5. Issues caused by the SDK or chip should not be marked severe, as there usually isn’t much to be done. Common sense should be applied when deciding. Such issues should be documented in the Wiki, for reference by users. +5. Issues caused by the SDK or chip should not be marked severe, as there usually isn’t much to be done. Common sense should be applied when deciding. Such issues should be documented in the documentation, for reference by users. 6. Issues with feature requests should be discussed for viability/desirability. 7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified. 8. Feature requests that are not accompanied by a PR: @@ -50,15 +49,16 @@ The process is straight-forward. - Create a Pull Request against the [**dev**](https://github.com/proddy/EMS-ESP/tree/dev) branch of EMS-ESP. 1. All pull requests must be done against the dev branch. -2. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled). -3. Only one feature/fix should be added per PR. -4. PRs that don't compile (fail in CI Tests) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in dev - you might need to rebase and resolve conflicts. -5. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner. -6. All pull requests should consider updates to the documentation. -7. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. -8. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. -9. By submitting a PR, it is needed to use the provided PR template and check all boxes, performing the required tasks and accepting the CLA. -10. Pull requests that don't meet the above will be denied and closed. +2. Make sure code is formatting per the `.clang-format` +3. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled). +4. Only one feature/fix should be added per PR. +5. PRs that don't compile (fail in CI Tests) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in dev - you might need to rebase and resolve conflicts. +6. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner. +7. All pull requests should consider updates to the documentation. +8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. +9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. +10. By submitting a PR, it is needed to use the provided PR template and check all boxes, performing the required tasks and accepting the CLA. +11. Pull requests that don't meet the above will be denied and closed. -------------------------------------- @@ -91,8 +91,6 @@ This Contributor License Agreement (CLA) was adopted on April 1st, 2019. The text of this license is available under the [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). It is based on the Linux [Developer Certificate Of Origin](http://elinux.org/Developer_Certificate_Of_Origin), but is modified to explicitly use the GPL-3.0 license and not mention sign-off (due to GitHub.com keeps an historial, with your user name, of PRs' commits and all editions on PR's comments). -To accept the CLA it is required to put a x between [ ] on `[ ] I accept the CLA` in the PR template when submitting it. The [ ] is an opt-in box, so you have to manually accept it. - **Why a CLA ?** _"A Contributor Licence Agreement (CLA) is strongly recommended when accepting third party contributions to an open development project, such as an open source software project. In order to redistribute contributions, it is necessary to ensure that the project has the necessary rights to do so. A Contributor Licence Agreement is a lightweight agreement, signed by the copyright holder, that grants the necessary rights for the contribution to be redistributed as part of the project."_ [OSS Watch](http://oss-watch.ac.uk/resources/cla) diff --git a/README.md b/README.md index 951b8773..164076b1 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,10 @@ **EMS-ESP** is an open-source firmware for the Espressif ESP8266 and ESP32 microcontroller that communicates with **EMS** (Energy Management System) based equipment from manufacturers like Bosch, Buderus, Nefit, Junkers, Worcester and Sieger. -[![version](https://img.shields.io/github/release/proddy/EMS-ESP.svg?label=Latest%20Release)](https://github.com/proddy/EMS-ESP/blob/master/CHANGELOG.md) +[![version](https://img.shields.io/github/release/proddy/EMS-ESP.svg?label=Latest%20Release)](https://github.com/proddy/EMS-ESP/blob/main/CHANGELOG.md) [![release-date](https://img.shields.io/github/release-date/proddy/EMS-ESP.svg?label=Released)](https://github.com/proddy/EMS-ESP/commits/master) [![license](https://img.shields.io/github/license/proddy/EMS-ESP.svg)](LICENSE) -[![travis](https://travis-ci.com/proddy/EMS-ESP.svg?branch=dev)](https://travis-ci.com/proddy/EMS-ESP) +![Build Firmware](https://github.com/proddy/EMS-ESP/workflows/Build%20Firmware/badge.svg?branch=dev) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/b8880625bdf841d4adb2829732030887)](https://app.codacy.com/app/proddy/EMS-ESP?utm_source=github.com&utm_medium=referral&utm_content=proddy/EMS-ESP&utm_campaign=Badge_Grade_Settings) [![downloads](https://img.shields.io/github/downloads/proddy/EMS-ESP/total.svg)](https://github.com/proddy/EMS-ESP/releases) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/proddy/EMS-ESP.svg)](http://isitmaintained.com/project/proddy/EMS-ESP "Average time to resolve an issue") @@ -19,152 +19,80 @@ If you like **EMS-ESP**, please give it a star, or fork it and contribute! [![GitHub forks](https://img.shields.io/github/forks/proddy/EMS-ESP.svg?style=social&label=Fork)](https://github.com/proddy/EMS-ESP/network) [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.com/paypalme/prderbyshire/2) -Note, EMS-ESP requires a small hardware circuit that can convert the EMS bus data to be read by the microcontroller. These can be purchased at https://bbqkees-electronics.nl/. +Note, EMS-ESP requires a small hardware circuit that can convert the EMS bus data to be read by the microcontroller. These can be ordered at https://bbqkees-electronics.nl. --- -## **New Features in version 2** +## **Features** -- Support for both ESP8266 and ESP32 modules -- A new multi-user Web interface (based on React/TypeScript) -- A new Console, accessible via Serial and Telnet -- Tighter security in both Web and Console. Admin privileges required to access core settings and commands. -- Support for Home Assistant MQTT Discovery (https://www.home-assistant.io/docs/mqtt/discovery/) -- Can be run standalone as an independent Access Point or join an existing WiFi network -- Easier first-time configuration via a web Captive Portal -- Supporting over 70 EMS devices (boilers, thermostats, solar modules, mixing modules, heat pumps, gateways) +- Compatible with both ESP8266 and ESP32 +- A multi-user secure web interface to change settings and monitor the data +- A console, accessible via Serial and Telnet for more monitoring +- Native support for Home Assistant via [MQTT Discovery](https://www.home-assistant.io/docs/mqtt/discovery/) +- Can run standalone as an independent WiFi Access Point or join an existing WiFi network +- Easy first-time configuration via a web Captive Portal +- Support for more than [70 EMS devices](https://emsesp.github.io/docs/#/Supported-EMS-Devices) (boilers, thermostats, solar modules, mixer modules, heat pumps, gateways) ## **Screenshots** +### Web Interface: + | | | | --- | --- | | | | | | | - - -## **Migrating from versions 1.9** - -EMS-ESP will attempt to automatically migrate the 1.9 settings. - -Note there are some noticeable differences to be aware of in version 2: -### MQTT: - - MQTT base has been removed. All MQTT topics are prefixed with only the hostname, for example `ems-esp/status` as opposed to `home/ems-esp/status`. - - `heatPmp` renamed to `heatPump` - - `ServiceCodeNumber` renamed to `serviceCodeNumber` - - Firmware version has been moved to the `start` topic - - `desinfection` renamed to `disinfection` - -### General: - - There is no "serial mode" anymore like with version 1.9. When the Wifi cannot connect to the SSID it will automatically enter a "safe" mode where the Serial console is activated (note Serial is always available on the ESP32 because it has multiple UARTs). The EMS-ESP's LED will blink fast when in Serial mode. When this happens connect via a USB using baud 115200. - -If you run into issues try first erasing the ESP8266 with `esptool.py erase_flash` and uploading the new firmware manually. BBQKees has a good write-up at https://bbqkees-electronics.nl/wiki/gateway/firmware-update-to-v2.html. - -## **Building the firmware using PlatformIO** - -1. Install [PlatformIO](https://platformio.org/install) and [NodeJS](https://nodejs.org/en/). -2. Decide how you want to upload the firmware, via USB or OTA (Over The Air). OTA requires that a version of EMS-ESP is already running. -3. Create a new file called `pio_local.ini` and add these two lines for USB: -```yaml -upload_protocol = esptool -upload_port = -``` -or these 2 for OTA: -```yaml -upload_protocol = espota -upload_flags = - --port=8266 - --auth=ems-esp-neo -upload_port = ems-esp.local -``` -3. type `pio run -t upload` to build and upload the firmware - -## **Uploading the firmware** - -Here we'll use the command-line. You'll need [Python]( https://www.python.org/downloads/) (version 3) installed and these 2 scripts: -- `esptool.py`. Install using `pip install esptool`. -- `espota.py` downloaded from https://github.com/esp8266/Arduino/blob/master/tools/espota.py +### Telnet Console: + -Both these tools are also in the repo in the `scripts` directory. - -Next step is to fetch the latest firmware binary from https://github.com/proddy/EMS-ESP/releases, and if you're using USB with an ESP8266: - - `esptool.py -p -b 921600 write_flash 0x00000 ` - -and for OTA: - - `espota.py --debug --progress --port 8266 --auth ems-esp-neo -i -f ` - -## **Configuring EMS-ESP for the first time** - - - After powering up the ESP, watch the onboard blue LED. A solid light means good connection and EMS data is coming in. A slow pulse means either the WiFi or the EMS bus is not connected yet. A very fast pulse is when the system is booting up and configuring itself which typically takes 5 seconds. +### In Home Assistant: + - - Connect to the Access Point called `ems-esp` using the WPA password `ems-esp-neo`. When you see the captive portal sign-in with username `admin` and password `admin`. Set the WiFi credentials and go back to http://ems-esp. Remember to change the passwords! - - - First thing to check is if Tx is working and that you have a connection to the EMS bus. If Tx fails are shown in the Web interface try changing the Tx Mode from the settings page. There is no need to re-start the EMS-ESP. +## **Installing** - - If Rx incomplete telegrams are reported in the Web interface, don't panic. Some telegrams can be missed and this is usually caused by noise interference on the line. +Refer to the [official documentation](https://emsesp.github.io/docs) to how to install the firmware and configure it. The documentation is being constantly updated as new features and settings are added. -## **Using the Console** +You can choose to use an pre-built firmware image or compile the code yourself: -Connecting to the console will give you more insight into the EMS bus traffic, MQTT queues and the full device information. - -The console is reachable via Telnet (port 22) or via the Serial port if using an USB (on baud 115200). To change any settings in the console you must be admin (use `su` with the default password `ems-esp-neo`). - -Some of the most common commands are: - * `help` lists the commands and keywords. This works in each context. - * `exit` will exit the console or exit the current context. `CTRL-D` does the same. - * `CTRL-U` for Undo - * `` for auto-complete - * Some specific commands are behind contexts. Think of this as a sub-menu. e.g. `system`, `thermostat`. The path will always show you which context you are in. `$` is the root. - * `su` will switch to the Admin super-user. The default password is `ems-esp-neo` and can be changed with `passwd` from the system menu or via the Web interface (called secret password). When in Admin mode the command prompt switches from `$` to `#`. - * Some settings can be changed in the console. The `set` command will list them. - * `show` shows the data specific to the which context you're in. From the root it will show you all the EMS device information and any external temperature sensors. - * `log` sets the logging level. `log off` disables logging. Use `log debug` for debugging commands and actions. This will be reset next time the console is opened. - * `watch` will output the incoming Rx telegrams directly to the console. You can also put on a watch on a specific EMS device ID or telegram ID. Also choose to output as verbose text as raw data bytes. - -The `call` command is to execute a command. The command names (`[cmd]`) are the same as the MQTT commands used in MQTT. - -For further details refer to the [Wiki](https://bbqkees-electronics.nl/wiki/). +* [Uploading a pre-built firmware build](https://emsesp.github.io/docs/#/Uploading-firmware) +* [Building the firmware from source code and flashing manually](https://emsesp.github.io/docs/#/Building-firmware) ## **Support Information** -For a list of the EMS devices currently supported see BBQKees's [EMS device compatibility list](https://bbqkees-electronics.nl/ems-device-compatibility/). - If you're looking for support on **EMS-ESP** there are some options available: ### Documentation -* [Documentation Site](https://bbqkees-electronics.nl/wiki/): For information on how to build and upload the firmware maintained by @BBQKees -* [FAQ and Troubleshooting](https://bbqkees-electronics.nl/wiki/gateway/troubleshooting.html): For information on common problems and solutions +* [Official EMS-ESP Documentation](https://emsesp.github.io/docs): For information on how to build and upload the firmware +* [FAQ and Troubleshooting](https://emsesp.github.io/docs/#/Troubleshooting): For information on common problems and solutions. See also [BBQKees's wiki](https://bbqkees-electronics.nl/wiki/gateway/troubleshooting.html) -### Support's Community +### Support Community * [EMS-ESP Support Chat](https://gitter.im/EMS-ESP/community#): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the community * [Search in Issues](https://github.com/proddy/EMS-ESP/issues): You might find an answer to your question by searching current or closed issues -### Developers' Community +### Developer's Community * [Bug Report](https://github.com/proddy/EMS-ESP/issues/new?template=bug_report.md): For reporting Bugs * [Feature Request](https://github.com/proddy/EMS-ESP/issues/new?template=feature_request.md): For requesting features/functions * [Troubleshooting](https://github.com/proddy/EMS-ESP/issues/new?template=questions---troubleshooting.md): As a last resort, you can open new *Troubleshooting & Question* issue on GitHub if the solution could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer -## **Contribute** +## **Contributing** You can contribute to EMS-ESP by -- providing Pull Requests (Features, Fixes, suggestions) -- testing new released features and report issues on your EMS equipment -- contributing missing [documentation](https://bbqkees-electronics.nl/wiki/) for features and devices +- providing Pull Requests (Features, Fixes, suggestions). +- testing new released features and report issues on your EMS equipment. +- contributing to missing [Documentation](https://emsesp.github.io/docs). ## **Credits** -A shout out to the people helping EMS-ESP get to where it is today -- @MichaelDvP for all his amazing contributions and patience. The core UART code is his. -- @BBQkees for his endless testing and building the awesome circuits -- @susisstrolch for writing a first working version of the EMS bridge circuit which I used to design EMS-ESP version 0.1 -- Plus many more providing suggestions, PRs and Donations. Thanks! +A shout out to the people helping EMS-ESP get to where it is today... +- **@MichaelDvP** for all his amazing contributions and patience. Specifically for the improved uart library, thermostat and mixer logic. +- **@BBQKees** for his endless testing and building the awesome circuit boards +- **@susisstrolch** for writing a first working version of the EMS bridge circuit which I used to design EMS-ESP version 0.1 back in August 2017 +- plus everyone else providing suggestions, PRs and the odd donation that keep us motivated. Thanks! ## **License** diff --git a/RELEASENOTES.md b/RELEASENOTES.md new file mode 100644 index 00000000..1a8605f4 --- /dev/null +++ b/RELEASENOTES.md @@ -0,0 +1,6 @@ +# ![logo](https://github.com/proddy/EMS-ESP/blob/main/media/EMS-ESP_logo_dark.png) + +# Firmware Installation + +Follow the instructions in the [documentation](https://emsesp.github.io/docs) on how to install the firmware binaries in the Assets below. + diff --git a/RELEASENOTES_DEV.md b/RELEASENOTES_DEV.md new file mode 100644 index 00000000..88cf53e9 --- /dev/null +++ b/RELEASENOTES_DEV.md @@ -0,0 +1,8 @@ +# ![logo](https://github.com/proddy/EMS-ESP/blob/main/media/EMS-ESP_logo_dark.png) + +This is a snapshot of the current "beta" development code and firmware binaries using the `dev` branch. It has all the latest features and fixes but please be aware that this is still experimental firmware used for testing and thus may contain the odd bug. Use at your own risk and remember to report an issue if you find something unusual. + +# Firmware Installation + +Follow the instructions in the [documentation](https://emsesp.github.io/docs) on how to install the firmware binaries in the Assets below. + diff --git a/doc/MQTT.md b/doc/MQTT.md deleted file mode 100644 index df9fc432..00000000 --- a/doc/MQTT.md +++ /dev/null @@ -1,55 +0,0 @@ -# **MQTT commands** - -All commands must be written as `{"cmd": ,"data":, "id":}`. - -The `id` can be replaced with `hc` for some devices that use heating circuits, and represented either as a string or a number. `cmd` is a string, `data` can be a string or number. - -topic = *boiler_cmd* -``` - comfort - flowtemp - wwtemp - boilhyston (negative value) - boilhystoff (positive value) - burnperiod - burnminpower <%> - burnmaxpower <%> - pumpdelay -``` - -topic = *thermostat_cmd* -``` ---- without hc --- - wwmode - calinttemp - minexttemp - building - language (0=de, 1=nl, 2=fr, 3=it) only RC30 - display (0=int temp, 1= int set, 2=ext. temp, 3=burner, 4=ww, 5=mode, 6=time, 7=date, 8=smoke) only RC30 - clockoffset (only RC30) - ---- with hc --- - mode - temp - nighttemp - daytemp - nofrosttemp - ecotemp - heattemp - summertemp - designtemp - offsettemp - holidaytemp - remotetemp - control <0 | 1 | 2> - pause - party - holiday - date -``` - -topic = *system_cmd* -``` - send <"0B XX XX .."> - pin -``` \ No newline at end of file diff --git a/doc/coding.md b/doc/coding.md deleted file mode 100644 index b0a4c13a..00000000 --- a/doc/coding.md +++ /dev/null @@ -1,80 +0,0 @@ -# Notes on customizing the code - -## **Basic Design Principles** - -- The core services like telnet, logging and shell are based off the libraries from @nomis. I also adopted his general design pattens such as making everything as asynchronous as possible so that no one operation should starve another operation of it's time to execute (https://isocpp.org/wiki/faq/ctors#static-init-order). -- All EMS devices (e.g. boiler, thermostat, solar modules, mixing units etc) are derived from a factory base class and each class handles its own registering of telegram and mqtt handlers. This makes the EMS device code easier to manage and we can extend with new telegrams types and features. -- For debugging there is an offline mode where the code can be compiled and executed standalone without uploading to an ESP controller. Use `make` (based off GNUMakefile). - -## **Customizing the Web UI** - -The Web is based off Rick's awesome [esp8266-react](https://github.com/rjwats/esp8266-react/) framework. These are the files that are modified: - -**`interface:`** - * `.env` project name and project path to ems-esp - * `.env.development` CORS URL - -**`interface/public:`** - * `app/manifest.json` ems-esp name - * `index.html` ems-esp name - * `app/icon.png` 256x256 PNG - * `favicon.ico` replaced - -**`interface/src:`** - * `CustomMuiTheme.tsx` colors for dark mode - * `interface/src/wifi/WifiSettingsController.tsx` rename esp8266-react - -**`interface/src/project:`** - * `ProjectRouting.tsx` removed demo, added paths to ems-esp/status, ems-esp/settings and * - * `DemoProject.tsx` remove /demo/ and changed title, renamed to EMSESP.tsx - * `ProjectMenu.tsx` title change, added /ems-esp/settings - * `DemoInformation.tsx` removed file - * `types.ts` add variables - * added all custom files starting with EMSESP* - -**`interface/src/mqtt:`** - * `types.ts` added mqtt_fails - * `MqttStatusForm.tsx` added MQTT Publish Errors - * `MqttStatus.ts` added function mqttPublishHighlight - * `MqttSettingsForm.tsx` added publish time, qos, format - -**`interface/src/authentication:`** - * `AuthenticationWrapper.tsx` commented out features.security because we added version - * `AuthenticationContext.tsx` added version - * `MqttSettingsForm.tsx` added publish time, qos, format - -**`interface/src/components:`** - * `MenuAppBar.tsx` added version to toolbar - -**`interface/src/system:`** - * `types.ts` added uptime and free_mem - * `SystemStatusForm.tsx` added system uptime, % free mem - -**`lib/framework`:** - * `SystemStatus.h` added #include , #include , #include "../../src/system.h" - * `SystemStatus.cpp` added LittleFS.info(fs_info); root["uptime"], root["free_mem"] - * Commented out all `Serial.print`'s in all files - * `MqttStatus.h` added #include "../../src/mqtt.h" - * `MqttStatus.cpp` added root["mqtt_fails"] - * `SecuritySettingsService.cpp` added version to the JWT payload - * `SecuritySettingsService.h` #include "../../src/version.h" - * `WiFiSettingsService.cpp` added WiFi.setOutputPower(20.0f), moved setHostname - * `OTASettingsService.h` added #include "../../src/system.h" - * `OTASettingsService.cpp` added call to emsesp::System::upload_status(true) - * `features.ini`: -D FT_NTP=0 - * `platformio.ini` using our own version - * `factory_settings.ini` modified with `ems-esp-neo` as password and `ems-esp` everywhere else - - -## To develop and test the Web UI -- uncomment the `-D ENABLE_CORS` in `platformio.ini` -```sh -cd interface -npm start -``` - -## To test the core, standalone with an ESP - -```sh -make run -``` diff --git a/doc/console.md b/doc/console.md deleted file mode 100644 index d4105c3d..00000000 --- a/doc/console.md +++ /dev/null @@ -1,72 +0,0 @@ -# **Console commands** - - -Connecting to the console will give you more insight into the EMS bus traffic, MQTT queues and the full device information. - -The console is reachable via Telnet (port 22) or via the Serial port if using an USB (on baud 115200). To change any settings in the console you must be admin (use `su` with the default password `ems-esp-neo`). - -Some of the most common commands are: - * `help` lists the commands and keywords. This works in each context. - * `exit` will exit the console or exit the current context. `CTRL-D` does the same. - * `CTRL-U` for Undo - * `` for auto-complete - * Some specific commands are behind contexts. Think of this as a sub-menu. e.g. `system`, `thermostat`. The path will always show you which context you are in. `$` is the root. - * `su` will switch to the Admin super-user. The default password is `ems-esp-neo` and can be changed with `passwd` from the system menu or via the Web interface (called secret password). When in Admin mode the command prompt switches from `$` to `#`. - * Some settings can be changed in the console. The `set` command will list them. - * `show` shows the data specific to the which context you're in. From the root it will show you all the EMS device information and any external temperature sensors. - * `log` sets the logging level. `log off` disables logging. Use `log debug` for debugging commands and actions. This will be reset next time the console is opened. - * `watch` will output the incoming Rx telegrams directly to the console. You can also put on a watch on a specific EMS device ID or telegram ID. Also choose to output as verbose text as raw data bytes. - -The `call` command is to execute a command. The command names (`[cmd]`) are the same as the MQTT commands used in MQTT. - -``` -(* = available in su/Admin mode) - -common commands available in all contexts: - exit - help - log [level] - watch [ID] - su - -(from the root) - system (enters a context) - boiler (enters a context) - thermostat (enters a context) - set - fetch - scan devices [deep] * - send telegram <"XX XX ..."> * - set bus_id * - set tx_mode * - show - show devices - show ems - show values - show mqtt - read * - -system - set - show - format * - show users * - passwd * - restart * - set wifi hostname * - set wifi password * - set wifi ssid * - wifi reconnect * - pin [data] * - -boiler - read * - call [cmd] [data] * - -thermostat - set - set master [device ID] * - read * - call [cmd] [data] [heating circuit] * - -``` \ No newline at end of file diff --git a/example_pio_local.ini b/example_pio_local.ini new file mode 100644 index 00000000..1c60ad8e --- /dev/null +++ b/example_pio_local.ini @@ -0,0 +1,6 @@ +[env] +upload_protocol = espota +upload_flags = + --port=8266 + --auth=ems-esp-neo +upload_port = ems-esp.local diff --git a/factory_settings.ini b/factory_settings.ini index 12a99b94..b8c4c81a 100644 --- a/factory_settings.ini +++ b/factory_settings.ini @@ -38,7 +38,7 @@ build_flags = -D FACTORY_MQTT_PASSWORD=\"\" -D FACTORY_MQTT_CLIENT_ID=\"ems-esp\" -D FACTORY_MQTT_KEEP_ALIVE=60 - -D FACTORY_MQTT_CLEAN_SESSION=false + -D FACTORY_MQTT_CLEAN_SESSION=true -D FACTORY_MQTT_MAX_TOPIC_LENGTH=128 ; JWT Secret diff --git a/interface/src/CustomMuiTheme.tsx b/interface/src/CustomMuiTheme.tsx index 971511ff..98caf131 100644 --- a/interface/src/CustomMuiTheme.tsx +++ b/interface/src/CustomMuiTheme.tsx @@ -25,7 +25,7 @@ const theme = createMuiTheme({ success: { main: green[500] } - }, + } }); export default class CustomMuiTheme extends Component { diff --git a/interface/src/mqtt/MqttSettingsForm.tsx b/interface/src/mqtt/MqttSettingsForm.tsx index 818c3954..21ab9192 100644 --- a/interface/src/mqtt/MqttSettingsForm.tsx +++ b/interface/src/mqtt/MqttSettingsForm.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { TextValidator, ValidatorForm, SelectValidator } from 'react-material-ui-form-validator'; -import { Checkbox, TextField } from '@material-ui/core'; +import { Checkbox, TextField, Typography } from '@material-ui/core'; import SaveIcon from '@material-ui/icons/Save'; import MenuItem from '@material-ui/core/MenuItem'; @@ -30,7 +30,7 @@ class MqttSettingsForm extends React.Component { value="enabled" /> } - label="Enable MQTT?" + label="Enable MQTT" /> { onChange={handleValueChange('keep_alive')} margin="normal" /> - - } - label="Clean Session?" - /> { onChange={handleValueChange('max_topic_length')} margin="normal" /> - - } - label="MQTT Heartbeat" - /> { Single Nested Home Assistant - Custom - 0 - 1 - 2 + 0 - At most once + 1 - At least once + 2 - Exactly once + + } + label="Clean Session" + /> + + } + label="Retain Flag" + /> +

+ + Publish Intervals + { validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']} errorMessages={['Publish time is required', "Must be a number", "Must be 0 or greater", "Max value is 65535"]} name="publish_time_thermostat" - label="MQTT Thermostat Publish Period (seconds, 0=on change)" + label="Thermostat Publish Interval (seconds, 0=on change)" fullWidth variant="outlined" value={data.publish_time_thermostat} @@ -177,7 +180,7 @@ class MqttSettingsForm extends React.Component { validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']} errorMessages={['Publish time is required', "Must be a number", "Must be 0 or greater", "Max value is 65535"]} name="publish_time_solar" - label="MQTT Solar Publish Period (seconds, 0=on change)" + label="Solar Publish Interval (seconds, 0=on change)" fullWidth variant="outlined" value={data.publish_time_solar} @@ -188,37 +191,37 @@ class MqttSettingsForm extends React.Component { diff --git a/interface/src/mqtt/types.ts b/interface/src/mqtt/types.ts index 7db88dbf..7558c3a1 100644 --- a/interface/src/mqtt/types.ts +++ b/interface/src/mqtt/types.ts @@ -30,10 +30,10 @@ export interface MqttSettings { publish_time_boiler: number; publish_time_thermostat: number; publish_time_solar: number; - publish_time_mixing: number; + publish_time_mixer: number; publish_time_other: number; publish_time_sensor: number; mqtt_format: number; mqtt_qos: number; - system_heartbeat: boolean; + mqtt_retain: boolean; } diff --git a/interface/src/ntp/NTPSettingsForm.tsx b/interface/src/ntp/NTPSettingsForm.tsx index c3e4dabd..d4370038 100644 --- a/interface/src/ntp/NTPSettingsForm.tsx +++ b/interface/src/ntp/NTPSettingsForm.tsx @@ -39,7 +39,7 @@ class NTPSettingsForm extends React.Component { value="enabled" /> } - label="Enable NTP?" + label="Enable NTP" /> body: { fontSize: 14, }, - }), + }) )(TableCell); function compareDevices(a: Device, b: Device) { @@ -58,39 +66,51 @@ interface EMSESPDevicesFormState { deviceData?: EMSESPDeviceData; } -type EMSESPDevicesFormProps = RestFormProps & AuthenticatedContextProps & WithWidthProps; +type EMSESPDevicesFormProps = RestFormProps & + AuthenticatedContextProps & + WithWidthProps; -class EMSESPDevicesForm extends Component { +function formatTemp(t: string) { + if (t == null) { + return "(not available)"; + } + return t + " °C"; +} +class EMSESPDevicesForm extends Component< + EMSESPDevicesFormProps, + EMSESPDevicesFormState +> { state: EMSESPDevicesFormState = { confirmScanDevices: false, - processing: false - } + processing: false, + }; noDevices = () => { - return (this.props.data.devices.length === 0); + return this.props.data.devices.length === 0; }; noSensors = () => { - return (this.props.data.sensors.length === 0); + return this.props.data.sensors.length === 0; }; noDeviceData = () => { - return (this.state.deviceData?.deviceData.length === 0); + return (this.state.deviceData?.deviceData || []).length === 0; }; createDeviceItems() { const { width, data } = this.props; return ( - - Devices - - - (click to show details) + + EMS Devices +

{!this.noDevices() && ( - +
Type @@ -99,45 +119,61 @@ class EMSESPDevicesForm extends ComponentDevice ID Product ID Version + - {data.devices.sort(compareDevices).map(device => ( - ( + this.handleRowClick(device.id)} > - {device.type} + + + + {device.brand} + {device.name} - {device.brand} - - - {device.name} - - - 0x{('00' + device.deviceid.toString(16).toUpperCase()).slice(-2)} - - - {device.productid} - - - {device.version} + 0x + {("00" + device.deviceid.toString(16).toUpperCase()).slice( + -2 + )} + {device.productid} + {device.version} + ))}
)} - {this.noDevices() && - ( - - - No EMS devices found. Check the connections and for possible Tx errors. - - - ) - } + {this.noDevices() && ( + + + No EMS devices found. Check the connections and for possible Tx + errors. + + + )}
); } @@ -148,39 +184,39 @@ class EMSESPDevicesForm extends Component

- Sensors + Dallas Sensors {!this.noSensors() && ( - ID + Sensor # + ID Temperature - {data.sensors.map(sensorData => ( - + {data.sensors.map((sensorData) => ( + - {sensorData.id} + {sensorData.no} + {sensorData.id} - {sensorData.temp.toFixed(1)}°C + {formatTemp(sensorData.temp)} ))}
)} - {this.noSensors() && - ( - - - No connected Dallas temperature sensors detected - - - ) - } + {this.noSensors() && ( + + + There are no external temperature sensors connected + + + )} ); } @@ -193,65 +229,88 @@ class EMSESPDevicesForm extends Component Confirm Scan Devices - Are you sure you want to initiate a scan on the EMS bus for all new devices? + Are you sure you want to initiate a scan on the EMS bus for all new + devices? - - - ) + ); } onScanDevices = () => { this.setState({ confirmScanDevices: true }); - } + }; onScanDevicesRejected = () => { this.setState({ confirmScanDevices: false }); - } + }; onScanDevicesConfirmed = () => { this.setState({ processing: true }); - redirectingAuthorizedFetch(SCANDEVICES_ENDPOINT).then(response => { - if (response.status === 200) { - this.props.enqueueSnackbar("Device scan is starting...", { variant: 'info' }); - this.setState({ processing: false, confirmScanDevices: false }); - } else { - throw Error("Invalid status code: " + response.status); - } - }) - .catch(error => { - this.props.enqueueSnackbar(error.message || "Problem with scan", { variant: 'error' }); + redirectingAuthorizedFetch(SCANDEVICES_ENDPOINT) + .then((response) => { + if (response.status === 200) { + this.props.enqueueSnackbar("Device scan is starting...", { + variant: "info", + }); + this.setState({ processing: false, confirmScanDevices: false }); + } else { + throw Error("Invalid status code: " + response.status); + } + }) + .catch((error) => { + this.props.enqueueSnackbar(error.message || "Problem with scan", { + variant: "error", + }); this.setState({ processing: false, confirmScanDevices: false }); }); - } + }; handleRowClick = (id: any) => { this.setState({ deviceData: undefined }); redirectingAuthorizedFetch(DEVICE_DATA_ENDPOINT, { - method: 'POST', + method: "POST", body: JSON.stringify({ id: id }), headers: { - 'Content-Type': 'application/json' - } - }).then(response => { - if (response.status === 200) { - return response.json(); - // this.setState({ errorMessage: undefined }, this.props.loadData); - } - throw Error("Unexpected response code: " + response.status); - }).then(json => { - this.setState({ deviceData: json }); - }).catch(error => { - this.props.enqueueSnackbar(error.message || "Problem getting device data", { variant: 'error' }); - this.setState({ deviceData: undefined }); - }); - } + "Content-Type": "application/json", + }, + }) + .then((response) => { + if (response.status === 200) { + return response.json(); + // this.setState({ errorMessage: undefined }, this.props.loadData); + } + throw Error("Unexpected response code: " + response.status); + }) + .then((json) => { + this.setState({ deviceData: json }); + }) + .catch((error) => { + this.props.enqueueSnackbar( + error.message || "Problem getting device data", + { variant: "error" } + ); + this.setState({ deviceData: undefined }); + }); + }; renderDeviceData() { const { deviceData } = this.state; @@ -265,40 +324,43 @@ class EMSESPDevicesForm extends Component

- - + + {deviceData.deviceName} - - - - - - - {deviceData.deviceData.map(deviceData => ( - - - {deviceData.name} - - - {deviceData.value} - - - ))} - -
-
+ {!this.noDeviceData() && ( + + + + + {deviceData.deviceData.map((deviceData) => ( + + + {deviceData.n} + + {deviceData.v} + + ))} + +
+
+ )} + {this.noDeviceData() && ( + + + No data available for this device + + + )} ); - } render() { @@ -311,21 +373,30 @@ class EMSESPDevicesForm extends Component
- } variant="contained" color="secondary" onClick={this.props.loadData}> + } + variant="contained" + color="secondary" + onClick={this.props.loadData} + > Refresh - } variant="contained" color="primary" onClick={this.onScanDevices}> + } + variant="contained" + color="primary" + onClick={this.onScanDevices} + > Scan Devices - + {this.renderScanDevicesDialog()} ); } - } export default withAuthenticatedContext(withWidth()(EMSESPDevicesForm)); diff --git a/interface/src/project/EMSESPHelp.tsx b/interface/src/project/EMSESPHelp.tsx index afa6131f..4e3fcebc 100644 --- a/interface/src/project/EMSESPHelp.tsx +++ b/interface/src/project/EMSESPHelp.tsx @@ -1,30 +1,80 @@ import React, { Component } from 'react'; -import { Typography, Box, Link } from '@material-ui/core'; +import { Typography, Box, List, ListItem, ListItemText, Link, ListItemAvatar } from '@material-ui/core'; import { SectionContent } from '../components'; +import CommentIcon from "@material-ui/icons/CommentTwoTone"; +import MenuBookIcon from "@material-ui/icons/MenuBookTwoTone"; +import GitHubIcon from "@material-ui/icons/GitHub"; +import StarIcon from "@material-ui/icons/Star"; +import ImportExportIcon from "@material-ui/icons/ImportExport"; +import BugReportIcon from "@material-ui/icons/BugReportTwoTone"; + +export const WebAPISystemInfo = window.location.origin + "/api?device=system&cmd=info"; +export const WebAPISystemReport = window.location.origin + "/api?device=system&cmd=report"; + class EMSESPHelp extends Component { render() { return ( + + + + + + + + For the latest news and updates go to the {'official documentation'} website + + + + + + + + + For live community chat visit our {'Gitter'} channel + + + + + + + + + To report an issue or feature request go to {'click here'} + + + + + + + + + To export your system settings {'click here'} + + + + + + + + + + To create a report of the current EMS-ESP status (for troubleshooting) {'click here'} + + + + + - - EMS-ESP is an open-source firmware for the Espressif ESP8266 and ESP32 microcontroller that communicates with EMS (Energy Management System) based equipment from manufacturers like Bosch, Buderus, Nefit, Junkers, Worcester and Sieger. -

- Please consider supporting this project via the GitHub page {'http://github.com/proddy/EMS-ESP'}. + + EMS-ESP is free and open-source. +

Please consider supporting this project by giving it a on our {'GitHub page'}.


- - Check for news and updates on the {'Wiki'}. - - - For live community chat go to {'Gitter'}. - - - To report an issue or feature request go to {'the github project page'}. -
) diff --git a/interface/src/project/EMSESPSettingsController.tsx b/interface/src/project/EMSESPSettingsController.tsx index 010d0dd7..24871b02 100644 --- a/interface/src/project/EMSESPSettingsController.tsx +++ b/interface/src/project/EMSESPSettingsController.tsx @@ -1,4 +1,4 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; import { ValidatorForm, TextValidator, SelectValidator } from 'react-material-ui-form-validator'; import { Checkbox, Typography, Box, Link } from '@material-ui/core'; @@ -48,18 +48,18 @@ function EMSESPSettingsControllerForm(props: EMSESPSettingsControllerFormProps) - Customize EMS-ESP by modifying the default settings here. + Change the default settings on this page. For help click {'here'}.

- EMS Bus Settings + EMS Bus

- Dallas Sensor Settings + Dallas Sensor

- LED Settings + LED

- Shower Settings + Shower

- Syslog Settings + API + + + } + label="Enable WEB API (for write commands)" + /> + + on/off + true/false + 1/0 + +

+ + Syslog +

+ + Analog Input + + + } + label="Enable ADC" + /> +

} variant="contained" color="primary" type="submit"> Save diff --git a/interface/src/project/EMSESPStatus.ts b/interface/src/project/EMSESPStatus.ts index c3378a7e..b60d9887 100644 --- a/interface/src/project/EMSESPStatus.ts +++ b/interface/src/project/EMSESPStatus.ts @@ -29,3 +29,12 @@ export const busStatus = ({ status }: EMSESPStatus) => { return "Unknown"; } } + +export const qualityHighlight = ( value: number, theme: Theme) => { + if (value >= 95) { + return theme.palette.success.main; + } + + return theme.palette.error.main; +} + diff --git a/interface/src/project/EMSESPStatusForm.tsx b/interface/src/project/EMSESPStatusForm.tsx index b9acfcc8..966e109b 100644 --- a/interface/src/project/EMSESPStatusForm.tsx +++ b/interface/src/project/EMSESPStatusForm.tsx @@ -1,14 +1,11 @@ import React, { Component, Fragment } from "react"; -import { WithTheme, withTheme, withStyles, Theme, createStyles } from "@material-ui/core/styles"; +import { WithTheme, withTheme } from "@material-ui/core/styles"; import { TableContainer, Table, - Box, - Typography, TableBody, TableCell, - TableHead, TableRow, List, ListItem, @@ -16,7 +13,7 @@ import { ListItemText, withWidth, WithWidthProps, - isWidthDown + isWidthDown, } from "@material-ui/core"; import RefreshIcon from "@material-ui/icons/Refresh"; @@ -32,35 +29,19 @@ import { import { busStatus, busStatusHighlight, - isConnected + isConnected, } from "./EMSESPStatus"; import { EMSESPStatus } from "./EMSESPtypes"; function formatNumber(num: number) { - return new Intl.NumberFormat().format(num); + return new Intl.NumberFormat().format(num); } type EMSESPStatusFormProps = RestFormProps & WithTheme & WithWidthProps; -const StyledTableCell = withStyles((theme: Theme) => - createStyles({ - head: { - backgroundColor: theme.palette.common.black, - color: theme.palette.common.white, - }, - body: { - fontSize: 14, - }, - }), -)(TableCell); - class EMSESPStatusForm extends Component { - rxErrors = () => { - return this.props.data.crc_errors !== 0; - } - createListItems() { const { data, theme, width } = this.props; return ( @@ -71,53 +52,42 @@ class EMSESPStatusForm extends Component { - + {isConnected(data) && ( - - - Statistic - # Telegrams - - - (Rx) Received telegrams + Received telegrams + + {formatNumber(data.rx_received)} - {formatNumber(data.rx_received)} - (Rx) Incomplete telegrams + Rx line quality + + {data.rx_quality} % - {formatNumber(data.crc_errors)} - (Tx) Successfully sent telegrams + Sent telegrams + + {formatNumber(data.tx_sent)} - {formatNumber(data.tx_sent)} - (Tx) Send Errors + Tx line quality + + {data.tx_quality} % - {formatNumber(data.tx_errors)}
- - {this.rxErrors() && ( - - - Note: Having a small number of incomplete Rx telegrams is normal and often caused by noise on the EMS line. - - - )} -
)} diff --git a/interface/src/project/EMSESPtypes.ts b/interface/src/project/EMSESPtypes.ts index 2f59596b..80ce4815 100644 --- a/interface/src/project/EMSESPtypes.ts +++ b/interface/src/project/EMSESPtypes.ts @@ -13,6 +13,9 @@ export interface EMSESPSettings { dallas_parasite: boolean; led_gpio: number; hide_led: boolean; + api_enabled: boolean; + bool_format: number; + analog_enabled: boolean; } export enum busConnectionStatus { @@ -25,8 +28,8 @@ export interface EMSESPStatus { status: busConnectionStatus; rx_received: number; tx_sent: number; - crc_errors: number; - tx_errors: number; + rx_quality: number; + tx_quality: number; } export interface Device { @@ -40,8 +43,9 @@ export interface Device { } export interface Sensor { + no: number; id: string; - temp: number; + temp: string; } export interface EMSESPDevices { @@ -50,8 +54,8 @@ export interface EMSESPDevices { } export interface DeviceData { - name: string; - value: string; + n: string; + v: string; } export interface EMSESPDeviceData { diff --git a/interface/src/security/SecuritySettingsForm.tsx b/interface/src/security/SecuritySettingsForm.tsx index 6407f5f7..41d5bbaa 100644 --- a/interface/src/security/SecuritySettingsForm.tsx +++ b/interface/src/security/SecuritySettingsForm.tsx @@ -24,9 +24,9 @@ class SecuritySettingsForm extends React.Component { { /> - The JWT secret is used to sign authentication tokens. If you modify the JWT Secret, all users will be signed out. + The Super User password is used to sign authentication tokens and also the Console's `su` password. If you modify this all users will be signed out. diff --git a/interface/src/system/OTASettingsForm.tsx b/interface/src/system/OTASettingsForm.tsx index c5189958..1e88ad6d 100644 --- a/interface/src/system/OTASettingsForm.tsx +++ b/interface/src/system/OTASettingsForm.tsx @@ -5,7 +5,7 @@ import { Checkbox } from '@material-ui/core'; import SaveIcon from '@material-ui/icons/Save'; import { RestFormProps, BlockFormControlLabel, PasswordValidator, FormButton, FormActions } from '../components'; -import {isIP,isHostname,or} from '../validators'; +import { isIP, isHostname, or } from '../validators'; import { OTASettings } from './types'; @@ -28,7 +28,7 @@ class OTASettingsForm extends React.Component { onChange={handleValueChange("enabled")} /> } - label="Enable OTA Updates?" + label="Enable OTA Updates" /> { return ( - Upload a new firmware (.bin) file below to replace the existing firmware. + Upload a new firmware file (.bin or .bin.gz) below to replace the existing firmware. diff --git a/interface/src/wifi/WiFiSettingsForm.tsx b/interface/src/wifi/WiFiSettingsForm.tsx index c13ce79b..839c3813 100644 --- a/interface/src/wifi/WiFiSettingsForm.tsx +++ b/interface/src/wifi/WiFiSettingsForm.tsx @@ -125,7 +125,7 @@ class WiFiSettingsForm extends React.Component { onChange={handleValueChange("static_ip_config")} /> } - label="Static IP Config?" + label="Static IP Config" /> { data.static_ip_config && diff --git a/lib_standalone/ArduinoJson/ArduinoJson.h b/lib/ArduinoJson/ArduinoJson.h similarity index 100% rename from lib_standalone/ArduinoJson/ArduinoJson.h rename to lib/ArduinoJson/ArduinoJson.h diff --git a/lib_standalone/ArduinoJson/CHANGELOG.md b/lib/ArduinoJson/CHANGELOG.md similarity index 90% rename from lib_standalone/ArduinoJson/CHANGELOG.md rename to lib/ArduinoJson/CHANGELOG.md index 165f2dc5..d140edaa 100644 --- a/lib_standalone/ArduinoJson/CHANGELOG.md +++ b/lib/ArduinoJson/CHANGELOG.md @@ -1,965 +1,1012 @@ -ArduinoJson: change log -======================= - -HEAD ----- - -* Fixed "maybe-uninitialized" warning (issue #1217) - -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++ -> DynamicJsonDocument doc1(64); -> doc1.set(String("example")); -> -> DynamicJsonDocument doc2 = doc1; -> Serial.print(doc2.capacity()); // 8 with ArduinoJson 6.14 -> // 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()` -* 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 -> ``` - -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()` 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` (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 -> ``` -> -> #### 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())`. - -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()` and `JsonVariant::is()`. - - `as()` returns `0` if the integer `T` overflows - - `is()` 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()` is not required anymore. -* `JsonDocument` now support the same operations as `JsonVariant`. - Calling `JsonDocument::as()` 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(i)` and `JsonArray::set(i,v)` -* Removed `JsonObject::is(k)` and `JsonObject::set(k,v)` -* Replaced `T JsonArray::get(i)` with `JsonVariant JsonArray::get(i)` -* Replaced `T JsonObject::get(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()` (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()` and `JsonVariant::to()` - -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(); -> myValue.set(42); -> ``` -> -> #### JsonPair -> -> Old code: -> -> ```c++ -> for(JsonPair p : myObject) { -> Serial.println(p.key); -> Serial.println(p.value.as()); -> } -> ``` -> -> New code: -> -> ```c++ -> for(JsonPair p : myObject) { -> Serial.println(p.key()); -> Serial.println(p.value().as()); -> } -> ``` -> -> 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()` 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(); -> JsonArray& arr = obj.createNestedArray("key"); -> if (!arr.success()) { -> Serial.println("Not enough memory"); -> return; -> } -> ``` -> -> New code: -> -> ```c++ -> JsonObject obj = doc.to(); -> 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(); -> ``` -> -> #### 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(); -> obj["key"] = "value"; -> serializeJson(doc, Serial); -> ``` - -v5.13.2 -------- - -* Fixed `JsonBuffer::parse()` not respecting nesting limit correctly (issue #693) -* Fixed inconsistencies in nesting level counting (PR #695 from Zhenyu Wu) -* Fixed null values that could be pass to `strcmp()` (PR #745 from Mike Karlesky) -* Added macros `ARDUINOJSON_VERSION`, `ARDUINOJSON_VERSION_MAJOR`... - -v5.13.1 -------- - -* Fixed `JsonVariant::operator|(int)` that returned the default value if the variant contained a double (issue #675) -* Allowed non-quoted key to contain underscores (issue #665) - -v5.13.0 -------- - -* Changed the rules of string duplication (issue #658) -* `RawJson()` accepts any kind of string and obeys to the same rules for duplication -* Changed the return type of `strdup()` to `const char*` to prevent double duplication -* Marked `strdup()` as deprecated - -> ### New rules for string duplication -> -> | type | duplication | -> |:---------------------------|:------------| -> | const char* | no | -> | char* | ~~no~~ yes | -> | String | yes | -> | std::string | yes | -> | const __FlashStringHelper* | yes | -> -> These new rules make `JsonBuffer::strdup()` useless. - -v5.12.0 -------- - -* Added `JsonVariant::operator|` to return a default value (see below) -* Added a clear error message when compiled as C instead of C++ (issue #629) -* Added detection of MPLAB XC compiler (issue #629) -* Added detection of Keil ARM Compiler (issue #629) -* Added an example that shows how to save and load a configuration file -* Reworked all other examples - -> ### How to use the new feature? -> -> If you have a block like this: -> -> ```c++ -> const char* ssid = root["ssid"]; -> if (!ssid) -> ssid = "default ssid"; -> ``` -> -> You can simplify like that: -> -> ```c++ -> const char* ssid = root["ssid"] | "default ssid"; -> ``` - -v5.11.2 -------- - -* Fixed `DynamicJsonBuffer::clear()` not resetting allocation size (issue #561) -* Fixed incorrect rounding for float values (issue #588) - -v5.11.1 -------- - -* Removed dependency on `PGM_P` as Particle 0.6.2 doesn't define it (issue #546) -* Fixed warning "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]" -* Fixed warning "floating constant exceeds range of 'float' [-Woverflow]" (issue #544) -* Fixed warning "this statement may fall through" [-Wimplicit-fallthrough=] (issue #539) -* Removed `ARDUINOJSON_DOUBLE_IS_64BITS` as it became useless. -* Fixed too many decimals places in float serialization (issue #543) - -v5.11.0 -------- - -* Made `JsonBuffer` non-copyable (PR #524 by @luisrayas3) -* Added `StaticJsonBuffer::clear()` -* Added `DynamicJsonBuffer::clear()` - -v5.10.1 -------- - -* Fixed IntelliSense errors in Visual Micro (issue #483) -* Fixed compilation in IAR Embedded Workbench (issue #515) -* Fixed reading "true" as a float (issue #516) -* Added `ARDUINOJSON_DOUBLE_IS_64BITS` -* Added `ARDUINOJSON_EMBEDDED_MODE` - -v5.10.0 -------- - -* Removed configurable number of decimal places (issues #288, #427 and #506) -* Changed exponentiation thresholds to `1e7` and `1e-5` (issues #288, #427 and #506) -* `JsonVariant::is()` now returns `true` for integers -* Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (issue #495) -* Fixed error `forming reference to reference` (issue #495) - -> ### BREAKING CHANGES :warning: -> -> | Old syntax | New syntax | -> |:--------------------------------|:--------------------| -> | `double_with_n_digits(3.14, 2)` | `3.14` | -> | `float_with_n_digits(3.14, 2)` | `3.14f` | -> | `obj.set("key", 3.14, 2)` | `obj["key"] = 3.14` | -> | `arr.add(3.14, 2)` | `arr.add(3.14)` | -> -> | Input | Old output | New output | -> |:----------|:-----------|:-----------| -> | `3.14159` | `3.14` | `3.14159` | -> | `42.0` | `42.00` | `42` | -> | `0.0` | `0.00` | `0` | -> -> | Expression | Old result | New result | -> |:-------------------------------|:-----------|:-----------| -> | `JsonVariant(42).is()` | `true` | `true` | -> | `JsonVariant(42).is()` | `false` | `true` | -> | `JsonVariant(42).is()` | `false` | `true` | - -v5.9.0 ------- - -* Added `JsonArray::remove(iterator)` (issue #479) -* Added `JsonObject::remove(iterator)` -* Renamed `JsonArray::removeAt(size_t)` into `remove(size_t)` -* Renamed folder `include/` to `src/` -* Fixed warnings `floating constant exceeds range of float`and `floating constant truncated to zero` (issue #483) -* Removed `Print` class and converted `printTo()` to a template method (issue #276) -* Removed example `IndentedPrintExample.ino` -* Now compatible with Particle 0.6.1, thanks to Jacob Nite (issue #294 and PR #461 by @foodbag) - -v5.8.4 ------- - -* Added custom implementation of `strtod()` (issue #453) -* Added custom implementation of `strtol()` (issue #465) -* `char` is now treated as an integral type (issue #337, #370) - -v5.8.3 ------- - -* Fixed an access violation in `DynamicJsonBuffer` when memory allocation fails (issue #433) -* Added operators `==` and `!=` for two `JsonVariant`s (issue #436) -* Fixed `JsonVariant::operator[const FlashStringHelper*]` (issue #441) - -v5.8.2 ------- - -* Fixed parsing of comments (issue #421) -* Fixed ignored `Stream` timeout (issue #422) -* Made sure we don't read more that necessary (issue #422) -* Fixed error when the key of a `JsonObject` is a `char[]` (issue #423) -* Reduced code size when using `const` references -* Fixed error with string of type `unsigned char*` (issue #428) -* Added `deprecated` attribute on `asArray()`, `asObject()` and `asString()` (issue #420) - -v5.8.1 ------- - -* Fixed error when assigning a `volatile int` to a `JsonVariant` (issue #415) -* Fixed errors with Variable Length Arrays (issue #416) -* Fixed error when both `ARDUINOJSON_ENABLE_STD_STREAM` and `ARDUINOJSON_ENABLE_ARDUINO_STREAM` are set to `1` -* Fixed error "Stream does not name a type" (issue #412) - -v5.8.0 ------- - -* Added operator `==` to compare `JsonVariant` and strings (issue #402) -* Added support for `Stream` (issue #300) -* Reduced memory consumption by not duplicating spaces and comments - -> ### BREAKING CHANGES :warning: -> -> `JsonBuffer::parseObject()` and `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`. -> -> This means that if you have code like: -> -> ```c++ -> void myFunction(JsonBuffer& jsonBuffer); -> ``` -> -> you need to replace it with one of the following: -> -> ```c++ -> void myFunction(DynamicJsonBuffer& jsonBuffer); -> void myFunction(StaticJsonBufferBase& jsonBuffer); -> template void myFunction(TJsonBuffer& jsonBuffer); -> ``` - -v5.7.3 ------- - -* Added an `printTo(char[N])` and `prettyPrintTo(char[N])` (issue #292) -* Added ability to set a nested value like this: `root["A"]["B"] = "C"` (issue #352) -* Renamed `*.ipp` to `*Impl.hpp` because they were ignored by Arduino IDE (issue #396) - -v5.7.2 ------- - -* Made PROGMEM available on more platforms (issue #381) -* Fixed PROGMEM causing an exception on ESP8266 (issue #383) - -v5.7.1 ------- - -* Added support for PROGMEM (issue #76) -* Fixed compilation error when index is not an `int` (issue #381) - -v5.7.0 ------- - -* Templatized all functions using `String` or `std::string` -* Removed `ArduinoJson::String` -* Removed `JsonVariant::defaultValue()` -* Removed non-template `JsonObject::get()` and `JsonArray.get()` -* Fixed support for `StringSumHelper` (issue #184) -* Replaced `ARDUINOJSON_USE_ARDUINO_STRING` by `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_ARDUINO_STRING` (issue #378) -* Added example `StringExample.ino` to show where `String` can be used -* Increased default nesting limit to 50 when compiled for a computer (issue #349) - -> ### BREAKING CHANGES :warning: -> -> The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return. -> -> Old code: -> -> ```c++ -> #define ARDUINOJSON_USE_ARDUINO_STRING 0 -> JsonVariant value1 = myObject.get("myKey"); -> JsonVariant value2 = myArray.get(0); -> ``` -> -> New code: -> -> ```c++ -> #define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 -> #define ARDUINOJSON_ENABLE_STD_STRING 1 -> JsonVariant value1 = myObject.get("myKey"); -> JsonVariant value2 = myArray.get(0); -> ``` - -v5.6.7 ------- - -* Fixed `array[idx].as()` and `object[key].as()` -* Fixed return value of `JsonObject::set()` (issue #350) -* Fixed undefined behavior in `Prettyfier` and `Print` (issue #354) -* Fixed parser that incorrectly rejected floats containing a `+` (issue #349) - -v5.6.6 ------- - -* Fixed `-Wparentheses` warning introduced in v5.6.5 (PR #335 by @nuket) -* Added `.mbedignore` for ARM mbdeb (PR #334 by @nuket) -* Fixed `JsonVariant::success()` which didn't propagate `JsonArray::success()` nor `JsonObject::success()` (issue #342). - -v5.6.5 ------- - -* `as()` now returns `true` when input is `null` (issue #330) - -v5.6.4 ------- - -* Fixed error in float serialization (issue #324) - -v5.6.3 ------- - -* Improved speed of float serialization (about twice faster) -* Added `as()` as a synonym for `as()`... (issue #291) -* Fixed `call of overloaded isinf(double&) is ambiguous` (issue #284) - -v5.6.2 ------- - -* Fixed build when another lib does `#undef isnan` (issue #284) - -v5.6.1 ------- - -* Added missing `#pragma once` (issue #310) - -v5.6.0 ------- - -* ArduinoJson is now a header-only library (issue #199) - -v5.5.1 ------- - -* Fixed compilation error with Intel Galileo (issue #299) - -v5.5.0 ------- - -* Added `JsonVariant::success()` (issue #279) -* Renamed `JsonVariant::invalid()` to `JsonVariant::defaultValue()` - -v5.4.0 ------- - -* Changed `::String` to `ArduinoJson::String` (issue #275) -* Changed `::Print` to `ArduinoJson::Print` too - -v5.3.0 ------- - -* Added custom implementation of `ftoa` (issues #266, #267, #269 and #270) -* Added `JsonVariant JsonBuffer::parse()` (issue #265) -* Fixed `unsigned long` printed as `signed long` (issue #170) - -v5.2.0 ------- - -* Added `JsonVariant::as()` as a synonym for `JsonVariant::as()` (issue #257) -* Added example `JsonHttpClient` (issue #256) -* Added `JsonArray::copyTo()` and `JsonArray::copyFrom()` (issue #254) -* Added `RawJson()` to insert pregenerated JSON portions (issue #259) - -v5.1.1 ------- - -* Removed `String` duplication when one replaces a value in a `JsonObject` (PR #232 by @ulion) - -v5.1.0 ------- - -* Added support of `long long` (issue #171) -* Moved all build settings to `ArduinoJson/Configuration.hpp` - -> ### BREAKING CHANGE :warning: -> -> If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`. - -v5.0.8 ------- - -* Made the library compatible with [PlatformIO](http://platformio.org/) (issue #181) -* Fixed `JsonVariant::is()` that was incorrectly returning false (issue #214) - -v5.0.7 ------- - -* Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)` -* Changed `String` to be a `typedef` of `std::string` (issues #142 and #161) - -> ### BREAKING CHANGES :warning: -> -> - `JsonVariant(true).as()` now returns `"true"` instead of `"1"` -> - `JsonVariant(false).as()` now returns `"false"` instead of `"0"` - -v5.0.6 ------- - -* Added parameter to `DynamicJsonBuffer` constructor to set initial size (issue #152) -* Fixed warning about library category in Arduino 1.6.6 (issue #147) -* Examples: Added a loop to wait for serial port to be ready (issue #156) - -v5.0.5 ------- - -* Added overload `JsonObjectSuscript::set(value, decimals)` (issue #143) -* Use `float` instead of `double` to reduce the size of `JsonVariant` (issue #134) - -v5.0.4 ------- - -* Fixed ambiguous overload with `JsonArraySubscript` and `JsonObjectSubscript` (issue #122) - -v5.0.3 ------- - -* Fixed `printTo(String)` which wrote numbers instead of strings (issue #120) -* Fixed return type of `JsonArray::is()` and some others (issue #121) - -v5.0.2 ------- - -* Fixed segmentation fault in `parseObject(String)` and `parseArray(String)`, when the - `StaticJsonBuffer` is too small to hold a copy of the string -* Fixed Clang warning "register specifier is deprecated" (issue #102) -* Fixed GCC warning "declaration shadows a member" (issue #103) -* Fixed memory alignment, which made ESP8266 crash (issue #104) -* Fixed compilation on Visual Studio 2010 and 2012 (issue #107) - -v5.0.1 ------- - -* Fixed compilation with Arduino 1.0.6 (issue #99) - -v5.0.0 ------- - -* Added support of `String` class (issues #55, #56, #70, #77) -* Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57) -* Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87) -* Added support of non standard JSON input (issue #44) -* Added support of comments in JSON input (issue #88) -* Added implicit cast between numerical types (issues #64, #69, #93) -* Added ability to read number values as string (issue #90) -* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66) -* Switched to new the library layout (requires Arduino 1.0.6 or above) - -> ### BREAKING CHANGES :warning: -> -> - `JsonObject::add()` was renamed to `set()` -> - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()` -> - Number of digits of floating point value are now set with `double_with_n_digits()` - -**Personal note about the `String` class**: -Support of the `String` class has been added to the library because many people use it in their programs. -However, you should not see this as an invitation to use the `String` class. -The `String` class is **bad** because it uses dynamic memory allocation. -Compared to static allocation, it compiles to a bigger, slower program, and is less predictable. -You certainly don't want that in an embedded environment! +ArduinoJson: change log +======================= + +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 ` (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()` and `is()` (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++ +> DynamicJsonDocument doc1(64); +> doc1.set(String("example")); +> +> DynamicJsonDocument doc2 = doc1; +> Serial.print(doc2.capacity()); // 8 with ArduinoJson 6.14 +> // 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()` +* 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 +> ``` + +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()` 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` (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 +> ``` +> +> #### 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())`. + +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()` and `JsonVariant::is()`. + - `as()` returns `0` if the integer `T` overflows + - `is()` 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()` is not required anymore. +* `JsonDocument` now support the same operations as `JsonVariant`. + Calling `JsonDocument::as()` 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(i)` and `JsonArray::set(i,v)` +* Removed `JsonObject::is(k)` and `JsonObject::set(k,v)` +* Replaced `T JsonArray::get(i)` with `JsonVariant JsonArray::get(i)` +* Replaced `T JsonObject::get(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()` (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()` and `JsonVariant::to()` + +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(); +> myValue.set(42); +> ``` +> +> #### JsonPair +> +> Old code: +> +> ```c++ +> for(JsonPair p : myObject) { +> Serial.println(p.key); +> Serial.println(p.value.as()); +> } +> ``` +> +> New code: +> +> ```c++ +> for(JsonPair p : myObject) { +> Serial.println(p.key()); +> Serial.println(p.value().as()); +> } +> ``` +> +> 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()` 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(); +> JsonArray& arr = obj.createNestedArray("key"); +> if (!arr.success()) { +> Serial.println("Not enough memory"); +> return; +> } +> ``` +> +> New code: +> +> ```c++ +> JsonObject obj = doc.to(); +> 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(); +> ``` +> +> #### 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(); +> obj["key"] = "value"; +> serializeJson(doc, Serial); +> ``` + +v5.13.2 +------- + +* Fixed `JsonBuffer::parse()` not respecting nesting limit correctly (issue #693) +* Fixed inconsistencies in nesting level counting (PR #695 from Zhenyu Wu) +* Fixed null values that could be pass to `strcmp()` (PR #745 from Mike Karlesky) +* Added macros `ARDUINOJSON_VERSION`, `ARDUINOJSON_VERSION_MAJOR`... + +v5.13.1 +------- + +* Fixed `JsonVariant::operator|(int)` that returned the default value if the variant contained a double (issue #675) +* Allowed non-quoted key to contain underscores (issue #665) + +v5.13.0 +------- + +* Changed the rules of string duplication (issue #658) +* `RawJson()` accepts any kind of string and obeys to the same rules for duplication +* Changed the return type of `strdup()` to `const char*` to prevent double duplication +* Marked `strdup()` as deprecated + +> ### New rules for string duplication +> +> | type | duplication | +> |:---------------------------|:------------| +> | const char* | no | +> | char* | ~~no~~ yes | +> | String | yes | +> | std::string | yes | +> | const __FlashStringHelper* | yes | +> +> These new rules make `JsonBuffer::strdup()` useless. + +v5.12.0 +------- + +* Added `JsonVariant::operator|` to return a default value (see below) +* Added a clear error message when compiled as C instead of C++ (issue #629) +* Added detection of MPLAB XC compiler (issue #629) +* Added detection of Keil ARM Compiler (issue #629) +* Added an example that shows how to save and load a configuration file +* Reworked all other examples + +> ### How to use the new feature? +> +> If you have a block like this: +> +> ```c++ +> const char* ssid = root["ssid"]; +> if (!ssid) +> ssid = "default ssid"; +> ``` +> +> You can simplify like that: +> +> ```c++ +> const char* ssid = root["ssid"] | "default ssid"; +> ``` + +v5.11.2 +------- + +* Fixed `DynamicJsonBuffer::clear()` not resetting allocation size (issue #561) +* Fixed incorrect rounding for float values (issue #588) + +v5.11.1 +------- + +* Removed dependency on `PGM_P` as Particle 0.6.2 doesn't define it (issue #546) +* Fixed warning "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]" +* Fixed warning "floating constant exceeds range of 'float' [-Woverflow]" (issue #544) +* Fixed warning "this statement may fall through" [-Wimplicit-fallthrough=] (issue #539) +* Removed `ARDUINOJSON_DOUBLE_IS_64BITS` as it became useless. +* Fixed too many decimals places in float serialization (issue #543) + +v5.11.0 +------- + +* Made `JsonBuffer` non-copyable (PR #524 by @luisrayas3) +* Added `StaticJsonBuffer::clear()` +* Added `DynamicJsonBuffer::clear()` + +v5.10.1 +------- + +* Fixed IntelliSense errors in Visual Micro (issue #483) +* Fixed compilation in IAR Embedded Workbench (issue #515) +* Fixed reading "true" as a float (issue #516) +* Added `ARDUINOJSON_DOUBLE_IS_64BITS` +* Added `ARDUINOJSON_EMBEDDED_MODE` + +v5.10.0 +------- + +* Removed configurable number of decimal places (issues #288, #427 and #506) +* Changed exponentiation thresholds to `1e7` and `1e-5` (issues #288, #427 and #506) +* `JsonVariant::is()` now returns `true` for integers +* Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (issue #495) +* Fixed error `forming reference to reference` (issue #495) + +> ### BREAKING CHANGES :warning: +> +> | Old syntax | New syntax | +> |:--------------------------------|:--------------------| +> | `double_with_n_digits(3.14, 2)` | `3.14` | +> | `float_with_n_digits(3.14, 2)` | `3.14f` | +> | `obj.set("key", 3.14, 2)` | `obj["key"] = 3.14` | +> | `arr.add(3.14, 2)` | `arr.add(3.14)` | +> +> | Input | Old output | New output | +> |:----------|:-----------|:-----------| +> | `3.14159` | `3.14` | `3.14159` | +> | `42.0` | `42.00` | `42` | +> | `0.0` | `0.00` | `0` | +> +> | Expression | Old result | New result | +> |:-------------------------------|:-----------|:-----------| +> | `JsonVariant(42).is()` | `true` | `true` | +> | `JsonVariant(42).is()` | `false` | `true` | +> | `JsonVariant(42).is()` | `false` | `true` | + +v5.9.0 +------ + +* Added `JsonArray::remove(iterator)` (issue #479) +* Added `JsonObject::remove(iterator)` +* Renamed `JsonArray::removeAt(size_t)` into `remove(size_t)` +* Renamed folder `include/` to `src/` +* Fixed warnings `floating constant exceeds range of float`and `floating constant truncated to zero` (issue #483) +* Removed `Print` class and converted `printTo()` to a template method (issue #276) +* Removed example `IndentedPrintExample.ino` +* Now compatible with Particle 0.6.1, thanks to Jacob Nite (issue #294 and PR #461 by @foodbag) + +v5.8.4 +------ + +* Added custom implementation of `strtod()` (issue #453) +* Added custom implementation of `strtol()` (issue #465) +* `char` is now treated as an integral type (issue #337, #370) + +v5.8.3 +------ + +* Fixed an access violation in `DynamicJsonBuffer` when memory allocation fails (issue #433) +* Added operators `==` and `!=` for two `JsonVariant`s (issue #436) +* Fixed `JsonVariant::operator[const FlashStringHelper*]` (issue #441) + +v5.8.2 +------ + +* Fixed parsing of comments (issue #421) +* Fixed ignored `Stream` timeout (issue #422) +* Made sure we don't read more that necessary (issue #422) +* Fixed error when the key of a `JsonObject` is a `char[]` (issue #423) +* Reduced code size when using `const` references +* Fixed error with string of type `unsigned char*` (issue #428) +* Added `deprecated` attribute on `asArray()`, `asObject()` and `asString()` (issue #420) + +v5.8.1 +------ + +* Fixed error when assigning a `volatile int` to a `JsonVariant` (issue #415) +* Fixed errors with Variable Length Arrays (issue #416) +* Fixed error when both `ARDUINOJSON_ENABLE_STD_STREAM` and `ARDUINOJSON_ENABLE_ARDUINO_STREAM` are set to `1` +* Fixed error "Stream does not name a type" (issue #412) + +v5.8.0 +------ + +* Added operator `==` to compare `JsonVariant` and strings (issue #402) +* Added support for `Stream` (issue #300) +* Reduced memory consumption by not duplicating spaces and comments + +> ### BREAKING CHANGES :warning: +> +> `JsonBuffer::parseObject()` and `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`. +> +> This means that if you have code like: +> +> ```c++ +> void myFunction(JsonBuffer& jsonBuffer); +> ``` +> +> you need to replace it with one of the following: +> +> ```c++ +> void myFunction(DynamicJsonBuffer& jsonBuffer); +> void myFunction(StaticJsonBufferBase& jsonBuffer); +> template void myFunction(TJsonBuffer& jsonBuffer); +> ``` + +v5.7.3 +------ + +* Added an `printTo(char[N])` and `prettyPrintTo(char[N])` (issue #292) +* Added ability to set a nested value like this: `root["A"]["B"] = "C"` (issue #352) +* Renamed `*.ipp` to `*Impl.hpp` because they were ignored by Arduino IDE (issue #396) + +v5.7.2 +------ + +* Made PROGMEM available on more platforms (issue #381) +* Fixed PROGMEM causing an exception on ESP8266 (issue #383) + +v5.7.1 +------ + +* Added support for PROGMEM (issue #76) +* Fixed compilation error when index is not an `int` (issue #381) + +v5.7.0 +------ + +* Templatized all functions using `String` or `std::string` +* Removed `ArduinoJson::String` +* Removed `JsonVariant::defaultValue()` +* Removed non-template `JsonObject::get()` and `JsonArray.get()` +* Fixed support for `StringSumHelper` (issue #184) +* Replaced `ARDUINOJSON_USE_ARDUINO_STRING` by `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_ARDUINO_STRING` (issue #378) +* Added example `StringExample.ino` to show where `String` can be used +* Increased default nesting limit to 50 when compiled for a computer (issue #349) + +> ### BREAKING CHANGES :warning: +> +> The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return. +> +> Old code: +> +> ```c++ +> #define ARDUINOJSON_USE_ARDUINO_STRING 0 +> JsonVariant value1 = myObject.get("myKey"); +> JsonVariant value2 = myArray.get(0); +> ``` +> +> New code: +> +> ```c++ +> #define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 +> #define ARDUINOJSON_ENABLE_STD_STRING 1 +> JsonVariant value1 = myObject.get("myKey"); +> JsonVariant value2 = myArray.get(0); +> ``` + +v5.6.7 +------ + +* Fixed `array[idx].as()` and `object[key].as()` +* Fixed return value of `JsonObject::set()` (issue #350) +* Fixed undefined behavior in `Prettyfier` and `Print` (issue #354) +* Fixed parser that incorrectly rejected floats containing a `+` (issue #349) + +v5.6.6 +------ + +* Fixed `-Wparentheses` warning introduced in v5.6.5 (PR #335 by @nuket) +* Added `.mbedignore` for ARM mbdeb (PR #334 by @nuket) +* Fixed `JsonVariant::success()` which didn't propagate `JsonArray::success()` nor `JsonObject::success()` (issue #342). + +v5.6.5 +------ + +* `as()` now returns `true` when input is `null` (issue #330) + +v5.6.4 +------ + +* Fixed error in float serialization (issue #324) + +v5.6.3 +------ + +* Improved speed of float serialization (about twice faster) +* Added `as()` as a synonym for `as()`... (issue #291) +* Fixed `call of overloaded isinf(double&) is ambiguous` (issue #284) + +v5.6.2 +------ + +* Fixed build when another lib does `#undef isnan` (issue #284) + +v5.6.1 +------ + +* Added missing `#pragma once` (issue #310) + +v5.6.0 +------ + +* ArduinoJson is now a header-only library (issue #199) + +v5.5.1 +------ + +* Fixed compilation error with Intel Galileo (issue #299) + +v5.5.0 +------ + +* Added `JsonVariant::success()` (issue #279) +* Renamed `JsonVariant::invalid()` to `JsonVariant::defaultValue()` + +v5.4.0 +------ + +* Changed `::String` to `ArduinoJson::String` (issue #275) +* Changed `::Print` to `ArduinoJson::Print` too + +v5.3.0 +------ + +* Added custom implementation of `ftoa` (issues #266, #267, #269 and #270) +* Added `JsonVariant JsonBuffer::parse()` (issue #265) +* Fixed `unsigned long` printed as `signed long` (issue #170) + +v5.2.0 +------ + +* Added `JsonVariant::as()` as a synonym for `JsonVariant::as()` (issue #257) +* Added example `JsonHttpClient` (issue #256) +* Added `JsonArray::copyTo()` and `JsonArray::copyFrom()` (issue #254) +* Added `RawJson()` to insert pregenerated JSON portions (issue #259) + +v5.1.1 +------ + +* Removed `String` duplication when one replaces a value in a `JsonObject` (PR #232 by @ulion) + +v5.1.0 +------ + +* Added support of `long long` (issue #171) +* Moved all build settings to `ArduinoJson/Configuration.hpp` + +> ### BREAKING CHANGE :warning: +> +> If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`. + +v5.0.8 +------ + +* Made the library compatible with [PlatformIO](http://platformio.org/) (issue #181) +* Fixed `JsonVariant::is()` that was incorrectly returning false (issue #214) + +v5.0.7 +------ + +* Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)` +* Changed `String` to be a `typedef` of `std::string` (issues #142 and #161) + +> ### BREAKING CHANGES :warning: +> +> - `JsonVariant(true).as()` now returns `"true"` instead of `"1"` +> - `JsonVariant(false).as()` now returns `"false"` instead of `"0"` + +v5.0.6 +------ + +* Added parameter to `DynamicJsonBuffer` constructor to set initial size (issue #152) +* Fixed warning about library category in Arduino 1.6.6 (issue #147) +* Examples: Added a loop to wait for serial port to be ready (issue #156) + +v5.0.5 +------ + +* Added overload `JsonObjectSuscript::set(value, decimals)` (issue #143) +* Use `float` instead of `double` to reduce the size of `JsonVariant` (issue #134) + +v5.0.4 +------ + +* Fixed ambiguous overload with `JsonArraySubscript` and `JsonObjectSubscript` (issue #122) + +v5.0.3 +------ + +* Fixed `printTo(String)` which wrote numbers instead of strings (issue #120) +* Fixed return type of `JsonArray::is()` and some others (issue #121) + +v5.0.2 +------ + +* Fixed segmentation fault in `parseObject(String)` and `parseArray(String)`, when the + `StaticJsonBuffer` is too small to hold a copy of the string +* Fixed Clang warning "register specifier is deprecated" (issue #102) +* Fixed GCC warning "declaration shadows a member" (issue #103) +* Fixed memory alignment, which made ESP8266 crash (issue #104) +* Fixed compilation on Visual Studio 2010 and 2012 (issue #107) + +v5.0.1 +------ + +* Fixed compilation with Arduino 1.0.6 (issue #99) + +v5.0.0 +------ + +* Added support of `String` class (issues #55, #56, #70, #77) +* Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57) +* Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87) +* Added support of non standard JSON input (issue #44) +* Added support of comments in JSON input (issue #88) +* Added implicit cast between numerical types (issues #64, #69, #93) +* Added ability to read number values as string (issue #90) +* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66) +* Switched to new the library layout (requires Arduino 1.0.6 or above) + +> ### BREAKING CHANGES :warning: +> +> - `JsonObject::add()` was renamed to `set()` +> - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()` +> - Number of digits of floating point value are now set with `double_with_n_digits()` + +**Personal note about the `String` class**: +Support of the `String` class has been added to the library because many people use it in their programs. +However, you should not see this as an invitation to use the `String` class. +The `String` class is **bad** because it uses dynamic memory allocation. +Compared to static allocation, it compiles to a bigger, slower program, and is less predictable. +You certainly don't want that in an embedded environment! diff --git a/lib_standalone/ArduinoJson/LICENSE.md b/lib/ArduinoJson/LICENSE.md similarity index 99% rename from lib_standalone/ArduinoJson/LICENSE.md rename to lib/ArduinoJson/LICENSE.md index 30cef099..90cb7e66 100644 --- a/lib_standalone/ArduinoJson/LICENSE.md +++ b/lib/ArduinoJson/LICENSE.md @@ -1,10 +1,10 @@ -The MIT License (MIT) ---------------------- - -Copyright © 2014-2020 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: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The MIT License (MIT) +--------------------- + +Copyright © 2014-2020 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: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib_standalone/ArduinoJson/README.md b/lib/ArduinoJson/README.md similarity index 90% rename from lib_standalone/ArduinoJson/README.md rename to lib/ArduinoJson/README.md index a1e19af6..3516985e 100644 --- a/lib_standalone/ArduinoJson/README.md +++ b/lib/ArduinoJson/README.md @@ -1,137 +1,137 @@ -![ArduinoJson](banner.svg) - ---- - -[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.15.0)](https://www.ardu-badge.com/ArduinoJson/6.15.0) -[![Build Status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) -[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson) -[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) -[![Coverage Status](https://coveralls.io/repos/github/bblanchon/ArduinoJson/badge.svg?branch=6.x)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x) -[![GitHub stars](https://img.shields.io/github/stars/bblanchon/ArduinoJson?style=flat)](https://github.com/bblanchon/ArduinoJson/stargazers) - -ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). - -## Features - -* [JSON deserialization](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme) - * [Optionally decodes UTF-16 escape sequences to UTF-8](https://arduinojson.org/v6/api/config/decode_unicode/?utm_source=github&utm_medium=readme) - * [Optionally stores links to the input buffer (zero-copy)](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme) - * [Optionally supports comments in the input](https://arduinojson.org/v6/api/config/enable_comments/?utm_source=github&utm_medium=readme) - * [Optionally filters the input to keep only desired values](https://arduinojson.org/v6/api/json/deserializejson/#filtering?utm_source=github&utm_medium=readme) - * Supports single quotes as a string delimiter - * Compatible with NDJSON and JSON Lines -* [JSON serialization](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme) - * [Can write to a buffer or a stream](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme) - * [Optionally indents the document (prettified JSON)](https://arduinojson.org/v6/api/json/serializejsonpretty/?utm_source=github&utm_medium=readme) -* [MessagePack serialization](https://arduinojson.org/v6/api/msgpack/serializemsgpack/?utm_source=github&utm_medium=readme) -* [MessagePack deserialization](https://arduinojson.org/v6/api/msgpack/deserializemsgpack/?utm_source=github&utm_medium=readme) -* Efficient - * [Twice smaller than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme) - * [Almost 10% faster than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme) - * [Consumes roughly 10% less RAM than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme) - * [Fixed memory allocation, no heap fragmentation](https://arduinojson.org/v6/api/jsondocument/?utm_source=github&utm_medium=readme) - * [Optionally works without heap memory (zero malloc)](https://arduinojson.org/v6/api/staticjsondocument/?utm_source=github&utm_medium=readme) -* Versatile - * [Supports custom allocators (to use external RAM chip, for example)](https://arduinojson.org/v6/how-to/use-external-ram-on-esp32/?utm_source=github&utm_medium=readme) - * Supports [Arduino's `String`](https://arduinojson.org/v6/api/config/enable_arduino_string/) and [STL's `std::string`](https://arduinojson.org/v6/api/config/enable_std_string/?utm_source=github&utm_medium=readme) - * Supports Arduino's `Stream` and [STL's `std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/?utm_source=github&utm_medium=readme) - * [Supports Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/?utm_source=github&utm_medium=readme) - * Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/#custom-writer?utm_source=github&utm_medium=readme) -* Portable - * Usable on any C++ project (not limited to Arduino) - * Compatible with C++98 - * Zero warnings with `-Wall -Wextra -pedantic` and `/W4` - * [Header-only library](https://en.wikipedia.org/wiki/Header-only) - * Works with virtually any board - * Arduino boards: [Uno](https://amzn.to/38aL2ik), [Due](https://amzn.to/36YkWi2), [Micro](https://amzn.to/35WkdwG), [Nano](https://amzn.to/2QTvwRX), [Mega](https://amzn.to/36XWhuf), [Yun](https://amzn.to/30odURc), [Leonardo](https://amzn.to/36XWjlR)... - * Espressif chips: [ESP8266](https://amzn.to/36YluV8), [ESP32](https://amzn.to/2G4pRCB) - * Lolin (WeMos) boards: [D1 mini](https://amzn.to/2QUpz7q), [D1 Mini Pro](https://amzn.to/36UsGSs)... - * Teensy boards: [4.0](https://amzn.to/30ljXGq), [3.2](https://amzn.to/2FT0EuC), [2.0](https://amzn.to/2QXUMXj) - * Particle boards: [Argon](https://amzn.to/2FQHa9X), [Boron](https://amzn.to/36WgLUd), [Electron](https://amzn.to/30vEc4k), [Photon](https://amzn.to/387F9Cd)... - * Texas Instruments boards: [MSP430](https://amzn.to/30nJWgg)... - * Tested on all major development environments - * [Arduino IDE](https://www.arduino.cc/en/Main/Software) - * [Atmel Studio](http://www.atmel.com/microsite/atmel-studio/) - * [Atollic TrueSTUDIO](https://atollic.com/truestudio/) - * [Energia](http://energia.nu/) - * [IAR Embedded Workbench](https://www.iar.com/iar-embedded-workbench/) - * [Keil uVision](http://www.keil.com/) - * [MPLAB X IDE](http://www.microchip.com/mplab/mplab-x-ide) - * [PlatformIO](http://platformio.org/) - * [Sloeber plugin for Eclipse](https://eclipse.baeyens.it/) - * [Visual Micro](http://www.visualmicro.com/) - * [Visual Studio](https://www.visualstudio.com/) - * [Even works with online compilers like wandbox.org](https://wandbox.org/permlink/t7KP7I6dVuLhqzDl) -* Well designed - * [Elegant API](http://127.0.0.1:4000/v6/example/) - * [Thread-safe](https://en.wikipedia.org/wiki/Thread_safety) - * Self-contained (no external dependency) - * `const` friendly - * [`for` friendly](https://arduinojson.org/v6/api/jsonobject/begin_end/?utm_source=github&utm_medium=readme) - * [TMP friendly](https://en.wikipedia.org/wiki/Template_metaprogramming) - * Handles [integer overflows](https://arduinojson.org/v6/api/jsonvariant/as/#integer-overflows?utm_source=github&utm_medium=readme) -* Well tested - * [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x) - * Continuously tested on - * [Visual Studio 2010, 2012, 2013, 2015, 2017, 2019](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) - * [GCC 4.4, 4.6, 4.7, 4.8, 4.9, 5, 6, 7, 8](https://travis-ci.org/bblanchon/ArduinoJson) - * [Clang 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 5.0, 6.0, 7, 8](https://travis-ci.org/bblanchon/ArduinoJson) - * [Continuously fuzzed with Google OSS Fuzz](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) -* Well documented - * [Tutorials](https://arduinojson.org/v6/doc/deserialization/?utm_source=github&utm_medium=readme) - * [Examples](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme) - * [How-tos](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme) - * [FAQ](https://arduinojson.org/v6/faq/?utm_source=github&utm_medium=readme) - * [Book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme) -* Vibrant user community - * Most popular of all Arduino libraries on [GitHub](https://github.com/search?o=desc&q=arduino+library&s=stars&type=Repositories) and [PlatformIO](https://platformio.org/lib/search) - * [Used in hundreds of projects](https://www.hackster.io/search?i=projects&q=arduinojson) - * [Responsive support](https://github.com/bblanchon/ArduinoJson/issues?q=is%3Aissue+is%3Aclosed) - -## Quickstart - -### Deserialization - -Here is a program that parses a JSON document with ArduinoJson. - -```c++ -char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; - -DynamicJsonDocument doc(1024); -deserializeJson(doc, json); - -const char* sensor = doc["sensor"]; -long time = doc["time"]; -double latitude = doc["data"][0]; -double longitude = doc["data"][1]; -``` - -See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_source=github&utm_medium=readme) - -### Serialization - -Here is a program that generates a JSON document with ArduinoJson: - -```c++ -DynamicJsonDocument doc(1024); - -doc["sensor"] = "gps"; -doc["time"] = 1351824120; - -JsonArray data = doc.createNestedArray("data"); -data.add(48.756080); -data.add(2.302038); - -serializeJson(doc, Serial); -// This prints: -// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} -``` - -See the [tutorial on arduinojson.org](https://arduinojson.org/doc/encoding/?utm_source=github&utm_medium=readme) - -## Support the project - -Do you like this library? Please [star this project on GitHub](https://github.com/bblanchon/ArduinoJson/stargazers)! - -What? You don't like it but you *love* it? -We don't take donations anymore, but [we sell a book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme), so you can help and learn at the same time?utm_source=github&utm_medium=readme! +![ArduinoJson](banner.svg) + +--- + +[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.17.0)](https://www.ardu-badge.com/ArduinoJson/6.17.0) +[![Build Status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) +[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson) +[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) +[![Coverage Status](https://coveralls.io/repos/github/bblanchon/ArduinoJson/badge.svg?branch=6.x)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x) +[![GitHub stars](https://img.shields.io/github/stars/bblanchon/ArduinoJson?style=flat)](https://github.com/bblanchon/ArduinoJson/stargazers) + +ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). + +## Features + +* [JSON deserialization](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme) + * [Optionally decodes UTF-16 escape sequences to UTF-8](https://arduinojson.org/v6/api/config/decode_unicode/?utm_source=github&utm_medium=readme) + * [Optionally stores links to the input buffer (zero-copy)](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme) + * [Optionally supports comments in the input](https://arduinojson.org/v6/api/config/enable_comments/?utm_source=github&utm_medium=readme) + * [Optionally filters the input to keep only desired values](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#filtering) + * Supports single quotes as a string delimiter + * Compatible with NDJSON and JSON Lines +* [JSON serialization](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme) + * [Can write to a buffer or a stream](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme) + * [Optionally indents the document (prettified JSON)](https://arduinojson.org/v6/api/json/serializejsonpretty/?utm_source=github&utm_medium=readme) +* [MessagePack serialization](https://arduinojson.org/v6/api/msgpack/serializemsgpack/?utm_source=github&utm_medium=readme) +* [MessagePack deserialization](https://arduinojson.org/v6/api/msgpack/deserializemsgpack/?utm_source=github&utm_medium=readme) +* Efficient + * [Twice smaller than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme) + * [Almost 10% faster than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme) + * [Consumes roughly 10% less RAM than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme) + * [Fixed memory allocation, no heap fragmentation](https://arduinojson.org/v6/api/jsondocument/?utm_source=github&utm_medium=readme) + * [Optionally works without heap memory (zero malloc)](https://arduinojson.org/v6/api/staticjsondocument/?utm_source=github&utm_medium=readme) + * Deduplicates strings +* Versatile + * [Supports custom allocators (to use external RAM chip, for example)](https://arduinojson.org/v6/how-to/use-external-ram-on-esp32/?utm_source=github&utm_medium=readme) + * Supports [Arduino's `String`](https://arduinojson.org/v6/api/config/enable_arduino_string/) and [STL's `std::string`](https://arduinojson.org/v6/api/config/enable_std_string/?utm_source=github&utm_medium=readme) + * Supports Arduino's `Stream` and [STL's `std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/?utm_source=github&utm_medium=readme) + * [Supports Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/?utm_source=github&utm_medium=readme) + * Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme#custom-writer) +* Portable + * Usable on any C++ project (not limited to Arduino) + * Compatible with C++98 + * Zero warnings with `-Wall -Wextra -pedantic` and `/W4` + * [Header-only library](https://en.wikipedia.org/wiki/Header-only) + * Works with virtually any board + * Arduino boards: [Uno](https://amzn.to/38aL2ik), [Due](https://amzn.to/36YkWi2), [Micro](https://amzn.to/35WkdwG), [Nano](https://amzn.to/2QTvwRX), [Mega](https://amzn.to/36XWhuf), [Yun](https://amzn.to/30odURc), [Leonardo](https://amzn.to/36XWjlR)... + * Espressif chips: [ESP8266](https://amzn.to/36YluV8), [ESP32](https://amzn.to/2G4pRCB) + * Lolin (WeMos) boards: [D1 mini](https://amzn.to/2QUpz7q), [D1 Mini Pro](https://amzn.to/36UsGSs)... + * Teensy boards: [4.0](https://amzn.to/30ljXGq), [3.2](https://amzn.to/2FT0EuC), [2.0](https://amzn.to/2QXUMXj) + * Particle boards: [Argon](https://amzn.to/2FQHa9X), [Boron](https://amzn.to/36WgLUd), [Electron](https://amzn.to/30vEc4k), [Photon](https://amzn.to/387F9Cd)... + * Texas Instruments boards: [MSP430](https://amzn.to/30nJWgg)... + * Tested on all major development environments + * [Arduino IDE](https://www.arduino.cc/en/Main/Software) + * [Atmel Studio](http://www.atmel.com/microsite/atmel-studio/) + * [Atollic TrueSTUDIO](https://atollic.com/truestudio/) + * [Energia](http://energia.nu/) + * [IAR Embedded Workbench](https://www.iar.com/iar-embedded-workbench/) + * [Keil uVision](http://www.keil.com/) + * [MPLAB X IDE](http://www.microchip.com/mplab/mplab-x-ide) + * [PlatformIO](http://platformio.org/) + * [Sloeber plugin for Eclipse](https://eclipse.baeyens.it/) + * [Visual Micro](http://www.visualmicro.com/) + * [Visual Studio](https://www.visualstudio.com/) + * [Even works with online compilers like wandbox.org](https://wandbox.org/permlink/t7KP7I6dVuLhqzDl) + * [CMake friendly](https://arduinojson.org/v6/how-to/use-arduinojson-with-cmake/?utm_source=github&utm_medium=readme) +* Well designed + * [Elegant API](http://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme) + * [Thread-safe](https://en.wikipedia.org/wiki/Thread_safety) + * Self-contained (no external dependency) + * `const` friendly + * [`for` friendly](https://arduinojson.org/v6/api/jsonobject/begin_end/?utm_source=github&utm_medium=readme) + * [TMP friendly](https://en.wikipedia.org/wiki/Template_metaprogramming) + * Handles [integer overflows](https://arduinojson.org/v6/api/jsonvariant/as/?utm_source=github&utm_medium=readme#integer-overflows) +* Well tested + * [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x) + * Continuously tested on + * [Visual Studio 2010, 2012, 2013, 2015, 2017, 2019](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) + * [GCC 4.4, 4.6, 4.7, 4.8, 4.9, 5, 6, 7, 8](https://travis-ci.org/bblanchon/ArduinoJson) + * [Clang 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 5.0, 6.0, 7, 8](https://travis-ci.org/bblanchon/ArduinoJson) + * [Continuously fuzzed with Google OSS Fuzz](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) +* Well documented + * [Tutorials](https://arduinojson.org/v6/doc/deserialization/?utm_source=github&utm_medium=readme) + * [Examples](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme) + * [How-tos](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme) + * [FAQ](https://arduinojson.org/v6/faq/?utm_source=github&utm_medium=readme) + * [Book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme) +* Vibrant user community + * Most popular of all Arduino libraries on [GitHub](https://github.com/search?o=desc&q=arduino+library&s=stars&type=Repositories) and [PlatformIO](https://platformio.org/lib/search) + * [Used in hundreds of projects](https://www.hackster.io/search?i=projects&q=arduinojson) + * [Responsive support](https://github.com/bblanchon/ArduinoJson/issues?q=is%3Aissue+is%3Aclosed) + +## Quickstart + +### Deserialization + +Here is a program that parses a JSON document with ArduinoJson. + +```c++ +char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; + +DynamicJsonDocument doc(1024); +deserializeJson(doc, json); + +const char* sensor = doc["sensor"]; +long time = doc["time"]; +double latitude = doc["data"][0]; +double longitude = doc["data"][1]; +``` + +See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_source=github&utm_medium=readme) + +### Serialization + +Here is a program that generates a JSON document with ArduinoJson: + +```c++ +DynamicJsonDocument doc(1024); + +doc["sensor"] = "gps"; +doc["time"] = 1351824120; +doc["data"][0] = 48.756080; +doc["data"][1] = 2.302038; + +serializeJson(doc, Serial); +// This prints: +// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} +``` + +See the [tutorial on arduinojson.org](https://arduinojson.org/doc/encoding/?utm_source=github&utm_medium=readme) + +## Support the project + +Do you like this library? Please [star this project on GitHub](https://github.com/bblanchon/ArduinoJson/stargazers)! + +What? You don't like it but you *love* it? +We don't take donations anymore, but [we sell a book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme), so you can help and learn at the same time. diff --git a/lib_standalone/ArduinoJson/SUPPORT.md b/lib/ArduinoJson/SUPPORT.md similarity index 100% rename from lib_standalone/ArduinoJson/SUPPORT.md rename to lib/ArduinoJson/SUPPORT.md diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson.h b/lib/ArduinoJson/src/ArduinoJson.h similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson.h rename to lib/ArduinoJson/src/ArduinoJson.h diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson.hpp b/lib/ArduinoJson/src/ArduinoJson.hpp similarity index 98% rename from lib_standalone/ArduinoJson/src/ArduinoJson.hpp rename to lib/ArduinoJson/src/ArduinoJson.hpp index d2a1f630..a5da7a2e 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson.hpp +++ b/lib/ArduinoJson/src/ArduinoJson.hpp @@ -28,6 +28,7 @@ #include "ArduinoJson/Object/MemberProxy.hpp" #include "ArduinoJson/Object/ObjectImpl.hpp" #include "ArduinoJson/Variant/VariantAsImpl.hpp" +#include "ArduinoJson/Variant/VariantCompare.hpp" #include "ArduinoJson/Variant/VariantImpl.hpp" #include "ArduinoJson/Json/JsonDeserializer.hpp" diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayFunctions.hpp b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayFunctions.hpp similarity index 70% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayFunctions.hpp rename to lib/ArduinoJson/src/ArduinoJson/Array/ArrayFunctions.hpp index c8335d28..517d0b89 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayFunctions.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayFunctions.hpp @@ -12,12 +12,13 @@ inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) { return arr ? arr->addElement(pool) : 0; } -template -inline void arrayAccept(const CollectionData *arr, Visitor &visitor) { +template +inline typename TVisitor::result_type arrayAccept(const CollectionData *arr, + TVisitor &visitor) { if (arr) - visitor.visitArray(*arr); + return visitor.visitArray(*arr); else - visitor.visitNull(); + return visitor.visitNull(); } inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) { diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayImpl.hpp b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayImpl.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayImpl.hpp rename to lib/ArduinoJson/src/ArduinoJson/Array/ArrayImpl.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayIterator.hpp b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayIterator.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayIterator.hpp rename to lib/ArduinoJson/src/ArduinoJson/Array/ArrayIterator.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayRef.hpp b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayRef.hpp similarity index 96% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayRef.hpp rename to lib/ArduinoJson/src/ArduinoJson/Array/ArrayRef.hpp index bb2fbaa7..2e8e7bfd 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayRef.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayRef.hpp @@ -27,9 +27,9 @@ class ArrayRefBase { return VariantConstRef(reinterpret_cast(data)); } - template - FORCE_INLINE void accept(Visitor& visitor) const { - arrayAccept(_data, visitor); + template + FORCE_INLINE typename TVisitor::result_type accept(TVisitor& visitor) const { + return arrayAccept(_data, visitor); } FORCE_INLINE bool isNull() const { diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayShortcuts.hpp b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayShortcuts.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Array/ArrayShortcuts.hpp rename to lib/ArduinoJson/src/ArduinoJson/Array/ArrayShortcuts.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Array/ElementProxy.hpp b/lib/ArduinoJson/src/ArduinoJson/Array/ElementProxy.hpp similarity index 90% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Array/ElementProxy.hpp rename to lib/ArduinoJson/src/ArduinoJson/Array/ElementProxy.hpp index 9af0994b..6d47ef37 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Array/ElementProxy.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Array/ElementProxy.hpp @@ -5,7 +5,8 @@ #pragma once #include -#include +#include +#include #include #ifdef _MSC_VER @@ -17,6 +18,7 @@ namespace ARDUINOJSON_NAMESPACE { template class ElementProxy : public VariantOperators >, + public VariantShortcuts >, public Visitable { typedef ElementProxy this_type; @@ -51,14 +53,6 @@ class ElementProxy : public VariantOperators >, return *this; } - FORCE_INLINE bool operator==(VariantConstRef rhs) const { - return static_cast(getUpstreamElement()) == rhs; - } - - FORCE_INLINE bool operator!=(VariantConstRef rhs) const { - return static_cast(getUpstreamElement()) != rhs; - } - FORCE_INLINE void clear() const { getUpstreamElement().clear(); } @@ -72,6 +66,11 @@ class ElementProxy : public VariantOperators >, return getUpstreamElement().template as(); } + template + FORCE_INLINE operator T() const { + return getUpstreamElement(); + } + template FORCE_INLINE bool is() const { return getUpstreamElement().template is(); @@ -99,8 +98,8 @@ class ElementProxy : public VariantOperators >, return getOrAddUpstreamElement().set(value); } - template - void accept(Visitor& visitor) const { + template + typename TVisitor::result_type accept(TVisitor& visitor) const { return getUpstreamElement().accept(visitor); } @@ -136,6 +135,10 @@ class ElementProxy : public VariantOperators >, return getOrAddUpstreamElement().getElement(index); } + VariantRef getOrAddElement(size_t index) const { + return getOrAddUpstreamElement().getOrAddElement(index); + } + FORCE_INLINE void remove(size_t index) const { getUpstreamElement().remove(index); } diff --git a/lib/ArduinoJson/src/ArduinoJson/Array/Utilities.hpp b/lib/ArduinoJson/src/ArduinoJson/Array/Utilities.hpp new file mode 100644 index 00000000..cd84eb80 --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/Array/Utilities.hpp @@ -0,0 +1,171 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include +#include + +namespace ARDUINOJSON_NAMESPACE { + +// Copy a 1D array to a JsonArray +template +inline typename enable_if::value && + !is_base_of::value, + bool>::type +copyArray(T (&src)[N], const TDestination& dst) { + return copyArray(src, N, dst); +} + +// Copy a 1D array to a JsonDocument +template +inline bool copyArray(T (&src)[N], JsonDocument& dst) { + return copyArray(src, dst.to()); +} + +// Copy a 1D array to a JsonArray +template +inline typename enable_if::value && + !is_base_of::value, + bool>::type +copyArray(T* src, size_t len, const TDestination& dst) { + bool ok = true; + for (size_t i = 0; i < len; i++) { + ok &= dst.add(src[i]); + } + return ok; +} + +// Copy a 1D array to a JsonDocument +template +inline bool copyArray(T* src, size_t len, JsonDocument& dst) { + return copyArray(src, len, dst.to()); +} + +// Copy a 2D array to a JsonArray +template +inline typename enable_if::value, + bool>::type +copyArray(T (&src)[N1][N2], const TDestination& dst) { + bool ok = true; + for (size_t i = 0; i < N1; i++) { + ArrayRef nestedArray = dst.createNestedArray(); + for (size_t j = 0; j < N2; j++) { + ok &= nestedArray.add(src[i][j]); + } + } + return ok; +} + +// Copy a 2D array to a JsonDocument +template +inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) { + return copyArray(src, dst.to()); +} + +template +class ArrayCopier1D : public Visitor { + public: + ArrayCopier1D(T* destination, size_t capacity) + : _destination(destination), _capacity(capacity) {} + + size_t visitArray(const CollectionData& array) { + size_t size = 0; + VariantSlot* slot = array.head(); + + while (slot != 0 && size < _capacity) { + _destination[size++] = variantAs(slot->data()); + slot = slot->next(); + } + return size; + } + + size_t visitObject(const CollectionData&) { + return 0; + } + + size_t visitFloat(Float) { + return 0; + } + + size_t visitString(const char*) { + return 0; + } + + size_t visitRawJson(const char*, size_t) { + return 0; + } + + size_t visitNegativeInteger(UInt) { + return 0; + } + + size_t visitPositiveInteger(UInt) { + return 0; + } + + size_t visitBoolean(bool) { + return 0; + } + + size_t visitNull() { + return 0; + } + + private: + T* _destination; + size_t _capacity; +}; + +template +class ArrayCopier2D : public Visitor { + public: + ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {} + + void visitArray(const CollectionData& array) { + VariantSlot* slot = array.head(); + size_t n = 0; + while (slot != 0 && n < N1) { + ArrayCopier1D copier((*_destination)[n++], N2); + variantAccept(slot->data(), copier); + slot = slot->next(); + } + } + void visitObject(const CollectionData&) {} + void visitFloat(Float) {} + void visitString(const char*) {} + void visitRawJson(const char*, size_t) {} + void visitNegativeInteger(UInt) {} + void visitPositiveInteger(UInt) {} + void visitBoolean(bool) {} + void visitNull() {} + + private: + T (*_destination)[N1][N2]; + size_t _capacity1, _capacity2; +}; + +// Copy a JsonArray to a 1D array +template +inline typename enable_if::value, size_t>::type copyArray( + const TSource& src, T (&dst)[N]) { + return copyArray(src, dst, N); +} + +// Copy a JsonArray to a 1D array +template +inline size_t copyArray(const TSource& src, T* dst, size_t len) { + ArrayCopier1D copier(dst, len); + + return src.accept(copier); +} + +// Copy a JsonArray to a 2D array +template +inline void copyArray(const TSource& src, T (&dst)[N1][N2]) { + ArrayCopier2D copier(&dst); + src.accept(copier); +} + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Collection/CollectionData.hpp b/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionData.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Collection/CollectionData.hpp rename to lib/ArduinoJson/src/ArduinoJson/Collection/CollectionData.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp b/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp similarity index 97% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp rename to lib/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp index 910a2a62..34975442 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp @@ -9,6 +9,10 @@ namespace ARDUINOJSON_NAMESPACE { +inline bool variantEquals(const VariantData* a, const VariantData* b) { + return variantCompare(a, b) == COMPARE_RESULT_EQUAL; +} + inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) { VariantSlot* slot = pool->allocVariant(); if (!slot) diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Configuration.hpp b/lib/ArduinoJson/src/ArduinoJson/Configuration.hpp similarity index 91% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Configuration.hpp rename to lib/ArduinoJson/src/ArduinoJson/Configuration.hpp index e6c01a2f..42ba498e 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Configuration.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Configuration.hpp @@ -4,12 +4,6 @@ #pragma once -#if defined(_MSC_VER) -#define ARDUINOJSON_HAS_INT64 1 -#else -#define ARDUINOJSON_HAS_INT64 0 -#endif - #if __cplusplus >= 201103L #define ARDUINOJSON_HAS_LONG_LONG 1 #define ARDUINOJSON_HAS_NULLPTR 1 @@ -20,6 +14,12 @@ #define ARDUINOJSON_HAS_RVALUE_REFERENCES 0 #endif +#if defined(_MSC_VER) && !ARDUINOJSON_HAS_LONG_LONG +#define ARDUINOJSON_HAS_INT64 1 +#else +#define ARDUINOJSON_HAS_INT64 0 +#endif + // Small or big machine? #ifndef ARDUINOJSON_EMBEDDED_MODE #if defined(ARDUINO) /* Arduino*/ \ @@ -164,7 +164,7 @@ // Convert unicode escape sequence (\u0123) to UTF-8 #ifndef ARDUINOJSON_DECODE_UNICODE -#define ARDUINOJSON_DECODE_UNICODE 0 +#define ARDUINOJSON_DECODE_UNICODE 1 #endif // Ignore comments in input @@ -203,10 +203,22 @@ #endif #endif +#ifndef ARDUINOJSON_ENABLE_ALIGNMENT +#if defined(__AVR) +#define ARDUINOJSON_ENABLE_ALIGNMENT 0 +#else +#define ARDUINOJSON_ENABLE_ALIGNMENT 1 +#endif +#endif + #ifndef ARDUINOJSON_TAB #define ARDUINOJSON_TAB " " #endif +#ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION +#define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1 +#endif + #ifndef ARDUINOJSON_STRING_BUFFER_SIZE #define ARDUINOJSON_STRING_BUFFER_SIZE 32 #endif @@ -218,3 +230,8 @@ #define ARDUINOJSON_DEBUG 0 #endif #endif + +#if ARDUINOJSON_HAS_NULLPTR && defined(nullptr) +#error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr +// See https://github.com/bblanchon/ArduinoJson/issues/1355 +#endif diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/DeserializationError.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/DeserializationError.hpp similarity index 67% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/DeserializationError.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/DeserializationError.hpp index 9ffd0de9..e8902f09 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/DeserializationError.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Deserialization/DeserializationError.hpp @@ -5,6 +5,8 @@ #pragma once #include +#include +#include #if ARDUINOJSON_ENABLE_STD_STREAM #include @@ -20,6 +22,7 @@ class DeserializationError { public: enum Code { Ok, + EmptyInput, IncompleteInput, InvalidInput, NoMemory, @@ -77,24 +80,31 @@ class DeserializationError { } const char* c_str() const { - switch (_code) { - case Ok: - return "Ok"; - case TooDeep: - return "TooDeep"; - case NoMemory: - return "NoMemory"; - case InvalidInput: - return "InvalidInput"; - case IncompleteInput: - return "IncompleteInput"; - case NotSupported: - return "NotSupported"; - default: - return "???"; - } + static const char* messages[] = { + "Ok", "EmptyInput", "IncompleteInput", "InvalidInput", + "NoMemory", "NotSupported", "TooDeep"}; + ARDUINOJSON_ASSERT(static_cast(_code) < + sizeof(messages) / sizeof(messages[0])); + return messages[_code]; } +#if ARDUINOJSON_ENABLE_PROGMEM + const __FlashStringHelper* f_str() const { + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s0, "Ok"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s1, "EmptyInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s2, "IncompleteInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s3, "InvalidInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s4, "NoMemory"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s5, "NotSupported"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s6, "TooDeep"); + ARDUINOJSON_DEFINE_STATIC_ARRAY( + const char*, messages, + ARDUINOJSON_EXPAND7({s0, s1, s2, s3, s4, s5, s6})); + return ARDUINOJSON_READ_STATIC_ARRAY(const __FlashStringHelper*, messages, + _code); + } +#endif + private: Code _code; }; diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Filter.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Filter.hpp similarity index 95% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Filter.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/Filter.hpp index 25248879..63e06a56 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Filter.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Filter.hpp @@ -33,7 +33,7 @@ class Filter { if (_variant == true) // "true" means "allow recursively" return *this; else - return Filter(_variant[key]); + return Filter(_variant[key] | _variant["*"]); } private: diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/NestingLimit.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/NestingLimit.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/NestingLimit.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/NestingLimit.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Reader.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Reader.hpp similarity index 95% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Reader.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/Reader.hpp index 9473f69e..da9a9f24 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Reader.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Reader.hpp @@ -37,6 +37,7 @@ struct BoundedReader { #include #include +#include #if ARDUINOJSON_ENABLE_ARDUINO_STREAM #include diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp similarity index 96% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp index 06352585..6c46d5d8 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp @@ -4,7 +4,7 @@ #pragma once -#include +#include namespace ARDUINOJSON_NAMESPACE { diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/FlashReader.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/FlashReader.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/FlashReader.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/FlashReader.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/IteratorReader.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/IteratorReader.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/IteratorReader.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/IteratorReader.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/RamReader.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/RamReader.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/RamReader.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/RamReader.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp diff --git a/lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/VariantReader.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/VariantReader.hpp new file mode 100644 index 00000000..b06bd4a0 --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/Deserialization/Readers/VariantReader.hpp @@ -0,0 +1,34 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include +#include + +namespace ARDUINOJSON_NAMESPACE { + +template +struct Reader, void> : Reader { + explicit Reader(const ElementProxy& x) + : Reader(x.template as()) {} +}; + +template +struct Reader, void> : Reader { + explicit Reader(const MemberProxy& x) + : Reader(x.template as()) {} +}; + +template <> +struct Reader : Reader { + explicit Reader(VariantRef x) : Reader(x.as()) {} +}; + +template <> +struct Reader : Reader { + explicit Reader(VariantConstRef x) + : Reader(x.as()) {} +}; +} // namespace ARDUINOJSON_NAMESPACE diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/deserialize.hpp b/lib/ArduinoJson/src/ArduinoJson/Deserialization/deserialize.hpp similarity index 94% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/deserialize.hpp rename to lib/ArduinoJson/src/ArduinoJson/Deserialization/deserialize.hpp index f80f587b..7b15e2da 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Deserialization/deserialize.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Deserialization/deserialize.hpp @@ -34,7 +34,7 @@ deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit, doc.clear(); return makeDeserializer( doc.memoryPool(), reader, - makeStringStorage(doc.memoryPool(), input)) + makeStringStorage(input, doc.memoryPool())) .parse(doc.data(), filter, nestingLimit); } // @@ -50,7 +50,7 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input, doc.clear(); return makeDeserializer( doc.memoryPool(), reader, - makeStringStorage(doc.memoryPool(), input)) + makeStringStorage(input, doc.memoryPool())) .parse(doc.data(), filter, nestingLimit); } // @@ -64,7 +64,7 @@ DeserializationError deserialize(JsonDocument &doc, TStream &input, doc.clear(); return makeDeserializer( doc.memoryPool(), reader, - makeStringStorage(doc.memoryPool(), input)) + makeStringStorage(input, doc.memoryPool())) .parse(doc.data(), filter, nestingLimit); } diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Document/BasicJsonDocument.hpp b/lib/ArduinoJson/src/ArduinoJson/Document/BasicJsonDocument.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Document/BasicJsonDocument.hpp rename to lib/ArduinoJson/src/ArduinoJson/Document/BasicJsonDocument.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Document/DynamicJsonDocument.hpp b/lib/ArduinoJson/src/ArduinoJson/Document/DynamicJsonDocument.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Document/DynamicJsonDocument.hpp rename to lib/ArduinoJson/src/ArduinoJson/Document/DynamicJsonDocument.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp b/lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp similarity index 97% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp rename to lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp index cad93318..13cb4911 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp @@ -15,8 +15,8 @@ namespace ARDUINOJSON_NAMESPACE { class JsonDocument : public Visitable { public: - template - void accept(Visitor& visitor) const { + template + typename TVisitor::result_type accept(TVisitor& visitor) const { return getVariant().accept(visitor); } @@ -48,6 +48,10 @@ class JsonDocument : public Visitable { return _pool.size(); } + bool overflowed() const { + return _pool.overflowed(); + } + size_t nesting() const { return _data.nesting(); } @@ -81,6 +85,7 @@ class JsonDocument : public Visitable { return _pool; } + // for internal use only VariantData& data() { return _data; } diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Document/StaticJsonDocument.hpp b/lib/ArduinoJson/src/ArduinoJson/Document/StaticJsonDocument.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Document/StaticJsonDocument.hpp rename to lib/ArduinoJson/src/ArduinoJson/Document/StaticJsonDocument.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/EscapeSequence.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/EscapeSequence.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Json/EscapeSequence.hpp rename to lib/ArduinoJson/src/ArduinoJson/Json/EscapeSequence.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp similarity index 56% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp rename to lib/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp index 276a30a7..a4de0f8e 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp @@ -19,34 +19,26 @@ namespace ARDUINOJSON_NAMESPACE { template class JsonDeserializer { - typedef typename remove_reference::type::StringBuilder - StringBuilder; - - struct StringOrError { - DeserializationError err; - const char *value; - - StringOrError(DeserializationError e) : err(e) {} - StringOrError(DeserializationError::Code c) : err(c) {} - StringOrError(const char *s) : err(DeserializationError::Ok), value(s) {} - }; - public: JsonDeserializer(MemoryPool &pool, TReader reader, TStringStorage stringStorage) - : _pool(&pool), _stringStorage(stringStorage), _latch(reader) {} + : _stringStorage(stringStorage), + _foundSomething(false), + _latch(reader), + _pool(&pool), + _error(DeserializationError::Ok) {} template DeserializationError parse(VariantData &variant, TFilter filter, NestingLimit nestingLimit) { - DeserializationError err = parseVariant(variant, filter, nestingLimit); + parseVariant(variant, filter, nestingLimit); - if (!err && _latch.last() != 0 && !variant.isEnclosed()) { + if (!_error && _latch.last() != 0 && !variant.isEnclosed()) { // We don't detect trailing characters earlier, so we need to check now - err = DeserializationError::InvalidInput; + return DeserializationError::InvalidInput; } - return err; + return _error; } private: @@ -68,11 +60,10 @@ class JsonDeserializer { } template - DeserializationError parseVariant(VariantData &variant, TFilter filter, - NestingLimit nestingLimit) { - DeserializationError err = skipSpacesAndComments(); - if (err) - return err; + bool parseVariant(VariantData &variant, TFilter filter, + NestingLimit nestingLimit) { + if (!skipSpacesAndComments()) + return false; switch (current()) { case '[': @@ -102,10 +93,9 @@ class JsonDeserializer { } } - DeserializationError skipVariant(NestingLimit nestingLimit) { - DeserializationError err = skipSpacesAndComments(); - if (err) - return err; + bool skipVariant(NestingLimit nestingLimit) { + if (!skipSpacesAndComments()) + return false; switch (current()) { case '[': @@ -124,23 +114,24 @@ class JsonDeserializer { } template - DeserializationError parseArray(CollectionData &array, TFilter filter, - NestingLimit nestingLimit) { - if (nestingLimit.reached()) - return DeserializationError::TooDeep; + bool parseArray(CollectionData &array, TFilter filter, + NestingLimit nestingLimit) { + if (nestingLimit.reached()) { + _error = DeserializationError::TooDeep; + return false; + } // Skip opening braket ARDUINOJSON_ASSERT(current() == '['); move(); // Skip spaces - DeserializationError err = skipSpacesAndComments(); - if (err) - return err; + if (!skipSpacesAndComments()) + return false; // Empty array? if (eat(']')) - return DeserializationError::Ok; + return true; TFilter memberFilter = filter[0UL]; @@ -149,35 +140,38 @@ class JsonDeserializer { if (memberFilter.allow()) { // Allocate slot in array VariantData *value = array.addElement(_pool); - if (!value) - return DeserializationError::NoMemory; + if (!value) { + _error = DeserializationError::NoMemory; + return false; + } // 1 - Parse value - err = parseVariant(*value, memberFilter, nestingLimit.decrement()); - if (err) - return err; + if (!parseVariant(*value, memberFilter, nestingLimit.decrement())) + return false; } else { - err = skipVariant(nestingLimit.decrement()); - if (err) - return err; + if (!skipVariant(nestingLimit.decrement())) + return false; } // 2 - Skip spaces - err = skipSpacesAndComments(); - if (err) - return err; + if (!skipSpacesAndComments()) + return false; // 3 - More values? if (eat(']')) - return DeserializationError::Ok; - if (!eat(',')) - return DeserializationError::InvalidInput; + return true; + if (!eat(',')) { + _error = DeserializationError::InvalidInput; + return false; + } } } - DeserializationError skipArray(NestingLimit nestingLimit) { - if (nestingLimit.reached()) - return DeserializationError::TooDeep; + bool skipArray(NestingLimit nestingLimit) { + if (nestingLimit.reached()) { + _error = DeserializationError::TooDeep; + return false; + } // Skip opening braket ARDUINOJSON_ASSERT(current() == '['); @@ -186,153 +180,162 @@ class JsonDeserializer { // Read each value for (;;) { // 1 - Skip value - DeserializationError err = skipVariant(nestingLimit.decrement()); - if (err) - return err; + if (!skipVariant(nestingLimit.decrement())) + return false; // 2 - Skip spaces - err = skipSpacesAndComments(); - if (err) - return err; + if (!skipSpacesAndComments()) + return false; // 3 - More values? if (eat(']')) - return DeserializationError::Ok; - if (!eat(',')) - return DeserializationError::InvalidInput; + return true; + if (!eat(',')) { + _error = DeserializationError::InvalidInput; + return false; + } } } template - DeserializationError parseObject(CollectionData &object, TFilter filter, - NestingLimit nestingLimit) { - if (nestingLimit.reached()) - return DeserializationError::TooDeep; + bool parseObject(CollectionData &object, TFilter filter, + NestingLimit nestingLimit) { + if (nestingLimit.reached()) { + _error = DeserializationError::TooDeep; + return false; + } // Skip opening brace ARDUINOJSON_ASSERT(current() == '{'); move(); // Skip spaces - DeserializationError err = skipSpacesAndComments(); - if (err) - return err; + if (!skipSpacesAndComments()) + return false; // Empty object? if (eat('}')) - return DeserializationError::Ok; + return true; // Read each key value pair for (;;) { // Parse key - StringOrError key = parseKey(); - err = key.err; // <- this trick saves 62 bytes on AVR - if (err) - return err; + if (!parseKey()) + return false; // Skip spaces - err = skipSpacesAndComments(); - if (err) - return err; // Colon - if (!eat(':')) - return DeserializationError::InvalidInput; + if (!skipSpacesAndComments()) + return false; - TFilter memberFilter = filter[key.value]; + // Colon + if (!eat(':')) { + _error = DeserializationError::InvalidInput; + return false; + } + + const char *key = _stringStorage.c_str(); + + TFilter memberFilter = filter[key]; if (memberFilter.allow()) { - VariantData *variant = object.getMember(adaptString(key.value)); + VariantData *variant = object.getMember(adaptString(key)); if (!variant) { + // Save key in memory pool. + // This MUST be done before adding the slot. + key = _stringStorage.save(); + // Allocate slot in object VariantSlot *slot = object.addSlot(_pool); - if (!slot) - return DeserializationError::NoMemory; + if (!slot) { + _error = DeserializationError::NoMemory; + return false; + } - slot->setOwnedKey(make_not_null(key.value)); + slot->setKey(key, typename TStringStorage::storage_policy()); variant = slot->data(); } // Parse value - err = parseVariant(*variant, memberFilter, nestingLimit.decrement()); - if (err) - return err; + if (!parseVariant(*variant, memberFilter, nestingLimit.decrement())) + return false; } else { - _stringStorage.reclaim(key.value); - err = skipVariant(nestingLimit.decrement()); - if (err) - return err; + if (!skipVariant(nestingLimit.decrement())) + return false; } // Skip spaces - err = skipSpacesAndComments(); - if (err) - return err; + if (!skipSpacesAndComments()) + return false; // More keys/values? if (eat('}')) - return DeserializationError::Ok; - if (!eat(',')) - return DeserializationError::InvalidInput; + return true; + if (!eat(',')) { + _error = DeserializationError::InvalidInput; + return false; + } // Skip spaces - err = skipSpacesAndComments(); - if (err) - return err; + if (!skipSpacesAndComments()) + return false; } } - DeserializationError skipObject(NestingLimit nestingLimit) { - if (nestingLimit.reached()) - return DeserializationError::TooDeep; + bool skipObject(NestingLimit nestingLimit) { + if (nestingLimit.reached()) { + _error = DeserializationError::TooDeep; + return false; + } // Skip opening brace ARDUINOJSON_ASSERT(current() == '{'); move(); // Skip spaces - DeserializationError err = skipSpacesAndComments(); - if (err) - return err; + if (!skipSpacesAndComments()) + return false; // Empty object? if (eat('}')) - return DeserializationError::Ok; + return true; // Read each key value pair for (;;) { // Skip key - err = skipVariant(nestingLimit.decrement()); - if (err) - return err; + if (!skipVariant(nestingLimit.decrement())) + return false; // Skip spaces - err = skipSpacesAndComments(); - if (err) - return err; + if (!skipSpacesAndComments()) + return false; // Colon - if (!eat(':')) - return DeserializationError::InvalidInput; + if (!eat(':')) { + _error = DeserializationError::InvalidInput; + return false; + } // Skip value - err = skipVariant(nestingLimit.decrement()); - if (err) - return err; + if (!skipVariant(nestingLimit.decrement())) + return false; // Skip spaces - err = skipSpacesAndComments(); - if (err) - return err; + if (!skipSpacesAndComments()) + return false; // More keys/values? if (eat('}')) - return DeserializationError::Ok; - if (!eat(',')) - return DeserializationError::InvalidInput; + return true; + if (!eat(',')) { + _error = DeserializationError::InvalidInput; + return false; + } } } - StringOrError parseKey() { + bool parseKey() { + _stringStorage.startString(); if (isQuote(current())) { return parseQuotedString(); } else { @@ -340,16 +343,16 @@ class JsonDeserializer { } } - DeserializationError parseStringValue(VariantData &variant) { - StringOrError result = parseQuotedString(); - if (result.err) - return result.err; - variant.setOwnedString(make_not_null(result.value)); - return DeserializationError::Ok; + bool parseStringValue(VariantData &variant) { + _stringStorage.startString(); + if (!parseQuotedString()) + return false; + const char *value = _stringStorage.save(); + variant.setStringPointer(value, typename TStringStorage::storage_policy()); + return true; } - StringOrError parseQuotedString() { - StringBuilder builder = _stringStorage.startString(); + bool parseQuotedString() { #if ARDUINOJSON_DECODE_UNICODE Utf16::Codepoint codepoint; #endif @@ -362,66 +365,82 @@ class JsonDeserializer { if (c == stopChar) break; - if (c == '\0') - return DeserializationError::IncompleteInput; + if (c == '\0') { + _error = DeserializationError::IncompleteInput; + return false; + } if (c == '\\') { c = current(); - if (c == '\0') - return DeserializationError::IncompleteInput; + + if (c == '\0') { + _error = DeserializationError::IncompleteInput; + return false; + } + if (c == 'u') { #if ARDUINOJSON_DECODE_UNICODE move(); uint16_t codeunit; - DeserializationError err = parseHex4(codeunit); - if (err) - return err; + if (!parseHex4(codeunit)) + return false; if (codepoint.append(codeunit)) - Utf8::encodeCodepoint(codepoint.value(), builder); + Utf8::encodeCodepoint(codepoint.value(), _stringStorage); continue; #else - return DeserializationError::NotSupported; + _error = DeserializationError::NotSupported; + return false; #endif } + // replace char c = EscapeSequence::unescapeChar(c); - if (c == '\0') - return DeserializationError::InvalidInput; + if (c == '\0') { + _error = DeserializationError::InvalidInput; + return false; + } move(); } - builder.append(c); + _stringStorage.append(c); } - const char *result = builder.complete(); - if (!result) - return DeserializationError::NoMemory; - return result; - } + _stringStorage.append('\0'); - StringOrError parseNonQuotedString() { - StringBuilder builder = _stringStorage.startString(); + if (!_stringStorage.isValid()) { + _error = DeserializationError::NoMemory; + return false; + } + + return true; + } + bool parseNonQuotedString() { char c = current(); ARDUINOJSON_ASSERT(c); if (canBeInNonQuotedString(c)) { // no quotes do { move(); - builder.append(c); + _stringStorage.append(c); c = current(); } while (canBeInNonQuotedString(c)); } else { - return DeserializationError::InvalidInput; + _error = DeserializationError::InvalidInput; + return false; + } + + _stringStorage.append('\0'); + + if (!_stringStorage.isValid()) { + _error = DeserializationError::NoMemory; + return false; } - const char *result = builder.complete(); - if (!result) - return DeserializationError::NoMemory; - return result; + return true; } - DeserializationError skipString() { + bool skipString() { const char stopChar = current(); move(); @@ -430,87 +449,90 @@ class JsonDeserializer { move(); if (c == stopChar) break; - if (c == '\0') - return DeserializationError::IncompleteInput; + if (c == '\0') { + _error = DeserializationError::IncompleteInput; + return false; + } if (c == '\\') { if (current() != '\0') move(); } } - return DeserializationError::Ok; + return true; } - DeserializationError parseNumericValue(VariantData &result) { - char buffer[64]; + bool parseNumericValue(VariantData &result) { uint8_t n = 0; char c = current(); while (canBeInNonQuotedString(c) && n < 63) { move(); - buffer[n++] = c; + _buffer[n++] = c; c = current(); } - buffer[n] = 0; + _buffer[n] = 0; - c = buffer[0]; + c = _buffer[0]; if (c == 't') { // true result.setBoolean(true); - return n == 4 ? DeserializationError::Ok - : DeserializationError::IncompleteInput; + if (n != 4) { + _error = DeserializationError::IncompleteInput; + return false; + } + return true; } if (c == 'f') { // false result.setBoolean(false); - return n == 5 ? DeserializationError::Ok - : DeserializationError::IncompleteInput; + if (n != 5) { + _error = DeserializationError::IncompleteInput; + return false; + } + return true; } if (c == 'n') { // null // the variant is already null - return n == 4 ? DeserializationError::Ok - : DeserializationError::IncompleteInput; + if (n != 4) { + _error = DeserializationError::IncompleteInput; + return false; + } + return true; } - ParsedNumber num = parseNumber(buffer); - - switch (num.type()) { - case VALUE_IS_NEGATIVE_INTEGER: - result.setNegativeInteger(num.uintValue); - return DeserializationError::Ok; - - case VALUE_IS_POSITIVE_INTEGER: - result.setPositiveInteger(num.uintValue); - return DeserializationError::Ok; - - case VALUE_IS_FLOAT: - result.setFloat(num.floatValue); - return DeserializationError::Ok; + if (!parseNumber(_buffer, result)) { + _error = DeserializationError::InvalidInput; + return false; } - return DeserializationError::InvalidInput; + return true; } - DeserializationError skipNumericValue() { + bool skipNumericValue() { char c = current(); while (canBeInNonQuotedString(c)) { move(); c = current(); } - return DeserializationError::Ok; + return true; } - DeserializationError parseHex4(uint16_t &result) { + bool parseHex4(uint16_t &result) { result = 0; for (uint8_t i = 0; i < 4; ++i) { char digit = current(); - if (!digit) - return DeserializationError::IncompleteInput; + if (!digit) { + _error = DeserializationError::IncompleteInput; + return false; + } uint8_t value = decodeHex(digit); - if (value > 0x0F) - return DeserializationError::InvalidInput; + if (value > 0x0F) { + _error = DeserializationError::InvalidInput; + return false; + } result = uint16_t((result << 4) | value); move(); } - return DeserializationError::Ok; + return true; } static inline bool isBetween(char c, char min, char max) { @@ -533,12 +555,14 @@ class JsonDeserializer { return uint8_t(c - 'A' + 10); } - DeserializationError skipSpacesAndComments() { + bool skipSpacesAndComments() { for (;;) { switch (current()) { // end of string case '\0': - return DeserializationError::IncompleteInput; + _error = _foundSomething ? DeserializationError::IncompleteInput + : DeserializationError::EmptyInput; + return false; // spaces case ' ': @@ -559,8 +583,10 @@ class JsonDeserializer { bool wasStar = false; for (;;) { char c = current(); - if (c == '\0') - return DeserializationError::IncompleteInput; + if (c == '\0') { + _error = DeserializationError::IncompleteInput; + return false; + } if (c == '/' && wasStar) { move(); break; @@ -577,8 +603,10 @@ class JsonDeserializer { for (;;) { move(); char c = current(); - if (c == '\0') - return DeserializationError::IncompleteInput; + if (c == '\0') { + _error = DeserializationError::IncompleteInput; + return false; + } if (c == '\n') break; } @@ -586,63 +614,83 @@ class JsonDeserializer { // not a comment, just a '/' default: - return DeserializationError::InvalidInput; + _error = DeserializationError::InvalidInput; + return false; } break; #endif default: - return DeserializationError::Ok; + _foundSomething = true; + return true; } } } - MemoryPool *_pool; TStringStorage _stringStorage; + bool _foundSomething; Latch _latch; + MemoryPool *_pool; + char _buffer[64]; // using a member instead of a local variable because it + // ended in the recursive path after compiler inlined the + // code + DeserializationError _error; }; +// // deserializeJson(JsonDocument&, const std::string&, ...) -template +// +// ... = NestingLimit +template DeserializationError deserializeJson( - JsonDocument &doc, const TInput &input, + JsonDocument &doc, const TString &input, NestingLimit nestingLimit = NestingLimit()) { return deserialize(doc, input, nestingLimit, AllowAllFilter()); } -template +// ... = Filter, NestingLimit +template DeserializationError deserializeJson( - JsonDocument &doc, const TInput &input, Filter filter, + JsonDocument &doc, const TString &input, Filter filter, NestingLimit nestingLimit = NestingLimit()) { return deserialize(doc, input, nestingLimit, filter); } -template -DeserializationError deserializeJson(JsonDocument &doc, const TInput &input, +// ... = NestingLimit, Filter +template +DeserializationError deserializeJson(JsonDocument &doc, const TString &input, NestingLimit nestingLimit, Filter filter) { return deserialize(doc, input, nestingLimit, filter); } -// deserializeJson(JsonDocument&, const std::istream&, ...) -template +// +// deserializeJson(JsonDocument&, std::istream&, ...) +// +// ... = NestingLimit +template DeserializationError deserializeJson( - JsonDocument &doc, TInput &input, + JsonDocument &doc, TStream &input, NestingLimit nestingLimit = NestingLimit()) { return deserialize(doc, input, nestingLimit, AllowAllFilter()); } -template +// ... = Filter, NestingLimit +template DeserializationError deserializeJson( - JsonDocument &doc, TInput &input, Filter filter, + JsonDocument &doc, TStream &input, Filter filter, NestingLimit nestingLimit = NestingLimit()) { return deserialize(doc, input, nestingLimit, filter); } -template -DeserializationError deserializeJson(JsonDocument &doc, TInput &input, +// ... = NestingLimit, Filter +template +DeserializationError deserializeJson(JsonDocument &doc, TStream &input, NestingLimit nestingLimit, Filter filter) { return deserialize(doc, input, nestingLimit, filter); } +// // deserializeJson(JsonDocument&, char*, ...) +// +// ... = NestingLimit template DeserializationError deserializeJson( JsonDocument &doc, TChar *input, @@ -650,19 +698,24 @@ DeserializationError deserializeJson( return deserialize(doc, input, nestingLimit, AllowAllFilter()); } +// ... = Filter, NestingLimit template DeserializationError deserializeJson( JsonDocument &doc, TChar *input, Filter filter, NestingLimit nestingLimit = NestingLimit()) { return deserialize(doc, input, nestingLimit, filter); } +// ... = NestingLimit, Filter template DeserializationError deserializeJson(JsonDocument &doc, TChar *input, NestingLimit nestingLimit, Filter filter) { return deserialize(doc, input, nestingLimit, filter); } +// // deserializeJson(JsonDocument&, char*, size_t, ...) +// +// ... = NestingLimit template DeserializationError deserializeJson( JsonDocument &doc, TChar *input, size_t inputSize, @@ -670,6 +723,7 @@ DeserializationError deserializeJson( return deserialize(doc, input, inputSize, nestingLimit, AllowAllFilter()); } +// ... = Filter, NestingLimit template DeserializationError deserializeJson( JsonDocument &doc, TChar *input, size_t inputSize, Filter filter, @@ -677,6 +731,7 @@ DeserializationError deserializeJson( return deserialize(doc, input, inputSize, nestingLimit, filter); } +// ... = NestingLimit, Filter template DeserializationError deserializeJson(JsonDocument &doc, TChar *input, size_t inputSize, diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp similarity index 76% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp rename to lib/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp index df0cac68..0baf3c52 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp @@ -12,11 +12,11 @@ namespace ARDUINOJSON_NAMESPACE { template -class JsonSerializer { +class JsonSerializer : public Visitor { public: JsonSerializer(TWriter writer) : _formatter(writer) {} - FORCE_INLINE void visitArray(const CollectionData &array) { + FORCE_INLINE size_t visitArray(const CollectionData &array) { write('['); VariantSlot *slot = array.head(); @@ -32,9 +32,10 @@ class JsonSerializer { } write(']'); + return bytesWritten(); } - void visitObject(const CollectionData &object) { + size_t visitObject(const CollectionData &object) { write('{'); VariantSlot *slot = object.head(); @@ -52,41 +53,49 @@ class JsonSerializer { } write('}'); + return bytesWritten(); } - void visitFloat(Float value) { + size_t visitFloat(Float value) { _formatter.writeFloat(value); + return bytesWritten(); } - void visitString(const char *value) { + size_t visitString(const char *value) { _formatter.writeString(value); + return bytesWritten(); } - void visitRawJson(const char *data, size_t n) { + size_t visitRawJson(const char *data, size_t n) { _formatter.writeRaw(data, n); + return bytesWritten(); } - void visitNegativeInteger(UInt value) { + size_t visitNegativeInteger(UInt value) { _formatter.writeNegativeInteger(value); + return bytesWritten(); } - void visitPositiveInteger(UInt value) { + size_t visitPositiveInteger(UInt value) { _formatter.writePositiveInteger(value); + return bytesWritten(); } - void visitBoolean(bool value) { + size_t visitBoolean(bool value) { _formatter.writeBoolean(value); + return bytesWritten(); } - void visitNull() { + size_t visitNull() { _formatter.writeRaw("null"); + return bytesWritten(); } + protected: size_t bytesWritten() const { return _formatter.bytesWritten(); } - protected: void write(char c) { _formatter.writeRaw(c); } diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/Latch.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/Latch.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Json/Latch.hpp rename to lib/ArduinoJson/src/ArduinoJson/Json/Latch.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/PrettyJsonSerializer.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/PrettyJsonSerializer.hpp similarity index 61% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Json/PrettyJsonSerializer.hpp rename to lib/ArduinoJson/src/ArduinoJson/Json/PrettyJsonSerializer.hpp index 96315d81..b53b920c 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/PrettyJsonSerializer.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Json/PrettyJsonSerializer.hpp @@ -18,44 +18,48 @@ class PrettyJsonSerializer : public JsonSerializer { public: PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {} - void visitArray(const CollectionData &array) { + size_t visitArray(const CollectionData &array) { VariantSlot *slot = array.head(); - if (!slot) - return base::write("[]"); - - base::write("[\r\n"); - _nesting++; - while (slot != 0) { + if (slot) { + base::write("[\r\n"); + _nesting++; + while (slot != 0) { + indent(); + slot->data()->accept(*this); + + slot = slot->next(); + base::write(slot ? ",\r\n" : "\r\n"); + } + _nesting--; indent(); - slot->data()->accept(*this); - - slot = slot->next(); - base::write(slot ? ",\r\n" : "\r\n"); + base::write("]"); + } else { + base::write("[]"); } - _nesting--; - indent(); - base::write("]"); + return this->bytesWritten(); } - void visitObject(const CollectionData &object) { + size_t visitObject(const CollectionData &object) { VariantSlot *slot = object.head(); - if (!slot) - return base::write("{}"); - - base::write("{\r\n"); - _nesting++; - while (slot != 0) { + if (slot) { + base::write("{\r\n"); + _nesting++; + while (slot != 0) { + indent(); + base::visitString(slot->key()); + base::write(": "); + slot->data()->accept(*this); + + slot = slot->next(); + base::write(slot ? ",\r\n" : "\r\n"); + } + _nesting--; indent(); - base::visitString(slot->key()); - base::write(": "); - slot->data()->accept(*this); - - slot = slot->next(); - base::write(slot ? ",\r\n" : "\r\n"); + base::write("}"); + } else { + base::write("{}"); } - _nesting--; - indent(); - base::write("}"); + return this->bytesWritten(); } private: diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp similarity index 85% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp rename to lib/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp index 6e0ca70d..eceef9e0 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp @@ -12,17 +12,18 @@ #include #include #include +#include namespace ARDUINOJSON_NAMESPACE { template class TextFormatter { public: - explicit TextFormatter(TWriter writer) : _writer(writer), _length(0) {} + explicit TextFormatter(TWriter writer) : _writer(writer) {} // Returns the number of bytes sent to the TWriter implementation. size_t bytesWritten() const { - return _length; + return _writer.count(); } void writeBoolean(bool value) { @@ -128,28 +129,28 @@ class TextFormatter { } void writeRaw(const char *s) { - _length += _writer.write(reinterpret_cast(s), strlen(s)); + _writer.write(reinterpret_cast(s), strlen(s)); } void writeRaw(const char *s, size_t n) { - _length += _writer.write(reinterpret_cast(s), n); + _writer.write(reinterpret_cast(s), n); } void writeRaw(const char *begin, const char *end) { - _length += _writer.write(reinterpret_cast(begin), - static_cast(end - begin)); + _writer.write(reinterpret_cast(begin), + static_cast(end - begin)); } template void writeRaw(const char (&s)[N]) { - _length += _writer.write(reinterpret_cast(s), N - 1); + _writer.write(reinterpret_cast(s), N - 1); } void writeRaw(char c) { - _length += _writer.write(static_cast(c)); + _writer.write(static_cast(c)); } protected: - TWriter _writer; + CountingDecorator _writer; size_t _length; private: diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/Utf16.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/Utf16.hpp similarity index 97% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Json/Utf16.hpp rename to lib/ArduinoJson/src/ArduinoJson/Json/Utf16.hpp index 33721a63..67fb5bae 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/Utf16.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Json/Utf16.hpp @@ -31,6 +31,8 @@ inline bool isLowSurrogate(uint16_t codeunit) { class Codepoint { public: + Codepoint() : _highSurrogate(0) {} + bool append(uint16_t codeunit) { if (isHighSurrogate(codeunit)) { _highSurrogate = codeunit & 0x3FF; diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Json/Utf8.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/Utf8.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Json/Utf8.hpp rename to lib/ArduinoJson/src/ArduinoJson/Json/Utf8.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Memory/Alignment.hpp b/lib/ArduinoJson/src/ArduinoJson/Memory/Alignment.hpp similarity index 64% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Memory/Alignment.hpp rename to lib/ArduinoJson/src/ArduinoJson/Memory/Alignment.hpp index 01299d73..f6868d15 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Memory/Alignment.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Memory/Alignment.hpp @@ -10,9 +10,11 @@ namespace ARDUINOJSON_NAMESPACE { -inline bool isAligned(void *ptr) { +#if ARDUINOJSON_ENABLE_ALIGNMENT + +inline bool isAligned(size_t value) { const size_t mask = sizeof(void *) - 1; - size_t addr = reinterpret_cast(ptr); + size_t addr = value; return (addr & mask) == 0; } @@ -21,16 +23,38 @@ inline size_t addPadding(size_t bytes) { return (bytes + mask) & ~mask; } -template -inline T *addPadding(T *p) { - size_t address = addPadding(reinterpret_cast(p)); - return reinterpret_cast(address); -} - template struct AddPadding { static const size_t mask = sizeof(void *) - 1; static const size_t value = (bytes + mask) & ~mask; }; +#else + +inline bool isAligned(size_t) { + return true; +} + +inline size_t addPadding(size_t bytes) { + return bytes; +} + +template +struct AddPadding { + static const size_t value = bytes; +}; + +#endif + +template +inline bool isAligned(T *ptr) { + return isAligned(reinterpret_cast(ptr)); +} + +template +inline T *addPadding(T *p) { + size_t address = addPadding(reinterpret_cast(p)); + return reinterpret_cast(address); +} + } // namespace ARDUINOJSON_NAMESPACE diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Memory/MemoryPool.hpp b/lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPool.hpp similarity index 64% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Memory/MemoryPool.hpp rename to lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPool.hpp index 7d3dbac5..135d8ee5 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Memory/MemoryPool.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPool.hpp @@ -5,13 +5,14 @@ #pragma once #include -#include #include #include #include #include // memmove +#define JSON_STRING_SIZE(SIZE) (SIZE + 1) + namespace ARDUINOJSON_NAMESPACE { // _begin _end @@ -28,7 +29,8 @@ class MemoryPool { : _begin(buf), _left(buf), _right(buf ? buf + capa : 0), - _end(buf ? buf + capa : 0) { + _end(buf ? buf + capa : 0), + _overflowed(false) { ARDUINOJSON_ASSERT(isAligned(_begin)); ARDUINOJSON_ASSERT(isAligned(_right)); ARDUINOJSON_ASSERT(isAligned(_end)); @@ -47,41 +49,61 @@ class MemoryPool { return size_t(_left - _begin + _end - _right); } + bool overflowed() const { + return _overflowed; + } + VariantSlot* allocVariant() { return allocRight(); } - char* allocFrozenString(size_t n) { - if (!canAlloc(n)) + template + const char* saveString(const TAdaptedString& str) { + if (str.isNull()) return 0; - char* s = _left; - _left += n; - checkInvariants(); - return s; + +#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION + const char* existingCopy = findString(str.begin()); + if (existingCopy) + return existingCopy; +#endif + + size_t n = str.size(); + + char* newCopy = allocString(n + 1); + if (newCopy) { + str.copyTo(newCopy, n); + newCopy[n] = 0; // force null-terminator + } + return newCopy; } - StringSlot allocExpandableString() { - StringSlot s; - s.value = _left; - s.size = size_t(_right - _left); - _left = _right; - checkInvariants(); - return s; + void getFreeZone(char** zoneStart, size_t* zoneSize) const { + *zoneStart = _left; + *zoneSize = size_t(_right - _left); } - void freezeString(StringSlot& s, size_t newSize) { - _left -= (s.size - newSize); - s.size = newSize; + const char* saveStringFromFreeZone(size_t len) { +#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION + const char* dup = findString(_left); + if (dup) + return dup; +#endif + + const char* str = _left; + _left += len; checkInvariants(); + return str; } - void reclaimLastString(const char* s) { - _left = const_cast(s); + void markAsOverflowed() { + _overflowed = true; } void clear() { _left = _begin; _right = _end; + _overflowed = false; } bool canAlloc(size_t bytes) const { @@ -92,18 +114,6 @@ class MemoryPool { return _begin <= p && p < _end; } - template - T* allocRight() { - return reinterpret_cast(allocRight(sizeof(T))); - } - - void* allocRight(size_t bytes) { - if (!canAlloc(bytes)) - return 0; - _right -= bytes; - return _right; - } - // Workaround for missing placement new void* operator new(size_t, void* p) { return p; @@ -144,10 +154,6 @@ class MemoryPool { } private: - StringSlot* allocStringSlot() { - return allocRight(); - } - void checkInvariants() { ARDUINOJSON_ASSERT(_begin <= _left); ARDUINOJSON_ASSERT(_left <= _right); @@ -155,7 +161,52 @@ class MemoryPool { ARDUINOJSON_ASSERT(isAligned(_right)); } +#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION + template + const char* findString(TIterator str) { + for (char* next = _begin; next < _left; ++next) { + char* begin = next; + + // try to match + for (TIterator it = str; *it == *next; ++it) { + if (*next++ == 0) + return begin; + } + + // jump to next terminator + while (*next) ++next; + } + return 0; + } +#endif + + char* allocString(size_t n) { + if (!canAlloc(n)) { + _overflowed = true; + return 0; + } + char* s = _left; + _left += n; + checkInvariants(); + return s; + } + + template + T* allocRight() { + return reinterpret_cast(allocRight(sizeof(T))); + } + + void* allocRight(size_t bytes) { + if (!canAlloc(bytes)) { + _overflowed = true; + return 0; + } + _right -= bytes; + return _right; + } + char *_begin, *_left, *_right, *_end; + bool _overflowed; }; } // namespace ARDUINOJSON_NAMESPACE diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Misc/SerializedValue.hpp b/lib/ArduinoJson/src/ArduinoJson/Misc/SerializedValue.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Misc/SerializedValue.hpp rename to lib/ArduinoJson/src/ArduinoJson/Misc/SerializedValue.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Misc/Visitable.hpp b/lib/ArduinoJson/src/ArduinoJson/Misc/Visitable.hpp similarity index 84% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Misc/Visitable.hpp rename to lib/ArduinoJson/src/ArduinoJson/Misc/Visitable.hpp index f259ae5a..65e2d8e6 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Misc/Visitable.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Misc/Visitable.hpp @@ -8,6 +8,11 @@ namespace ARDUINOJSON_NAMESPACE { +template +struct Visitor { + typedef TResult result_type; +}; + struct Visitable { // template // void accept(Visitor&) const; diff --git a/lib/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp b/lib/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp new file mode 100644 index 00000000..76228541 --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp @@ -0,0 +1,637 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace ARDUINOJSON_NAMESPACE { + +template +class MsgPackDeserializer { + public: + MsgPackDeserializer(MemoryPool &pool, TReader reader, + TStringStorage stringStorage) + : _pool(&pool), + _reader(reader), + _stringStorage(stringStorage), + _error(DeserializationError::Ok), + _foundSomething(false) {} + + template + DeserializationError parse(VariantData &variant, TFilter filter, + NestingLimit nestingLimit) { + parseVariant(variant, filter, nestingLimit); + return _foundSomething ? _error : DeserializationError::EmptyInput; + } + + private: + // Prevent VS warning "assignment operator could not be generated" + MsgPackDeserializer &operator=(const MsgPackDeserializer &); + + bool invalidInput() { + _error = DeserializationError::InvalidInput; + return false; + } + + bool notSupported() { + _error = DeserializationError::NotSupported; + return false; + } + + template + bool parseVariant(VariantData &variant, TFilter filter, + NestingLimit nestingLimit) { + uint8_t code = 0; + if (!readByte(code)) + return false; + + _foundSomething = true; + + bool allowValue = filter.allowValue(); + + switch (code) { + case 0xc0: + // already null + return true; + + case 0xc1: + return invalidInput(); + + case 0xc2: + if (allowValue) + variant.setBoolean(false); + return true; + + case 0xc3: + if (allowValue) + variant.setBoolean(true); + return true; + + case 0xc4: // bin 8 + if (allowValue) + return notSupported(); + else + return skipString(); + + case 0xc5: // bin 16 + if (allowValue) + return notSupported(); + else + return skipString(); + + case 0xc6: // bin 32 + if (allowValue) + return notSupported(); + else + return skipString(); + + case 0xc7: // ext 8 + if (allowValue) + return notSupported(); + else + return skipExt(); + + case 0xc8: // ext 16 + if (allowValue) + return notSupported(); + else + return skipExt(); + + case 0xc9: // ext 32 + if (allowValue) + return notSupported(); + else + return skipExt(); + + case 0xca: + if (allowValue) + return readFloat(variant); + else + return skipBytes(4); + + case 0xcb: + if (allowValue) + return readDouble(variant); + else + return skipBytes(8); + + case 0xcc: + if (allowValue) + return readInteger(variant); + else + return skipBytes(1); + + case 0xcd: + if (allowValue) + return readInteger(variant); + else + return skipBytes(2); + + case 0xce: + if (allowValue) + return readInteger(variant); + else + return skipBytes(4); + + case 0xcf: + if (allowValue) +#if ARDUINOJSON_USE_LONG_LONG + return readInteger(variant); +#else + return notSupported(); +#endif + else + return skipBytes(8); + + case 0xd0: + if (allowValue) + return readInteger(variant); + else + return skipBytes(1); + + case 0xd1: + if (allowValue) + return readInteger(variant); + else + return skipBytes(2); + + case 0xd2: + if (allowValue) + return readInteger(variant); + else + return skipBytes(4); + + case 0xd3: + if (allowValue) +#if ARDUINOJSON_USE_LONG_LONG + return readInteger(variant); +#else + return notSupported(); +#endif + else + return skipBytes(8); + + case 0xd4: // fixext 1 + if (allowValue) + return notSupported(); + else + return skipBytes(2); + + case 0xd5: // fixext 2 + if (allowValue) + return notSupported(); + else + return skipBytes(3); + + case 0xd6: // fixext 4 + if (allowValue) + return notSupported(); + else + return skipBytes(5); + + case 0xd7: // fixext 8 + if (allowValue) + return notSupported(); + else + return skipBytes(9); + + case 0xd8: // fixext 16 + if (allowValue) + return notSupported(); + else + return skipBytes(17); + + case 0xd9: + if (allowValue) + return readString(variant); + else + return skipString(); + + case 0xda: + if (allowValue) + return readString(variant); + else + return skipString(); + + case 0xdb: + if (allowValue) + return readString(variant); + else + return skipString(); + + case 0xdc: + return readArray(variant, filter, nestingLimit); + + case 0xdd: + return readArray(variant, filter, nestingLimit); + + case 0xde: + return readObject(variant, filter, nestingLimit); + + case 0xdf: + return readObject(variant, filter, nestingLimit); + } + + switch (code & 0xf0) { + case 0x80: + return readObject(variant, code & 0x0F, filter, nestingLimit); + + case 0x90: + return readArray(variant, code & 0x0F, filter, nestingLimit); + } + + if ((code & 0xe0) == 0xa0) { + if (allowValue) + return readString(variant, code & 0x1f); + else + return skipBytes(code & 0x1f); + } + + if (allowValue) + variant.setInteger(static_cast(code)); + + return true; + } + + bool readByte(uint8_t &value) { + int c = _reader.read(); + if (c < 0) { + _error = DeserializationError::IncompleteInput; + return false; + } + value = static_cast(c); + return true; + } + + bool readBytes(uint8_t *p, size_t n) { + if (_reader.readBytes(reinterpret_cast(p), n) == n) + return true; + _error = DeserializationError::IncompleteInput; + return false; + } + + template + bool readBytes(T &value) { + return readBytes(reinterpret_cast(&value), sizeof(value)); + } + + bool skipBytes(size_t n) { + for (; n; --n) { + if (_reader.read() < 0) { + _error = DeserializationError::IncompleteInput; + return false; + } + } + return true; + } + + template + bool readInteger(T &value) { + if (!readBytes(value)) + return false; + fixEndianess(value); + return true; + } + + template + bool readInteger(VariantData &variant) { + T value; + if (!readInteger(value)) + return false; + variant.setInteger(value); + return true; + } + + template + typename enable_if::type readFloat( + VariantData &variant) { + T value; + if (!readBytes(value)) + return false; + fixEndianess(value); + variant.setFloat(value); + return true; + } + + template + typename enable_if::type readDouble( + VariantData &variant) { + T value; + if (!readBytes(value)) + return false; + fixEndianess(value); + variant.setFloat(value); + return true; + } + + template + typename enable_if::type readDouble( + VariantData &variant) { + uint8_t i[8]; // input is 8 bytes + T value; // output is 4 bytes + uint8_t *o = reinterpret_cast(&value); + if (!readBytes(i, 8)) + return false; + doubleToFloat(i, o); + fixEndianess(value); + variant.setFloat(value); + return true; + } + + template + bool readString(VariantData &variant) { + T size; + if (!readInteger(size)) + return false; + return readString(variant, size); + } + + template + bool readString() { + T size; + if (!readInteger(size)) + return false; + return readString(size); + } + + template + bool skipString() { + T size; + if (!readInteger(size)) + return false; + return skipBytes(size); + } + + bool readString(VariantData &variant, size_t n) { + if (!readString(n)) + return false; + variant.setStringPointer(_stringStorage.save(), + typename TStringStorage::storage_policy()); + return true; + } + + bool readString(size_t n) { + _stringStorage.startString(); + for (; n; --n) { + uint8_t c; + if (!readBytes(c)) + return false; + _stringStorage.append(static_cast(c)); + } + _stringStorage.append('\0'); + if (!_stringStorage.isValid()) { + _error = DeserializationError::NoMemory; + return false; + } + + return true; + } + + template + bool readArray(VariantData &variant, TFilter filter, + NestingLimit nestingLimit) { + TSize size; + if (!readInteger(size)) + return false; + return readArray(variant, size, filter, nestingLimit); + } + + template + bool readArray(VariantData &variant, size_t n, TFilter filter, + NestingLimit nestingLimit) { + if (nestingLimit.reached()) { + _error = DeserializationError::TooDeep; + return false; + } + + bool allowArray = filter.allowArray(); + + CollectionData *array = allowArray ? &variant.toArray() : 0; + + TFilter memberFilter = filter[0U]; + + for (; n; --n) { + VariantData *value; + + if (memberFilter.allow()) { + value = array->addElement(_pool); + if (!value) { + _error = DeserializationError::NoMemory; + return false; + } + } else { + value = 0; + } + + if (!parseVariant(*value, memberFilter, nestingLimit.decrement())) + return false; + } + + return true; + } + + template + bool readObject(VariantData &variant, TFilter filter, + NestingLimit nestingLimit) { + TSize size; + if (!readInteger(size)) + return false; + return readObject(variant, size, filter, nestingLimit); + } + + template + bool readObject(VariantData &variant, size_t n, TFilter filter, + NestingLimit nestingLimit) { + if (nestingLimit.reached()) { + _error = DeserializationError::TooDeep; + return false; + } + + CollectionData *object = filter.allowObject() ? &variant.toObject() : 0; + + for (; n; --n) { + if (!readKey()) + return false; + + const char *key = _stringStorage.c_str(); + TFilter memberFilter = filter[key]; + VariantData *member; + + if (memberFilter.allow()) { + // Save key in memory pool. + // This MUST be done before adding the slot. + key = _stringStorage.save(); + + VariantSlot *slot = object->addSlot(_pool); + if (!slot) { + _error = DeserializationError::NoMemory; + return false; + } + + slot->setKey(key, typename TStringStorage::storage_policy()); + + member = slot->data(); + } else { + member = 0; + } + + if (!parseVariant(*member, memberFilter, nestingLimit.decrement())) + return false; + } + + return true; + } + + bool readKey() { + uint8_t code; + if (!readByte(code)) + return false; + + if ((code & 0xe0) == 0xa0) + return readString(code & 0x1f); + + switch (code) { + case 0xd9: + return readString(); + + case 0xda: + return readString(); + + case 0xdb: + return readString(); + + default: + return notSupported(); + } + } + + template + bool skipExt() { + T size; + if (!readInteger(size)) + return false; + return skipBytes(size + 1); + } + + MemoryPool *_pool; + TReader _reader; + TStringStorage _stringStorage; + DeserializationError _error; + bool _foundSomething; +}; + +// +// deserializeMsgPack(JsonDocument&, const std::string&, ...) +// +// ... = NestingLimit +template +DeserializationError deserializeMsgPack( + JsonDocument &doc, const TString &input, + NestingLimit nestingLimit = NestingLimit()) { + return deserialize(doc, input, nestingLimit, + AllowAllFilter()); +} +// ... = Filter, NestingLimit +template +DeserializationError deserializeMsgPack( + JsonDocument &doc, const TString &input, Filter filter, + NestingLimit nestingLimit = NestingLimit()) { + return deserialize(doc, input, nestingLimit, filter); +} +// ... = NestingLimit, Filter +template +DeserializationError deserializeMsgPack(JsonDocument &doc, const TString &input, + NestingLimit nestingLimit, + Filter filter) { + return deserialize(doc, input, nestingLimit, filter); +} + +// +// deserializeMsgPack(JsonDocument&, std::istream&, ...) +// +// ... = NestingLimit +template +DeserializationError deserializeMsgPack( + JsonDocument &doc, TStream &input, + NestingLimit nestingLimit = NestingLimit()) { + return deserialize(doc, input, nestingLimit, + AllowAllFilter()); +} +// ... = Filter, NestingLimit +template +DeserializationError deserializeMsgPack( + JsonDocument &doc, TStream &input, Filter filter, + NestingLimit nestingLimit = NestingLimit()) { + return deserialize(doc, input, nestingLimit, filter); +} +// ... = NestingLimit, Filter +template +DeserializationError deserializeMsgPack(JsonDocument &doc, TStream &input, + NestingLimit nestingLimit, + Filter filter) { + return deserialize(doc, input, nestingLimit, filter); +} + +// +// deserializeMsgPack(JsonDocument&, char*, ...) +// +// ... = NestingLimit +template +DeserializationError deserializeMsgPack( + JsonDocument &doc, TChar *input, + NestingLimit nestingLimit = NestingLimit()) { + return deserialize(doc, input, nestingLimit, + AllowAllFilter()); +} +// ... = Filter, NestingLimit +template +DeserializationError deserializeMsgPack( + JsonDocument &doc, TChar *input, Filter filter, + NestingLimit nestingLimit = NestingLimit()) { + return deserialize(doc, input, nestingLimit, filter); +} +// ... = NestingLimit, Filter +template +DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input, + NestingLimit nestingLimit, + Filter filter) { + return deserialize(doc, input, nestingLimit, filter); +} + +// +// deserializeMsgPack(JsonDocument&, char*, size_t, ...) +// +// ... = NestingLimit +template +DeserializationError deserializeMsgPack( + JsonDocument &doc, TChar *input, size_t inputSize, + NestingLimit nestingLimit = NestingLimit()) { + return deserialize(doc, input, inputSize, nestingLimit, + AllowAllFilter()); +} +// ... = Filter, NestingLimit +template +DeserializationError deserializeMsgPack( + JsonDocument &doc, TChar *input, size_t inputSize, Filter filter, + NestingLimit nestingLimit = NestingLimit()) { + return deserialize(doc, input, inputSize, nestingLimit, + filter); +} +// ... = NestingLimit, Filter +template +DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input, + size_t inputSize, + NestingLimit nestingLimit, + Filter filter) { + return deserialize(doc, input, inputSize, nestingLimit, + filter); +} + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp b/lib/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp similarity index 77% rename from lib_standalone/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp rename to lib/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp index eedff5b4..e1086367 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,19 +15,20 @@ namespace ARDUINOJSON_NAMESPACE { template -class MsgPackSerializer { +class MsgPackSerializer : public Visitor { public: - MsgPackSerializer(TWriter writer) : _writer(writer), _bytesWritten(0) {} + MsgPackSerializer(TWriter writer) : _writer(writer) {} template - typename enable_if::type visitFloat(T value32) { + typename enable_if::type visitFloat(T value32) { writeByte(0xCA); writeInteger(value32); + return bytesWritten(); } template ARDUINOJSON_NO_SANITIZE("float-cast-overflow") - typename enable_if::type visitFloat(T value64) { + typename enable_if::type visitFloat(T value64) { float value32 = float(value64); if (value32 == value64) { writeByte(0xCA); @@ -35,9 +37,10 @@ class MsgPackSerializer { writeByte(0xCB); writeInteger(value64); } + return bytesWritten(); } - void visitArray(const CollectionData& array) { + size_t visitArray(const CollectionData& array) { size_t n = array.size(); if (n < 0x10) { writeByte(uint8_t(0x90 + array.size())); @@ -51,9 +54,10 @@ class MsgPackSerializer { for (VariantSlot* slot = array.head(); slot; slot = slot->next()) { slot->data()->accept(*this); } + return bytesWritten(); } - void visitObject(const CollectionData& object) { + size_t visitObject(const CollectionData& object) { size_t n = object.size(); if (n < 0x10) { writeByte(uint8_t(0x80 + n)); @@ -68,9 +72,10 @@ class MsgPackSerializer { visitString(slot->key()); slot->data()->accept(*this); } + return bytesWritten(); } - void visitString(const char* value) { + size_t visitString(const char* value) { ARDUINOJSON_ASSERT(value != NULL); size_t n = strlen(value); @@ -88,13 +93,15 @@ class MsgPackSerializer { writeInteger(uint32_t(n)); } writeBytes(reinterpret_cast(value), n); + return bytesWritten(); } - void visitRawJson(const char* data, size_t size) { + size_t visitRawJson(const char* data, size_t size) { writeBytes(reinterpret_cast(data), size); + return bytesWritten(); } - void visitNegativeInteger(UInt value) { + size_t visitNegativeInteger(UInt value) { UInt negated = UInt(~value + 1); if (value <= 0x20) { writeInteger(int8_t(negated)); @@ -114,9 +121,10 @@ class MsgPackSerializer { writeInteger(int64_t(negated)); } #endif + return bytesWritten(); } - void visitPositiveInteger(UInt value) { + size_t visitPositiveInteger(UInt value) { if (value <= 0x7F) { writeInteger(uint8_t(value)); } else if (value <= 0xFF) { @@ -125,7 +133,13 @@ class MsgPackSerializer { } else if (value <= 0xFFFF) { writeByte(0xCD); writeInteger(uint16_t(value)); - } else if (value <= 0xFFFFFFFF) { + } +#if ARDUINOJSON_USE_LONG_LONG + else if (value <= 0xFFFFFFFF) +#else + else +#endif + { writeByte(0xCE); writeInteger(uint32_t(value)); } @@ -135,27 +149,30 @@ class MsgPackSerializer { writeInteger(uint64_t(value)); } #endif + return bytesWritten(); } - void visitBoolean(bool value) { + size_t visitBoolean(bool value) { writeByte(value ? 0xC3 : 0xC2); + return bytesWritten(); } - void visitNull() { + size_t visitNull() { writeByte(0xC0); + return bytesWritten(); } + private: size_t bytesWritten() const { - return _bytesWritten; + return _writer.count(); } - private: void writeByte(uint8_t c) { - _bytesWritten += _writer.write(c); + _writer.write(c); } void writeBytes(const uint8_t* p, size_t n) { - _bytesWritten += _writer.write(p, n); + _writer.write(p, n); } template @@ -164,8 +181,7 @@ class MsgPackSerializer { writeBytes(reinterpret_cast(&value), sizeof(value)); } - TWriter _writer; - size_t _bytesWritten; + CountingDecorator _writer; }; template diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/MsgPack/endianess.hpp b/lib/ArduinoJson/src/ArduinoJson/MsgPack/endianess.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/MsgPack/endianess.hpp rename to lib/ArduinoJson/src/ArduinoJson/MsgPack/endianess.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/MsgPack/ieee754.hpp b/lib/ArduinoJson/src/ArduinoJson/MsgPack/ieee754.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/MsgPack/ieee754.hpp rename to lib/ArduinoJson/src/ArduinoJson/MsgPack/ieee754.hpp diff --git a/lib/ArduinoJson/src/ArduinoJson/Namespace.hpp b/lib/ArduinoJson/src/ArduinoJson/Namespace.hpp new file mode 100644 index 00000000..085ac273 --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/Namespace.hpp @@ -0,0 +1,26 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include +#include +#include + +#ifndef ARDUINOJSON_NAMESPACE + +#define ARDUINOJSON_NAMESPACE \ + ARDUINOJSON_CONCAT4( \ + ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \ + ARDUINOJSON_VERSION_MINOR, \ + ARDUINOJSON_VERSION_REVISION), \ + _, \ + ARDUINOJSON_HEX_DIGIT(ARDUINOJSON_ENABLE_PROGMEM, \ + ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, \ + ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \ + ARDUINOJSON_HEX_DIGIT( \ + ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \ + ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE)) + +#endif diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/Float.hpp b/lib/ArduinoJson/src/ArduinoJson/Numbers/Float.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/Float.hpp rename to lib/ArduinoJson/src/ArduinoJson/Numbers/Float.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/FloatParts.hpp b/lib/ArduinoJson/src/ArduinoJson/Numbers/FloatParts.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/FloatParts.hpp rename to lib/ArduinoJson/src/ArduinoJson/Numbers/FloatParts.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/FloatTraits.hpp b/lib/ArduinoJson/src/ArduinoJson/Numbers/FloatTraits.hpp similarity index 53% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/FloatTraits.hpp rename to lib/ArduinoJson/src/ArduinoJson/Numbers/FloatTraits.hpp index 6f4df596..78bf617c 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/FloatTraits.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Numbers/FloatTraits.hpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include namespace ARDUINOJSON_NAMESPACE { @@ -46,48 +48,60 @@ struct FloatTraits { } static T positiveBinaryPowerOfTen(int index) { - static T factors[] = { - 1e1, - 1e2, - 1e4, - 1e8, - 1e16, - forge(0x4693B8B5, 0xB5056E17), // 1e32 - forge(0x4D384F03, 0xE93FF9F5), // 1e64 - forge(0x5A827748, 0xF9301D32), // 1e128 - forge(0x75154FDD, 0x7F73BF3C) // 1e256 - }; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( // + uint32_t, factors, + ARDUINOJSON_EXPAND18({ + 0x40240000, 0x00000000, // 1e1 + 0x40590000, 0x00000000, // 1e2 + 0x40C38800, 0x00000000, // 1e4 + 0x4197D784, 0x00000000, // 1e8 + 0x4341C379, 0x37E08000, // 1e16 + 0x4693B8B5, 0xB5056E17, // 1e32 + 0x4D384F03, 0xE93FF9F5, // 1e64 + 0x5A827748, 0xF9301D32, // 1e128 + 0x75154FDD, 0x7F73BF3C // 1e256 + })); + return forge( + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index), + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1)); } static T negativeBinaryPowerOfTen(int index) { - static T factors[] = { - forge(0x3FB99999, 0x9999999A), // 1e-1 - forge(0x3F847AE1, 0x47AE147B), // 1e-2 - forge(0x3F1A36E2, 0xEB1C432D), // 1e-4 - forge(0x3E45798E, 0xE2308C3A), // 1e-8 - forge(0x3C9CD2B2, 0x97D889BC), // 1e-16 - forge(0x3949F623, 0xD5A8A733), // 1e-32 - forge(0x32A50FFD, 0x44F4A73D), // 1e-64 - forge(0x255BBA08, 0xCF8C979D), // 1e-128 - forge(0x0AC80628, 0x64AC6F43) // 1e-256 - }; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( // + uint32_t, factors, + ARDUINOJSON_EXPAND18({ + 0x3FB99999, 0x9999999A, // 1e-1 + 0x3F847AE1, 0x47AE147B, // 1e-2 + 0x3F1A36E2, 0xEB1C432D, // 1e-4 + 0x3E45798E, 0xE2308C3A, // 1e-8 + 0x3C9CD2B2, 0x97D889BC, // 1e-16 + 0x3949F623, 0xD5A8A733, // 1e-32 + 0x32A50FFD, 0x44F4A73D, // 1e-64 + 0x255BBA08, 0xCF8C979D, // 1e-128 + 0x0AC80628, 0x64AC6F43 // 1e-256 + })); + return forge( + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index), + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1)); } static T negativeBinaryPowerOfTenPlusOne(int index) { - static T factors[] = { - 1e0, - forge(0x3FB99999, 0x9999999A), // 1e-1 - forge(0x3F50624D, 0xD2F1A9FC), // 1e-3 - forge(0x3E7AD7F2, 0x9ABCAF48), // 1e-7 - forge(0x3CD203AF, 0x9EE75616), // 1e-15 - forge(0x398039D6, 0x65896880), // 1e-31 - forge(0x32DA53FC, 0x9631D10D), // 1e-63 - forge(0x25915445, 0x81B7DEC2), // 1e-127 - forge(0x0AFE07B2, 0x7DD78B14) // 1e-255 - }; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( // + uint32_t, factors, + ARDUINOJSON_EXPAND18({ + 0x3FF00000, 0x00000000, // 1e0 + 0x3FB99999, 0x9999999A, // 1e-1 + 0x3F50624D, 0xD2F1A9FC, // 1e-3 + 0x3E7AD7F2, 0x9ABCAF48, // 1e-7 + 0x3CD203AF, 0x9EE75616, // 1e-15 + 0x398039D6, 0x65896880, // 1e-31 + 0x32DA53FC, 0x9631D10D, // 1e-63 + 0x25915445, 0x81B7DEC2, // 1e-127 + 0x0AFE07B2, 0x7DD78B14 // 1e-255 + })); + return forge( + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index), + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1)); } static T nan() { @@ -144,18 +158,24 @@ struct FloatTraits { } static T positiveBinaryPowerOfTen(int index) { - static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( + T, factors, + ARDUINOJSON_EXPAND6({1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f})); + return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index); } static T negativeBinaryPowerOfTen(int index) { - static T factors[] = {1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f}; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( + T, factors, + ARDUINOJSON_EXPAND6({1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f})); + return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index); } static T negativeBinaryPowerOfTenPlusOne(int index) { - static T factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( + T, factors, + ARDUINOJSON_EXPAND6({1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f})); + return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index); } static T forge(uint32_t bits) { diff --git a/lib/ArduinoJson/src/ArduinoJson/Numbers/Integer.hpp b/lib/ArduinoJson/src/ArduinoJson/Numbers/Integer.hpp new file mode 100644 index 00000000..bca137cf --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/Numbers/Integer.hpp @@ -0,0 +1,32 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include +#include + +#include // int64_t + +namespace ARDUINOJSON_NAMESPACE { + +#if ARDUINOJSON_USE_LONG_LONG +typedef int64_t Integer; +typedef uint64_t UInt; +#else +typedef long Integer; +typedef unsigned long UInt; +#endif + +} // namespace ARDUINOJSON_NAMESPACE + +#if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG +#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \ + static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer), \ + "To use 64-bit integers with ArduinoJson, you must set " \ + "ARDUINOJSON_USE_LONG_LONG to 1. See " \ + "https://arduinojson.org/v6/api/config/use_long_long/"); +#else +#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) +#endif diff --git a/lib/ArduinoJson/src/ArduinoJson/Numbers/arithmeticCompare.hpp b/lib/ArduinoJson/src/ArduinoJson/Numbers/arithmeticCompare.hpp new file mode 100644 index 00000000..df30d172 --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/Numbers/arithmeticCompare.hpp @@ -0,0 +1,121 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include +#include + +namespace ARDUINOJSON_NAMESPACE { + +enum CompareResult { + COMPARE_RESULT_DIFFER = 0, + COMPARE_RESULT_EQUAL = 1, + COMPARE_RESULT_GREATER = 2, + COMPARE_RESULT_LESS = 4, + + COMPARE_RESULT_GREATER_OR_EQUAL = 3, + COMPARE_RESULT_LESS_OR_EQUAL = 5 +}; + +template +CompareResult arithmeticCompare(const T &lhs, const T &rhs) { + if (lhs < rhs) + return COMPARE_RESULT_LESS; + else if (lhs > rhs) + return COMPARE_RESULT_GREATER; + else + return COMPARE_RESULT_EQUAL; +} + +template +CompareResult arithmeticCompare( + const T1 &lhs, const T2 &rhs, + typename enable_if::value && is_integral::value && + sizeof(T1) < sizeof(T2), + int // Using int instead of void to avoid C2572 on + // Visual Studio 2012, 2013, and 2015 + >::type * = 0) { + return arithmeticCompare(static_cast(lhs), rhs); +} + +template +CompareResult arithmeticCompare( + const T1 &lhs, const T2 &rhs, + typename enable_if::value && is_integral::value && + sizeof(T2) < sizeof(T1)>::type * = 0) { + return arithmeticCompare(lhs, static_cast(rhs)); +} + +template +CompareResult arithmeticCompare( + const T1 &lhs, const T2 &rhs, + typename enable_if::value && is_integral::value && + is_signed::value == is_signed::value && + sizeof(T2) == sizeof(T1)>::type * = 0) { + return arithmeticCompare(lhs, static_cast(rhs)); +} + +template +CompareResult arithmeticCompare( + const T1 &lhs, const T2 &rhs, + typename enable_if::value && is_integral::value && + is_unsigned::value && is_signed::value && + sizeof(T2) == sizeof(T1)>::type * = 0) { + if (rhs < 0) + return COMPARE_RESULT_GREATER; + return arithmeticCompare(lhs, static_cast(rhs)); +} + +template +CompareResult arithmeticCompare( + const T1 &lhs, const T2 &rhs, + typename enable_if::value && is_integral::value && + is_signed::value && is_unsigned::value && + sizeof(T2) == sizeof(T1)>::type * = 0) { + if (lhs < 0) + return COMPARE_RESULT_LESS; + return arithmeticCompare(static_cast(lhs), rhs); +} + +template +CompareResult arithmeticCompare( + const T1 &lhs, const T2 &rhs, + typename enable_if::value || + is_floating_point::value>::type * = 0) { + return arithmeticCompare(static_cast(lhs), + static_cast(rhs)); +} + +template +CompareResult arithmeticCompareNegateLeft( + UInt, const T2 &, typename enable_if::value>::type * = 0) { + return COMPARE_RESULT_LESS; +} + +template +CompareResult arithmeticCompareNegateLeft( + UInt lhs, const T2 &rhs, + typename enable_if::value>::type * = 0) { + if (rhs > 0) + return COMPARE_RESULT_LESS; + return arithmeticCompare(-rhs, static_cast(lhs)); +} + +template +CompareResult arithmeticCompareNegateRight( + const T1 &, UInt, typename enable_if::value>::type * = 0) { + return COMPARE_RESULT_GREATER; +} + +template +CompareResult arithmeticCompareNegateRight( + const T1 &lhs, UInt rhs, + typename enable_if::value>::type * = 0) { + if (lhs > 0) + return COMPARE_RESULT_GREATER; + return arithmeticCompare(static_cast(rhs), -lhs); +} + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/convertNumber.hpp b/lib/ArduinoJson/src/ArduinoJson/Numbers/convertNumber.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/convertNumber.hpp rename to lib/ArduinoJson/src/ArduinoJson/Numbers/convertNumber.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/parseNumber.hpp b/lib/ArduinoJson/src/ArduinoJson/Numbers/parseNumber.hpp similarity index 54% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/parseNumber.hpp rename to lib/ArduinoJson/src/ArduinoJson/Numbers/parseNumber.hpp index ad493a3c..2bd18227 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Numbers/parseNumber.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Numbers/parseNumber.hpp @@ -10,54 +10,18 @@ #include #include #include -#include +#include +#include namespace ARDUINOJSON_NAMESPACE { -template -struct ParsedNumber { - ParsedNumber() : uintValue(0), floatValue(0), _type(VALUE_IS_NULL) {} - - ParsedNumber(TUInt value, bool is_negative) - : uintValue(value), - floatValue(TFloat(value)), - _type(uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER - : VALUE_IS_POSITIVE_INTEGER)) {} - ParsedNumber(TFloat value) : floatValue(value), _type(VALUE_IS_FLOAT) {} - - template - T as() const { - switch (_type) { - case VALUE_IS_NEGATIVE_INTEGER: - return convertNegativeInteger(uintValue); - case VALUE_IS_POSITIVE_INTEGER: - return convertPositiveInteger(uintValue); - case VALUE_IS_FLOAT: - return convertFloat(floatValue); - default: - return 0; - } - } - - uint8_t type() const { - return _type; - } - - TUInt uintValue; - TFloat floatValue; - uint8_t _type; -}; - template struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {}; -template -inline ParsedNumber parseNumber(const char *s) { - typedef FloatTraits traits; - typedef typename choose_largest::type - mantissa_t; - typedef typename traits::exponent_type exponent_t; - typedef ParsedNumber return_type; +inline bool parseNumber(const char* s, VariantData& result) { + typedef FloatTraits traits; + typedef choose_largest::type mantissa_t; + typedef traits::exponent_type exponent_t; ARDUINOJSON_ASSERT(s != 0); @@ -73,21 +37,25 @@ inline ParsedNumber parseNumber(const char *s) { } #if ARDUINOJSON_ENABLE_NAN - if (*s == 'n' || *s == 'N') - return traits::nan(); + if (*s == 'n' || *s == 'N') { + result.setFloat(traits::nan()); + return true; + } #endif #if ARDUINOJSON_ENABLE_INFINITY - if (*s == 'i' || *s == 'I') - return is_negative ? -traits::inf() : traits::inf(); + if (*s == 'i' || *s == 'I') { + result.setFloat(is_negative ? -traits::inf() : traits::inf()); + return true; + } #endif if (!isdigit(*s) && *s != '.') - return return_type(); + return false; mantissa_t mantissa = 0; exponent_t exponent_offset = 0; - const mantissa_t maxUint = TUInt(-1); + const mantissa_t maxUint = UInt(-1); while (isdigit(*s)) { uint8_t digit = uint8_t(*s - '0'); @@ -100,8 +68,13 @@ inline ParsedNumber parseNumber(const char *s) { s++; } - if (*s == '\0') - return return_type(TUInt(mantissa), is_negative); + if (*s == '\0') { + if (is_negative) + result.setNegativeInteger(UInt(mantissa)); + else + result.setPositiveInteger(UInt(mantissa)); + return true; + } // avoid mantissa overflow while (mantissa > traits::mantissa_max) { @@ -141,9 +114,10 @@ inline ParsedNumber parseNumber(const char *s) { exponent = exponent * 10 + (*s - '0'); if (exponent + exponent_offset > traits::exponent_max) { if (negative_exponent) - return is_negative ? -0.0f : 0.0f; + result.setFloat(is_negative ? -0.0f : 0.0f); else - return is_negative ? -traits::inf() : traits::inf(); + result.setFloat(is_negative ? -traits::inf() : traits::inf()); + return true; } s++; } @@ -154,10 +128,20 @@ inline ParsedNumber parseNumber(const char *s) { // we should be at the end of the string, otherwise it's an error if (*s != '\0') - return return_type(); + return false; - TFloat result = traits::make_float(static_cast(mantissa), exponent); + Float final_result = + traits::make_float(static_cast(mantissa), exponent); + + result.setFloat(is_negative ? -final_result : final_result); + return true; +} - return is_negative ? -result : result; +template +inline T parseNumber(const char* s) { + VariantData value; + value.init(); // VariantData is a POD, so it has no constructor + parseNumber(s, value); + return variantAs(&value); } } // namespace ARDUINOJSON_NAMESPACE diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Object/MemberProxy.hpp b/lib/ArduinoJson/src/ArduinoJson/Object/MemberProxy.hpp similarity index 91% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Object/MemberProxy.hpp rename to lib/ArduinoJson/src/ArduinoJson/Object/MemberProxy.hpp index 926a1e76..a9ee6034 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Object/MemberProxy.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Object/MemberProxy.hpp @@ -5,8 +5,11 @@ #pragma once #include -#include #include +#include +#include +#include +#include #ifdef _MSC_VER #pragma warning(push) @@ -17,6 +20,7 @@ namespace ARDUINOJSON_NAMESPACE { template class MemberProxy : public VariantOperators >, + public VariantShortcuts >, public Visitable { typedef MemberProxy this_type; @@ -52,14 +56,6 @@ class MemberProxy : public VariantOperators >, return *this; } - FORCE_INLINE bool operator==(VariantConstRef rhs) const { - return static_cast(getUpstreamMember()) == rhs; - } - - FORCE_INLINE bool operator!=(VariantConstRef rhs) const { - return static_cast(getUpstreamMember()) != rhs; - } - FORCE_INLINE void clear() const { getUpstreamMember().clear(); } @@ -73,6 +69,11 @@ class MemberProxy : public VariantOperators >, return getUpstreamMember().template as(); } + template + FORCE_INLINE operator T() const { + return getUpstreamMember(); + } + template FORCE_INLINE bool is() const { return getUpstreamMember().template is(); @@ -119,8 +120,8 @@ class MemberProxy : public VariantOperators >, return getOrAddUpstreamMember().set(value); } - template - void accept(Visitor &visitor) const { + template + typename TVisitor::result_type accept(TVisitor &visitor) const { return getUpstreamMember().accept(visitor); } diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectFunctions.hpp b/lib/ArduinoJson/src/ArduinoJson/Object/ObjectFunctions.hpp similarity index 81% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectFunctions.hpp rename to lib/ArduinoJson/src/ArduinoJson/Object/ObjectFunctions.hpp index 0c754eb3..1c7d5f3e 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectFunctions.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Object/ObjectFunctions.hpp @@ -8,12 +8,13 @@ namespace ARDUINOJSON_NAMESPACE { -template -void objectAccept(const CollectionData *obj, Visitor &visitor) { +template +typename TVisitor::result_type objectAccept(const CollectionData *obj, + TVisitor &visitor) { if (obj) - visitor.visitObject(*obj); + return visitor.visitObject(*obj); else - visitor.visitNull(); + return visitor.visitNull(); } inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) { diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectImpl.hpp b/lib/ArduinoJson/src/ArduinoJson/Object/ObjectImpl.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectImpl.hpp rename to lib/ArduinoJson/src/ArduinoJson/Object/ObjectImpl.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectIterator.hpp b/lib/ArduinoJson/src/ArduinoJson/Object/ObjectIterator.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectIterator.hpp rename to lib/ArduinoJson/src/ArduinoJson/Object/ObjectIterator.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectRef.hpp b/lib/ArduinoJson/src/ArduinoJson/Object/ObjectRef.hpp similarity index 97% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectRef.hpp rename to lib/ArduinoJson/src/ArduinoJson/Object/ObjectRef.hpp index 599a2ae9..e57e088e 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectRef.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Object/ObjectRef.hpp @@ -22,9 +22,9 @@ class ObjectRefBase { return VariantConstRef(reinterpret_cast(data)); } - template - FORCE_INLINE void accept(Visitor& visitor) const { - objectAccept(_data, visitor); + template + typename TVisitor::result_type accept(TVisitor& visitor) const { + return objectAccept(_data, visitor); } FORCE_INLINE bool isNull() const { diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectShortcuts.hpp b/lib/ArduinoJson/src/ArduinoJson/Object/ObjectShortcuts.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Object/ObjectShortcuts.hpp rename to lib/ArduinoJson/src/ArduinoJson/Object/ObjectShortcuts.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Object/Pair.hpp b/lib/ArduinoJson/src/ArduinoJson/Object/Pair.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Object/Pair.hpp rename to lib/ArduinoJson/src/ArduinoJson/Object/Pair.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/alias_cast.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/alias_cast.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/alias_cast.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/alias_cast.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/assert.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/assert.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/assert.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/assert.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/attributes.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/attributes.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/attributes.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/attributes.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/ctype.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/ctype.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/ctype.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/ctype.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/limits.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/limits.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/limits.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/limits.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/math.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/math.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/math.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/math.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/mpl/max.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/mpl/max.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/mpl/max.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/mpl/max.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/pgmspace.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/pgmspace.hpp similarity index 97% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/pgmspace.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/pgmspace.hpp index ffeffd18..0cdc5cb7 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/pgmspace.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Polyfills/pgmspace.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include #include diff --git a/lib/ArduinoJson/src/ArduinoJson/Polyfills/pgmspace_generic.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/pgmspace_generic.hpp new file mode 100644 index 00000000..c6c1847e --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/Polyfills/pgmspace_generic.hpp @@ -0,0 +1,32 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include +#include + +namespace ARDUINOJSON_NAMESPACE { + +template +typename enable_if::value, T>::type pgm_read(const void* p) { + return reinterpret_cast(pgm_read_ptr(p)); +} + +template +typename enable_if::value && + sizeof(T) == sizeof(float), // on AVR sizeof(double) == + // sizeof(float) + T>::type +pgm_read(const void* p) { + return pgm_read_float(p); +} + +template +typename enable_if::value, T>::type pgm_read( + const void* p) { + return pgm_read_dword(p); +} + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/lib/ArduinoJson/src/ArduinoJson/Polyfills/preprocessor.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/preprocessor.hpp new file mode 100644 index 00000000..4df13d8b --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/Polyfills/preprocessor.hpp @@ -0,0 +1,36 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#define ARDUINOJSON_EXPAND6(a, b, c, d, e, f) a, b, c, d, e, f +#define ARDUINOJSON_EXPAND7(a, b, c, d, e, f, g) a, b, c, d, e, f, g +#define ARDUINOJSON_EXPAND9(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i +#define ARDUINOJSON_EXPAND18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, \ + q, r) \ + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r + +#define ARDUINOJSON_CONCAT_(A, B) A##B +#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B) +#define ARDUINOJSON_CONCAT4(A, B, C, D) \ + ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D)) + +#define ARDUINOJSON_HEX_DIGIT_0000() 0 +#define ARDUINOJSON_HEX_DIGIT_0001() 1 +#define ARDUINOJSON_HEX_DIGIT_0010() 2 +#define ARDUINOJSON_HEX_DIGIT_0011() 3 +#define ARDUINOJSON_HEX_DIGIT_0100() 4 +#define ARDUINOJSON_HEX_DIGIT_0101() 5 +#define ARDUINOJSON_HEX_DIGIT_0110() 6 +#define ARDUINOJSON_HEX_DIGIT_0111() 7 +#define ARDUINOJSON_HEX_DIGIT_1000() 8 +#define ARDUINOJSON_HEX_DIGIT_1001() 9 +#define ARDUINOJSON_HEX_DIGIT_1010() A +#define ARDUINOJSON_HEX_DIGIT_1011() B +#define ARDUINOJSON_HEX_DIGIT_1100() C +#define ARDUINOJSON_HEX_DIGIT_1101() D +#define ARDUINOJSON_HEX_DIGIT_1110() E +#define ARDUINOJSON_HEX_DIGIT_1111() F +#define ARDUINOJSON_HEX_DIGIT_(A, B, C, D) ARDUINOJSON_HEX_DIGIT_##A##B##C##D() +#define ARDUINOJSON_HEX_DIGIT(A, B, C, D) ARDUINOJSON_HEX_DIGIT_(A, B, C, D) diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/safe_strcmp.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/safe_strcmp.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/safe_strcmp.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/safe_strcmp.hpp diff --git a/lib/ArduinoJson/src/ArduinoJson/Polyfills/static_array.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/static_array.hpp new file mode 100644 index 00000000..c642b270 --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/Polyfills/static_array.hpp @@ -0,0 +1,34 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include + +#if ARDUINOJSON_ENABLE_PROGMEM + +#include + +#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY +#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ + static type const name[] PROGMEM = value; +#endif + +#ifndef ARDUINOJSON_READ_STATIC_ARRAY +#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \ + pgm_read(name + index) +#endif + +#else // i.e. ARDUINOJSON_ENABLE_PROGMEM == 0 + +#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY +#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ + static type const name[] = value; +#endif + +#ifndef ARDUINOJSON_READ_STATIC_ARRAY +#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index] +#endif + +#endif diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits.hpp similarity index 95% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits.hpp index 324f1444..43dc4e01 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits.hpp @@ -15,6 +15,7 @@ #include "type_traits/is_enum.hpp" #include "type_traits/is_floating_point.hpp" #include "type_traits/is_integral.hpp" +#include "type_traits/is_pointer.hpp" #include "type_traits/is_same.hpp" #include "type_traits/is_signed.hpp" #include "type_traits/is_unsigned.hpp" diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/conditional.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/conditional.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/conditional.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/conditional.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/declval.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/declval.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/declval.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/declval.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/enable_if.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/enable_if.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/enable_if.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/enable_if.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/integral_constant.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/integral_constant.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/integral_constant.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/integral_constant.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_array.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_array.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_array.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_array.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_base_of.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_base_of.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_base_of.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_base_of.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_class.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_class.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_class.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_class.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_const.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_const.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_const.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_const.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_convertible.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_convertible.hpp similarity index 77% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_convertible.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_convertible.hpp index e0232aae..61cd7caa 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_convertible.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_convertible.hpp @@ -12,6 +12,11 @@ #pragma warning(disable : 4244) #endif +#ifdef __ICCARM__ +// Suppress IAR Compiler Warning[Pa093]: implicit conversion from floating point to integer +#pragma diag_suppress=Pa093 +#endif + namespace ARDUINOJSON_NAMESPACE { template @@ -32,3 +37,7 @@ struct is_convertible { #ifdef _MSC_VER #pragma warning(pop) #endif + +#ifdef __ICCARM__ +#pragma diag_default=Pa093 +#endif diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_enum.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_enum.hpp similarity index 81% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_enum.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_enum.hpp index 8ef57d8f..ed33a6cd 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_enum.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_enum.hpp @@ -16,8 +16,7 @@ template struct is_enum { static const bool value = is_convertible::value && !is_class::value && !is_integral::value && - !is_floating_point::value && - !is_same::value; + !is_floating_point::value; }; } // namespace ARDUINOJSON_NAMESPACE diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_integral.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_integral.hpp similarity index 90% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_integral.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_integral.hpp index b45a8636..9c6f0976 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_integral.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_integral.hpp @@ -25,9 +25,7 @@ struct is_integral { is_same::value || is_same::value || #endif - is_same::value; - - // CAUTION: differs from std::is_integral as it doesn't include bool + is_same::value || is_same::value; }; template diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Memory/StringSlot.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_pointer.hpp similarity index 51% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Memory/StringSlot.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_pointer.hpp index 05f940b1..92ba098a 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Memory/StringSlot.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_pointer.hpp @@ -4,16 +4,13 @@ #pragma once -#include // for size_t - -#include - -#define JSON_STRING_SIZE(SIZE) (SIZE) +#include "integral_constant.hpp" namespace ARDUINOJSON_NAMESPACE { -struct StringSlot { - char *value; - size_t size; -}; +template +struct is_pointer : false_type {}; + +template +struct is_pointer : true_type {}; } // namespace ARDUINOJSON_NAMESPACE diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_same.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_same.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_same.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_same.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_signed.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_signed.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_signed.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_signed.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/make_unsigned.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/make_unsigned.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/make_unsigned.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/make_unsigned.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/remove_const.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/remove_const.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/remove_const.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/remove_const.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/remove_reference.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/remove_reference.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/remove_reference.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/remove_reference.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/type_identity.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/type_identity.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/type_identity.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/type_traits/type_identity.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/utility.hpp b/lib/ArduinoJson/src/ArduinoJson/Polyfills/utility.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Polyfills/utility.hpp rename to lib/ArduinoJson/src/ArduinoJson/Polyfills/utility.hpp diff --git a/lib/ArduinoJson/src/ArduinoJson/Serialization/CountingDecorator.hpp b/lib/ArduinoJson/src/ArduinoJson/Serialization/CountingDecorator.hpp new file mode 100644 index 00000000..140ada71 --- /dev/null +++ b/lib/ArduinoJson/src/ArduinoJson/Serialization/CountingDecorator.hpp @@ -0,0 +1,33 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include + +namespace ARDUINOJSON_NAMESPACE { + +template +class CountingDecorator { + public: + explicit CountingDecorator(TWriter& writer) : _writer(writer), _count(0) {} + + void write(uint8_t c) { + _count += _writer.write(c); + } + + void write(const uint8_t* s, size_t n) { + _count += _writer.write(s, n); + } + + size_t count() const { + return _count; + } + + private: + TWriter _writer; + size_t _count; +}; + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writer.hpp b/lib/ArduinoJson/src/ArduinoJson/Serialization/Writer.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writer.hpp rename to lib/ArduinoJson/src/ArduinoJson/Serialization/Writer.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp b/lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp similarity index 97% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp rename to lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp index 1fac2602..801cb86c 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp @@ -4,7 +4,7 @@ #pragma once -#include +#include namespace ARDUINOJSON_NAMESPACE { diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/DummyWriter.hpp b/lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/DummyWriter.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/DummyWriter.hpp rename to lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/DummyWriter.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/PrintWriter.hpp b/lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/PrintWriter.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/PrintWriter.hpp rename to lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/PrintWriter.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/StaticStringWriter.hpp b/lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/StaticStringWriter.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/StaticStringWriter.hpp rename to lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/StaticStringWriter.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/StdStreamWriter.hpp b/lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/StdStreamWriter.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/StdStreamWriter.hpp rename to lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/StdStreamWriter.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/StdStringWriter.hpp b/lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/StdStringWriter.hpp similarity index 100% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/Writers/StdStringWriter.hpp rename to lib/ArduinoJson/src/ArduinoJson/Serialization/Writers/StdStringWriter.hpp diff --git a/lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/measure.hpp b/lib/ArduinoJson/src/ArduinoJson/Serialization/measure.hpp similarity index 86% rename from lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/measure.hpp rename to lib/ArduinoJson/src/ArduinoJson/Serialization/measure.hpp index e2434042..00f79077 100644 --- a/lib_standalone/ArduinoJson/src/ArduinoJson/Serialization/measure.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Serialization/measure.hpp @@ -12,8 +12,7 @@ template