mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
initial commit
This commit is contained in:
18
.gitignore
vendored
18
.gitignore
vendored
@@ -1,16 +1,12 @@
|
||||
# vscode
|
||||
.vscode
|
||||
|
||||
# build
|
||||
build/
|
||||
|
||||
# platformio
|
||||
.pio
|
||||
lib/readme.txt
|
||||
|
||||
# web stuff compiled
|
||||
src/websrc/temp
|
||||
src/webh/*.gz.h
|
||||
|
||||
# NPM directories
|
||||
node_modules
|
||||
pio_local.ini
|
||||
|
||||
# OS specific
|
||||
.DS_Store
|
||||
@@ -18,6 +14,8 @@ node_modules
|
||||
# project specfic
|
||||
scripts/stackdmp.txt
|
||||
firmware
|
||||
|
||||
# firmware
|
||||
*.bin
|
||||
emsesp
|
||||
doc/github.txt
|
||||
doc/test_data.txt
|
||||
|
||||
|
||||
88
.travis.yml
88
.travis.yml
@@ -1,88 +0,0 @@
|
||||
os: linux
|
||||
dist: bionic
|
||||
language: python
|
||||
python:
|
||||
- "3.8"
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- ${HOME}/.pio
|
||||
|
||||
env:
|
||||
global:
|
||||
# - BUILDER_TOTAL_THREADS=4
|
||||
- BUILDER_TOTAL_THREADS=1
|
||||
- OWNER=${TRAVIS_REPO_SLUG%/*}
|
||||
- DEV=${OWNER/proddy/dev}
|
||||
- BRANCH=${TRAVIS_BRANCH/dev/}
|
||||
- TAG=${DEV}${BRANCH:+_}${BRANCH}
|
||||
|
||||
install:
|
||||
- env | grep TRAVIS
|
||||
- set -e
|
||||
- pip install -U platformio
|
||||
- pio platform update -p
|
||||
- set +e
|
||||
|
||||
branches:
|
||||
except:
|
||||
- /^travis-.*-build$/
|
||||
|
||||
script:
|
||||
- ./scripts/build.sh
|
||||
# - ./scripts/build.sh -p
|
||||
|
||||
stages:
|
||||
- name: Release
|
||||
# if: type IN (cron, api)
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: Release
|
||||
# env: BUILDER_THREAD=0
|
||||
# - env: BUILDER_THREAD=1
|
||||
# - env: BUILDER_THREAD=2
|
||||
# - env: BUILDER_THREAD=3
|
||||
|
||||
before_deploy:
|
||||
- export FIRMWARE_VERSION=$(grep -E '^#define APP_VERSION' ./src/version.h | awk '{print $3}' | sed 's/"//g')
|
||||
- git tag -f travis-${TAG}-build
|
||||
- git remote add gh
|
||||
https://${OWNER}:${GITHUB_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git
|
||||
- git push gh :travis-${TAG}-build || true
|
||||
- git push -f gh travis-${TAG}-build
|
||||
- git remote remove gh
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
edge:
|
||||
# source: wenkokke/dpl
|
||||
branch: master
|
||||
token: ${GITHUB_TOKEN}
|
||||
file_glob: true
|
||||
# file: "firmware/*.bin"
|
||||
file: "*.bin"
|
||||
name: latest development build
|
||||
release_notes:
|
||||
Version $FIRMWARE_VERSION.
|
||||
Automatic firmware builds of the current EMS-ESP branch built on $(date +'%F %T %Z') from commit $TRAVIS_COMMIT.
|
||||
Warning, this is a development build and not fully tested. Use at your own risk.
|
||||
cleanup: false
|
||||
prerelease: true
|
||||
overwrite: true
|
||||
target_commitish: $TRAVIS_COMMIT
|
||||
on:
|
||||
tags: false
|
||||
branch: dev
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: change
|
||||
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/57e15f7798656d888194
|
||||
on_success: always
|
||||
on_failure: never
|
||||
on_start: never
|
||||
581
CHANGELOG.md
581
CHANGELOG.md
@@ -1,581 +0,0 @@
|
||||
# EMS-ESP 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).
|
||||
|
||||
## [1.9.5] 30-04-2020
|
||||
|
||||
### Added
|
||||
- Solar Module SM200 support
|
||||
- Support writing to Junkers FR100 thermostats
|
||||
- Support writing to RC100, Moduline 1000/1010 thermostats
|
||||
- MM10 Mixing module support (thanks @MichaelDvP)
|
||||
- MM200 warm water circuits (https://github.com/proddy/EMS-ESP/pull/315)
|
||||
- Support for Moduline 200 and Sieger ES72 thermostats
|
||||
- First implementation of writing to generic Junker Thermostats (thanks @Neonox31)
|
||||
- Added model type (Buderus, Sieger, Junkers, Nefit, Bosch, Worcester) to device names
|
||||
- `set master_thermostat <product id>` to choose with thermostat is master when there are multiple on the bus
|
||||
- `boiler wwonetime` command from Telnet
|
||||
- `set bus_id <ID>` to support multiple EMS-ESP circuits. Default is 0x0B to mimic a service key.
|
||||
- `mqtt_nestedjson` option to disable multiple data records being nested into a single JSON string
|
||||
- MQTT publish messages are queued and gracefully published every second to avoid TCP blocks
|
||||
- Added features to WW messages (0x33, 0x34) to improve WW monitoring. (PR#338 by @ypaindaveine)
|
||||
- Added mixing log and stub for EMS type 0xAC (PR#338 by @ypaindaveine)
|
||||
- Added Thermostat retrieving settings (0xA5) (validated on RC30N) with MQTT support (thanks Yves @ypaindaveine. See #352)
|
||||
- Merged with PR https://github.com/proddy/EMS-ESP/pull/366 from @MichaelDvP fixing RC20 and MM50
|
||||
|
||||
### Fixed
|
||||
- set boiler warm water temp on Junkers/Bosch HT3
|
||||
- fixed detection of the Moduline 400 thermostat
|
||||
- RC35 setting temperature also forces the current select temp to change, irrespective of the mode
|
||||
|
||||
### Changed
|
||||
- improved MQTT publishing to stop network flooding. `publish_time` of -1 is no publish, 0 is automatic otherwise its a time interval
|
||||
- External sensors (like Dallas DS18*) are sent as a nested MQTT topic including their unqiue identifier
|
||||
- `mqttlog` console command renamed to `mqttqueue` to only show the current publish queue
|
||||
- `status` payload on start-up shows the IP and Version of EMS-ESP
|
||||
- `thermostat mode` takes a string like manual,auto,heat,day,night,eco,comfort,holiday,nofrost
|
||||
- `thermostat temp` also takes a mode string, e.g. `thermostat temp 20 heat`
|
||||
- `queue` renamed to `txqueue`
|
||||
|
||||
### Removed
|
||||
- `autodetect scan`. Replaced with `devices scan` and `devices scan+` for deep scanning
|
||||
- `mqttlog all` and showing MQTT log in the web interface - no point showing history of previous mqtt publishes in ESP's precious memory. For debugging I recommend using MQTT Explorer or another external tool.
|
||||
|
||||
## [1.9.4] 15-12-2019
|
||||
|
||||
There are breaking changes in this release. Make you sure you adjust the MQTT topics as described in the wiki.
|
||||
|
||||
### Added
|
||||
|
||||
- Added `publish_always` forcing MQTT topics to be always sent regardless if the data hasn't changed
|
||||
- Support for DHW once (OneTime water) heating command via MQTT [issue 195](https://github.com/proddy/EMS-ESP/issues/195)
|
||||
- Added scripts to automatically build firmware images on every Commit/Pull and nightly builds using TravisCI
|
||||
- Added option to WebUI to also download the latest development build
|
||||
- Added build scripts for automated CI with TravisCI
|
||||
- Implemented timezone support and automatic adjustment, also taking daylight saving times into account
|
||||
- Added `kick` command to reset core services like NTP, Web, Web Sockets
|
||||
- Added WiFi static IP (setting done in WebUI only)
|
||||
- `log w <type_id>` for watching a specific telegram type ID
|
||||
- initial support for EMS+ GB125s and MC110's (https://github.com/proddy/EMS-ESP/wiki/MC110-controller)
|
||||
- Buderus RFM200 receiver
|
||||
|
||||
### Fixed
|
||||
|
||||
- Stability for some Wemos clones by decreasing wifi Tx strength and adding small delay
|
||||
|
||||
### Changed
|
||||
|
||||
- Debug log times show real internet time (if NTP enabled)
|
||||
- `system` shows local time instead of UTC
|
||||
- fixed version numbers of libraries in `platformio.ini`
|
||||
- Normalized Heating modes to `off`, `manual`, `auto`, `night` and `day` to keep generic and not Home Assistant specific (like `heat`)
|
||||
- Keeping Thermostat day/night modes separate from off/auto/manual, and setting this for the Junkers FR50
|
||||
- Removed `publish_always`
|
||||
- Changed NTP interval from 1 hour to 12 hours
|
||||
- Refactored EMS device library to make it support multi-EMS devices easier (e.g. multiple thermostats)
|
||||
- `autodetect deep` removed and replaced with `autodetect scan` for scanning known devices.
|
||||
- MQTT data will be sent when new data arrives. So `publish_time` is used to force a publish at a given frequency (2 mins is default), or 0 for off.
|
||||
|
||||
### Removed
|
||||
|
||||
- thermostat scan and autodetect deep functions
|
||||
- removed Event Logging to SPIFFS (worried about wearing). Replaced with SysLog.
|
||||
|
||||
## [1.9.3] 2019-10-26
|
||||
|
||||
### Added
|
||||
|
||||
- Report # TCP dropouts in the `system` command. These could be due to WiFI or MQTT disconnected.
|
||||
- Added temp and mode to the MQTT `thermostat_cmd` topic
|
||||
|
||||
### Fixed
|
||||
|
||||
- vertical bar showing in WebUI sidebar menu using FireFox
|
||||
|
||||
### Changed
|
||||
|
||||
- Heartbeat MQTT payload is now in JSON
|
||||
- platformio.ini targets. Use `debug` for custom builds.
|
||||
|
||||
## [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).
|
||||
- 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
|
||||
|
||||
### Added
|
||||
|
||||
- Handling of Mixing Module MM100 Status Messages (thanks @kstaniek)
|
||||
- Retrieve/Set thermostat mode for Junkers FW100/120 thermostats (thanks @Neonox31)
|
||||
- Added sending of all Mixer Module data via MQTT (thanks @peclik)
|
||||
- Improved handling of MQTT publish and subscribe errors
|
||||
- Added MQTT QOS (`mqtt_qos`, default 0), Keep Alive (`mqtt_keepalive`, default 60 seconds) and Retain (`mqtt_retain`, default off) as parameters to both telnet and WebUI
|
||||
|
||||
### Fixed
|
||||
|
||||
- `publish` command also sends Dallas external temperature sensor values
|
||||
- `log_events` setting wasn't persisted in config file
|
||||
|
||||
### Changed
|
||||
|
||||
- External dallas sensor values sent in MQTT payload as float values and not strings
|
||||
- All MQTT topics for the Thermostat have the Heating Circuit appended (e.g. `thermostat_data1`). This includes the commands.
|
||||
- Shower timer and shower alert and not MQTT published at boot up
|
||||
- Heating Active logic change to use Selected Flow Temp of min 30 instead of 70 (https://github.com/proddy/EMS-ESP/issues/193)
|
||||
- Cleaned up Telnet messages during bootup to only show key information.
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed telnet command `shower timer` and `shower alert` to toggle the switches
|
||||
|
||||
## [1.9.1] 2019-10-05
|
||||
|
||||
### Added
|
||||
|
||||
- Support for multiple Heating Circuits - https://github.com/proddy/EMS-ESP/issues/162
|
||||
- new `mqttlog` command also shows which MQTT topics it is subscribed too
|
||||
- Optimized event log loading in web and added integrity checks on all config and log files during boot
|
||||
- `autodetect quick` for detecting known devices from our database list
|
||||
- `log_events` option, now optional to save the log events to SPIFFS
|
||||
|
||||
### Fixed
|
||||
|
||||
- fixed zero values (0.0) for setpoint temperature with the RC35 thermostat when in Auto mode - https://github.com/proddy/EMS-ESP/issues/180
|
||||
- added check for corrupted event log, which could happen due to SPIFFS writing while UART is active
|
||||
- made Junkers work again (broke in 1.9.0)
|
||||
|
||||
### Changed
|
||||
|
||||
- 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
|
||||
- Slowed down firmware upload via the Web to prevent users rebooting too early
|
||||
- Change way WiFi is intialized to prevent dual AP and Client
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed `heating_circuit` config setting
|
||||
- Removed showing the JSON config files when Saving from the Web
|
||||
|
||||
## [1.9.0] 2019-09-01
|
||||
|
||||
### 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
|
||||
- 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
|
||||
- Renamed `heartbeat` to `mqtt_heartbeat` in config settings
|
||||
- Renamed MQTT topic "wwactivated" to "boiler_cmd_wwactivated"
|
||||
|
||||
### Fixed
|
||||
|
||||
- Handle Read and Write to EMS+ device logic changed, tested with RC3000
|
||||
|
||||
## [1.8.1] 2019-07-27
|
||||
|
||||
### Added
|
||||
|
||||
- Added back -DCRASH in Debug build target for capturing any ESP8266 stack dumps during crashes
|
||||
- Basic Web Interface, for checking stats and setting wifi credentials. See wiki 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).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Detecting unset values in the SPIFFS and setting default values
|
||||
- Bosch Easy Connect wrongly classified as a thermostat
|
||||
- Correctly handle telegrams who's size are exactly 32 bytes (e.g. 0x19 MonitorSlow)
|
||||
- Telnet also available when in AP mode
|
||||
- Handling of thermostat temperatures that were single bytes and couldn't exceed 25.5 (0xFF) degrees!
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved handling of Solar Modules (thanks @Vuego123)
|
||||
- `publish_wait` renamed to `publish_time`, a value of 0 means disabling all MQTT sending
|
||||
- How signed shorts are handled such as the current and setpoint temps on RC300s
|
||||
- Stopped automatic refresh of web page, which causes crashes/memory loss after a short time
|
||||
- Support HA 0.96 climate component changes
|
||||
- -DDEFAULT_NO_SERIAL changed to -DFORCE_SERIAL
|
||||
- some code cleanups, removing NULLS and moving some things fron heap to stack to prevent memory fragmentation
|
||||
|
||||
## [1.8.0] 2019-06-15
|
||||
|
||||
### Added
|
||||
|
||||
- HeatPump support (e.g. the Nefit Enviline)
|
||||
- new device: Buderus MM50 Mixer
|
||||
- new devices: Junkers FW100 and ISM1 (thanks Vuego123)
|
||||
- Improved Tx logic to support EMS, EMS+ and Heatronic 3 (thanks kwertie01, susisstrolch, philrich)
|
||||
- MQTT heartbeat
|
||||
|
||||
### Fixed
|
||||
|
||||
- runtime exceptions with latest 2.5.1 arduino core
|
||||
|
||||
## [1.7.0] 2019-05-11
|
||||
|
||||
### Added
|
||||
|
||||
- EMS+ core support (thanks too @gl3nni3 for doing the first research)
|
||||
- MQTT 'restart' topic to reboot ESP (thanks @balk77)
|
||||
- Support for multiple thermostat heating circuits like the HC1/HC2 on a RC35, also via MQTT (thanks @lobocobra)
|
||||
- `boiler flowtemp` command to set the flow temperature [(issue 59)](https://github.com/proddy/EMS-ESP/issues/59)
|
||||
- added a test harness to try out response to various telegrams (test command)
|
||||
- `tx_delay` setting for circuits where we needed to slow down Tx transmission
|
||||
- new boiler: Nefit proline hrc 24 cw4 thermostat and Nefit Enviline heatpump
|
||||
- new boiler: Buderus Logamax plus
|
||||
- new thermostat: Buderus RC300 and RC310 thermostats, read-only [(issue 37)](https://github.com/proddy/EMS-ESP/issues/37)
|
||||
- new thermostat: Junkers FR10, read-only [(issue 98)](https://github.com/proddy/EMS-ESP/issues/98)
|
||||
- new devices: Buderus Web Gateway KM200, Buderus Solar Module SM100
|
||||
|
||||
### Changed
|
||||
|
||||
- `types` renamed to `devices` to also show all detected devices
|
||||
- renamed `silent_mode` to `listen_mode`
|
||||
- increased Tx queue to 100
|
||||
|
||||
## [1.6.0] 2019-03-24
|
||||
|
||||
### Added
|
||||
|
||||
- `system` command to show ESP8266 stats
|
||||
- `crash` command to see stack of last system crash, with .py files to track stack dump (compile with `-DCRASH`)
|
||||
- publish dallas external temp sensors to MQTT (thanks @JewelZB)
|
||||
- shower timer and shower alert options available via set commands
|
||||
- added support for warm water modes Hot, Comfort and Intelligent [(issue 67)](https://github.com/proddy/EMS-ESP/issues/67)
|
||||
- added `set publish_time` to set how often to force a publish of MQTT
|
||||
- support for SM10 Solar Module including MQTT [(issue 77)](https://github.com/proddy/EMS-ESP/issues/77)
|
||||
- `refresh` command to force a fetch of all known data from the connected EMS devices
|
||||
|
||||
### Fixed
|
||||
|
||||
- incorrect rendering of null temperature values (the -3200 degrees issue)
|
||||
- OTA is more stable
|
||||
- Added a hack to overcome WiFi power issues in arduino core 2.5.0 libraries causing constant wifi re-connects
|
||||
- Performance issues with telnet output
|
||||
|
||||
### Changed
|
||||
|
||||
- included various fixes and suggestions from @nomis
|
||||
- upgraded MyESP library with many optimizations
|
||||
- `test_mode` renamed to `silent_mode`
|
||||
- `set wifi` replaced with `set wifi_ssid` and `set wifi_password` to allow values with spaces
|
||||
- EMS values are stored in the raw format and only converted to strings when displayed or published, removing the need for parsing floats
|
||||
- All floating point temperatures are to one decimal place [(issue 79)](https://github.com/proddy/EMS-ESP/issues/79)
|
||||
|
||||
## [1.5.6] 2019-03-09
|
||||
|
||||
### Added
|
||||
|
||||
- test_mode option
|
||||
|
||||
### Changed
|
||||
|
||||
- upgraded MyESP library
|
||||
- minor changes
|
||||
|
||||
## [1.5.5] 2019-03-07
|
||||
|
||||
### Fixed
|
||||
- Support the latest ArduinoJson v6 and espressif8266 2.0.4 libraries (in PlatformIO do a `pio lib update` and `pio update`)
|
||||
|
||||
### Changed
|
||||
|
||||
- MQTT keep alive to 2 minutes (60 seconds was just too short for slower networks)
|
||||
- Improved MQTT startup time
|
||||
- Setting wifi or mqtt settings are immediate, no need to restart the ESP
|
||||
- Text changes in the help
|
||||
|
||||
### Added
|
||||
- Show if MQTT is connected
|
||||
- Show version of MyESP (the custom MQTT, Wifi, OTA, MDNS, Telnet library)
|
||||
- EMS-OT OpenTherm connector
|
||||
|
||||
## [1.5.4] 2019-03-03
|
||||
|
||||
### Changed
|
||||
|
||||
- MQTT keep alive changed from 5 minutes to 1 minute
|
||||
|
||||
### Added
|
||||
- Callback for OTA. This is used to disable EMS bus during a firmware OTA update, which caused problems with the latest ESP89266 core libraries
|
||||
- Added rough estimate of WiFi signal strength to info page
|
||||
- Added the build time & date to the info page (optional in platformio.ini)
|
||||
|
||||
## [1.5.3] 2019-02-22
|
||||
|
||||
### Changed
|
||||
|
||||
- Support for latest esp8266 arduino core version [2.5.0](https://github.com/esp8266/Arduino/releases/tag/2.5.0) and platform espressif8266 version 2.0.0
|
||||
- Added board type to the info screen
|
||||
|
||||
### Added
|
||||
|
||||
- Improved MQTT LWT (Last Will Testament). Uses payload called 'online' and 'offline'. See https://github.com/proddy/EMS-ESP/issues/57
|
||||
- Added ESP32 support to MyESP library
|
||||
- Added Bosch Easy thermostat, Buderus Logamax U122
|
||||
- Support for changing boiler wwtemp via MQTT (merge #58 from egrekov). thanks!
|
||||
|
||||
### Removed
|
||||
|
||||
- Custom MDNS support. Now handled much better in the new esp core under OTA
|
||||
|
||||
## [1.5.2] 2019-02-04
|
||||
|
||||
### Changed
|
||||
|
||||
- Change wifi settings using the `set wifi <ssid> <password>` command
|
||||
|
||||
### Added
|
||||
|
||||
- Added incoming MQTT "TOPIC_BOILER_WWACTIVATED" to set the warm water on/off. Payload is 1 or 0. See [issue](https://github.com/proddy/EMS-ESP/issues/46#issuecomment-460375689).
|
||||
- Added the list of all MQTT topics to the README file
|
||||
|
||||
## [1.5.1] 2019-02-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- issue with Serial monitoring conflicting with UART when both running
|
||||
- Fixed typo with -D settings in the example platformio.ini
|
||||
|
||||
### Changed
|
||||
|
||||
- `thermostat temp` now except floats (e.g. 20.5). Some thermostats may round up or down if they use 0.5 intervals.
|
||||
|
||||
## [1.5.0] 2019-02-03
|
||||
|
||||
### Added
|
||||
|
||||
- Support for RC10 thermostat
|
||||
- New command `set serial`
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved Tx logic. Retries are more efficient and startup is faster and less error prone.
|
||||
- "# Rx telegrams" and "# Tx telegrams" show number of successful Reads and Writes initiated by the user or automatically by the code. This makes it easy to see if the Tx is working.
|
||||
- Some refactoring in preparation for the EMS+ support coming soon
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed the `poll` and `tx` commands
|
||||
- `DEBUG_SUPPORT`. Now controlled with the 'set serial' command
|
||||
- removed MQTT and WIFI settings from my_config.h. These have to be set either within the application (using set) or hardcoded in platformio.ini You can now check in `my_config.h` without everyone seeing your passwords!
|
||||
- TxCapable removed from `info`
|
||||
|
||||
## [1.4.1] 2019-01-29
|
||||
|
||||
### Added
|
||||
|
||||
- The led pin, dallas pin and both thermostat and boiler type IDs can be set with the application, and stored.
|
||||
|
||||
### Changed
|
||||
|
||||
- some minor improvements to autodetect
|
||||
|
||||
## [1.4.0] 2019-01-27
|
||||
|
||||
### Changed
|
||||
|
||||
- last will MQTT topic prefixed with a header like the rest of the topics
|
||||
- All double and float numbers rendered to 2 decimal places (precision = 2)
|
||||
- Default logging set to None when starting a telnet session
|
||||
|
||||
### Added
|
||||
|
||||
- Added support for external Dallas sensors (DS1822, DS18S20, DS18B20, DS1825). See readme
|
||||
- Added UBAParametersMessage type to fetch boiler modulation min & max values
|
||||
- Report shows system load average
|
||||
|
||||
## [1.3.2] 2019-01-23
|
||||
|
||||
### Fixed
|
||||
|
||||
- Handle thermostats that don't have builtin temperature sensors when showing current temperature (https://github.com/proddy/EMS-ESP/issues/18#issuecomment-451012963)
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved way to identify if the EMS bus is connected
|
||||
- Improved 'types' command to show more details
|
||||
- Improved auto detect of thermostat types
|
||||
|
||||
### Added
|
||||
|
||||
- Some more devices like the Nefit Topline & RC310 thermostat recognition
|
||||
- Added a check to see Tx is possible. See 'Tx Capable' under the 'info' screen
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed `MY_BOILER_MODELID` from `my_config.h`. It's always hardcoded.
|
||||
|
||||
## [1.3.1] 2019-01-12
|
||||
|
||||
### Fixed
|
||||
|
||||
- telnet commands with set are no longer forced to lower case
|
||||
|
||||
### Changed
|
||||
|
||||
- Custom settings (e.g set led) moved outside MyESP
|
||||
- Moved all MQTT to my_config.h making it independent from Home Assistant
|
||||
|
||||
### Added
|
||||
|
||||
- MQTT keep alive, last will testament and other settings all configurable in my_config.h
|
||||
- RC35: MQTT day/night/auto mode; sets setpoint temperature in type 0x3D depends on current night/day Mode (@SpaceTeddy) [#33](https://github.com/proddy/EMS-ESP/pull/33)
|
||||
|
||||
## [1.3.0] 2019-01-09
|
||||
|
||||
### Changed
|
||||
|
||||
- Renamed project from EMS-ESP-Boiler to EMS-ESP since it's kinda EMS generic now
|
||||
- Support for RC20RF and RFM20 (https://github.com/proddy/EMS-ESP/issues/18)
|
||||
- Moved all EMS device information into a separate file `ems_devices.h` so no longer need to touch `ems.h`
|
||||
- Telnet commands can be strings now and output is suspended when typing
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed SHOWER_TEST
|
||||
- Removed WIFI and MQTT credentials from the platformio.ini file
|
||||
|
||||
### Added
|
||||
|
||||
- Settings are saved and loaded from the ESP8266's file system (SPIFFS). Can be set using the 'set' command
|
||||
- Improved support when in Access Point mode (192.168.4.1)
|
||||
- pre-built firmwares are back
|
||||
|
||||
## [1.2.4] 2019-01-04
|
||||
|
||||
### Changed
|
||||
|
||||
- Scanning known EMS Devices now ignores duplicates (https://github.com/proddy/EMS-ESP/pull/30)
|
||||
- ServiceCode stored as a two byte char
|
||||
- Support for RC20RF and RFM20 (https://github.com/proddy/EMS-ESP/issues/18)
|
||||
|
||||
## [1.2.3] 2019-01-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- Can now hardcode Boiler and Thermostat types in my_config.h to bypass auto-detection
|
||||
- Fixed MQTT subscribing to Heating and Hot Water active topics
|
||||
- Fixed for listening to incoming MQTT topics (https://github.com/proddy/EMS-ESP/issues/27)
|
||||
- Fixed handling of current temperature on an RC35-type thermostat that doesn't have a sensor (https://github.com/proddy/EMS-ESP/issues/18)
|
||||
|
||||
## [1.2.2] 2019-01-02
|
||||
|
||||
### Fixed
|
||||
|
||||
- Issues in 1.2.1 (see https://github.com/proddy/EMS-ESP/issues/25)
|
||||
- Logic for determining if there is activity on the EMS bus and using the onboard LEDs properly
|
||||
|
||||
## [1.2.1] 2019-01-02
|
||||
|
||||
### Fixed
|
||||
|
||||
- Only process broadcast messages if the offset (byte 4) is 0. (https://github.com/proddy/EMS-ESP/issues/23)
|
||||
- Improved checking for duplicate sent Tx telegrams by comparing CRCs
|
||||
- Removed distiquishing between noise on the line and corrupt telegrams (https://github.com/proddy/EMS-ESP/issues/24)
|
||||
|
||||
## [1.2.0] 2019-01-01
|
||||
|
||||
### Fixed
|
||||
|
||||
- Incorrect indenting in `climate.yaml` (thanks @mrfixit1)
|
||||
- Improved support for slower WiFi connections
|
||||
- Fixed issue with OTA not always giving back a completion response to platformio
|
||||
- Fixed issue with repeating reads after a raw mode send
|
||||
- Fixed handling of long integers (thanks @SpaceTeddy)
|
||||
|
||||
### Added
|
||||
|
||||
- added 'dout' flashmode to platformio.ini so OTA works now when uploading to a Wemos D1 Pro's or any other board with larger flash's
|
||||
- added un tested supporting RC35 type of thermostats
|
||||
- Try and discover and set Boiler and Thermostat types automatically
|
||||
- Fetch UBATotalUptimeMessage from Boiler to get total working minutes
|
||||
- Added check to see if bus is connected. Shown in stats page
|
||||
- If no Wifi connection can be made, start up as a WiFi Access Point (AP)
|
||||
- Report out service codes and water-flow [pull-request](https://github.com/proddy/EMS-ESP/pull/20/files). Thanks @Bonusbartus
|
||||
|
||||
### Changed
|
||||
|
||||
- Build option is called `DEBUG_SUPPORT` (was `USE_SERIAL`)
|
||||
- Replaced old **ESPHelper** with my own **MyESP** library to handle Wifi, MQTT, MDNS and Telnet handlers. Supports asynchronous TCP and has smaller memory footprint. And moved to libs directory.
|
||||
- Simplified LED error checking. If enabled (by default), solid means connected and flashing means error. Uses either an external pull-up or the onboard ESP8266 LED.
|
||||
- Improved Telnet debugging which uses TelnetSpy to keep a buffer of previous output
|
||||
- Optimized memory usage & heap conflicts, removing nasty things like strcpy, sprintf where possible
|
||||
- Improved checking for tap water on/off (thanks @Bonusbartus)
|
||||
|
||||
### Removed
|
||||
|
||||
- Time and TimeLib's. Not used in code.
|
||||
- Removed build option `MQTT_MAX_PACKAGE_SIZE` as not using the PubSubClient library any more
|
||||
- Removed all of Espurna's pre-built firmwares and instructions to build. Keeping it simple.
|
||||
|
||||
## [1.1.1] 2018-12-23
|
||||
|
||||
### Removed
|
||||
|
||||
- Espurna build notes and ready made firmware
|
||||
|
||||
## [1.1.0] 2018-12-22
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed handling of negative floating point values (like outdoor temp)
|
||||
- Fixed handling of auto & manual mode on an RC30
|
||||
- [Fixed condition where all telegram types were processed, instead of only broadcasts or our own reads](https://github.com/proddy/EMS-ESP/issues/15)
|
||||
|
||||
### Added
|
||||
|
||||
- Created this CHANGELOG.md file!
|
||||
- [Added support for the Nefit Easy thermostat, reading of temperature values only](https://github.com/proddy/EMS-ESP/issues/9) - note *read only* (big thanks @**kroon040** for lending me an Easy device)
|
||||
- [Added support for RC35/Moduline 400](https://github.com/proddy/EMS-ESP/issues/14) - *read only*
|
||||
- [New raw logging mode for logging](https://github.com/proddy/EMS-ESP/issues/11)
|
||||
- [New 'r'command to send raw data to EMS](https://github.com/proddy/EMS-ESP/issues/11)
|
||||
- [Added MQTT messages for hot water on and heating on](https://github.com/proddy/EMS-ESP/issues/10)
|
||||
- Implemented FIFO circular buffer queue for up to 20 Tx messages (Q command to show queue)
|
||||
- Toggle Tx transmission via telnet (use 'X' command)
|
||||
- Show thermostat type in help stats (use 's' command)
|
||||
- Show version is help stats (use '?' command)
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved overall formatting of logging
|
||||
- Include app name and version in telnet help
|
||||
- Improved method to switch off hot tap water in Shower Alert
|
||||
- Telnet P and M commands have changed
|
||||
- Enabling Logging in telnet is now the 'l' command
|
||||
- Logging is set back to None when telnet session closes
|
||||
- Improved fetching of initial boiler values to post to MQTT at startup
|
||||
- Improved handling and retrying of write/Tx commands
|
||||
|
||||
### Removed
|
||||
|
||||
- Hid access from telnet to the Experimental custom function command 'x'
|
||||
- Tx and Rx stats have gone from the stats page, as they were pretty meaningless
|
||||
- Removed NO_TX define in platformio and replaced with system parameter 'command X'
|
||||
- Removed -DDEBUG option in build
|
||||
- Removed wwtemp MQTT messages to set the boiler temp. You'll never miss it.
|
||||
- Removed LEDs for Tx, Rx and Err. Too many flashing lights and it drains the current.
|
||||
- Removed capturing of last Rx and Tx times
|
||||
- Support for older RC20 thermostats
|
||||
|
||||
### Known Issues
|
||||
|
||||
- There's a nasty memory leek when in telnet's verbose mode with sending which causes the EMS to reset when running for a while.
|
||||
|
||||
## [1.0.1] 2018-09-24
|
||||
|
||||
- Initial stable version
|
||||
|
||||
## [0.1.0] 2018-05-14
|
||||
|
||||
- Initial development version
|
||||
165
LICENSE
165
LICENSE
@@ -1,165 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
100
README.md
100
README.md
@@ -1,42 +1,74 @@
|
||||

|
||||
# EMS-ESP version 2.0 (alpha)
|
||||
|
||||
[](https://github.com/proddy/EMS-ESP/blob/master/CHANGELOG.md)
|
||||
[](https://github.com/proddy/EMS-ESP/commits/master)
|
||||
<br />
|
||||
[](LICENSE)
|
||||
[](https://travis-ci.com/proddy/EMS-ESP)
|
||||
[](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)
|
||||
[](https://github.com/proddy/EMS-ESP/releases)
|
||||
<br />
|
||||
[](https://gitter.im/EMS-ESP/community)
|
||||
<br>
|
||||
|
||||
EMS-ESP is a open-source system built for the Espressif ESP8266 microcontroller to communicate with **EMS** (Energy Management System) based boilers, thermostats and other modules from manufacturers like Bosch, Buderus, Nefit, Junkers and Sieger.
|
||||
|
||||
## Features
|
||||
|
||||
* Supporting more than [50 EMS devices](https://emsesp.github.io/docs/#/Supported-EMS-Devices) (EMS 1, EMS 2.0/Plus and Heatronics 3).
|
||||
* A web interface for easy configuration and real-time monitoring of the EMS bus.
|
||||
* Telnet for advanced configuration and verbose traffic logging.
|
||||
* Configurable MQTT, with templates for Home Assistant and Domoticz.
|
||||
* Includes an simple schematic for a test breadboard interface board.
|
||||
* Native compatibility with bbqkees' [EMS Gateway](https://bbqkees-electronics.nl/) interface board.
|
||||
|
||||
Please reference the [Wiki](https://emsesp.github.io/docs) for further details and instructions on how to build and configure the firmware.
|
||||
*Warning: this is a snapshot the EMS-ESP2 development in still in early stages of development and not for production!*
|
||||
|
||||
---
|
||||
|
||||
## Say Thanks
|
||||
If you like EMS-ESP buy me a :coffee: via [PayPal](https://www.paypal.me/prderbyshire/2).
|
||||
## Major changes since version 1.9.x
|
||||
|
||||
---
|
||||
### **Design & Coding principles**
|
||||
|
||||
|  |  |
|
||||
| - | - |
|
||||

|
||||
- The code can be built and run without an ESP microcontroller, which helps with testing and simulating handling of telegrams.
|
||||
- I used C++11 containers where I could (std::string, std::deque, std::list, std::multimap etc).
|
||||
- The core is based off the great libraries from @nomis and 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 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 extend with new telegrams types and features.
|
||||
- Built to work with both EMS8266 and ESP32.
|
||||
|
||||
|  |  |
|
||||
| - | - |
|
||||
### **Features**
|
||||
|
||||
|  |  |  |
|
||||
| - | - | - |
|
||||
- A web interface built using React and TypeScript to be secure and cross-browser compatible. Each restful endpoint is protected and issues a JWT which is then sent using Bearer Authentication. Implements a Web captive portal. On first installs EMS-ESP starts an Access Point where system settings can be configured. Note, this is still in a separate repo and pending a merge into this project.
|
||||
|
||||
- A new console. Like 1.9.x it works with both Serial and Telnet but a lot more intuitive behaving like a Linux shell and secure. Multiple telnet sessions are supported now but watch out for slow connections and low memory. A password is need to change any settings. You can use TAB to auto-complete commands. Some key commands:
|
||||
* `help` lists the commands and keywords
|
||||
* some commands take you into a new context, a bit like a sub-menu. e.g. `system`, `mqtt`, `thermostat`. Use `help` to show which commands this context has and `exit` to get back to the root.
|
||||
* To change a setting use the `set` command. Typing `set` shows the current settings.
|
||||
* `show` shows the data specific to the context you're in.
|
||||
* `su` to switch to Admin which enables more commands such as most of the `set` commands. The default password is "neo". When in Admin mode the command prompt switches from `$` to `#`.
|
||||
* `log` sets the logging. `log off` disables logging. Use `log trace` to see the telegram traffic and `log debug` for very verbose logging. To watch a specific telegram ID or device ID use `log trace [id]`.
|
||||
|
||||
- There is no "serial mode" anymore. 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 2 UARTs.
|
||||
|
||||
- LED behaves like in 1.9. A solid LED means good connection and EMS data is coming in. A slow pulse means either the WiFi or the EMS bus is not connected. A very fast pulse is when the system is booting up and configuring itself.
|
||||
|
||||
- on a new install you will want to enter `su` and then go to the `system` context. Use `set wifi ...` to set the network up. Then go to the `mqtt` context to set the mqtt up.
|
||||
|
||||
|
||||
----------
|
||||
|
||||
### **Fixes and Improvements to work on now**
|
||||
|
||||
```
|
||||
TODO figure out why sometimes telnet on ESP32 (and sometimes ESP8266) has slow response times.
|
||||
TODO Get the ESP32 UART code working.
|
||||
TODO console auto-complete with 'set' command in the system context is not showing all commands, only the hostname.
|
||||
|
||||
```
|
||||
|
||||
### **Features to add next**
|
||||
|
||||
```
|
||||
TODO finish porting over code for Solar, Mixing and Heat pump.
|
||||
TODO implement 0xE9 telegram type for EMS+ boilers. This was a request #382 (https://github.com/proddy/EMS-ESP/issues/382)
|
||||
```
|
||||
|
||||
### **To tidy up in code later**
|
||||
|
||||
```
|
||||
TODO replace vectors of class objects with shared pointers and use emplace_back since it instantiates during construction. It may have a performance gain.
|
||||
TODO decide if we really need to store the timestamp of each incoming Rx telegram.
|
||||
TODO make more use of comparison operators in the Telegram class e.g. the compare like "friend inline bool operator==(const Telegram & lhs, const Telegram & rhs)"
|
||||
TODO exit from serial should be prevented? Because you never can really exit, just close it.
|
||||
TODO add real unit tests using platformio's test bed (https://docs.platformio.org/en/latest/plus/pio-remote.html)
|
||||
TODO See if it's easier to use timers instead of millis() timers, using https://github.com/esp8266/Arduino/blob/master/libraries/esp8266/examples/BlinkPolledTimeout/BlinkPolledTimeout.ino
|
||||
```
|
||||
|
||||
### **These features to add**
|
||||
|
||||
```
|
||||
TODO merge in the web code
|
||||
TODO merge in NTP code
|
||||
TODO make ascii colors in the console optional?
|
||||
TODO decide what to do with gateways, switches and other bogus EMS devices
|
||||
TODO add MQTT subscribe topic to toggle on/off the shower alert and timer. If really needed.
|
||||
TODO decide if I want to port over the shower one-shot cold water logic. Don't think its used.
|
||||
```
|
||||
|
||||
21
lib/rtcvars/LICENSE
Normal file
21
lib/rtcvars/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 highno
|
||||
|
||||
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.
|
||||
193
lib/rtcvars/RTCVars.cpp
Normal file
193
lib/rtcvars/RTCVars.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
// https://github.com/highno/rtcvars
|
||||
|
||||
#if defined(ESP8266)
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "RTCVars.h"
|
||||
|
||||
#define RTC_BASE 28 // this is a known good offset for unused RTC memory
|
||||
#define RTC_STATE_HEADER_SIZE 6 // 3 bytes signature, 1 byte state_id, 2 byte
|
||||
#define RTC_MAX_SIZE (511 - RTC_BASE) // 512 - RTC_BASE - 1 for checksum
|
||||
|
||||
#define RTC_STATE_TYPE_NONE 0
|
||||
#define RTC_STATE_TYPE_INT 1
|
||||
#define RTC_STATE_TYPE_LONG 2
|
||||
#define RTC_STATE_TYPE_FLOAT 3
|
||||
#define RTC_STATE_TYPE_BYTE 4
|
||||
#define RTC_STATE_TYPE_CHAR 5
|
||||
#define RTC_STATE_TYPE_BOOL 6
|
||||
|
||||
RTCVars::RTCVars() {
|
||||
_state_size = RTC_STATE_HEADER_SIZE;
|
||||
_state_variables_counter = 0;
|
||||
_state_id = 0;
|
||||
_last_read_state_id = RTC_STATE_ID_INVALID;
|
||||
_last_read_status = RTC_OK;
|
||||
}
|
||||
|
||||
bool RTCVars::registerVar(char * v) {
|
||||
return _checkAndReserve((uintptr_t)v, RTC_STATE_TYPE_CHAR);
|
||||
}
|
||||
|
||||
bool RTCVars::registerVar(byte * v) {
|
||||
return _checkAndReserve((uintptr_t)v, RTC_STATE_TYPE_BYTE);
|
||||
}
|
||||
|
||||
bool RTCVars::registerVar(int * v) {
|
||||
return _checkAndReserve((uintptr_t)v, RTC_STATE_TYPE_INT);
|
||||
}
|
||||
|
||||
bool RTCVars::registerVar(long * v) {
|
||||
return _checkAndReserve((uintptr_t)v, RTC_STATE_TYPE_LONG);
|
||||
}
|
||||
|
||||
bool RTCVars::registerVar(float * v) {
|
||||
return _checkAndReserve((uintptr_t)v, RTC_STATE_TYPE_FLOAT);
|
||||
}
|
||||
|
||||
bool RTCVars::registerVar(bool * v) {
|
||||
return _checkAndReserve((uintptr_t)v, RTC_STATE_TYPE_BOOL);
|
||||
}
|
||||
|
||||
bool RTCVars::_checkAndReserve(uintptr_t v, byte type_of_var) {
|
||||
// check if there is enough room for this var
|
||||
if ((_state_variables_counter >= RTC_MAX_VARIABLES) || (_state_variable_size[type_of_var] + _state_size >= RTC_MAX_SIZE))
|
||||
return false;
|
||||
// keep the pointer to the var
|
||||
_state_variables_ptr[_state_variables_counter] = v;
|
||||
// keep the type of var so we copy the correct number of bytes
|
||||
_state_variables_type[_state_variables_counter] = type_of_var;
|
||||
// remove these bytes from the free mem counter
|
||||
_state_size += _state_variable_size[type_of_var];
|
||||
// up to the next one
|
||||
_state_variables_counter++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTCVars::saveToRTC() {
|
||||
unsigned char buf[_state_size + 1];
|
||||
int p = RTC_STATE_HEADER_SIZE;
|
||||
int s = 0;
|
||||
|
||||
// migic bytes signature
|
||||
buf[0] = 'M';
|
||||
buf[1] = 'G';
|
||||
buf[2] = 'C';
|
||||
buf[3] = _state_id;
|
||||
buf[4] = (unsigned char)((_state_size >> 8) & 0xff);
|
||||
buf[5] = (unsigned char)(_state_size & 0xff);
|
||||
|
||||
// copy the values from the local variables' memory places into buffer
|
||||
for (int i = 0; i < _state_variables_counter; i++) {
|
||||
s = _state_variable_size[_state_variables_type[i]];
|
||||
memcpy(&buf[p], reinterpret_cast<void *>(_state_variables_ptr[i]), s);
|
||||
p += s;
|
||||
}
|
||||
|
||||
buf[_state_size] = 0;
|
||||
for (int j = 0; j < _state_size; j++) {
|
||||
buf[_state_size] += buf[j]; // simple checksum
|
||||
}
|
||||
return ESP.rtcUserMemoryWrite(RTC_BASE, (uint32_t *)&buf, _state_size + 1);
|
||||
}
|
||||
|
||||
bool RTCVars::loadFromRTC() {
|
||||
if (!_checkValidRTCData())
|
||||
return false;
|
||||
_last_read_status = RTC_ERROR_READING_FAILED;
|
||||
unsigned char buf[_state_size + 1];
|
||||
if (!ESP.rtcUserMemoryRead(RTC_BASE, (uint32_t *)&buf, _state_size + 1))
|
||||
return false;
|
||||
|
||||
// check if state id is ok
|
||||
_last_read_status = RTC_ERROR_STATE_ID;
|
||||
if (_last_read_state_id != _state_id)
|
||||
return false;
|
||||
// finally check if state sizes are equal
|
||||
_last_read_status = RTC_ERROR_SIZE;
|
||||
int size_in_rtc = (int)(buf[4] * 256 + buf[5]);
|
||||
if (size_in_rtc != _state_size)
|
||||
return false;
|
||||
|
||||
// copy the values into the local variables' memory places
|
||||
_last_read_status = RTC_ERROR_OTHER;
|
||||
int p = RTC_STATE_HEADER_SIZE;
|
||||
int s = 0;
|
||||
for (int i = 0; i < _state_variables_counter; i++) {
|
||||
s = _state_variable_size[_state_variables_type[i]];
|
||||
memcpy(reinterpret_cast<void *>(_state_variables_ptr[i]), &buf[p], s);
|
||||
p += s;
|
||||
}
|
||||
_last_read_status = RTC_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTCVars::_checkValidRTCData() {
|
||||
// load header only from RTC
|
||||
_last_read_status = RTC_ERROR_READING_FAILED;
|
||||
unsigned char buf_head[RTC_STATE_HEADER_SIZE];
|
||||
if (!ESP.rtcUserMemoryRead(RTC_BASE, (uint32_t *)&buf_head, RTC_STATE_HEADER_SIZE))
|
||||
return false;
|
||||
|
||||
_last_read_status = RTC_ERROR_MAGIC_BYTES;
|
||||
// check if magic bytes are ok
|
||||
if (buf_head[0] != 'M')
|
||||
return false;
|
||||
if (buf_head[1] != 'G')
|
||||
return false;
|
||||
if (buf_head[2] != 'C')
|
||||
return false;
|
||||
|
||||
_last_read_status = RTC_ERROR_SIZE;
|
||||
// check for valid size
|
||||
int size_in_rtc = (int)(buf_head[4] * 256 + buf_head[5]);
|
||||
if (size_in_rtc > RTC_MAX_SIZE)
|
||||
return false;
|
||||
|
||||
_last_read_status = RTC_ERROR_READING_FAILED;
|
||||
// load the full state from RTC
|
||||
unsigned char buf[size_in_rtc + 1];
|
||||
if (!ESP.rtcUserMemoryRead(RTC_BASE, (uint32_t *)&buf, size_in_rtc + 1))
|
||||
return false;
|
||||
|
||||
_last_read_status = RTC_ERROR_CHECKSUM;
|
||||
// check for checksum
|
||||
unsigned char temp = 0;
|
||||
for (int j = 0; j < size_in_rtc; j++)
|
||||
temp += buf[j]; //checksum
|
||||
if (temp != buf[size_in_rtc])
|
||||
return false;
|
||||
|
||||
_last_read_status = RTC_OK;
|
||||
_last_read_state_id = buf[3];
|
||||
return true;
|
||||
}
|
||||
|
||||
int RTCVars::getFreeRTCMem() {
|
||||
return RTC_MAX_SIZE - _state_size;
|
||||
}
|
||||
|
||||
int RTCVars::getFreeRTCVars() {
|
||||
return RTC_MAX_VARIABLES - _state_variables_counter;
|
||||
}
|
||||
|
||||
byte RTCVars::getStateID() {
|
||||
return _state_id;
|
||||
}
|
||||
|
||||
byte RTCVars::getStateIDFromRTC() {
|
||||
if (!_checkValidRTCData())
|
||||
return RTC_STATE_ID_INVALID;
|
||||
return _last_read_state_id;
|
||||
}
|
||||
|
||||
void RTCVars::setStateID(byte new_state_id) {
|
||||
if (new_state_id != RTC_STATE_ID_INVALID)
|
||||
_state_id = new_state_id;
|
||||
}
|
||||
|
||||
byte RTCVars::getReadError() {
|
||||
return _last_read_status;
|
||||
}
|
||||
|
||||
#endif
|
||||
51
lib/rtcvars/RTCVars.h
Normal file
51
lib/rtcvars/RTCVars.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef RTCVARS_H
|
||||
#define RTCVARS_H
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifndef RTC_MAX_VARIABLES
|
||||
#define RTC_MAX_VARIABLES 32
|
||||
#endif
|
||||
|
||||
const static byte RTC_OK = 0;
|
||||
const static byte RTC_ERROR_MAGIC_BYTES = 1;
|
||||
const static byte RTC_ERROR_SIZE = 2;
|
||||
const static byte RTC_ERROR_READING_FAILED = 3;
|
||||
const static byte RTC_ERROR_CHECKSUM = 4;
|
||||
const static byte RTC_ERROR_STATE_ID = 5;
|
||||
const static byte RTC_ERROR_OTHER = 99;
|
||||
const static byte RTC_STATE_ID_INVALID = 255;
|
||||
|
||||
class RTCVars {
|
||||
public:
|
||||
RTCVars();
|
||||
bool registerVar(char * v);
|
||||
bool registerVar(byte * v);
|
||||
bool registerVar(bool * v);
|
||||
bool registerVar(int * v);
|
||||
bool registerVar(long * v);
|
||||
bool registerVar(float * v);
|
||||
void debugOutputRTCVars();
|
||||
bool saveToRTC();
|
||||
bool loadFromRTC();
|
||||
int getFreeRTCMem();
|
||||
int getFreeRTCVars();
|
||||
byte getStateID();
|
||||
byte getStateIDFromRTC();
|
||||
void setStateID(byte new_state_id);
|
||||
byte getReadError();
|
||||
|
||||
private:
|
||||
byte _state_id;
|
||||
byte _last_read_state_id;
|
||||
byte _last_read_status;
|
||||
int _state_size;
|
||||
int _state_variables_counter;
|
||||
uintptr_t _state_variables_ptr[RTC_MAX_VARIABLES];
|
||||
byte _state_variables_type[RTC_MAX_VARIABLES];
|
||||
const byte _state_variable_size[7] = {0, sizeof(int), sizeof(long), sizeof(float), sizeof(byte), sizeof(char), sizeof(bool)};
|
||||
bool _checkAndReserve(uintptr_t v, byte type_of_var);
|
||||
bool _checkValidRTCData();
|
||||
};
|
||||
|
||||
#endif
|
||||
674
lib/uuid-common/COPYING
Normal file
674
lib/uuid-common/COPYING
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
25
lib/uuid-common/README.rst
Normal file
25
lib/uuid-common/README.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
mcu-uuid-common |Build Status|
|
||||
==============================
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Microcontroller common utilities library
|
||||
|
||||
Purpose
|
||||
-------
|
||||
|
||||
The primary purpose of this library is to maintain a common 64-bit uptime in
|
||||
milliseconds with overflow handling, as long as the loop function is called
|
||||
regularly.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
`Read the documentation <https://mcu-uuid-common.readthedocs.io/>`_ generated
|
||||
from the docs_ directory.
|
||||
|
||||
.. _docs: docs/
|
||||
|
||||
.. |Build Status| image:: https://travis-ci.org/nomis/mcu-uuid-common.svg?branch=master
|
||||
:target: https://travis-ci.org/nomis/mcu-uuid-common
|
||||
31
lib/uuid-common/library.json
Normal file
31
lib/uuid-common/library.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "uuid-common",
|
||||
"description": "Common utilities library",
|
||||
"keywords": "utility, uptime",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Simon Arlott",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nomis/mcu-uuid-common.git"
|
||||
},
|
||||
"version": "1.1.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"homepage": "https://mcu-uuid-common.readthedocs.io/",
|
||||
"export": {
|
||||
"exclude": [
|
||||
".travis.yml",
|
||||
"test/*"
|
||||
]
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"build": {
|
||||
"flags": "-Wall -Wextra",
|
||||
"libLDFMode": "off"
|
||||
}
|
||||
}
|
||||
19
lib/uuid-common/src/common.cpp
Normal file
19
lib/uuid-common/src/common.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* uuid-common - Microcontroller common utilities
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/common.h>
|
||||
40
lib/uuid-common/src/get_uptime_ms.cpp
Normal file
40
lib/uuid-common/src/get_uptime_ms.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* uuid-common - Microcontroller common utilities
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/common.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
uint64_t get_uptime_ms() {
|
||||
static uint32_t high_millis = 0;
|
||||
static uint32_t low_millis = 0;
|
||||
|
||||
uint32_t now_millis = ::millis();
|
||||
|
||||
if (now_millis < low_millis) {
|
||||
high_millis++;
|
||||
}
|
||||
|
||||
low_millis = now_millis;
|
||||
|
||||
return ((uint64_t)high_millis << 32) | low_millis;
|
||||
}
|
||||
|
||||
} // namespace uuid
|
||||
27
lib/uuid-common/src/loop.cpp
Normal file
27
lib/uuid-common/src/loop.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* uuid-common - Microcontroller common utilities
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/common.h>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
void loop() {
|
||||
get_uptime_ms();
|
||||
}
|
||||
|
||||
} // namespace uuid
|
||||
62
lib/uuid-common/src/printable_to_string.cpp
Normal file
62
lib/uuid-common/src/printable_to_string.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* uuid-common - Microcontroller common utilities
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/common.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
class PrintableString : public ::Print {
|
||||
public:
|
||||
explicit PrintableString(std::string & output)
|
||||
: output_(output) {
|
||||
}
|
||||
~PrintableString() = default;
|
||||
|
||||
size_t write(uint8_t data) final override {
|
||||
output_.append(1, reinterpret_cast<unsigned char>(data));
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t write(const uint8_t * buffer, size_t size) final override {
|
||||
output_.append(reinterpret_cast<const char *>(buffer), size);
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string & output_;
|
||||
};
|
||||
|
||||
size_t print_to_string(const Printable & printable, std::string & output) {
|
||||
PrintableString pstr{output};
|
||||
|
||||
return printable.printTo(pstr);
|
||||
}
|
||||
|
||||
std::string printable_to_string(const Printable & printable) {
|
||||
std::string str;
|
||||
|
||||
print_to_string(printable, str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
} // namespace uuid
|
||||
35
lib/uuid-common/src/read_flash_string.cpp
Normal file
35
lib/uuid-common/src/read_flash_string.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* uuid-common - Microcontroller common utilities
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/common.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
std::string read_flash_string(const __FlashStringHelper * flash_str) {
|
||||
std::string str(::strlen_P(reinterpret_cast<PGM_P>(flash_str)), '\0');
|
||||
|
||||
::strncpy_P(&str[0], reinterpret_cast<PGM_P>(flash_str), str.capacity() + 1);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
} // namespace uuid
|
||||
91
lib/uuid-common/src/uuid/common.h
Normal file
91
lib/uuid-common/src/uuid/common.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* uuid-common - Microcontroller common utilities
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UUID_COMMON_H_
|
||||
#define UUID_COMMON_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Common utilities.
|
||||
*
|
||||
* - <a href="https://github.com/nomis/mcu-uuid-common/">Git Repository</a>
|
||||
* - <a href="https://mcu-uuid-common.readthedocs.io/">Documentation</a>
|
||||
*/
|
||||
namespace uuid {
|
||||
|
||||
/**
|
||||
* Read a string from flash and convert it to a std::string.
|
||||
*
|
||||
* The flash string must be stored with appropriate alignment for
|
||||
* reading it on the platform.
|
||||
*
|
||||
* @param[in] flash_str Pointer to string stored in flash.
|
||||
* @return A string copy of the flash string.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
std::string read_flash_string(const __FlashStringHelper * flash_str);
|
||||
|
||||
/**
|
||||
* Append to a std::string by printing a Printable object.
|
||||
*
|
||||
* @param[in] printable Printable object.
|
||||
* @param[in,out] output String to append to.
|
||||
* @return The number of bytes that were written.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
size_t print_to_string(const Printable & printable, std::string & output);
|
||||
|
||||
/**
|
||||
* Create a std::string from a Printable object.
|
||||
*
|
||||
* @param[in] printable Printable object.
|
||||
* @return A string containing the printed output.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
std::string printable_to_string(const Printable & printable);
|
||||
|
||||
/**
|
||||
* Type definition for a std::vector of flash strings.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
using flash_string_vector = std::vector<const __FlashStringHelper *>;
|
||||
|
||||
/**
|
||||
* Loop function that must be called regularly to detect a 32-bit
|
||||
* uptime overflow.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void loop();
|
||||
|
||||
/**
|
||||
* Get the current uptime as a 64-bit milliseconds value.
|
||||
*
|
||||
* @return The current uptime in milliseconds.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
uint64_t get_uptime_ms();
|
||||
|
||||
} // namespace uuid
|
||||
|
||||
#endif
|
||||
674
lib/uuid-console/COPYING
Normal file
674
lib/uuid-console/COPYING
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
25
lib/uuid-console/README.rst
Normal file
25
lib/uuid-console/README.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
mcu-uuid-console |Build Status|
|
||||
===============================
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Microcontroller console shell
|
||||
|
||||
Purpose
|
||||
-------
|
||||
|
||||
Provides a framework for creating a console shell with commands. The
|
||||
container of commands (``uuid::console::Commands``) can be shared
|
||||
across multiple shell instances.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
`Read the documentation <https://mcu-uuid-console.readthedocs.io/>`_ generated
|
||||
from the docs_ directory.
|
||||
|
||||
.. _docs: docs/
|
||||
|
||||
.. |Build Status| image:: https://travis-ci.org/nomis/mcu-uuid-console.svg?branch=master
|
||||
:target: https://travis-ci.org/nomis/mcu-uuid-console
|
||||
35
lib/uuid-console/library.json
Normal file
35
lib/uuid-console/library.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "uuid-console",
|
||||
"description": "Console shell",
|
||||
"keywords": "console, shell, command line",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Simon Arlott",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nomis/mcu-uuid-console.git"
|
||||
},
|
||||
"version": "0.7.3",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"homepage": "https://mcu-uuid-console.readthedocs.io/",
|
||||
"export": {
|
||||
"exclude": [
|
||||
".travis.yml",
|
||||
"test/*"
|
||||
]
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"dependencies": {
|
||||
"uuid-common": "^1.0.0",
|
||||
"uuid-log": "^2.0.3"
|
||||
},
|
||||
"build": {
|
||||
"flags": "-Wall -Wextra",
|
||||
"libLDFMode": "off"
|
||||
}
|
||||
}
|
||||
166
lib/uuid-console/src/command_line.cpp
Normal file
166
lib/uuid-console/src/command_line.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* uuid-console - Microcontroller console shell
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/console.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace console {
|
||||
|
||||
CommandLine::CommandLine(const std::string & line) {
|
||||
bool string_escape_double = false;
|
||||
bool string_escape_single = false;
|
||||
bool char_escape = false;
|
||||
bool quoted_argument = false;
|
||||
|
||||
if (!line.empty()) {
|
||||
parameters_.emplace_back(std::string{});
|
||||
}
|
||||
|
||||
for (char c : line) {
|
||||
switch (c) {
|
||||
case ' ':
|
||||
if (string_escape_double || string_escape_single) {
|
||||
if (char_escape) {
|
||||
parameters_.back().push_back('\\');
|
||||
char_escape = false;
|
||||
}
|
||||
parameters_.back().push_back(' ');
|
||||
} else if (char_escape) {
|
||||
parameters_.back().push_back(' ');
|
||||
char_escape = false;
|
||||
} else {
|
||||
// Begin a new argument if the previous
|
||||
// one is not empty or it was quoted
|
||||
if (quoted_argument || !parameters_.back().empty()) {
|
||||
parameters_.emplace_back(std::string{});
|
||||
}
|
||||
quoted_argument = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case '"':
|
||||
if (char_escape || string_escape_single) {
|
||||
parameters_.back().push_back('"');
|
||||
char_escape = false;
|
||||
} else {
|
||||
string_escape_double = !string_escape_double;
|
||||
quoted_argument = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
if (char_escape || string_escape_double) {
|
||||
parameters_.back().push_back('\'');
|
||||
char_escape = false;
|
||||
} else {
|
||||
string_escape_single = !string_escape_single;
|
||||
quoted_argument = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
if (char_escape) {
|
||||
parameters_.back().push_back('\\');
|
||||
char_escape = false;
|
||||
} else {
|
||||
char_escape = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (char_escape) {
|
||||
parameters_.back().push_back('\\');
|
||||
char_escape = false;
|
||||
}
|
||||
parameters_.back().push_back(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parameters_.empty() && parameters_.back().empty() && !quoted_argument) {
|
||||
parameters_.pop_back();
|
||||
if (!parameters_.empty()) {
|
||||
trailing_space = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CommandLine::CommandLine(std::initializer_list<const std::vector<std::string>> arguments) {
|
||||
for (auto & argument : arguments) {
|
||||
parameters_.insert(parameters_.end(), argument.begin(), argument.end());
|
||||
}
|
||||
}
|
||||
|
||||
std::string CommandLine::to_string(size_t reserve) const {
|
||||
std::string line;
|
||||
size_t escape = escape_parameters_;
|
||||
|
||||
line.reserve(reserve);
|
||||
|
||||
for (auto & item : parameters_) {
|
||||
if (!line.empty()) {
|
||||
line += ' ';
|
||||
}
|
||||
|
||||
if (item.empty()) {
|
||||
line += '\"';
|
||||
line += '\"';
|
||||
goto next;
|
||||
}
|
||||
|
||||
for (char c : item) {
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
if (escape > 0) {
|
||||
line += '\\';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
line += c;
|
||||
}
|
||||
|
||||
next:
|
||||
if (escape > 0) {
|
||||
escape--;
|
||||
}
|
||||
}
|
||||
|
||||
if (trailing_space && !line.empty()) {
|
||||
line += ' ';
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
void CommandLine::reset() {
|
||||
parameters_.clear();
|
||||
escape_all_parameters();
|
||||
trailing_space = false;
|
||||
}
|
||||
|
||||
} // namespace console
|
||||
|
||||
} // namespace uuid
|
||||
543
lib/uuid-console/src/commands.cpp
Normal file
543
lib/uuid-console/src/commands.cpp
Normal file
@@ -0,0 +1,543 @@
|
||||
/*
|
||||
* uuid-console - Microcontroller console shell
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a std::copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/console.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifndef __cpp_lib_make_unique
|
||||
namespace std {
|
||||
|
||||
template <typename _Tp, typename... _Args>
|
||||
inline unique_ptr<_Tp> make_unique(_Args &&... __args) {
|
||||
return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...));
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace console {
|
||||
|
||||
void Commands::add_command(const flash_string_vector & name, command_function function) {
|
||||
add_command(0, 0, name, flash_string_vector{}, function, nullptr);
|
||||
}
|
||||
|
||||
void Commands::add_command(const flash_string_vector & name, const flash_string_vector & arguments, command_function function) {
|
||||
add_command(0, 0, name, arguments, function, nullptr);
|
||||
}
|
||||
|
||||
void Commands::add_command(const flash_string_vector & name,
|
||||
const flash_string_vector & arguments,
|
||||
command_function function,
|
||||
argument_completion_function arg_function) {
|
||||
add_command(0, 0, name, arguments, function, arg_function);
|
||||
}
|
||||
|
||||
void Commands::add_command(unsigned int context, unsigned int flags, const flash_string_vector & name, command_function function) {
|
||||
add_command(context, flags, name, flash_string_vector{}, function, nullptr);
|
||||
}
|
||||
|
||||
void Commands::add_command(unsigned int context,
|
||||
unsigned int flags,
|
||||
const flash_string_vector & name,
|
||||
const flash_string_vector & arguments,
|
||||
command_function function) {
|
||||
add_command(context, flags, name, arguments, function, nullptr);
|
||||
}
|
||||
|
||||
void Commands::add_command(unsigned int context,
|
||||
unsigned int flags,
|
||||
const flash_string_vector & name,
|
||||
const flash_string_vector & arguments,
|
||||
command_function function,
|
||||
argument_completion_function arg_function) {
|
||||
commands_.emplace(std::piecewise_construct, std::forward_as_tuple(context), std::forward_as_tuple(flags, name, arguments, function, arg_function));
|
||||
}
|
||||
|
||||
// added by proddy
|
||||
void Commands::remove_context_commands(unsigned int context) {
|
||||
commands_.erase(context);
|
||||
/*
|
||||
|
||||
auto commands = commands_.equal_range(context);
|
||||
for (auto command_it = commands.first; command_it != commands.second; command_it++) {
|
||||
shell.printf("Got: ");
|
||||
for (auto flash_name : command_it->second.name_) {
|
||||
shell.printf("%s ", read_flash_string(flash_name).c_str());
|
||||
}
|
||||
shell.println();
|
||||
}
|
||||
|
||||
size_t nun = commands_.erase(context);
|
||||
shell.printfln("Erased %d commands", nun);
|
||||
*/
|
||||
}
|
||||
|
||||
Commands::Execution Commands::execute_command(Shell & shell, CommandLine && command_line) {
|
||||
auto commands = find_command(shell, command_line);
|
||||
auto longest = commands.exact.crbegin();
|
||||
Execution result;
|
||||
|
||||
result.error = nullptr;
|
||||
|
||||
if (commands.exact.empty()) {
|
||||
result.error = F("Command not found");
|
||||
} else if (commands.exact.count(longest->first) == 1) {
|
||||
auto & command = longest->second;
|
||||
std::vector<std::string> arguments;
|
||||
|
||||
for (auto it = std::next(command_line->cbegin(), command->name_.size()); it != command_line->cend(); it++) {
|
||||
arguments.push_back(std::move(*it));
|
||||
}
|
||||
command_line.reset();
|
||||
|
||||
if (commands.partial.upper_bound(longest->first) != commands.partial.end() && !arguments.empty()) {
|
||||
result.error = F("Command not found");
|
||||
} else if (arguments.size() < command->minimum_arguments()) {
|
||||
result.error = F("Not enough arguments for command");
|
||||
} else if (arguments.size() > command->maximum_arguments()) {
|
||||
result.error = F("Too many arguments for command");
|
||||
} else {
|
||||
command->function_(shell, arguments);
|
||||
}
|
||||
} else {
|
||||
result.error = F("Fatal error (multiple commands found)");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Commands::find_longest_common_prefix(const std::multimap<size_t, const Command *> & commands, std::vector<std::string> & longest_name) {
|
||||
size_t component_prefix = 0;
|
||||
size_t shortest_match = commands.begin()->first;
|
||||
|
||||
longest_name.reserve(shortest_match);
|
||||
|
||||
{
|
||||
// Check if any of the commands have a common prefix of components
|
||||
auto & first = commands.begin()->second->name_;
|
||||
bool all_match = true;
|
||||
|
||||
for (size_t length = 0; all_match && length < shortest_match; length++) {
|
||||
for (auto command_it = std::next(commands.begin()); command_it != commands.end(); command_it++) {
|
||||
if (read_flash_string(*std::next(first.begin(), length)) != read_flash_string(*std::next(command_it->second->name_.begin(), length))) {
|
||||
all_match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_match) {
|
||||
component_prefix = length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto name_it = first.begin();
|
||||
for (size_t i = 0; i < component_prefix; i++) {
|
||||
longest_name.push_back(std::move(read_flash_string(*name_it)));
|
||||
name_it++;
|
||||
}
|
||||
}
|
||||
|
||||
if (component_prefix < shortest_match) {
|
||||
// Check if the next component has a common substring
|
||||
auto first = *std::next(commands.begin()->second->name_.begin(), component_prefix);
|
||||
bool all_match = true;
|
||||
size_t chars_prefix = 0;
|
||||
|
||||
for (size_t length = 0; all_match; length++) {
|
||||
for (auto command_it = std::next(commands.begin()); command_it != commands.end(); command_it++) {
|
||||
// This relies on the null terminator character limiting the
|
||||
// length before it becomes longer than any of the strings
|
||||
if (pgm_read_byte(reinterpret_cast<PGM_P>(first) + length)
|
||||
!= pgm_read_byte(reinterpret_cast<PGM_P>(*std::next(command_it->second->name_.begin(), component_prefix)) + length)) {
|
||||
all_match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_match) {
|
||||
chars_prefix = length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (chars_prefix > 0) {
|
||||
longest_name.push_back(std::move(read_flash_string(first).substr(0, chars_prefix)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Commands::find_longest_common_prefix(const std::vector<std::string> & arguments) {
|
||||
auto & first = *arguments.begin();
|
||||
bool all_match = true;
|
||||
size_t chars_prefix = 0;
|
||||
|
||||
for (size_t length = 0; all_match; length++) {
|
||||
for (auto argument_it = std::next(arguments.begin()); argument_it != arguments.end(); argument_it++) {
|
||||
// This relies on the null terminator character limiting the
|
||||
// length before it becomes longer than any of the strings
|
||||
if (first[length] != (*argument_it)[length]) {
|
||||
all_match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_match) {
|
||||
chars_prefix = length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return arguments.begin()->substr(0, chars_prefix);
|
||||
}
|
||||
|
||||
Commands::Completion Commands::complete_command(Shell & shell, const CommandLine & command_line) {
|
||||
auto commands = find_command(shell, command_line);
|
||||
Completion result;
|
||||
|
||||
auto match = commands.partial.begin();
|
||||
size_t count;
|
||||
if (match != commands.partial.end()) {
|
||||
count = commands.partial.count(match->first);
|
||||
} else if (!commands.exact.empty()) {
|
||||
// Use prev() because both iterators must be forwards
|
||||
match = std::prev(commands.exact.end());
|
||||
count = commands.exact.count(match->first);
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<Command> temp_command;
|
||||
std::vector<std::string> temp_command_name;
|
||||
std::multimap<size_t, const Command *>::iterator temp_command_it;
|
||||
|
||||
if (commands.partial.size() > 1 && (commands.exact.empty() || command_line.total_size() > commands.exact.begin()->second->name_.size())) {
|
||||
// There are multiple partial matching commands, find the longest common prefix
|
||||
bool whole_components = find_longest_common_prefix(commands.partial, temp_command_name);
|
||||
|
||||
if (count == 1 && whole_components && temp_command_name.size() == match->first) {
|
||||
// If the longest common prefix is the same as the single shortest matching command
|
||||
// then there's no need for a temporary command, but add a trailing space because
|
||||
// there are longer commands that matched.
|
||||
temp_command_name.clear();
|
||||
result.replacement.trailing_space = true;
|
||||
}
|
||||
|
||||
if (!temp_command_name.empty() && command_line.total_size() <= temp_command_name.size()) {
|
||||
temp_command = std::make_unique<Command>(0, flash_string_vector{}, flash_string_vector{}, nullptr, nullptr);
|
||||
count = 1;
|
||||
match = commands.partial.end();
|
||||
result.replacement.trailing_space = whole_components;
|
||||
|
||||
for (auto & name : temp_command_name) {
|
||||
result.replacement->emplace_back(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 1 && !temp_command) {
|
||||
// Construct a replacement string for a single matching command
|
||||
auto & matching_command = match->second;
|
||||
|
||||
for (auto & name : matching_command->name_) {
|
||||
result.replacement->push_back(std::move(read_flash_string(name)));
|
||||
}
|
||||
|
||||
if (command_line.total_size() > result.replacement->size()
|
||||
&& command_line.total_size() <= matching_command->name_.size() + matching_command->maximum_arguments()) {
|
||||
// Try to auto-complete arguments
|
||||
std::vector<std::string> arguments{std::next(command_line->cbegin(), result.replacement->size()), command_line->cend()};
|
||||
|
||||
result.replacement->insert(result.replacement->end(), arguments.cbegin(), arguments.cend());
|
||||
result.replacement.trailing_space = command_line.trailing_space;
|
||||
|
||||
auto current_args_count = arguments.size();
|
||||
std::string last_argument;
|
||||
|
||||
if (!command_line.trailing_space) {
|
||||
// Remove the last argument so that it can be auto-completed
|
||||
last_argument = std::move(result.replacement->back());
|
||||
result.replacement->pop_back();
|
||||
if (!arguments.empty()) {
|
||||
arguments.pop_back();
|
||||
current_args_count--;
|
||||
}
|
||||
}
|
||||
|
||||
auto potential_arguments = matching_command->arg_function_ ? matching_command->arg_function_(shell, arguments) : std::vector<std::string>{};
|
||||
|
||||
// Remove arguments that can't match
|
||||
if (!command_line.trailing_space) {
|
||||
for (auto it = potential_arguments.begin(); it != potential_arguments.end();) {
|
||||
if (it->rfind(last_argument, 0) == std::string::npos) {
|
||||
it = potential_arguments.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-complete if there's something present in the last argument
|
||||
// or the only potential argument is an empty string.
|
||||
if (!command_line.trailing_space) {
|
||||
if (potential_arguments.size() == 1) {
|
||||
if (last_argument == *potential_arguments.begin()) {
|
||||
if (result.replacement->size() + 1 < matching_command->name_.size() + matching_command->maximum_arguments()) {
|
||||
// Add a space because this argument is complete and there are more arguments for this command
|
||||
result.replacement.trailing_space = true;
|
||||
}
|
||||
}
|
||||
|
||||
last_argument = *potential_arguments.begin();
|
||||
potential_arguments.clear();
|
||||
|
||||
// Remaining help should skip the replaced argument
|
||||
current_args_count++;
|
||||
} else if (potential_arguments.size() > 1) {
|
||||
last_argument = find_longest_common_prefix(potential_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
// Put the last argument back
|
||||
if (!command_line.trailing_space) {
|
||||
result.replacement->push_back(std::move(last_argument));
|
||||
}
|
||||
|
||||
CommandLine remaining_help;
|
||||
|
||||
if (!potential_arguments.empty()) {
|
||||
// Remaining help should skip the suggested argument
|
||||
current_args_count++;
|
||||
}
|
||||
|
||||
if (current_args_count < matching_command->maximum_arguments()) {
|
||||
remaining_help.escape_initial_parameters();
|
||||
|
||||
for (auto it = std::next(matching_command->arguments_.cbegin(), current_args_count); it != matching_command->arguments_.cend(); it++) {
|
||||
remaining_help->push_back(std::move(read_flash_string(*it)));
|
||||
}
|
||||
}
|
||||
|
||||
if (potential_arguments.empty()) {
|
||||
if (!remaining_help->empty()) {
|
||||
result.help.push_back(std::move(remaining_help));
|
||||
}
|
||||
} else {
|
||||
for (auto potential_argument : potential_arguments) {
|
||||
CommandLine help;
|
||||
|
||||
help->emplace_back(potential_argument);
|
||||
|
||||
if (!remaining_help->empty()) {
|
||||
help.escape_initial_parameters();
|
||||
help->insert(help->end(), remaining_help->begin(), remaining_help->end());
|
||||
}
|
||||
|
||||
result.help.push_back(std::move(help));
|
||||
}
|
||||
}
|
||||
} else if (result.replacement->size() < matching_command->name_.size() + matching_command->maximum_arguments()) {
|
||||
// Add a space because there are more arguments for this command
|
||||
result.replacement.trailing_space = true;
|
||||
}
|
||||
} else if (count > 1 || temp_command) {
|
||||
// Provide help for all of the potential commands
|
||||
for (auto command_it = commands.partial.begin(); command_it != commands.partial.end(); command_it++) {
|
||||
CommandLine help;
|
||||
|
||||
auto line_it = command_line->cbegin();
|
||||
auto flash_name_it = command_it->second->name_.cbegin();
|
||||
|
||||
if (temp_command) {
|
||||
// Skip parts of the command name/line when the longest common prefix was used
|
||||
size_t skip = temp_command_name.size();
|
||||
if (!result.replacement.trailing_space) {
|
||||
skip--;
|
||||
}
|
||||
|
||||
flash_name_it += skip;
|
||||
while (line_it != command_line->cend()) {
|
||||
line_it++;
|
||||
}
|
||||
}
|
||||
|
||||
for (; flash_name_it != command_it->second->name_.cend(); flash_name_it++) {
|
||||
std::string name = read_flash_string(*flash_name_it);
|
||||
|
||||
// Skip parts of the command name that match the command line
|
||||
if (line_it != command_line->cend()) {
|
||||
if (name == *line_it++) {
|
||||
continue;
|
||||
} else {
|
||||
line_it = command_line->cend();
|
||||
}
|
||||
}
|
||||
|
||||
help->emplace_back(name);
|
||||
}
|
||||
|
||||
help.escape_initial_parameters();
|
||||
|
||||
for (auto argument : command_it->second->arguments_) {
|
||||
// Skip parts of the command arguments that exist in the command line
|
||||
if (line_it != command_line->cend()) {
|
||||
line_it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
help->push_back(std::move(read_flash_string(argument)));
|
||||
}
|
||||
|
||||
result.help.push_back(std::move(help));
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 1 && !commands.exact.empty()) {
|
||||
// Try to add a space to exact matches
|
||||
auto longest = commands.exact.crbegin();
|
||||
|
||||
if (commands.exact.count(longest->first) == 1) {
|
||||
for (auto & name : longest->second->name_) {
|
||||
result.replacement->push_back(std::move(read_flash_string(name)));
|
||||
}
|
||||
|
||||
// Add a space because there are sub-commands for a command that has matched exactly
|
||||
result.replacement.trailing_space = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't try to shorten the command line or offer an identical replacement
|
||||
if (command_line.total_size() > result.replacement.total_size() || result.replacement == command_line) {
|
||||
result.replacement.reset();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Commands::Match Commands::find_command(Shell & shell, const CommandLine & command_line) {
|
||||
Match commands;
|
||||
auto context_commands = commands_.equal_range(shell.context());
|
||||
|
||||
for (auto it = context_commands.first; it != context_commands.second; it++) {
|
||||
auto & command = it->second;
|
||||
bool match = true;
|
||||
bool exact = true;
|
||||
|
||||
if (!shell.has_flags(command.flags_)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto name_it = command.name_.cbegin();
|
||||
auto line_it = command_line->cbegin();
|
||||
|
||||
for (; name_it != command.name_.cend() && line_it != command_line->cend(); name_it++, line_it++) {
|
||||
std::string name = read_flash_string(*name_it);
|
||||
size_t found = name.rfind(*line_it, 0);
|
||||
|
||||
if (found == std::string::npos) {
|
||||
match = false;
|
||||
break;
|
||||
} else if (line_it->length() != name.length()) {
|
||||
for (auto line_check_it = std::next(line_it); line_check_it != command_line->cend(); line_check_it++) {
|
||||
if (!line_check_it->empty()) {
|
||||
// If there's more in the command line then this can't match
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (command_line.trailing_space) {
|
||||
// If there's a trailing space in the command line then this can't be a partial match
|
||||
match = false;
|
||||
}
|
||||
|
||||
// Don't check the rest of the command if this is only a partial match
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (name_it != command.name_.cend()) {
|
||||
exact = false;
|
||||
}
|
||||
|
||||
if (match) {
|
||||
if (exact) {
|
||||
commands.exact.emplace(command.name_.size(), &command);
|
||||
} else {
|
||||
commands.partial.emplace(command.name_.size(), &command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
void Commands::for_each_available_command(Shell & shell, apply_function f) const {
|
||||
auto commands = commands_.equal_range(shell.context());
|
||||
|
||||
for (auto command_it = commands.first; command_it != commands.second; command_it++) {
|
||||
if (shell.has_flags(command_it->second.flags_)) {
|
||||
std::vector<std::string> name;
|
||||
std::vector<std::string> arguments;
|
||||
|
||||
name.reserve(command_it->second.name_.size());
|
||||
for (auto flash_name : command_it->second.name_) {
|
||||
name.push_back(std::move(read_flash_string(flash_name)));
|
||||
}
|
||||
|
||||
arguments.reserve(command_it->second.arguments_.size());
|
||||
for (auto flash_argument : command_it->second.arguments_) {
|
||||
arguments.push_back(std::move(read_flash_string(flash_argument)));
|
||||
}
|
||||
|
||||
f(name, arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Commands::Command::Command(unsigned int flags,
|
||||
const flash_string_vector name,
|
||||
const flash_string_vector arguments,
|
||||
command_function function,
|
||||
argument_completion_function arg_function)
|
||||
: flags_(flags)
|
||||
, name_(name)
|
||||
, arguments_(arguments)
|
||||
, function_(function)
|
||||
, arg_function_(arg_function) {
|
||||
}
|
||||
|
||||
Commands::Command::~Command() {
|
||||
}
|
||||
|
||||
size_t Commands::Command::minimum_arguments() const {
|
||||
return std::count_if(arguments_.cbegin(), arguments_.cend(), [](const __FlashStringHelper * argument) { return pgm_read_byte(argument) == '<'; });
|
||||
}
|
||||
|
||||
} // namespace console
|
||||
|
||||
} // namespace uuid
|
||||
19
lib/uuid-console/src/console.cpp
Normal file
19
lib/uuid-console/src/console.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* uuid-console - Microcontroller console shell
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/console.h>
|
||||
519
lib/uuid-console/src/shell.cpp
Normal file
519
lib/uuid-console/src/shell.cpp
Normal file
@@ -0,0 +1,519 @@
|
||||
/*
|
||||
* uuid-console - Microcontroller console shell
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/console.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <uuid/common.h>
|
||||
#include <uuid/log.h>
|
||||
|
||||
#ifndef __cpp_lib_make_unique
|
||||
namespace std {
|
||||
|
||||
template <typename _Tp, typename... _Args>
|
||||
inline unique_ptr<_Tp> make_unique(_Args &&... __args) {
|
||||
return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...));
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace console {
|
||||
|
||||
// cppcheck-suppress passedByValue
|
||||
Shell::Shell(std::shared_ptr<Commands> commands, unsigned int context, unsigned int flags)
|
||||
: commands_(std::move(commands))
|
||||
, flags_(flags) {
|
||||
enter_context(context);
|
||||
}
|
||||
|
||||
Shell::~Shell() {
|
||||
uuid::log::Logger::unregister_handler(this);
|
||||
}
|
||||
|
||||
void Shell::start() {
|
||||
// Added by proddy - default log level
|
||||
#ifdef EMSESP_DEBUG
|
||||
uuid::log::Logger::register_handler(this, uuid::log::Level::NOTICE); // was debug
|
||||
#else
|
||||
uuid::log::Logger::register_handler(this, uuid::log::Level::NOTICE);
|
||||
#endif
|
||||
|
||||
line_buffer_.reserve(maximum_command_line_length_);
|
||||
display_banner();
|
||||
display_prompt();
|
||||
shells_.insert(shared_from_this());
|
||||
idle_time_ = uuid::get_uptime_ms();
|
||||
started();
|
||||
};
|
||||
|
||||
void Shell::started() {
|
||||
}
|
||||
|
||||
bool Shell::running() const {
|
||||
return !stopped_;
|
||||
}
|
||||
|
||||
void Shell::stop() {
|
||||
if (mode_ == Mode::BLOCKING) {
|
||||
auto * blocking_data = reinterpret_cast<Shell::BlockingData *>(mode_data_.get());
|
||||
|
||||
blocking_data->stop_ = true;
|
||||
} else {
|
||||
if (running()) {
|
||||
stopped_ = true;
|
||||
stopped();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::stopped() {
|
||||
}
|
||||
|
||||
bool Shell::exit_context() {
|
||||
if (context_.size() > 1) {
|
||||
context_.pop_back();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::loop_one() {
|
||||
if (!running()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mode_) {
|
||||
case Mode::NORMAL:
|
||||
output_logs();
|
||||
loop_normal();
|
||||
break;
|
||||
|
||||
case Mode::PASSWORD:
|
||||
output_logs();
|
||||
loop_password();
|
||||
break;
|
||||
|
||||
case Mode::DELAY:
|
||||
output_logs();
|
||||
loop_delay();
|
||||
break;
|
||||
|
||||
case Mode::BLOCKING:
|
||||
loop_blocking();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::loop_normal() {
|
||||
const int input = read_one_char();
|
||||
|
||||
if (input < 0) {
|
||||
check_idle_timeout();
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned char c = input;
|
||||
|
||||
switch (c) {
|
||||
case '\x03':
|
||||
// Interrupt (^C)
|
||||
line_buffer_.clear();
|
||||
println();
|
||||
prompt_displayed_ = false;
|
||||
display_prompt();
|
||||
break;
|
||||
|
||||
case '\x04':
|
||||
// End of transmission (^D)
|
||||
if (line_buffer_.empty()) {
|
||||
end_of_transmission();
|
||||
}
|
||||
break;
|
||||
|
||||
case '\x08':
|
||||
case '\x7F':
|
||||
// Backspace (^H)
|
||||
// Delete (^?)
|
||||
if (!line_buffer_.empty()) {
|
||||
erase_characters(1);
|
||||
line_buffer_.pop_back();
|
||||
}
|
||||
break;
|
||||
|
||||
case '\x09':
|
||||
// Tab (^I)
|
||||
process_completion();
|
||||
break;
|
||||
|
||||
case '\x0A':
|
||||
// Line feed (^J)
|
||||
if (previous_ != '\x0D') {
|
||||
process_command();
|
||||
}
|
||||
break;
|
||||
|
||||
case '\x0C':
|
||||
// New page (^L)
|
||||
erase_current_line();
|
||||
prompt_displayed_ = false;
|
||||
display_prompt();
|
||||
break;
|
||||
|
||||
case '\x0D':
|
||||
// Carriage return (^M)
|
||||
process_command();
|
||||
break;
|
||||
|
||||
case '\x15':
|
||||
// Delete line (^U)
|
||||
erase_current_line();
|
||||
prompt_displayed_ = false;
|
||||
line_buffer_.clear();
|
||||
display_prompt();
|
||||
break;
|
||||
|
||||
case '\x17':
|
||||
// Delete word (^W)
|
||||
delete_buffer_word(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (c >= '\x20' && c <= '\x7E') {
|
||||
// ASCII text
|
||||
if (line_buffer_.length() < maximum_command_line_length_) {
|
||||
line_buffer_.push_back(c);
|
||||
write((uint8_t)c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
previous_ = c;
|
||||
|
||||
// This is a hack to let TelnetStream know that command
|
||||
// execution is complete and that output can be flushed.
|
||||
available_char();
|
||||
|
||||
idle_time_ = uuid::get_uptime_ms();
|
||||
}
|
||||
|
||||
Shell::PasswordData::PasswordData(const __FlashStringHelper * password_prompt, password_function && password_function)
|
||||
: password_prompt_(password_prompt)
|
||||
, password_function_(std::move(password_function)) {
|
||||
}
|
||||
|
||||
void Shell::loop_password() {
|
||||
const int input = read_one_char();
|
||||
|
||||
if (input < 0) {
|
||||
check_idle_timeout();
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned char c = input;
|
||||
|
||||
switch (c) {
|
||||
case '\x03':
|
||||
// Interrupt (^C)
|
||||
process_password(false);
|
||||
break;
|
||||
|
||||
case '\x08':
|
||||
case '\x7F':
|
||||
// Backspace (^H)
|
||||
// Delete (^?)
|
||||
if (!line_buffer_.empty()) {
|
||||
line_buffer_.pop_back();
|
||||
}
|
||||
break;
|
||||
|
||||
case '\x0A':
|
||||
// Line feed (^J)
|
||||
if (previous_ != '\x0D') {
|
||||
process_password(true);
|
||||
}
|
||||
break;
|
||||
|
||||
case '\x0C':
|
||||
// New page (^L)
|
||||
erase_current_line();
|
||||
prompt_displayed_ = false;
|
||||
display_prompt();
|
||||
break;
|
||||
|
||||
case '\x0D':
|
||||
// Carriage return (^M)
|
||||
process_password(true);
|
||||
break;
|
||||
|
||||
case '\x15':
|
||||
// Delete line (^U)
|
||||
line_buffer_.clear();
|
||||
break;
|
||||
|
||||
case '\x17':
|
||||
// Delete word (^W)
|
||||
delete_buffer_word(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (c >= '\x20' && c <= '\x7E') {
|
||||
// ASCII text
|
||||
if (line_buffer_.length() < maximum_command_line_length_) {
|
||||
line_buffer_.push_back(c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
previous_ = c;
|
||||
|
||||
// This is a hack to let TelnetStream know that command
|
||||
// execution is complete and that output can be flushed.
|
||||
available_char();
|
||||
|
||||
idle_time_ = uuid::get_uptime_ms();
|
||||
}
|
||||
|
||||
Shell::DelayData::DelayData(uint64_t delay_time, delay_function && delay_function)
|
||||
: delay_time_(delay_time)
|
||||
, delay_function_(std::move(delay_function)) {
|
||||
}
|
||||
|
||||
void Shell::loop_delay() {
|
||||
auto * delay_data = reinterpret_cast<Shell::DelayData *>(mode_data_.get());
|
||||
|
||||
if (uuid::get_uptime_ms() >= delay_data->delay_time_) {
|
||||
auto function_copy = delay_data->delay_function_;
|
||||
|
||||
mode_ = Mode::NORMAL;
|
||||
mode_data_.reset();
|
||||
|
||||
function_copy(*this);
|
||||
|
||||
if (running()) {
|
||||
display_prompt();
|
||||
}
|
||||
|
||||
idle_time_ = uuid::get_uptime_ms();
|
||||
}
|
||||
}
|
||||
|
||||
Shell::BlockingData::BlockingData(blocking_function && blocking_function)
|
||||
: blocking_function_(std::move(blocking_function)) {
|
||||
}
|
||||
|
||||
void Shell::loop_blocking() {
|
||||
auto * blocking_data = reinterpret_cast<Shell::BlockingData *>(mode_data_.get());
|
||||
|
||||
/* It is not possible to change mode while executing this function,
|
||||
* because that would require copying either the std::shared_ptr or
|
||||
* the std::function on every loop execution (to ensure that the
|
||||
* function captures aren't destroyed while executing).
|
||||
*/
|
||||
if (blocking_data->blocking_function_(*this, blocking_data->stop_)) {
|
||||
bool stop_pending = blocking_data->stop_;
|
||||
|
||||
mode_ = Mode::NORMAL;
|
||||
mode_data_.reset();
|
||||
|
||||
if (stop_pending) {
|
||||
stop();
|
||||
}
|
||||
|
||||
if (running()) {
|
||||
display_prompt();
|
||||
}
|
||||
|
||||
idle_time_ = uuid::get_uptime_ms();
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::enter_password(const __FlashStringHelper * prompt, password_function function) {
|
||||
if (mode_ == Mode::NORMAL) {
|
||||
mode_ = Mode::PASSWORD;
|
||||
mode_data_ = std::make_unique<Shell::PasswordData>(prompt, std::move(function));
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::delay_for(unsigned long ms, delay_function function) {
|
||||
delay_until(uuid::get_uptime_ms() + ms, std::move(function));
|
||||
}
|
||||
|
||||
void Shell::delay_until(uint64_t ms, delay_function function) {
|
||||
if (mode_ == Mode::NORMAL) {
|
||||
mode_ = Mode::DELAY;
|
||||
mode_data_ = std::make_unique<Shell::DelayData>(ms, std::move(function));
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::block_with(blocking_function function) {
|
||||
if (mode_ == Mode::NORMAL) {
|
||||
mode_ = Mode::BLOCKING;
|
||||
mode_data_ = std::make_unique<Shell::BlockingData>(std::move(function));
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::delete_buffer_word(bool display) {
|
||||
size_t pos = line_buffer_.find_last_of(' ');
|
||||
|
||||
if (pos == std::string::npos) {
|
||||
line_buffer_.clear();
|
||||
if (display) {
|
||||
erase_current_line();
|
||||
prompt_displayed_ = false;
|
||||
display_prompt();
|
||||
}
|
||||
} else {
|
||||
if (display) {
|
||||
erase_characters(line_buffer_.length() - pos);
|
||||
}
|
||||
line_buffer_.resize(pos);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Shell::maximum_command_line_length() const {
|
||||
return maximum_command_line_length_;
|
||||
}
|
||||
|
||||
void Shell::maximum_command_line_length(size_t length) {
|
||||
maximum_command_line_length_ = std::max((size_t)1, length);
|
||||
line_buffer_.reserve(maximum_command_line_length_);
|
||||
}
|
||||
|
||||
void Shell::process_command() {
|
||||
CommandLine command_line{line_buffer_};
|
||||
|
||||
line_buffer_.clear();
|
||||
println();
|
||||
prompt_displayed_ = false;
|
||||
|
||||
if (!command_line->empty()) {
|
||||
if (commands_) {
|
||||
auto execution = commands_->execute_command(*this, std::move(command_line));
|
||||
|
||||
if (execution.error != nullptr) {
|
||||
println(execution.error);
|
||||
}
|
||||
} else {
|
||||
println(F("No commands configured"));
|
||||
}
|
||||
}
|
||||
|
||||
if (running()) {
|
||||
display_prompt();
|
||||
}
|
||||
::yield();
|
||||
}
|
||||
|
||||
void Shell::process_completion() {
|
||||
CommandLine command_line{line_buffer_};
|
||||
|
||||
if (!command_line->empty() && commands_) {
|
||||
auto completion = commands_->complete_command(*this, command_line);
|
||||
bool redisplay = false;
|
||||
|
||||
if (!completion.help.empty()) {
|
||||
println();
|
||||
redisplay = true;
|
||||
|
||||
for (auto & help : completion.help) {
|
||||
std::string help_line = help.to_string(maximum_command_line_length_);
|
||||
|
||||
println(help_line);
|
||||
}
|
||||
}
|
||||
|
||||
if (!completion.replacement->empty()) {
|
||||
if (!redisplay) {
|
||||
erase_current_line();
|
||||
prompt_displayed_ = false;
|
||||
redisplay = true;
|
||||
}
|
||||
|
||||
line_buffer_ = completion.replacement.to_string(maximum_command_line_length_);
|
||||
}
|
||||
|
||||
if (redisplay) {
|
||||
display_prompt();
|
||||
}
|
||||
}
|
||||
|
||||
::yield();
|
||||
}
|
||||
|
||||
void Shell::process_password(bool completed) {
|
||||
println();
|
||||
|
||||
auto * password_data = reinterpret_cast<Shell::PasswordData *>(mode_data_.get());
|
||||
auto function_copy = password_data->password_function_;
|
||||
|
||||
mode_ = Mode::NORMAL;
|
||||
mode_data_.reset();
|
||||
|
||||
function_copy(*this, completed, line_buffer_);
|
||||
line_buffer_.clear();
|
||||
|
||||
if (running()) {
|
||||
display_prompt();
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::invoke_command(const std::string & line) {
|
||||
if (!line_buffer_.empty()) {
|
||||
println();
|
||||
prompt_displayed_ = false;
|
||||
}
|
||||
if (!prompt_displayed_) {
|
||||
display_prompt();
|
||||
}
|
||||
line_buffer_ = line;
|
||||
print(line_buffer_);
|
||||
process_command();
|
||||
}
|
||||
|
||||
unsigned long Shell::idle_timeout() const {
|
||||
return idle_timeout_ / 1000;
|
||||
}
|
||||
|
||||
void Shell::idle_timeout(unsigned long timeout) {
|
||||
idle_timeout_ = (uint64_t)timeout * 1000;
|
||||
}
|
||||
|
||||
void Shell::check_idle_timeout() {
|
||||
if (idle_timeout_ > 0 && uuid::get_uptime_ms() - idle_time_ >= idle_timeout_) {
|
||||
println();
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace console
|
||||
|
||||
} // namespace uuid
|
||||
108
lib/uuid-console/src/shell_log.cpp
Normal file
108
lib/uuid-console/src/shell_log.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* uuid-console - Microcontroller console shell
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/console.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace console {
|
||||
|
||||
static const char __pstr__logger_name[] __attribute__((__aligned__(sizeof(int)))) PROGMEM = "shell";
|
||||
const uuid::log::Logger Shell::logger_{reinterpret_cast<const __FlashStringHelper *>(__pstr__logger_name), uuid::log::Facility::LPR};
|
||||
|
||||
Shell::QueuedLogMessage::QueuedLogMessage(unsigned long id, std::shared_ptr<uuid::log::Message> && content)
|
||||
: id_(id)
|
||||
, content_(std::move(content)) {
|
||||
}
|
||||
|
||||
void Shell::operator<<(std::shared_ptr<uuid::log::Message> message) {
|
||||
if (log_messages_.size() >= maximum_log_messages_) {
|
||||
log_messages_.pop_front();
|
||||
}
|
||||
|
||||
log_messages_.emplace_back(log_message_id_++, std::move(message));
|
||||
}
|
||||
|
||||
uuid::log::Level Shell::log_level() const {
|
||||
return uuid::log::Logger::get_log_level(this);
|
||||
}
|
||||
|
||||
void Shell::log_level(uuid::log::Level level) {
|
||||
uuid::log::Logger::register_handler(this, level);
|
||||
}
|
||||
|
||||
size_t Shell::maximum_log_messages() const {
|
||||
return maximum_log_messages_;
|
||||
}
|
||||
|
||||
void Shell::maximum_log_messages(size_t count) {
|
||||
maximum_log_messages_ = std::max((size_t)1, count);
|
||||
while (log_messages_.size() > maximum_log_messages_) {
|
||||
log_messages_.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::output_logs() {
|
||||
if (!log_messages_.empty()) {
|
||||
if (mode_ != Mode::DELAY) {
|
||||
erase_current_line();
|
||||
prompt_displayed_ = false;
|
||||
}
|
||||
|
||||
while (!log_messages_.empty()) {
|
||||
auto message = std::move(log_messages_.front());
|
||||
log_messages_.pop_front();
|
||||
|
||||
|
||||
print(uuid::log::format_timestamp_ms(message.content_->uptime_ms, 3));
|
||||
printf(F(" %c %lu: [%S] "), uuid::log::format_level_char(message.content_->level), message.id_, message.content_->name);
|
||||
|
||||
if ((message.content_->level == uuid::log::Level::ERR) || (message.content_->level == uuid::log::Level::WARNING)) {
|
||||
print(COLOR_RED);
|
||||
println(message.content_->text);
|
||||
print(COLOR_RESET);
|
||||
} else if (message.content_->level == uuid::log::Level::INFO) {
|
||||
print(COLOR_YELLOW);
|
||||
println(message.content_->text);
|
||||
print(COLOR_RESET);
|
||||
} else if (message.content_->level == uuid::log::Level::DEBUG) {
|
||||
print(COLOR_CYAN);
|
||||
println(message.content_->text);
|
||||
print(COLOR_RESET);
|
||||
} else {
|
||||
println(message.content_->text);
|
||||
}
|
||||
|
||||
::yield();
|
||||
|
||||
display_prompt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace console
|
||||
|
||||
} // namespace uuid
|
||||
45
lib/uuid-console/src/shell_loop_all.cpp
Normal file
45
lib/uuid-console/src/shell_loop_all.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* uuid-console - Microcontroller console shell
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/console.h>
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace console {
|
||||
|
||||
std::set<std::shared_ptr<Shell>> Shell::shells_;
|
||||
|
||||
void Shell::loop_all() {
|
||||
for (auto shell = shells_.begin(); shell != shells_.end();) {
|
||||
shell->get()->loop_one();
|
||||
|
||||
// This avoids copying the shared_ptr every time loop_one() is called
|
||||
if (!shell->get()->running()) {
|
||||
shell = shells_.erase(shell);
|
||||
} else {
|
||||
shell++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace console
|
||||
|
||||
} // namespace uuid
|
||||
165
lib/uuid-console/src/shell_print.cpp
Normal file
165
lib/uuid-console/src/shell_print.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* uuid-console - Microcontroller console shell
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/console.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace console {
|
||||
|
||||
size_t Shell::print(const std::string & data) {
|
||||
if (data.empty()) {
|
||||
return 0;
|
||||
} else {
|
||||
return write(reinterpret_cast<const uint8_t *>(data.c_str()), data.length());
|
||||
}
|
||||
}
|
||||
|
||||
size_t Shell::println(const std::string & data) {
|
||||
size_t len = print(data);
|
||||
len += println();
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t Shell::printf(const char * format, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
size_t len = vprintf(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t Shell::printf(const __FlashStringHelper * format, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
size_t len = vprintf(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t Shell::printfln(const char * format, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
size_t len = vprintf(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
len += println();
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t Shell::printfln(const __FlashStringHelper * format, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
size_t len = vprintf(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
len += println();
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t Shell::vprintf(const char * format, va_list ap) {
|
||||
size_t print_len = 0;
|
||||
va_list copy_ap;
|
||||
|
||||
va_copy(copy_ap, ap);
|
||||
|
||||
int format_len = ::vsnprintf(nullptr, 0, format, ap);
|
||||
if (format_len > 0) {
|
||||
std::string text(static_cast<std::string::size_type>(format_len), '\0');
|
||||
|
||||
::vsnprintf(&text[0], text.capacity() + 1, format, copy_ap);
|
||||
print_len = print(text);
|
||||
}
|
||||
|
||||
va_end(copy_ap);
|
||||
return print_len;
|
||||
}
|
||||
|
||||
size_t Shell::vprintf(const __FlashStringHelper * format, va_list ap) {
|
||||
size_t print_len = 0;
|
||||
va_list copy_ap;
|
||||
|
||||
va_copy(copy_ap, ap);
|
||||
|
||||
int format_len = ::vsnprintf_P(nullptr, 0, reinterpret_cast<PGM_P>(format), ap);
|
||||
if (format_len > 0) {
|
||||
std::string text(static_cast<std::string::size_type>(format_len), '\0');
|
||||
|
||||
::vsnprintf_P(&text[0], text.capacity() + 1, reinterpret_cast<PGM_P>(format), copy_ap);
|
||||
print_len = print(text);
|
||||
}
|
||||
|
||||
va_end(copy_ap);
|
||||
return print_len;
|
||||
}
|
||||
|
||||
// modified by proddy
|
||||
void Shell::print_all_available_commands() {
|
||||
/*
|
||||
commands_->for_each_available_command(*this, [this](std::vector<std::string> & name, std::vector<std::string> & arguments) {
|
||||
CommandLine command_line{name, arguments};
|
||||
|
||||
command_line.escape_initial_parameters(name.size());
|
||||
name.clear();
|
||||
arguments.clear();
|
||||
print(" "); // added by proddy
|
||||
println(command_line.to_string(maximum_command_line_length()));
|
||||
});
|
||||
*/
|
||||
|
||||
// changed by proddy - sort the help commands
|
||||
std::list<std::string> sorted_cmds;
|
||||
|
||||
commands_->for_each_available_command(*this, [&](std::vector<std::string> & name, std::vector<std::string> & arguments) {
|
||||
CommandLine command_line{name, arguments};
|
||||
command_line.escape_initial_parameters(name.size());
|
||||
name.clear();
|
||||
arguments.clear();
|
||||
sorted_cmds.push_back(command_line.to_string(maximum_command_line_length()));
|
||||
});
|
||||
|
||||
sorted_cmds.sort();
|
||||
for (auto & cl : sorted_cmds) {
|
||||
// print(" ");
|
||||
println(cl);
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::erase_current_line() {
|
||||
print(F("\033[0G\033[K"));
|
||||
}
|
||||
|
||||
void Shell::erase_characters(size_t count) {
|
||||
print(std::string(count, '\x08'));
|
||||
print(F("\033[K"));
|
||||
}
|
||||
|
||||
} // namespace console
|
||||
|
||||
} // namespace uuid
|
||||
93
lib/uuid-console/src/shell_prompt.cpp
Normal file
93
lib/uuid-console/src/shell_prompt.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* uuid-console - Microcontroller console shell
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/console.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace console {
|
||||
|
||||
void Shell::display_banner() {
|
||||
}
|
||||
|
||||
std::string Shell::hostname_text() {
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
std::string Shell::context_text() {
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
std::string Shell::prompt_prefix() {
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
std::string Shell::prompt_suffix() {
|
||||
return std::string{'$'};
|
||||
}
|
||||
|
||||
void Shell::end_of_transmission() {
|
||||
if (idle_timeout_ > 0) {
|
||||
println();
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::display_prompt() {
|
||||
switch (mode_) {
|
||||
case Mode::DELAY:
|
||||
case Mode::BLOCKING:
|
||||
break;
|
||||
|
||||
case Mode::PASSWORD:
|
||||
print(reinterpret_cast<Shell::PasswordData *>(mode_data_.get())->password_prompt_);
|
||||
break;
|
||||
|
||||
case Mode::NORMAL:
|
||||
std::string hostname = hostname_text();
|
||||
std::string context = context_text();
|
||||
|
||||
print(prompt_prefix());
|
||||
// colors added by proddy
|
||||
if (!hostname.empty()) {
|
||||
print(COLOR_BRIGHT_GREEN);
|
||||
print(COLOR_BOLD_ON);
|
||||
print(hostname);
|
||||
print(COLOR_RESET);
|
||||
print(':');
|
||||
}
|
||||
if (!context.empty()) {
|
||||
print(COLOR_BRIGHT_BLUE);
|
||||
print(COLOR_BOLD_ON);
|
||||
print(context);
|
||||
print(COLOR_RESET);
|
||||
// print(' ');
|
||||
}
|
||||
print(prompt_suffix());
|
||||
print(' ');
|
||||
print(line_buffer_);
|
||||
prompt_displayed_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace console
|
||||
|
||||
} // namespace uuid
|
||||
125
lib/uuid-console/src/shell_stream.cpp
Normal file
125
lib/uuid-console/src/shell_stream.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* uuid-console - Microcontroller console shell
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/console.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace console {
|
||||
|
||||
int Shell::available() {
|
||||
if (mode_ == Mode::BLOCKING) {
|
||||
auto * blocking_data = reinterpret_cast<Shell::BlockingData *>(mode_data_.get());
|
||||
|
||||
if (!available_char()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (blocking_data->consume_line_feed_) {
|
||||
const int input = peek_one_char();
|
||||
|
||||
if (input >= 0) {
|
||||
const unsigned char c = input;
|
||||
|
||||
blocking_data->consume_line_feed_ = false;
|
||||
|
||||
if (previous_ == '\x0D' && c == '\x0A') {
|
||||
// Consume the first LF following a CR
|
||||
read_one_char();
|
||||
previous_ = c;
|
||||
return available();
|
||||
}
|
||||
} else {
|
||||
// The underlying stream has not implemented peek,
|
||||
// so the next read() could return -1 if LF is
|
||||
// filtered out.
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Shell::read() {
|
||||
if (mode_ == Mode::BLOCKING) {
|
||||
auto * blocking_data = reinterpret_cast<Shell::BlockingData *>(mode_data_.get());
|
||||
const int input = read_one_char();
|
||||
|
||||
if (input >= 0) {
|
||||
const unsigned char c = input;
|
||||
|
||||
if (blocking_data->consume_line_feed_) {
|
||||
blocking_data->consume_line_feed_ = false;
|
||||
|
||||
if (previous_ == '\x0D' && c == '\x0A') {
|
||||
// Consume the first LF following a CR
|
||||
previous_ = c;
|
||||
return read();
|
||||
}
|
||||
}
|
||||
|
||||
// Track read characters so that a final CR means we ignore the next LF
|
||||
previous_ = c;
|
||||
}
|
||||
|
||||
return input;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int Shell::peek() {
|
||||
if (mode_ == Mode::BLOCKING) {
|
||||
auto * blocking_data = reinterpret_cast<Shell::BlockingData *>(mode_data_.get());
|
||||
const int input = peek_one_char();
|
||||
|
||||
if (blocking_data->consume_line_feed_) {
|
||||
if (input >= 0) {
|
||||
const unsigned char c = input;
|
||||
|
||||
blocking_data->consume_line_feed_ = false;
|
||||
|
||||
if (previous_ == '\x0D' && c == '\x0A') {
|
||||
// Consume the first LF following a CR
|
||||
read_one_char();
|
||||
previous_ = c;
|
||||
return peek();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return input;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::flush() {
|
||||
// This is a pure virtual function in Arduino's Stream class, which
|
||||
// makes no sense because that class is for input and this is an
|
||||
// output function. Later versions move it to Print as an empty
|
||||
// virtual function so this is here for backward compatibility.
|
||||
}
|
||||
|
||||
} // namespace console
|
||||
|
||||
} // namespace uuid
|
||||
63
lib/uuid-console/src/stream_console.cpp
Normal file
63
lib/uuid-console/src/stream_console.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* uuid-console - Microcontroller console shell
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/console.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace console {
|
||||
|
||||
StreamConsole::StreamConsole(Stream & stream)
|
||||
: Shell()
|
||||
, stream_(stream) {
|
||||
}
|
||||
|
||||
// cppcheck-suppress passedByValue
|
||||
StreamConsole::StreamConsole(std::shared_ptr<Commands> commands, Stream & stream, unsigned int context, unsigned int flags)
|
||||
: Shell(std::move(commands), context, flags)
|
||||
, stream_(stream) {
|
||||
}
|
||||
|
||||
size_t StreamConsole::write(uint8_t data) {
|
||||
return stream_.write(data);
|
||||
}
|
||||
|
||||
size_t StreamConsole::write(const uint8_t * buffer, size_t size) {
|
||||
return stream_.write(buffer, size);
|
||||
}
|
||||
|
||||
bool StreamConsole::available_char() {
|
||||
return stream_.available() > 0;
|
||||
}
|
||||
|
||||
int StreamConsole::read_one_char() {
|
||||
return stream_.read();
|
||||
}
|
||||
|
||||
int StreamConsole::peek_one_char() {
|
||||
return stream_.peek();
|
||||
}
|
||||
|
||||
} // namespace console
|
||||
|
||||
} // namespace uuid
|
||||
1516
lib/uuid-console/src/uuid/console.h
Normal file
1516
lib/uuid-console/src/uuid/console.h
Normal file
File diff suppressed because it is too large
Load Diff
674
lib/uuid-log/COPYING
Normal file
674
lib/uuid-log/COPYING
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
25
lib/uuid-log/README.rst
Normal file
25
lib/uuid-log/README.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
mcu-uuid-log |Build Status|
|
||||
===========================
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Microcontroller logging framework
|
||||
|
||||
Purpose
|
||||
-------
|
||||
|
||||
Provides a framework for handling log messages. This library is for
|
||||
single threaded applications and cannot be used from an interrupt
|
||||
context.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
`Read the documentation <https://mcu-uuid-log.readthedocs.io/>`_ generated
|
||||
from the docs_ directory.
|
||||
|
||||
.. _docs: docs/
|
||||
|
||||
.. |Build Status| image:: https://travis-ci.org/nomis/mcu-uuid-log.svg?branch=master
|
||||
:target: https://travis-ci.org/nomis/mcu-uuid-log
|
||||
34
lib/uuid-log/library.json
Normal file
34
lib/uuid-log/library.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "uuid-log",
|
||||
"description": "Logging framework",
|
||||
"keywords": "logging",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Simon Arlott",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nomis/mcu-uuid-log.git"
|
||||
},
|
||||
"version": "2.1.1",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"homepage": "https://mcu-uuid-log.readthedocs.io/",
|
||||
"export": {
|
||||
"exclude": [
|
||||
".travis.yml",
|
||||
"test/*"
|
||||
]
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"dependencies": {
|
||||
"uuid-common": "^1.0.0"
|
||||
},
|
||||
"build": {
|
||||
"flags": "-Wall -Wextra",
|
||||
"libLDFMode": "off"
|
||||
}
|
||||
}
|
||||
32
lib/uuid-log/src/format_level_char.cpp
Normal file
32
lib/uuid-log/src/format_level_char.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace log {
|
||||
|
||||
char format_level_char(Level level) {
|
||||
constexpr char log_level_chars[(int)Level::ALL - (int)Level::OFF + 1] = {' ', 'P', 'A', 'C', 'E', 'W', 'N', 'I', 'T', 'D', ' '}; // changed by proddy
|
||||
return log_level_chars[(int)level + 1];
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
60
lib/uuid-log/src/format_level_lowercase.cpp
Normal file
60
lib/uuid-log/src/format_level_lowercase.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace log {
|
||||
|
||||
static constexpr const char * pstr_level_lowercase_off __attribute__((__aligned__(sizeof(int)))) PROGMEM = "off";
|
||||
static constexpr const char * pstr_level_lowercase_emerg __attribute__((__aligned__(sizeof(int)))) PROGMEM = "emerg";
|
||||
static constexpr const char * pstr_level_lowercase_crit __attribute__((__aligned__(sizeof(int)))) PROGMEM = "crit";
|
||||
static constexpr const char * pstr_level_lowercase_alert __attribute__((__aligned__(sizeof(int)))) PROGMEM = "alert";
|
||||
static constexpr const char * pstr_level_lowercase_err __attribute__((__aligned__(sizeof(int)))) PROGMEM = "err";
|
||||
static constexpr const char * pstr_level_lowercase_warning __attribute__((__aligned__(sizeof(int)))) PROGMEM = "warning";
|
||||
static constexpr const char * pstr_level_lowercase_notice __attribute__((__aligned__(sizeof(int)))) PROGMEM = "notice";
|
||||
static constexpr const char * pstr_level_lowercase_info __attribute__((__aligned__(sizeof(int)))) PROGMEM = "info";
|
||||
static constexpr const char * pstr_level_lowercase_debug __attribute__((__aligned__(sizeof(int)))) PROGMEM = "debug";
|
||||
static constexpr const char * pstr_level_lowercase_trace __attribute__((__aligned__(sizeof(int)))) PROGMEM = "trace";
|
||||
static constexpr const char * pstr_level_lowercase_all __attribute__((__aligned__(sizeof(int)))) PROGMEM = "all";
|
||||
|
||||
static const __FlashStringHelper * log_level_lowercase[(int)Level::ALL - (int)Level::OFF + 1] __attribute__((__aligned__(sizeof(int))))
|
||||
PROGMEM = {reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_off),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_emerg),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_crit),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_alert),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_err),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_warning),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_notice),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_info),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_trace), // switched by proddy
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_debug),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_all)};
|
||||
|
||||
const __FlashStringHelper * format_level_lowercase(Level level) {
|
||||
return log_level_lowercase[(int)level + 1];
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
60
lib/uuid-log/src/format_level_uppercase.cpp
Normal file
60
lib/uuid-log/src/format_level_uppercase.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace log {
|
||||
|
||||
static constexpr const char * pstr_level_uppercase_off __attribute__((__aligned__(sizeof(int)))) PROGMEM = "OFF";
|
||||
static constexpr const char * pstr_level_uppercase_emerg __attribute__((__aligned__(sizeof(int)))) PROGMEM = "EMERG";
|
||||
static constexpr const char * pstr_level_uppercase_crit __attribute__((__aligned__(sizeof(int)))) PROGMEM = "CRIT";
|
||||
static constexpr const char * pstr_level_uppercase_alert __attribute__((__aligned__(sizeof(int)))) PROGMEM = "ALERT";
|
||||
static constexpr const char * pstr_level_uppercase_err __attribute__((__aligned__(sizeof(int)))) PROGMEM = "ERR";
|
||||
static constexpr const char * pstr_level_uppercase_warning __attribute__((__aligned__(sizeof(int)))) PROGMEM = "WARNING";
|
||||
static constexpr const char * pstr_level_uppercase_notice __attribute__((__aligned__(sizeof(int)))) PROGMEM = "NOTICE";
|
||||
static constexpr const char * pstr_level_uppercase_info __attribute__((__aligned__(sizeof(int)))) PROGMEM = "INFO";
|
||||
static constexpr const char * pstr_level_uppercase_debug __attribute__((__aligned__(sizeof(int)))) PROGMEM = "DEBUG";
|
||||
static constexpr const char * pstr_level_uppercase_trace __attribute__((__aligned__(sizeof(int)))) PROGMEM = "TRACE";
|
||||
static constexpr const char * pstr_level_uppercase_all __attribute__((__aligned__(sizeof(int)))) PROGMEM = "ALL";
|
||||
|
||||
static const __FlashStringHelper * log_level_uppercase[(int)Level::ALL - (int)Level::OFF + 1] __attribute__((__aligned__(sizeof(int))))
|
||||
PROGMEM = {reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_off),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_emerg),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_crit),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_alert),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_err),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_warning),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_notice),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_info),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_trace), // switched by proddy
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_debug),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_all)};
|
||||
|
||||
const __FlashStringHelper * format_level_uppercase(Level level) {
|
||||
return log_level_uppercase[(int)level + 1];
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
57
lib/uuid-log/src/format_timestamp_ms.cpp
Normal file
57
lib/uuid-log/src/format_timestamp_ms.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace log {
|
||||
|
||||
std::string format_timestamp_ms(uint64_t timestamp_ms, unsigned int days_width) {
|
||||
unsigned long days;
|
||||
unsigned int hours, minutes, seconds, milliseconds;
|
||||
|
||||
days = timestamp_ms / 86400000UL;
|
||||
timestamp_ms %= 86400000UL;
|
||||
|
||||
hours = timestamp_ms / 3600000UL;
|
||||
timestamp_ms %= 3600000UL;
|
||||
|
||||
minutes = timestamp_ms / 60000UL;
|
||||
timestamp_ms %= 60000UL;
|
||||
|
||||
seconds = timestamp_ms / 1000UL;
|
||||
timestamp_ms %= 1000UL;
|
||||
|
||||
milliseconds = timestamp_ms;
|
||||
|
||||
std::vector<char> text(10 + 1 /* days */ + 2 + 1 /* hours */ + 2 + 1 /* minutes */ + 2 + 1 /* seconds */ + 3 /* milliseconds */ + 1);
|
||||
|
||||
snprintf_P(text.data(), text.size(), PSTR("%0*lu+%02u:%02u:%02u.%03u"), std::min(days_width, 10U), days, hours, minutes, seconds, milliseconds);
|
||||
|
||||
return text.data();
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
43
lib/uuid-log/src/levels.cpp
Normal file
43
lib/uuid-log/src/levels.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace log {
|
||||
|
||||
std::vector<Level> levels() {
|
||||
return {Level::OFF,
|
||||
Level::EMERG,
|
||||
Level::ALERT,
|
||||
Level::CRIT,
|
||||
Level::ERR,
|
||||
Level::WARNING,
|
||||
Level::NOTICE,
|
||||
Level::INFO,
|
||||
Level::TRACE,
|
||||
Level::DEBUG, // switched by proddy
|
||||
Level::ALL};
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
45
lib/uuid-log/src/levels_lowercase.cpp
Normal file
45
lib/uuid-log/src/levels_lowercase.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <uuid/common.h>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace log {
|
||||
|
||||
std::vector<std::string> levels_lowercase() {
|
||||
return {uuid::read_flash_string(format_level_lowercase(Level::OFF)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::EMERG)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::ALERT)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::CRIT)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::ERR)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::WARNING)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::NOTICE)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::INFO)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::TRACE)), // switched by proddy
|
||||
uuid::read_flash_string(format_level_lowercase(Level::DEBUG)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::ALL))};
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
45
lib/uuid-log/src/levels_uppercase.cpp
Normal file
45
lib/uuid-log/src/levels_uppercase.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <uuid/common.h>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace log {
|
||||
|
||||
std::vector<std::string> levels_uppercase() {
|
||||
return {uuid::read_flash_string(format_level_uppercase(Level::OFF)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::EMERG)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::ALERT)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::CRIT)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::ERR)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::WARNING)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::NOTICE)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::INFO)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::TRACE)), // switched by proddy
|
||||
uuid::read_flash_string(format_level_uppercase(Level::DEBUG)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::ALL))};
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
335
lib/uuid-log/src/log.cpp
Normal file
335
lib/uuid-log/src/log.cpp
Normal file
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace log {
|
||||
|
||||
std::map<Handler *, Level> Logger::handlers_;
|
||||
Level Logger::level_ = Level::OFF;
|
||||
|
||||
Message::Message(uint64_t uptime_ms, Level level, Facility facility, const __FlashStringHelper * name, const std::string && text)
|
||||
: uptime_ms(uptime_ms)
|
||||
, level(level)
|
||||
, facility(facility)
|
||||
, name(name)
|
||||
, text(std::move(text)) {
|
||||
}
|
||||
|
||||
Logger::Logger(const __FlashStringHelper * name, Facility facility)
|
||||
: name_(name)
|
||||
, facility_(facility){
|
||||
|
||||
};
|
||||
|
||||
void Logger::register_handler(Handler * handler, Level level) {
|
||||
handlers_[handler] = level;
|
||||
refresh_log_level();
|
||||
};
|
||||
|
||||
void Logger::unregister_handler(Handler * handler) {
|
||||
handlers_.erase(handler);
|
||||
refresh_log_level();
|
||||
};
|
||||
|
||||
Level Logger::get_log_level(const Handler * handler) {
|
||||
const auto level = handlers_.find(const_cast<Handler *>(handler));
|
||||
|
||||
if (level != handlers_.end()) {
|
||||
return level->second;
|
||||
}
|
||||
|
||||
return Level::OFF;
|
||||
}
|
||||
|
||||
void Logger::emerg(const char * format, ...) const {
|
||||
if (enabled(Level::EMERG)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::EMERG, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::emerg(const __FlashStringHelper * format, ...) const {
|
||||
if (enabled(Level::EMERG)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::EMERG, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::crit(const char * format, ...) const {
|
||||
if (enabled(Level::CRIT)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::CRIT, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::crit(const __FlashStringHelper * format, ...) const {
|
||||
if (enabled(Level::CRIT)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::CRIT, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::alert(const char * format, ...) const {
|
||||
if (enabled(Level::ALERT)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::ALERT, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::alert(const __FlashStringHelper * format, ...) const {
|
||||
if (enabled(Level::ALERT)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::ALERT, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
void Logger::err(const char * format, ...) const {
|
||||
if (enabled(Level::ERR)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::ERR, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::err(const __FlashStringHelper * format, ...) const {
|
||||
if (enabled(Level::ERR)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::ERR, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::warning(const char * format, ...) const {
|
||||
if (enabled(Level::WARNING)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::WARNING, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::warning(const __FlashStringHelper * format, ...) const {
|
||||
if (enabled(Level::WARNING)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::WARNING, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::notice(const char * format, ...) const {
|
||||
if (enabled(Level::NOTICE)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::NOTICE, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::notice(const __FlashStringHelper * format, ...) const {
|
||||
if (enabled(Level::NOTICE)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::NOTICE, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::info(const char * format, ...) const {
|
||||
if (enabled(Level::INFO)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::INFO, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::info(const __FlashStringHelper * format, ...) const {
|
||||
if (enabled(Level::INFO)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::INFO, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::debug(const char * format, ...) const {
|
||||
if (enabled(Level::DEBUG)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::DEBUG, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::debug(const __FlashStringHelper * format, ...) const {
|
||||
if (enabled(Level::DEBUG)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::DEBUG, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::trace(const char * format, ...) const {
|
||||
if (enabled(Level::TRACE)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::TRACE, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::trace(const __FlashStringHelper * format, ...) const {
|
||||
if (enabled(Level::TRACE)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(Level::TRACE, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::log(Level level, Facility facility, const char * format, ...) const {
|
||||
if (level < Level::EMERG) {
|
||||
level = Level::EMERG;
|
||||
} else if (level > Level::TRACE) {
|
||||
level = Level::TRACE;
|
||||
}
|
||||
|
||||
if (enabled(level)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(level, facility, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::log(Level level, Facility facility, const __FlashStringHelper * format, ...) const {
|
||||
if (level < Level::EMERG) {
|
||||
level = Level::EMERG;
|
||||
} else if (level > Level::TRACE) {
|
||||
level = Level::TRACE;
|
||||
}
|
||||
|
||||
if (enabled(level)) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vlog(level, facility, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
void Logger::vlog(Level level, const char * format, va_list ap) const {
|
||||
vlog(level, facility_, format, ap);
|
||||
}
|
||||
|
||||
void Logger::vlog(Level level, Facility facility, const char * format, va_list ap) const {
|
||||
std::vector<char> text(MAX_LOG_LENGTH + 1);
|
||||
|
||||
if (vsnprintf(text.data(), text.size(), format, ap) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(level, facility, text);
|
||||
}
|
||||
|
||||
void Logger::vlog(Level level, const __FlashStringHelper * format, va_list ap) const {
|
||||
vlog(level, facility_, format, ap);
|
||||
}
|
||||
|
||||
void Logger::vlog(Level level, Facility facility, const __FlashStringHelper * format, va_list ap) const {
|
||||
std::vector<char> text(MAX_LOG_LENGTH + 1);
|
||||
|
||||
if (vsnprintf_P(text.data(), text.size(), reinterpret_cast<PGM_P>(format), ap) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(level, facility, text);
|
||||
}
|
||||
|
||||
void Logger::dispatch(Level level, Facility facility, std::vector<char> & text) const {
|
||||
std::shared_ptr<Message> message = std::make_shared<Message>(get_uptime_ms(), level, facility, name_, text.data());
|
||||
text.resize(0);
|
||||
|
||||
for (auto & handler : handlers_) {
|
||||
if (level <= handler.second) {
|
||||
*handler.first << message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::refresh_log_level() {
|
||||
level_ = Level::OFF;
|
||||
|
||||
for (auto & handler : handlers_) {
|
||||
if (level_ < handler.second) {
|
||||
level_ = handler.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
41
lib/uuid-log/src/parse_level_lowercase.cpp
Normal file
41
lib/uuid-log/src/parse_level_lowercase.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace log {
|
||||
|
||||
bool parse_level_lowercase(const std::string & name, Level & level) {
|
||||
for (auto value : levels()) {
|
||||
if (!strcmp_P(name.c_str(), reinterpret_cast<PGM_P>(format_level_lowercase(value)))) {
|
||||
level = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
41
lib/uuid-log/src/parse_level_uppercase.cpp
Normal file
41
lib/uuid-log/src/parse_level_uppercase.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace log {
|
||||
|
||||
bool parse_level_uppercase(const std::string & name, Level & level) {
|
||||
for (auto value : levels()) {
|
||||
if (!strcmp_P(name.c_str(), reinterpret_cast<PGM_P>(format_level_uppercase(value)))) {
|
||||
level = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
656
lib/uuid-log/src/uuid/log.h
Normal file
656
lib/uuid-log/src/uuid/log.h
Normal file
@@ -0,0 +1,656 @@
|
||||
/*
|
||||
* uuid-log - Microcontroller logging framework
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UUID_LOG_H_
|
||||
#define UUID_LOG_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <uuid/common.h>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
/**
|
||||
* Logging framework.
|
||||
*
|
||||
* Provides a framework for handling log messages. This library is for
|
||||
* single threaded applications and cannot be used from an interrupt
|
||||
* context.
|
||||
*
|
||||
* - <a href="https://github.com/nomis/mcu-uuid-log/">Git Repository</a>
|
||||
* - <a href="https://mcu-uuid-log.readthedocs.io/">Documentation</a>
|
||||
*/
|
||||
|
||||
// ANSI Colors - added by Proddy
|
||||
// See https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html
|
||||
#define COLOR_RESET "\x1B[0m"
|
||||
#define COLOR_BLACK "\x1B[0;30m"
|
||||
#define COLOR_RED "\x1B[0;31m"
|
||||
#define COLOR_GREEN "\x1B[0;32m"
|
||||
#define COLOR_YELLOW "\x1B[0;33m"
|
||||
#define COLOR_BLUE "\x1B[0;34m"
|
||||
#define COLOR_MAGENTA "\x1B[0;35m"
|
||||
#define COLOR_CYAN "\x1B[0;36m"
|
||||
#define COLOR_WHITE "\x1B[0;37m"
|
||||
#define COLOR_BOLD_ON "\x1B[1m"
|
||||
#define COLOR_BOLD_OFF "\x1B[22m"
|
||||
#define COLOR_BRIGHT_BLACK "\x1B[0;90m"
|
||||
#define COLOR_BRIGHT_RED "\x1B[0;91m"
|
||||
#define COLOR_BRIGHT_GREEN "\x1B[0;92m"
|
||||
#define COLOR_BRIGHT_YELLOW "\x1B[0;99m"
|
||||
#define COLOR_BRIGHT_BLUE "\x1B[0;94m"
|
||||
#define COLOR_BRIGHT_MAGENTA "\x1B[0;95m"
|
||||
#define COLOR_BRIGHT_CYAN "\x1B[0;96m"
|
||||
#define COLOR_BRIGHT_WHITE "\x1B[0;97m"
|
||||
#define COLOR_UNDERLINE "\x1B[4m"
|
||||
|
||||
/*
|
||||
Background Black: \u001b[40m
|
||||
Background Red: \u001b[41m
|
||||
Background Green: \u001b[42m
|
||||
Background Yellow: \u001b[43m
|
||||
Background Blue: \u001b[44m
|
||||
Background Magenta: \u001b[45m
|
||||
Background Cyan: \u001b[46m
|
||||
Background White: \u001b[47m
|
||||
With the bright versions being:
|
||||
|
||||
Background Bright Black: \u001b[40;1m
|
||||
Background Bright Red: \u001b[41;1m
|
||||
Background Bright Green: \u001b[42;1m
|
||||
Background Bright Yellow: \u001b[43;1m
|
||||
Background Bright Blue: \u001b[44;1m
|
||||
Background Bright Magenta: \u001b[45;1m
|
||||
Background Bright Cyan: \u001b[46;1m
|
||||
Background Bright White: \u001b[47;1m
|
||||
*/
|
||||
|
||||
#define COLOR_BRIGHT_RED_BACKGROUND "\x1B[41;1m"
|
||||
|
||||
|
||||
namespace log {
|
||||
|
||||
/**
|
||||
* Severity level of log messages. Proddy added a VERBOSE
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
enum Level : int8_t {
|
||||
OFF = -1, /*!< Meta level representing no log messages. @since 1.0.0 */
|
||||
EMERG = 0, /*!< System is unusable. @since 1.0.0 */
|
||||
ALERT, /*!< Action must be taken immediately. @since 1.0.0 */
|
||||
CRIT, /*!< Critical conditions. @since 1.0.0 */
|
||||
ERR, /*!< Error conditions. @since 1.0.0 */
|
||||
WARNING, /*!< Warning conditions. @since 1.0.0 */
|
||||
NOTICE, /*!< Normal but significant conditions. @since 1.0.0 */
|
||||
INFO, /*!< Informational messages. @since 1.0.0 */
|
||||
TRACE, /*!< Trace messages. @since 1.0.0 */
|
||||
DEBUG, /*!< Debug-level messages. @since 1.0.0 */
|
||||
ALL, /*!< Meta level representing all log messages. @since 1.0.0 */
|
||||
};
|
||||
|
||||
/**
|
||||
* Facility type of the process logging a message.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
enum Facility : uint8_t {
|
||||
KERN = 0, /*!< Kernel messages. @since 1.0.0 */
|
||||
USER, /*!< User-level messages. @since 1.0.0 */
|
||||
MAIL, /*!< Mail system. @since 1.0.0 */
|
||||
DAEMON, /*!< System daemons. @since 1.0.0 */
|
||||
AUTH, /*!< Security/authentication messages. @since 1.0.0 */
|
||||
SYSLOG, /*!< Messages generated internally by logger. @since 1.0.0 */
|
||||
LPR, /*!< Line printer subsystem. @since 1.0.0 */
|
||||
NEWS, /*!< Network news subsystem. @since 1.0.0 */
|
||||
UUCP, /*!< UUCP subsystem. @since 1.0.0 */
|
||||
CRON, /*!< Clock daemon. @since 1.0.0 */
|
||||
AUTHPRIV, /*!< Security/authentication messages (private). @since 1.0.0 */
|
||||
FTP, /*!< FTP daemon. @since 1.0.0 */
|
||||
NTP, /*!< NTP subsystem. @since 1.0.0 */
|
||||
SECURITY, /*!< Log audit. @since 1.0.0 */
|
||||
CONSOLE, /*!< Log alert. @since 1.0.0 */
|
||||
CRON2, /*!< Scheduling daemon. @since 1.0.0 */
|
||||
LOCAL0, /*!< Locally used facility 0. @since 1.0.0 */
|
||||
LOCAL1, /*!< Locally used facility 1. @since 1.0.0 */
|
||||
LOCAL2, /*!< Locally used facility 2. @since 1.0.0 */
|
||||
LOCAL3, /*!< Locally used facility 3. @since 1.0.0 */
|
||||
LOCAL4, /*!< Locally used facility 4. @since 1.0.0 */
|
||||
LOCAL5, /*!< Locally used facility 5. @since 1.0.0 */
|
||||
LOCAL6, /*!< Locally used facility 6. @since 1.0.0 */
|
||||
LOCAL7, /*!< Locally used facility 7. @since 1.0.0 */
|
||||
};
|
||||
|
||||
/**
|
||||
* Format a system uptime timestamp as a string.
|
||||
*
|
||||
* Using the format "d+HH:mm:ss.SSS" with leading zeros for the days.
|
||||
*
|
||||
* @param[in] timestamp_ms System uptime in milliseconds, see uuid::get_uptime_ms().
|
||||
* @param[in] days_width Leading zeros for the days part of the output.
|
||||
* @return String with the formatted system uptime.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
std::string format_timestamp_ms(uint64_t timestamp_ms, unsigned int days_width = 1);
|
||||
|
||||
/**
|
||||
* Get all log levels.
|
||||
*
|
||||
* @return A list of all log levels in priority order from
|
||||
* uuid::log::Level::OFF to uuid::log::Level::ALL.
|
||||
* @since 2.1.0
|
||||
*/
|
||||
std::vector<Level> levels();
|
||||
|
||||
/**
|
||||
* Format a log level as a single character.
|
||||
*
|
||||
* Level::EMERG is represented as 'P' because it conflicts with
|
||||
* Level::ERR and it used to be the "panic" level.
|
||||
*
|
||||
* @param[in] level Log level.
|
||||
* @return Single character uppercase representation of the log level.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
char format_level_char(Level level);
|
||||
|
||||
/**
|
||||
* Format a log level as an uppercase string.
|
||||
*
|
||||
* @param[in] level Log level.
|
||||
* @return Uppercase name of the log level (flash string).
|
||||
* @since 1.0.0
|
||||
*/
|
||||
const __FlashStringHelper * format_level_uppercase(Level level);
|
||||
|
||||
/**
|
||||
* Get all log levels as uppercase strings.
|
||||
*
|
||||
* @return A list of all log levels in priority order from
|
||||
* uuid::log::Level::OFF to uuid::log::Level::ALL
|
||||
* as uppercase strings.
|
||||
* @since 2.1.0
|
||||
*/
|
||||
std::vector<std::string> levels_uppercase();
|
||||
|
||||
/**
|
||||
* Parse an uppercase string to a log level.
|
||||
*
|
||||
* @param[in] name Uppercase name of the log level.
|
||||
* @param[out] level Log level.
|
||||
* @return True if the named level is valid, otherwise false.
|
||||
* @since 2.1.0
|
||||
*/
|
||||
bool parse_level_uppercase(const std::string & name, Level & level);
|
||||
|
||||
/**
|
||||
* Format a log level as a lowercase string.
|
||||
*
|
||||
* @param[in] level Log level.
|
||||
* @return Lowercase name of the log level (flash string).
|
||||
* @since 1.0.0
|
||||
*/
|
||||
const __FlashStringHelper * format_level_lowercase(Level level);
|
||||
|
||||
/**
|
||||
* Get all log levels as lowercase strings.
|
||||
*
|
||||
* @return A list of all log levels in priority order from
|
||||
* uuid::log::Level::OFF to uuid::log::Level::ALL
|
||||
* as lowercase strings.
|
||||
* @since 2.1.0
|
||||
*/
|
||||
std::vector<std::string> levels_lowercase();
|
||||
|
||||
/**
|
||||
* Parse a lowercase string to a log level.
|
||||
*
|
||||
* @param[in] name Lowercase name of the log level.
|
||||
* @param[out] level Log level.
|
||||
* @return True if the named level is valid, otherwise false.
|
||||
* @since 2.1.0
|
||||
*/
|
||||
bool parse_level_lowercase(const std::string & name, Level & level);
|
||||
|
||||
/**
|
||||
* Log message text with timestamp and logger attributes.
|
||||
*
|
||||
* These will be created when a message is logged and then passed to
|
||||
* all registered handlers.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
struct Message {
|
||||
/**
|
||||
* Create a new log message (not directly useful).
|
||||
*
|
||||
* @param[in] uptime_ms System uptime, see uuid::get_uptime_ms().
|
||||
* @param[in] level Severity level of the message.
|
||||
* @param[in] facility Facility type of the process logging the message.
|
||||
* @param[in] name Logger name (flash string).
|
||||
* @param[in] text Log message text.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
Message(uint64_t uptime_ms, Level level, Facility facility, const __FlashStringHelper * name, const std::string && text);
|
||||
~Message() = default;
|
||||
|
||||
/**
|
||||
* System uptime at the time the message was logged.
|
||||
*
|
||||
* @see uuid::get_uptime_ms()
|
||||
* @since 1.0.0
|
||||
*/
|
||||
const uint64_t uptime_ms;
|
||||
|
||||
/**
|
||||
* Severity level of the message.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
const Level level;
|
||||
|
||||
/**
|
||||
* Facility type of the process that logged the message.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
const Facility facility;
|
||||
|
||||
/**
|
||||
* Name of the logger used (flash string).
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
const __FlashStringHelper * name;
|
||||
|
||||
/**
|
||||
* Formatted log message text.
|
||||
*
|
||||
* Does not include any of the other message attributes, those must
|
||||
* be added by the handler when outputting messages.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
const std::string text;
|
||||
};
|
||||
|
||||
/**
|
||||
* Logger handler used to process log messages.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Handler {
|
||||
public:
|
||||
virtual ~Handler() = default;
|
||||
|
||||
/**
|
||||
* Add a new log message.
|
||||
*
|
||||
* This should normally be put in a queue instead of being
|
||||
* processed immediately so that log messages have minimal impact
|
||||
* at the time of use.
|
||||
*
|
||||
* Queues should have a maximum size and discard the oldest message
|
||||
* when full.
|
||||
*
|
||||
* @param[in] message New log message, shared by all handlers.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
virtual void operator<<(std::shared_ptr<Message> message) = 0;
|
||||
|
||||
protected:
|
||||
Handler() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* Logger instance used to make log messages.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Logger {
|
||||
public:
|
||||
/**
|
||||
* This is the maximum length of any log message.
|
||||
*
|
||||
* Determines the size of the buffer used for format string
|
||||
* printing.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
static constexpr size_t MAX_LOG_LENGTH = 255; // proddy note, kept at 255
|
||||
|
||||
/**
|
||||
* Create a new logger with the given name and logging facility.
|
||||
*
|
||||
* @param[in] name Logger name (flash string).
|
||||
* @param[in] facility Default logging facility for messages.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
Logger(const __FlashStringHelper * name, Facility facility = Facility::LOCAL0);
|
||||
~Logger() = default;
|
||||
|
||||
/**
|
||||
* Register a log handler.
|
||||
*
|
||||
* Call again to change the log level.
|
||||
*
|
||||
* Do not call this function from a static initializer.
|
||||
*
|
||||
* @param[in] handler Handler object that will handle log
|
||||
* messages.
|
||||
* @param[in] level Minimum log level that the handler is
|
||||
* interested in.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
static void register_handler(Handler * handler, Level level);
|
||||
|
||||
/**
|
||||
* Unregister a log handler.
|
||||
*
|
||||
* It is safe to call this with a handler that is not registered.
|
||||
*
|
||||
* Do not call this function from a static initializer.
|
||||
*
|
||||
* @param[in] handler Handler object that will no longer handle
|
||||
* log messages.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
static void unregister_handler(Handler * handler);
|
||||
|
||||
/**
|
||||
* Get the current log level of a handler.
|
||||
*
|
||||
* It is safe to call this with a handler that is not registered.
|
||||
*
|
||||
* Do not call this function from a static initializer.
|
||||
*
|
||||
* @param[in] handler Handler object that may handle log
|
||||
* messages.
|
||||
* @return The current log level of the specified handler.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
static Level get_log_level(const Handler * handler);
|
||||
|
||||
/**
|
||||
* Determine if the current log level is enabled by any registered
|
||||
* handlers.
|
||||
*
|
||||
* @return The current minimum global log level across all
|
||||
* handlers.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
static inline bool enabled(Level level) {
|
||||
return level <= level_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message at level Level::EMERG.
|
||||
*
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void emerg(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
/**
|
||||
* Log a message at level Level::EMERG.
|
||||
*
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void emerg(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
|
||||
/**
|
||||
* Log a message at level Level::ALERT.
|
||||
*
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void alert(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
/**
|
||||
* Log a message at level Level::ALERT.
|
||||
*
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void alert(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
|
||||
/**
|
||||
* Log a message at level Level::CRIT.
|
||||
*
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void crit(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
/**
|
||||
* Log a message at level Level::CRIT.
|
||||
*
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void crit(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
|
||||
/**
|
||||
* Log a message at level Level::ERR.
|
||||
*
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void err(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
/**
|
||||
* Log a message at level Level::ERR.
|
||||
*
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void err(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
|
||||
/**
|
||||
* Log a message at level Level::WARNING.
|
||||
*
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void warning(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
/**
|
||||
* Log a message at level Level::WARNING.
|
||||
*
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void warning(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
|
||||
/**
|
||||
* Log a message at level Level::NOTICE.
|
||||
*
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void notice(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
/**
|
||||
* Log a message at level Level::NOTICE.
|
||||
*
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void notice(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
|
||||
/**
|
||||
* Log a message at level Level::INFO.
|
||||
*
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void info(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
/**
|
||||
* Log a message at level Level::INFO.
|
||||
*
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ... Format string arguments.
|
||||
*/
|
||||
void info(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
|
||||
/**
|
||||
* Log a message at level Level::DEBUG.
|
||||
*
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void debug(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
/**
|
||||
* Log a message at level Level::DEBUG.
|
||||
*
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void debug(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
|
||||
/**
|
||||
* Log a message at level Level::TRACE.
|
||||
*
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void trace(const char * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
/**
|
||||
* Log a message at level Level::TRACE.
|
||||
*
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void trace(const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 2, 3))) */;
|
||||
|
||||
/**
|
||||
* Log a message with a custom facility.
|
||||
*
|
||||
* @param[in] level Severity level of the message.
|
||||
* @param[in] facility Facility type of the process logging the message.
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void log(Level level, Facility facility, const char * format, ...) const /* __attribute__((format (printf, 3, 4))) */;
|
||||
/**
|
||||
* Log a message with a custom facility.
|
||||
*
|
||||
* @param[in] level Severity level of the message.
|
||||
* @param[in] facility Facility type of the process logging the message.
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ... Format string arguments.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void log(Level level, Facility facility, const __FlashStringHelper * format, ...) const /* __attribute__((format (printf, 4, 5))) */;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Refresh the minimum global log level across all handlers.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
static void refresh_log_level();
|
||||
|
||||
/**
|
||||
* Log a message at the specified level.
|
||||
*
|
||||
* @param[in] level Severity level of the message.
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ap Variable arguments pointer for format string.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void vlog(Level level, const char * format, va_list ap) const;
|
||||
/**
|
||||
* Log a message at the specified level.
|
||||
*
|
||||
* @param[in] level Severity level of the message.
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ap Variable arguments pointer for format string.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void vlog(Level level, const __FlashStringHelper * format, va_list ap) const;
|
||||
|
||||
/**
|
||||
* Log a message at the specified level and facility.
|
||||
*
|
||||
* @param[in] level Severity level of the message.
|
||||
* @param[in] facility Facility type of the process logging the message.
|
||||
* @param[in] format Format string.
|
||||
* @param[in] ap Variable arguments pointer for format string.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void vlog(Level level, Facility facility, const char * format, va_list ap) const;
|
||||
/**
|
||||
* Log a message at the specified level and facility.
|
||||
*
|
||||
* @param[in] level Severity level of the message.
|
||||
* @param[in] facility Facility type of the process logging the message.
|
||||
* @param[in] format Format string (flash string).
|
||||
* @param[in] ap Variable arguments pointer for format string.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void vlog(Level level, Facility facility, const __FlashStringHelper * format, va_list ap) const;
|
||||
|
||||
/**
|
||||
* Dispatch a log message to all handlers that are registered to
|
||||
* handle messages of the specified level.
|
||||
*
|
||||
* Automatically sets the timestamp of the message to the current
|
||||
* system uptime.
|
||||
*
|
||||
* @param[in] level Severity level of the message.
|
||||
* @param[in] facility Facility type of the process logging the message.
|
||||
* @param[in] text Log message text.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void dispatch(Level level, Facility facility, std::vector<char> & text) const;
|
||||
|
||||
static std::map<Handler *, Level> handlers_; /*!< Registered log handlers. @since 1.0.0 */
|
||||
static Level level_; /*!< Minimum global log level across all handlers. @since 1.0.0 */
|
||||
|
||||
const __FlashStringHelper * name_; /*!< Logger name (flash string). @since 1.0.0 */
|
||||
const Facility facility_; /*!< Default logging facility for messages. @since 1.0.0 */
|
||||
};
|
||||
|
||||
} // namespace log
|
||||
|
||||
} // namespace uuid
|
||||
|
||||
#endif
|
||||
674
lib/uuid-syslog/COPYING
Normal file
674
lib/uuid-syslog/COPYING
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
24
lib/uuid-syslog/README.rst
Normal file
24
lib/uuid-syslog/README.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
mcu-uuid-syslog |Build Status|
|
||||
==============================
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Microcontroller syslog service
|
||||
|
||||
Purpose
|
||||
-------
|
||||
|
||||
Provides a log handler that sends messages to a syslog server (using
|
||||
the `RFC 5424 protocol <https://tools.ietf.org/html/rfc5424>`_).
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
`Read the documentation <https://mcu-uuid-syslog.readthedocs.io/>`_
|
||||
generated from the docs_ directory.
|
||||
|
||||
.. _docs: docs/
|
||||
|
||||
.. |Build Status| image:: https://travis-ci.org/nomis/mcu-uuid-syslog.svg?branch=master
|
||||
:target: https://travis-ci.org/nomis/mcu-uuid-syslog
|
||||
35
lib/uuid-syslog/library.json
Normal file
35
lib/uuid-syslog/library.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "uuid-syslog",
|
||||
"description": "Syslog service",
|
||||
"keywords": "logging,syslog",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Simon Arlott",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nomis/mcu-uuid-syslog.git"
|
||||
},
|
||||
"version": "2.0.4",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"homepage": "https://mcu-uuid-syslog.readthedocs.io/",
|
||||
"export": {
|
||||
"exclude": [
|
||||
".travis.yml",
|
||||
"test/*"
|
||||
]
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"dependencies": {
|
||||
"uuid-common": "^1.0.2",
|
||||
"uuid-log": "^2.0.3"
|
||||
},
|
||||
"build": {
|
||||
"flags": "-Wall -Wextra",
|
||||
"libLDFMode": "chain+"
|
||||
}
|
||||
}
|
||||
430
lib/uuid-syslog/src/syslog.cpp
Normal file
430
lib/uuid-syslog/src/syslog.cpp
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* uuid-syslog - Syslog service
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "uuid/syslog.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#ifndef UUID_SYSLOG_HAVE_GETTIMEOFDAY
|
||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||
// time() does not return UTC on the ESP8266: https://github.com/esp8266/Arduino/issues/4637
|
||||
#define UUID_SYSLOG_HAVE_GETTIMEOFDAY 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UUID_SYSLOG_HAVE_GETTIMEOFDAY
|
||||
#define UUID_SYSLOG_HAVE_GETTIMEOFDAY 0
|
||||
#endif
|
||||
|
||||
#ifndef UUID_SYSLOG_HAVE_IPADDRESS_TYPE
|
||||
#if defined(ARDUINO_ARCH_ESP8266)
|
||||
#define UUID_SYSLOG_HAVE_IPADDRESS_TYPE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UUID_SYSLOG_HAVE_IPADDRESS_TYPE
|
||||
#define UUID_SYSLOG_HAVE_IPADDRESS_TYPE 0
|
||||
#endif
|
||||
|
||||
#ifndef UUID_SYSLOG_ARP_CHECK
|
||||
#if defined(LWIP_VERSION_MAJOR) && defined(LWIP_IPV4) && LWIP_VERSION_MAJOR >= 2 && LWIP_IPV4
|
||||
#define UUID_SYSLOG_ARP_CHECK 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UUID_SYSLOG_ARP_CHECK
|
||||
#define UUID_SYSLOG_ARP_CHECK 0
|
||||
#endif
|
||||
|
||||
#ifndef UUID_SYSLOG_NDP_CHECK
|
||||
#if defined(LWIP_VERSION_MAJOR) && defined(LWIP_IPV6) && LWIP_VERSION_MAJOR >= 2 && LWIP_IPV6
|
||||
#define UUID_SYSLOG_NDP_CHECK 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UUID_SYSLOG_NDP_CHECK
|
||||
#define UUID_SYSLOG_NDP_CHECK 0
|
||||
#endif
|
||||
|
||||
#if UUID_SYSLOG_ARP_CHECK or UUID_SYSLOG_NDP_CHECK
|
||||
#include <lwip/netif.h>
|
||||
#endif
|
||||
#if UUID_SYSLOG_ARP_CHECK
|
||||
#include <lwip/ip4_addr.h>
|
||||
#include <lwip/etharp.h>
|
||||
#endif
|
||||
#if UUID_SYSLOG_NDP_CHECK
|
||||
#include <lwip/ip6_addr.h>
|
||||
#include <lwip/nd6.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <uuid/common.h>
|
||||
#include <uuid/log.h>
|
||||
|
||||
static const char __pstr__logger_name[] __attribute__((__aligned__(sizeof(int)))) PROGMEM = "syslog";
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace syslog {
|
||||
|
||||
uuid::log::Logger SyslogService::logger_{FPSTR(__pstr__logger_name), uuid::log::Facility::SYSLOG};
|
||||
bool SyslogService::QueuedLogMessage::time_good_ = false;
|
||||
|
||||
SyslogService::~SyslogService() {
|
||||
uuid::log::Logger::unregister_handler(this);
|
||||
}
|
||||
|
||||
void SyslogService::start() {
|
||||
uuid::log::Logger::register_handler(this, uuid::log::Level::ALL);
|
||||
}
|
||||
|
||||
uuid::log::Level SyslogService::log_level() const {
|
||||
return uuid::log::Logger::get_log_level(this);
|
||||
}
|
||||
|
||||
void SyslogService::remove_queued_messages(uuid::log::Level level) {
|
||||
unsigned long offset = 0;
|
||||
|
||||
for (auto it = log_messages_.begin(); it != log_messages_.end();) {
|
||||
if (it->content_->level > level) {
|
||||
offset++;
|
||||
it = log_messages_.erase(it);
|
||||
} else {
|
||||
it->id_ -= offset;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
log_message_id_ -= offset;
|
||||
}
|
||||
|
||||
void SyslogService::log_level(uuid::log::Level level) {
|
||||
if (!started_) {
|
||||
remove_queued_messages(level);
|
||||
}
|
||||
|
||||
static bool level_set = false;
|
||||
bool level_changed = !level_set || (level != log_level());
|
||||
level_set = true;
|
||||
|
||||
if (level_changed && level < uuid::log::Level::NOTICE) {
|
||||
logger_.info(F("Log level set to %S"), uuid::log::format_level_uppercase(level));
|
||||
}
|
||||
uuid::log::Logger::register_handler(this, level);
|
||||
if (level_changed && level >= uuid::log::Level::NOTICE) {
|
||||
logger_.info(F("Log level set to %S"), uuid::log::format_level_uppercase(level));
|
||||
}
|
||||
}
|
||||
|
||||
size_t SyslogService::maximum_log_messages() const {
|
||||
return maximum_log_messages_;
|
||||
}
|
||||
|
||||
void SyslogService::maximum_log_messages(size_t count) {
|
||||
maximum_log_messages_ = std::max((size_t)1, count);
|
||||
|
||||
while (log_messages_.size() > maximum_log_messages_) {
|
||||
log_messages_.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<IPAddress, uint16_t> SyslogService::destination() const {
|
||||
return std::make_pair(host_, port_);
|
||||
}
|
||||
|
||||
void SyslogService::destination(IPAddress host, uint16_t port) {
|
||||
host_ = host;
|
||||
port_ = port;
|
||||
|
||||
if ((uint32_t)host_ == (uint32_t)0) {
|
||||
started_ = false;
|
||||
remove_queued_messages(log_level());
|
||||
}
|
||||
}
|
||||
|
||||
std::string SyslogService::hostname() const {
|
||||
return hostname_;
|
||||
}
|
||||
|
||||
void SyslogService::hostname(std::string hostname) {
|
||||
if (hostname.empty() || hostname.find(' ') != std::string::npos) {
|
||||
hostname_ = '-';
|
||||
} else {
|
||||
hostname_ = std::move(hostname);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long SyslogService::mark_interval() const {
|
||||
return mark_interval_ / 1000;
|
||||
}
|
||||
|
||||
void SyslogService::mark_interval(unsigned long interval) {
|
||||
mark_interval_ = (uint64_t)interval * 1000;
|
||||
}
|
||||
|
||||
SyslogService::QueuedLogMessage::QueuedLogMessage(unsigned long id, std::shared_ptr<uuid::log::Message> && content)
|
||||
: id_(id)
|
||||
, content_(std::move(content)) {
|
||||
if (time_good_ || WiFi.status() == WL_CONNECTED) {
|
||||
#if UUID_SYSLOG_HAVE_GETTIMEOFDAY
|
||||
if (gettimeofday(&time_, nullptr) != 0) {
|
||||
time_.tv_sec = (time_t)-1;
|
||||
}
|
||||
#else
|
||||
time_.tv_sec = time(nullptr);
|
||||
time_.tv_usec = 0;
|
||||
#endif
|
||||
|
||||
if (time_.tv_sec >= 0 && time_.tv_sec < 18140 * 86400) {
|
||||
time_.tv_sec = (time_t)-1;
|
||||
}
|
||||
|
||||
if (time_.tv_sec != (time_t)-1) {
|
||||
time_good_ = true;
|
||||
}
|
||||
} else {
|
||||
time_.tv_sec = (time_t)-1;
|
||||
}
|
||||
}
|
||||
|
||||
void SyslogService::operator<<(std::shared_ptr<uuid::log::Message> message) {
|
||||
if (log_messages_.size() >= maximum_log_messages_) {
|
||||
log_messages_overflow_ = true;
|
||||
log_messages_.pop_front();
|
||||
}
|
||||
|
||||
log_messages_.emplace_back(log_message_id_++, std::move(message));
|
||||
}
|
||||
|
||||
void SyslogService::loop() {
|
||||
while (!log_messages_.empty() && can_transmit()) {
|
||||
auto message = log_messages_.front();
|
||||
|
||||
started_ = true;
|
||||
log_messages_overflow_ = false;
|
||||
auto ok = transmit(message);
|
||||
if (ok) {
|
||||
// The transmit() may have called yield() allowing
|
||||
// other messages to have been added to the queue.
|
||||
if (!log_messages_overflow_) {
|
||||
log_messages_.pop_front();
|
||||
}
|
||||
last_message_ = uuid::get_uptime_ms();
|
||||
}
|
||||
|
||||
::yield();
|
||||
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (started_ && mark_interval_ != 0 && log_messages_.empty()) {
|
||||
if (uuid::get_uptime_ms() - last_message_ >= mark_interval_) {
|
||||
// This is generated manually because the log level may not
|
||||
// be high enough to receive INFO messages.
|
||||
operator<<(std::make_shared<uuid::log::Message>(uuid::get_uptime_ms(),
|
||||
uuid::log::Level::INFO,
|
||||
uuid::log::Facility::SYSLOG,
|
||||
reinterpret_cast<const __FlashStringHelper *>(__pstr__logger_name),
|
||||
uuid::read_flash_string(F("-- MARK --"))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SyslogService::can_transmit() {
|
||||
#if UUID_SYSLOG_HAVE_IPADDRESS_TYPE
|
||||
if (host_.isV4() && (uint32_t)host_ == (uint32_t)0) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if ((uint32_t)host_ == (uint32_t)0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint64_t now = uuid::get_uptime_ms();
|
||||
uint64_t message_delay = 100;
|
||||
|
||||
#if UUID_SYSLOG_ARP_CHECK
|
||||
#if UUID_SYSLOG_HAVE_IPADDRESS_TYPE
|
||||
if (host_.isV4())
|
||||
#endif
|
||||
{
|
||||
message_delay = 10;
|
||||
}
|
||||
#endif
|
||||
#if UUID_SYSLOG_NDP_CHECK && UUID_SYSLOG_HAVE_IPADDRESS_TYPE
|
||||
if (host_.isV6()) {
|
||||
message_delay = 10;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (now < last_transmit_ || now - last_transmit_ < message_delay) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if UUID_SYSLOG_ARP_CHECK
|
||||
#if UUID_SYSLOG_HAVE_IPADDRESS_TYPE
|
||||
if (host_.isV4())
|
||||
#endif
|
||||
{
|
||||
ip4_addr_t ipaddr;
|
||||
|
||||
ip4_addr_set_u32(&ipaddr, (uint32_t)host_);
|
||||
|
||||
if (!ip4_addr_isloopback(&ipaddr) && !ip4_addr_ismulticast(&ipaddr) && !ip4_addr_isbroadcast(&ipaddr, netif_default)) {
|
||||
struct eth_addr * eth_ret = nullptr;
|
||||
const ip4_addr_t * ip_ret = nullptr;
|
||||
|
||||
if (!ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif_default), netif_ip4_netmask(netif_default))) {
|
||||
// Replace addresses outside the network with the gateway address
|
||||
const ip4_addr_t * gw_addr = netif_ip4_gw(netif_default);
|
||||
|
||||
if (gw_addr != nullptr) {
|
||||
ipaddr = *gw_addr;
|
||||
}
|
||||
}
|
||||
|
||||
if (etharp_find_addr(netif_default, &ipaddr, ð_ret, &ip_ret) == -1) {
|
||||
etharp_query(netif_default, &ipaddr, NULL);
|
||||
// Avoid querying lwIP again for 1 second
|
||||
last_transmit_ = uuid::get_uptime_ms() + (uint64_t)1000 - message_delay;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if UUID_SYSLOG_NDP_CHECK && UUID_SYSLOG_HAVE_IPADDRESS_TYPE
|
||||
if (host_.isV6()) {
|
||||
ip6_addr_t ip6addr;
|
||||
|
||||
IP6_ADDR(&ip6addr, host_.raw6()[0], host_.raw6()[1], host_.raw6()[2], host_.raw6()[3]);
|
||||
ip6_addr_assign_zone(&ip6addr, IP6_UNICAST, netif_default);
|
||||
|
||||
if (!ip6_addr_isloopback(&ip6addr) && !ip6_addr_ismulticast(&ip6addr)) {
|
||||
// Don't send to a scoped address until we have a valid address of the same type
|
||||
bool have_address = false;
|
||||
const u8_t * hwaddr = nullptr;
|
||||
|
||||
for (size_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
if (ip6_addr_isvalid(netif_ip6_addr_state(netif_default, i))) {
|
||||
if (ip6_addr_isglobal(&ip6addr)) {
|
||||
if (ip6_addr_isglobal(netif_ip6_addr(netif_default, i))) {
|
||||
have_address = true;
|
||||
break;
|
||||
}
|
||||
} else if (ip6_addr_issitelocal(&ip6addr)) {
|
||||
if (ip6_addr_issitelocal(netif_ip6_addr(netif_default, i))) {
|
||||
have_address = true;
|
||||
break;
|
||||
}
|
||||
} else if (ip6_addr_isuniquelocal(&ip6addr)) {
|
||||
if (ip6_addr_isuniquelocal(netif_ip6_addr(netif_default, i))) {
|
||||
have_address = true;
|
||||
break;
|
||||
}
|
||||
} else if (ip6_addr_islinklocal(&ip6addr)) {
|
||||
if (ip6_addr_islinklocal(netif_ip6_addr(netif_default, i))) {
|
||||
have_address = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
have_address = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_address) {
|
||||
// Avoid checking lwIP again for 1 second
|
||||
last_transmit_ = uuid::get_uptime_ms() + (uint64_t)1000 - message_delay;
|
||||
|
||||
return false;
|
||||
} else if (nd6_get_next_hop_addr_or_queue(netif_default, NULL, &ip6addr, &hwaddr) != ERR_OK) {
|
||||
// Avoid querying lwIP again for 1 second
|
||||
last_transmit_ = uuid::get_uptime_ms() + (uint64_t)1000 - message_delay;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SyslogService::transmit(const QueuedLogMessage & message) {
|
||||
struct tm tm;
|
||||
|
||||
tm.tm_year = 0;
|
||||
if (message.time_.tv_sec != (time_t)-1) {
|
||||
gmtime_r(&message.time_.tv_sec, &tm);
|
||||
}
|
||||
|
||||
if (udp_.beginPacket(host_, port_) != 1) {
|
||||
last_transmit_ = uuid::get_uptime_ms();
|
||||
return false;
|
||||
}
|
||||
udp_.printf_P(PSTR("<%u>1 "), ((unsigned int)message.content_->facility * 8) + std::min(7U, (unsigned int)message.content_->level));
|
||||
if (tm.tm_year != 0) {
|
||||
udp_.printf_P(PSTR("%04u-%02u-%02uT%02u:%02u:%02u.%06luZ"),
|
||||
tm.tm_year + 1900,
|
||||
tm.tm_mon + 1,
|
||||
tm.tm_mday,
|
||||
tm.tm_hour,
|
||||
tm.tm_min,
|
||||
tm.tm_sec,
|
||||
(unsigned long)message.time_.tv_usec);
|
||||
} else {
|
||||
udp_.print('-');
|
||||
}
|
||||
udp_.printf_P(PSTR(" %s - - - - \xEF\xBB\xBF"), hostname_.c_str());
|
||||
udp_.print(uuid::log::format_timestamp_ms(message.content_->uptime_ms, 3).c_str());
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
udp_.printf_P(PSTR(" %c %lu: [%S] "), uuid::log::format_level_char(message.content_->level), message.id_, message.content_->name);
|
||||
#pragma GCC diagnostic pop
|
||||
udp_.print(message.content_->text.c_str());
|
||||
bool ok = (udp_.endPacket() == 1);
|
||||
|
||||
last_transmit_ = uuid::get_uptime_ms();
|
||||
return ok;
|
||||
}
|
||||
|
||||
} // namespace syslog
|
||||
|
||||
} // namespace uuid
|
||||
263
lib/uuid-syslog/src/uuid/syslog.h
Normal file
263
lib/uuid-syslog/src/uuid/syslog.h
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* uuid-syslog - Syslog service
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UUID_SYSLOG_H_
|
||||
#define UUID_SYSLOG_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
#include <WiFiUdp.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
/**
|
||||
* Syslog service.
|
||||
*
|
||||
* - <a href="https://github.com/nomis/mcu-uuid-syslog/">Git Repository</a>
|
||||
* - <a href="https://mcu-uuid-syslog.readthedocs.io/">Documentation</a>
|
||||
*/
|
||||
namespace syslog {
|
||||
|
||||
/**
|
||||
* Log handler for sending messages to a syslog server.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class SyslogService : public uuid::log::Handler {
|
||||
public:
|
||||
static constexpr size_t MAX_LOG_MESSAGES = 50; /*!< Maximum number of log messages to buffer before they are output. @since 1.0.0 */
|
||||
static constexpr uint16_t DEFAULT_PORT = 514; /*!< Default UDP port to send messages to. @since 1.0.0 */
|
||||
|
||||
/**
|
||||
* Create a new syslog service log handler.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
SyslogService() = default;
|
||||
|
||||
~SyslogService();
|
||||
|
||||
/**
|
||||
* Register the log handler with the logging framework.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Get the current log level.
|
||||
*
|
||||
* This only affects newly received log messages, not messages that
|
||||
* have already been queued.
|
||||
*
|
||||
* @return The current log level.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
uuid::log::Level log_level() const;
|
||||
/**
|
||||
* Set the current log level.
|
||||
*
|
||||
* Unless this is the first time the log level is being set, this
|
||||
* only affects newly received log messages, not messages that have
|
||||
* already been queued.
|
||||
*
|
||||
* @param[in] level Minimum log level that will be sent to the
|
||||
* syslog server.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
void log_level(uuid::log::Level level);
|
||||
|
||||
/**
|
||||
* Get the maximum number of queued log messages.
|
||||
*
|
||||
* @return The maximum number of queued log messages.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
size_t maximum_log_messages() const;
|
||||
/**
|
||||
* Set the maximum number of queued log messages.
|
||||
*
|
||||
* Defaults to SyslogService::MAX_LOG_MESSAGES.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
void maximum_log_messages(size_t count);
|
||||
|
||||
/**
|
||||
* Get the server to send messages to.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return IP address and UDP port of the syslog server.
|
||||
*/
|
||||
std::pair<IPAddress, uint16_t> destination() const;
|
||||
/**
|
||||
* Set the server to send messages to.
|
||||
*
|
||||
* To disable sending messages, set the host to `0.0.0.0` and the
|
||||
* log level to uuid::log::Level::OFF (otherwise they will be
|
||||
* queued but not sent).
|
||||
*
|
||||
* @param[in] host IP address of the syslog server.
|
||||
* @param[in] port UDP port to send messages to.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
void destination(IPAddress host, uint16_t port = DEFAULT_PORT);
|
||||
|
||||
/**
|
||||
* Get local hostname.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return Hostname of this device.
|
||||
*/
|
||||
std::string hostname() const;
|
||||
/**
|
||||
* Set local hostname.
|
||||
*
|
||||
* @param[in] hostname Hostname of this device.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
void hostname(std::string hostname);
|
||||
|
||||
/**
|
||||
* Get mark interval.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @return Mark interval in seconds (0 = disable).
|
||||
*/
|
||||
unsigned long mark_interval() const;
|
||||
/**
|
||||
* Set mark interval.
|
||||
*
|
||||
* When no messages have been sent for this period of time, a
|
||||
* `-- MARK --` message will be generated automatically.
|
||||
*
|
||||
* @param[in] interval Mark interval in seconds (0 = disable).
|
||||
* @since 2.0.0
|
||||
*/
|
||||
void mark_interval(unsigned long interval);
|
||||
|
||||
/**
|
||||
* Dispatch queued log messages.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void loop();
|
||||
|
||||
/**
|
||||
* Add a new log message.
|
||||
*
|
||||
* This will be put in a queue for output at the next loop()
|
||||
* process. The queue has a maximum size of
|
||||
* get_maximum_log_messages() and will discard the oldest message
|
||||
* first.
|
||||
*
|
||||
* @param[in] message New log message, shared by all handlers.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
virtual void operator<<(std::shared_ptr<uuid::log::Message> message);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Log message that has been queued.
|
||||
*
|
||||
* Contains an identifier sequence to indicate when log messages
|
||||
* could not be output because the queue discarded one or more
|
||||
* messages.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class QueuedLogMessage {
|
||||
public:
|
||||
/**
|
||||
* Create a queued log message.
|
||||
*
|
||||
* @param[in] id Identifier to use for the log message on the queue.
|
||||
* @param[in] content Log message content.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
QueuedLogMessage(unsigned long id, std::shared_ptr<uuid::log::Message> && content);
|
||||
~QueuedLogMessage() = default;
|
||||
|
||||
unsigned long id_; /*!< Sequential identifier for this log message. @since 1.0.0 */
|
||||
struct timeval time_; /*!< Time message was received. @since 1.0.0 */
|
||||
const std::shared_ptr<const uuid::log::Message> content_; /*!< Log message content. @since 1.0.0 */
|
||||
|
||||
private:
|
||||
static bool time_good_; /*!< System time appears to be valid. @since 1.0.0 */
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove messages that were queued before the log level was set.
|
||||
*
|
||||
* @param[in] level New log level
|
||||
* @since 1.0.0
|
||||
*/
|
||||
void remove_queued_messages(uuid::log::Level level);
|
||||
|
||||
/**
|
||||
* Check if it is possible to transmit to the server.
|
||||
*
|
||||
* @return True if it is safe to transmit a message to the server,
|
||||
* otherwise false.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
bool can_transmit();
|
||||
|
||||
/**
|
||||
* Attempt to transmit one message to the server.
|
||||
*
|
||||
* @param[in] message Log message to be sent.
|
||||
* @return True if the message was successfully set, otherwise
|
||||
* false.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
bool transmit(const QueuedLogMessage & message);
|
||||
|
||||
static uuid::log::Logger logger_; /*!< uuid::log::Logger instance for syslog services. @since 1.0.0 */
|
||||
|
||||
bool started_ = false; /*!< Flag to indicate that messages have started being transmitted. @since 1.0.0 */
|
||||
WiFiUDP udp_; /*!< UDP client. @since 1.0.0 */
|
||||
IPAddress host_; /*!< Host to send messages to. @since 1.0.0 */
|
||||
uint16_t port_ = DEFAULT_PORT; /*!< Port to send messages to. @since 1.0.0 */
|
||||
uint64_t last_transmit_ = 0; /*!< Last transmit time. @since 1.0.0 */
|
||||
std::string hostname_{'-'}; /*!< Local hostname. @since 1.0.0 */
|
||||
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; /*!< Maximum number of log messages to buffer before they are output. @since 1.0.0 */
|
||||
unsigned long log_message_id_ = 0; /*!< The next identifier to use for queued log messages. @since 1.0.0 */
|
||||
std::list<QueuedLogMessage> log_messages_; /*!< Queued log messages, in the order they were received. @since 1.0.0 */
|
||||
std::atomic<bool> log_messages_overflow_{false}; /*!< Check if log messages have overflowed the buffer. @since 1.0.0 */
|
||||
uint64_t mark_interval_ = 0; /*!< Mark interval in milliseconds. @since 2.0.0 */
|
||||
uint64_t last_message_ = 0; /*!< Last message/mark time. @since 2.0.0 */
|
||||
};
|
||||
|
||||
} // namespace syslog
|
||||
|
||||
} // namespace uuid
|
||||
|
||||
#endif
|
||||
674
lib/uuid-telnet/COPYING
Normal file
674
lib/uuid-telnet/COPYING
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
24
lib/uuid-telnet/README.rst
Normal file
24
lib/uuid-telnet/README.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
mcu-uuid-telnet |Build Status|
|
||||
==============================
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Microcontroller telnet service
|
||||
|
||||
Purpose
|
||||
-------
|
||||
|
||||
Provides access to a console shell as a telnet server (using the
|
||||
`RFC 854 protocol <https://tools.ietf.org/html/rfc854>`_).
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
`Read the documentation <https://mcu-uuid-telnet.readthedocs.io/>`_
|
||||
generated from the docs_ directory.
|
||||
|
||||
.. _docs: docs/
|
||||
|
||||
.. |Build Status| image:: https://travis-ci.org/nomis/mcu-uuid-telnet.svg?branch=master
|
||||
:target: https://travis-ci.org/nomis/mcu-uuid-telnet
|
||||
36
lib/uuid-telnet/library.json
Normal file
36
lib/uuid-telnet/library.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "uuid-telnet",
|
||||
"description": "Telnet service",
|
||||
"keywords": "communication,telnet",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Simon Arlott",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nomis/mcu-uuid-telnet.git"
|
||||
},
|
||||
"version": "0.1.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"homepage": "https://mcu-uuid-telnet.readthedocs.io/",
|
||||
"export": {
|
||||
"exclude": [
|
||||
".travis.yml",
|
||||
"test/*"
|
||||
]
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"dependencies": {
|
||||
"uuid-common": "^1.1.0",
|
||||
"uuid-log": "^2.1.1",
|
||||
"uuid-console": "^0.7.0"
|
||||
},
|
||||
"build": {
|
||||
"flags": "-Wall -Wextra",
|
||||
"libLDFMode": "chain+"
|
||||
}
|
||||
}
|
||||
358
lib/uuid-telnet/src/stream.cpp
Normal file
358
lib/uuid-telnet/src/stream.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* uuid-telnet - Telnet service
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "uuid/telnet.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace telnet {
|
||||
|
||||
TelnetStream::TelnetStream(WiFiClient &client)
|
||||
: client_(client) {
|
||||
output_buffer_.reserve(BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void TelnetStream::start() {
|
||||
raw_write({
|
||||
IAC, WILL, OPT_ECHO,
|
||||
IAC, WILL, OPT_BINARY,
|
||||
IAC, WILL, OPT_SGA,
|
||||
IAC, DONT, OPT_ECHO,
|
||||
IAC, DO, OPT_BINARY,
|
||||
IAC, DO, OPT_SGA
|
||||
});
|
||||
}
|
||||
|
||||
int TelnetStream::available() {
|
||||
if (peek() == -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int TelnetStream::read() {
|
||||
if (peek_ != -1) {
|
||||
int data = peek_;
|
||||
peek_ = -1;
|
||||
return data;
|
||||
}
|
||||
|
||||
buffer_flush();
|
||||
|
||||
restart:
|
||||
int data = raw_read();
|
||||
|
||||
if (data == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char c = data;
|
||||
|
||||
if (sub_negotiation_) {
|
||||
if (previous_raw_in_ == IAC) {
|
||||
switch (c) {
|
||||
case SE:
|
||||
sub_negotiation_ = false;
|
||||
previous_raw_in_ = 0;
|
||||
goto restart;
|
||||
|
||||
case IAC:
|
||||
previous_raw_in_ = 0;
|
||||
goto restart;
|
||||
}
|
||||
} else {
|
||||
switch (c) {
|
||||
case IAC:
|
||||
previous_raw_in_ = c;
|
||||
goto restart;
|
||||
|
||||
default:
|
||||
previous_raw_in_ = 0;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (previous_raw_in_ == IAC) {
|
||||
switch (c) {
|
||||
case IP:
|
||||
// Interrupt (^C)
|
||||
previous_raw_in_ = 0;
|
||||
c = '\x03';
|
||||
break;
|
||||
|
||||
case EC:
|
||||
// Backspace (^H)
|
||||
previous_raw_in_ = 0;
|
||||
c = '\x08';
|
||||
break;
|
||||
|
||||
case EL:
|
||||
// Delete line (^U)
|
||||
previous_raw_in_ = 0;
|
||||
c = '\x15';
|
||||
break;
|
||||
|
||||
case IAC:
|
||||
previous_raw_in_ = 0;
|
||||
break;
|
||||
|
||||
case SB:
|
||||
case WILL:
|
||||
case WONT:
|
||||
case DO:
|
||||
case DONT:
|
||||
previous_raw_in_ = c;
|
||||
goto restart;
|
||||
|
||||
case SE:
|
||||
case DM:
|
||||
case BRK:
|
||||
case AO:
|
||||
case AYT:
|
||||
case GA:
|
||||
case NOP:
|
||||
default:
|
||||
previous_raw_in_ = 0;
|
||||
goto restart;
|
||||
}
|
||||
} else if (previous_raw_in_ == SB) {
|
||||
sub_negotiation_ = true;
|
||||
previous_raw_in_ = 0;
|
||||
goto restart;
|
||||
} else if (previous_raw_in_ == WILL || previous_raw_in_ == WONT) {
|
||||
switch (c) {
|
||||
case OPT_ECHO:
|
||||
// Don't do these
|
||||
raw_write({IAC, DONT, c});
|
||||
break;
|
||||
|
||||
case OPT_BINARY:
|
||||
case OPT_SGA:
|
||||
// Do these
|
||||
raw_write({IAC, DO, c});
|
||||
break;
|
||||
|
||||
default:
|
||||
// Don't do anything else
|
||||
raw_write({IAC, DONT, c});
|
||||
break;
|
||||
}
|
||||
|
||||
previous_raw_in_ = 0;
|
||||
goto restart;
|
||||
} else if (previous_raw_in_ == DO) {
|
||||
switch (c) {
|
||||
case OPT_ECHO:
|
||||
case OPT_BINARY:
|
||||
case OPT_SGA:
|
||||
// These are always enabled
|
||||
break;
|
||||
|
||||
default:
|
||||
// Refuse to do anything else
|
||||
raw_write({IAC, WONT, c});
|
||||
break;
|
||||
}
|
||||
|
||||
previous_raw_in_ = 0;
|
||||
goto restart;
|
||||
} else if (previous_raw_in_ == DONT) {
|
||||
switch (c) {
|
||||
case OPT_ECHO:
|
||||
case OPT_BINARY:
|
||||
case OPT_SGA:
|
||||
// Insist that we do these
|
||||
raw_write({IAC, WILL, c});
|
||||
break;
|
||||
|
||||
default:
|
||||
// Everything else is always disabled
|
||||
break;
|
||||
}
|
||||
|
||||
previous_raw_in_ = 0;
|
||||
goto restart;
|
||||
} else {
|
||||
switch (c) {
|
||||
case IAC:
|
||||
previous_raw_in_ = c;
|
||||
goto restart;
|
||||
|
||||
default:
|
||||
previous_raw_in_ = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (previous_in_ == CR) {
|
||||
if (c == NUL) {
|
||||
previous_in_ = 0;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
previous_in_ = c;
|
||||
return c;
|
||||
}
|
||||
|
||||
int TelnetStream::peek() {
|
||||
buffer_flush();
|
||||
|
||||
// It's too complicated to implement this by calling peek()
|
||||
// on the original stream, especially if the original stream
|
||||
// doesn't actually support peeking.
|
||||
if (peek_ == -1) {
|
||||
peek_ = read();
|
||||
}
|
||||
|
||||
return peek_;
|
||||
}
|
||||
|
||||
size_t TelnetStream::write(uint8_t data) {
|
||||
if (previous_out_ == CR && data != LF) {
|
||||
previous_out_ = data;
|
||||
|
||||
if (raw_write({NUL, data}) != 2) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
previous_out_ = data;
|
||||
}
|
||||
|
||||
if (data == IAC) {
|
||||
if (raw_write({IAC, IAC}) != 2) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (raw_write(data) != 1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t TelnetStream::write(const uint8_t *buffer, size_t size) {
|
||||
std::vector<unsigned char> data;
|
||||
data.reserve(size);
|
||||
|
||||
while (size-- > 0) {
|
||||
unsigned char c = *buffer++;
|
||||
|
||||
if (previous_out_ == CR && c != LF) {
|
||||
data.push_back((unsigned char)NUL);
|
||||
}
|
||||
|
||||
if (c == IAC) {
|
||||
data.push_back((unsigned char)IAC);
|
||||
}
|
||||
|
||||
previous_out_ = c;
|
||||
data.push_back(c);
|
||||
}
|
||||
|
||||
size_t len = raw_write(data);
|
||||
if (len < size) {
|
||||
len = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void TelnetStream::flush() {
|
||||
// This is a pure virtual function in Arduino's Stream class, which
|
||||
// makes no sense because that class is for input and this is an
|
||||
// output function. Later versions move it to Print as an empty
|
||||
// virtual function so this is here for backward compatibility.
|
||||
}
|
||||
|
||||
int TelnetStream::raw_available() {
|
||||
return client_.available();
|
||||
}
|
||||
|
||||
int TelnetStream::raw_read() {
|
||||
return client_.read();
|
||||
}
|
||||
|
||||
void TelnetStream::buffer_flush() {
|
||||
if (!output_buffer_.empty()) {
|
||||
size_t len = client_.write(reinterpret_cast<const unsigned char*>(output_buffer_.data()), output_buffer_.size());
|
||||
if (len != output_buffer_.size()) {
|
||||
client_.stop();
|
||||
}
|
||||
output_buffer_.clear();
|
||||
output_buffer_.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
||||
size_t TelnetStream::raw_write(unsigned char data) {
|
||||
output_buffer_.push_back(data);
|
||||
|
||||
if (output_buffer_.size() >= BUFFER_SIZE) {
|
||||
buffer_flush();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t TelnetStream::raw_write(const std::vector<unsigned char> &data) {
|
||||
return raw_write(reinterpret_cast<const unsigned char*>(data.data()), data.size());
|
||||
}
|
||||
|
||||
size_t TelnetStream::raw_write(const uint8_t *buffer, size_t size) {
|
||||
size_t offset = 0;
|
||||
size_t remaining = size;
|
||||
|
||||
if (!output_buffer_.empty()) {
|
||||
// Fill the rest of the buffer
|
||||
size_t block = std::min(remaining, BUFFER_SIZE - output_buffer_.size());
|
||||
|
||||
output_buffer_.insert(output_buffer_.end(), buffer, buffer + block);
|
||||
offset += block;
|
||||
remaining -= block;
|
||||
|
||||
if (output_buffer_.size() >= BUFFER_SIZE) {
|
||||
buffer_flush();
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining >= BUFFER_SIZE) {
|
||||
// Output directly if it won't fit in the buffer
|
||||
size_t len = client_.write(buffer + offset, remaining);
|
||||
if (len != remaining) {
|
||||
client_.stop();
|
||||
return offset + len;
|
||||
}
|
||||
} else if (remaining > 0) {
|
||||
// Put the rest in the buffer
|
||||
output_buffer_.insert(output_buffer_.end(), buffer + offset, buffer + offset + remaining);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
} // namespace telnet
|
||||
|
||||
} // namespace uuid
|
||||
237
lib/uuid-telnet/src/telnet.cpp
Normal file
237
lib/uuid-telnet/src/telnet.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* uuid-telnet - Telnet service
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "uuid/telnet.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#elif defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <uuid/common.h>
|
||||
#include <uuid/log.h>
|
||||
|
||||
#ifndef UUID_TELNET_HAVE_WIFICLIENT_REMOTE
|
||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||
#define UUID_TELNET_HAVE_WIFICLIENT_REMOTE 1
|
||||
#else
|
||||
#define UUID_TELNET_HAVE_WIFICLIENT_REMOTE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UUID_TELNET_HAVE_WIFICLIENT_NODELAY
|
||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||
#define UUID_TELNET_HAVE_WIFICLIENT_NODELAY 1
|
||||
#else
|
||||
#define UUID_TELNET_HAVE_WIFICLIENT_NODELAY 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UUID_TELNET_HAVE_WIFICLIENT_KEEPALIVE
|
||||
#if defined(ARDUINO_ARCH_ESP8266)
|
||||
#define UUID_TELNET_HAVE_WIFICLIENT_KEEPALIVE 1
|
||||
#else
|
||||
#define UUID_TELNET_HAVE_WIFICLIENT_KEEPALIVE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const char __pstr__logger_name[] __attribute__((__aligned__(sizeof(int)))) PROGMEM = "telnet";
|
||||
|
||||
namespace uuid {
|
||||
|
||||
namespace telnet {
|
||||
|
||||
uuid::log::Logger TelnetService::logger_{FPSTR(__pstr__logger_name), uuid::log::Facility::DAEMON};
|
||||
|
||||
TelnetService::TelnetService(std::shared_ptr<uuid::console::Commands> commands, unsigned int context, unsigned int flags)
|
||||
: TelnetService(DEFAULT_PORT, commands, context, flags) {
|
||||
}
|
||||
|
||||
TelnetService::TelnetService(uint16_t port, std::shared_ptr<uuid::console::Commands> commands, unsigned int context, unsigned int flags)
|
||||
: TelnetService(port,
|
||||
[commands, context, flags](Stream & stream, const IPAddress & addr __attribute__((unused)), uint16_t port __attribute__((unused)))
|
||||
-> std::shared_ptr<uuid::console::Shell> { return std::make_shared<uuid::console::StreamConsole>(commands, stream, context, flags); }) {
|
||||
}
|
||||
|
||||
TelnetService::TelnetService(shell_factory_function shell_factory)
|
||||
: TelnetService(DEFAULT_PORT, shell_factory) {
|
||||
}
|
||||
|
||||
TelnetService::TelnetService(uint16_t port, shell_factory_function shell_factory)
|
||||
: server_(port)
|
||||
, shell_factory_(shell_factory) {
|
||||
}
|
||||
|
||||
void TelnetService::start() {
|
||||
server_.begin();
|
||||
}
|
||||
|
||||
void TelnetService::close_all() {
|
||||
while (!connections_.empty()) {
|
||||
connections_.front().stop();
|
||||
connections_.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void TelnetService::stop() {
|
||||
server_.stop();
|
||||
}
|
||||
|
||||
size_t TelnetService::maximum_connections() const {
|
||||
return maximum_connections_;
|
||||
}
|
||||
|
||||
void TelnetService::maximum_connections(size_t count) {
|
||||
maximum_connections_ = std::max((size_t)1, count);
|
||||
|
||||
while (connections_.size() > maximum_connections_) {
|
||||
for (auto it = connections_.begin(); it != connections_.end();) {
|
||||
if (it->active()) {
|
||||
it->stop();
|
||||
it = connections_.erase(it);
|
||||
break;
|
||||
} else {
|
||||
it = connections_.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long TelnetService::initial_idle_timeout() const {
|
||||
return initial_idle_timeout_;
|
||||
}
|
||||
|
||||
void TelnetService::initial_idle_timeout(unsigned long timeout) {
|
||||
initial_idle_timeout_ = timeout;
|
||||
}
|
||||
|
||||
unsigned long TelnetService::default_write_timeout() const {
|
||||
return write_timeout_;
|
||||
}
|
||||
|
||||
void TelnetService::default_write_timeout(unsigned long timeout) {
|
||||
write_timeout_ = timeout;
|
||||
}
|
||||
|
||||
void TelnetService::loop() {
|
||||
for (auto it = connections_.begin(); it != connections_.end();) {
|
||||
if (!it->loop()) {
|
||||
it = connections_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
WiFiClient client = server_.available();
|
||||
if (client) {
|
||||
if (connections_.size() >= maximum_connections_) {
|
||||
#if UUID_TELNET_HAVE_WIFICLIENT_REMOTE
|
||||
logger_.info(F("New connection from [%s]:%u rejected (connection limit reached)"),
|
||||
uuid::printable_to_string(client.remoteIP()).c_str(),
|
||||
client.remotePort());
|
||||
#else
|
||||
logger_.info(F("New connection rejected (connection limit reached)"));
|
||||
#endif
|
||||
client.println(F("Maximum connection limit reached"));
|
||||
client.stop();
|
||||
} else {
|
||||
#if UUID_TELNET_HAVE_WIFICLIENT_REMOTE
|
||||
logger_.info(F("New connection from [%s]:%u accepted"), uuid::printable_to_string(client.remoteIP()).c_str(), client.remotePort());
|
||||
#endif
|
||||
connections_.emplace_back(shell_factory_, std::move(client), initial_idle_timeout_, write_timeout_);
|
||||
#if !(UUID_TELNET_HAVE_WIFICLIENT_REMOTE)
|
||||
logger_.info(F("New connection %p accepted"), &connections_.back());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TelnetService::Connection::Connection(shell_factory_function & shell_factory, WiFiClient && client, unsigned long idle_timeout, unsigned long write_timeout)
|
||||
: client_(std::move(client))
|
||||
, stream_(client_) {
|
||||
#if UUID_TELNET_HAVE_WIFICLIENT_REMOTE
|
||||
// These have to be copied because they're not accessible on closed connections
|
||||
addr_ = client_.remoteIP();
|
||||
port_ = client_.remotePort();
|
||||
#else
|
||||
port_ = 0;
|
||||
#endif
|
||||
|
||||
#if UUID_TELNET_HAVE_WIFICLIENT_NODELAY
|
||||
client_.setNoDelay(true);
|
||||
#endif
|
||||
|
||||
#if UUID_TELNET_HAVE_WIFICLIENT_KEEPALIVE
|
||||
// Disconnect after 30 seconds without a response
|
||||
client_.keepAlive(5, 5, 5);
|
||||
#endif
|
||||
|
||||
if (write_timeout > 0) {
|
||||
client_.setTimeout(write_timeout);
|
||||
}
|
||||
|
||||
stream_.start();
|
||||
|
||||
if (client_.connected()) {
|
||||
std::shared_ptr<uuid::console::Shell> shell = shell_factory(stream_, addr_, port_);
|
||||
shell->idle_timeout(idle_timeout);
|
||||
shell->start();
|
||||
shell_ = shell;
|
||||
} else {
|
||||
shell_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool TelnetService::Connection::active() {
|
||||
return shell_.use_count() > 1;
|
||||
}
|
||||
|
||||
bool TelnetService::Connection::loop() {
|
||||
if (active()) {
|
||||
if (!client_.connected()) {
|
||||
shell_->stop();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
#if UUID_TELNET_HAVE_WIFICLIENT_REMOTE
|
||||
logger_.info(F("Connection from [%s]:%u closed"), uuid::printable_to_string(addr_).c_str(), port_);
|
||||
#else
|
||||
logger_.info(F("Connection %p closed"), this);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void TelnetService::Connection::stop() {
|
||||
if (shell_) {
|
||||
shell_->stop();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace telnet
|
||||
|
||||
} // namespace uuid
|
||||
441
lib/uuid-telnet/src/uuid/telnet.h
Normal file
441
lib/uuid-telnet/src/uuid/telnet.h
Normal file
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* uuid-telnet - Telnet service
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UUID_TELNET_H_
|
||||
#define UUID_TELNET_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
# include <ESP8266WiFi.h>
|
||||
#else
|
||||
# include <WiFi.h>
|
||||
#endif
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <uuid/console.h>
|
||||
|
||||
namespace uuid {
|
||||
|
||||
/**
|
||||
* Telnet service.
|
||||
*
|
||||
* - <a href="https://github.com/nomis/mcu-uuid-telnet/">Git Repository</a>
|
||||
* - <a href="https://mcu-uuid-telnet.readthedocs.io/">Documentation</a>
|
||||
*/
|
||||
namespace telnet {
|
||||
|
||||
/**
|
||||
* Stream wrapper that performs telnet protocol handling, option
|
||||
* negotiation and output buffering.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
class TelnetStream: public ::Stream {
|
||||
public:
|
||||
/**
|
||||
* Create a new telnet stream wrapper.
|
||||
*
|
||||
* @param[in] client Client connection.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
explicit TelnetStream(WiFiClient &client);
|
||||
virtual ~TelnetStream() = default;
|
||||
|
||||
/**
|
||||
* Perform initial negotiation.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Check for available input.
|
||||
*
|
||||
* @return The number of bytes available to read.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
int available() override;
|
||||
/**
|
||||
* Read one byte from the available input.
|
||||
*
|
||||
* @return An unsigned char if input is available, otherwise -1.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
int read() override;
|
||||
/**
|
||||
* Read one byte from the available input without advancing to the
|
||||
* next one.
|
||||
*
|
||||
* @return An unsigned char if input is available, otherwise -1.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
int peek() override;
|
||||
/**
|
||||
* Write one byte to the output stream.
|
||||
*
|
||||
* Disconnect the client if the socket buffer is full.
|
||||
*
|
||||
* @param[in] data Data to be output.
|
||||
* @return The number of bytes that were output.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
size_t write(uint8_t data) override;
|
||||
/**
|
||||
* Write an array of bytes to the output stream.
|
||||
*
|
||||
* Disconnect the client if the socket buffer is full.
|
||||
*
|
||||
* @param[in] buffer Buffer to be output.
|
||||
* @param[in] size Length of the buffer.
|
||||
* @return The number of bytes that were output.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
size_t write(const uint8_t *buffer, size_t size) override;
|
||||
/**
|
||||
* Does nothing.
|
||||
*
|
||||
* This is a pure virtual function in Arduino's Stream class, which
|
||||
* makes no sense because that class is for input and this is an
|
||||
* output function. Later versions move it to Print as an empty
|
||||
* virtual function so this is here for backward compatibility.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void flush() override;
|
||||
|
||||
private:
|
||||
static constexpr const unsigned char NUL = 0; /*!< No operation. @since 0.1.0 */
|
||||
static constexpr const unsigned char BEL = 7; /*!< Produces an audible or visible signal. @since 0.1.0 */
|
||||
static constexpr const unsigned char BS = 8; /*!< Moves the print head one character position towards the left margin. @since 0.1.0 */
|
||||
static constexpr const unsigned char HT = 9; /*!< Moves the printer to the next horizontal tab stop. @since 0.1.0 */
|
||||
static constexpr const unsigned char LF = 10; /*!< Line Feed. @since 0.1.0 */
|
||||
static constexpr const unsigned char VT = 11; /*!< Moves the printer to the next vertical tab stop. @since 0.1.0 */
|
||||
static constexpr const unsigned char FF = 12; /*!< Moves the printer to the top of the next page, keeping the same horizontal position. @since 0.1.0 */
|
||||
static constexpr const unsigned char CR = 13; /*!< Carriage Return. @since 0.1.0 */
|
||||
static constexpr const unsigned char SE = 240; /*!< End of sub-negotiation parameters. @since 0.1.0 */
|
||||
static constexpr const unsigned char NOP = 241; /*!< No operation. @since 0.1.0 */
|
||||
static constexpr const unsigned char DM = 242; /*!< The data stream portion of a Synch. @since 0.1.0 */
|
||||
static constexpr const unsigned char BRK = 243; /*!< NVT character BRK. @since 0.1.0 */
|
||||
static constexpr const unsigned char IP = 244; /*!< Interrupt Process function. @since 0.1.0 */
|
||||
static constexpr const unsigned char AO = 245; /*!< Abort Output function. @since 0.1.0 */
|
||||
static constexpr const unsigned char AYT = 246; /*!< Are You There function. @since 0.1.0 */
|
||||
static constexpr const unsigned char EC = 247; /*!< Erase Character function. @since 0.1.0 */
|
||||
static constexpr const unsigned char EL = 248; /*!< Erase Line function. @since 0.1.0 */
|
||||
static constexpr const unsigned char GA = 249; /*!< Go Ahead signal. @since 0.1.0 */
|
||||
static constexpr const unsigned char SB = 250; /*!< Sub-negotiation of the indicated option. @since 0.1.0 */
|
||||
static constexpr const unsigned char WILL = 251; /*!< Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option. @since 0.1.0 */
|
||||
static constexpr const unsigned char WONT = 252; /*!< Indicates the refusal to perform, or continue performing, the indicated option. @since 0.1.0 */
|
||||
static constexpr const unsigned char DO = 253; /*!< Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option. @since 0.1.0 */
|
||||
static constexpr const unsigned char DONT = 254; /*!< Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option. @since 0.1.0 */
|
||||
static constexpr const unsigned char IAC = 255; /*!< Interpret As Command escape character. @since 0.1.0 */
|
||||
|
||||
static constexpr const unsigned char OPT_BINARY = 0; /*!< Binary (8-bit) transmission mode. (RFC 856). @since 0.1.0 */
|
||||
static constexpr const unsigned char OPT_ECHO = 1; /*!< Remote Echo (RFC 857). @since 0.1.0 */
|
||||
static constexpr const unsigned char OPT_SGA = 3; /*!< Suppress Go Ahead (RFC 858). @since 0.1.0 */
|
||||
|
||||
static constexpr const size_t BUFFER_SIZE = 536; /*!< Output buffer size. @since 0.1.0 */
|
||||
|
||||
TelnetStream(const TelnetStream&) = delete;
|
||||
TelnetStream& operator=(const TelnetStream&) = delete;
|
||||
|
||||
/**
|
||||
* Directly check for available input.
|
||||
*
|
||||
* @return The number of bytes available to read.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
int raw_available();
|
||||
/**
|
||||
* Read one byte directly from the available input.
|
||||
*
|
||||
* @return An unsigned char if input is available, otherwise -1.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
int raw_read();
|
||||
/**
|
||||
* Flush output stream buffer.
|
||||
*
|
||||
* Disconnect the client if the socket buffer is full.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void buffer_flush();
|
||||
/**
|
||||
* Write one byte directly to the output stream.
|
||||
*
|
||||
* Disconnect the client if the socket buffer is full.
|
||||
*
|
||||
* @param[in] data Data to be output.
|
||||
* @return The number of bytes that were output.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
size_t raw_write(unsigned char data);
|
||||
/**
|
||||
* Write a vector of bytes directly to the output stream.
|
||||
*
|
||||
* Disconnect the client if the socket buffer is full.
|
||||
*
|
||||
* @param[in] data Data to be output.
|
||||
* @return The number of bytes that were output.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
size_t raw_write(const std::vector<unsigned char> &data);
|
||||
/**
|
||||
* Write an array of bytes directly to the output stream.
|
||||
*
|
||||
* Disconnect the client if the socket buffer is full.
|
||||
*
|
||||
* @param[in] buffer Buffer to be output.
|
||||
* @param[in] size Length of the buffer.
|
||||
* @return The number of bytes that were output.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
size_t raw_write(const uint8_t *buffer, size_t size);
|
||||
|
||||
WiFiClient &client_; /*!< Client connection. @since 0.1.0 */
|
||||
unsigned char previous_raw_in_ = 0; /*!< Previous raw character that was received. Used to detect commands. @since 0.1.0 */
|
||||
bool sub_negotiation_ = false; /*!< Sub-negotiation mode. @since 0.1.0 */
|
||||
unsigned char previous_in_ = 0; /*!< Previous character that was received. Used to detect CR NUL. @since 0.1.0 */
|
||||
unsigned char previous_out_ = 0; /*!< Previous character that was sent. Used to insert NUL after CR without LF. @since 0.1.0 */
|
||||
int peek_ = -1; /*!< Previously read data cached by peek(). @since 0.1.0 */
|
||||
std::vector<char> output_buffer_; /*!< Buffer data to be output until a read function is called. @since 0.1.0 */
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides access to a console shell as a telnet server.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
class TelnetService {
|
||||
public:
|
||||
static constexpr size_t MAX_CONNECTIONS = 3; /*!< Maximum number of concurrent open connections. @since 0.1.0 */
|
||||
static constexpr uint16_t DEFAULT_PORT = 23; /*!< Default TCP port to listen on. @since 0.1.0 */
|
||||
static constexpr unsigned long DEFAULT_IDLE_TIMEOUT = 600; /*!< Default initial idle timeout (in seconds). @since 0.1.0 */
|
||||
static constexpr unsigned long DEFAULT_WRITE_TIMEOUT = 0; /*!< Default write timeout (in milliseconds). @ since 0.1.0 */
|
||||
|
||||
/**
|
||||
* Function to handle the creation of a shell.
|
||||
*
|
||||
* @param[in] stream Stream for the telnet connection.
|
||||
* @param[in] addr Remote IP address.
|
||||
* @param[in] port Remote port.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
using shell_factory_function = std::function<std::shared_ptr<uuid::console::Shell>(Stream &stream, const IPAddress &addr, uint16_t port)>;
|
||||
|
||||
/**
|
||||
* Create a new telnet service listening on the default port.
|
||||
*
|
||||
* @param[in] commands Commands available for execution in shells.
|
||||
* @param[in] context Default context for shells.
|
||||
* @param[in] flags Initial flags for shells.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
TelnetService(std::shared_ptr<uuid::console::Commands> commands, unsigned int context = 0, unsigned int flags = 0);
|
||||
|
||||
/**
|
||||
* Create a new telnet service listening on a specific port.
|
||||
*
|
||||
* @param[in] port TCP listening port.
|
||||
* @param[in] commands Commands available for execution in shells.
|
||||
* @param[in] context Default context for shells.
|
||||
* @param[in] flags Initial flags for shells.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
TelnetService(uint16_t port, std::shared_ptr<uuid::console::Commands> commands, unsigned int context = 0, unsigned int flags = 0);
|
||||
|
||||
/**
|
||||
* Create a new telnet service listening on the default port.
|
||||
*
|
||||
* @param[in] shell_factory Function to create a shell for new connections.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
explicit TelnetService(shell_factory_function shell_factory);
|
||||
|
||||
/**
|
||||
* Create a new telnet service listening on a specific port.
|
||||
*
|
||||
* @param[in] port TCP listening port.
|
||||
* @param[in] shell_factory Function to create a shell for new connections.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
TelnetService(uint16_t port, shell_factory_function shell_factory);
|
||||
|
||||
~TelnetService() = default;
|
||||
|
||||
/**
|
||||
* Start listening for connections on the configured port.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void start();
|
||||
/**
|
||||
* Close all connections.
|
||||
*
|
||||
* The listening status is not affected.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void close_all();
|
||||
/**
|
||||
* Stop listening for connections.
|
||||
*
|
||||
* Existing connections are not affected.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Get the maximum number of concurrent open connections.
|
||||
*
|
||||
* @return The maximum number of concurrent open connections.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
size_t maximum_connections() const;
|
||||
/**
|
||||
* Set the maximum number of concurrent open connections.
|
||||
*
|
||||
* Defaults to TelnetService::MAX_CONNECTIONS.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void maximum_connections(size_t count);
|
||||
|
||||
/**
|
||||
* Get the initial idle timeout for new connections.
|
||||
*
|
||||
* @return The initial idle timeout in seconds (or 0 for disabled).
|
||||
* @since 0.1.0
|
||||
*/
|
||||
unsigned long initial_idle_timeout() const;
|
||||
/**
|
||||
* Set the initial idle timeout for new connections.
|
||||
*
|
||||
* Defaults to TelnetService::DEFAULT_IDLE_TIMEOUT.
|
||||
*
|
||||
* @param[in] timeout Idle timeout in seconds (or 0 to disable).
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void initial_idle_timeout(unsigned long timeout);
|
||||
|
||||
/**
|
||||
* Get the default socket write timeout for new connections.
|
||||
*
|
||||
* @return The default socket write timeout in seconds (or 0 for
|
||||
* platform default).
|
||||
* @since 0.1.0
|
||||
*/
|
||||
unsigned long default_write_timeout() const;
|
||||
/**
|
||||
* Set the default socket write timeout for new connections.
|
||||
*
|
||||
* Defaults to TelnetService::DEFAULT_WRITE_TIMEOUT (platform
|
||||
* default).
|
||||
*
|
||||
* @param[in] timeout Socket write timeout in seconds (or 0 for
|
||||
* platform default).
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void default_write_timeout(unsigned long timeout);
|
||||
|
||||
/**
|
||||
* Accept new connections.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void loop();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Telnet connection.
|
||||
*
|
||||
* Holds the client and stream instance for the lifetime of the shell.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
class Connection {
|
||||
public:
|
||||
/**
|
||||
* Create a telnet connection shell.
|
||||
*
|
||||
* @param[in] shell_factory Function to create a shell for new connections.
|
||||
* @param[in] client Client connection.
|
||||
* @param[in] idle_timeout Idle timeout in seconds.
|
||||
* @param[in] write_timeout Idle timeout in milliseconds.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
Connection(shell_factory_function &shell_factory, WiFiClient &&client, unsigned long idle_timeout, unsigned long write_timeout);
|
||||
~Connection() = default;
|
||||
|
||||
/**
|
||||
* Check if the shell is still active.
|
||||
*
|
||||
* @return Active status of the shell.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
bool active();
|
||||
/**
|
||||
* Stop the shell if the client is not connected.
|
||||
*
|
||||
* @return Active status of the shell.
|
||||
* @since 0.1.0
|
||||
*/
|
||||
bool loop();
|
||||
/**
|
||||
* Stop the shell.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
void stop();
|
||||
|
||||
private:
|
||||
Connection(const Connection&) = delete;
|
||||
Connection& operator=(const Connection&) = delete;
|
||||
|
||||
WiFiClient client_; /*!< Client connection. @since 0.1.0 */
|
||||
TelnetStream stream_; /*!< Telnet stream for the connection. @since 0.1.0 */
|
||||
std::shared_ptr<uuid::console::Shell> shell_; /*!< Shell for connection. @since 0.1.0 */
|
||||
IPAddress addr_; /*!< Remote address of connection. @since 0.1.0 */
|
||||
uint16_t port_; /*!< Remote port of connection. @since 0.1.0 */
|
||||
};
|
||||
|
||||
TelnetService(const TelnetService&) = delete;
|
||||
TelnetService& operator=(const TelnetService&) = delete;
|
||||
|
||||
static uuid::log::Logger logger_; /*!< uuid::log::Logger instance for telnet services. @since 0.1.0 */
|
||||
|
||||
WiFiServer server_; /*!< TCP server. @since 0.1.0 */
|
||||
size_t maximum_connections_ = MAX_CONNECTIONS; /*!< Maximum number of concurrent open connections. @since 0.1.0 */
|
||||
std::list<Connection> connections_; /*!< Open connections. @since 0.1.0 */
|
||||
shell_factory_function shell_factory_; /*!< Function to create a shell. @since 0.1.0 */
|
||||
unsigned long initial_idle_timeout_ = DEFAULT_IDLE_TIMEOUT; /*!< Initial idle timeout (in seconds). @since 0.1.0 */
|
||||
unsigned long write_timeout_ = DEFAULT_WRITE_TIMEOUT; /*!< Write timeout (in milliseconds). @since 0.1.0 */
|
||||
};
|
||||
|
||||
} // namespace telnet
|
||||
|
||||
} // namespace uuid
|
||||
|
||||
#endif
|
||||
180
lib_standalone/Arduino.cpp
Normal file
180
lib_standalone/Arduino.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
NativeConsole Serial;
|
||||
|
||||
/* millis() on C++ native could be
|
||||
for non-Arduino
|
||||
millis():
|
||||
#include <chrono>
|
||||
auto start = std::chrono::system_clock::now();
|
||||
auto end = std::chrono::system_clock::now();
|
||||
diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
*/
|
||||
|
||||
static unsigned long __millis = 0;
|
||||
static bool __output_pins[256];
|
||||
static int __output_level[256];
|
||||
|
||||
int main(int argc __attribute__((unused)), char * argv[] __attribute__((unused))) {
|
||||
memset(__output_pins, 0, sizeof(__output_pins));
|
||||
memset(__output_level, 0, sizeof(__output_level));
|
||||
setup();
|
||||
// loop(); // run once
|
||||
|
||||
static unsigned long __cycles = 0;
|
||||
|
||||
while (millis() <= 10 * 1000 && __cycles++ <= 10 * 1000) {
|
||||
loop();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long millis() {
|
||||
return __millis;
|
||||
}
|
||||
|
||||
void delay(unsigned long millis) {
|
||||
__millis += millis;
|
||||
}
|
||||
|
||||
void yield(void) {
|
||||
}
|
||||
|
||||
int snprintf_P(char * str, size_t size, const char * format, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
int ret = vsnprintf_P(str, size, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vsnprintf_P(char * str, size_t size, const char * format, va_list ap) {
|
||||
std::string native_format;
|
||||
|
||||
char previous = 0;
|
||||
for (size_t i = 0; i < strlen(format); i++) {
|
||||
char c = format[i];
|
||||
|
||||
// This would be a lot easier if the ESP8266 platform
|
||||
// simply read all strings with 32-bit accesses instead
|
||||
// of repurposing %S (wchar_t).
|
||||
if (previous == '%' && c == 'S') {
|
||||
c = 's';
|
||||
}
|
||||
|
||||
native_format += c;
|
||||
previous = c;
|
||||
}
|
||||
|
||||
return vsnprintf(str, size, native_format.c_str(), ap);
|
||||
}
|
||||
|
||||
void pinMode(uint8_t pin, uint8_t mode) {
|
||||
__output_pins[pin] = (mode == OUTPUT);
|
||||
}
|
||||
|
||||
void digitalWrite(uint8_t pin, uint8_t value) {
|
||||
__output_level[pin] = (value == HIGH) ? HIGH : LOW;
|
||||
}
|
||||
|
||||
int digitalRead(uint8_t pin) {
|
||||
if (__output_pins[pin]) {
|
||||
return __output_level[pin];
|
||||
} else if (pin & 1) {
|
||||
return HIGH;
|
||||
} else {
|
||||
return LOW;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Copy string src to buffer dst of size dsize. At most dsize-1
|
||||
* chars will be copied. Always NUL terminates (unless dsize == 0).
|
||||
* Returns strlen(src); if retval >= dsize, truncation occurred.
|
||||
*
|
||||
* https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcpy.c
|
||||
*/
|
||||
size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize) {
|
||||
const char * osrc = src;
|
||||
size_t nleft = dsize;
|
||||
|
||||
/* Copy as many bytes as will fit. */
|
||||
if (nleft != 0) {
|
||||
while (--nleft != 0) {
|
||||
if ((*dst++ = *src++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src. */
|
||||
if (nleft == 0) {
|
||||
if (dsize != 0)
|
||||
*dst = '\0'; /* NUL-terminate dst */
|
||||
while (*src++)
|
||||
;
|
||||
}
|
||||
|
||||
return (src - osrc - 1); /* count does not include NUL */
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* full size of dst, not space left). At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* If retval >= siz, truncation occurred.
|
||||
*
|
||||
* https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcat.c
|
||||
*/
|
||||
size_t strlcat(char * dst, const char * src, size_t siz) {
|
||||
char * d = dst;
|
||||
const char * s = src;
|
||||
size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return (dlen + strlen(s));
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return (dlen + (s - src)); /* count does not include NUL */
|
||||
}
|
||||
221
lib_standalone/Arduino.h
Normal file
221
lib_standalone/Arduino.h
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright 2019 Simon Arlott
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ARDUINO_H_
|
||||
#define ARDUINO_H_
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <algorithm> // for count_if
|
||||
|
||||
#define IPAddress std::string
|
||||
#define ICACHE_FLASH_ATTR
|
||||
#define ICACHE_RAM_ATTR
|
||||
#define os_event_t void
|
||||
#define byte uint8_t
|
||||
#define ltoa itoa
|
||||
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
|
||||
#define NAN 0
|
||||
|
||||
#define INPUT 0
|
||||
#define OUTPUT 1
|
||||
#define INPUT_PULLUP 2
|
||||
|
||||
void pinMode(uint8_t pin, uint8_t mode);
|
||||
void digitalWrite(uint8_t pin, uint8_t value);
|
||||
int digitalRead(uint8_t pin);
|
||||
|
||||
#define PROGMEM
|
||||
#define PGM_P const char *
|
||||
#define PSTR(s) \
|
||||
(__extension__({ \
|
||||
static const char __c[] = (s); \
|
||||
&__c[0]; \
|
||||
}))
|
||||
|
||||
class __FlashStringHelper;
|
||||
#define FPSTR(string_literal) (reinterpret_cast<const __FlashStringHelper *>(string_literal))
|
||||
#define F(string_literal) (FPSTR(PSTR(string_literal)))
|
||||
|
||||
#define strlen_P strlen
|
||||
#define strncpy_P strncpy
|
||||
#define strcmp_P strcmp
|
||||
|
||||
int snprintf_P(char * str, size_t size, const char * format, ...);
|
||||
int vsnprintf_P(char * str, size_t size, const char * format, va_list ap);
|
||||
|
||||
#define pgm_read_byte(addr) (*reinterpret_cast<const char *>(addr))
|
||||
|
||||
class Print;
|
||||
|
||||
class Printable {
|
||||
public:
|
||||
virtual size_t printTo(Print & print) const = 0;
|
||||
};
|
||||
|
||||
class Print {
|
||||
public:
|
||||
virtual size_t write(uint8_t c) = 0;
|
||||
virtual size_t write(const uint8_t * buffer, size_t size) = 0;
|
||||
size_t print(char c) {
|
||||
return write((uint8_t)c);
|
||||
}
|
||||
size_t print(const char * data) {
|
||||
return write(reinterpret_cast<const uint8_t *>(data), strlen(data));
|
||||
}
|
||||
size_t print(const __FlashStringHelper * data) {
|
||||
return print(reinterpret_cast<const char *>(data));
|
||||
}
|
||||
size_t print(const Printable & printable) {
|
||||
return printable.printTo(*this);
|
||||
}
|
||||
size_t print(int value) {
|
||||
return print(std::to_string(value).c_str());
|
||||
}
|
||||
size_t print(unsigned int value) {
|
||||
return print(std::to_string(value).c_str());
|
||||
}
|
||||
size_t print(long value) {
|
||||
return print(std::to_string(value).c_str());
|
||||
}
|
||||
size_t print(unsigned long value) {
|
||||
return print(std::to_string(value).c_str());
|
||||
}
|
||||
size_t println() {
|
||||
return print("\r\n");
|
||||
}
|
||||
size_t println(const char * data) {
|
||||
return print(data) + println();
|
||||
}
|
||||
size_t println(const __FlashStringHelper * data) {
|
||||
return print(reinterpret_cast<const char *>(data)) + println();
|
||||
}
|
||||
size_t println(const Printable & printable) {
|
||||
return printable.printTo(*this) + println();
|
||||
}
|
||||
size_t println(int value) {
|
||||
return print(std::to_string(value).c_str()) + println();
|
||||
}
|
||||
size_t println(unsigned int value) {
|
||||
return print(std::to_string(value).c_str()) + println();
|
||||
}
|
||||
size_t println(long value) {
|
||||
return print(std::to_string(value).c_str()) + println();
|
||||
}
|
||||
size_t println(unsigned long value) {
|
||||
return print(std::to_string(value).c_str()) + println();
|
||||
}
|
||||
virtual void flush(){};
|
||||
};
|
||||
|
||||
class Stream : public Print {
|
||||
public:
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
};
|
||||
|
||||
class String {
|
||||
public:
|
||||
String(const char * data = "")
|
||||
: data_(data) {
|
||||
}
|
||||
|
||||
long toInt() const {
|
||||
return std::stol(data_);
|
||||
}
|
||||
|
||||
const char * c_str() const {
|
||||
return data_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string data_;
|
||||
};
|
||||
|
||||
class NativeConsole : public Stream {
|
||||
public:
|
||||
void begin(unsigned long baud __attribute__((unused))) {
|
||||
}
|
||||
|
||||
int available() override {
|
||||
if (peek() >= 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int read() override {
|
||||
peek();
|
||||
|
||||
if (peek_) {
|
||||
peek_ = false;
|
||||
return peek_data_;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int peek() override {
|
||||
if (!peek_) {
|
||||
int ret = ::read(STDIN_FILENO, &peek_data_, 1);
|
||||
peek_ = ret > 0;
|
||||
}
|
||||
|
||||
if (peek_) {
|
||||
return peek_data_;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
size_t write(uint8_t c) override {
|
||||
return ::write(STDOUT_FILENO, &c, 1);
|
||||
}
|
||||
|
||||
size_t write(const uint8_t * buffer, size_t size) override {
|
||||
return ::write(STDOUT_FILENO, buffer, size);
|
||||
}
|
||||
|
||||
private:
|
||||
bool peek_ = false;
|
||||
unsigned char peek_data_;
|
||||
};
|
||||
|
||||
extern NativeConsole Serial;
|
||||
|
||||
unsigned long millis();
|
||||
|
||||
void delay(unsigned long millis);
|
||||
|
||||
void yield(void);
|
||||
|
||||
void setup(void);
|
||||
void loop(void);
|
||||
|
||||
size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize);
|
||||
size_t strlcat(char * dst, const char * src, size_t siz);
|
||||
|
||||
#endif
|
||||
8
lib_standalone/ArduinoJson/.clang-format
Normal file
8
lib_standalone/ArduinoJson/.clang-format
Normal file
@@ -0,0 +1,8 @@
|
||||
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
|
||||
BasedOnStyle: Google
|
||||
Standard: Cpp03
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
|
||||
# Always break after if to get accurate coverage
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
6
lib_standalone/ArduinoJson/.mbedignore
Normal file
6
lib_standalone/ArduinoJson/.mbedignore
Normal file
@@ -0,0 +1,6 @@
|
||||
.github/
|
||||
examples/
|
||||
fuzzing/
|
||||
scripts/
|
||||
test/
|
||||
third-party/
|
||||
5
lib_standalone/ArduinoJson/ArduinoJson.h
Normal file
5
lib_standalone/ArduinoJson/ArduinoJson.h
Normal file
@@ -0,0 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#include "src/ArduinoJson.h"
|
||||
965
lib_standalone/ArduinoJson/CHANGELOG.md
Normal file
965
lib_standalone/ArduinoJson/CHANGELOG.md
Normal file
@@ -0,0 +1,965 @@
|
||||
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<nullptr_t>()`
|
||||
* Fixed value returned by `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` when writing to a `String`
|
||||
* Improved speed of `serializeJson()`, `serializeJsonPretty()`, and `serializeMsgPack()` when writing to a `String`
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### Comments
|
||||
>
|
||||
> Support for comments in input is now optional and disabled by default.
|
||||
>
|
||||
> If you need support for comments, you must defined `ARDUINOJSON_ENABLE_COMMENTS` to `1`; otherwise, you'll receive `InvalidInput` errors.
|
||||
>
|
||||
> ```c++
|
||||
> #define ARDUINOJSON_ENABLE_COMMENTS 1
|
||||
> #include <ArduinoJson.h>
|
||||
> ```
|
||||
|
||||
v6.13.0 (2019-11-01)
|
||||
-------
|
||||
|
||||
* Added support for custom writer/reader classes (issue #1088)
|
||||
* Added conversion from `JsonArray` and `JsonObject` to `bool`, to be consistent with `JsonVariant`
|
||||
* Fixed `deserializeJson()` when input contains duplicate keys (issue #1095)
|
||||
* Improved `deserializeMsgPack()` speed by reading several bytes at once
|
||||
* Added detection of Atmel AVR8/GNU C Compiler (issue #1112)
|
||||
* Fixed deserializer that stopped reading at the first `0xFF` (PR #1118 by @mikee47)
|
||||
* Fixed dangling reference in copies of `MemberProxy` and `ElementProxy` (issue #1120)
|
||||
|
||||
v6.12.0 (2019-09-05)
|
||||
-------
|
||||
|
||||
* Use absolute instead of relative includes (issue #1072)
|
||||
* Changed `JsonVariant::as<bool>()` to return `true` for any non-null value (issue #1005)
|
||||
* Moved ancillary files to `extras/` (issue #1011)
|
||||
|
||||
v6.11.5 (2019-08-23)
|
||||
-------
|
||||
|
||||
* Added fallback implementations of `strlen_P()`, `strncmp_P()`, `strcmp_P()`, and `memcpy_P()` (issue #1073)
|
||||
|
||||
v6.11.4 (2019-08-12)
|
||||
-------
|
||||
|
||||
* Added `measureJson()` to the `ArduinoJson` namespace (PR #1069 by @nomis)
|
||||
* Added support for `basic_string<char, traits, allocator>` (issue #1045)
|
||||
* Fixed example `JsonConfigFile.ino` for ESP8266
|
||||
* Include `Arduino.h` if `ARDUINO` is defined (PR #1071 by @nomis)
|
||||
|
||||
v6.11.3 (2019-07-22)
|
||||
-------
|
||||
|
||||
* Added operators `==` and `!=` for `JsonDocument`, `ElementProxy`, and `MemberProxy`
|
||||
* Fixed comparison of `JsonVariant` when one contains a linked string and the other contains an owned string (issue #1051)
|
||||
|
||||
v6.11.2 (2019-07-08)
|
||||
-------
|
||||
|
||||
* Fixed assignment of `JsonDocument` to `JsonVariant` (issue #1023)
|
||||
* Fix invalid conversion error on Particle Argon (issue #1035)
|
||||
|
||||
v6.11.1 (2019-06-21)
|
||||
-------
|
||||
|
||||
* Fixed `serialized()` not working with Flash strings (issue #1030)
|
||||
|
||||
v6.11.0 (2019-05-26)
|
||||
-------
|
||||
|
||||
* Fixed `deserializeJson()` silently accepting a `Stream*` (issue #978)
|
||||
* Fixed invalid result from `operator|` (issue #981)
|
||||
* Made `deserializeJson()` more picky about trailing characters (issue #980)
|
||||
* Added `ARDUINOJSON_ENABLE_NAN` (default=0) to enable NaN in JSON (issue #973)
|
||||
* Added `ARDUINOJSON_ENABLE_INFINITY` (default=0) to enable Infinity in JSON
|
||||
* Removed implicit conversion in comparison operators (issue #998)
|
||||
* Added lexicographical comparison for `JsonVariant`
|
||||
* Added support for `nullptr` (issue #998)
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### NaN and Infinity
|
||||
>
|
||||
> The JSON specification allows neither NaN not Infinity, but previous
|
||||
> versions of ArduinoJson supported it. Now, ArduinoJson behaves like most
|
||||
> other libraries: a NaN or and Infinity in the `JsonDocument`, becomes
|
||||
> a `null` in the output JSON. Also, `deserializeJson()` returns
|
||||
> `InvalidInput` if the JSON document contains NaN or Infinity.
|
||||
>
|
||||
> This version still supports NaN and Infinity in JSON documents, but
|
||||
> it's disabled by default to be compatible with other JSON parsers.
|
||||
> If you need the old behavior back, define `ARDUINOJSON_ENABLE_NAN` and
|
||||
> `ARDUINOJSON_ENABLE_INFINITY` to `1`;:
|
||||
>
|
||||
> ```c++
|
||||
> #define ARDUINOJSON_ENABLE_NAN 1
|
||||
> #define ARDUINOJSON_ENABLE_INFINITY 1
|
||||
> #include <ArduinoJson.h>
|
||||
> ```
|
||||
>
|
||||
> #### The "or" operator
|
||||
>
|
||||
> This version slightly changes the behavior of the | operator when the
|
||||
> variant contains a float and the user requests an integer.
|
||||
>
|
||||
> Older versions returned the floating point value truncated.
|
||||
> Now, it returns the default value.
|
||||
>
|
||||
> ```c++
|
||||
> // suppose variant contains 1.2
|
||||
> int value = variant | 3;
|
||||
>
|
||||
> // old behavior:
|
||||
> value == 1
|
||||
>
|
||||
> // new behavior
|
||||
> value == 3
|
||||
> ```
|
||||
>
|
||||
> If you need the old behavior, you must add `if (variant.is<float>())`.
|
||||
|
||||
v6.10.1 (2019-04-23)
|
||||
-------
|
||||
|
||||
* Fixed error "attributes are not allowed on a function-definition"
|
||||
* Fixed `deserializeJson()` not being picky enough (issue #969)
|
||||
* Fixed error "no matching function for call to write(uint8_t)" (issue #972)
|
||||
|
||||
v6.10.0 (2019-03-22)
|
||||
-------
|
||||
|
||||
* Fixed an integer overflow in the JSON deserializer
|
||||
* Added overflow handling in `JsonVariant::as<T>()` and `JsonVariant::is<T>()`.
|
||||
- `as<T>()` returns `0` if the integer `T` overflows
|
||||
- `is<T>()` returns `false` if the integer `T` overflows
|
||||
* Added `BasicJsonDocument` to support custom allocator (issue #876)
|
||||
* Added `JsonDocument::containsKey()` (issue #938)
|
||||
* Added `JsonVariant::containsKey()`
|
||||
|
||||
v6.9.1 (2019-03-01)
|
||||
------
|
||||
|
||||
* Fixed warning "unused variable" with GCC 4.4 (issue #912)
|
||||
* Fixed warning "cast increases required alignment" (issue #914)
|
||||
* Fixed warning "conversion may alter value" (issue #914)
|
||||
* Fixed naming conflict with "CAPACITY" (issue #839)
|
||||
* Muted warning "will change in GCC 7.1" (issue #914)
|
||||
* Added a clear error message for `StaticJsonBuffer` and `DynamicJsonBuffer`
|
||||
* Marked ArduinoJson.h as a "system header"
|
||||
|
||||
v6.9.0 (2019-02-26)
|
||||
------
|
||||
|
||||
* Decode escaped Unicode characters like \u00DE (issue #304, PR #791)
|
||||
Many thanks to Daniel Schulte (aka @trilader) who implemented this feature.
|
||||
* Added option ARDUINOJSON_DECODE_UNICODE to enable it
|
||||
* Converted `JsonArray::copyFrom()/copyTo()` to free functions `copyArray()`
|
||||
* Renamed `JsonArray::copyFrom()` and `JsonObject::copyFrom()` to `set()`
|
||||
* Renamed `JsonArray::get()` to `getElement()`
|
||||
* Renamed `JsonArray::add()` (without arg) to `addElement()`
|
||||
* Renamed `JsonObject::get()` to `getMember()`
|
||||
* Renamed `JsonObject::getOrCreate()` to `getOrAddMember()`
|
||||
* Fixed `JsonVariant::isNull()` not returning `true` after `set((char*)0)`
|
||||
* Fixed segfault after `variant.set(serialized((char*)0))`
|
||||
* Detect `IncompleteInput` in `false`, `true`, and `null`
|
||||
* Added `JsonDocument::size()`
|
||||
* Added `JsonDocument::remove()`
|
||||
* Added `JsonVariant::clear()`
|
||||
* Added `JsonVariant::remove()`
|
||||
|
||||
v6.8.0-beta (2019-01-30)
|
||||
-----------
|
||||
|
||||
* Import functions in the ArduinoJson namespace to get clearer errors
|
||||
* Improved syntax highlighting in Arduino IDE
|
||||
* Removed default capacity of `DynamicJsonDocument`
|
||||
* `JsonArray::copyFrom()` accepts `JsonArrayConst`
|
||||
* `JsonVariant::set()` accepts `JsonArrayConst` and `JsonObjectConst`
|
||||
* `JsonDocument` was missing in the ArduinoJson namespace
|
||||
* Added `memoryUsage()` to `JsonArray`, `JsonObject`, and `JsonVariant`
|
||||
* Added `nesting()` to `JsonArray`, `JsonDocument`, `JsonObject`, and `JsonVariant`
|
||||
* Replaced `JsonDocument::nestingLimit` with an additional parameter
|
||||
to `deserializeJson()` and `deserializeMsgPack()`
|
||||
* Fixed uninitialized variant in `JsonDocument`
|
||||
* Fixed `StaticJsonDocument` copy constructor and copy assignment
|
||||
* The copy constructor of `DynamicJsonDocument` chooses the capacity according to the memory usage of the source, not from the capacity of the source.
|
||||
* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant`
|
||||
* Added `JsonDocument::isNull()`
|
||||
* Added `JsonDocument::operator[]`
|
||||
* Added `ARDUINOJSON_TAB` to configure the indentation character
|
||||
* Reduced the size of the pretty JSON serializer
|
||||
* Added `add()`, `createNestedArray()` and `createNestedObject()` to `JsonVariant`
|
||||
* `JsonVariant` automatically promotes to `JsonObject` or `JsonArray` on write.
|
||||
Calling `JsonVariant::to<T>()` is not required anymore.
|
||||
* `JsonDocument` now support the same operations as `JsonVariant`.
|
||||
Calling `JsonDocument::as<T>()` is not required anymore.
|
||||
* Fixed example `JsonHttpClient.ino`
|
||||
* User can now use a `JsonString` as a key or a value
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### `DynamicJsonDocument`'s constructor
|
||||
>
|
||||
> The parameter to the constructor of `DynamicJsonDocument` is now mandatory
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc;
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc(1024);
|
||||
> ```
|
||||
>
|
||||
> #### Nesting limit
|
||||
>
|
||||
> `JsonDocument::nestingLimit` was replaced with a new parameter to `deserializeJson()` and `deserializeMsgPack()`.
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> doc.nestingLimit = 15;
|
||||
> deserializeJson(doc, input);
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> deserializeJson(doc, input, DeserializationOption::NestingLimit(15));
|
||||
> ```
|
||||
|
||||
v6.7.0-beta (2018-12-07)
|
||||
-----------
|
||||
|
||||
* Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity.
|
||||
* Restored the monotonic allocator because the code was getting too big
|
||||
* Reduced the memory usage
|
||||
* Reduced the code size
|
||||
* Renamed `JsonKey` to `JsonString`
|
||||
* Removed spurious files in the Particle library
|
||||
|
||||
v6.6.0-beta (2018-11-13)
|
||||
-----------
|
||||
|
||||
* Removed `JsonArray::is<T>(i)` and `JsonArray::set(i,v)`
|
||||
* Removed `JsonObject::is<T>(k)` and `JsonObject::set(k,v)`
|
||||
* Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)`
|
||||
* Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)`
|
||||
* Added `JSON_STRING_SIZE()`
|
||||
* ~~Replacing or removing a value now releases the memory~~
|
||||
* Added `DeserializationError::code()` to be used in switch statements (issue #846)
|
||||
|
||||
v6.5.0-beta (2018-10-13)
|
||||
-----------
|
||||
|
||||
* Added implicit conversion from `JsonArray` and `JsonObject` to `JsonVariant`
|
||||
* Allow mixed configuration in compilation units (issue #809)
|
||||
* Fixed object keys not being duplicated
|
||||
* `JsonPair::key()` now returns a `JsonKey`
|
||||
* Increased the default capacity of `DynamicJsonDocument`
|
||||
* Fixed `JsonVariant::is<String>()` (closes #763)
|
||||
* Added `JsonArrayConst`, `JsonObjectConst`, and `JsonVariantConst`
|
||||
* Added copy-constructor and copy-assignment-operator for `JsonDocument` (issue #827)
|
||||
|
||||
v6.4.0-beta (2018-09-11)
|
||||
-----------
|
||||
|
||||
* Copy `JsonArray` and `JsonObject`, instead of storing pointers (issue #780)
|
||||
* Added `JsonVariant::to<JsonArray>()` and `JsonVariant::to<JsonObject>()`
|
||||
|
||||
v6.3.0-beta (2018-08-31)
|
||||
-----------
|
||||
|
||||
* Implemented reference semantics for `JsonVariant`
|
||||
* Replaced `JsonPair`'s `key` and `value` with `key()` and `value()`
|
||||
* Fixed `serializeJson(obj[key], dst)` (issue #794)
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### JsonVariant
|
||||
>
|
||||
> `JsonVariant` now has a semantic similar to `JsonObject` and `JsonArray`.
|
||||
> It's a reference to a value stored in the `JsonDocument`.
|
||||
> As a consequence, a `JsonVariant` cannot be used as a standalone variable anymore.
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> JsonVariant myValue = 42;
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc;
|
||||
> JsonVariant myValue = doc.to<JsonVariant>();
|
||||
> myValue.set(42);
|
||||
> ```
|
||||
>
|
||||
> #### JsonPair
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> for(JsonPair p : myObject) {
|
||||
> Serial.println(p.key);
|
||||
> Serial.println(p.value.as<int>());
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> for(JsonPair p : myObject) {
|
||||
> Serial.println(p.key());
|
||||
> Serial.println(p.value().as<int>());
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> CAUTION: the key is now read only!
|
||||
|
||||
v6.2.3-beta (2018-07-19)
|
||||
-----------
|
||||
|
||||
* Fixed exception when using Flash strings as object keys (issue #784)
|
||||
|
||||
v6.2.2-beta (2018-07-18)
|
||||
-----------
|
||||
|
||||
* Fixed `invalid application of 'sizeof' to incomplete type '__FlashStringHelper'` (issue #783)
|
||||
* Fixed `char[]` not duplicated when passed to `JsonVariant::operator[]`
|
||||
|
||||
v6.2.1-beta (2018-07-17)
|
||||
-----------
|
||||
|
||||
* Fixed `JsonObject` not inserting keys of type `String` (issue #782)
|
||||
|
||||
v6.2.0-beta (2018-07-12)
|
||||
-----------
|
||||
|
||||
* Disabled lazy number deserialization (issue #772)
|
||||
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
|
||||
* Improved float serialization when `-fsingle-precision-constant` is used
|
||||
* Renamed function `RawJson()` to `serialized()`
|
||||
* `serializeMsgPack()` now supports values marked with `serialized()`
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### Non quoted strings
|
||||
>
|
||||
> Non quoted strings are now forbidden in values, but they are still allowed in keys.
|
||||
> For example, `{key:"value"}` is accepted, but `{key:value}` is not.
|
||||
>
|
||||
> #### Preformatted values
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> object["values"] = RawJson("[1,2,3,4]");
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> object["values"] = serialized("[1,2,3,4]");
|
||||
> ```
|
||||
|
||||
v6.1.0-beta (2018-07-02)
|
||||
-----------
|
||||
|
||||
* Return `JsonArray` and `JsonObject` by value instead of reference (issue #309)
|
||||
* Replaced `success()` with `isNull()`
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> JsonObject& obj = doc.to<JsonObject>();
|
||||
> JsonArray& arr = obj.createNestedArray("key");
|
||||
> if (!arr.success()) {
|
||||
> Serial.println("Not enough memory");
|
||||
> return;
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> JsonObject obj = doc.to<JsonObject>();
|
||||
> JsonArray arr = obj.createNestedArray("key");
|
||||
> if (arr.isNull()) {
|
||||
> Serial.println("Not enough memory");
|
||||
> return;
|
||||
> }
|
||||
> ```
|
||||
|
||||
v6.0.1-beta (2018-06-11)
|
||||
-----------
|
||||
|
||||
* Fixed conflicts with `isnan()` and `isinf()` macros (issue #752)
|
||||
|
||||
v6.0.0-beta (2018-06-07)
|
||||
-----------
|
||||
|
||||
* Added `DynamicJsonDocument` and `StaticJsonDocument`
|
||||
* Added `deserializeJson()`
|
||||
* Added `serializeJson()` and `serializeJsonPretty()`
|
||||
* Added `measureJson()` and `measureJsonPretty()`
|
||||
* Added `serializeMsgPack()`, `deserializeMsgPack()` and `measureMsgPack()` (issue #358)
|
||||
* Added example `MsgPackParser.ino` (issue #358)
|
||||
* Added support for non zero-terminated strings (issue #704)
|
||||
* Removed `JsonBuffer::parseArray()`, `parseObject()` and `parse()`
|
||||
* Removed `JsonBuffer::createArray()` and `createObject()`
|
||||
* Removed `printTo()` and `prettyPrintTo()`
|
||||
* Removed `measureLength()` and `measurePrettyLength()`
|
||||
* Removed all deprecated features
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### Deserialization
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonBuffer jb;
|
||||
> JsonObject& obj = jb.parseObject(json);
|
||||
> if (obj.success()) {
|
||||
>
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc;
|
||||
> DeserializationError error = deserializeJson(doc, json);
|
||||
> if (error) {
|
||||
>
|
||||
> }
|
||||
> JsonObject& obj = doc.as<JsonObject>();
|
||||
> ```
|
||||
>
|
||||
> #### Serialization
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonBuffer jb;
|
||||
> JsonObject& obj = jb.createObject();
|
||||
> obj["key"] = "value";
|
||||
> obj.printTo(Serial);
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument obj;
|
||||
> JsonObject& obj = doc.to<JsonObject>();
|
||||
> obj["key"] = "value";
|
||||
> serializeJson(doc, Serial);
|
||||
> ```
|
||||
|
||||
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<double>()` 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<int>()` | `true` | `true` |
|
||||
> | `JsonVariant(42).is<float>()` | `false` | `true` |
|
||||
> | `JsonVariant(42).is<double>()` | `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<typename TJsonBuffer> 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<T>()`
|
||||
* 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<JsonVariant>("myKey");
|
||||
> JsonVariant value2 = myArray.get<JsonVariant>(0);
|
||||
> ```
|
||||
|
||||
v5.6.7
|
||||
------
|
||||
|
||||
* Fixed `array[idx].as<JsonVariant>()` and `object[key].as<JsonVariant>()`
|
||||
* 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<char*>()` 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<JsonArray>()` as a synonym for `as<JsonArray&>()`... (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<T>()` to `JsonVariant::defaultValue<T>()`
|
||||
|
||||
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<char*>()` as a synonym for `JsonVariant::as<const char*>()` (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<bool>()` 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<String>()` now returns `"true"` instead of `"1"`
|
||||
> - `JsonVariant(false).as<String>()` 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<T>()` 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!
|
||||
42
lib_standalone/ArduinoJson/CMakeLists.txt
Normal file
42
lib_standalone/ArduinoJson/CMakeLists.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2020
|
||||
# MIT License
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(ArduinoJson)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_definitions(-DARDUINOJSON_DEBUG=1)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8)
|
||||
add_compile_options(-g -Og)
|
||||
else()
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0)
|
||||
add_compile_options(-g -Og)
|
||||
else()
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9.0)
|
||||
add_compile_options(-g -Og)
|
||||
else()
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${COVERAGE})
|
||||
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
add_subdirectory(extras/tests)
|
||||
add_subdirectory(extras/fuzzing)
|
||||
11
lib_standalone/ArduinoJson/CONTRIBUTING.md
Normal file
11
lib_standalone/ArduinoJson/CONTRIBUTING.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Contribution to ArduinoJson
|
||||
|
||||
First, thank you for taking the time to contribute to this project.
|
||||
|
||||
You can submit changes via GitHub Pull Requests.
|
||||
|
||||
Please:
|
||||
|
||||
1. Unit test every change in behavior
|
||||
2. Use clang-format in "file" mode to format the code
|
||||
3. Consider using the Continuous Integration (Travis and AppVeyor)
|
||||
10
lib_standalone/ArduinoJson/LICENSE.md
Normal file
10
lib_standalone/ArduinoJson/LICENSE.md
Normal file
@@ -0,0 +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.
|
||||
137
lib_standalone/ArduinoJson/README.md
Normal file
137
lib_standalone/ArduinoJson/README.md
Normal file
@@ -0,0 +1,137 @@
|
||||

|
||||
|
||||
---
|
||||
|
||||
[](https://www.ardu-badge.com/ArduinoJson/6.15.0)
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
|
||||
[](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
|
||||
[](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!
|
||||
27
lib_standalone/ArduinoJson/SUPPORT.md
Normal file
27
lib_standalone/ArduinoJson/SUPPORT.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# ArduinoJson Support
|
||||
|
||||
First off, thank you very much for using ArduinoJson.
|
||||
|
||||
We'll be very happy to help you, but first please read the following.
|
||||
|
||||
## Before asking for help
|
||||
|
||||
1. Read the [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=support)
|
||||
2. Search in the [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=support)
|
||||
|
||||
If you did not find the answer, please create a [new issue on GitHub](https://github.com/bblanchon/ArduinoJson/issues/new).
|
||||
|
||||
It is OK to add a comment to a currently opened issue, but please avoid adding comments to a closed issue.
|
||||
|
||||
## Before hitting the Submit button
|
||||
|
||||
Please provide all the relevant information:
|
||||
|
||||
* Good title
|
||||
* Short description of the problem
|
||||
* Target platform
|
||||
* Compiler model and version
|
||||
* [MVCE](https://stackoverflow.com/help/mcve)
|
||||
* Compiler output
|
||||
|
||||
Good questions get fast answers!
|
||||
22
lib_standalone/ArduinoJson/appveyor.yml
Normal file
22
lib_standalone/ArduinoJson/appveyor.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
version: 6.15.0.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
CMAKE_GENERATOR: Visual Studio 16 2019
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
CMAKE_GENERATOR: Visual Studio 12 2013
|
||||
- CMAKE_GENERATOR: Visual Studio 11 2012
|
||||
- CMAKE_GENERATOR: Visual Studio 10 2010
|
||||
- CMAKE_GENERATOR: MinGW Makefiles
|
||||
configuration: Debug
|
||||
before_build:
|
||||
- set PATH=C:\MinGW\bin;%PATH:C:\Program Files\Git\usr\bin;=% # Workaround for CMake not wanting sh.exe on PATH for MinGW
|
||||
- cmake -DCMAKE_BUILD_TYPE=%CONFIGURATION% -G "%CMAKE_GENERATOR%" .
|
||||
build_script:
|
||||
- cmake --build . --config %CONFIGURATION%
|
||||
test_script:
|
||||
- ctest -C %CONFIGURATION% --output-on-failure .
|
||||
367
lib_standalone/ArduinoJson/banner.svg
Normal file
367
lib_standalone/ArduinoJson/banner.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 32 KiB |
1
lib_standalone/ArduinoJson/component.mk
Normal file
1
lib_standalone/ArduinoJson/component.mk
Normal file
@@ -0,0 +1 @@
|
||||
COMPONENT_ADD_INCLUDEDIRS := src
|
||||
20
lib_standalone/ArduinoJson/extras/ci/arduino.sh
Normal file
20
lib_standalone/ArduinoJson/extras/ci/arduino.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash -eux
|
||||
|
||||
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16
|
||||
sleep 3
|
||||
export DISPLAY=:1.0
|
||||
|
||||
mkdir -p /tmp/arduino
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tar.xz | tar xJ -C /tmp/arduino --strip 1 ||
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tgz | tar xz -C /tmp/arduino --strip 1
|
||||
export PATH=$PATH:/tmp/arduino/
|
||||
|
||||
if [[ "$BOARD" =~ "arduino:samd:" ]]; then
|
||||
arduino --install-boards arduino:samd
|
||||
fi
|
||||
|
||||
ln -s $PWD /tmp/arduino/libraries/ArduinoJson
|
||||
|
||||
for EXAMPLE in $PWD/examples/*/*.ino; do
|
||||
arduino --verify --board $BOARD $EXAMPLE
|
||||
done
|
||||
14
lib_standalone/ArduinoJson/extras/ci/build.sh
Normal file
14
lib_standalone/ArduinoJson/extras/ci/build.sh
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
export CC="$_CC"
|
||||
export CXX="$_CXX"
|
||||
|
||||
if [ -n "$SANITIZE" ]; then
|
||||
export CXXFLAGS="-fsanitize=$SANITIZE"
|
||||
BUILD_TYPE="Debug"
|
||||
else
|
||||
BUILD_TYPE="Release"
|
||||
fi
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE .
|
||||
cmake --build .
|
||||
9
lib_standalone/ArduinoJson/extras/ci/coverage.sh
Normal file
9
lib_standalone/ArduinoJson/extras/ci/coverage.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh -eux
|
||||
|
||||
cmake -DCOVERAGE=true .
|
||||
make
|
||||
make test
|
||||
|
||||
pip install --user cpp-coveralls 'requests[security]'
|
||||
pwd
|
||||
coveralls --include 'src' --gcov-options '\-lp'
|
||||
26
lib_standalone/ArduinoJson/extras/ci/fuzz.sh
Normal file
26
lib_standalone/ArduinoJson/extras/ci/fuzz.sh
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash -eux
|
||||
|
||||
ROOT_DIR=$(dirname $0)/../../
|
||||
INCLUDE_DIR=${ROOT_DIR}/src/
|
||||
FUZZING_DIR=${ROOT_DIR}/extras/fuzzing/
|
||||
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,undefined,fuzzer -fno-sanitize-recover=all"
|
||||
|
||||
fuzz() {
|
||||
NAME="$1"
|
||||
FUZZER="${NAME}_fuzzer"
|
||||
FUZZER_CPP="${FUZZING_DIR}/${NAME}_fuzzer.cpp"
|
||||
CORPUS_DIR="${FUZZING_DIR}/${NAME}_corpus"
|
||||
SEED_CORPUS_DIR="${FUZZING_DIR}/${NAME}_seed_corpus"
|
||||
|
||||
clang++-${CLANG} ${CXXFLAGS} -o ${FUZZER} -I$INCLUDE_DIR ${FUZZER_CPP}
|
||||
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="${FUZZER}.profraw"
|
||||
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30 -timeout=1
|
||||
|
||||
llvm-profdata-${CLANG} merge -sparse ${LLVM_PROFILE_FILE} -o ${FUZZER}.profdata
|
||||
llvm-cov-${CLANG} report ./${FUZZER} -instr-profile=${FUZZER}.profdata
|
||||
}
|
||||
|
||||
fuzz json
|
||||
fuzz msgpack
|
||||
20
lib_standalone/ArduinoJson/extras/ci/platformio.sh
Normal file
20
lib_standalone/ArduinoJson/extras/ci/platformio.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh -eux
|
||||
|
||||
pip install --user platformio
|
||||
|
||||
case $BOARD in
|
||||
uno)
|
||||
platformio lib install 868 # SD library
|
||||
platformio lib install 872 # Ethernet library
|
||||
;;
|
||||
esp01)
|
||||
platformio lib uninstall 161 || true
|
||||
platformio lib uninstall 868 || true
|
||||
platformio lib uninstall 872 || true
|
||||
;;
|
||||
esac
|
||||
|
||||
for EXAMPLE in $PWD/examples/*/*.ino;
|
||||
do
|
||||
platformio ci $EXAMPLE -l '.' -b $BOARD
|
||||
done
|
||||
4
lib_standalone/ArduinoJson/extras/ci/test.sh
Normal file
4
lib_standalone/ArduinoJson/extras/ci/test.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
"$(dirname "$0")/build.sh"
|
||||
ctest --output-on-failure .
|
||||
17
lib_standalone/ArduinoJson/extras/fuzzing/CMakeLists.txt
Normal file
17
lib_standalone/ArduinoJson/extras/fuzzing/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2020
|
||||
# MIT License
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
add_executable(msgpack_fuzzer
|
||||
msgpack_fuzzer.cpp
|
||||
fuzzer_main.cpp
|
||||
)
|
||||
|
||||
add_executable(json_fuzzer
|
||||
json_fuzzer.cpp
|
||||
fuzzer_main.cpp
|
||||
)
|
||||
22
lib_standalone/ArduinoJson/extras/fuzzing/Makefile
Normal file
22
lib_standalone/ArduinoJson/extras/fuzzing/Makefile
Normal file
@@ -0,0 +1,22 @@
|
||||
# CAUTION: this file is invoked by https://github.com/google/oss-fuzz
|
||||
|
||||
CXXFLAGS += -I../../src -DARDUINOJSON_DEBUG=1
|
||||
|
||||
all: \
|
||||
$(OUT)/json_fuzzer \
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/json_fuzzer.options \
|
||||
$(OUT)/msgpack_fuzzer \
|
||||
$(OUT)/msgpack_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/msgpack_fuzzer.options
|
||||
|
||||
$(OUT)/%_fuzzer: %_fuzzer.cpp $(shell find ../../src -type f)
|
||||
$(CXX) $(CXXFLAGS) $< -o$@ $(LIB_FUZZING_ENGINE)
|
||||
|
||||
$(OUT)/%_fuzzer_seed_corpus.zip: %_seed_corpus/*
|
||||
zip -j $@ $?
|
||||
|
||||
$(OUT)/%_fuzzer.options:
|
||||
@echo "[libfuzzer]" > $@
|
||||
@echo "max_len = 256" >> $@
|
||||
@echo "timeout = 10" >> $@
|
||||
50
lib_standalone/ArduinoJson/extras/fuzzing/fuzzer_main.cpp
Normal file
50
lib_standalone/ArduinoJson/extras/fuzzing/fuzzer_main.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
// This file is NOT use by Google's OSS fuzz
|
||||
// I only use it to reproduce the bugs found
|
||||
|
||||
#include <stdint.h> // size_t
|
||||
#include <stdio.h> // fopen et al.
|
||||
#include <stdlib.h> // exit
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
|
||||
|
||||
std::vector<uint8_t> read(const char* path) {
|
||||
FILE* f = fopen(path, "rb");
|
||||
if (!f) {
|
||||
std::cerr << "Failed to open " << path << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
std::vector<uint8_t> buffer(size);
|
||||
if (fread(buffer.data(), 1, size, f) != size) {
|
||||
fclose(f);
|
||||
std::cerr << "Failed to read " << path << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "Usage: msgpack_fuzzer files" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
std::cout << "Loading " << argv[i] << std::endl;
|
||||
std::vector<uint8_t> buffer = read(argv[i]);
|
||||
LLVMFuzzerTestOneInput(buffer.data(), buffer.size());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
2
lib_standalone/ArduinoJson/extras/fuzzing/json_corpus/.gitignore
vendored
Normal file
2
lib_standalone/ArduinoJson/extras/fuzzing/json_corpus/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
11
lib_standalone/ArduinoJson/extras/fuzzing/json_fuzzer.cpp
Normal file
11
lib_standalone/ArduinoJson/extras/fuzzing/json_fuzzer.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc(4096);
|
||||
DeserializationError error = deserializeJson(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
//comment
|
||||
/*comment*/
|
||||
[ //comment
|
||||
/*comment*/"comment"/*comment*/,//comment
|
||||
/*comment*/{//comment
|
||||
/* comment*/"key"//comment
|
||||
: //comment
|
||||
"value"//comment
|
||||
}/*comment*/
|
||||
]//comment
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
[1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20,[21,[22,[23,[24,[25,[26,[27,[28,[29,[30,[31,[32,[33,[34,[35,[36,[37,[38,[39,[40,[41,[42,[43,[44,[45,[46,[47,[48,[49,[50,[51,[52,[53,[54,[55,[56,[57,[58,[59,[60,[61,[62,[63,[64,[65,[66,[67,[68,[69,[70,[71,[72,[73,[74,[75,[76,[77,[78,[79,[80,[81,[82,[83,[84,[85,[86,[87,[88,[89,[90,[91,[92,[93,[94,[95,[96,[97,[98,[99,[100,[101,[102,[103,[104,[105,[106,[107,[108,[109,[110,[111,[112,[113,[114,[115,[116,[117,[118,[119,[120]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
|
||||
@@ -0,0 +1 @@
|
||||
9720730739393920739
|
||||
@@ -0,0 +1,24 @@
|
||||
[
|
||||
123,
|
||||
-123,
|
||||
123.456,
|
||||
-123.456,
|
||||
12e34,
|
||||
12e-34,
|
||||
12e+34,
|
||||
12E34,
|
||||
12E-34,
|
||||
12E+34,
|
||||
12.34e56,
|
||||
12.34e-56,
|
||||
12.34e+56,
|
||||
12.34E56,
|
||||
12.34E-56,
|
||||
12.34E+56,
|
||||
NaN,
|
||||
-NaN,
|
||||
+NaN,
|
||||
Infinity,
|
||||
+Infinity,
|
||||
-Infinity
|
||||
]
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"coord": {
|
||||
"lon": -0.13,
|
||||
"lat": 51.51
|
||||
},
|
||||
"weather": [
|
||||
{
|
||||
"id": 301,
|
||||
"main": "Drizzle",
|
||||
"description": "drizzle",
|
||||
"icon": "09n"
|
||||
},
|
||||
{
|
||||
"id": 701,
|
||||
"main": "Mist",
|
||||
"description": "mist",
|
||||
"icon": "50n"
|
||||
},
|
||||
{
|
||||
"id": 741,
|
||||
"main": "Fog",
|
||||
"description": "fog",
|
||||
"icon": "50n"
|
||||
}
|
||||
],
|
||||
"base": "stations",
|
||||
"main": {
|
||||
"temp": 281.87,
|
||||
"pressure": 1032,
|
||||
"humidity": 100,
|
||||
"temp_min": 281.15,
|
||||
"temp_max": 283.15
|
||||
},
|
||||
"visibility": 2900,
|
||||
"wind": {
|
||||
"speed": 1.5
|
||||
},
|
||||
"clouds": {
|
||||
"all": 90
|
||||
},
|
||||
"dt": 1483820400,
|
||||
"sys": {
|
||||
"type": 1,
|
||||
"id": 5091,
|
||||
"message": 0.0226,
|
||||
"country": "GB",
|
||||
"sunrise": 1483776245,
|
||||
"sunset": 1483805443
|
||||
},
|
||||
"id": 2643743,
|
||||
"name": "London",
|
||||
"cod": 200
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[
|
||||
"hello",
|
||||
'hello',
|
||||
hello,
|
||||
{"hello":"world"},
|
||||
{'hello':'world'},
|
||||
{hello:world}
|
||||
]
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"response": {
|
||||
"version": "0.1",
|
||||
"termsofService": "http://www.wunderground.com/weather/api/d/terms.html",
|
||||
"features": {
|
||||
"conditions": 1
|
||||
}
|
||||
},
|
||||
"current_observation": {
|
||||
"image": {
|
||||
"url": "http://icons-ak.wxug.com/graphics/wu2/logo_130x80.png",
|
||||
"title": "Weather Underground",
|
||||
"link": "http://www.wunderground.com"
|
||||
},
|
||||
"display_location": {
|
||||
"full": "San Francisco, CA",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"state_name": "California",
|
||||
"country": "US",
|
||||
"country_iso3166": "US",
|
||||
"zip": "94101",
|
||||
"latitude": "37.77500916",
|
||||
"longitude": "-122.41825867",
|
||||
"elevation": "47.00000000"
|
||||
},
|
||||
"observation_location": {
|
||||
"full": "SOMA - Near Van Ness, San Francisco, California",
|
||||
"city": "SOMA - Near Van Ness, San Francisco",
|
||||
"state": "California",
|
||||
"country": "US",
|
||||
"country_iso3166": "US",
|
||||
"latitude": "37.773285",
|
||||
"longitude": "-122.417725",
|
||||
"elevation": "49 ft"
|
||||
},
|
||||
"estimated": {},
|
||||
"station_id": "KCASANFR58",
|
||||
"observation_time": "Last Updated on June 27, 5:27 PM PDT",
|
||||
"observation_time_rfc822": "Wed, 27 Jun 2012 17:27:13 -0700",
|
||||
"observation_epoch": "1340843233",
|
||||
"local_time_rfc822": "Wed, 27 Jun 2012 17:27:14 -0700",
|
||||
"local_epoch": "1340843234",
|
||||
"local_tz_short": "PDT",
|
||||
"local_tz_long": "America/Los_Angeles",
|
||||
"local_tz_offset": "-0700",
|
||||
"weather": "Partly Cloudy",
|
||||
"temperature_string": "66.3 F (19.1 C)",
|
||||
"temp_f": 66.3,
|
||||
"temp_c": 19.1,
|
||||
"relative_humidity": "65%",
|
||||
"wind_string": "From the NNW at 22.0 MPH Gusting to 28.0 MPH",
|
||||
"wind_dir": "NNW",
|
||||
"wind_degrees": 346,
|
||||
"wind_mph": 22,
|
||||
"wind_gust_mph": "28.0",
|
||||
"wind_kph": 35.4,
|
||||
"wind_gust_kph": "45.1",
|
||||
"pressure_mb": "1013",
|
||||
"pressure_in": "29.93",
|
||||
"pressure_trend": "+",
|
||||
"dewpoint_string": "54 F (12 C)",
|
||||
"dewpoint_f": 54,
|
||||
"dewpoint_c": 12,
|
||||
"heat_index_string": "NA",
|
||||
"heat_index_f": "NA",
|
||||
"heat_index_c": "NA",
|
||||
"windchill_string": "NA",
|
||||
"windchill_f": "NA",
|
||||
"windchill_c": "NA",
|
||||
"feelslike_string": "66.3 F (19.1 C)",
|
||||
"feelslike_f": "66.3",
|
||||
"feelslike_c": "19.1",
|
||||
"visibility_mi": "10.0",
|
||||
"visibility_km": "16.1",
|
||||
"solarradiation": "",
|
||||
"UV": "5",
|
||||
"precip_1hr_string": "0.00 in ( 0 mm)",
|
||||
"precip_1hr_in": "0.00",
|
||||
"precip_1hr_metric": " 0",
|
||||
"precip_today_string": "0.00 in (0 mm)",
|
||||
"precip_today_in": "0.00",
|
||||
"precip_today_metric": "0",
|
||||
"icon": "partlycloudy",
|
||||
"icon_url": "http://icons-ak.wxug.com/i/c/k/partlycloudy.gif",
|
||||
"forecast_url": "http://www.wunderground.com/US/CA/San_Francisco.html",
|
||||
"history_url": "http://www.wunderground.com/history/airport/KCASANFR58/2012/6/27/DailyHistory.html",
|
||||
"ob_url": "http://www.wunderground.com/cgi-bin/findweather/getForecast?query=37.773285,-122.417725"
|
||||
}
|
||||
}
|
||||
2
lib_standalone/ArduinoJson/extras/fuzzing/msgpack_corpus/.gitignore
vendored
Normal file
2
lib_standalone/ArduinoJson/extras/fuzzing/msgpack_corpus/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
11
lib_standalone/ArduinoJson/extras/fuzzing/msgpack_fuzzer.cpp
Normal file
11
lib_standalone/ArduinoJson/extras/fuzzing/msgpack_fuzzer.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc(4096);
|
||||
DeserializationError error = deserializeMsgPack(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
serializeMsgPack(doc, json);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
<EFBFBD>
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>hello<EFBFBD>world
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD>
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>one<01>two
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD>hello world
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user