mirror of
https://github.com/luc-github/ESP3D.git
synced 2025-10-31 11:56:48 -07:00
2.0
This commit is contained in:
66
.gitlab-ci.yml
Normal file
66
.gitlab-ci.yml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
before_script:
|
||||||
|
- cd $HOME
|
||||||
|
- wget https://pypi.python.org/packages/df/c9/d9da7fafaf2a2b323d20eee050503ab08237c16b0119c7bbf1597d53f793/pyserial-2.7.tar.gz#md5=794506184df83ef2290de0d18803dd11
|
||||||
|
- tar -xvf pyserial-2.7.tar.gz
|
||||||
|
- cd pyserial-2.7
|
||||||
|
- python ./setup.py install
|
||||||
|
- wget http://downloads.arduino.cc/arduino-1.8.0-linux64.tar.xz
|
||||||
|
- tar xf ./arduino-1.8.0-linux64.tar.xz
|
||||||
|
- mv arduino-1.8.0 $HOME/arduino_ide
|
||||||
|
- cd $HOME/arduino_ide/hardware
|
||||||
|
- mkdir esp8266com
|
||||||
|
- cd esp8266com
|
||||||
|
- git clone https://github.com/esp8266/Arduino.git esp8266
|
||||||
|
- cd esp8266/tools
|
||||||
|
- python get.py
|
||||||
|
- cd ..
|
||||||
|
- touch pt.txt
|
||||||
|
- echo 'build.flash_ld=eagle.flash.4m.ld' >> pt.txt
|
||||||
|
- echo 'build.flash_freq=40' >> pt.txt
|
||||||
|
- echo 'build.flash_size=4M' >> pt.txt
|
||||||
|
- echo 'build.f_cpu=160000000L' >> pt.txt
|
||||||
|
- echo 'build.flash_mode=dio' >> pt.txt
|
||||||
|
- cat ./platform.txt >> pt.txt
|
||||||
|
- rm -fr platform.txt
|
||||||
|
- mv pt.txt platform.txt
|
||||||
|
- mv $CI_PROJECT_DIR/libraries/SdFat/SdFat $HOME/arduino_ide/libraries/
|
||||||
|
- mv $CI_PROJECT_DIR/libraries/IniFile $HOME/arduino_ide/libraries/
|
||||||
|
- mv $CI_PROJECT_DIR/libraries/ESPAsyncWebServer $HOME/arduino_ide/libraries/
|
||||||
|
- mv $CI_PROJECT_DIR/libraries/ESPAsyncTCP $HOME/arduino_ide/libraries/
|
||||||
|
- mv $CI_PROJECT_DIR/libraries/AsyncTCP $HOME/arduino_ide/libraries/
|
||||||
|
- mv $CI_PROJECT_DIR/libraries/oled-ssd1306 $HOME/arduino_ide/libraries/
|
||||||
|
- mv $CI_PROJECT_DIR/libraries/ESP32SSDP $HOME/arduino_ide/libraries/
|
||||||
|
- mv $CI_PROJECT_DIR/libraries/arduinoWebSockets $HOME/arduino_ide/libraries/
|
||||||
|
- mv $CI_PROJECT_DIR/libraries/DHT_sensor_library_for_ESPx $HOME/arduino_ide/libraries/
|
||||||
|
- mkdir $HOME/arduino_ide/libraries/ESP3D
|
||||||
|
- mv $CI_PROJECT_DIR/src $HOME/arduino_ide/libraries/ESP3D
|
||||||
|
- mv $CI_PROJECT_DIR/library.properties $HOME/arduino_ide/libraries/ESP3D
|
||||||
|
- cd $HOME/arduino_ide/hardware
|
||||||
|
- mkdir esp32
|
||||||
|
- cd esp32
|
||||||
|
- git clone https://github.com/espressif/arduino-esp32.git esp32
|
||||||
|
- cd esp32
|
||||||
|
- cd tools
|
||||||
|
- python get.py
|
||||||
|
- cd ..
|
||||||
|
- touch pt.txt
|
||||||
|
- echo 'build.flash_freq=80m' >> pt.txt
|
||||||
|
- cat ./platform.txt >> pt.txt
|
||||||
|
- rm -fr platform.txt
|
||||||
|
- mv pt.txt platform.txt
|
||||||
|
|
||||||
|
job1:
|
||||||
|
script:
|
||||||
|
- cd $CI_PROJECT_DIR
|
||||||
|
- source command.sh
|
||||||
|
- export PATH="$HOME/arduino_ide:$PATH"
|
||||||
|
- arduino --get-pref
|
||||||
|
- arduino --board esp8266com:esp8266:generic --save-prefs
|
||||||
|
- sed -i "s/\/\/#define SDCARD_FEATURE /#define SDCARD_FEATURE/g" $HOME/arduino_ide/libraries/ESP3D/src/config.h
|
||||||
|
- echo "build ESP8266"
|
||||||
|
- build_sketch $CI_PROJECT_DIR/examples/basicesp3d/basicesp3d.ino
|
||||||
|
- arduino --board esp32:esp32:esp32 --save-prefs
|
||||||
|
- echo "build ESP32"
|
||||||
|
- build_sketch $CI_PROJECT_DIR/examples/basicesp3d/basicesp3d.ino
|
||||||
|
|
||||||
|
|
||||||
32
.travis.yml
32
.travis.yml
@@ -11,9 +11,9 @@ before_install:
|
|||||||
before_script:
|
before_script:
|
||||||
- "export DISPLAY=:99.0"
|
- "export DISPLAY=:99.0"
|
||||||
- sleep 3 # give xvfb some time to start
|
- sleep 3 # give xvfb some time to start
|
||||||
- wget http://downloads.arduino.cc/arduino-1.8.4-linux64.tar.xz
|
- wget http://downloads.arduino.cc/arduino-1.8.5-linux64.tar.xz
|
||||||
- tar xf arduino-1.8.4-linux64.tar.xz
|
- tar xf arduino-1.8.5-linux64.tar.xz
|
||||||
- mv arduino-1.8.4 $HOME/arduino_ide
|
- mv arduino-1.8.5 $HOME/arduino_ide
|
||||||
- cd $HOME/arduino_ide/hardware
|
- cd $HOME/arduino_ide/hardware
|
||||||
- mkdir esp8266com
|
- mkdir esp8266com
|
||||||
- cd esp8266com
|
- cd esp8266com
|
||||||
@@ -35,6 +35,16 @@ before_script:
|
|||||||
- python get.py
|
- python get.py
|
||||||
- cd ..
|
- cd ..
|
||||||
- echo 'build.flash_freq=40m' >> platform.txt
|
- echo 'build.flash_freq=40m' >> platform.txt
|
||||||
|
- mv $TRAVIS_BUILD_DIR/libraries/ESPAsyncWebServer $HOME/arduino_ide/libraries/
|
||||||
|
- mv $TRAVIS_BUILD_DIR/libraries/ESPAsyncTCP $HOME/arduino_ide/libraries/
|
||||||
|
- mv $TRAVIS_BUILD_DIR/libraries/AsyncTCP $HOME/arduino_ide/libraries/
|
||||||
|
- mv $TRAVIS_BUILD_DIR/libraries/oled-ssd1306 $HOME/arduino_ide/libraries/
|
||||||
|
- mv $TRAVIS_BUILD_DIR/libraries/ESP32SSDP $HOME/arduino_ide/libraries/
|
||||||
|
- mv $TRAVIS_BUILD_DIR/libraries/arduinoWebSockets $HOME/arduino_ide/libraries/
|
||||||
|
- mv $TRAVIS_BUILD_DIR/libraries/DHT_sensor_library_for_ESPx $HOME/arduino_ide/libraries/
|
||||||
|
- mkdir $HOME/arduino_ide/libraries/ESP3D
|
||||||
|
- mv $TRAVIS_BUILD_DIR/src $HOME/arduino_ide/libraries/ESP3D
|
||||||
|
- mv $TRAVIS_BUILD_DIR/library.properties $HOME/arduino_ide/libraries/ESP3D
|
||||||
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
@@ -43,9 +53,21 @@ script:
|
|||||||
- export PATH="$HOME/arduino_ide:$PATH"
|
- export PATH="$HOME/arduino_ide:$PATH"
|
||||||
- arduino --board esp8266com:esp8266:generic --save-prefs
|
- arduino --board esp8266com:esp8266:generic --save-prefs
|
||||||
- arduino --get-pref sketchbook.path
|
- arduino --get-pref sketchbook.path
|
||||||
- build_sketch esp3d/esp3d.ino
|
- build_sketch $TRAVIS_BUILD_DIR/examples/basicesp3d/basicesp3d.ino
|
||||||
- arduino --board esp32:esp32:esp32 --save-prefs
|
- arduino --board esp32:esp32:esp32 --save-prefs
|
||||||
- build_sketch esp3d/esp3d.ino
|
- build_sketch $TRAVIS_BUILD_DIR/examples/basicesp3d/basicesp3d.ino
|
||||||
|
- sed -i "s/\/\/#define AUTHENTICATION_FEATURE /#define AUTHENTICATION_FEATURE/g" $HOME/arduino_ide/libraries/ESP3D/src/config.h
|
||||||
|
- arduino --board esp8266com:esp8266:generic --save-prefs
|
||||||
|
- arduino --get-pref sketchbook.path
|
||||||
|
- build_sketch $TRAVIS_BUILD_DIR/examples/basicesp3d/basicesp3d.ino
|
||||||
|
- arduino --board esp32:esp32:esp32 --save-prefs
|
||||||
|
- build_sketch $TRAVIS_BUILD_DIR/examples/basicesp3d/basicesp3d.ino
|
||||||
|
- sed -i "s/\/\/#define ASYNCWEBSERVER /#define ASYNCWEBSERVER/g" $HOME/arduino_ide/libraries/ESP3D/src/config.h
|
||||||
|
- arduino --board esp8266com:esp8266:generic --save-prefs
|
||||||
|
- arduino --get-pref sketchbook.path
|
||||||
|
- build_sketch $TRAVIS_BUILD_DIR/examples/basicesp3d/basicesp3d.ino
|
||||||
|
- arduino --board esp32:esp32:esp32 --save-prefs
|
||||||
|
- build_sketch $TRAVIS_BUILD_DIR/examples/basicesp3d/basicesp3d.ino
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
email:
|
||||||
|
|||||||
37
README.md
37
README.md
@@ -1,4 +1,4 @@
|
|||||||
# ESP3D[](https://codeclimate.com/github/luc-github/ESP3D)
|
# ESP3D 2.0 [](https://codeclimate.com/github/luc-github/ESP3D)
|
||||||
|
|
||||||
Firmware for ESP8266/ESP8285 and ESP32 used with 3D printer using [ESP8266 core version](https://github.com/esp8266/Arduino) and [ESP32 core version](https://github.com/espressif/arduino-esp32)
|
Firmware for ESP8266/ESP8285 and ESP32 used with 3D printer using [ESP8266 core version](https://github.com/esp8266/Arduino) and [ESP32 core version](https://github.com/espressif/arduino-esp32)
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ Arduino ide 1.6.5 with stable [2.0.0](http://arduino.esp8266.com/versions/2.0.0/
|
|||||||
Arduino ide 1.6.8 with stable [2.2.0](http://arduino.esp8266.com/versions/2.2.0/package_esp8266com_index.json) from ESP8266, please use https://github.com/luc-github/ESP3D/releases/tag/v0.6.2
|
Arduino ide 1.6.8 with stable [2.2.0](http://arduino.esp8266.com/versions/2.2.0/package_esp8266com_index.json) from ESP8266, please use https://github.com/luc-github/ESP3D/releases/tag/v0.6.2
|
||||||
Arduino ide 1.8.5 with stable [2.4.0](http://arduino.esp8266.com/versions/2.4.0/package_esp8266com_index.json) from ESP8266, please use https://github.com/luc-github/ESP3D/releases/tag/1.0 [](https://travis-ci.org/luc-github/ESP3D)
|
Arduino ide 1.8.5 with stable [2.4.0](http://arduino.esp8266.com/versions/2.4.0/package_esp8266com_index.json) from ESP8266, please use https://github.com/luc-github/ESP3D/releases/tag/1.0 [](https://travis-ci.org/luc-github/ESP3D)
|
||||||
|
|
||||||
<u>[Development version for 2.0 (2.0 branch)](https://github.com/luc-github/ESP3D/tree/2.0) & [ESP-WEBUI (2.0 branch)](https://github.com/luc-github/ESP3D-WEBUI/tree/2.0):</u>
|
<u>[Development version for 2.0](https://github.com/luc-github/ESP3D/tree/2.0) & [ESP-WEBUI (2.0 branch)](https://github.com/luc-github/ESP3D-WEBUI/tree/2.0):</u>
|
||||||
Arduino ide 1.8.5 with git version from ESP8266 or ESP32 for 100% support of ESP32 : [](https://travis-ci.org/luc-github/ESP3D)
|
Arduino ide 1.8.5 with git version from ESP8266 or ESP32 for 100% support of ESP32 : [](https://travis-ci.org/luc-github/ESP3D)
|
||||||
|
|
||||||
[All releases](https://github.com/luc-github/ESP3D/wiki)
|
[All releases](https://github.com/luc-github/ESP3D/wiki)
|
||||||
@@ -38,12 +38,13 @@ Especially if need to buy new modules for testing.
|
|||||||
* Authentication for sensitive pages, here to enable/disable [AUTHENTICATION_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
* Authentication for sensitive pages, here to enable/disable [AUTHENTICATION_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
||||||
* Update firmware by web browser, here to enable/disable [WEB_UPDATE_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
* Update firmware by web browser, here to enable/disable [WEB_UPDATE_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
||||||
* Control ESP module using commands on serial or data port, here to enable/disable [SERIAL_COMMAND_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
* Control ESP module using commands on serial or data port, here to enable/disable [SERIAL_COMMAND_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
||||||
* UI fully constomizable without reflashing FW using html templates, [keywords](https://raw.githubusercontent.com/luc-github/ESP3D/master/docs/keywords.txt) and html files/images
|
|
||||||
* Captive portal in Access point mode which redirect all unknow call to main page, here to enable/disable [CAPTIVE_PORTAL_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
* Captive portal in Access point mode which redirect all unknow call to main page, here to enable/disable [CAPTIVE_PORTAL_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
||||||
* mDNS which allows to key the name defined in web browser and connect only with bonjour installed on computer, here to enable/disable [MDNS_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
* mDNS which allows to key the name defined in web browser and connect only with bonjour installed on computer, here to enable/disable [MDNS_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
||||||
* SSDP, this feature is a discovery protocol, supported on Windows out of the box, here to enable/disable [SSDP_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
* SSDP, this feature is a discovery protocol, supported on Windows out of the box, here to enable/disable [SSDP_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
||||||
* Printer monitoring / control (temperatures/speed/jog/list SDCard content/launch,pause or stop a print/etc...), here to enable/disable [MONITORING_FEATURE/INFO_MSG_FEATURE/ERROR_MSG_FEATURE/STATUS_MSG_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
|
||||||
* Fail safe mode (Access point)is enabled if cannot connect to defined station at boot.
|
* Fail safe mode (Access point)is enabled if cannot connect to defined station at boot.
|
||||||
|
* Choice of web server Async or Sync
|
||||||
|
* Websocket support
|
||||||
|
* OLED screen support
|
||||||
* The web ui add even more feature : https://github.com/luc-github/ESP3D-WEBUI/blob/master/README.md#features
|
* The web ui add even more feature : https://github.com/luc-github/ESP3D-WEBUI/blob/master/README.md#features
|
||||||
|
|
||||||
|
|
||||||
@@ -70,6 +71,7 @@ Mask: 255.255.255.0
|
|||||||
GW:192.168.0.1
|
GW:192.168.0.1
|
||||||
Baud rate: 115200
|
Baud rate: 115200
|
||||||
Web port:80
|
Web port:80
|
||||||
|
On async webserver the websocket is web port => 80+1 : 81
|
||||||
Data port: 8888
|
Data port: 8888
|
||||||
Web Page refresh: 3 secondes
|
Web Page refresh: 3 secondes
|
||||||
User: admin
|
User: admin
|
||||||
@@ -84,14 +86,27 @@ Check wiki : https://github.com/luc-github/ESP3D/wiki/Direct-ESP3D-commands
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
1. Please follow installation of the ESP core you want to use : [ESP8266 core version](https://github.com/esp8266/Arduino) or [ESP32 core version](https://github.com/espressif/arduino-esp32)
|
1. Please follow installation of the ESP core you want to use : [ESP8266 core version](https://github.com/esp8266/Arduino) or [ESP32 core version](https://github.com/espressif/arduino-esp32)
|
||||||
2. Add missing libraries if you target ESP32 present in libraries directory
|
2. Add libraries
|
||||||
* DNSServer (from https://github.com/bbx10/DNSServer_tng)
|
* ESP3D because it is now a library so copy project to your arduino library folder
|
||||||
* WebServer (from https://github.com/bbx10/WebServer_tng)
|
If you want async webserver (currently not recommended for ESP8266, suggested for ESP32):
|
||||||
* NetBIOS and SSDP are currently disabled for ESP32 as not yet supported
|
* ESPAsyncWebServer from @me-no-dev
|
||||||
3. Compile project (ESP3D.ino) according target: ESP8266 board or ESP32 board, please review config.h to enable disable a feature, by default athenticatio is disabled and all others are enabled.
|
if you target ESP8266
|
||||||
|
* ESPAsyncTCP from @me-no-dev
|
||||||
|
if you target ESP32:
|
||||||
|
* AsyncTCP from @me-no-dev
|
||||||
|
Specific for ESP32
|
||||||
|
* ESP32SSDP
|
||||||
|
If you want sync webserver (recommended for ESP8266, slow for ESP32):
|
||||||
|
* arduinoWebSockets fron @Links2004
|
||||||
|
If you want OLED support:
|
||||||
|
* oled-ssd1306 from @squix78
|
||||||
|
If you want DHT11/22 support:
|
||||||
|
* DHT_sensor_library_for_ESPx from @beegee-tokyo
|
||||||
|
3. Compile project from examples\basicesp3d\basicesp3d.ino) according target: ESP8266 board or ESP32 board, please review config.h to enable disable a feature, by default athenticatio is disabled and all others are enabled.
|
||||||
* for ESP8266 set CPU freq to 160MHz for better (https://github.com/luc-github/ESP3D/wiki/Install-Instructions)
|
* for ESP8266 set CPU freq to 160MHz for better (https://github.com/luc-github/ESP3D/wiki/Install-Instructions)
|
||||||
4. Upload the data content on ESP3D file system
|
4. Upload the data content on ESP3D file system
|
||||||
* Using SPIFFS uploader, this plugin and install instructions is available on each ESP core - please refere to it
|
* Using SPIFFS uploader, this plugin and install instructions is available on each ESP core - please refere to it
|
||||||
|
or
|
||||||
* Using embedded uploader (you may need to format SPIFFS using : [ESP710]FORMAT on ESP8266 first)
|
* Using embedded uploader (you may need to format SPIFFS using : [ESP710]FORMAT on ESP8266 first)
|
||||||
if embedded uploader does not show up you can force it ti display using : http://your_IP_address?forcefallback=yes
|
if embedded uploader does not show up you can force it ti display using : http://your_IP_address?forcefallback=yes
|
||||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/docs/embedded.png><br>
|
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/docs/embedded.png><br>
|
||||||
@@ -99,7 +114,7 @@ if embedded uploader does not show up you can force it ti display using : http:/
|
|||||||
## Update
|
## Update
|
||||||
* Generate a binary using the export binary menu from Arduino IDE and upload it using ESP-WEBUI or embedded interface
|
* Generate a binary using the export binary menu from Arduino IDE and upload it using ESP-WEBUI or embedded interface
|
||||||
|
|
||||||
<H3>:warning:Do not flash your Printer fw with ESP connected - it bring troubles, at least on DaVinci</H3>
|
<H3>:warning:Do not flash your Printer fw with ESP connected on Serial - it bring troubles, at least on DaVinci, but no issue if you update using web UI</H3>
|
||||||
|
|
||||||
## Contribution/customization
|
## Contribution/customization
|
||||||
* To style the code before pushing PR please use [astyle --style=otbs *.h *.cpp *.ino](http://astyle.sourceforge.net/)
|
* To style the code before pushing PR please use [astyle --style=otbs *.h *.cpp *.ino](http://astyle.sourceforge.net/)
|
||||||
@@ -107,7 +122,6 @@ if embedded uploader does not show up you can force it ti display using : http:/
|
|||||||
* The current UI is located [here](https://github.com/luc-github/ESP3D-WEBUI)
|
* The current UI is located [here](https://github.com/luc-github/ESP3D-WEBUI)
|
||||||
* An optional UI is under development using old repetier UI - check [UI\repetier\testui.htm] (https://github.com/luc-github/ESP3D/blob/master/UI/repetier/testui.htm) file
|
* An optional UI is under development using old repetier UI - check [UI\repetier\testui.htm] (https://github.com/luc-github/ESP3D/blob/master/UI/repetier/testui.htm) file
|
||||||
|
|
||||||
Feedback/suggestion/discussions are always welcome
|
|
||||||
|
|
||||||
## Need more information about supported boards or wiring ?
|
## Need more information about supported boards or wiring ?
|
||||||
[Check the wiki](https://github.com/luc-github/ESP3D/wiki)
|
[Check the wiki](https://github.com/luc-github/ESP3D/wiki)
|
||||||
@@ -120,6 +134,7 @@ Check [Wiki](https://github.com/luc-github/ESP3D/wiki/Install-Instructions) and
|
|||||||
|
|
||||||
## ESP3D is used by :
|
## ESP3D is used by :
|
||||||
* Custom version is used on azteeg mini wifi : http://www.panucatt.com/azteeg_X5_mini_reprap_3d_printer_controller_p/ax5mini.htm
|
* Custom version is used on azteeg mini wifi : http://www.panucatt.com/azteeg_X5_mini_reprap_3d_printer_controller_p/ax5mini.htm
|
||||||
|
* Several boards, mostly chinese ones, but without noticed me, so I can't promote them here...
|
||||||
* More to come...
|
* More to come...
|
||||||
|
|
||||||
If you use ESP3D on your product, drop me a message so I can link your product page here.
|
If you use ESP3D on your product, drop me a message so I can link your product page here.
|
||||||
|
|||||||
@@ -50,9 +50,6 @@ if authentication is on, need admin password
|
|||||||
* Get hostname
|
* Get hostname
|
||||||
[ESP112]<header answer>
|
[ESP112]<header answer>
|
||||||
|
|
||||||
* Restart time client
|
|
||||||
[ESP114]
|
|
||||||
|
|
||||||
*Get/Set pin value
|
*Get/Set pin value
|
||||||
[ESP201]P<pin> V<value> [PULLUP=YES RAW=YES]pwd=<admin password>
|
[ESP201]P<pin> V<value> [PULLUP=YES RAW=YES]pwd=<admin password>
|
||||||
if no V<value> get P<pin> value
|
if no V<value> get P<pin> value
|
||||||
@@ -61,11 +58,22 @@ GPIO1 and GPIO3 cannot be used as they are used for serial
|
|||||||
if PULLUP=YES set input pull up, if not set input
|
if PULLUP=YES set input pull up, if not set input
|
||||||
if RAW=YES do not set pinmode just read value
|
if RAW=YES do not set pinmode just read value
|
||||||
|
|
||||||
|
* Output to oled column C and line L
|
||||||
|
[ESP210]C=<col> L=<line> T=<Text>
|
||||||
|
|
||||||
|
* Output to oled line 1
|
||||||
|
[ESP211]<Text>
|
||||||
|
|
||||||
|
* Output to oled line 2
|
||||||
|
[ESP212]<Text>
|
||||||
|
|
||||||
|
* Output to oled line 3
|
||||||
|
[ESP213]<Text>
|
||||||
|
|
||||||
|
* Output to oled line 4
|
||||||
|
[ESP214]<Text>
|
||||||
|
|
||||||
|
|
||||||
*Save data string
|
|
||||||
[ESP300]<data> pwd=<user/admin password>
|
|
||||||
*Get data string
|
|
||||||
[ESP301] pwd=<user/admin password>
|
|
||||||
|
|
||||||
*Get full EEPROM settings content
|
*Get full EEPROM settings content
|
||||||
but do not give any passwords
|
but do not give any passwords
|
||||||
@@ -76,6 +84,40 @@ can filter if only need wifi or printer
|
|||||||
position in EEPROM, type: B(byte), I(integer/long), S(string), A(IP address / mask)
|
position in EEPROM, type: B(byte), I(integer/long), S(string), A(IP address / mask)
|
||||||
[ESP401]P=<position> T=<type> V=<value> pwd=<user/admin password>
|
[ESP401]P=<position> T=<type> V=<value> pwd=<user/admin password>
|
||||||
|
|
||||||
|
Positions:
|
||||||
|
* EP_WIFI_MODE 0 //1 byte = flag
|
||||||
|
* EP_STA_SSID 1 //33 bytes 32+1 = string ; warning does not support multibyte char like chinese
|
||||||
|
* EP_STA_PASSWORD 34 //65 bytes 64 +1 = string ;warning does not support multibyte char like chinese
|
||||||
|
* EP_STA_IP_MODE 99 //1 byte = flag
|
||||||
|
* EP_STA_IP_VALUE 100 //4 bytes xxx.xxx.xxx.xxx
|
||||||
|
* EP_STA_MASK_VALUE 104 //4 bytes xxx.xxx.xxx.xxx
|
||||||
|
* EP_STA_GATEWAY_VALUE 108 //4 bytes xxx.xxx.xxx.xxx
|
||||||
|
* EP_BAUD_RATE 112 //4 bytes = int
|
||||||
|
* EP_STA_PHY_MODE 116 //1 byte = flag
|
||||||
|
* EP_SLEEP_MODE 117 //1 byte = flag
|
||||||
|
* EP_CHANNEL 118 //1 byte = flag
|
||||||
|
* EP_AUTH_TYPE 119 //1 byte = flag
|
||||||
|
* EP_SSID_VISIBLE 120 //1 byte = flag
|
||||||
|
* EP_WEB_PORT 121 //4 bytes = int
|
||||||
|
* EP_DATA_PORT 125 //4 bytes = int
|
||||||
|
* EP_OUTPUT_FLAG 129 //1 bytes = flag
|
||||||
|
* EP_HOSTNAME 130//33 bytes 32+1 = string ; warning does not support multibyte char like chinese
|
||||||
|
* EP_DHT_INTERVAL 164//4 bytes = int
|
||||||
|
* EP_FREE_INT2 168//4 bytes = int
|
||||||
|
* EP_FREE_INT3 172//4 bytes = int
|
||||||
|
* EP_ADMIN_PWD 176//21 bytes 20+1 = string ; warning does not support multibyte char like chinese
|
||||||
|
* EP_USER_PWD 197//21 bytes 20+1 = string ; warning does not support multibyte char like chinese
|
||||||
|
* EP_AP_SSID 218 //33 bytes 32+1 = string ; warning does not support multibyte char like chinese
|
||||||
|
* EP_AP_PASSWORD 251 //65 bytes 64 +1 = string ;warning does not support multibyte char like chinese
|
||||||
|
* EP_AP_IP_VALUE 316 //4 bytes xxx.xxx.xxx.xxx
|
||||||
|
* EP_AP_MASK_VALUE 320 //4 bytes xxx.xxx.xxx.xxx
|
||||||
|
* EP_AP_GATEWAY_VALUE 324 //4 bytes xxx.xxx.xxx.xxx
|
||||||
|
* EP_AP_IP_MODE 329 //1 byte = flag
|
||||||
|
* EP_AP_PHY_MODE 330 //1 byte = flag
|
||||||
|
* EP_FREE_STRING1 331 //129 bytes 128+1 = string ; warning does not support multibyte char like chinese
|
||||||
|
* EP_DHT_TYPE 460 //1 bytes = flag
|
||||||
|
* EP_TARGET_FW 461 //1 bytes = flag
|
||||||
|
|
||||||
*Get available AP list (limited to 30)
|
*Get available AP list (limited to 30)
|
||||||
output is JSON or plain text according parameter
|
output is JSON or plain text according parameter
|
||||||
[ESP410]<plain>
|
[ESP410]<plain>
|
||||||
@@ -109,7 +151,7 @@ if no password set it use default one
|
|||||||
* Get fw target
|
* Get fw target
|
||||||
[ESP801]<header answer>
|
[ESP801]<header answer>
|
||||||
|
|
||||||
* Clear status/error/info list
|
* Check SD presence
|
||||||
cmd can be ALL, ERROR, INFO, STATUS
|
[ESP802]
|
||||||
[ESP999]<cmd>
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
docs/Files/index.html.gz
Normal file
BIN
docs/Files/index.html.gz
Normal file
Binary file not shown.
9
docs/Readme.txt
Normal file
9
docs/Readme.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Commands.txt list all ESP commands
|
||||||
|
wconfig.txt list all parameters for SD file config
|
||||||
|
flash.docx explain how to flash
|
||||||
|
Files directory contain all files needed by ESP3D
|
||||||
|
- index.html.gz // main ui file (mandatory)
|
||||||
|
- 404.htm // custom 404 page (optional)
|
||||||
|
- favicon.ico //custom browser esp3D icon (optional)
|
||||||
|
- macrocfg.json //macro command file (optional)
|
||||||
|
|
||||||
BIN
docs/flash.docx
Normal file
BIN
docs/flash.docx
Normal file
Binary file not shown.
319
embedded/out.h
Normal file
319
embedded/out.h
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
/*
|
||||||
|
File Generated with bin2c Conversion Tool v0.14.0 - Windows - [FINAL].
|
||||||
|
Free for any use.
|
||||||
|
Compiled on Jan 1 2017 at 05:41:46.
|
||||||
|
DO NOT MODIFY THIS FILE!!!
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
ut.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
const unsigned char a[4862] = {
|
||||||
|
0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xED, 0x5C, 0x7D, 0x93, 0xDA, 0x46,
|
||||||
|
0x93, 0xFF, 0x2A, 0xB2, 0x52, 0x36, 0x70, 0x2B, 0x40, 0x12, 0xAF, 0x8B, 0x16, 0xF2, 0x24, 0xB1,
|
||||||
|
0x7D, 0xF1, 0x95, 0x13, 0xBB, 0xBC, 0xEB, 0x7B, 0xAE, 0x2A, 0x4E, 0xB9, 0x84, 0x34, 0x80, 0xCE,
|
||||||
|
0x42, 0xD2, 0x49, 0xC3, 0xEE, 0x62, 0xC2, 0x77, 0xBF, 0xEE, 0x79, 0x91, 0x46, 0x42, 0xB0, 0xEC,
|
||||||
|
0x26, 0x79, 0xF2, 0xFC, 0x91, 0x60, 0x23, 0x98, 0x99, 0xEE, 0xE9, 0xE9, 0xE9, 0xFE, 0x75, 0x4F,
|
||||||
|
0x0F, 0xCE, 0xD5, 0x8A, 0xAE, 0xC3, 0xD9, 0xD5, 0x8A, 0xB8, 0xFE, 0xEC, 0x2A, 0xA3, 0xDB, 0x90,
|
||||||
|
0xCC, 0xB0, 0x65, 0xB7, 0x88, 0x23, 0xDA, 0x5E, 0xB8, 0xEB, 0x20, 0xDC, 0x4E, 0x32, 0x37, 0xCA,
|
||||||
|
0xDA, 0x19, 0x49, 0x83, 0x85, 0xD3, 0x5E, 0x67, 0x6D, 0x4A, 0xEE, 0x69, 0x3B, 0x0B, 0xBE, 0x92,
|
||||||
|
0xB6, 0xEB, 0xFF, 0xEF, 0x26, 0xA3, 0x13, 0xCB, 0x34, 0x9F, 0x3B, 0xED, 0x3B, 0x32, 0xFF, 0x12,
|
||||||
|
0xD0, 0x23, 0xBD, 0x8C, 0x1D, 0xB6, 0xC2, 0xD7, 0xE4, 0x7E, 0x3F, 0x8F, 0xFD, 0x6D, 0x69, 0x0A,
|
||||||
|
0xFD, 0x47, 0x12, 0xDE, 0x12, 0x1A, 0x78, 0xAE, 0xF6, 0x33, 0xD9, 0x10, 0xDD, 0xC8, 0xBF, 0x1B,
|
||||||
|
0xDF, 0xA5, 0x81, 0x1B, 0x1A, 0x8A, 0x0C, 0x0A, 0xAF, 0x7E, 0x72, 0xEF, 0x84, 0x41, 0x44, 0xDA,
|
||||||
|
0x2B, 0x12, 0x2C, 0x57, 0x30, 0x57, 0xA7, 0x6F, 0x8F, 0x07, 0x23, 0xAB, 0xDF, 0x73, 0xBC, 0x38,
|
||||||
|
0x8C, 0xD3, 0xC9, 0x37, 0xBD, 0x5E, 0xCF, 0x99, 0xBB, 0xDE, 0x97, 0x65, 0x1A, 0x6F, 0x22, 0xBF,
|
||||||
|
0x2D, 0x5A, 0x17, 0x8B, 0xC5, 0xBE, 0xE3, 0x01, 0x1F, 0x17, 0x88, 0xD3, 0xDD, 0xDA, 0x4D, 0x97,
|
||||||
|
0x41, 0xD4, 0x4E, 0x19, 0x0F, 0x77, 0x43, 0x63, 0x47, 0xB4, 0x84, 0x64, 0x21, 0x1A, 0x12, 0xD7,
|
||||||
|
0xF7, 0x83, 0x68, 0xC9, 0x5B, 0xAC, 0x01, 0xCC, 0x2B, 0x5B, 0x38, 0x15, 0x36, 0xED, 0xA9, 0x3B,
|
||||||
|
0x0F, 0xC9, 0x6E, 0x1E, 0xA7, 0x3E, 0x49, 0x27, 0xA6, 0xC3, 0x3F, 0xB4, 0xB3, 0xC4, 0xF5, 0x60,
|
||||||
|
0x20, 0x34, 0xAC, 0xDD, 0xFB, 0xF6, 0x5D, 0xE0, 0xD3, 0x15, 0x53, 0xCA, 0xBE, 0xC3, 0xC6, 0xB7,
|
||||||
|
0xF9, 0x30, 0xE2, 0xEF, 0x8A, 0x2E, 0x41, 0x3A, 0xB1, 0x92, 0x7B, 0x2D, 0x8B, 0xC3, 0xC0, 0xD7,
|
||||||
|
0xBE, 0xF1, 0x7D, 0x5F, 0x4A, 0x35, 0x8F, 0x29, 0x8D, 0xD7, 0x13, 0x1B, 0x35, 0x49, 0x81, 0x6C,
|
||||||
|
0x15, 0x50, 0xC2, 0x66, 0x21, 0x93, 0x28, 0xBE, 0x4B, 0xDD, 0x44, 0xCA, 0x36, 0xB1, 0xD7, 0xEB,
|
||||||
|
0x3D, 0x5D, 0xED, 0xD8, 0x9E, 0xB8, 0x61, 0xB0, 0x8C, 0x26, 0x28, 0xBF, 0x98, 0x78, 0x46, 0x71,
|
||||||
|
0x1B, 0x66, 0x34, 0x9D, 0x51, 0xDF, 0x38, 0x68, 0x5A, 0xE5, 0x4D, 0xCC, 0x36, 0xCA, 0xA3, 0xF2,
|
||||||
|
0xA6, 0xD5, 0x4E, 0x4E, 0x35, 0x3E, 0xBE, 0x15, 0xB7, 0x24, 0xC5, 0x9D, 0x0C, 0x85, 0x08, 0x34,
|
||||||
|
0x4E, 0xA4, 0x6A, 0xE0, 0x63, 0x65, 0x8D, 0x55, 0xA5, 0xD4, 0x08, 0x59, 0xD7, 0xB7, 0x3A, 0xEC,
|
||||||
|
0x3B, 0x10, 0xBB, 0xAE, 0x6F, 0xB5, 0xAB, 0xD5, 0xF4, 0xA1, 0x14, 0x8F, 0xE2, 0x26, 0x76, 0x48,
|
||||||
|
0xEC, 0xB5, 0x0D, 0xDB, 0x24, 0x68, 0x32, 0x9A, 0x06, 0x89, 0x22, 0xF8, 0x24, 0xA2, 0xAB, 0x76,
|
||||||
|
0xBC, 0x68, 0xD3, 0x6D, 0x42, 0x9A, 0xB1, 0xEF, 0xB7, 0x76, 0x35, 0xB6, 0x7A, 0x89, 0xAF, 0xFD,
|
||||||
|
0x3F, 0xD6, 0xC4, 0x0F, 0x5C, 0xAD, 0xB9, 0x06, 0x03, 0xE0, 0x7C, 0x47, 0x43, 0xD0, 0x79, 0x6B,
|
||||||
|
0xA7, 0xD8, 0xB1, 0x68, 0x1F, 0xA0, 0x61, 0xD4, 0x10, 0x5C, 0x5E, 0xDA, 0xB5, 0x04, 0x97, 0xA3,
|
||||||
|
0x23, 0x04, 0x96, 0x6D, 0x9A, 0xB5, 0x14, 0x96, 0xC5, 0x49, 0x3A, 0x91, 0x7B, 0xAB, 0x9A, 0xAD,
|
||||||
|
0x10, 0xD9, 0xF3, 0xBC, 0x8A, 0xC3, 0x98, 0x55, 0x77, 0x31, 0xC1, 0x58, 0x32, 0x70, 0x63, 0x44,
|
||||||
|
0x1C, 0xB0, 0xDA, 0x88, 0xD4, 0x78, 0x29, 0xF3, 0x5D, 0xAE, 0xD0, 0xD4, 0xF5, 0x83, 0x4D, 0x36,
|
||||||
|
0x19, 0x82, 0x91, 0xD5, 0x38, 0x81, 0xBB, 0x4B, 0xE2, 0x2C, 0xA0, 0x41, 0x1C, 0x4D, 0x52, 0x12,
|
||||||
|
0xBA, 0x34, 0xB8, 0x25, 0x8E, 0x1F, 0x64, 0x49, 0xE8, 0x6E, 0x27, 0xF3, 0x30, 0xF6, 0xBE, 0xE4,
|
||||||
|
0x0E, 0x81, 0xE8, 0xA3, 0x31, 0xF7, 0x65, 0x3E, 0xE1, 0x13, 0x2F, 0x4E, 0x5D, 0x46, 0xC8, 0x64,
|
||||||
|
0x28, 0xE4, 0xDF, 0x77, 0x5C, 0x0F, 0xF9, 0xEC, 0x0A, 0xC4, 0xA8, 0x91, 0xD0, 0x34, 0x4D, 0x39,
|
||||||
|
0x50, 0x73, 0x0D, 0x77, 0xB2, 0x88, 0xBD, 0x4D, 0x06, 0xCF, 0x55, 0x0C, 0x36, 0xBF, 0x53, 0xC1,
|
||||||
|
0x26, 0x71, 0x23, 0x12, 0xEE, 0x0E, 0x65, 0xAF, 0x07, 0xA7, 0x23, 0xFE, 0x5F, 0x56, 0x06, 0x82,
|
||||||
|
0x9F, 0x44, 0xDD, 0x79, 0x7C, 0xDF, 0xCE, 0x56, 0xAE, 0x1F, 0xDF, 0x4D, 0x4C, 0x0D, 0xA9, 0xF0,
|
||||||
|
0x6F, 0xBA, 0x9C, 0xBB, 0x4D, 0xD3, 0xC0, 0x57, 0xC7, 0x1C, 0xB4, 0x9C, 0x73, 0x06, 0x09, 0x49,
|
||||||
|
0xDB, 0x0C, 0xA1, 0x73, 0xAD, 0x21, 0xB8, 0x89, 0x0E, 0x34, 0x76, 0x68, 0xDB, 0x1D, 0x6A, 0xF4,
|
||||||
|
0x34, 0xE2, 0x0E, 0xF0, 0x25, 0x57, 0x20, 0x1A, 0x95, 0x35, 0x01, 0x12, 0x70, 0xD3, 0x90, 0xAB,
|
||||||
|
0xEB, 0xA1, 0x6E, 0x8A, 0x3E, 0x34, 0xA3, 0x9A, 0x2E, 0xA1, 0xC9, 0x8A, 0xF7, 0x86, 0xEE, 0x1C,
|
||||||
|
0x94, 0x2D, 0x2D, 0x20, 0x88, 0x18, 0x2E, 0x71, 0x43, 0x28, 0x43, 0x70, 0xC5, 0x98, 0x70, 0x15,
|
||||||
|
0x2C, 0xBA, 0xDC, 0x71, 0x0C, 0x1B, 0xE1, 0xF6, 0x32, 0x43, 0x09, 0xA2, 0x45, 0x2C, 0xF7, 0xB3,
|
||||||
|
0x07, 0xC6, 0x3F, 0x86, 0x2D, 0x5D, 0xC4, 0xE9, 0xBA, 0x8D, 0x9E, 0x91, 0xC6, 0xC5, 0x64, 0x7C,
|
||||||
|
0x16, 0x3E, 0x03, 0x0B, 0x1C, 0x02, 0x0E, 0x7B, 0xFD, 0x22, 0x64, 0xA0, 0x19, 0x6B, 0x96, 0x2D,
|
||||||
|
0x27, 0x3B, 0x37, 0x94, 0x0D, 0x06, 0x83, 0x63, 0xD6, 0x52, 0xB4, 0x06, 0x6B, 0x77, 0x29, 0x1D,
|
||||||
|
0xEA, 0xC0, 0x86, 0xD0, 0x2F, 0xCF, 0xB2, 0xA1, 0x20, 0xCA, 0x08, 0xD5, 0x8E, 0x18, 0xC9, 0xA8,
|
||||||
|
0x6C, 0x4A, 0x0F, 0x8E, 0x6D, 0xC7, 0x6D, 0x9A, 0x42, 0xF8, 0xE6, 0x0E, 0xAA, 0x5A, 0x80, 0x46,
|
||||||
|
0xDC, 0x8C, 0x80, 0x6E, 0xDB, 0xF1, 0x86, 0x6A, 0x1D, 0x6B, 0x90, 0x19, 0x05, 0xDF, 0x83, 0xBE,
|
||||||
|
0xB2, 0xC2, 0xB9, 0xAB, 0xED, 0xCA, 0xF6, 0x34, 0x1C, 0xBA, 0x0B, 0x72, 0xE9, 0x00, 0x05, 0x6A,
|
||||||
|
0x12, 0x02, 0xEE, 0x13, 0x96, 0x66, 0x98, 0xD0, 0x39, 0x96, 0x1D, 0x96, 0x69, 0x1B, 0xD6, 0x68,
|
||||||
|
0x60, 0xD8, 0xBD, 0x9E, 0xD1, 0x19, 0xB6, 0x84, 0x0C, 0xA8, 0xEB, 0xA4, 0xE2, 0xCC, 0xDC, 0x47,
|
||||||
|
0xE6, 0x34, 0x3A, 0x66, 0x77, 0xEA, 0x60, 0xB3, 0x64, 0x66, 0x7D, 0xD3, 0x74, 0x94, 0x10, 0xED,
|
||||||
|
0x91, 0x88, 0x92, 0xB4, 0x1A, 0x35, 0xD7, 0x81, 0xEF, 0x87, 0x84, 0x27, 0x60, 0xF1, 0xC6, 0x5B,
|
||||||
|
0xB5, 0x11, 0x76, 0x40, 0x9F, 0x6B, 0x37, 0x0A, 0x92, 0x4D, 0xC8, 0x40, 0xCC, 0x39, 0xDE, 0xE3,
|
||||||
|
0x6D, 0xD2, 0x0C, 0x54, 0x94, 0xC4, 0x01, 0x63, 0x7E, 0xA6, 0xC5, 0xB0, 0x7D, 0x4B, 0xDC, 0x14,
|
||||||
|
0x24, 0x72, 0x4E, 0xA4, 0x19, 0x8F, 0xB4, 0xE7, 0x1A, 0x13, 0x5C, 0xC7, 0x5F, 0xDB, 0x9B, 0x0C,
|
||||||
|
0x93, 0x25, 0x12, 0x12, 0x8F, 0x72, 0x71, 0x70, 0xAD, 0x07, 0x8D, 0xD5, 0x06, 0xA6, 0xF3, 0x76,
|
||||||
|
0x92, 0xC2, 0x32, 0xD2, 0xED, 0x69, 0xB4, 0xEE, 0xF5, 0x46, 0xEE, 0x7C, 0x54, 0xC1, 0x20, 0x9B,
|
||||||
|
0x0C, 0x7D, 0xB7, 0x5F, 0xE2, 0x22, 0x10, 0xDD, 0x28, 0xB5, 0x71, 0x68, 0x2F, 0x35, 0x31, 0x94,
|
||||||
|
0x2F, 0x35, 0x4D, 0x6A, 0x28, 0x27, 0x87, 0x94, 0x07, 0xF1, 0xA1, 0x46, 0x58, 0x7B, 0x3C, 0x34,
|
||||||
|
0x2F, 0xCD, 0x8A, 0xB0, 0x96, 0x6D, 0xCF, 0xFB, 0xE6, 0xDE, 0x73, 0x13, 0xDC, 0x54, 0x89, 0xC1,
|
||||||
|
0x2C, 0x8D, 0x1A, 0x2B, 0x29, 0xA9, 0xB0, 0xB2, 0x71, 0x01, 0xCA, 0xA3, 0xD1, 0xC8, 0x39, 0xC8,
|
||||||
|
0x02, 0xDD, 0x10, 0x4C, 0xAC, 0x04, 0xF2, 0x35, 0xC1, 0xF5, 0xB4, 0x51, 0x1C, 0x6C, 0xA5, 0xE0,
|
||||||
|
0xDA, 0xCE, 0x36, 0x9E, 0x47, 0xB2, 0xAC, 0x26, 0x9F, 0xF1, 0x17, 0x0B, 0xD3, 0x1F, 0x57, 0x23,
|
||||||
|
0xC1, 0x90, 0x5C, 0x7A, 0xC3, 0x3C, 0x84, 0x78, 0xA3, 0x61, 0xCF, 0x97, 0xAC, 0x7C, 0x37, 0x5A,
|
||||||
|
0x82, 0xB6, 0x6A, 0xA0, 0xCF, 0xF6, 0x89, 0x4F, 0x2A, 0x9C, 0xC8, 0xDC, 0xF3, 0x7C, 0x4B, 0x72,
|
||||||
|
0x72, 0x2F, 0xFB, 0xFD, 0xBE, 0xBD, 0xEF, 0xAC, 0xDC, 0xAC, 0x4D, 0xD2, 0x14, 0x20, 0xA7, 0x0C,
|
||||||
|
0xDB, 0x65, 0x5A, 0x3E, 0xFA, 0xCF, 0x06, 0xC4, 0xA3, 0xD2, 0xD4, 0x62, 0xDA, 0xB8, 0xDF, 0x1B,
|
||||||
|
0xF4, 0xFA, 0x4F, 0x46, 0x32, 0x74, 0xCD, 0x6F, 0x3C, 0x32, 0xEE, 0x8F, 0x7B, 0x8F, 0x91, 0xB1,
|
||||||
|
0x4A, 0x5B, 0x92, 0x59, 0x88, 0xDB, 0xE6, 0x61, 0xB6, 0x46, 0xD3, 0x62, 0xF3, 0x4F, 0xEA, 0x9A,
|
||||||
|
0xEF, 0xF1, 0xBF, 0x46, 0xD7, 0xB5, 0xF2, 0xD4, 0x6A, 0xDB, 0x9E, 0x0F, 0xFA, 0xB6, 0xF7, 0xFB,
|
||||||
|
0xB4, 0x3D, 0x1C, 0xCD, 0xAD, 0xE1, 0xF8, 0x69, 0xDA, 0xE6, 0xB4, 0x15, 0xA9, 0x6B, 0xF5, 0x2D,
|
||||||
|
0x7D, 0x04, 0x61, 0x45, 0x78, 0xC8, 0x49, 0x3C, 0xF1, 0x2F, 0xC1, 0x8C, 0x16, 0x55, 0xB7, 0xEB,
|
||||||
|
0xF7, 0x16, 0x3D, 0x57, 0x65, 0x52, 0xC2, 0x3E, 0xD1, 0xA4, 0x00, 0x98, 0x68, 0x51, 0x90, 0x8F,
|
||||||
|
0xB7, 0x4C, 0x0E, 0xC9, 0x26, 0x07, 0x64, 0xE7, 0xC0, 0x9E, 0x77, 0xD9, 0x33, 0x6D, 0xAF, 0x22,
|
||||||
|
0xE6, 0x68, 0x68, 0x79, 0xD6, 0x25, 0x13, 0x33, 0x58, 0x2F, 0x77, 0x22, 0x96, 0xAD, 0xDC, 0xA8,
|
||||||
|
0x9A, 0x12, 0x0F, 0xEB, 0xF0, 0x8A, 0x27, 0xE0, 0x9C, 0x56, 0x88, 0x50, 0x83, 0x25, 0x26, 0xBE,
|
||||||
|
0x2A, 0xF3, 0x9A, 0x20, 0xE2, 0x5F, 0xEE, 0x78, 0x20, 0x38, 0x93, 0xF4, 0xF4, 0xCA, 0x7B, 0xA6,
|
||||||
|
0x48, 0x3F, 0xE4, 0xD8, 0x87, 0x56, 0xFA, 0xD7, 0xAF, 0x2B, 0x04, 0xD1, 0x20, 0x43, 0xF8, 0x22,
|
||||||
|
0x0D, 0x82, 0x1D, 0xA6, 0xF2, 0xD6, 0x89, 0xB0, 0xB1, 0x45, 0x10, 0x12, 0xF6, 0x9D, 0xBB, 0x6B,
|
||||||
|
0x3E, 0xF6, 0xB2, 0x0F, 0xBB, 0x1A, 0x44, 0xC9, 0x86, 0xFE, 0x82, 0xA7, 0xE7, 0x29, 0x8E, 0xFB,
|
||||||
|
0x75, 0x32, 0x91, 0xCB, 0xC2, 0xAF, 0xED, 0x4D, 0x12, 0xC6, 0xAE, 0xDF, 0x9E, 0x6F, 0x20, 0x9A,
|
||||||
|
0xFD, 0x9D, 0x97, 0xFD, 0x6B, 0xF3, 0x32, 0xE7, 0xA4, 0x9B, 0x0F, 0xE6, 0x9E, 0x79, 0x10, 0xBA,
|
||||||
|
0xFB, 0xC3, 0xF9, 0xD8, 0x77, 0x1F, 0xB5, 0xA9, 0xC2, 0x2A, 0xFE, 0xDE, 0xDA, 0x7F, 0x9F, 0xAD,
|
||||||
|
0xED, 0x59, 0x73, 0xD3, 0xAF, 0x9E, 0xF4, 0xAD, 0xF9, 0xD0, 0x1F, 0x0F, 0x1E, 0xB7, 0xB5, 0x1C,
|
||||||
|
0xC0, 0xFE, 0xDE, 0xDA, 0x7F, 0xF3, 0xAD, 0xB5, 0x87, 0x97, 0xEE, 0xDC, 0xDB, 0xE7, 0x40, 0x5D,
|
||||||
|
0x82, 0xF3, 0x32, 0x7A, 0x2B, 0x68, 0x5E, 0x4A, 0x05, 0x04, 0x9A, 0x8B, 0x0A, 0xD3, 0x22, 0x8E,
|
||||||
|
0x41, 0xA9, 0x27, 0x0A, 0x4C, 0xAC, 0xFE, 0xF2, 0xB4, 0x1A, 0xD3, 0x41, 0x9D, 0x17, 0x0D, 0x0E,
|
||||||
|
0xC3, 0x24, 0xDF, 0xAB, 0xBE, 0x92, 0x34, 0xF4, 0xF0, 0xA5, 0x92, 0x2A, 0x9D, 0xBD, 0xFE, 0xE5,
|
||||||
|
0xD8, 0x9F, 0x57, 0x54, 0x3F, 0x30, 0x9F, 0x3B, 0xB2, 0x6E, 0x0A, 0xD2, 0xCA, 0x9D, 0xC2, 0xCF,
|
||||||
|
0x60, 0x3B, 0x6B, 0x5E, 0x66, 0xCC, 0x92, 0x20, 0xD2, 0xEC, 0x4C, 0xC3, 0xCD, 0x74, 0x53, 0x2D,
|
||||||
|
0x88, 0x16, 0x41, 0x04, 0x96, 0xB0, 0xFF, 0xC7, 0x17, 0xB2, 0x5D, 0xA4, 0xEE, 0x9A, 0x64, 0x1A,
|
||||||
|
0x0E, 0xD9, 0x99, 0xCF, 0x77, 0xCC, 0x5C, 0x30, 0x63, 0x9D, 0xA4, 0x31, 0x75, 0x29, 0x69, 0x9A,
|
||||||
|
0xAD, 0x3D, 0x16, 0xAD, 0x0E, 0x3B, 0x7A, 0x43, 0x00, 0xD3, 0x65, 0x6B, 0xFF, 0x97, 0x68, 0x70,
|
||||||
|
0x1D, 0xFB, 0x6E, 0x51, 0xFF, 0x62, 0x46, 0x94, 0x57, 0x63, 0x17, 0xC1, 0x3D, 0xF1, 0x9D, 0xAF,
|
||||||
|
0xED, 0x20, 0xF2, 0xC9, 0x3D, 0x56, 0xDC, 0xCC, 0xA2, 0x10, 0xCC, 0x78, 0x61, 0x7D, 0xD9, 0x61,
|
||||||
|
0x25, 0x62, 0x70, 0x5A, 0x68, 0x30, 0x1D, 0xA5, 0x38, 0x27, 0x35, 0x88, 0x9F, 0xD1, 0x5C, 0x16,
|
||||||
|
0x21, 0x24, 0x1A, 0xAC, 0xA8, 0x56, 0x5B, 0x89, 0x3D, 0x6C, 0x55, 0x93, 0x90, 0x7E, 0x4B, 0x88,
|
||||||
|
0xCA, 0xF2, 0x7F, 0x70, 0xC1, 0x5D, 0xB1, 0xA6, 0x52, 0x75, 0xD1, 0x32, 0xCB, 0x95, 0xC7, 0x52,
|
||||||
|
0x55, 0x52, 0xED, 0x14, 0x45, 0xFE, 0x63, 0xB4, 0xA2, 0xFB, 0x18, 0x39, 0x5E, 0x0B, 0xE4, 0xE6,
|
||||||
|
0x24, 0x0B, 0x13, 0x4A, 0x7D, 0x16, 0x4B, 0x50, 0x16, 0x42, 0x81, 0x59, 0xCA, 0xA5, 0xEC, 0x96,
|
||||||
|
0x73, 0x58, 0xEB, 0xE6, 0x70, 0x58, 0xBA, 0xA8, 0x9A, 0xD4, 0xA8, 0xE3, 0x9B, 0x05, 0xC1, 0x97,
|
||||||
|
0xD4, 0x03, 0x56, 0x72, 0x15, 0x2B, 0xB1, 0xC5, 0x84, 0x4E, 0x9E, 0xFC, 0xE2, 0xAB, 0x8E, 0x8B,
|
||||||
|
0x8D, 0xAF, 0x63, 0xC5, 0xD9, 0x47, 0xAA, 0xAF, 0x54, 0x9E, 0x5C, 0xE0, 0x4B, 0x8A, 0x57, 0xAE,
|
||||||
|
0x40, 0x9B, 0x42, 0x3A, 0xD9, 0x5B, 0x35, 0xF1, 0xA1, 0x94, 0x5E, 0x18, 0x4D, 0xBF, 0x33, 0x20,
|
||||||
|
0xEB, 0xC7, 0x2F, 0xE5, 0x50, 0x9C, 0xDF, 0xB9, 0xDB, 0x27, 0xEE, 0x6D, 0xCA, 0xD6, 0xC8, 0xFB,
|
||||||
|
0x06, 0x63, 0xF5, 0x2A, 0x26, 0xF3, 0x52, 0x42, 0x22, 0x0D, 0xB2, 0x7D, 0xA0, 0xCF, 0x0B, 0xD7,
|
||||||
|
0xA3, 0xE1, 0xE8, 0x28, 0x3D, 0xBB, 0x57, 0xDC, 0x5F, 0x75, 0xF9, 0x4D, 0xEE, 0x55, 0x97, 0xDF,
|
||||||
|
0xEB, 0xB2, 0xDB, 0xA6, 0x2B, 0x3F, 0xB8, 0xD5, 0x58, 0xFB, 0x54, 0xCF, 0x4D, 0xC8, 0x9D, 0xC3,
|
||||||
|
0x62, 0x37, 0x94, 0x08, 0xE7, 0xE3, 0x97, 0x33, 0xA6, 0x3E, 0xFB, 0x6F, 0xAB, 0x63, 0x6B, 0x2F,
|
||||||
|
0xA2, 0x79, 0x96, 0x38, 0xFC, 0xFD, 0xAA, 0x0B, 0xE4, 0xB3, 0x2B, 0x1E, 0x4D, 0x67, 0x57, 0x2B,
|
||||||
|
0x7B, 0xF6, 0x86, 0x6A, 0x19, 0x21, 0xEB, 0x4C, 0xDB, 0xC6, 0x1B, 0xCD, 0x8F, 0xB5, 0x28, 0xA6,
|
||||||
|
0xDA, 0xCA, 0xC5, 0x8B, 0x90, 0x68, 0xAB, 0x31, 0x87, 0xEF, 0xE0, 0x4D, 0xB2, 0x16, 0x91, 0x80,
|
||||||
|
0xAE, 0x48, 0xAA, 0x34, 0x75, 0x96, 0x5F, 0x0D, 0x2D, 0x09, 0xB1, 0xC0, 0xAB, 0xF1, 0x90, 0xAF,
|
||||||
|
0x05, 0x54, 0x8B, 0x53, 0xF8, 0xE2, 0x03, 0x9C, 0x21, 0xC3, 0x54, 0x5B, 0x04, 0xE9, 0xFA, 0x0E,
|
||||||
|
0x62, 0xA5, 0x16, 0x2C, 0x80, 0x05, 0x1E, 0x84, 0xB1, 0xE4, 0x06, 0x2B, 0xB2, 0x67, 0x38, 0xA1,
|
||||||
|
0xE7, 0x46, 0x30, 0x04, 0x14, 0x03, 0x78, 0xA3, 0x01, 0x7B, 0xA2, 0x4D, 0xB4, 0x2B, 0x57, 0xF3,
|
||||||
|
0x42, 0x37, 0xCB, 0xA6, 0x7A, 0x7E, 0x8A, 0xD0, 0xB5, 0x55, 0x4A, 0x16, 0x53, 0x7D, 0x45, 0x69,
|
||||||
|
0x92, 0x4D, 0xBA, 0xDD, 0x25, 0xC8, 0xB2, 0x99, 0xC3, 0x89, 0x7A, 0xDD, 0x0D, 0x37, 0x5E, 0x9B,
|
||||||
|
0x7F, 0xED, 0xBE, 0xBA, 0x7E, 0xDF, 0x7B, 0xD9, 0xFE, 0xE7, 0xAB, 0xEF, 0x3F, 0xBE, 0xD1, 0x67,
|
||||||
|
0x67, 0x0F, 0xBD, 0xEA, 0xBA, 0xA0, 0x61, 0xA9, 0x11, 0xD4, 0xAE, 0x98, 0x9D, 0x81, 0xB0, 0xAE,
|
||||||
|
0x05, 0xFE, 0x54, 0xBF, 0x7E, 0xFF, 0xE6, 0xF5, 0xEB, 0x6B, 0xFD, 0xB0, 0x5B, 0xDE, 0xA3, 0xE8,
|
||||||
|
0xB3, 0xD7, 0xD0, 0xBA, 0xD2, 0x5E, 0x43, 0x60, 0xCC, 0xB6, 0x19, 0x25, 0x6B, 0xA1, 0xE9, 0x03,
|
||||||
|
0x02, 0xDC, 0x44, 0x60, 0xC4, 0x52, 0x28, 0x8D, 0xA5, 0x50, 0x3A, 0x46, 0x53, 0x3E, 0x0F, 0x4B,
|
||||||
|
0x9F, 0x78, 0x1C, 0xD7, 0xB5, 0x08, 0xC2, 0xC8, 0x54, 0x5F, 0x6F, 0xB1, 0x31, 0xFB, 0xE5, 0x57,
|
||||||
|
0x5D, 0x5B, 0x6F, 0x42, 0x1A, 0x24, 0xB8, 0xF1, 0xF2, 0x93, 0x3E, 0xD3, 0x04, 0x27, 0xA9, 0x31,
|
||||||
|
0x1A, 0x69, 0x4A, 0x85, 0x52, 0x17, 0x33, 0xF0, 0x54, 0x8C, 0xCF, 0x51, 0xCA, 0xCE, 0x74, 0x50,
|
||||||
|
0xBC, 0x17, 0x06, 0xDE, 0x17, 0x58, 0x23, 0x89, 0x7C, 0x9C, 0xAA, 0xD9, 0x72, 0x74, 0xED, 0xD6,
|
||||||
|
0x0D, 0x37, 0x40, 0xF7, 0x91, 0x8D, 0xD5, 0x67, 0x25, 0x13, 0x4A, 0xD2, 0x78, 0x99, 0x62, 0x45,
|
||||||
|
0x43, 0x58, 0xE1, 0x6D, 0x90, 0x05, 0xF3, 0x20, 0x0C, 0xE8, 0x76, 0xB2, 0x82, 0x7C, 0x8C, 0x44,
|
||||||
|
0x52, 0xF4, 0x24, 0x5D, 0xF2, 0x29, 0xD9, 0x07, 0xB0, 0xFC, 0xA9, 0x0E, 0x86, 0x0D, 0x8B, 0xEF,
|
||||||
|
0x4A, 0x16, 0x60, 0xD3, 0x29, 0xFF, 0x7B, 0xA0, 0xF7, 0xE3, 0xAA, 0xE3, 0x97, 0xD7, 0x57, 0x14,
|
||||||
|
0xA8, 0xA8, 0xAF, 0x31, 0x87, 0x99, 0xEA, 0xE6, 0xF3, 0x5C, 0xA9, 0xE7, 0xA9, 0xA2, 0xB4, 0xEE,
|
||||||
|
0x1F, 0xE2, 0x35, 0x24, 0x86, 0x7E, 0xB3, 0x81, 0xB7, 0x99, 0x0D, 0xA3, 0xE1, 0x86, 0x61, 0x43,
|
||||||
|
0x51, 0xC3, 0x07, 0xB2, 0x00, 0x69, 0x57, 0x28, 0x39, 0xF5, 0x0F, 0x66, 0x45, 0x39, 0x73, 0x6E,
|
||||||
|
0x3F, 0xA4, 0x04, 0x6C, 0xDF, 0x0F, 0xD2, 0x66, 0x4B, 0x57, 0x24, 0x81, 0x93, 0x3C, 0x8C, 0xCC,
|
||||||
|
0x6E, 0x97, 0x92, 0xB2, 0x6F, 0x82, 0x4D, 0x33, 0x8C, 0xE3, 0x9F, 0x6F, 0x03, 0x72, 0xF7, 0x7D,
|
||||||
|
0x0C, 0x1A, 0xC2, 0x03, 0x76, 0x1F, 0xFF, 0xC0, 0xF8, 0x14, 0xEC, 0x40, 0x83, 0xB6, 0x81, 0xAE,
|
||||||
|
0x6D, 0x51, 0x77, 0xBA, 0xA4, 0xEE, 0x29, 0xD4, 0x36, 0x7C, 0x4E, 0x61, 0x90, 0x0D, 0x8F, 0x2D,
|
||||||
|
0x7B, 0xC0, 0x2E, 0x86, 0x53, 0x5D, 0xA4, 0x79, 0x7A, 0xB7, 0xE0, 0x83, 0x43, 0xB7, 0x8C, 0x9D,
|
||||||
|
0xE0, 0x63, 0x0D, 0x0A, 0x3E, 0xF8, 0xF9, 0x01, 0x3E, 0x98, 0x8F, 0x23, 0x1F, 0x8B, 0x0B, 0x64,
|
||||||
|
0xC3, 0x23, 0x4F, 0x6E, 0xA1, 0x75, 0x2C, 0xBE, 0xDE, 0x09, 0x8E, 0x63, 0xD8, 0x6C, 0xC1, 0x84,
|
||||||
|
0xE5, 0xC9, 0xFA, 0xEC, 0x02, 0x14, 0x08, 0x3C, 0x40, 0x8F, 0xA0, 0x8A, 0x99, 0x70, 0x11, 0xA1,
|
||||||
|
0x53, 0xAE, 0x48, 0x34, 0x17, 0x9E, 0xCC, 0xE5, 0xEA, 0x13, 0x5F, 0x2B, 0xC3, 0xF3, 0x25, 0x98,
|
||||||
|
0xF9, 0x26, 0x30, 0x53, 0x73, 0xE9, 0x2A, 0xA7, 0xC4, 0xEB, 0x3E, 0x69, 0xBC, 0x2A, 0x75, 0x17,
|
||||||
|
0x6D, 0xA7, 0x2B, 0xED, 0x08, 0x1F, 0x92, 0x82, 0x7F, 0x29, 0xDD, 0xF2, 0xEB, 0xD2, 0xCE, 0x8B,
|
||||||
|
0x83, 0x00, 0x1A, 0x21, 0x87, 0x64, 0x66, 0x84, 0x2B, 0xD5, 0x1C, 0x6E, 0xC0, 0xCA, 0x80, 0xF7,
|
||||||
|
0x0A, 0xDB, 0x67, 0x3F, 0x83, 0x1F, 0xE4, 0x5F, 0xAE, 0x41, 0x4B, 0xF2, 0x4B, 0xC9, 0x80, 0x2A,
|
||||||
|
0x6D, 0x62, 0x45, 0xAC, 0x55, 0x48, 0x2A, 0x26, 0x43, 0x07, 0xC8, 0x71, 0xE2, 0x33, 0xDA, 0x2A,
|
||||||
|
0x1B, 0xC7, 0xE3, 0x82, 0x5C, 0xCF, 0x11, 0xDC, 0xE1, 0x91, 0x96, 0xFB, 0x63, 0x06, 0xE9, 0xE6,
|
||||||
|
0x26, 0x2B, 0x34, 0x7A, 0xF0, 0x7E, 0x8E, 0x37, 0x16, 0xC8, 0x27, 0x21, 0xFE, 0x23, 0xC3, 0xFD,
|
||||||
|
0x07, 0x80, 0xAF, 0xE4, 0xBD, 0x47, 0x71, 0xF0, 0xEE, 0x28, 0x0A, 0x2A, 0xF6, 0xF2, 0x34, 0xE4,
|
||||||
|
0x03, 0xDE, 0x07, 0x18, 0xC0, 0x71, 0xEE, 0x10, 0xFD, 0x70, 0x3D, 0xEA, 0x8C, 0x8F, 0x81, 0xBE,
|
||||||
|
0xC5, 0x5D, 0x0E, 0x7E, 0xF8, 0xB1, 0x1E, 0xFE, 0x72, 0xCE, 0x70, 0x84, 0x8C, 0xD8, 0xF0, 0x75,
|
||||||
|
0xB6, 0xD4, 0x8F, 0xB3, 0x9F, 0x7D, 0x20, 0xB0, 0x79, 0x70, 0x06, 0x8E, 0x96, 0x79, 0xEC, 0xBD,
|
||||||
|
0x73, 0x03, 0xDA, 0x81, 0xFF, 0xC0, 0xA9, 0x80, 0x89, 0xC2, 0xCA, 0x83, 0x1C, 0x89, 0x72, 0xCF,
|
||||||
|
0xE1, 0x3D, 0x87, 0xC6, 0x5F, 0xDD, 0x74, 0xEE, 0x7E, 0x90, 0x85, 0x26, 0x70, 0xFE, 0xCD, 0xFD,
|
||||||
|
0x88, 0xA5, 0x28, 0x65, 0x1B, 0x28, 0x65, 0x2D, 0x75, 0x5D, 0x3C, 0x2D, 0x85, 0x9E, 0x55, 0x6F,
|
||||||
|
0xF6, 0x06, 0x44, 0xA7, 0xC1, 0x02, 0x0E, 0xEE, 0x98, 0xAD, 0x40, 0xF0, 0xEF, 0xD5, 0x18, 0x5A,
|
||||||
|
0x91, 0x2E, 0xEA, 0x7C, 0x0D, 0x62, 0x25, 0xA5, 0x6E, 0x44, 0x0F, 0x9D, 0x9F, 0xC0, 0x21, 0x69,
|
||||||
|
0x26, 0xB3, 0x8F, 0x70, 0xF0, 0x9D, 0x88, 0xE5, 0x55, 0x42, 0xA1, 0x7A, 0x49, 0x20, 0xAD, 0x81,
|
||||||
|
0x93, 0xE7, 0x8B, 0xFC, 0x8C, 0xE7, 0xE6, 0xCF, 0xBC, 0x51, 0xA8, 0xBC, 0xB8, 0xF2, 0x2F, 0xD4,
|
||||||
|
0xB6, 0x4A, 0xCF, 0x17, 0xE8, 0x3D, 0xF4, 0xDD, 0x01, 0x50, 0x3C, 0x42, 0xA8, 0x44, 0x90, 0xA8,
|
||||||
|
0x82, 0xC9, 0xB6, 0x87, 0x85, 0xC3, 0xE0, 0x79, 0x44, 0x97, 0xC2, 0xE5, 0xCB, 0x4E, 0x26, 0x6D,
|
||||||
|
0xFF, 0x98, 0xDB, 0x14, 0x71, 0x71, 0x33, 0x5F, 0x07, 0xF4, 0x03, 0xF9, 0xBF, 0x0D, 0x98, 0x1C,
|
||||||
|
0x46, 0x33, 0xE1, 0x15, 0xBC, 0xBD, 0x16, 0x3C, 0x20, 0xD1, 0x0D, 0x12, 0x3A, 0x5B, 0x6C, 0x22,
|
||||||
|
0x56, 0x6C, 0x01, 0x5F, 0xB8, 0x9D, 0xBB, 0x10, 0x09, 0x77, 0xB7, 0x70, 0x46, 0x06, 0x52, 0xC5,
|
||||||
|
0xF9, 0x75, 0x83, 0x4E, 0xBD, 0x4D, 0x8A, 0x45, 0x14, 0x84, 0xEC, 0x0E, 0x1C, 0x3B, 0x03, 0xDA,
|
||||||
|
0xD4, 0xBB, 0x7A, 0xCB, 0x88, 0xA6, 0xF0, 0x30, 0x82, 0xA9, 0xE5, 0x80, 0xB6, 0x9A, 0xE4, 0x02,
|
||||||
|
0xE9, 0x7C, 0x21, 0x6F, 0x83, 0xC7, 0xD2, 0x86, 0x96, 0xCB, 0xF9, 0x49, 0x57, 0xD8, 0x4C, 0x1B,
|
||||||
|
0xDD, 0x86, 0xA3, 0x1D, 0x8F, 0xE8, 0x9F, 0xF4, 0x59, 0x97, 0x79, 0x81, 0xEE, 0x04, 0x57, 0xB4,
|
||||||
|
0x13, 0x92, 0x68, 0x49, 0x57, 0x6D, 0xCB, 0x69, 0x45, 0x17, 0x53, 0xFA, 0x4B, 0xF0, 0xEB, 0x05,
|
||||||
|
0xCE, 0x7C, 0x64, 0xC6, 0x23, 0x13, 0xEA, 0x17, 0xD1, 0x85, 0xFE, 0xD0, 0xA4, 0xFA, 0x05, 0xE7,
|
||||||
|
0x9E, 0xFB, 0xBB, 0x90, 0xC2, 0x08, 0x2E, 0x2E, 0x9C, 0x94, 0xD0, 0x4D, 0x1A, 0x69, 0x6C, 0x5A,
|
||||||
|
0xD5, 0x39, 0xF5, 0x7D, 0xAE, 0x48, 0xB0, 0xAF, 0x6C, 0xF5, 0x39, 0x00, 0xC3, 0x51, 0x94, 0x59,
|
||||||
|
0x64, 0x13, 0x0D, 0xBB, 0xDF, 0x90, 0x71, 0x9C, 0x7D, 0x96, 0xD9, 0x44, 0x03, 0xB3, 0x09, 0xCB,
|
||||||
|
0x1E, 0xE3, 0xDF, 0x06, 0x2C, 0x5A, 0x9D, 0x4A, 0x24, 0x05, 0x8D, 0x81, 0xDD, 0x80, 0x60, 0xDE,
|
||||||
|
0xB0, 0xE0, 0x01, 0xE1, 0xBF, 0x31, 0x6C, 0x60, 0xF8, 0xC7, 0x87, 0xE4, 0x3D, 0x28, 0x78, 0x8F,
|
||||||
|
0x1A, 0xC2, 0x14, 0x1B, 0x18, 0xD6, 0xE1, 0xE4, 0xEA, 0x3B, 0x0D, 0xAD, 0x3B, 0x13, 0x3A, 0xAB,
|
||||||
|
0x72, 0xAC, 0xE7, 0x61, 0x97, 0x79, 0xB0, 0xCC, 0xA0, 0x8E, 0x4B, 0xCF, 0xE4, 0x5C, 0xC6, 0x47,
|
||||||
|
0xE4, 0x1A, 0x8E, 0x0A, 0x9E, 0x80, 0xAB, 0x67, 0x49, 0x66, 0x97, 0x79, 0x5A, 0x26, 0x67, 0x8A,
|
||||||
|
0x4F, 0xC1, 0x75, 0xAC, 0x72, 0xED, 0x3F, 0x86, 0xA9, 0x7D, 0x59, 0xCB, 0xA4, 0x77, 0xE6, 0x72,
|
||||||
|
0xFB, 0x9C, 0x4B, 0xBF, 0xC7, 0x45, 0x1B, 0x71, 0xC9, 0x46, 0x39, 0x4F, 0x85, 0xE5, 0xF0, 0x5C,
|
||||||
|
0x9E, 0xC3, 0x3F, 0x81, 0xE7, 0xF8, 0x8F, 0xE0, 0xC9, 0xF3, 0x3F, 0xC5, 0xC0, 0xF1, 0x4C, 0x2F,
|
||||||
|
0xED, 0x9B, 0x1B, 0xE9, 0xF9, 0xF6, 0x6D, 0xF7, 0xE1, 0x4F, 0x03, 0x82, 0x33, 0xF8, 0xA3, 0xE6,
|
||||||
|
0x4F, 0x1B, 0x3F, 0x8D, 0x8C, 0x9E, 0xF6, 0xD6, 0x36, 0xC6, 0xDA, 0xDB, 0x91, 0x61, 0xF5, 0xD8,
|
||||||
|
0xBB, 0xA9, 0xBD, 0xB5, 0xC4, 0x63, 0x6C, 0x58, 0x16, 0x7F, 0x0C, 0x78, 0xE3, 0x10, 0x1E, 0x26,
|
||||||
|
0x7B, 0x5C, 0x1A, 0xD6, 0x88, 0xBD, 0x5F, 0xB2, 0x26, 0x1B, 0x86, 0xDB, 0xE2, 0x61, 0x1B, 0xD6,
|
||||||
|
0x98, 0x3D, 0xC6, 0xAC, 0x6D, 0x88, 0x5C, 0x87, 0xDA, 0x57, 0x5C, 0x60, 0x1A, 0x7F, 0x81, 0x15,
|
||||||
|
0xB2, 0xB3, 0x6A, 0x83, 0xA7, 0xBB, 0x0D, 0xB6, 0xD2, 0xDA, 0x85, 0xF2, 0xB4, 0xE6, 0x33, 0x1E,
|
||||||
|
0x10, 0x48, 0x6B, 0xA7, 0x20, 0xC9, 0xC5, 0x94, 0x30, 0xF4, 0x51, 0x71, 0x44, 0x67, 0x29, 0x9E,
|
||||||
|
0xA1, 0x03, 0x8E, 0xE8, 0xAD, 0x82, 0x07, 0x9C, 0x65, 0xB1, 0xFC, 0x7C, 0x0D, 0xF9, 0x69, 0xB4,
|
||||||
|
0xCC, 0x9A, 0xC4, 0xA0, 0x52, 0x69, 0x80, 0x0B, 0xA4, 0x43, 0xE3, 0xB7, 0xF1, 0x1D, 0x49, 0x7F,
|
||||||
|
0x80, 0xDC, 0xA0, 0xD9, 0x02, 0x98, 0xA5, 0x95, 0x16, 0x72, 0x45, 0xBF, 0x6D, 0x5B, 0x13, 0x32,
|
||||||
|
0xA3, 0xDF, 0x5A, 0x13, 0xB3, 0x60, 0x8B, 0xB5, 0x3F, 0x97, 0x7A, 0x2B, 0x96, 0x69, 0xB1, 0x0C,
|
||||||
|
0x11, 0x45, 0x44, 0xB4, 0x81, 0x5C, 0x1E, 0x00, 0x73, 0xD1, 0x84, 0xA7, 0x7A, 0x12, 0xBC, 0x66,
|
||||||
|
0x83, 0x26, 0x9A, 0x7E, 0x41, 0x3A, 0x9C, 0xC0, 0xA0, 0x17, 0xE5, 0x21, 0xBF, 0xA9, 0x5F, 0x6E,
|
||||||
|
0x62, 0xEA, 0x86, 0x1A, 0x2F, 0x96, 0x33, 0x22, 0x8A, 0x0D, 0xA7, 0x69, 0x20, 0xC0, 0xFB, 0x2A,
|
||||||
|
0x09, 0x44, 0x6C, 0xFF, 0x34, 0xC5, 0x3B, 0xCF, 0xDB, 0x24, 0xBC, 0x4A, 0xAB, 0xE9, 0x6C, 0xE8,
|
||||||
|
0xD5, 0x9A, 0x40, 0x1C, 0xD4, 0xD6, 0x41, 0x04, 0x06, 0xD3, 0x60, 0x99, 0x18, 0x47, 0x8C, 0x15,
|
||||||
|
0x58, 0xD4, 0xB4, 0x71, 0x09, 0x9F, 0x78, 0x6C, 0x6B, 0xE0, 0x0C, 0x71, 0x4E, 0x0F, 0xB8, 0x0E,
|
||||||
|
0x1B, 0xC8, 0x88, 0xC5, 0x21, 0xA2, 0xDA, 0xFF, 0x5C, 0x37, 0xFC, 0xD8, 0xDB, 0xAC, 0x61, 0x0F,
|
||||||
|
0x3B, 0x4B, 0x42, 0x5F, 0x85, 0x04, 0x3F, 0x7E, 0xBF, 0x7D, 0x03, 0x7B, 0x27, 0x92, 0xEC, 0x56,
|
||||||
|
0x27, 0x88, 0x22, 0x92, 0xFE, 0x78, 0xF3, 0xD3, 0xDB, 0x29, 0x35, 0x50, 0x93, 0x06, 0x6C, 0xF3,
|
||||||
|
0x33, 0x35, 0xF8, 0x71, 0x25, 0x47, 0xA5, 0x78, 0x08, 0xB1, 0x87, 0xBE, 0xC1, 0x52, 0xCB, 0xBB,
|
||||||
|
0x05, 0x46, 0x45, 0xA3, 0xD4, 0xC7, 0xC3, 0x96, 0xDD, 0x72, 0xD8, 0xEA, 0x68, 0x2A, 0xBD, 0x4C,
|
||||||
|
0xBD, 0x57, 0x3E, 0x11, 0xB0, 0x4A, 0x71, 0x17, 0x86, 0x90, 0xA6, 0x69, 0x44, 0x17, 0x56, 0xEB,
|
||||||
|
0xE1, 0x38, 0x86, 0x61, 0x11, 0x82, 0x99, 0xE2, 0xAD, 0x45, 0x4C, 0x03, 0xB3, 0x0C, 0x31, 0x25,
|
||||||
|
0x01, 0x6C, 0x68, 0xCC, 0xE0, 0x2C, 0x80, 0x09, 0xA9, 0xCC, 0x37, 0xF5, 0x3D, 0x61, 0x77, 0x06,
|
||||||
|
0x59, 0x07, 0xE4, 0xA3, 0x4D, 0x69, 0x72, 0x25, 0xD3, 0xAD, 0x5A, 0x75, 0x07, 0x33, 0x69, 0x83,
|
||||||
|
0xB2, 0x47, 0x6B, 0xDF, 0x62, 0xC9, 0x00, 0xEA, 0x29, 0x98, 0x9A, 0x10, 0xBC, 0x25, 0x3F, 0xAE,
|
||||||
|
0x0B, 0x07, 0xE2, 0x68, 0x4B, 0x6F, 0x5B, 0xA0, 0x57, 0x4E, 0xDF, 0x14, 0xFD, 0x10, 0x75, 0x3B,
|
||||||
|
0x78, 0x3A, 0x6D, 0xBD, 0x78, 0xD1, 0x64, 0xCA, 0xBA, 0xF9, 0x30, 0x13, 0x46, 0xC1, 0xB2, 0x6E,
|
||||||
|
0x80, 0x18, 0x15, 0x57, 0x14, 0xB8, 0xA9, 0x81, 0x18, 0x6D, 0xF6, 0x89, 0x16, 0x28, 0x63, 0x19,
|
||||||
|
0x36, 0xA0, 0x84, 0x61, 0x5B, 0x88, 0x35, 0x36, 0x7E, 0x1E, 0xF2, 0xC7, 0x88, 0xB5, 0x59, 0x88,
|
||||||
|
0x0F, 0x6F, 0x2D, 0x5B, 0xBC, 0x5B, 0x1A, 0x0E, 0xB3, 0xCE, 0x40, 0x0C, 0xBC, 0x52, 0xD0, 0xEE,
|
||||||
|
0x2D, 0x1E, 0x91, 0xB7, 0xF8, 0x6C, 0x68, 0xF7, 0x36, 0x3C, 0x00, 0x59, 0xB7, 0x36, 0x8B, 0x80,
|
||||||
|
0x15, 0x0E, 0xFC, 0x6B, 0x5B, 0x08, 0x6F, 0x35, 0xBA, 0x72, 0x89, 0x39, 0xAB, 0x81, 0xE0, 0x64,
|
||||||
|
0x0A, 0x56, 0x3D, 0xCE, 0xCA, 0x32, 0xCF, 0xE0, 0x05, 0x6B, 0x3E, 0xE0, 0xD3, 0xAF, 0xF0, 0xE9,
|
||||||
|
0x3F, 0x91, 0xCF, 0xB8, 0xC2, 0x67, 0x7C, 0x06, 0x1F, 0x59, 0x3B, 0x60, 0xF9, 0x13, 0x2C, 0xB3,
|
||||||
|
0x71, 0x75, 0xF3, 0x52, 0xE4, 0x6A, 0x9F, 0x44, 0xB2, 0xF6, 0xA9, 0x91, 0x57, 0x48, 0x65, 0x19,
|
||||||
|
0x3D, 0xB9, 0x77, 0xC0, 0x7C, 0x5D, 0x51, 0x47, 0x6C, 0x80, 0x1F, 0x33, 0xD0, 0x55, 0xCC, 0x04,
|
||||||
|
0xED, 0xEC, 0xA2, 0x01, 0x49, 0xB9, 0x9B, 0x82, 0x2B, 0x4F, 0x3F, 0x83, 0x00, 0xD1, 0x97, 0x52,
|
||||||
|
0x56, 0x5D, 0x94, 0x23, 0x67, 0x0D, 0x9C, 0xB9, 0x42, 0xCC, 0x75, 0x2E, 0xF2, 0x61, 0xAC, 0x29,
|
||||||
|
0xDE, 0xBC, 0x9C, 0x81, 0x6C, 0x5C, 0xCA, 0x8A, 0x3D, 0x8A, 0xB1, 0x7C, 0x84, 0x34, 0x3B, 0xF3,
|
||||||
|
0x79, 0x43, 0x9D, 0xEF, 0x93, 0x28, 0x1C, 0x7D, 0xD2, 0x15, 0x57, 0x7E, 0x09, 0xF1, 0x83, 0x92,
|
||||||
|
0x26, 0x43, 0xAA, 0xB2, 0xE8, 0x7A, 0xA3, 0x85, 0x99, 0x26, 0x72, 0x56, 0xD3, 0xC5, 0x92, 0x54,
|
||||||
|
0x38, 0x1F, 0xF7, 0x49, 0x7C, 0x43, 0x5F, 0x28, 0xFC, 0x2A, 0x04, 0xBF, 0x0A, 0xAB, 0x7E, 0x15,
|
||||||
|
0x0A, 0xBF, 0x9A, 0x56, 0xFD, 0x2A, 0xFC, 0x43, 0xFD, 0x4A, 0xF1, 0xAA, 0x4B, 0x1E, 0x9E, 0x2F,
|
||||||
|
0x31, 0xD0, 0x42, 0x90, 0x86, 0x78, 0x2C, 0xDE, 0x06, 0x18, 0x72, 0xFB, 0xE8, 0x45, 0x7D, 0xF4,
|
||||||
|
0xBB, 0x01, 0x73, 0x3E, 0x9B, 0x0D, 0xC5, 0x07, 0x06, 0x6A, 0x74, 0xC5, 0x1E, 0xA3, 0x1F, 0xB0,
|
||||||
|
0x77, 0x9B, 0x7B, 0x22, 0xF4, 0x9F, 0x17, 0xA7, 0x0B, 0xA3, 0xD2, 0x71, 0x5B, 0xCA, 0x27, 0x00,
|
||||||
|
0x2D, 0xDF, 0xFE, 0x3C, 0xAB, 0x39, 0xBC, 0x99, 0x53, 0x51, 0x57, 0x09, 0xF5, 0xCA, 0x76, 0x85,
|
||||||
|
0xC5, 0x76, 0x39, 0x72, 0xBF, 0x2A, 0x7D, 0x25, 0xE3, 0x90, 0xF2, 0x3C, 0xD9, 0x56, 0x8E, 0xCF,
|
||||||
|
0xFF, 0x24, 0x73, 0x39, 0x1A, 0xEF, 0x8A, 0x9A, 0x54, 0x39, 0xE4, 0x1D, 0x25, 0x60, 0xA5, 0x3A,
|
||||||
|
0x75, 0xAC, 0x3C, 0x2E, 0x16, 0x29, 0x89, 0xB0, 0x76, 0xCC, 0x94, 0xE2, 0x08, 0xAF, 0x12, 0x9A,
|
||||||
|
0xFA, 0x0F, 0xFC, 0x83, 0xE6, 0x63, 0x17, 0x8E, 0x89, 0x17, 0xB8, 0x99, 0x3C, 0x3D, 0x00, 0x73,
|
||||||
|
0x2C, 0xE5, 0x4F, 0x6C, 0x10, 0x81, 0x0C, 0xF6, 0x80, 0xA7, 0x4C, 0xC0, 0x4E, 0xB1, 0x85, 0x31,
|
||||||
|
0xB0, 0x81, 0x71, 0xBA, 0x3D, 0xC1, 0x1B, 0xC6, 0x94, 0xD9, 0x2B, 0x05, 0x60, 0x71, 0x52, 0x4B,
|
||||||
|
0x52, 0x88, 0x6C, 0x70, 0xB6, 0x7D, 0xCF, 0xCB, 0x35, 0xEC, 0xA2, 0xA1, 0xE0, 0xCD, 0x0A, 0x46,
|
||||||
|
0x90, 0x13, 0x80, 0x6A, 0xA3, 0x4D, 0x18, 0x3E, 0x9B, 0x92, 0xCA, 0x3C, 0x9E, 0x64, 0x08, 0xF3,
|
||||||
|
0x74, 0xC0, 0x09, 0xD7, 0xCD, 0x96, 0x32, 0x9D, 0x3A, 0x94, 0x45, 0x53, 0x9E, 0x4A, 0x44, 0xE4,
|
||||||
|
0x4E, 0xFB, 0x9F, 0x9F, 0xDE, 0xFE, 0x48, 0x69, 0x22, 0x4E, 0xF0, 0x70, 0xA0, 0xD6, 0xBB, 0xCC,
|
||||||
|
0x04, 0xBE, 0xE5, 0x3F, 0x85, 0x98, 0xC2, 0x9A, 0x20, 0x6E, 0x42, 0x26, 0x85, 0xAD, 0xBC, 0x6C,
|
||||||
|
0x75, 0x41, 0x22, 0x2F, 0xF6, 0xC9, 0xC7, 0x0F, 0x6F, 0x9A, 0xB4, 0x65, 0xB0, 0x4E, 0x96, 0x34,
|
||||||
|
0xA8, 0x1D, 0x6A, 0xE2, 0x72, 0x7C, 0x73, 0x45, 0xD1, 0xB6, 0xD5, 0x61, 0xAE, 0xD2, 0x29, 0x2A,
|
||||||
|
0x59, 0xA2, 0xAA, 0x15, 0xC2, 0x9A, 0xA3, 0x4E, 0x1C, 0xC1, 0xE2, 0xFC, 0x2D, 0xA6, 0x4A, 0xC4,
|
||||||
|
0x5B, 0xE1, 0xAF, 0x0B, 0xA7, 0x79, 0x6E, 0xD0, 0xDA, 0x41, 0xC6, 0xD9, 0x9F, 0x4E, 0xA3, 0x0E,
|
||||||
|
0x1B, 0x83, 0xC9, 0x26, 0x69, 0x41, 0x93, 0x6D, 0x9A, 0xD8, 0xC8, 0xD3, 0x2B, 0xA9, 0xE3, 0xFF,
|
||||||
|
0xBA, 0x7E, 0xF7, 0x33, 0x20, 0x7A, 0x0A, 0x09, 0x2E, 0x8E, 0xCF, 0x92, 0x38, 0xCA, 0xC8, 0x0D,
|
||||||
|
0xB9, 0xA7, 0x27, 0x0C, 0xF6, 0x84, 0x88, 0xA2, 0xDA, 0x66, 0xD4, 0xA6, 0xC4, 0x7B, 0x12, 0xC2,
|
||||||
|
0x36, 0x56, 0xCA, 0x23, 0x7B, 0x5C, 0x4D, 0x42, 0xA2, 0xA6, 0xFE, 0x9F, 0xAF, 0x6E, 0xE0, 0x5C,
|
||||||
|
0x6F, 0x3C, 0x33, 0x5B, 0xD0, 0x94, 0xC1, 0xF6, 0x34, 0x2B, 0xDB, 0xC5, 0xCB, 0x8C, 0xBB, 0xBC,
|
||||||
|
0x8D, 0xD9, 0x37, 0x2C, 0x8C, 0x08, 0xD0, 0x85, 0xED, 0x4C, 0x36, 0xAC, 0x04, 0x20, 0xB3, 0x6F,
|
||||||
|
0xC2, 0x7F, 0xDF, 0xE0, 0x77, 0x45, 0xCA, 0xFC, 0x1F, 0x90, 0xBD, 0x1E, 0x5F, 0x17, 0xDE, 0xB6,
|
||||||
|
0xB4, 0x3A, 0x3C, 0xA3, 0x3D, 0xE1, 0x7E, 0xE5, 0x7B, 0x20, 0x49, 0x20, 0x4A, 0xA1, 0x80, 0x6A,
|
||||||
|
0x5A, 0xA7, 0xD3, 0xD1, 0x2F, 0xF0, 0xF0, 0xF0, 0x1A, 0xAF, 0xFF, 0x9B, 0x66, 0x0B, 0xF3, 0xDD,
|
||||||
|
0xFD, 0x9E, 0x8B, 0x74, 0x12, 0x06, 0x64, 0xF1, 0xB6, 0xC5, 0x31, 0x07, 0x8F, 0x0E, 0xE6, 0xB3,
|
||||||
|
0xA9, 0xAC, 0xB7, 0xB4, 0x76, 0x4F, 0x96, 0x09, 0x45, 0x3A, 0x01, 0x28, 0x6C, 0xE1, 0xC7, 0x0D,
|
||||||
|
0xCE, 0x29, 0x7C, 0xE3, 0x75, 0x9C, 0xAE, 0x5F, 0xBA, 0xD4, 0x75, 0xA2, 0x8E, 0x9B, 0x24, 0xB8,
|
||||||
|
0x49, 0x1C, 0x8E, 0xD4, 0x3C, 0xBB, 0x9A, 0x72, 0x52, 0x35, 0xD9, 0xDC, 0xF1, 0x90, 0x89, 0x65,
|
||||||
|
0x1D, 0xC3, 0x57, 0x33, 0xF7, 0x8B, 0x50, 0xE0, 0xEB, 0xB5, 0x5E, 0x30, 0xF7, 0x8D, 0x90, 0x87,
|
||||||
|
0x4B, 0xA3, 0x98, 0xAF, 0x28, 0x69, 0x1B, 0xA1, 0x71, 0xC8, 0xA0, 0xC5, 0x14, 0xED, 0xD6, 0x78,
|
||||||
|
0xB2, 0xE3, 0x0A, 0x4B, 0x7B, 0xFF, 0xEE, 0xFA, 0x06, 0x4F, 0x13, 0x8C, 0x8F, 0xCE, 0x2C, 0xCE,
|
||||||
|
0xED, 0x70, 0x15, 0x76, 0x20, 0x32, 0xBD, 0xBA, 0x05, 0x8E, 0x6F, 0x01, 0x90, 0x09, 0x00, 0x2C,
|
||||||
|
0x6A, 0x87, 0x17, 0x9D, 0x01, 0x46, 0x8C, 0x67, 0x16, 0x0E, 0x8D, 0x23, 0x1C, 0x5A, 0xF1, 0x38,
|
||||||
|
0xE6, 0x5E, 0x53, 0x37, 0xF7, 0xAF, 0xA7, 0xED, 0xD5, 0x13, 0x76, 0x29, 0xF7, 0xB9, 0xF3, 0x2C,
|
||||||
|
0x4B, 0x4C, 0xA7, 0x3B, 0x35, 0x3E, 0xAA, 0xA0, 0x81, 0x5B, 0x46, 0x03, 0xE1, 0xBC, 0xEC, 0x5F,
|
||||||
|
0x24, 0x34, 0xF5, 0xEF, 0xC0, 0xF9, 0xD8, 0x6F, 0xE1, 0xF1, 0x4C, 0x07, 0x1B, 0xE0, 0x3F, 0x83,
|
||||||
|
0x63, 0x36, 0x28, 0x86, 0x79, 0x6D, 0xD4, 0xDA, 0x17, 0x7E, 0xAB, 0x5E, 0x10, 0xFC, 0xA9, 0x9E,
|
||||||
|
0xBB, 0xB8, 0x3B, 0xC7, 0x77, 0xF1, 0x92, 0x40, 0x8D, 0x9C, 0x0F, 0x7B, 0x2D, 0x48, 0x79, 0x10,
|
||||||
|
0xEB, 0x2A, 0x17, 0x37, 0xDA, 0xB7, 0x7A, 0x4B, 0xCA, 0x7D, 0x7C, 0x13, 0xEE, 0x7E, 0xA7, 0x73,
|
||||||
|
0x17, 0xD7, 0x2F, 0x4F, 0x33, 0x02, 0x65, 0xFE, 0x27, 0x90, 0x73, 0xC5, 0x9D, 0x88, 0x49, 0xE7,
|
||||||
|
0xAB, 0xFC, 0xC4, 0x58, 0xF1, 0x73, 0x01, 0x39, 0x91, 0xF8, 0x51, 0xD5, 0x54, 0xC7, 0x5F, 0x55,
|
||||||
|
0x9D, 0xF6, 0x0C, 0xB6, 0xFD, 0x27, 0x10, 0x4C, 0x22, 0x52, 0x19, 0xC5, 0x8C, 0x07, 0x01, 0x4A,
|
||||||
|
0xEF, 0xEA, 0x8F, 0x04, 0x26, 0x8E, 0x4B, 0x05, 0xDD, 0x23, 0xF0, 0x88, 0xFF, 0xFE, 0x03, 0x96,
|
||||||
|
0xF2, 0xD7, 0x40, 0x92, 0x6A, 0x61, 0xE7, 0x82, 0xD2, 0xC1, 0xEE, 0x9E, 0xB8, 0x67, 0x3B, 0xC1,
|
||||||
|
0x46, 0xDE, 0xB8, 0x3D, 0xCD, 0xC4, 0xFE, 0x10, 0x07, 0x39, 0xC6, 0x44, 0x5E, 0x38, 0x27, 0xF7,
|
||||||
|
0x67, 0x7A, 0x97, 0x04, 0xD8, 0x3F, 0xCD, 0x17, 0x0F, 0xC9, 0x15, 0x19, 0x9D, 0x83, 0xBC, 0xAE,
|
||||||
|
0x82, 0xE4, 0x88, 0x3B, 0x3A, 0x16, 0x7C, 0x64, 0xED, 0xF1, 0xC5, 0x0B, 0xBD, 0x5F, 0xFE, 0xAA,
|
||||||
|
0xF6, 0xFE, 0xF6, 0x9B, 0xC0, 0x7C, 0x81, 0x75, 0x0B, 0x17, 0x6C, 0xDC, 0xD7, 0x5B, 0x86, 0x6E,
|
||||||
|
0xC3, 0xE1, 0x56, 0x8E, 0x6A, 0x95, 0x07, 0x79, 0x6E, 0xE4, 0x81, 0x84, 0x18, 0x16, 0x1C, 0x16,
|
||||||
|
0x37, 0x70, 0xCE, 0x9E, 0x3A, 0x9E, 0xC3, 0xA5, 0x11, 0x4D, 0x4D, 0xF0, 0xC1, 0x87, 0x1C, 0xDB,
|
||||||
|
0x09, 0x3A, 0x58, 0x7B, 0xEC, 0x9B, 0x06, 0x9D, 0x66, 0x84, 0xBE, 0x41, 0x53, 0x01, 0x2D, 0x37,
|
||||||
|
0x15, 0x6B, 0x8F, 0x2E, 0xA6, 0xD6, 0xC3, 0x00, 0xC1, 0xB7, 0x26, 0x3A, 0xC7, 0x0E, 0x0B, 0x93,
|
||||||
|
0xEE, 0x5B, 0xED, 0xC8, 0x88, 0x66, 0x7D, 0x13, 0x8E, 0xEC, 0x1E, 0x58, 0x74, 0x9A, 0xCF, 0x0F,
|
||||||
|
0xA9, 0x7E, 0x18, 0xF3, 0xBB, 0x59, 0xD0, 0x31, 0x9A, 0x0F, 0x1E, 0x31, 0x0C, 0x8B, 0xF4, 0xCA,
|
||||||
|
0xE1, 0xB2, 0xA4, 0x3A, 0x0C, 0x95, 0x8F, 0x8A, 0xA5, 0x45, 0x30, 0x15, 0xB8, 0xF1, 0x16, 0x6F,
|
||||||
|
0x3A, 0x9B, 0x27, 0xDC, 0xF9, 0x9C, 0x04, 0xFD, 0x38, 0xAD, 0xBC, 0xC4, 0x3E, 0x40, 0x61, 0xF6,
|
||||||
|
0xDB, 0x73, 0xA5, 0x24, 0x5F, 0xC9, 0xE4, 0x4F, 0xC9, 0x73, 0x94, 0x27, 0x43, 0x76, 0x61, 0xB3,
|
||||||
|
0xA7, 0xE9, 0x95, 0x3B, 0x67, 0xB1, 0x91, 0xE2, 0x50, 0x67, 0x9C, 0x88, 0xBA, 0x75, 0x97, 0xC2,
|
||||||
|
0x15, 0x6A, 0xBC, 0x35, 0x65, 0xC3, 0xBE, 0xFD, 0x78, 0xFD, 0xEA, 0x83, 0x7A, 0x62, 0xC3, 0xAC,
|
||||||
|
0x04, 0xC4, 0x8B, 0x28, 0x64, 0x2B, 0x17, 0xFA, 0x8B, 0xF7, 0xDF, 0x5D, 0x5F, 0xFF, 0xF3, 0xDD,
|
||||||
|
0x87, 0x97, 0xF5, 0x43, 0x28, 0x0E, 0xB9, 0xFE, 0xF8, 0xFD, 0x4F, 0x6F, 0x6E, 0xA6, 0x5B, 0xCC,
|
||||||
|
0x2A, 0x83, 0x3A, 0xC4, 0x0F, 0x1E, 0x38, 0xB9, 0xC1, 0xB1, 0x2D, 0x50, 0x8E, 0x6D, 0x2F, 0x5E,
|
||||||
|
0x00, 0x84, 0x3F, 0x83, 0x26, 0xE9, 0x9A, 0x65, 0x0B, 0xD8, 0x1B, 0x81, 0x7A, 0x76, 0x8A, 0x58,
|
||||||
|
0xD8, 0x08, 0xE4, 0xD9, 0x09, 0x95, 0xAA, 0x16, 0xB0, 0x21, 0x24, 0x39, 0x77, 0x41, 0xE4, 0xC7,
|
||||||
|
0x77, 0x35, 0xD1, 0xE2, 0xF8, 0xED, 0x89, 0x73, 0xD5, 0x15, 0xD7, 0xD3, 0x57, 0x5D, 0xF1, 0x83,
|
||||||
|
0x19, 0xF6, 0xFF, 0xCC, 0xF9, 0x7F, 0xE5, 0xCC, 0x32, 0xCA, 0x3A, 0x47, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t a_SIZE = 4862;
|
||||||
|
const char * a_NAME = "ool.html.gz";
|
||||||
Binary file not shown.
@@ -131,6 +131,9 @@ var formData = new FormData();
|
|||||||
formData.append('path', currentpath);
|
formData.append('path', currentpath);
|
||||||
for (var i3 = 0; i3 < files.length; i3++) {
|
for (var i3 = 0; i3 < files.length; i3++) {
|
||||||
var file = files[i3];
|
var file = files[i3];
|
||||||
|
var arg = currentpath + file.name + "S";
|
||||||
|
//append file size first to check updload is complete
|
||||||
|
formData.append(arg, file.size);
|
||||||
formData.append('myfiles[]', file, currentpath+file.name);}
|
formData.append('myfiles[]', file, currentpath+file.name);}
|
||||||
var xmlhttp = new XMLHttpRequest();
|
var xmlhttp = new XMLHttpRequest();
|
||||||
xmlhttp.open('POST', '/files', true);
|
xmlhttp.open('POST', '/files', true);
|
||||||
@@ -175,6 +178,9 @@ document.getElementById('prgfw').style.visibility = "visible";
|
|||||||
var formData = new FormData();
|
var formData = new FormData();
|
||||||
for (var i4 = 0; i4 < files.length; i4++) {
|
for (var i4 = 0; i4 < files.length; i4++) {
|
||||||
var file = files[i4];
|
var file = files[i4];
|
||||||
|
var arg = "/" + file.name + "S";
|
||||||
|
//append file size first to check updload is complete
|
||||||
|
formData.append(arg, file.size);
|
||||||
formData.append('myfile[]', file, "/"+file.name);}
|
formData.append('myfile[]', file, "/"+file.name);}
|
||||||
var xmlhttp = new XMLHttpRequest();
|
var xmlhttp = new XMLHttpRequest();
|
||||||
xmlhttp.open('POST', '/updatefw', true);
|
xmlhttp.open('POST', '/updatefw', true);
|
||||||
|
|||||||
@@ -6,11 +6,12 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div style="position:absolute;top:0;right:0;">
|
<div style="position:absolute;top:0;right:0;">
|
||||||
V1.1
|
V1.2
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<center>
|
<center>
|
||||||
<h2>It seems you do not have any index.html neither index.html.gz, please upload it or update your firmware if necessary.</h2>
|
<h2>It seems you do not have any index.html neither index.html.gz, please upload it or update your firmware if necessary.</h2>
|
||||||
|
you can find one here : <a class='blacklink' href='https://github.com/luc-github/ESP3D-WEBUI'>https://github.com/luc-github/ESP3D-WEBUI</a>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
<div class="panel" id="SPIFFS">
|
<div class="panel" id="SPIFFS">
|
||||||
|
|||||||
209
esp3d/bridge.cpp
209
esp3d/bridge.cpp
@@ -1,209 +0,0 @@
|
|||||||
/*
|
|
||||||
bridge.cpp - esp3d bridge serial/tcp class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "bridge.h"
|
|
||||||
#include "command.h"
|
|
||||||
#include "webinterface.h"
|
|
||||||
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
WiFiServer * data_server;
|
|
||||||
WiFiClient serverClients[MAX_SRV_CLIENTS];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool BRIDGE::header_sent = false;
|
|
||||||
String BRIDGE::buffer_web = "";
|
|
||||||
void BRIDGE::print (const __FlashStringHelper *data, tpipe output)
|
|
||||||
{
|
|
||||||
String tmp = data;
|
|
||||||
BRIDGE::print(tmp.c_str(), output);
|
|
||||||
}
|
|
||||||
void BRIDGE::print (String & data, tpipe output)
|
|
||||||
{
|
|
||||||
BRIDGE::print(data.c_str(), output);
|
|
||||||
}
|
|
||||||
void BRIDGE::print (const char * data, tpipe output)
|
|
||||||
{
|
|
||||||
switch(output) {
|
|
||||||
case SERIAL_PIPE:
|
|
||||||
header_sent = false;
|
|
||||||
ESP_SERIAL_OUT.print(data);
|
|
||||||
break;
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
case TCP_PIPE:
|
|
||||||
header_sent = false;
|
|
||||||
BRIDGE::send2TCP(data);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case WEB_PIPE:
|
|
||||||
if (!header_sent) {
|
|
||||||
web_interface->web_server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
|
||||||
web_interface->web_server.sendHeader("Content-Type","text/html");
|
|
||||||
web_interface->web_server.sendHeader("Cache-Control","no-cache");
|
|
||||||
web_interface->web_server.send(200);
|
|
||||||
header_sent = true;
|
|
||||||
}
|
|
||||||
buffer_web+=data;
|
|
||||||
if (buffer_web.length() > 1200) {
|
|
||||||
//send data
|
|
||||||
web_interface->web_server.sendContent(buffer_web);
|
|
||||||
//reset buffer
|
|
||||||
buffer_web="";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void BRIDGE::println (const __FlashStringHelper *data, tpipe output)
|
|
||||||
{
|
|
||||||
BRIDGE::print(data,output);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
BRIDGE::print("\r",output);
|
|
||||||
#endif
|
|
||||||
BRIDGE::print("\n",output);
|
|
||||||
}
|
|
||||||
void BRIDGE::println (String & data, tpipe output)
|
|
||||||
{
|
|
||||||
BRIDGE::print(data,output);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
BRIDGE::print("\r",output);
|
|
||||||
#endif
|
|
||||||
BRIDGE::print("\n",output);
|
|
||||||
}
|
|
||||||
void BRIDGE::println (const char * data, tpipe output)
|
|
||||||
{
|
|
||||||
BRIDGE::print(data,output);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
BRIDGE::print("\r",output);
|
|
||||||
#endif
|
|
||||||
BRIDGE::print("\n",output);
|
|
||||||
}
|
|
||||||
void BRIDGE::flush (tpipe output)
|
|
||||||
{
|
|
||||||
switch(output) {
|
|
||||||
case SERIAL_PIPE:
|
|
||||||
ESP_SERIAL_OUT.flush();
|
|
||||||
break;
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
case TCP_PIPE:
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case WEB_PIPE:
|
|
||||||
if(header_sent) {
|
|
||||||
//send data
|
|
||||||
web_interface->web_server.sendContent(buffer_web);
|
|
||||||
//close line
|
|
||||||
web_interface->web_server.sendContent("");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
header_sent = false;
|
|
||||||
buffer_web = String();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
void BRIDGE::send2TCP(const __FlashStringHelper *data)
|
|
||||||
{
|
|
||||||
String tmp = data;
|
|
||||||
BRIDGE::send2TCP(tmp.c_str());
|
|
||||||
}
|
|
||||||
void BRIDGE::send2TCP(String data)
|
|
||||||
{
|
|
||||||
BRIDGE::send2TCP(data.c_str());
|
|
||||||
}
|
|
||||||
void BRIDGE::send2TCP(const char * data)
|
|
||||||
{
|
|
||||||
for(uint8_t i = 0; i < MAX_SRV_CLIENTS; i++) {
|
|
||||||
if (serverClients[i] && serverClients[i].connected()) {
|
|
||||||
serverClients[i].write(data, strlen(data));
|
|
||||||
delay(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool BRIDGE::processFromSerial2TCP()
|
|
||||||
{
|
|
||||||
uint8_t i;
|
|
||||||
//check UART for data
|
|
||||||
if(ESP_SERIAL_OUT.available()) {
|
|
||||||
size_t len = ESP_SERIAL_OUT.available();
|
|
||||||
uint8_t sbuf[len];
|
|
||||||
ESP_SERIAL_OUT.readBytes(sbuf, len);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
if (WiFi.getMode()!=WIFI_OFF ) {
|
|
||||||
//push UART data to all connected tcp clients
|
|
||||||
for(i = 0; i < MAX_SRV_CLIENTS; i++) {
|
|
||||||
if (serverClients[i] && serverClients[i].connected()) {
|
|
||||||
serverClients[i].write(sbuf, len);
|
|
||||||
delay(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
//process data if any
|
|
||||||
COMMAND::read_buffer_serial(sbuf, len);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
void BRIDGE::processFromTCP2Serial()
|
|
||||||
{
|
|
||||||
uint8_t i,data;
|
|
||||||
//check if there are any new clients
|
|
||||||
if (data_server->hasClient()) {
|
|
||||||
for(i = 0; i < MAX_SRV_CLIENTS; i++) {
|
|
||||||
//find free/disconnected spot
|
|
||||||
if (!serverClients[i] || !serverClients[i].connected()) {
|
|
||||||
if(serverClients[i]) {
|
|
||||||
serverClients[i].stop();
|
|
||||||
}
|
|
||||||
serverClients[i] = data_server->available();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//no free/disconnected spot so reject
|
|
||||||
WiFiClient serverClient = data_server->available();
|
|
||||||
serverClient.stop();
|
|
||||||
}
|
|
||||||
//check clients for data
|
|
||||||
//to avoid any pollution if Uploading file to SDCard
|
|
||||||
if ((web_interface->blockserial) == false) {
|
|
||||||
for(i = 0; i < MAX_SRV_CLIENTS; i++) {
|
|
||||||
if (serverClients[i] && serverClients[i].connected()) {
|
|
||||||
if(serverClients[i].available()) {
|
|
||||||
//get data from the tcp client and push it to the UART
|
|
||||||
while(serverClients[i].available()) {
|
|
||||||
data = serverClients[i].read();
|
|
||||||
ESP_SERIAL_OUT.write(data);
|
|
||||||
COMMAND::read_buffer_tcp(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
bridge.h - esp3d bridge serial/tcp class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BRIDGE_H
|
|
||||||
#define BRIDGE_H
|
|
||||||
#include <WiFiServer.h>
|
|
||||||
#include "config.h"
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
extern WiFiServer * data_server;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class BRIDGE
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static bool header_sent;
|
|
||||||
static String buffer_web;
|
|
||||||
static bool processFromSerial2TCP();
|
|
||||||
static void print (const __FlashStringHelper *data, tpipe output);
|
|
||||||
static void print (String & data, tpipe output);
|
|
||||||
static void print (const char * data, tpipe output);
|
|
||||||
static void println (const __FlashStringHelper *data, tpipe output);
|
|
||||||
static void println (String & data, tpipe output);
|
|
||||||
static void println (const char * data, tpipe output);
|
|
||||||
static void flush (tpipe output);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
static void processFromTCP2Serial();
|
|
||||||
static void send2TCP(const __FlashStringHelper *data);
|
|
||||||
static void send2TCP(String data);
|
|
||||||
static void send2TCP(const char * data);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
1600
esp3d/command.cpp
1600
esp3d/command.cpp
File diff suppressed because it is too large
Load Diff
1865
esp3d/config.cpp
1865
esp3d/config.cpp
File diff suppressed because it is too large
Load Diff
Binary file not shown.
189
esp3d/esp3d.ino
189
esp3d/esp3d.ino
@@ -1,189 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of ESP3D Firmware for 3D printer.
|
|
||||||
|
|
||||||
ESP3D Firmware for 3D printer 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.
|
|
||||||
|
|
||||||
ESP3D Firmware for 3D printer 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 Firmware. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
This firmware is using the standard arduino IDE with module to support ESP8266:
|
|
||||||
https://github.com/esp8266/Arduino from Bootmanager
|
|
||||||
|
|
||||||
Latest version of the code and documentation can be found here :
|
|
||||||
https://github.com/luc-github/ESP3D
|
|
||||||
|
|
||||||
Main author: luc lebosse
|
|
||||||
|
|
||||||
*/
|
|
||||||
//be sure correct IDE and settings are used for ESP8266 or ESP32
|
|
||||||
#if !(defined( ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32))
|
|
||||||
#error Oops! Make sure you have 'ESP8266 or ESP32' compatible board selected from the 'Tools -> Boards' menu.
|
|
||||||
#endif
|
|
||||||
#include <EEPROM.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "wificonf.h"
|
|
||||||
#include "bridge.h"
|
|
||||||
#include "webinterface.h"
|
|
||||||
#include "command.h"
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include "ESP8266WiFi.h"
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
#include <ESP8266mDNS.h>
|
|
||||||
#endif
|
|
||||||
#include <ESP8266WebServer.h>
|
|
||||||
#else
|
|
||||||
#include <WiFi.h>
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
#include <ESPmDNS.h>
|
|
||||||
#endif
|
|
||||||
#include "esp_wifi.h"
|
|
||||||
#include <WebServer.h>
|
|
||||||
#include "FS.h"
|
|
||||||
#include "SPIFFS.h"
|
|
||||||
#include "Update.h"
|
|
||||||
#endif
|
|
||||||
#include <WiFiClient.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
#include <DNSServer.h>
|
|
||||||
extern DNSServer dnsServer;
|
|
||||||
#endif
|
|
||||||
#ifdef SSDP_FEATURE
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include <ESP8266SSDP.h>
|
|
||||||
#else
|
|
||||||
//#include <ESPSSDP.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifdef NETBIOS_FEATURE
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include <ESP8266NetBIOS.h>
|
|
||||||
#else
|
|
||||||
//#include <ESPNetBIOS.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifndef FS_NO_GLOBALS
|
|
||||||
#define FS_NO_GLOBALS
|
|
||||||
#endif
|
|
||||||
#include <FS.h>
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
bool breset_config=false;
|
|
||||||
bool directsd_check = false;
|
|
||||||
web_interface = NULL;
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
data_server = NULL;
|
|
||||||
#endif
|
|
||||||
// init:
|
|
||||||
#ifdef DEBUG_ESP3D
|
|
||||||
if (ESP_SERIAL_OUT.baudRate() != DEFAULT_BAUD_RATE)ESP_SERIAL_OUT.begin(DEFAULT_BAUD_RATE);
|
|
||||||
delay(2000);
|
|
||||||
LOG("\r\nDebug Serial set\r\n")
|
|
||||||
#endif
|
|
||||||
//WiFi.disconnect();
|
|
||||||
WiFi.mode(WIFI_OFF);
|
|
||||||
delay(8000);
|
|
||||||
CONFIG::InitDirectSD();
|
|
||||||
CONFIG::InitPins();
|
|
||||||
#ifdef RECOVERY_FEATURE
|
|
||||||
delay(8000);
|
|
||||||
//check if reset config is requested
|
|
||||||
if (digitalRead(RESET_CONFIG_PIN)==0) {
|
|
||||||
breset_config=true; //if requested =>reset settings
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
//check if EEPROM has value
|
|
||||||
if ( !CONFIG::InitBaudrate() || !CONFIG::InitExternalPorts()) {
|
|
||||||
breset_config=true; //cannot access to config settings=> reset settings
|
|
||||||
LOG("Error no EEPROM access\r\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
//reset is requested
|
|
||||||
if(breset_config) {
|
|
||||||
//update EEPROM with default settings
|
|
||||||
if (ESP_SERIAL_OUT.baudRate() != DEFAULT_BAUD_RATE)ESP_SERIAL_OUT.begin(DEFAULT_BAUD_RATE);
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
ESP_SERIAL_OUT.setRxBufferSize(SERIAL_RX_BUFFER_SIZE);
|
|
||||||
#endif
|
|
||||||
delay(2000);
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 ESP EEPROM reset"));
|
|
||||||
#ifdef DEBUG_ESP3D
|
|
||||||
CONFIG::print_config(DEBUG_PIPE, true);
|
|
||||||
delay(1000);
|
|
||||||
#endif
|
|
||||||
CONFIG::reset_config();
|
|
||||||
delay(1000);
|
|
||||||
//put some default value to a void some exception at first start
|
|
||||||
WiFi.mode(WIFI_AP);
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
WiFi.setPhyMode(WIFI_PHY_MODE_11G);
|
|
||||||
#else
|
|
||||||
esp_wifi_set_protocol(ESP_IF_WIFI_AP, WIFI_PHY_MODE_11G);
|
|
||||||
#endif
|
|
||||||
CONFIG::esp_restart();
|
|
||||||
}
|
|
||||||
#if defined(DEBUG_ESP3D) && defined(DEBUG_OUTPUT_SERIAL)
|
|
||||||
LOG("\r\n");
|
|
||||||
delay(500);
|
|
||||||
ESP_SERIAL_OUT.flush();
|
|
||||||
#endif
|
|
||||||
//get target FW
|
|
||||||
CONFIG::InitFirmwareTarget();
|
|
||||||
//Update is done if any so should be Ok
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
SPIFFS.begin(true);
|
|
||||||
#else
|
|
||||||
SPIFFS.begin();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//setup wifi according settings
|
|
||||||
if (!wifi_config.Setup()) {
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Safe mode 1"));
|
|
||||||
//try again in AP mode
|
|
||||||
if (!wifi_config.Setup(true)) {
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Safe mode 2"));
|
|
||||||
wifi_config.Safe_Setup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delay(1000);
|
|
||||||
//setup servers
|
|
||||||
if (!wifi_config.Enable_servers()) {
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Error enabling servers"));
|
|
||||||
}
|
|
||||||
LOG("Setup Done\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//main loop
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
//be sure wifi is on to proceed wifi function
|
|
||||||
if (WiFi.getMode()!=WIFI_OFF ) {
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
if (WiFi.getMode()!=WIFI_STA ) {
|
|
||||||
dnsServer.processNextRequest();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
//web requests
|
|
||||||
web_interface->web_server.handleClient();
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
BRIDGE::processFromTCP2Serial();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
BRIDGE::processFromSerial2TCP();
|
|
||||||
//in case of restart requested
|
|
||||||
if (web_interface->restartmodule) {
|
|
||||||
CONFIG::esp_restart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
326
esp3d/nofile.h
326
esp3d/nofile.h
@@ -1,326 +0,0 @@
|
|||||||
/*
|
|
||||||
nofile.h - ESP3D data file
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
//data generated by https://github.com/AraHaan/bin2c
|
|
||||||
//bin2c Conversion Tool v0.14.0 - Windows - [FINAL].
|
|
||||||
#define PAGE_NOFILES_SIZE 4776
|
|
||||||
const char PAGE_NOFILES [] PROGMEM =
|
|
||||||
{
|
|
||||||
|
|
||||||
0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xED, 0x5C, 0x7D, 0x93, 0xDA, 0x46,
|
|
||||||
0x93, 0xFF, 0x2A, 0xB2, 0x52, 0x36, 0x70, 0x2B, 0x58, 0x49, 0xBC, 0xA3, 0x05, 0x3F, 0x49, 0x1C,
|
|
||||||
0x5F, 0x7C, 0xE5, 0xC4, 0x2E, 0xEF, 0xFA, 0xEE, 0xAA, 0xE2, 0x94, 0x4B, 0x48, 0x03, 0xE8, 0xB1,
|
|
||||||
0x90, 0x74, 0xD2, 0xB0, 0xBB, 0x98, 0xF0, 0xDD, 0xAF, 0x7B, 0x5E, 0xA4, 0x91, 0x10, 0x2C, 0xBB,
|
|
||||||
0x49, 0x9E, 0x3C, 0x7F, 0x24, 0x78, 0x11, 0xCC, 0x4C, 0xF7, 0xF4, 0xF4, 0x74, 0xFF, 0xBA, 0xA7,
|
|
||||||
0x87, 0xCA, 0xD5, 0x8A, 0xAE, 0xC3, 0xD9, 0xD5, 0x8A, 0xB8, 0xFE, 0xEC, 0x2A, 0xA3, 0xDB, 0x90,
|
|
||||||
0xCC, 0xB0, 0x65, 0xB7, 0x88, 0x23, 0xDA, 0x5E, 0xB8, 0xEB, 0x20, 0xDC, 0x4E, 0x32, 0x37, 0xCA,
|
|
||||||
0xDA, 0x19, 0x49, 0x83, 0x85, 0xD3, 0x5E, 0x67, 0x6D, 0x4A, 0xEE, 0x69, 0x3B, 0x0B, 0xBE, 0x92,
|
|
||||||
0xB6, 0xEB, 0xFF, 0x73, 0x93, 0xD1, 0x89, 0x65, 0x9A, 0xCF, 0x9D, 0xF6, 0x1D, 0x99, 0x7F, 0x09,
|
|
||||||
0xE8, 0x91, 0x5E, 0xC6, 0x0E, 0x5B, 0xE1, 0x6B, 0x72, 0xBF, 0x9F, 0xC7, 0xFE, 0xB6, 0x34, 0x85,
|
|
||||||
0xFE, 0x23, 0x09, 0x6F, 0x09, 0x0D, 0x3C, 0x57, 0xFB, 0x99, 0x6C, 0x88, 0x6E, 0xE4, 0xDF, 0x8D,
|
|
||||||
0x6F, 0xD3, 0xC0, 0x0D, 0x0D, 0x45, 0x06, 0x85, 0x57, 0x2F, 0xB9, 0x77, 0xC2, 0x20, 0x22, 0xED,
|
|
||||||
0x15, 0x09, 0x96, 0x2B, 0x98, 0xAB, 0xD3, 0xB3, 0x47, 0xFD, 0xA1, 0xD5, 0xEB, 0x3A, 0x5E, 0x1C,
|
|
||||||
0xC6, 0xE9, 0xE4, 0x9B, 0x6E, 0xB7, 0xEB, 0xCC, 0x5D, 0xEF, 0xCB, 0x32, 0x8D, 0x37, 0x91, 0xDF,
|
|
||||||
0x16, 0xAD, 0x8B, 0xC5, 0x62, 0xDF, 0xF1, 0x80, 0x8F, 0x0B, 0xC4, 0xE9, 0x6E, 0xED, 0xA6, 0xCB,
|
|
||||||
0x20, 0x6A, 0xA7, 0x8C, 0x87, 0xBB, 0xA1, 0xB1, 0x23, 0x5A, 0x42, 0xB2, 0x10, 0x0D, 0x89, 0xEB,
|
|
||||||
0xFB, 0x41, 0xB4, 0xE4, 0x2D, 0x56, 0x1F, 0xE6, 0x95, 0x2D, 0x9C, 0x0A, 0x9B, 0xF6, 0xD4, 0x9D,
|
|
||||||
0x87, 0x64, 0x37, 0x8F, 0x53, 0x9F, 0xA4, 0x13, 0xD3, 0xE1, 0x1F, 0xDA, 0x59, 0xE2, 0x7A, 0x30,
|
|
||||||
0x10, 0x1A, 0xD6, 0xEE, 0x7D, 0xFB, 0x2E, 0xF0, 0xE9, 0x8A, 0x29, 0x65, 0xDF, 0x61, 0xE3, 0xDB,
|
|
||||||
0x7C, 0x18, 0xF1, 0x77, 0x45, 0x97, 0x20, 0x9D, 0x58, 0xC9, 0xBD, 0x96, 0xC5, 0x61, 0xE0, 0x6B,
|
|
||||||
0xDF, 0xF8, 0xBE, 0x2F, 0xA5, 0x9A, 0xC7, 0x94, 0xC6, 0xEB, 0x89, 0x8D, 0x9A, 0xA4, 0x40, 0xB6,
|
|
||||||
0x0A, 0x28, 0x61, 0xB3, 0x90, 0x49, 0x14, 0xDF, 0xA5, 0x6E, 0x22, 0x65, 0x9B, 0xD8, 0xEB, 0xF5,
|
|
||||||
0x9E, 0xAE, 0x76, 0x6C, 0x4F, 0xDC, 0x30, 0x58, 0x46, 0x13, 0x94, 0x5F, 0x4C, 0x3C, 0xA3, 0xB8,
|
|
||||||
0x0D, 0x33, 0x9A, 0xCE, 0xA8, 0x6F, 0x1C, 0x34, 0xAD, 0xF2, 0x26, 0x66, 0x1B, 0xE5, 0x51, 0x79,
|
|
||||||
0xD3, 0x6A, 0x27, 0xA7, 0x1A, 0x1D, 0xDF, 0x8A, 0x5B, 0x92, 0xE2, 0x4E, 0x86, 0x42, 0x04, 0x1A,
|
|
||||||
0x27, 0x52, 0x35, 0xF0, 0xB1, 0xB2, 0xC6, 0xAA, 0x52, 0x6A, 0x84, 0xAC, 0xEB, 0x5B, 0x1D, 0xF6,
|
|
||||||
0x1D, 0x88, 0x5D, 0xD7, 0xB7, 0xDA, 0xD5, 0x6A, 0xFA, 0x50, 0x8A, 0x47, 0x71, 0x13, 0x3B, 0x24,
|
|
||||||
0xF6, 0xDA, 0x86, 0x6D, 0x12, 0x34, 0x19, 0x4D, 0x83, 0x44, 0x11, 0x7C, 0x12, 0xD1, 0x55, 0x3B,
|
|
||||||
0x5E, 0xB4, 0xE9, 0x36, 0x21, 0xCD, 0xD8, 0xF7, 0x5B, 0xBB, 0x1A, 0x5B, 0x1D, 0xE3, 0x6B, 0xFF,
|
|
||||||
0x8F, 0x35, 0xF1, 0x03, 0x57, 0x6B, 0xAE, 0xC1, 0x00, 0x38, 0xDF, 0xE1, 0x00, 0x74, 0xDE, 0xDA,
|
|
||||||
0x29, 0x76, 0x2C, 0xDA, 0xFB, 0x68, 0x18, 0x35, 0x04, 0xE3, 0xB1, 0x5D, 0x4B, 0x30, 0x1E, 0x1E,
|
|
||||||
0x21, 0xB0, 0x6C, 0xD3, 0xAC, 0xA5, 0xB0, 0x2C, 0x4E, 0xD2, 0x89, 0xDC, 0x5B, 0xD5, 0x6C, 0x85,
|
|
||||||
0xC8, 0x9E, 0xE7, 0x55, 0x1C, 0xC6, 0xAC, 0xBA, 0x8B, 0x09, 0xC6, 0x92, 0x81, 0x1B, 0x23, 0xE2,
|
|
||||||
0x80, 0xD5, 0x46, 0xA4, 0xC6, 0x4B, 0x99, 0xEF, 0x72, 0x85, 0xA6, 0xAE, 0x1F, 0x6C, 0xB2, 0xC9,
|
|
||||||
0x00, 0x8C, 0xAC, 0xC6, 0x09, 0xDC, 0x5D, 0x12, 0x67, 0x01, 0x0D, 0xE2, 0x68, 0x92, 0x92, 0xD0,
|
|
||||||
0xA5, 0xC1, 0x2D, 0x71, 0xFC, 0x20, 0x4B, 0x42, 0x77, 0x3B, 0x99, 0x87, 0xB1, 0xF7, 0x25, 0x77,
|
|
||||||
0x08, 0x44, 0x1F, 0x8D, 0xB9, 0x2F, 0xF3, 0x09, 0x9F, 0x78, 0x71, 0xEA, 0x32, 0x42, 0x26, 0x43,
|
|
||||||
0x21, 0xFF, 0xBE, 0xE3, 0x7A, 0xC8, 0x67, 0x57, 0x20, 0x46, 0x8D, 0x84, 0xA6, 0x69, 0xCA, 0x81,
|
|
||||||
0x9A, 0x6B, 0xB8, 0x93, 0x45, 0xEC, 0x6D, 0x32, 0x78, 0xAE, 0x62, 0xB0, 0xF9, 0x9D, 0x0A, 0x36,
|
|
||||||
0x89, 0x1B, 0x91, 0x70, 0x77, 0x28, 0x7B, 0x3D, 0x38, 0x1D, 0xF1, 0xFF, 0xB2, 0x32, 0x10, 0xFC,
|
|
||||||
0x24, 0xEA, 0xCE, 0xE3, 0xFB, 0x76, 0xB6, 0x72, 0xFD, 0xF8, 0x6E, 0x62, 0x6A, 0x48, 0x85, 0x7F,
|
|
||||||
0xE9, 0x72, 0xEE, 0x36, 0x4D, 0x03, 0x5F, 0x1D, 0xB3, 0xDF, 0x72, 0xCE, 0x19, 0x24, 0x24, 0x6D,
|
|
||||||
0x33, 0x84, 0xCE, 0xB5, 0x86, 0xE0, 0x26, 0x3A, 0xD0, 0xD8, 0xA1, 0x6D, 0x77, 0xA8, 0xD1, 0xD3,
|
|
||||||
0x88, 0xDB, 0xC7, 0x97, 0x5C, 0x81, 0x68, 0x54, 0xD6, 0x04, 0x48, 0xC0, 0x4D, 0x43, 0xAE, 0xAE,
|
|
||||||
0x8B, 0xBA, 0x29, 0xFA, 0xD0, 0x8C, 0x6A, 0xBA, 0x84, 0x26, 0x2B, 0xDE, 0x1B, 0xBA, 0x73, 0x50,
|
|
||||||
0xB6, 0xB4, 0x80, 0x20, 0x62, 0xB8, 0xC4, 0x0D, 0xA1, 0x0C, 0xC1, 0x15, 0x63, 0xC2, 0x55, 0xB0,
|
|
||||||
0xE8, 0x72, 0xC7, 0x31, 0x6C, 0x88, 0xDB, 0xCB, 0x0C, 0x25, 0x88, 0x16, 0xB1, 0xDC, 0xCF, 0x2E,
|
|
||||||
0x18, 0xFF, 0x08, 0xB6, 0x74, 0x11, 0xA7, 0xEB, 0x36, 0x7A, 0x46, 0x1A, 0x17, 0x93, 0xF1, 0x59,
|
|
||||||
0xF8, 0x0C, 0x2C, 0x70, 0x08, 0x38, 0xEC, 0xF6, 0x8A, 0x90, 0x81, 0x66, 0xAC, 0x59, 0xB6, 0x9C,
|
|
||||||
0xEC, 0xDC, 0x50, 0xD6, 0xEF, 0xF7, 0x8F, 0x59, 0x4B, 0xD1, 0x1A, 0xAC, 0xDD, 0xA5, 0x74, 0xA8,
|
|
||||||
0x03, 0x1B, 0x42, 0xBF, 0x3C, 0xCB, 0x86, 0x82, 0x28, 0x23, 0x54, 0x3B, 0x62, 0x24, 0xC3, 0xB2,
|
|
||||||
0x29, 0x3D, 0x38, 0xB6, 0x1D, 0xB7, 0x69, 0x0A, 0xE1, 0x9B, 0x3B, 0xA8, 0x6A, 0x01, 0x1A, 0x71,
|
|
||||||
0x33, 0x02, 0xBA, 0x6D, 0xC7, 0x1B, 0xAA, 0x75, 0xAC, 0x7E, 0x66, 0x14, 0x7C, 0x0F, 0xFA, 0xCA,
|
|
||||||
0x0A, 0xE7, 0xAE, 0xB6, 0x2B, 0xDB, 0xD3, 0x60, 0xE0, 0x2E, 0xC8, 0xD8, 0x01, 0x0A, 0xD4, 0x24,
|
|
||||||
0x04, 0xDC, 0x27, 0x2C, 0xCD, 0x30, 0xA1, 0x73, 0x24, 0x3B, 0x2C, 0xD3, 0x36, 0xAC, 0x61, 0xDF,
|
|
||||||
0xB0, 0xBB, 0x5D, 0xA3, 0x33, 0x68, 0x09, 0x19, 0x50, 0xD7, 0x49, 0xC5, 0x99, 0xB9, 0x8F, 0xCC,
|
|
||||||
0x69, 0x74, 0xCC, 0xEE, 0xD4, 0xC1, 0x66, 0xC9, 0xCC, 0x7A, 0xA6, 0xE9, 0x28, 0x21, 0xDA, 0x23,
|
|
||||||
0x11, 0x25, 0x69, 0x35, 0x6A, 0xAE, 0x03, 0xDF, 0x0F, 0x09, 0x4F, 0xC0, 0xE2, 0x8D, 0xB7, 0x6A,
|
|
||||||
0x23, 0xEC, 0x80, 0x3E, 0xD7, 0x6E, 0x14, 0x24, 0x9B, 0x90, 0x81, 0x98, 0x73, 0xBC, 0xC7, 0xDB,
|
|
||||||
0xA4, 0x19, 0xA8, 0x28, 0x89, 0x03, 0xC6, 0xFC, 0x4C, 0x8B, 0x61, 0xFB, 0x96, 0xB8, 0x29, 0x48,
|
|
||||||
0xE4, 0x9C, 0x48, 0x33, 0x1E, 0x69, 0xCF, 0x35, 0x26, 0xB8, 0x8E, 0xBF, 0xB6, 0x37, 0x19, 0x26,
|
|
||||||
0x4B, 0x24, 0x24, 0x1E, 0xE5, 0xE2, 0xE0, 0x5A, 0x0F, 0x1A, 0xAB, 0x0D, 0x4C, 0xE7, 0xED, 0x24,
|
|
||||||
0x85, 0x65, 0xA4, 0xDB, 0xD3, 0x68, 0xDD, 0xED, 0x0E, 0xDD, 0xF9, 0xB0, 0x82, 0x41, 0x36, 0x19,
|
|
||||||
0xF8, 0x6E, 0xAF, 0xC4, 0x45, 0x20, 0xBA, 0x51, 0x6A, 0xE3, 0xD0, 0x5E, 0x6A, 0x62, 0x28, 0x5F,
|
|
||||||
0x6A, 0x9A, 0xD4, 0x50, 0x4E, 0x0E, 0x29, 0x0F, 0xE2, 0x43, 0x8D, 0xB0, 0xF6, 0x68, 0x60, 0x8E,
|
|
||||||
0xCD, 0x8A, 0xB0, 0x96, 0x6D, 0xCF, 0x7B, 0xE6, 0xDE, 0x73, 0x13, 0xDC, 0x54, 0x89, 0xC1, 0x2C,
|
|
||||||
0x8D, 0x1A, 0x29, 0x29, 0xA9, 0xB0, 0xB2, 0x51, 0x01, 0xCA, 0xC3, 0xE1, 0xD0, 0x39, 0xC8, 0x02,
|
|
||||||
0xDD, 0x10, 0x4C, 0xAC, 0x04, 0xF2, 0x35, 0xC1, 0xF5, 0xB4, 0x51, 0x1C, 0x6C, 0xA5, 0xE0, 0xDA,
|
|
||||||
0xCE, 0x36, 0x9E, 0x47, 0xB2, 0xAC, 0x26, 0x9F, 0xF1, 0x17, 0x0B, 0xD3, 0x1F, 0x55, 0x23, 0xC1,
|
|
||||||
0x80, 0x8C, 0xBD, 0x41, 0x1E, 0x42, 0xBC, 0xE1, 0xA0, 0xEB, 0x4B, 0x56, 0xBE, 0x1B, 0x2D, 0x41,
|
|
||||||
0x5B, 0x35, 0xD0, 0x67, 0xFB, 0xC4, 0x27, 0x15, 0x4E, 0x64, 0xEE, 0x79, 0xBE, 0x25, 0x39, 0xB9,
|
|
||||||
0xE3, 0x5E, 0xAF, 0x67, 0xEF, 0x3B, 0x2B, 0x37, 0x6B, 0x93, 0x34, 0x05, 0xC8, 0x29, 0xC3, 0x76,
|
|
||||||
0x99, 0x96, 0x8F, 0xFE, 0xB3, 0x01, 0xF1, 0xA8, 0x34, 0xB5, 0x98, 0x36, 0xEA, 0x75, 0xFB, 0xDD,
|
|
||||||
0xDE, 0x93, 0x91, 0x0C, 0x5D, 0xF3, 0x1B, 0x8F, 0x8C, 0x7A, 0xA3, 0xEE, 0x63, 0x64, 0xAC, 0xD2,
|
|
||||||
0x96, 0x64, 0x16, 0xE2, 0xB6, 0x79, 0x98, 0xAD, 0xD1, 0xB4, 0xD8, 0xFC, 0x93, 0xBA, 0xE6, 0x7B,
|
|
||||||
0xFC, 0xAF, 0xD1, 0x75, 0xAD, 0x3C, 0xB5, 0xDA, 0xB6, 0xE7, 0xFD, 0x9E, 0xED, 0xFD, 0x3E, 0x6D,
|
|
||||||
0x0F, 0x86, 0x73, 0x6B, 0x30, 0x7A, 0x9A, 0xB6, 0x39, 0x6D, 0x45, 0xEA, 0x5A, 0x7D, 0x4B, 0x1F,
|
|
||||||
0x41, 0x58, 0x11, 0x1E, 0x72, 0x12, 0x4F, 0xFC, 0x31, 0x98, 0xD1, 0xA2, 0xEA, 0x76, 0xBD, 0xEE,
|
|
||||||
0xA2, 0xEB, 0xAA, 0x4C, 0x4A, 0xD8, 0x27, 0x9A, 0x14, 0x00, 0x13, 0x2D, 0x0A, 0xF2, 0xF1, 0x96,
|
|
||||||
0xC9, 0x21, 0xD9, 0xE4, 0x80, 0xEC, 0x1C, 0xD8, 0xF3, 0xC6, 0x5D, 0xD3, 0xF6, 0x2A, 0x62, 0x0E,
|
|
||||||
0x07, 0x96, 0x67, 0x8D, 0x99, 0x98, 0xC1, 0x7A, 0xB9, 0x13, 0xB1, 0x6C, 0xE5, 0x46, 0xD5, 0x94,
|
|
||||||
0x78, 0x50, 0x87, 0x57, 0x3C, 0x01, 0xE7, 0xB4, 0x42, 0x84, 0x1A, 0x2C, 0x31, 0xF1, 0x55, 0x99,
|
|
||||||
0xD7, 0x04, 0x11, 0xFF, 0x72, 0xC7, 0x03, 0xC1, 0x99, 0xA4, 0xA7, 0x57, 0xDE, 0x35, 0x45, 0xFA,
|
|
||||||
0x21, 0xC7, 0x3E, 0xB4, 0xD2, 0xBF, 0x7E, 0x5D, 0x21, 0x88, 0x06, 0x19, 0xC2, 0x17, 0x69, 0x10,
|
|
||||||
0xEC, 0x30, 0x95, 0xB7, 0x4E, 0x84, 0x8D, 0x2D, 0x82, 0x90, 0xB0, 0xEF, 0xDC, 0x5D, 0xF3, 0xB1,
|
|
||||||
0xE3, 0x1E, 0xEC, 0x6A, 0x10, 0x25, 0x1B, 0xFA, 0x0B, 0x9E, 0x9E, 0xA7, 0x38, 0xEE, 0xD7, 0xC9,
|
|
||||||
0x44, 0x2E, 0x0B, 0xBF, 0xB6, 0x37, 0x49, 0x18, 0xBB, 0x7E, 0x7B, 0xBE, 0x81, 0x68, 0xF6, 0x77,
|
|
||||||
0x5E, 0xF6, 0xAF, 0xCD, 0xCB, 0x9C, 0x93, 0x6E, 0xDE, 0x9F, 0x7B, 0xE6, 0x41, 0xE8, 0xEE, 0x0D,
|
|
||||||
0xE6, 0x23, 0xDF, 0x7D, 0xD4, 0xA6, 0x0A, 0xAB, 0xF8, 0x7B, 0x6B, 0xFF, 0x7D, 0xB6, 0xB6, 0x6B,
|
|
||||||
0xCD, 0x4D, 0xBF, 0x7A, 0xD2, 0xB7, 0xE6, 0x03, 0x7F, 0xD4, 0x7F, 0xDC, 0xD6, 0x72, 0x00, 0xFB,
|
|
||||||
0x7B, 0x6B, 0xFF, 0xCD, 0xB7, 0xD6, 0x1E, 0x8C, 0xDD, 0xB9, 0xB7, 0xCF, 0x81, 0xBA, 0x04, 0xE7,
|
|
||||||
0x65, 0xF4, 0x56, 0xD0, 0xBC, 0x94, 0x0A, 0x08, 0x34, 0x17, 0x15, 0xA6, 0x45, 0x1C, 0x83, 0x52,
|
|
||||||
0x4F, 0x14, 0x98, 0x58, 0xFD, 0xE5, 0x69, 0x35, 0xA6, 0x83, 0x3A, 0x2F, 0x1A, 0x1C, 0x86, 0x49,
|
|
||||||
0xBE, 0x57, 0x3D, 0x25, 0x69, 0xE8, 0xE2, 0x4B, 0x25, 0x55, 0x3A, 0xBB, 0xBD, 0xF1, 0xC8, 0x9F,
|
|
||||||
0x57, 0x54, 0xDF, 0x37, 0x9F, 0x3B, 0xB2, 0x6E, 0x0A, 0xD2, 0xCA, 0x9D, 0xC2, 0xCF, 0x60, 0x3B,
|
|
||||||
0x6B, 0x5E, 0x66, 0xCC, 0x92, 0x20, 0xD2, 0xEC, 0x4C, 0xC3, 0xCD, 0x74, 0x53, 0x2D, 0x88, 0x16,
|
|
||||||
0x41, 0x04, 0x96, 0xB0, 0xFF, 0xC7, 0x17, 0xB2, 0x5D, 0xA4, 0xEE, 0x9A, 0x64, 0x1A, 0x0E, 0xD9,
|
|
||||||
0x99, 0xCF, 0x77, 0xCC, 0x5C, 0x30, 0x63, 0x9D, 0xA4, 0x31, 0x75, 0x29, 0x69, 0x9A, 0xAD, 0x3D,
|
|
||||||
0x16, 0xAD, 0x0E, 0x3B, 0xBA, 0x03, 0x00, 0xD3, 0x65, 0x6B, 0xFF, 0x97, 0x68, 0x70, 0x1D, 0xFB,
|
|
||||||
0x6E, 0x51, 0xFF, 0x62, 0x46, 0x94, 0x57, 0x63, 0x17, 0xC1, 0x3D, 0xF1, 0x9D, 0xAF, 0xED, 0x20,
|
|
||||||
0xF2, 0xC9, 0x3D, 0x56, 0xDC, 0xCC, 0xA2, 0x10, 0xCC, 0x78, 0x61, 0x7D, 0xD9, 0x61, 0x25, 0x62,
|
|
||||||
0x70, 0x5A, 0x68, 0x30, 0x1D, 0xA5, 0x38, 0x27, 0x35, 0x88, 0x9F, 0xD1, 0x5C, 0x16, 0x21, 0x24,
|
|
||||||
0x1A, 0xAC, 0xA8, 0x56, 0x5B, 0x89, 0x3D, 0x6C, 0x55, 0x93, 0x90, 0x5E, 0x4B, 0x88, 0xCA, 0xF2,
|
|
||||||
0x7F, 0x70, 0xC1, 0x5D, 0xB1, 0xA6, 0x52, 0x75, 0xD1, 0x32, 0xCB, 0x95, 0xC7, 0x52, 0x55, 0x52,
|
|
||||||
0xED, 0x14, 0x45, 0xFE, 0x63, 0xB4, 0xA2, 0xFB, 0x18, 0x39, 0x5E, 0x0B, 0xE4, 0xE6, 0x24, 0x0B,
|
|
||||||
0x13, 0x4A, 0x7D, 0x16, 0x4B, 0x50, 0x16, 0x42, 0x81, 0x59, 0xCA, 0xA5, 0xEC, 0x96, 0x73, 0x58,
|
|
||||||
0xEB, 0xE6, 0x70, 0x58, 0xBA, 0xA8, 0x9A, 0xD4, 0xA8, 0xE3, 0x9B, 0x05, 0xC1, 0x97, 0xD4, 0x03,
|
|
||||||
0x56, 0x72, 0x15, 0x2B, 0xB1, 0xC5, 0x84, 0x4E, 0x9E, 0xFC, 0xE2, 0xAB, 0x8E, 0x8B, 0x8D, 0xAF,
|
|
||||||
0x63, 0xC5, 0xD9, 0x47, 0xAA, 0xAF, 0x54, 0x9E, 0x5C, 0xE0, 0x4B, 0x8A, 0x57, 0xAE, 0x40, 0x9B,
|
|
||||||
0x42, 0x3A, 0xD9, 0x5B, 0x35, 0xF1, 0x81, 0x94, 0x5E, 0x18, 0x4D, 0xAF, 0xD3, 0x27, 0xEB, 0xC7,
|
|
||||||
0x2F, 0xE5, 0x50, 0x9C, 0xDF, 0xB9, 0xDB, 0x27, 0xEE, 0x6D, 0xCA, 0xD6, 0xC8, 0xFB, 0xFA, 0x23,
|
|
||||||
0xF5, 0x2A, 0x26, 0xF3, 0x52, 0x42, 0x22, 0x0D, 0xB2, 0x7D, 0xA0, 0xCF, 0x0B, 0xD7, 0xC3, 0xC1,
|
|
||||||
0xF0, 0x28, 0x3D, 0xBB, 0x57, 0xDC, 0x5F, 0x5D, 0xF2, 0x9B, 0xDC, 0xAB, 0x4B, 0x7E, 0xAF, 0xCB,
|
|
||||||
0x6E, 0x9B, 0xAE, 0xFC, 0xE0, 0x56, 0x63, 0xED, 0x53, 0x3D, 0x37, 0x21, 0x77, 0x0E, 0x8B, 0xDD,
|
|
||||||
0x50, 0x22, 0x9C, 0x8F, 0x5F, 0xCE, 0x98, 0xFA, 0xEC, 0xBF, 0xAD, 0x8E, 0xA5, 0xBD, 0x88, 0xE6,
|
|
||||||
0x59, 0xE2, 0xF0, 0xF7, 0xAB, 0x4B, 0x20, 0x9F, 0x5D, 0xF1, 0x68, 0x3A, 0xBB, 0x5A, 0xD9, 0xB3,
|
|
||||||
0x37, 0x54, 0xCB, 0x08, 0x59, 0x67, 0xDA, 0x36, 0xDE, 0x68, 0x7E, 0xAC, 0x45, 0x31, 0xD5, 0x56,
|
|
||||||
0x2E, 0x5E, 0x84, 0x44, 0x5B, 0x8D, 0x39, 0x7C, 0x07, 0x6F, 0x92, 0xB5, 0x88, 0x04, 0x74, 0x45,
|
|
||||||
0x52, 0xA5, 0xA9, 0xB3, 0xFC, 0x6A, 0x68, 0x49, 0x88, 0x05, 0x5E, 0x8D, 0x87, 0x7C, 0x2D, 0xA0,
|
|
||||||
0x5A, 0x9C, 0xC2, 0x17, 0x1F, 0xE0, 0x0C, 0x19, 0xA6, 0xDA, 0x22, 0x48, 0xD7, 0x77, 0x10, 0x2B,
|
|
||||||
0xB5, 0x60, 0x01, 0x2C, 0xF0, 0x20, 0x8C, 0x25, 0x37, 0x58, 0x91, 0x0D, 0xCB, 0x92, 0x62, 0xE0,
|
|
||||||
0x92, 0xBC, 0xD0, 0xCD, 0x32, 0x58, 0x12, 0x22, 0x9F, 0xAE, 0x05, 0xFE, 0x54, 0xBF, 0x7E, 0xFF,
|
|
||||||
0xE6, 0xF5, 0xEB, 0x6B, 0xFD, 0xB0, 0x5B, 0x5E, 0x5E, 0xE8, 0xB3, 0xD7, 0xD0, 0xBA, 0xD2, 0x5E,
|
|
||||||
0x43, 0x34, 0xCA, 0xB6, 0x19, 0x25, 0x6B, 0xB1, 0xBC, 0x03, 0x02, 0xD4, 0x1C, 0x30, 0x62, 0x79,
|
|
||||||
0x8B, 0xC6, 0xF2, 0x16, 0x1D, 0x43, 0x18, 0x9F, 0x87, 0xE5, 0x2C, 0x3C, 0x78, 0xEA, 0x5A, 0x04,
|
|
||||||
0xD8, 0x3D, 0xD5, 0xD7, 0x5B, 0x6C, 0xCC, 0x7E, 0xF9, 0x55, 0xD7, 0xD6, 0x9B, 0x90, 0x06, 0x09,
|
|
||||||
0x6A, 0x5B, 0x7E, 0xD2, 0x67, 0x9A, 0xE0, 0x24, 0xE6, 0x80, 0xE3, 0x9A, 0xA6, 0x94, 0x05, 0x75,
|
|
||||||
0x31, 0x03, 0xCF, 0x7F, 0xF8, 0x1C, 0xA5, 0x94, 0x48, 0xD7, 0xE2, 0xC8, 0x0B, 0x03, 0xEF, 0x0B,
|
|
||||||
0xAC, 0x91, 0x44, 0x3E, 0x4E, 0xD5, 0x6C, 0x39, 0xBA, 0x76, 0xEB, 0x86, 0x1B, 0xA0, 0xFB, 0xC8,
|
|
||||||
0xC6, 0xEA, 0xB3, 0xD2, 0xBE, 0x25, 0x69, 0xBC, 0x4C, 0xB1, 0x8C, 0x20, 0xB6, 0xFE, 0x36, 0xC8,
|
|
||||||
0x82, 0x79, 0x10, 0x06, 0x74, 0x3B, 0x59, 0x41, 0x12, 0x44, 0x22, 0x29, 0x7A, 0x92, 0x2E, 0xF9,
|
|
||||||
0x94, 0xEC, 0x03, 0x98, 0xDB, 0x54, 0x07, 0x6B, 0x82, 0xC5, 0x5F, 0x4A, 0x16, 0x60, 0x48, 0x29,
|
|
||||||
0xFF, 0x3B, 0xD0, 0xFB, 0x71, 0xD5, 0xF1, 0x1B, 0xE3, 0x2B, 0x0A, 0x54, 0xD4, 0xD7, 0x98, 0x95,
|
|
||||||
0x4E, 0x75, 0xF3, 0x79, 0xAE, 0xD4, 0xF3, 0x54, 0x51, 0x5A, 0xF7, 0xF7, 0xF1, 0x1A, 0xB2, 0x31,
|
|
||||||
0xBF, 0xD9, 0xC0, 0x2B, 0xC4, 0x86, 0xD1, 0x70, 0xC3, 0xB0, 0xA1, 0xA8, 0xE1, 0x03, 0x59, 0x80,
|
|
||||||
0xB4, 0x2B, 0x94, 0x9C, 0xFA, 0x07, 0xB3, 0xA2, 0x9C, 0x39, 0xB7, 0xEF, 0x53, 0x02, 0x06, 0xE7,
|
|
||||||
0x07, 0x69, 0xB3, 0xA5, 0x2B, 0x92, 0xC0, 0xF1, 0x19, 0x46, 0x66, 0xB7, 0x4B, 0x49, 0xD9, 0x33,
|
|
||||||
0x75, 0x8D, 0x03, 0x0B, 0xFF, 0x7C, 0x1B, 0x90, 0xBB, 0xEF, 0x62, 0xD0, 0x10, 0x9E, 0x6A, 0x7B,
|
|
||||||
0xF8, 0x0F, 0xC6, 0xA7, 0x60, 0x07, 0x1A, 0xB4, 0xF5, 0x75, 0x6D, 0x8B, 0xBA, 0xD3, 0x25, 0x75,
|
|
||||||
0x57, 0xA1, 0xB6, 0xE1, 0x73, 0x0A, 0x83, 0x6C, 0x78, 0x6C, 0xD9, 0x03, 0x76, 0x31, 0x9C, 0xEA,
|
|
||||||
0x22, 0xB7, 0xD2, 0x2F, 0x0B, 0x3E, 0x38, 0x74, 0xCB, 0xD8, 0x09, 0x3E, 0x56, 0xBF, 0xE0, 0x83,
|
|
||||||
0x9F, 0x1F, 0xE0, 0x83, 0x49, 0x30, 0xF2, 0xB1, 0xB8, 0x40, 0x36, 0x3C, 0xF2, 0x8C, 0x12, 0x5A,
|
|
||||||
0x47, 0xE2, 0xEB, 0x9D, 0xE0, 0x38, 0x82, 0xCD, 0x16, 0x4C, 0x58, 0x72, 0xAA, 0xCF, 0x2E, 0x40,
|
|
||||||
0x81, 0xC0, 0x03, 0xF4, 0x08, 0xAA, 0x98, 0x09, 0x17, 0x11, 0x3A, 0xE5, 0x8A, 0x44, 0x73, 0xE1,
|
|
||||||
0x19, 0x54, 0xAE, 0x3E, 0xF1, 0xB5, 0x32, 0x3C, 0x5F, 0x82, 0x99, 0x6F, 0x02, 0x33, 0x35, 0x97,
|
|
||||||
0xAE, 0x72, 0x4A, 0xBC, 0x63, 0x93, 0xC6, 0xAB, 0x52, 0x5F, 0xA2, 0xED, 0x5C, 0x4A, 0x3B, 0xC2,
|
|
||||||
0x87, 0xA4, 0xE0, 0x5F, 0x4A, 0x57, 0xEB, 0xBA, 0xB4, 0xF3, 0x22, 0xFB, 0x46, 0x23, 0xE4, 0x38,
|
|
||||||
0xC8, 0x8C, 0x70, 0xA5, 0x9A, 0xC3, 0x0D, 0x58, 0x19, 0xF0, 0x5E, 0x61, 0xFB, 0xEC, 0x67, 0xF0,
|
|
||||||
0x83, 0xFC, 0xCB, 0x35, 0x68, 0x49, 0x7E, 0x29, 0x19, 0x50, 0xA5, 0x4D, 0xAC, 0x88, 0xB5, 0x0A,
|
|
||||||
0x49, 0xC5, 0x64, 0xE8, 0x00, 0x39, 0x4E, 0x7C, 0x46, 0x5B, 0x65, 0xE3, 0x38, 0x18, 0xCB, 0xF5,
|
|
||||||
0x1C, 0xC1, 0x1D, 0x1E, 0xDE, 0xB8, 0x3F, 0x66, 0x90, 0xE3, 0x6D, 0xB2, 0x42, 0xA3, 0x07, 0xEF,
|
|
||||||
0xE7, 0x78, 0x63, 0x81, 0x7C, 0x12, 0x57, 0x3F, 0x32, 0xB0, 0x7D, 0x00, 0xF8, 0x4A, 0xDE, 0x7B,
|
|
||||||
0x14, 0x07, 0xEF, 0x8E, 0xA2, 0xA0, 0x62, 0x2F, 0x4F, 0x43, 0x3E, 0xE0, 0x7D, 0x80, 0x01, 0x1C,
|
|
||||||
0xE7, 0x0E, 0xD1, 0x0F, 0xD7, 0xA3, 0xCE, 0xF8, 0x18, 0xE8, 0x5B, 0xDC, 0xE5, 0xE0, 0x87, 0x1F,
|
|
||||||
0xEB, 0xE1, 0x2F, 0xE7, 0x0C, 0xE7, 0xB6, 0x88, 0x0D, 0x5F, 0x67, 0x4B, 0xFD, 0x38, 0xFB, 0xD9,
|
|
||||||
0x07, 0x02, 0x9B, 0x07, 0x07, 0xCF, 0x68, 0x99, 0x07, 0xBC, 0x3B, 0x37, 0xA0, 0x1D, 0xF8, 0x0F,
|
|
||||||
0x9C, 0x0A, 0x98, 0x28, 0xAC, 0x3C, 0x48, 0x4C, 0x28, 0xF7, 0x1C, 0xDE, 0x73, 0x68, 0xFC, 0xD5,
|
|
||||||
0x4D, 0xE7, 0xEE, 0x07, 0xA9, 0x5F, 0x02, 0x87, 0xCE, 0xDC, 0x8F, 0x58, 0x5E, 0x50, 0xB6, 0x81,
|
|
||||||
0x52, 0xAA, 0x50, 0xD7, 0xC5, 0x73, 0x41, 0xE8, 0x59, 0x75, 0x67, 0x6F, 0x40, 0x74, 0x1A, 0x2C,
|
|
||||||
0xE0, 0xB4, 0x8C, 0x29, 0x02, 0x44, 0xDC, 0x6E, 0x8D, 0xA1, 0x15, 0x39, 0x9A, 0xCE, 0xD7, 0x20,
|
|
||||||
0x56, 0x52, 0xEA, 0x46, 0xF4, 0xD0, 0xF9, 0xB1, 0x17, 0x32, 0x55, 0x32, 0xFB, 0x08, 0xA7, 0xCD,
|
|
||||||
0x89, 0x58, 0x5E, 0x25, 0x14, 0xAA, 0x95, 0x79, 0x69, 0x0D, 0x9C, 0x3C, 0x5F, 0xE4, 0x67, 0x3C,
|
|
||||||
0xAC, 0x7E, 0xE6, 0x8D, 0x42, 0xE5, 0xC5, 0x3D, 0x7B, 0xA1, 0xB6, 0x55, 0x7A, 0xBE, 0x40, 0xEF,
|
|
||||||
0xA1, 0xEF, 0x0E, 0x80, 0xE2, 0x11, 0x42, 0x25, 0x82, 0x44, 0x15, 0x4C, 0xB6, 0x3D, 0x2C, 0x1C,
|
|
||||||
0x06, 0xCF, 0x23, 0xBA, 0x14, 0x2E, 0x5F, 0x76, 0x32, 0x69, 0xFB, 0xC7, 0xDC, 0xA6, 0x88, 0x8B,
|
|
||||||
0x9B, 0xF9, 0x3A, 0xA0, 0x1F, 0xC8, 0xFF, 0x6D, 0xC0, 0xE4, 0x30, 0x9A, 0x09, 0xAF, 0xE0, 0xED,
|
|
||||||
0xB5, 0xE0, 0x01, 0xD9, 0x65, 0x90, 0xD0, 0xD9, 0x62, 0x13, 0xB1, 0x0A, 0x07, 0xF8, 0xC2, 0xED,
|
|
||||||
0xDC, 0x85, 0x48, 0xB8, 0xBB, 0x85, 0x83, 0x29, 0x90, 0x2A, 0xCE, 0xAF, 0x1B, 0x74, 0xEA, 0x6D,
|
|
||||||
0x52, 0xAC, 0x5C, 0x20, 0x64, 0x77, 0xE0, 0xAC, 0x17, 0xD0, 0xA6, 0x7E, 0xA9, 0xB7, 0x8C, 0x68,
|
|
||||||
0x0A, 0x0F, 0x23, 0x98, 0x5A, 0x0E, 0x68, 0xAB, 0x49, 0x2E, 0x90, 0xCE, 0x17, 0xF2, 0x36, 0x78,
|
|
||||||
0x2C, 0x6D, 0x68, 0xB9, 0x9C, 0x9F, 0x74, 0x85, 0xCD, 0xB4, 0x71, 0xD9, 0x70, 0xB4, 0xE3, 0x11,
|
|
||||||
0xFD, 0x93, 0x3E, 0xBB, 0x64, 0x5E, 0xA0, 0x3B, 0xC1, 0x15, 0xED, 0x84, 0x24, 0x5A, 0xD2, 0x55,
|
|
||||||
0xDB, 0x72, 0x5A, 0xD1, 0xC5, 0x94, 0xFE, 0x12, 0xFC, 0x7A, 0x81, 0x33, 0x1F, 0x99, 0xF1, 0xC8,
|
|
||||||
0x84, 0xFA, 0x45, 0x74, 0xA1, 0x3F, 0x34, 0xA9, 0x7E, 0xC1, 0xB9, 0xE7, 0xFE, 0x2E, 0xA4, 0x30,
|
|
||||||
0x82, 0x8B, 0x0B, 0x27, 0x25, 0x74, 0x93, 0x46, 0x1A, 0x9B, 0x56, 0x75, 0x4E, 0x7D, 0x9F, 0x2B,
|
|
||||||
0x12, 0xEC, 0x2B, 0x5B, 0x7D, 0x0E, 0xC0, 0x70, 0x14, 0x65, 0x16, 0xD9, 0x44, 0xC3, 0xEE, 0x35,
|
|
||||||
0x64, 0x1C, 0x67, 0x9F, 0x65, 0x36, 0xD1, 0xC0, 0x6C, 0xC2, 0xB2, 0x47, 0xF8, 0xD7, 0x80, 0x45,
|
|
||||||
0xAB, 0x53, 0x89, 0xA4, 0xA0, 0xD1, 0xB7, 0x1B, 0x10, 0xCC, 0x1B, 0x16, 0x3C, 0x20, 0xFC, 0x37,
|
|
||||||
0x06, 0x0D, 0x0C, 0xFF, 0xF8, 0x90, 0xBC, 0xFB, 0x05, 0xEF, 0x61, 0x43, 0x98, 0x62, 0x03, 0xC3,
|
|
||||||
0x3A, 0x1C, 0x17, 0x7D, 0xA7, 0xA1, 0x5D, 0xCE, 0x84, 0xCE, 0xAA, 0x1C, 0xEB, 0x79, 0xD8, 0x65,
|
|
||||||
0x1E, 0x2C, 0x33, 0xA8, 0xE3, 0xD2, 0x35, 0x39, 0x97, 0xD1, 0x11, 0xB9, 0x06, 0xC3, 0x82, 0x27,
|
|
||||||
0xE0, 0xEA, 0x59, 0x92, 0xD9, 0x65, 0x9E, 0x96, 0xC9, 0x99, 0xE2, 0x53, 0x70, 0x1D, 0xA9, 0x5C,
|
|
||||||
0x7B, 0x8F, 0x61, 0x6A, 0x8F, 0x6B, 0x99, 0x74, 0xCF, 0x5C, 0x6E, 0x8F, 0x73, 0xE9, 0x75, 0xB9,
|
|
||||||
0x68, 0x43, 0x2E, 0xD9, 0x30, 0xE7, 0xA9, 0xB0, 0x1C, 0x9C, 0xCB, 0x73, 0xF0, 0x27, 0xF0, 0x1C,
|
|
||||||
0xFD, 0x11, 0x3C, 0x79, 0xFE, 0xA7, 0x18, 0x38, 0x1E, 0xA4, 0xA5, 0x7D, 0x73, 0x23, 0x3D, 0xDF,
|
|
||||||
0xBE, 0xED, 0x1E, 0xFC, 0x6B, 0x40, 0x70, 0x06, 0x7F, 0xD4, 0xFC, 0x69, 0xE3, 0xA7, 0xA1, 0xD1,
|
|
||||||
0xD5, 0xDE, 0xDA, 0xC6, 0x48, 0x7B, 0x3B, 0x34, 0xAC, 0x2E, 0x7B, 0x37, 0xB5, 0xB7, 0x96, 0x78,
|
|
||||||
0x8C, 0x0C, 0xCB, 0xE2, 0x8F, 0x3E, 0x6F, 0x1C, 0xC0, 0xC3, 0x64, 0x8F, 0xB1, 0x61, 0x0D, 0xD9,
|
|
||||||
0xFB, 0x98, 0x35, 0xD9, 0x30, 0xDC, 0x16, 0x0F, 0xDB, 0xB0, 0x46, 0xEC, 0x31, 0x62, 0x6D, 0x03,
|
|
||||||
0xE4, 0x3A, 0xD0, 0xBE, 0xE2, 0x02, 0xD3, 0xF8, 0x0B, 0xAC, 0x90, 0x5D, 0x33, 0x35, 0x78, 0xBA,
|
|
||||||
0xDB, 0x60, 0x2B, 0xAD, 0x5D, 0x28, 0x4F, 0x6B, 0x3E, 0xE3, 0x01, 0x81, 0xB4, 0x76, 0x0A, 0x92,
|
|
||||||
0x5C, 0x4C, 0x09, 0x43, 0x1F, 0x15, 0x47, 0x74, 0x96, 0xE2, 0x19, 0x3A, 0xE0, 0x88, 0xDE, 0x2A,
|
|
||||||
0x78, 0x78, 0xF1, 0x1A, 0x6B, 0xBE, 0xD7, 0x90, 0x9F, 0x46, 0xCB, 0xAC, 0x49, 0x0C, 0x2A, 0x95,
|
|
||||||
0x06, 0xB8, 0x40, 0x3A, 0x34, 0x7E, 0x1B, 0xDF, 0x91, 0xF4, 0x7B, 0xC8, 0x0D, 0x9A, 0x2D, 0x80,
|
|
||||||
0x59, 0x5A, 0x69, 0x21, 0x57, 0xF4, 0x65, 0xDB, 0x9A, 0x90, 0x19, 0x7D, 0x69, 0x4D, 0xCC, 0x82,
|
|
||||||
0x2D, 0x16, 0xDC, 0x5C, 0xEA, 0xAD, 0x58, 0xA6, 0xC5, 0x32, 0x44, 0x14, 0x11, 0xD1, 0x06, 0x72,
|
|
||||||
0x79, 0x00, 0xCC, 0x45, 0x13, 0x9E, 0xEA, 0x49, 0xF0, 0x9A, 0x0D, 0x9A, 0x68, 0xFA, 0x05, 0xE9,
|
|
||||||
0x70, 0x02, 0x83, 0x5E, 0x94, 0x87, 0xFC, 0xA6, 0x7E, 0xB9, 0x89, 0xA9, 0x1B, 0x6A, 0xBC, 0x42,
|
|
||||||
0xCD, 0x88, 0x28, 0x36, 0x9C, 0xA6, 0x81, 0x00, 0xEF, 0xAB, 0x24, 0x10, 0xB1, 0xFD, 0xD3, 0x14,
|
|
||||||
0xEF, 0x3C, 0x6F, 0x93, 0xF0, 0xD2, 0xA8, 0xA6, 0xB3, 0xA1, 0x57, 0x6B, 0x02, 0x71, 0x50, 0x5B,
|
|
||||||
0x07, 0x11, 0x18, 0x4C, 0x83, 0x65, 0x62, 0x1C, 0x31, 0x56, 0x60, 0x51, 0xD3, 0xC6, 0x18, 0x3E,
|
|
||||||
0xF1, 0xD8, 0xD6, 0xC0, 0x19, 0xE2, 0x9C, 0x1E, 0x70, 0x1D, 0x36, 0x90, 0x11, 0x8B, 0x43, 0x44,
|
|
||||||
0xB5, 0xFF, 0xB9, 0x6E, 0xF8, 0xB1, 0xB7, 0x59, 0xC3, 0x1E, 0x76, 0x96, 0x84, 0xFE, 0x10, 0x12,
|
|
||||||
0xFC, 0xF8, 0xDD, 0xF6, 0x0D, 0xEC, 0x9D, 0x48, 0xB2, 0x5B, 0x9D, 0x20, 0x8A, 0x48, 0xFA, 0xE3,
|
|
||||||
0xCD, 0x4F, 0x6F, 0xA7, 0xD4, 0x40, 0x4D, 0x1A, 0xB0, 0xCD, 0xCF, 0xD4, 0xE0, 0xC7, 0x95, 0x1C,
|
|
||||||
0x95, 0xE2, 0x21, 0xC4, 0x1E, 0xFA, 0x06, 0xEB, 0x1B, 0xEF, 0x16, 0x18, 0x15, 0x8D, 0x52, 0x1F,
|
|
||||||
0x0F, 0x5B, 0x76, 0xCB, 0x61, 0xAB, 0xA3, 0xA9, 0xF4, 0x32, 0xF5, 0x32, 0xF7, 0x44, 0xC0, 0x2A,
|
|
||||||
0xC5, 0x5D, 0x18, 0x42, 0x9A, 0xA6, 0x11, 0x5D, 0x58, 0xAD, 0x87, 0xE3, 0x18, 0x86, 0x45, 0x08,
|
|
||||||
0x66, 0x8A, 0xB7, 0x16, 0x31, 0x0D, 0xCC, 0x32, 0xC4, 0x94, 0x04, 0xB0, 0xA1, 0x31, 0x83, 0xB3,
|
|
||||||
0x00, 0x26, 0xA4, 0x32, 0xDF, 0xD4, 0xF7, 0x84, 0x15, 0xEA, 0xB3, 0x0E, 0xC8, 0x47, 0x9B, 0xD2,
|
|
||||||
0xE4, 0x4A, 0xA6, 0x5B, 0xB5, 0xEA, 0x0E, 0x66, 0xD2, 0x06, 0x65, 0x8F, 0xD6, 0xBE, 0xC5, 0x92,
|
|
||||||
0x01, 0xD4, 0x53, 0x30, 0x35, 0x21, 0x78, 0x4B, 0x7E, 0x5C, 0x17, 0x0E, 0xC4, 0xD1, 0x96, 0xDE,
|
|
||||||
0xB6, 0x40, 0xAF, 0x9C, 0xBE, 0x29, 0xFA, 0x21, 0xEA, 0x76, 0xF0, 0x74, 0xDA, 0x7A, 0xF1, 0xA2,
|
|
||||||
0xC9, 0x94, 0x75, 0xF3, 0x61, 0x26, 0x8C, 0x82, 0x65, 0xDD, 0x00, 0x31, 0x2A, 0xAE, 0x28, 0x70,
|
|
||||||
0x53, 0x03, 0x31, 0xDA, 0xEC, 0x13, 0x2D, 0x50, 0xC6, 0x32, 0x6C, 0x40, 0x09, 0xC3, 0xB6, 0x10,
|
|
||||||
0x6B, 0x6C, 0xFC, 0x3C, 0xE0, 0x8F, 0x21, 0x6B, 0xB3, 0x10, 0x1F, 0xDE, 0x5A, 0xB6, 0x78, 0xB7,
|
|
||||||
0x34, 0x1C, 0x66, 0x9D, 0x81, 0x18, 0x58, 0xC7, 0xD7, 0xEE, 0x2D, 0x1E, 0x91, 0xB7, 0xF8, 0x6C,
|
|
||||||
0x68, 0xF7, 0x36, 0x3C, 0x00, 0x59, 0xB7, 0x36, 0x8B, 0x80, 0x15, 0x0E, 0xFC, 0x6B, 0x5B, 0x08,
|
|
||||||
0x6F, 0x35, 0x2E, 0xE5, 0x12, 0x73, 0x56, 0x7D, 0xC1, 0xC9, 0x14, 0xAC, 0xBA, 0x9C, 0x95, 0x65,
|
|
||||||
0x9E, 0xC1, 0x0B, 0xD6, 0x7C, 0xC0, 0xA7, 0x57, 0xE1, 0xD3, 0x7B, 0x22, 0x9F, 0x51, 0x85, 0xCF,
|
|
||||||
0xE8, 0x0C, 0x3E, 0xB2, 0x76, 0xC0, 0xF2, 0x27, 0x58, 0x66, 0xE3, 0xEA, 0xE6, 0x95, 0xC8, 0xD5,
|
|
||||||
0x3E, 0x89, 0x64, 0xED, 0x53, 0x23, 0x2F, 0x4B, 0xCA, 0xDA, 0x75, 0x72, 0xEF, 0x80, 0xF9, 0xBA,
|
|
||||||
0xDA, 0x2A, 0x25, 0x8B, 0xA9, 0xDE, 0x00, 0x3F, 0x66, 0xA0, 0xAB, 0x98, 0x09, 0xDA, 0xD9, 0x45,
|
|
||||||
0x03, 0x92, 0x72, 0x37, 0x05, 0x57, 0x9E, 0x7E, 0x06, 0x01, 0xA2, 0x2F, 0xA5, 0xAC, 0x3A, 0xFF,
|
|
||||||
0x25, 0x81, 0x3E, 0x6B, 0xE0, 0xCC, 0x15, 0x62, 0xAE, 0x73, 0x91, 0x0F, 0xBB, 0xF0, 0x77, 0xF3,
|
|
||||||
0x6A, 0x06, 0xB2, 0x71, 0x29, 0x2B, 0xF6, 0x28, 0xC6, 0xF2, 0x11, 0xD2, 0xEC, 0xCC, 0xE7, 0x0D,
|
|
||||||
0x75, 0xBE, 0x4F, 0xA2, 0x70, 0xF4, 0x49, 0x57, 0x5C, 0xF9, 0x15, 0xC4, 0x0F, 0x4A, 0x9A, 0x0C,
|
|
||||||
0xA9, 0xCA, 0xA2, 0xEB, 0x8D, 0x16, 0x66, 0x9A, 0xC8, 0x59, 0x4D, 0x17, 0x4B, 0x52, 0xE1, 0x7C,
|
|
||||||
0xDC, 0x27, 0xF1, 0x0D, 0x7D, 0xA1, 0xF0, 0xAB, 0x10, 0xFC, 0x2A, 0xAC, 0xFA, 0x55, 0x28, 0xFC,
|
|
||||||
0x6A, 0x5A, 0xF5, 0xAB, 0xF0, 0x0F, 0xF5, 0x2B, 0xC5, 0xAB, 0xC6, 0x3C, 0x3C, 0x8F, 0x31, 0xD0,
|
|
||||||
0x42, 0x90, 0x86, 0x78, 0x2C, 0xDE, 0xFA, 0x18, 0x72, 0x7B, 0xE8, 0x45, 0x3D, 0xF4, 0xBB, 0x3E,
|
|
||||||
0x73, 0x3E, 0x9B, 0x0D, 0xC5, 0x07, 0x06, 0x6A, 0x74, 0xC5, 0x2E, 0xA3, 0xEF, 0xB3, 0x77, 0x9B,
|
|
||||||
0x7B, 0x22, 0xF4, 0x9F, 0x17, 0xA7, 0x0B, 0xA3, 0xD2, 0x71, 0x5B, 0xCA, 0x27, 0x00, 0x2D, 0xDF,
|
|
||||||
0xFE, 0x3C, 0xAB, 0x39, 0xBC, 0x0E, 0x53, 0x51, 0x57, 0x09, 0xF5, 0xCA, 0x76, 0x85, 0xC5, 0x76,
|
|
||||||
0x39, 0x72, 0xBF, 0x2A, 0x7D, 0x25, 0xE3, 0x90, 0xF2, 0x3C, 0xD9, 0x56, 0x8E, 0xCF, 0xFF, 0x24,
|
|
||||||
0x73, 0x39, 0x1A, 0xEF, 0x8A, 0x9A, 0x54, 0x39, 0xE4, 0x1D, 0x25, 0x60, 0xA5, 0x3A, 0x75, 0xAC,
|
|
||||||
0x3C, 0x2E, 0x16, 0x29, 0x89, 0xB0, 0x76, 0xCC, 0x94, 0xE2, 0x08, 0xEB, 0xF7, 0x4D, 0xFD, 0x7B,
|
|
||||||
0xFE, 0x41, 0xF3, 0xB1, 0x0B, 0xC7, 0xC4, 0x0B, 0xDC, 0x4C, 0x9E, 0x1E, 0x80, 0x39, 0x96, 0xF2,
|
|
||||||
0x27, 0x36, 0x88, 0x40, 0x06, 0x7B, 0xC0, 0x53, 0x26, 0x60, 0xA7, 0xD8, 0xC2, 0x18, 0xD8, 0xC0,
|
|
||||||
0x38, 0xDD, 0x9E, 0xE0, 0x0D, 0x63, 0xCA, 0xEC, 0x95, 0x02, 0xB0, 0x38, 0xA9, 0x25, 0x29, 0x44,
|
|
||||||
0x36, 0x38, 0xDB, 0xBE, 0xE7, 0xE5, 0x1A, 0x76, 0xD1, 0x50, 0xF0, 0x66, 0x05, 0x23, 0xC8, 0x09,
|
|
||||||
0x40, 0xB5, 0xD1, 0x26, 0x0C, 0x9F, 0x4D, 0x49, 0x65, 0x1E, 0x4F, 0x32, 0x84, 0x79, 0x3A, 0xE0,
|
|
||||||
0x84, 0xEB, 0x66, 0x4B, 0x99, 0x4E, 0x1D, 0xCA, 0xA2, 0x29, 0x4F, 0x25, 0x22, 0x72, 0xA7, 0xFD,
|
|
||||||
0xEF, 0x4F, 0x6F, 0x7F, 0xA4, 0x34, 0x11, 0x27, 0x78, 0x38, 0x50, 0xEB, 0x97, 0xCC, 0x04, 0x5E,
|
|
||||||
0xF2, 0xDF, 0x1F, 0x4C, 0x61, 0x4D, 0x10, 0x37, 0x21, 0x93, 0xC2, 0x56, 0x5E, 0xB6, 0xBA, 0x20,
|
|
||||||
0x91, 0x17, 0xFB, 0xE4, 0xE3, 0x87, 0x37, 0x4D, 0xDA, 0x32, 0x58, 0x27, 0x4B, 0x1A, 0xD4, 0x0E,
|
|
||||||
0x35, 0x71, 0x39, 0xBE, 0xB9, 0xA2, 0x68, 0xDB, 0xEA, 0x30, 0x57, 0xE9, 0x14, 0x95, 0x2C, 0x51,
|
|
||||||
0xD5, 0x0A, 0x61, 0xCD, 0x51, 0x27, 0x8E, 0x60, 0x71, 0xFE, 0x16, 0x53, 0x25, 0xE2, 0xAD, 0xF0,
|
|
||||||
0x27, 0x7D, 0xD3, 0x3C, 0x37, 0x68, 0xED, 0x20, 0xE3, 0xEC, 0x4D, 0xA7, 0x51, 0x87, 0x8D, 0xC1,
|
|
||||||
0x64, 0x93, 0xB4, 0xA0, 0xC9, 0x36, 0x4D, 0x6C, 0xE4, 0xE9, 0x95, 0xD4, 0xF1, 0x7F, 0x5D, 0xBF,
|
|
||||||
0xFB, 0x19, 0x10, 0x3D, 0x85, 0x04, 0x17, 0xC7, 0x67, 0x49, 0x1C, 0x65, 0xE4, 0x86, 0xDC, 0xD3,
|
|
||||||
0x13, 0x06, 0x7B, 0x42, 0x44, 0x51, 0x6D, 0x33, 0x6A, 0x53, 0xE2, 0x3D, 0x09, 0x61, 0x1B, 0x2B,
|
|
||||||
0xE5, 0x91, 0x3D, 0xAE, 0x26, 0x21, 0x51, 0x53, 0xFF, 0xCF, 0x1F, 0x6E, 0xE0, 0x5C, 0x6F, 0x3C,
|
|
||||||
0x33, 0x5B, 0xD0, 0x94, 0xC1, 0xF6, 0x34, 0x2B, 0xDB, 0xC5, 0xCB, 0x8C, 0xBB, 0xBC, 0x8D, 0xD9,
|
|
||||||
0x37, 0x2C, 0x8C, 0x08, 0xD0, 0x85, 0xED, 0x4C, 0x36, 0xAC, 0x04, 0x20, 0xB3, 0x6F, 0xC2, 0x7F,
|
|
||||||
0x54, 0xE0, 0x5F, 0x8A, 0x94, 0xF9, 0x3F, 0x20, 0x7B, 0x3D, 0xBE, 0x2E, 0xBC, 0x6D, 0x69, 0x75,
|
|
||||||
0x78, 0x46, 0x7B, 0xC2, 0xFD, 0xCA, 0xF7, 0x40, 0x92, 0x40, 0x94, 0x42, 0x01, 0xD5, 0xB4, 0x4E,
|
|
||||||
0xA7, 0xA3, 0x5F, 0xE0, 0xE1, 0xE1, 0x35, 0xDE, 0xB9, 0x37, 0xCD, 0x16, 0xE6, 0xBB, 0xFB, 0x3D,
|
|
||||||
0x17, 0xE9, 0x24, 0x0C, 0xC8, 0xE2, 0x6D, 0x8B, 0x63, 0x0E, 0x1E, 0x1D, 0xCC, 0x67, 0x53, 0x59,
|
|
||||||
0x6F, 0x69, 0xED, 0x9E, 0x2C, 0x13, 0x8A, 0x74, 0x02, 0x50, 0xD8, 0xC2, 0x8F, 0x1B, 0x9C, 0x53,
|
|
||||||
0xF8, 0xC6, 0xEB, 0x38, 0x5D, 0xBF, 0x72, 0xA9, 0xEB, 0x44, 0x1D, 0x37, 0x49, 0x70, 0x93, 0x38,
|
|
||||||
0x1C, 0xA9, 0x79, 0x76, 0x35, 0xE5, 0xA4, 0x6A, 0xB2, 0xB9, 0xE3, 0x21, 0x13, 0xCB, 0x3A, 0x0A,
|
|
||||||
0x8F, 0xA2, 0x4C, 0x6D, 0x84, 0x2A, 0xAB, 0x8B, 0x50, 0xA4, 0xB1, 0x48, 0xE5, 0xD7, 0x78, 0xA7,
|
|
||||||
0xE3, 0x0B, 0xEB, 0x79, 0xFF, 0xEE, 0xFA, 0x06, 0x4F, 0x08, 0x8C, 0x8F, 0xCE, 0xAC, 0xC8, 0xEF,
|
|
||||||
0x70, 0xB5, 0x74, 0x20, 0xDA, 0xFC, 0x70, 0x0B, 0x1C, 0xDF, 0x02, 0xC8, 0x12, 0x00, 0x4D, 0x5C,
|
|
||||||
0x31, 0x2F, 0x24, 0x03, 0x34, 0x18, 0xCF, 0x2C, 0x1C, 0x1A, 0x47, 0x38, 0xB4, 0xE2, 0x45, 0xCC,
|
|
||||||
0x65, 0xA6, 0x7E, 0xEE, 0x33, 0x4F, 0xD3, 0xFF, 0x13, 0x34, 0x9F, 0xFB, 0xD1, 0x79, 0xD6, 0x22,
|
|
||||||
0xA6, 0xD3, 0x9D, 0x1A, 0xBF, 0x53, 0x3C, 0xDC, 0x2F, 0x7B, 0xB8, 0x70, 0x48, 0xF6, 0xD3, 0xFE,
|
|
||||||
0xA6, 0xFE, 0x2D, 0x38, 0x14, 0xFB, 0x51, 0x39, 0x9E, 0xD3, 0x60, 0x03, 0xFC, 0x67, 0x70, 0x74,
|
|
||||||
0x06, 0xC5, 0x30, 0x4F, 0x8C, 0x5A, 0xFB, 0xC2, 0x17, 0xD5, 0xA2, 0xFF, 0x9F, 0xEA, 0x8D, 0x8B,
|
|
||||||
0xBB, 0x73, 0xFC, 0x11, 0x0B, 0xFF, 0x6A, 0x34, 0x7C, 0xD8, 0x13, 0x41, 0xCA, 0x83, 0xF8, 0x55,
|
|
||||||
0xB9, 0x8C, 0xD1, 0x5E, 0xEA, 0x2D, 0x29, 0xF7, 0xF1, 0x4D, 0xB8, 0xFB, 0x9D, 0x0E, 0x5B, 0x5C,
|
|
||||||
0xA9, 0x3C, 0xCD, 0x08, 0x94, 0xF9, 0x9F, 0x40, 0xCE, 0x15, 0x77, 0x22, 0xCE, 0x9C, 0xAF, 0xF2,
|
|
||||||
0x13, 0x63, 0xC5, 0x4F, 0x00, 0xE4, 0x44, 0xE2, 0xD7, 0x49, 0x53, 0x1D, 0x7F, 0x9E, 0x74, 0xDA,
|
|
||||||
0x33, 0xD8, 0xF6, 0x9F, 0x40, 0x25, 0x89, 0x32, 0x65, 0x64, 0x32, 0x1E, 0x09, 0x3A, 0x1C, 0x73,
|
|
||||||
0xF4, 0x4B, 0xFD, 0xF1, 0x58, 0xC3, 0x7F, 0x24, 0x01, 0x62, 0xFE, 0x35, 0x70, 0xA3, 0x5A, 0xCF,
|
|
||||||
0xB9, 0x80, 0x73, 0xB0, 0x73, 0x27, 0xEE, 0xC5, 0x4E, 0xB0, 0x91, 0x37, 0x64, 0x4F, 0x33, 0x9F,
|
|
||||||
0x3F, 0xC4, 0xF8, 0x8F, 0x31, 0x91, 0x17, 0xC4, 0xC9, 0xFD, 0x99, 0x9E, 0x23, 0xC1, 0xF3, 0x4F,
|
|
||||||
0xF3, 0xB3, 0x43, 0x72, 0x45, 0x46, 0xE7, 0x20, 0x0F, 0xAB, 0xA0, 0x34, 0x62, 0x8A, 0x8E, 0x05,
|
|
||||||
0x1A, 0x59, 0x2B, 0x7C, 0xF1, 0x42, 0xEF, 0x95, 0xBF, 0xAA, 0xBD, 0xBF, 0xFD, 0x26, 0xF0, 0x5C,
|
|
||||||
0xE0, 0xD8, 0xC2, 0x05, 0x1B, 0xF7, 0xF5, 0x96, 0xA1, 0xDB, 0x70, 0x18, 0x95, 0xA3, 0x5A, 0xE5,
|
|
||||||
0x41, 0x9E, 0x1B, 0x79, 0x20, 0x21, 0x42, 0xBE, 0xC3, 0x62, 0x02, 0xCE, 0xD9, 0x55, 0xC7, 0x73,
|
|
||||||
0x28, 0x34, 0xA2, 0xA9, 0x09, 0xFE, 0xF5, 0x90, 0xD3, 0x3A, 0x41, 0x07, 0x6B, 0x85, 0x3D, 0xD3,
|
|
||||||
0xA0, 0xD3, 0x8C, 0xD0, 0x37, 0x68, 0x2A, 0xA0, 0xE5, 0xA6, 0x62, 0xED, 0xD1, 0xC5, 0xD4, 0x7A,
|
|
||||||
0xD8, 0xF9, 0xF9, 0xD6, 0x44, 0xE7, 0xD8, 0x61, 0x61, 0xD2, 0x3D, 0xAB, 0x1D, 0x19, 0xD1, 0xAC,
|
|
||||||
0x67, 0xC2, 0x11, 0xDB, 0x03, 0x8B, 0x4E, 0xF3, 0xF9, 0x21, 0x35, 0x0F, 0x63, 0x7E, 0x97, 0x0A,
|
|
||||||
0x3A, 0x46, 0xF3, 0xC1, 0x23, 0x81, 0x61, 0x91, 0x6E, 0x39, 0x14, 0x96, 0x54, 0x87, 0x61, 0xF0,
|
|
||||||
0x51, 0x71, 0xB2, 0x08, 0x94, 0x02, 0x37, 0xDE, 0xE2, 0xCD, 0x64, 0xF3, 0x84, 0x3B, 0x9F, 0x93,
|
|
||||||
0x50, 0x1F, 0xA7, 0x95, 0x97, 0xCE, 0x07, 0x08, 0xCB, 0x7E, 0xA0, 0xAD, 0x94, 0xD0, 0x2B, 0x99,
|
|
||||||
0xF7, 0x29, 0x79, 0x8E, 0xF2, 0x64, 0xA8, 0x2D, 0x6C, 0xF6, 0x34, 0xBD, 0x72, 0x47, 0x2C, 0x36,
|
|
||||||
0x52, 0x1C, 0xC2, 0x8C, 0x13, 0x11, 0xB5, 0xEE, 0x12, 0xB7, 0x42, 0x8D, 0xB7, 0x9C, 0x6C, 0xD8,
|
|
||||||
0xCB, 0x8F, 0xD7, 0x3F, 0x7C, 0x50, 0x4F, 0x58, 0x98, 0x71, 0x80, 0x78, 0x11, 0x85, 0x4C, 0xE4,
|
|
||||||
0x42, 0x7F, 0xF1, 0xFE, 0xDB, 0xEB, 0xEB, 0xFF, 0x79, 0xF7, 0xE1, 0x55, 0xFD, 0x10, 0x8A, 0x43,
|
|
||||||
0xAE, 0x3F, 0x7E, 0xF7, 0xD3, 0x9B, 0x9B, 0xE9, 0x16, 0x33, 0xC6, 0xA0, 0x0E, 0xF1, 0x83, 0x07,
|
|
||||||
0x4E, 0x5A, 0x70, 0xCC, 0x0A, 0x94, 0x63, 0xD6, 0x8B, 0x17, 0x00, 0xE1, 0xCF, 0xA0, 0x49, 0xBA,
|
|
||||||
0x66, 0xD9, 0x02, 0xF6, 0x46, 0xA0, 0x9E, 0x75, 0x22, 0x16, 0x36, 0x02, 0x79, 0xD6, 0x41, 0xA5,
|
|
||||||
0xAA, 0x05, 0x67, 0x08, 0x49, 0xCE, 0x5D, 0x10, 0xF9, 0xF1, 0x5D, 0x4D, 0xB4, 0x38, 0x7E, 0xDB,
|
|
||||||
0xE1, 0x5C, 0x5D, 0x8A, 0xEB, 0xE4, 0xAB, 0x4B, 0xF1, 0x03, 0x17, 0xF6, 0x3F, 0x96, 0xF9, 0x7F,
|
|
||||||
0x4B, 0x13, 0x97, 0xBB, 0x5F, 0x46, 0x00, 0x00
|
|
||||||
};
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
/*
|
|
||||||
storestrings.cpp - rolling storage class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#include "storestrings.h"
|
|
||||||
//Constructor
|
|
||||||
STORESTRINGS_CLASS::STORESTRINGS_CLASS (int maxsize, int maxstringlength)
|
|
||||||
{
|
|
||||||
//for rolling buffer
|
|
||||||
//if max size is reached then remove oldest one and add the new one
|
|
||||||
_maxsize=maxsize;
|
|
||||||
//to limit the storage space
|
|
||||||
_maxstringlength=maxstringlength;
|
|
||||||
//need space for the "..."
|
|
||||||
if (_maxstringlength<4 && _maxstringlength!=-1) {
|
|
||||||
_maxstringlength=4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Destructor
|
|
||||||
STORESTRINGS_CLASS::~STORESTRINGS_CLASS ()
|
|
||||||
{
|
|
||||||
// clear list and content
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool STORESTRINGS_CLASS::setsize(int size)
|
|
||||||
{
|
|
||||||
_maxsize=size;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool STORESTRINGS_CLASS::setlength(int len)
|
|
||||||
{
|
|
||||||
if (len < 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_maxstringlength = len;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Clear list and content
|
|
||||||
void STORESTRINGS_CLASS::clear()
|
|
||||||
{
|
|
||||||
//while list is not empty
|
|
||||||
while(_charlist.size()) {
|
|
||||||
//remove element
|
|
||||||
char * str = _charlist.pop();
|
|
||||||
//destroy it
|
|
||||||
delete str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool STORESTRINGS_CLASS::add (const __FlashStringHelper *str)
|
|
||||||
{
|
|
||||||
String stmp;
|
|
||||||
stmp=str;
|
|
||||||
return add(stmp.c_str());
|
|
||||||
}
|
|
||||||
//Add element in storage
|
|
||||||
bool STORESTRINGS_CLASS::add (const char * string)
|
|
||||||
{
|
|
||||||
//if we reach max size
|
|
||||||
if (_maxsize==_charlist.size()) {
|
|
||||||
//remove oldest one
|
|
||||||
char * str = _charlist.shift();
|
|
||||||
delete str;
|
|
||||||
}
|
|
||||||
//add new one
|
|
||||||
//get size including \0 at the end
|
|
||||||
size_t size = strlen(string)+1;
|
|
||||||
bool need_resize=false;
|
|
||||||
if ( (_maxstringlength!=-1) && (size >_maxstringlength+1 )) {
|
|
||||||
need_resize = true;
|
|
||||||
size=_maxstringlength+1;
|
|
||||||
}
|
|
||||||
//reserve memory
|
|
||||||
char * ptr = new char[size*sizeof(char)];
|
|
||||||
//copy string to storage
|
|
||||||
if (need_resize) {
|
|
||||||
//copy maximum length minus 3
|
|
||||||
strncpy(ptr,string,_maxstringlength-3);
|
|
||||||
strcpy(ptr+_maxstringlength-3,"...");
|
|
||||||
} else {
|
|
||||||
//copy as it is
|
|
||||||
strcpy(ptr,string);
|
|
||||||
}
|
|
||||||
//add storage to list
|
|
||||||
_charlist.add(ptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//Remove element at pos position
|
|
||||||
bool STORESTRINGS_CLASS::remove(int pos)
|
|
||||||
{
|
|
||||||
//be sure index is in range
|
|
||||||
if (pos<0 && pos>(_charlist.size()-1)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//remove item from list
|
|
||||||
char * str = _charlist.remove(pos);
|
|
||||||
//destroy item
|
|
||||||
delete str;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//Get element at pos position
|
|
||||||
const char * STORESTRINGS_CLASS::get(int pos)
|
|
||||||
{
|
|
||||||
//be sure index is in range
|
|
||||||
if (pos<0 && pos>(_charlist.size()-1)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return (const char *) _charlist.get(pos);
|
|
||||||
}
|
|
||||||
//Get index for defined string
|
|
||||||
int STORESTRINGS_CLASS::get_index(const char * string)
|
|
||||||
{
|
|
||||||
//parse the list until it is found
|
|
||||||
for (int p=0; p<_charlist.size(); p++) {
|
|
||||||
if (strcmp ( _charlist.get(p), string)==0) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//if not found return -1
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
storestrings.h - rolling storage class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef STORESTRINGS_h
|
|
||||||
#define STORESTRINGS_h
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include "GenLinkedList.h"
|
|
||||||
class STORESTRINGS_CLASS
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
STORESTRINGS_CLASS (int maxsize = -1, int maxstringlength=-1);
|
|
||||||
~STORESTRINGS_CLASS ();
|
|
||||||
bool add (const char * string);
|
|
||||||
inline bool add (String & string)
|
|
||||||
{
|
|
||||||
return add(string.c_str());
|
|
||||||
};
|
|
||||||
bool add (const __FlashStringHelper *str);
|
|
||||||
bool remove(int pos);
|
|
||||||
const char * get(int pos);
|
|
||||||
int get_index(const char * string);
|
|
||||||
void clear();
|
|
||||||
inline int size()
|
|
||||||
{
|
|
||||||
return _charlist.size();
|
|
||||||
};
|
|
||||||
bool setsize(int size);
|
|
||||||
bool setlength(int len);
|
|
||||||
inline int getsize()
|
|
||||||
{
|
|
||||||
return _maxsize;
|
|
||||||
};
|
|
||||||
inline int getlength()
|
|
||||||
{
|
|
||||||
return _maxstringlength;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
int _maxsize;
|
|
||||||
int _maxstringlength;
|
|
||||||
GenLinkedList<char *> _charlist;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,505 +0,0 @@
|
|||||||
/*
|
|
||||||
wificonf.cpp - ESP3D configuration class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#include "config.h"
|
|
||||||
#include "wificonf.h"
|
|
||||||
#include "bridge.h"
|
|
||||||
#include "webinterface.h"
|
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include "ESP8266WiFi.h"
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
#include <ESP8266mDNS.h>
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#include <WiFi.h>
|
|
||||||
#include "esp_wifi.h"
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
#include <ESPmDNS.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#include "IPAddress.h"
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
#include <DNSServer.h>
|
|
||||||
DNSServer dnsServer;
|
|
||||||
const byte DNS_PORT = 53;
|
|
||||||
#endif
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include <ESP8266WebServer.h>
|
|
||||||
#else
|
|
||||||
#include <WebServer.h>
|
|
||||||
#endif
|
|
||||||
#ifdef SSDP_FEATURE
|
|
||||||
#include <ESP8266SSDP.h>
|
|
||||||
#endif
|
|
||||||
#ifdef NETBIOS_FEATURE
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include <ESP8266NetBIOS.h>
|
|
||||||
#else
|
|
||||||
#include <ESPNetBIOS.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
extern "C" {
|
|
||||||
#include "user_interface.h"
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef TIMESTAMP_FEATURE
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WIFI_CONFIG::WIFI_CONFIG()
|
|
||||||
{
|
|
||||||
iweb_port=DEFAULT_WEB_PORT;
|
|
||||||
idata_port=DEFAULT_DATA_PORT;
|
|
||||||
baud_rate=DEFAULT_BAUD_RATE;
|
|
||||||
sleep_mode=DEFAULT_SLEEP_MODE;
|
|
||||||
_hostname[0]=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t WIFI_CONFIG::getSignal(int32_t RSSI)
|
|
||||||
{
|
|
||||||
if (RSSI <= -100) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (RSSI >= -50) {
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
return (2* (RSSI+100));
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * WIFI_CONFIG::get_hostname()
|
|
||||||
{
|
|
||||||
String hname;
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
hname = WiFi.hostname();
|
|
||||||
#else
|
|
||||||
hname = WiFi.getHostname();
|
|
||||||
#endif
|
|
||||||
if (hname.length()==0) {
|
|
||||||
if (!CONFIG::read_string(EP_HOSTNAME, _hostname, MAX_HOSTNAME_LENGTH)) {
|
|
||||||
strcpy(_hostname,get_default_hostname());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
strcpy(_hostname,hname.c_str());
|
|
||||||
}
|
|
||||||
return _hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * WIFI_CONFIG::get_default_hostname()
|
|
||||||
{
|
|
||||||
static char hostname[13];
|
|
||||||
uint8_t mac [WL_MAC_ADDR_LENGTH];
|
|
||||||
WiFi.macAddress(mac);
|
|
||||||
if (0>sprintf(hostname,"ESP_%02X%02X%02X",mac[3],mac[4],mac[5])) {
|
|
||||||
strcpy (hostname, "ESP8266");
|
|
||||||
}
|
|
||||||
return hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
//safe setup if no connection
|
|
||||||
void WIFI_CONFIG::Safe_Setup()
|
|
||||||
{
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
dnsServer.stop();
|
|
||||||
delay(100);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WiFi.disconnect();
|
|
||||||
//setup Soft AP
|
|
||||||
WiFi.mode(WIFI_AP);
|
|
||||||
IPAddress local_ip (DEFAULT_IP_VALUE[0],DEFAULT_IP_VALUE[1],DEFAULT_IP_VALUE[2],DEFAULT_IP_VALUE[3]);
|
|
||||||
IPAddress gateway (DEFAULT_GATEWAY_VALUE[0],DEFAULT_GATEWAY_VALUE[1],DEFAULT_GATEWAY_VALUE[2],DEFAULT_GATEWAY_VALUE[3]);
|
|
||||||
IPAddress subnet (DEFAULT_MASK_VALUE[0],DEFAULT_MASK_VALUE[1],DEFAULT_MASK_VALUE[2],DEFAULT_MASK_VALUE[3]);
|
|
||||||
String ssid = FPSTR(DEFAULT_AP_SSID);
|
|
||||||
String pwd = FPSTR(DEFAULT_AP_PASSWORD);
|
|
||||||
WiFi.softAP(ssid.c_str(),pwd.c_str());
|
|
||||||
delay(500);
|
|
||||||
WiFi.softAPConfig( local_ip, gateway, subnet);
|
|
||||||
delay(1000);
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Safe mode started"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Read configuration settings and apply them
|
|
||||||
bool WIFI_CONFIG::Setup(bool force_ap)
|
|
||||||
{
|
|
||||||
char pwd[MAX_PASSWORD_LENGTH+1];
|
|
||||||
char sbuf[MAX_SSID_LENGTH+1];
|
|
||||||
char hostname [MAX_HOSTNAME_LENGTH+1];
|
|
||||||
//int wstatus;
|
|
||||||
IPAddress currentIP;
|
|
||||||
byte bflag=0;
|
|
||||||
byte bmode=0;
|
|
||||||
//system_update_cpu_freq(SYS_CPU_160MHZ);
|
|
||||||
//set the sleep mode
|
|
||||||
if (!CONFIG::read_byte(EP_SLEEP_MODE, &bflag )) {
|
|
||||||
LOG("Error read Sleep mode\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
WiFi.setSleepMode ((WiFiSleepType_t)bflag);
|
|
||||||
#else
|
|
||||||
esp_wifi_set_ps((wifi_ps_type_t)bflag);
|
|
||||||
#endif
|
|
||||||
sleep_mode=bflag;
|
|
||||||
if (force_ap) {
|
|
||||||
bmode = AP_MODE;
|
|
||||||
} else {
|
|
||||||
//AP or client ?
|
|
||||||
if (!CONFIG::read_byte(EP_WIFI_MODE, &bmode ) ) {
|
|
||||||
LOG("Error read wifi mode\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!CONFIG::read_string(EP_HOSTNAME, hostname, MAX_HOSTNAME_LENGTH)) {
|
|
||||||
strcpy(hostname,get_default_hostname());
|
|
||||||
}
|
|
||||||
//this is AP mode
|
|
||||||
if (bmode==AP_MODE) {
|
|
||||||
LOG("Set AP mode\r\n")
|
|
||||||
if(!CONFIG::read_string(EP_AP_SSID, sbuf, MAX_SSID_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!CONFIG::read_string(EP_AP_PASSWORD, pwd, MAX_PASSWORD_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.print(F("SSID "));
|
|
||||||
ESP_SERIAL_OUT.println(sbuf);
|
|
||||||
LOG("SSID ")
|
|
||||||
LOG(sbuf)
|
|
||||||
LOG("\r\n")
|
|
||||||
//DHCP or Static IP ?
|
|
||||||
if (!CONFIG::read_byte(EP_AP_IP_MODE, &bflag )) {
|
|
||||||
LOG("Error IP mode\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
LOG("IP Mode: ")
|
|
||||||
LOG(CONFIG::intTostr(bflag))
|
|
||||||
LOG("\r\n")
|
|
||||||
if (bflag==STATIC_IP_MODE) {
|
|
||||||
byte ip_buf[4];
|
|
||||||
LOG("Static mode\r\n")
|
|
||||||
//get the IP
|
|
||||||
LOG("IP value:")
|
|
||||||
if (!CONFIG::read_buffer(EP_AP_IP_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
LOG("Error\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress local_ip (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
LOG(local_ip.toString())
|
|
||||||
LOG("\r\nGW value:")
|
|
||||||
//get the gateway
|
|
||||||
if (!CONFIG::read_buffer(EP_AP_GATEWAY_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
LOG("Error\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress gateway (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
LOG(gateway.toString())
|
|
||||||
LOG("\r\nMask value:")
|
|
||||||
//get the mask
|
|
||||||
if (!CONFIG::read_buffer(EP_AP_MASK_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
LOG("Error Mask value\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress subnet (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
LOG(subnet.toString())
|
|
||||||
LOG("\r\n")
|
|
||||||
//apply according active wifi mode
|
|
||||||
LOG("Set IP\r\n")
|
|
||||||
WiFi.softAPConfig( local_ip, gateway, subnet);
|
|
||||||
delay(100);
|
|
||||||
}
|
|
||||||
LOG("Disable STA\r\n")
|
|
||||||
WiFi.enableSTA(false);
|
|
||||||
delay(100);
|
|
||||||
LOG("Set phy mode\r\n")
|
|
||||||
//setup PHY_MODE
|
|
||||||
if (!CONFIG::read_byte(EP_AP_PHY_MODE, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
esp_wifi_set_protocol(ESP_IF_WIFI_AP, bflag);
|
|
||||||
#endif
|
|
||||||
LOG("Set AP\r\n")
|
|
||||||
//setup Soft AP
|
|
||||||
WiFi.mode(WIFI_AP);
|
|
||||||
delay(50);
|
|
||||||
WiFi.softAP(sbuf, pwd);
|
|
||||||
delay(100);
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
WiFi.setPhyMode((WiFiPhyMode_t)bflag);
|
|
||||||
#endif
|
|
||||||
delay(100);
|
|
||||||
LOG("Get current config\r\n")
|
|
||||||
//get current config
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
wifi_config_t conf;
|
|
||||||
esp_wifi_get_config(ESP_IF_WIFI_AP, &conf);
|
|
||||||
#else
|
|
||||||
struct softap_config apconfig;
|
|
||||||
wifi_softap_get_config(&apconfig);
|
|
||||||
#endif
|
|
||||||
//set the chanel
|
|
||||||
if (!CONFIG::read_byte(EP_CHANNEL, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
conf.ap.channel=bflag;
|
|
||||||
#else
|
|
||||||
apconfig.channel=bflag;
|
|
||||||
#endif
|
|
||||||
//set Authentification type
|
|
||||||
if (!CONFIG::read_byte(EP_AUTH_TYPE, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
conf.ap.authmode=(wifi_auth_mode_t)bflag;
|
|
||||||
#else
|
|
||||||
apconfig.authmode=(AUTH_MODE)bflag;
|
|
||||||
#endif
|
|
||||||
//set the visibility of SSID
|
|
||||||
if (!CONFIG::read_byte(EP_SSID_VISIBLE, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
conf.ap.ssid_hidden=!bflag;
|
|
||||||
#else
|
|
||||||
apconfig.ssid_hidden=!bflag;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//no need to add these settings to configuration just use default ones
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
conf.ap.max_connection=DEFAULT_MAX_CONNECTIONS;
|
|
||||||
conf.ap.beacon_interval=DEFAULT_BEACON_INTERVAL;
|
|
||||||
if (esp_wifi_set_config(ESP_IF_WIFI_AP, &conf)!=ESP_OK){
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Error Wifi AP!"));
|
|
||||||
delay(1000);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
apconfig.max_connection=DEFAULT_MAX_CONNECTIONS;
|
|
||||||
apconfig.beacon_interval=DEFAULT_BEACON_INTERVAL;
|
|
||||||
//apply settings to current and to default
|
|
||||||
if (!wifi_softap_set_config(&apconfig) || !wifi_softap_set_config_current(&apconfig)) {
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Error Wifi AP!"));
|
|
||||||
delay(1000);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
LOG("Set STA mode\r\n")
|
|
||||||
if(!CONFIG::read_string(EP_STA_SSID, sbuf, MAX_SSID_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!CONFIG::read_string(EP_STA_PASSWORD, pwd, MAX_PASSWORD_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.print(F("SSID "));
|
|
||||||
ESP_SERIAL_OUT.println(sbuf);
|
|
||||||
LOG("SSID ")
|
|
||||||
LOG(sbuf)
|
|
||||||
LOG("\r\n")
|
|
||||||
if (!CONFIG::read_byte(EP_STA_IP_MODE, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bflag==STATIC_IP_MODE) {
|
|
||||||
byte ip_buf[4];
|
|
||||||
//get the IP
|
|
||||||
if (!CONFIG::read_buffer(EP_STA_IP_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress local_ip (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
//get the gateway
|
|
||||||
if (!CONFIG::read_buffer(EP_STA_GATEWAY_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress gateway (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
//get the mask
|
|
||||||
if (!CONFIG::read_buffer(EP_STA_MASK_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress subnet (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
//apply according active wifi mode
|
|
||||||
WiFi.config( local_ip, gateway, subnet);
|
|
||||||
}
|
|
||||||
WiFi.enableAP(false);
|
|
||||||
delay(100);
|
|
||||||
//setup PHY_MODE
|
|
||||||
if (!CONFIG::read_byte(EP_STA_PHY_MODE, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
esp_wifi_set_protocol(ESP_IF_WIFI_STA, bflag);
|
|
||||||
#endif
|
|
||||||
//setup station mode
|
|
||||||
WiFi.mode(WIFI_STA);
|
|
||||||
delay(100);
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
WiFi.setPhyMode((WiFiPhyMode_t)bflag);
|
|
||||||
#endif
|
|
||||||
WiFi.begin(sbuf, pwd);
|
|
||||||
delay(100);
|
|
||||||
byte i=0;
|
|
||||||
//try to connect
|
|
||||||
byte dot = 0;
|
|
||||||
String msg;
|
|
||||||
while (WiFi.status() != WL_CONNECTED && i<40) {
|
|
||||||
switch(WiFi.status()) {
|
|
||||||
case 1:
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.println(F("No SSID found!"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.println(F("No Connection!"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
if (dot == 0)msg = F("Connecting");
|
|
||||||
dot++;
|
|
||||||
msg.trim();
|
|
||||||
msg +=F(".");
|
|
||||||
//for smoothieware to keep position
|
|
||||||
for (byte i= 0;i< 4-dot; i++)msg +=F(" ");
|
|
||||||
if (dot == 4)dot=0;
|
|
||||||
ESP_SERIAL_OUT.println(msg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
delay(500);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.println(F("Not Connectied!"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
WiFi.hostname(hostname);
|
|
||||||
#else
|
|
||||||
WiFi.setHostname(hostname);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get IP
|
|
||||||
if (WiFi.getMode()==WIFI_STA) {
|
|
||||||
currentIP=WiFi.localIP();
|
|
||||||
} else {
|
|
||||||
currentIP=WiFi.softAPIP();
|
|
||||||
}
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.println(currentIP);
|
|
||||||
ESP_SERIAL_OUT.flush();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WIFI_CONFIG::Enable_servers()
|
|
||||||
{
|
|
||||||
//start web interface
|
|
||||||
web_interface = new WEBINTERFACE_CLASS(wifi_config.iweb_port);
|
|
||||||
//here the list of headers to be recorded
|
|
||||||
const char * headerkeys[] = {"Cookie"} ;
|
|
||||||
size_t headerkeyssize = sizeof(headerkeys)/sizeof(char*);
|
|
||||||
//ask server to track these headers
|
|
||||||
web_interface->web_server.collectHeaders(headerkeys, headerkeyssize );
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
if (WiFi.getMode()!=WIFI_STA ) {
|
|
||||||
// if DNSServer is started with "*" for domain name, it will reply with
|
|
||||||
// provided IP to all DNS request
|
|
||||||
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
|
|
||||||
dnsServer.start(DNS_PORT, "*", WiFi.softAPIP());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
web_interface->web_server.begin();
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
//start TCP/IP interface
|
|
||||||
data_server = new WiFiServer (wifi_config.idata_port);
|
|
||||||
data_server->begin();
|
|
||||||
data_server->setNoDelay(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
// Set up mDNS responder:
|
|
||||||
//useless in AP mode and service consuming
|
|
||||||
if (WiFi.getMode()!=WIFI_AP ){
|
|
||||||
char hostname [MAX_HOSTNAME_LENGTH+1];
|
|
||||||
if (!CONFIG::read_string(EP_HOSTNAME, hostname, MAX_HOSTNAME_LENGTH)) {
|
|
||||||
strcpy(hostname,get_default_hostname());
|
|
||||||
}
|
|
||||||
if (!mdns.begin(hostname)) {
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.println(F("Error with mDNS!"));
|
|
||||||
delay(1000);
|
|
||||||
} else {
|
|
||||||
// Check for any mDNS queries and send responses
|
|
||||||
delay(100);
|
|
||||||
wifi_config.mdns.addService("http", "tcp", wifi_config.iweb_port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(SSDP_FEATURE) || defined(NETBIOS_FEATURE)
|
|
||||||
String shost;
|
|
||||||
if (!CONFIG::read_string(EP_HOSTNAME, shost, MAX_HOSTNAME_LENGTH)) {
|
|
||||||
shost=wifi_config.get_default_hostname();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef SSDP_FEATURE
|
|
||||||
String stmp;
|
|
||||||
SSDP.setSchemaURL("description.xml");
|
|
||||||
SSDP.setHTTPPort( wifi_config.iweb_port);
|
|
||||||
SSDP.setName(shost.c_str());
|
|
||||||
stmp=String(ESP.getChipId());
|
|
||||||
SSDP.setSerialNumber(stmp.c_str());
|
|
||||||
SSDP.setURL("/");
|
|
||||||
SSDP.setModelName("ESP8266 01");
|
|
||||||
SSDP.setModelNumber("01");
|
|
||||||
SSDP.setModelURL("http://espressif.com/en/products/esp8266/");
|
|
||||||
SSDP.setManufacturer("Espressif Systems");
|
|
||||||
SSDP.setManufacturerURL("http://espressif.com");
|
|
||||||
SSDP.setDeviceType("upnp:rootdevice");
|
|
||||||
if (WiFi.getMode()!=WIFI_AP )SSDP.begin();
|
|
||||||
#endif
|
|
||||||
#ifdef NETBIOS_FEATURE
|
|
||||||
//useless in AP mode and service consuming
|
|
||||||
if (WiFi.getMode()!=WIFI_AP )NBNS.begin(shost.c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WIFI_CONFIG::Disable_servers()
|
|
||||||
{
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
data_server->stop();
|
|
||||||
#endif
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
if (WiFi.getMode()!=WIFI_STA ) {
|
|
||||||
dnsServer.stop();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef NETBIOS_FEATURE
|
|
||||||
//useless in AP mode and service consuming
|
|
||||||
if (WiFi.getMode()!=WIFI_AP )NBNS.end();
|
|
||||||
#endif
|
|
||||||
web_interface->web_server.stop();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
WIFI_CONFIG wifi_config;
|
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
ESP8266WebServer.h - Dead simple web-server.
|
basic esp3d sample
|
||||||
Supports only one simultaneous client, knows how to handle GET and POST.
|
|
||||||
|
|
||||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
@@ -17,13 +16,21 @@
|
|||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library; if not, write to the Free Software
|
License along with this library; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
|
|
||||||
*/
|
*/
|
||||||
|
//library include
|
||||||
|
#include "esp3d.h"
|
||||||
|
|
||||||
|
//global variable
|
||||||
|
Esp3D myesp3d;
|
||||||
|
|
||||||
#ifndef ESP8266WEBSERVER_H
|
//Setup
|
||||||
#define ESP8266WEBSERVER_H
|
void setup()
|
||||||
|
{
|
||||||
|
myesp3d.begin();
|
||||||
|
}
|
||||||
|
|
||||||
#include <WebServer.h>
|
//main loop
|
||||||
|
void loop()
|
||||||
#endif //ESP8266WEBSERVER_H
|
{
|
||||||
|
myesp3d.process();
|
||||||
|
}
|
||||||
37
libraries/AsyncTCP/.travis.yml
Normal file
37
libraries/AsyncTCP/.travis.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
sudo: false
|
||||||
|
language: bash
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
|
||||||
|
script:
|
||||||
|
- /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
|
||||||
|
- wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz
|
||||||
|
- tar xf arduino-1.6.5-linux64.tar.xz
|
||||||
|
- mv arduino-1.6.5 $HOME/arduino_ide
|
||||||
|
- export PATH="$HOME/arduino_ide:$PATH"
|
||||||
|
- which arduino
|
||||||
|
- mkdir -p $HOME/Arduino/libraries
|
||||||
|
- cp -r $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/ESPAsyncTCP
|
||||||
|
- cd $HOME/arduino_ide/hardware
|
||||||
|
- mkdir esp8266com
|
||||||
|
- cd esp8266com
|
||||||
|
- git clone https://github.com/esp8266/Arduino.git esp8266
|
||||||
|
- cd esp8266/tools
|
||||||
|
- python get.py
|
||||||
|
- source $TRAVIS_BUILD_DIR/travis/common.sh
|
||||||
|
- arduino --board esp8266com:esp8266:generic --save-prefs
|
||||||
|
- arduino --get-pref sketchbook.path
|
||||||
|
- build_sketches arduino $HOME/Arduino/libraries/ESPAsyncTCP esp8266
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email:
|
||||||
|
on_success: change
|
||||||
|
on_failure: change
|
||||||
|
webhooks:
|
||||||
|
urls:
|
||||||
|
- https://webhooks.gitter.im/e/60e65d0c78ea0a920347
|
||||||
|
on_success: change # options: [always|never|change] default: always
|
||||||
|
on_failure: always # options: [always|never|change] default: always
|
||||||
|
on_start: false # default: false
|
||||||
165
libraries/AsyncTCP/LICENSE
Normal file
165
libraries/AsyncTCP/LICENSE
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
GNU LESSER 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.
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
11
libraries/AsyncTCP/README.md
Normal file
11
libraries/AsyncTCP/README.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# AsyncTCP
|
||||||
|
Async TCP Library for ESP32 Arduino
|
||||||
|
|
||||||
|
[](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
|
This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs.
|
||||||
|
|
||||||
|
This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer)
|
||||||
|
|
||||||
|
## AsyncClient and AsyncServer
|
||||||
|
The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use.
|
||||||
3
libraries/AsyncTCP/component.mk
Normal file
3
libraries/AsyncTCP/component.mk
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
COMPONENT_ADD_INCLUDEDIRS := src
|
||||||
|
COMPONENT_SRCDIRS := src
|
||||||
|
CXXFLAGS += -fno-rtti
|
||||||
19
libraries/AsyncTCP/library.json
Normal file
19
libraries/AsyncTCP/library.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name":"AsyncTCP",
|
||||||
|
"description":"Asynchronous TCP Library for ESP32",
|
||||||
|
"keywords":"async,tcp",
|
||||||
|
"authors":
|
||||||
|
{
|
||||||
|
"name": "Hristo Gochkov",
|
||||||
|
"maintainer": true
|
||||||
|
},
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/me-no-dev/AsyncTCP.git"
|
||||||
|
},
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "LGPL-3.0",
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": ["espressif32", "espressif32_stage"]
|
||||||
|
}
|
||||||
9
libraries/AsyncTCP/library.properties
Normal file
9
libraries/AsyncTCP/library.properties
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
name=AsyncTCP
|
||||||
|
version=1.0.0
|
||||||
|
author=Me-No-Dev
|
||||||
|
maintainer=Me-No-Dev
|
||||||
|
sentence=Async TCP Library for ESP32
|
||||||
|
paragraph=Async TCP Library for ESP32
|
||||||
|
category=Other
|
||||||
|
url=https://github.com/me-no-dev/AsyncTCP
|
||||||
|
architectures=*
|
||||||
1055
libraries/AsyncTCP/src/AsyncTCP.cpp
Normal file
1055
libraries/AsyncTCP/src/AsyncTCP.cpp
Normal file
File diff suppressed because it is too large
Load Diff
191
libraries/AsyncTCP/src/AsyncTCP.h
Normal file
191
libraries/AsyncTCP/src/AsyncTCP.h
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous TCP library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ASYNCTCP_H_
|
||||||
|
#define ASYNCTCP_H_
|
||||||
|
|
||||||
|
#include "IPAddress.h"
|
||||||
|
#include <functional>
|
||||||
|
extern "C" {
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
class AsyncClient;
|
||||||
|
|
||||||
|
#define ASYNC_MAX_ACK_TIME 5000
|
||||||
|
#define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given)
|
||||||
|
#define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react.
|
||||||
|
|
||||||
|
typedef std::function<void(void*, AsyncClient*)> AcConnectHandler;
|
||||||
|
typedef std::function<void(void*, AsyncClient*, size_t len, uint32_t time)> AcAckHandler;
|
||||||
|
typedef std::function<void(void*, AsyncClient*, int8_t error)> AcErrorHandler;
|
||||||
|
typedef std::function<void(void*, AsyncClient*, void *data, size_t len)> AcDataHandler;
|
||||||
|
typedef std::function<void(void*, AsyncClient*, uint32_t time)> AcTimeoutHandler;
|
||||||
|
|
||||||
|
struct tcp_pcb;
|
||||||
|
struct pbuf;
|
||||||
|
struct _ip_addr;
|
||||||
|
|
||||||
|
class AsyncClient {
|
||||||
|
protected:
|
||||||
|
tcp_pcb* _pcb;
|
||||||
|
|
||||||
|
AcConnectHandler _connect_cb;
|
||||||
|
void* _connect_cb_arg;
|
||||||
|
AcConnectHandler _discard_cb;
|
||||||
|
void* _discard_cb_arg;
|
||||||
|
AcAckHandler _sent_cb;
|
||||||
|
void* _sent_cb_arg;
|
||||||
|
AcErrorHandler _error_cb;
|
||||||
|
void* _error_cb_arg;
|
||||||
|
AcDataHandler _recv_cb;
|
||||||
|
void* _recv_cb_arg;
|
||||||
|
AcTimeoutHandler _timeout_cb;
|
||||||
|
void* _timeout_cb_arg;
|
||||||
|
AcConnectHandler _poll_cb;
|
||||||
|
void* _poll_cb_arg;
|
||||||
|
|
||||||
|
bool _pcb_busy;
|
||||||
|
uint32_t _pcb_sent_at;
|
||||||
|
bool _close_pcb;
|
||||||
|
bool _ack_pcb;
|
||||||
|
uint32_t _rx_ack_len;
|
||||||
|
uint32_t _rx_last_packet;
|
||||||
|
uint32_t _rx_since_timeout;
|
||||||
|
uint32_t _ack_timeout;
|
||||||
|
uint16_t _connect_port;
|
||||||
|
|
||||||
|
int8_t _close();
|
||||||
|
int8_t _connected(void* pcb, int8_t err);
|
||||||
|
void _error(int8_t err);
|
||||||
|
int8_t _poll(tcp_pcb* pcb);
|
||||||
|
int8_t _sent(tcp_pcb* pcb, uint16_t len);
|
||||||
|
void _dns_found(struct _ip_addr *ipaddr);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsyncClient* prev;
|
||||||
|
AsyncClient* next;
|
||||||
|
|
||||||
|
AsyncClient(tcp_pcb* pcb = 0);
|
||||||
|
~AsyncClient();
|
||||||
|
|
||||||
|
AsyncClient & operator=(const AsyncClient &other);
|
||||||
|
AsyncClient & operator+=(const AsyncClient &other);
|
||||||
|
|
||||||
|
bool operator==(const AsyncClient &other);
|
||||||
|
|
||||||
|
bool operator!=(const AsyncClient &other) {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
bool connect(IPAddress ip, uint16_t port);
|
||||||
|
bool connect(const char* host, uint16_t port);
|
||||||
|
void close(bool now = false);
|
||||||
|
void stop();
|
||||||
|
int8_t abort();
|
||||||
|
bool free();
|
||||||
|
|
||||||
|
bool canSend();//ack is not pending
|
||||||
|
size_t space();
|
||||||
|
size_t add(const char* data, size_t size, uint8_t apiflags=0);//add for sending
|
||||||
|
bool send();//send all data added with the method above
|
||||||
|
size_t ack(size_t len); //ack data that you have not acked using the method below
|
||||||
|
void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData
|
||||||
|
|
||||||
|
size_t write(const char* data);
|
||||||
|
size_t write(const char* data, size_t size, uint8_t apiflags=0); //only when canSend() == true
|
||||||
|
|
||||||
|
uint8_t state();
|
||||||
|
bool connecting();
|
||||||
|
bool connected();
|
||||||
|
bool disconnecting();
|
||||||
|
bool disconnected();
|
||||||
|
bool freeable();//disconnected or disconnecting
|
||||||
|
|
||||||
|
uint16_t getMss();
|
||||||
|
uint32_t getRxTimeout();
|
||||||
|
void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds
|
||||||
|
uint32_t getAckTimeout();
|
||||||
|
void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds
|
||||||
|
void setNoDelay(bool nodelay);
|
||||||
|
bool getNoDelay();
|
||||||
|
uint32_t getRemoteAddress();
|
||||||
|
uint16_t getRemotePort();
|
||||||
|
uint32_t getLocalAddress();
|
||||||
|
uint16_t getLocalPort();
|
||||||
|
|
||||||
|
IPAddress remoteIP();
|
||||||
|
uint16_t remotePort();
|
||||||
|
IPAddress localIP();
|
||||||
|
uint16_t localPort();
|
||||||
|
|
||||||
|
void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect
|
||||||
|
void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected
|
||||||
|
void onAck(AcAckHandler cb, void* arg = 0); //ack received
|
||||||
|
void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error
|
||||||
|
void onData(AcDataHandler cb, void* arg = 0); //data received
|
||||||
|
void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout
|
||||||
|
void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected
|
||||||
|
|
||||||
|
const char * errorToString(int8_t error);
|
||||||
|
const char * stateToString();
|
||||||
|
|
||||||
|
int8_t _recv(tcp_pcb* pcb, pbuf* pb, int8_t err);
|
||||||
|
|
||||||
|
static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb);
|
||||||
|
static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err);
|
||||||
|
static void _s_error(void *arg, int8_t err);
|
||||||
|
static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len);
|
||||||
|
static int8_t _s_connected(void* arg, void* tpcb, int8_t err);
|
||||||
|
static void _s_dns_found(const char *name, struct _ip_addr *ipaddr, void *arg);
|
||||||
|
|
||||||
|
bool _in_lwip_thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncServer {
|
||||||
|
protected:
|
||||||
|
uint16_t _port;
|
||||||
|
IPAddress _addr;
|
||||||
|
bool _noDelay;
|
||||||
|
bool _in_lwip_thread;
|
||||||
|
tcp_pcb* _pcb;
|
||||||
|
AcConnectHandler _connect_cb;
|
||||||
|
void* _connect_cb_arg;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
AsyncServer(IPAddress addr, uint16_t port);
|
||||||
|
AsyncServer(uint16_t port);
|
||||||
|
~AsyncServer();
|
||||||
|
void onClient(AcConnectHandler cb, void* arg);
|
||||||
|
void begin();
|
||||||
|
void end();
|
||||||
|
void setNoDelay(bool nodelay);
|
||||||
|
bool getNoDelay();
|
||||||
|
uint8_t status();
|
||||||
|
|
||||||
|
static int8_t _s_accept(void *arg, tcp_pcb* newpcb, int8_t err);
|
||||||
|
protected:
|
||||||
|
int8_t _accept(tcp_pcb* newpcb, int8_t err);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ASYNCTCP_H_ */
|
||||||
23
libraries/AsyncTCP/travis/common.sh
Normal file
23
libraries/AsyncTCP/travis/common.sh
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function build_sketches()
|
||||||
|
{
|
||||||
|
local arduino=$1
|
||||||
|
local srcpath=$2
|
||||||
|
local platform=$3
|
||||||
|
local sketches=$(find $srcpath -name *.ino)
|
||||||
|
for sketch in $sketches; do
|
||||||
|
local sketchdir=$(dirname $sketch)
|
||||||
|
if [[ -f "$sketchdir/.$platform.skip" ]]; then
|
||||||
|
echo -e "\n\n ------------ Skipping $sketch ------------ \n\n";
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo -e "\n\n ------------ Building $sketch ------------ \n\n";
|
||||||
|
$arduino --verify $sketch;
|
||||||
|
local result=$?
|
||||||
|
if [ $result -ne 0 ]; then
|
||||||
|
echo "Build failed ($1)"
|
||||||
|
return $result
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
424
libraries/DHT_sensor_library_for_ESPx/DHTesp.cpp
Normal file
424
libraries/DHT_sensor_library_for_ESPx/DHTesp.cpp
Normal file
@@ -0,0 +1,424 @@
|
|||||||
|
/******************************************************************
|
||||||
|
DHT Temperature & Humidity Sensor library for Arduino & ESP32.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Support for DHT11 and DHT22/AM2302/RHT03
|
||||||
|
- Auto detect sensor model
|
||||||
|
- Very low memory footprint
|
||||||
|
- Very small code
|
||||||
|
|
||||||
|
https://github.com/beegee-tokyo/arduino-DHTesp
|
||||||
|
|
||||||
|
Written by Mark Ruys, mark@paracas.nl.
|
||||||
|
Updated to work with ESP32 by Bernd Giesecke, bernd@giesecke.tk
|
||||||
|
|
||||||
|
GNU General Public License, check LICENSE for more information.
|
||||||
|
All text above must be included in any redistribution.
|
||||||
|
|
||||||
|
Datasheets:
|
||||||
|
- http://www.micro4you.com/files/sensor/DHT11.pdf
|
||||||
|
- http://www.adafruit.com/datasheets/DHT22.pdf
|
||||||
|
- http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Weather/RHT03.pdf
|
||||||
|
- http://meteobox.tk/files/AM2302.pdf
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
2013-06-10: Initial version
|
||||||
|
2013-06-12: Refactored code
|
||||||
|
2013-07-01: Add a resetTimer method
|
||||||
|
2017-12-12: Added task switch disable
|
||||||
|
Added computeHeatIndex function from Adafruit DNT library
|
||||||
|
2017-12-14: Added computeDewPoint function from idDHTLib Library
|
||||||
|
Added getComfortRatio function from libDHT Library
|
||||||
|
2017-12-15: Added computePerception function
|
||||||
|
2018-01-02: Added example for multiple sensors usage.
|
||||||
|
2018-01-03: Added function getTempAndHumidity which returns temperature and humidity in one call.
|
||||||
|
2018-01-03: Added retry in case the reading from the sensor fails with a timeout.
|
||||||
|
2018-01-08: Added ESP8266 (and probably AVR) compatibility.
|
||||||
|
2018-03-11: Updated DHT example
|
||||||
|
******************************************************************/
|
||||||
|
|
||||||
|
#include "DHTesp.h"
|
||||||
|
|
||||||
|
void DHTesp::setup(uint8_t pin, DHT_MODEL_t model)
|
||||||
|
{
|
||||||
|
DHTesp::pin = pin;
|
||||||
|
DHTesp::model = model;
|
||||||
|
DHTesp::resetTimer(); // Make sure we do read the sensor in the next readSensor()
|
||||||
|
|
||||||
|
if ( model == AUTO_DETECT) {
|
||||||
|
DHTesp::model = DHT22;
|
||||||
|
readSensor();
|
||||||
|
if ( error == ERROR_TIMEOUT ) {
|
||||||
|
DHTesp::model = DHT11;
|
||||||
|
// Warning: in case we auto detect a DHT11, you should wait at least 1000 msec
|
||||||
|
// before your first read request. Otherwise you will get a time out error.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set default comfort profile.
|
||||||
|
|
||||||
|
//In computing these constants the following reference was used
|
||||||
|
//http://epb.apogee.net/res/refcomf.asp
|
||||||
|
//It was simplified as 4 straight lines and added very little skew on
|
||||||
|
//the vertical lines (+0.1 on x for C,D)
|
||||||
|
//The for points used are(from top left, clock wise)
|
||||||
|
//A(30%, 30*C) B(70%, 26.2*C) C(70.1%, 20.55*C) D(30.1%, 22.22*C)
|
||||||
|
//On the X axis we have the rel humidity in % and on the Y axis the temperature in *C
|
||||||
|
|
||||||
|
//Too hot line AB
|
||||||
|
m_comfort.m_tooHot_m = -0.095;
|
||||||
|
m_comfort.m_tooHot_b = 32.85;
|
||||||
|
//Too humid line BC
|
||||||
|
m_comfort.m_tooHumid_m = -56.5;
|
||||||
|
m_comfort.m_tooHumid_b = 3981.2;
|
||||||
|
//Too cold line DC
|
||||||
|
m_comfort.m_tooCold_m = -0.04175;
|
||||||
|
m_comfort.m_tooHCold_b = 23.476675;
|
||||||
|
//Too dry line AD
|
||||||
|
m_comfort.m_tooDry_m = -77.8;
|
||||||
|
m_comfort.m_tooDry_b = 2364;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DHTesp::resetTimer()
|
||||||
|
{
|
||||||
|
DHTesp::lastReadTime = millis() - 3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
float DHTesp::getHumidity()
|
||||||
|
{
|
||||||
|
readSensor();
|
||||||
|
if ( error == ERROR_TIMEOUT ) { // Try a second time to read
|
||||||
|
readSensor();
|
||||||
|
}
|
||||||
|
return humidity;
|
||||||
|
}
|
||||||
|
|
||||||
|
float DHTesp::getTemperature()
|
||||||
|
{
|
||||||
|
readSensor();
|
||||||
|
if ( error == ERROR_TIMEOUT ) { // Try a second time to read
|
||||||
|
readSensor();
|
||||||
|
}
|
||||||
|
return temperature;
|
||||||
|
}
|
||||||
|
|
||||||
|
TempAndHumidity DHTesp::getTempAndHumidity()
|
||||||
|
{
|
||||||
|
readSensor();
|
||||||
|
if ( error == ERROR_TIMEOUT ) { // Try a second time to read
|
||||||
|
readSensor();
|
||||||
|
}
|
||||||
|
values.temperature = temperature;
|
||||||
|
values.humidity = humidity;
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef OPTIMIZE_SRAM_SIZE
|
||||||
|
|
||||||
|
const char* DHTesp::getStatusString()
|
||||||
|
{
|
||||||
|
switch ( error ) {
|
||||||
|
case DHTesp::ERROR_TIMEOUT:
|
||||||
|
return "TIMEOUT";
|
||||||
|
|
||||||
|
case DHTesp::ERROR_CHECKSUM:
|
||||||
|
return "CHECKSUM";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// At the expense of 26 bytes of extra PROGMEM, we save 11 bytes of
|
||||||
|
// SRAM by using the following method:
|
||||||
|
|
||||||
|
prog_char P_OK[] PROGMEM = "OK";
|
||||||
|
prog_char P_TIMEOUT[] PROGMEM = "TIMEOUT";
|
||||||
|
prog_char P_CHECKSUM[] PROGMEM = "CHECKSUM";
|
||||||
|
|
||||||
|
const char *DHTesp::getStatusString() {
|
||||||
|
prog_char *c;
|
||||||
|
switch ( error ) {
|
||||||
|
case DHTesp::ERROR_CHECKSUM:
|
||||||
|
c = P_CHECKSUM; break;
|
||||||
|
|
||||||
|
case DHTesp::ERROR_TIMEOUT:
|
||||||
|
c = P_TIMEOUT; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
c = P_OK; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char buffer[9];
|
||||||
|
strcpy_P(buffer, c);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void DHTesp::readSensor()
|
||||||
|
{
|
||||||
|
// Make sure we don't poll the sensor too often
|
||||||
|
// - Max sample rate DHT11 is 1 Hz (duty cicle 1000 ms)
|
||||||
|
// - Max sample rate DHT22 is 0.5 Hz (duty cicle 2000 ms)
|
||||||
|
unsigned long startTime = millis();
|
||||||
|
if ( (unsigned long)(startTime - lastReadTime) < (model == DHT11 ? 999L : 1999L) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastReadTime = startTime;
|
||||||
|
|
||||||
|
temperature = NAN;
|
||||||
|
humidity = NAN;
|
||||||
|
|
||||||
|
uint16_t rawHumidity = 0;
|
||||||
|
uint16_t rawTemperature = 0;
|
||||||
|
uint16_t data = 0;
|
||||||
|
|
||||||
|
// Request sample
|
||||||
|
digitalWrite(pin, LOW); // Send start signal
|
||||||
|
pinMode(pin, OUTPUT);
|
||||||
|
if ( model == DHT11 ) {
|
||||||
|
delay(18);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// This will fail for a DHT11 - that's how we can detect such a device
|
||||||
|
delayMicroseconds(800);
|
||||||
|
}
|
||||||
|
|
||||||
|
pinMode(pin, INPUT);
|
||||||
|
digitalWrite(pin, HIGH); // Switch bus to receive data
|
||||||
|
|
||||||
|
// We're going to read 83 edges:
|
||||||
|
// - First a FALLING, RISING, and FALLING edge for the start bit
|
||||||
|
// - Then 40 bits: RISING and then a FALLING edge per bit
|
||||||
|
// To keep our code simple, we accept any HIGH or LOW reading if it's max 85 usecs long
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
// ESP32 is a multi core / multi processing chip
|
||||||
|
// It is necessary to disable task switches during the readings
|
||||||
|
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
portENTER_CRITICAL(&mux);
|
||||||
|
#else
|
||||||
|
cli();
|
||||||
|
#endif
|
||||||
|
for ( int8_t i = -3 ; i < 2 * 40; i++ ) {
|
||||||
|
byte age;
|
||||||
|
startTime = micros();
|
||||||
|
|
||||||
|
do {
|
||||||
|
age = (unsigned long)(micros() - startTime);
|
||||||
|
if ( age > 90 ) {
|
||||||
|
error = ERROR_TIMEOUT;
|
||||||
|
#ifdef ESP32
|
||||||
|
portEXIT_CRITICAL(&mux);
|
||||||
|
#else
|
||||||
|
sei();
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ( digitalRead(pin) == (i & 1) ? HIGH : LOW );
|
||||||
|
|
||||||
|
if ( i >= 0 && (i & 1) ) {
|
||||||
|
// Now we are being fed our 40 bits
|
||||||
|
data <<= 1;
|
||||||
|
|
||||||
|
// A zero max 30 usecs, a one at least 68 usecs.
|
||||||
|
if ( age > 30 ) {
|
||||||
|
data |= 1; // we got a one
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( i ) {
|
||||||
|
case 31:
|
||||||
|
rawHumidity = data;
|
||||||
|
break;
|
||||||
|
case 63:
|
||||||
|
rawTemperature = data;
|
||||||
|
data = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
portEXIT_CRITICAL(&mux);
|
||||||
|
#else
|
||||||
|
sei();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Verify checksum
|
||||||
|
|
||||||
|
if ( (byte)(((byte)rawHumidity) + (rawHumidity >> 8) + ((byte)rawTemperature) + (rawTemperature >> 8)) != data ) {
|
||||||
|
error = ERROR_CHECKSUM;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store readings
|
||||||
|
|
||||||
|
if ( model == DHT11 ) {
|
||||||
|
humidity = rawHumidity >> 8;
|
||||||
|
temperature = rawTemperature >> 8;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
humidity = rawHumidity * 0.1;
|
||||||
|
|
||||||
|
if ( rawTemperature & 0x8000 ) {
|
||||||
|
rawTemperature = -(int16_t)(rawTemperature & 0x7FFF);
|
||||||
|
}
|
||||||
|
temperature = ((int16_t)rawTemperature) * 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//boolean isFahrenheit: True == Fahrenheit; False == Celcius
|
||||||
|
float DHTesp::computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit) {
|
||||||
|
// Using both Rothfusz and Steadman's equations
|
||||||
|
// http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml
|
||||||
|
float hi;
|
||||||
|
|
||||||
|
if (!isFahrenheit) {
|
||||||
|
temperature = toFahrenheit(temperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
hi = 0.5 * (temperature + 61.0 + ((temperature - 68.0) * 1.2) + (percentHumidity * 0.094));
|
||||||
|
|
||||||
|
if (hi > 79) {
|
||||||
|
hi = -42.379 +
|
||||||
|
2.04901523 * temperature +
|
||||||
|
10.14333127 * percentHumidity +
|
||||||
|
-0.22475541 * temperature*percentHumidity +
|
||||||
|
-0.00683783 * pow(temperature, 2) +
|
||||||
|
-0.05481717 * pow(percentHumidity, 2) +
|
||||||
|
0.00122874 * pow(temperature, 2) * percentHumidity +
|
||||||
|
0.00085282 * temperature*pow(percentHumidity, 2) +
|
||||||
|
-0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2);
|
||||||
|
|
||||||
|
if((percentHumidity < 13) && (temperature >= 80.0) && (temperature <= 112.0))
|
||||||
|
hi -= ((13.0 - percentHumidity) * 0.25) * sqrt((17.0 - abs(temperature - 95.0)) * 0.05882);
|
||||||
|
|
||||||
|
else if((percentHumidity > 85.0) && (temperature >= 80.0) && (temperature <= 87.0))
|
||||||
|
hi += ((percentHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isFahrenheit ? hi : toCelsius(hi);
|
||||||
|
}
|
||||||
|
|
||||||
|
//boolean isFahrenheit: True == Fahrenheit; False == Celcius
|
||||||
|
float DHTesp::computeDewPoint(float temperature, float percentHumidity, bool isFahrenheit) {
|
||||||
|
// reference: http://wahiduddin.net/calc/density_algorithms.htm
|
||||||
|
if (isFahrenheit) {
|
||||||
|
temperature = toCelsius(temperature);
|
||||||
|
}
|
||||||
|
double A0 = 373.15 / (273.15 + (double) temperature);
|
||||||
|
double SUM = -7.90298 * (A0 - 1);
|
||||||
|
SUM += 5.02808 * log10(A0);
|
||||||
|
SUM += -1.3816e-7 * (pow(10, (11.344 * (1 - 1 / A0))) - 1) ;
|
||||||
|
SUM += 8.1328e-3 * (pow(10, (-3.49149 * (A0 - 1))) - 1) ;
|
||||||
|
SUM += log10(1013.246);
|
||||||
|
double VP = pow(10, SUM - 3) * (double) percentHumidity;
|
||||||
|
double Td = log(VP / 0.61078); // temp var
|
||||||
|
Td = (241.88 * Td) / (17.558 - Td);
|
||||||
|
return isFahrenheit ? toFahrenheit(Td) : Td;
|
||||||
|
}
|
||||||
|
|
||||||
|
//boolean isFahrenheit: True == Fahrenheit; False == Celcius
|
||||||
|
byte DHTesp::computePerception(float temperature, float percentHumidity, bool isFahrenheit) {
|
||||||
|
// Computing human perception from dew point
|
||||||
|
// reference: https://en.wikipedia.org/wiki/Dew_point ==> Relationship to human comfort
|
||||||
|
// reference: Horstmeyer, Steve (2006-08-15). "Relative Humidity....Relative to What? The Dew Point Temperature...a better approach". Steve Horstmeyer, Meteorologist, WKRC TV, Cincinnati, Ohio, USA. Retrieved 2009-08-20.
|
||||||
|
// Using table
|
||||||
|
// Return value Dew point Human perception[6]
|
||||||
|
// 7 Over 26 °C Severely high, even deadly for asthma related illnesses
|
||||||
|
// 6 24–26 °C Extremely uncomfortable, oppressive
|
||||||
|
// 5 21–24 °C Very humid, quite uncomfortable
|
||||||
|
// 4 18–21 °C Somewhat uncomfortable for most people at upper edge
|
||||||
|
// 3 16–18 °C OK for most, but all perceive the humidity at upper edge
|
||||||
|
// 2 13–16 °C Comfortable
|
||||||
|
// 1 10–12 °C Very comfortable
|
||||||
|
// 0 Under 10 °C A bit dry for some
|
||||||
|
|
||||||
|
if (isFahrenheit) {
|
||||||
|
temperature = toCelsius(temperature);
|
||||||
|
}
|
||||||
|
float dewPoint = computeDewPoint(temperature, percentHumidity);
|
||||||
|
|
||||||
|
if (dewPoint < 10.0f) {
|
||||||
|
return Perception_Dry;
|
||||||
|
} else if (dewPoint < 13.0f) {
|
||||||
|
return Perception_VeryComfy;
|
||||||
|
} else if (dewPoint < 16.0f) {
|
||||||
|
return Perception_Comfy;
|
||||||
|
} else if (dewPoint < 18.0f) {
|
||||||
|
return Perception_Ok;
|
||||||
|
} else if (dewPoint < 21.0f) {
|
||||||
|
return Perception_UnComfy;
|
||||||
|
} else if (dewPoint < 24.0f) {
|
||||||
|
return Perception_QuiteUnComfy;
|
||||||
|
} else if (dewPoint < 26.0f) {
|
||||||
|
return Perception_VeryUnComfy;
|
||||||
|
}
|
||||||
|
// else dew >= 26.0
|
||||||
|
return Perception_SevereUncomfy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//boolean isFahrenheit: True == Fahrenheit; False == Celcius
|
||||||
|
float DHTesp::getComfortRatio(ComfortState& destComfortStatus, float temperature, float percentHumidity, bool isFahrenheit) {
|
||||||
|
float ratio = 100; //100%
|
||||||
|
float distance = 0;
|
||||||
|
float kTempFactor = 3; //take into account the slope of the lines
|
||||||
|
float kHumidFactor = 0.1; //take into account the slope of the lines
|
||||||
|
uint8_t tempComfort = 0;
|
||||||
|
|
||||||
|
if (isFahrenheit) {
|
||||||
|
temperature = toCelsius(temperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
destComfortStatus = Comfort_OK;
|
||||||
|
|
||||||
|
distance = m_comfort.distanceTooHot(temperature, percentHumidity);
|
||||||
|
if(distance > 0)
|
||||||
|
{
|
||||||
|
//update the comfort descriptor
|
||||||
|
tempComfort += (uint8_t)Comfort_TooHot;
|
||||||
|
//decrease the comfot ratio taking the distance into account
|
||||||
|
ratio -= distance * kTempFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
distance = m_comfort.distanceTooHumid(temperature, percentHumidity);
|
||||||
|
if(distance > 0)
|
||||||
|
{
|
||||||
|
//update the comfort descriptor
|
||||||
|
tempComfort += (uint8_t)Comfort_TooHumid;
|
||||||
|
//decrease the comfot ratio taking the distance into account
|
||||||
|
ratio -= distance * kHumidFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
distance = m_comfort.distanceTooCold(temperature, percentHumidity);
|
||||||
|
if(distance > 0)
|
||||||
|
{
|
||||||
|
//update the comfort descriptor
|
||||||
|
tempComfort += (uint8_t)Comfort_TooCold;
|
||||||
|
//decrease the comfot ratio taking the distance into account
|
||||||
|
ratio -= distance * kTempFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
distance = m_comfort.distanceTooDry(temperature, percentHumidity);
|
||||||
|
if(distance > 0)
|
||||||
|
{
|
||||||
|
//update the comfort descriptor
|
||||||
|
tempComfort += (uint8_t)Comfort_TooDry;
|
||||||
|
//decrease the comfot ratio taking the distance into account
|
||||||
|
ratio -= distance * kHumidFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
destComfortStatus = (ComfortState)tempComfort;
|
||||||
|
|
||||||
|
if(ratio < 0)
|
||||||
|
ratio = 0;
|
||||||
|
|
||||||
|
return ratio;
|
||||||
|
}
|
||||||
170
libraries/DHT_sensor_library_for_ESPx/DHTesp.h
Normal file
170
libraries/DHT_sensor_library_for_ESPx/DHTesp.h
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/******************************************************************
|
||||||
|
DHT Temperature & Humidity Sensor library for Arduino & ESP32.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Support for DHT11 and DHT22/AM2302/RHT03
|
||||||
|
- Auto detect sensor model
|
||||||
|
- Very low memory footprint
|
||||||
|
- Very small code
|
||||||
|
|
||||||
|
https://github.com/beegee-tokyo/arduino-DHTesp
|
||||||
|
|
||||||
|
Written by Mark Ruys, mark@paracas.nl.
|
||||||
|
Updated to work with ESP32 by Bernd Giesecke, bernd@giesecke.tk
|
||||||
|
|
||||||
|
GNU General Public License, check LICENSE for more information.
|
||||||
|
All text above must be included in any redistribution.
|
||||||
|
|
||||||
|
Datasheets:
|
||||||
|
- http://www.micro4you.com/files/sensor/DHT11.pdf
|
||||||
|
- http://www.adafruit.com/datasheets/DHT22.pdf
|
||||||
|
- http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Weather/RHT03.pdf
|
||||||
|
- http://meteobox.tk/files/AM2302.pdf
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
2013-06-10: Initial version
|
||||||
|
2013-06-12: Refactored code
|
||||||
|
2013-07-01: Add a resetTimer method
|
||||||
|
2017-12-12: Added task switch disable
|
||||||
|
Added computeHeatIndex function from Adafruit DNT library
|
||||||
|
2017-12-14: Added computeDewPoint function from idDHTLib Library
|
||||||
|
Added getComfortRatio function from libDHT Library
|
||||||
|
2017-12-15: Added computePerception function
|
||||||
|
2018-01-02: Added example for multiple sensors usage.
|
||||||
|
2018-01-03: Added function getTempAndHumidity which returns temperature and humidity in one call.
|
||||||
|
2018-01-03: Added retry in case the reading from the sensor fails with a timeout.
|
||||||
|
2018-01-08: Added ESP8266 (and probably AVR) compatibility.
|
||||||
|
******************************************************************/
|
||||||
|
|
||||||
|
#ifndef dhtesp_h
|
||||||
|
#define dhtesp_h
|
||||||
|
|
||||||
|
#if ARDUINO < 100
|
||||||
|
#include <WProgram.h>
|
||||||
|
#else
|
||||||
|
#include <Arduino.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Reference: http://epb.apogee.net/res/refcomf.asp (References invalid)
|
||||||
|
enum ComfortState {
|
||||||
|
Comfort_OK = 0,
|
||||||
|
Comfort_TooHot = 1,
|
||||||
|
Comfort_TooCold = 2,
|
||||||
|
Comfort_TooDry = 4,
|
||||||
|
Comfort_TooHumid = 8,
|
||||||
|
Comfort_HotAndHumid = 9,
|
||||||
|
Comfort_HotAndDry = 5,
|
||||||
|
Comfort_ColdAndHumid = 10,
|
||||||
|
Comfort_ColdAndDry = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
// References https://en.wikipedia.org/wiki/Dew_point ==> Relationship to human comfort
|
||||||
|
enum PerceptionState {
|
||||||
|
Perception_Dry = 0,
|
||||||
|
Perception_VeryComfy = 1,
|
||||||
|
Perception_Comfy = 2,
|
||||||
|
Perception_Ok = 3,
|
||||||
|
Perception_UnComfy = 4,
|
||||||
|
Perception_QuiteUnComfy = 5,
|
||||||
|
Perception_VeryUnComfy = 6,
|
||||||
|
Perception_SevereUncomfy = 7
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TempAndHumidity {
|
||||||
|
float temperature;
|
||||||
|
float humidity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ComfortProfile
|
||||||
|
{
|
||||||
|
//Represent the 4 line equations:
|
||||||
|
//dry, humid, hot, cold, using the y = mx + b formula
|
||||||
|
float m_tooHot_m, m_tooHot_b;
|
||||||
|
float m_tooCold_m, m_tooHCold_b;
|
||||||
|
float m_tooDry_m, m_tooDry_b;
|
||||||
|
float m_tooHumid_m, m_tooHumid_b;
|
||||||
|
|
||||||
|
inline bool isTooHot(float temp, float humidity) {return (temp > (humidity * m_tooHot_m + m_tooHot_b));}
|
||||||
|
inline bool isTooHumid(float temp, float humidity) {return (temp > (humidity * m_tooHumid_m + m_tooHumid_b));}
|
||||||
|
inline bool isTooCold(float temp, float humidity) {return (temp < (humidity * m_tooCold_m + m_tooHCold_b));}
|
||||||
|
inline bool isTooDry(float temp, float humidity) {return (temp < (humidity * m_tooDry_m + m_tooDry_b));}
|
||||||
|
|
||||||
|
inline float distanceTooHot(float temp, float humidity) {return temp - (humidity * m_tooHot_m + m_tooHot_b);}
|
||||||
|
inline float distanceTooHumid(float temp, float humidity) {return temp - (humidity * m_tooHumid_m + m_tooHumid_b);}
|
||||||
|
inline float distanceTooCold(float temp, float humidity) {return (humidity * m_tooCold_m + m_tooHCold_b) - temp;}
|
||||||
|
inline float distanceTooDry(float temp, float humidity) {return (humidity * m_tooDry_m + m_tooDry_b) - temp;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DHTesp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AUTO_DETECT,
|
||||||
|
DHT11,
|
||||||
|
DHT22,
|
||||||
|
AM2302, // Packaged DHT22
|
||||||
|
RHT03 // Equivalent to DHT22
|
||||||
|
}
|
||||||
|
DHT_MODEL_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ERROR_NONE = 0,
|
||||||
|
ERROR_TIMEOUT,
|
||||||
|
ERROR_CHECKSUM
|
||||||
|
}
|
||||||
|
DHT_ERROR_t;
|
||||||
|
|
||||||
|
TempAndHumidity values;
|
||||||
|
|
||||||
|
void setup(uint8_t pin, DHT_MODEL_t model=AUTO_DETECT);
|
||||||
|
void resetTimer();
|
||||||
|
|
||||||
|
float getTemperature();
|
||||||
|
float getHumidity();
|
||||||
|
TempAndHumidity getTempAndHumidity();
|
||||||
|
|
||||||
|
DHT_ERROR_t getStatus() { return error; };
|
||||||
|
const char* getStatusString();
|
||||||
|
|
||||||
|
DHT_MODEL_t getModel() { return model; }
|
||||||
|
|
||||||
|
int getMinimumSamplingPeriod() { return model == DHT11 ? 1000 : 2000; }
|
||||||
|
|
||||||
|
int8_t getNumberOfDecimalsTemperature() { return model == DHT11 ? 0 : 1; };
|
||||||
|
int8_t getLowerBoundTemperature() { return model == DHT11 ? 0 : -40; };
|
||||||
|
int8_t getUpperBoundTemperature() { return model == DHT11 ? 50 : 125; };
|
||||||
|
|
||||||
|
int8_t getNumberOfDecimalsHumidity() { return 0; };
|
||||||
|
int8_t getLowerBoundHumidity() { return model == DHT11 ? 20 : 0; };
|
||||||
|
int8_t getUpperBoundHumidity() { return model == DHT11 ? 90 : 100; };
|
||||||
|
|
||||||
|
static float toFahrenheit(float fromCelcius) { return 1.8 * fromCelcius + 32.0; };
|
||||||
|
static float toCelsius(float fromFahrenheit) { return (fromFahrenheit - 32.0) / 1.8; };
|
||||||
|
|
||||||
|
float computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit=false);
|
||||||
|
float computeDewPoint(float temperature, float percentHumidity, bool isFahrenheit=false);
|
||||||
|
float getComfortRatio(ComfortState& destComfStatus, float temperature, float percentHumidity, bool isFahrenheit=false);
|
||||||
|
ComfortProfile getComfortProfile() {return m_comfort;}
|
||||||
|
void setComfortProfile(ComfortProfile& c) {m_comfort = c;}
|
||||||
|
inline bool isTooHot(float temp, float humidity) {return m_comfort.isTooHot(temp, humidity);}
|
||||||
|
inline bool isTooHumid(float temp, float humidity) {return m_comfort.isTooHumid(temp, humidity);}
|
||||||
|
inline bool isTooCold(float temp, float humidity) {return m_comfort.isTooCold(temp, humidity);}
|
||||||
|
inline bool isTooDry(float temp, float humidity) {return m_comfort.isTooDry(temp, humidity);}
|
||||||
|
byte computePerception(float temperature, float percentHumidity, bool isFahrenheit=false);
|
||||||
|
protected:
|
||||||
|
void readSensor();
|
||||||
|
|
||||||
|
float temperature;
|
||||||
|
float humidity;
|
||||||
|
|
||||||
|
uint8_t pin;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DHT_MODEL_t model;
|
||||||
|
DHT_ERROR_t error;
|
||||||
|
unsigned long lastReadTime;
|
||||||
|
ComfortProfile m_comfort;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*dhtesp_h*/
|
||||||
@@ -631,8 +631,8 @@ 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
|
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.
|
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.>
|
{one line to give the program's name and a brief idea of what it does.}
|
||||||
Copyright (C) <year> <name of author>
|
Copyright (C) {year} {name of author}
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
|
|||||||
If the program does terminal interaction, make it output a short
|
If the program does terminal interaction, make it output a short
|
||||||
notice like this when it starts in an interactive mode:
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
<program> Copyright (C) <year> <name of author>
|
{project} Copyright (C) {year} {fullname}
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
This is free software, and you are welcome to redistribute it
|
This is free software, and you are welcome to redistribute it
|
||||||
under certain conditions; type `show c' for details.
|
under certain conditions; type `show c' for details.
|
||||||
149
libraries/DHT_sensor_library_for_ESPx/README.md
Normal file
149
libraries/DHT_sensor_library_for_ESPx/README.md
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
DHTesp
|
||||||
|
===
|
||||||
|
|
||||||
|
An Arduino library for reading the DHT family of temperature and humidity sensors.
|
||||||
|
Forked from [arduino-DHT](https://github.com/markruys/arduino-DHT)
|
||||||
|
Original written by Mark Ruys, <mark@paracas.nl>.
|
||||||
|
|
||||||
|
Why did I clone this library instead of forking the original repo and push the changes?
|
||||||
|
When I searched through Github for DHT libraries, I found a lot of them, some of them offers additional functions, some of them only basic temperature and humidity values. I wanted to combine all interesting functions into one library. In addition, none of the DHT libraries I found were written to work without errors on the ESP32. For ESP32 (a multi core/ multi processing SOC) task switching must be disabled while reading data from the sensor.
|
||||||
|
Another problem I found is that many of the available libraries use the same naming (dht.h, dht.cpp), which easily leads to conflicts if different libraries are used for different platforms.
|
||||||
|
|
||||||
|
The library is tested as well on ESP8266 and should work on AVR boards as well.
|
||||||
|
|
||||||
|
Changes to the original library:
|
||||||
|
--------
|
||||||
|
- 2017-12-12: Renamed DHT class to DHTesp and filenames from dht.* to DHTesp.* to avoid conflicts with other libraries - beegee-tokyo, <beegee@giesecke.tk>.
|
||||||
|
- 2017-12-12: Updated to work with ESP32 - beegee-tokyo, <beegee@giesecke.tk>.
|
||||||
|
- 2017-12-12: Added function computeHeatIndex. Reference: [Adafruit DHT library](https://github.com/adafruit/DHT-sensor-library).
|
||||||
|
- 2017-12-14: Added function computeDewPoint. Reference: [idDHTLib](https://github.com/niesteszeck/idDHTLib).
|
||||||
|
- 2017-12-14: Added function getComfortRatio. Reference: [libDHT](https://github.com/ADiea/libDHT). (References about Human Comfort invalid)
|
||||||
|
- 2017-12-15: Added function computePerception. Reference: [WikiPedia Dew point==> Relationship to human comfort](https://en.wikipedia.org/wiki/Dew_point) - beegee-tokyo, <beegee@giesecke.tk>.
|
||||||
|
- 2018-01-02: Added example for multiple sensors usage.
|
||||||
|
- 2018-01-03: Added function getTempAndHumidity which returns temperature and humidity in one call.
|
||||||
|
- 2018-01-03: Added retry in case the reading from the sensor fails with a timeout.
|
||||||
|
- 2018-01-08: Added ESP8266 (and probably AVR) compatibility.
|
||||||
|
- 2018-03-11: Updated DHT example
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
- Support for DHT11 and DHT22, AM2302, RHT03
|
||||||
|
- Auto detect sensor model
|
||||||
|
- Determine heat index
|
||||||
|
- Determine dewpoint
|
||||||
|
- Determine thermal comfort:
|
||||||
|
* Empiric comfort function based on comfort profiles(parametric lines)
|
||||||
|
* Multiple comfort profiles possible. Default based on http://epb.apogee.net/res/refcomf.asp (References invalid)
|
||||||
|
* Determine if it's too cold, hot, humid, dry, based on current comfort profile
|
||||||
|
* More info at [Determining Thermal Comfort Using a Humidity and Temperature Sensor](https://www.azosensors.com/article.aspx?ArticleID=487)
|
||||||
|
- Determine human perception based on humidity, temperature and dew point according to Horstmeyer, Steve (2006-08-15). [Relative Humidity....Relative to What? The Dew Point Temperature...a better approach](http://www.shorstmeyer.com/wxfaqs/humidity/humidity.html)
|
||||||
|
|
||||||
|
Functions
|
||||||
|
-----
|
||||||
|
_**`void setup(uint8_t pin, DHT_MODEL_t model=AUTO_DETECT);`**_
|
||||||
|
- Call to initialize the interface, define the GPIO pin to which the sensor is connected and define the sensor type. Valid sensor types are:
|
||||||
|
- AUTO_DETECT Try to detect which sensor is connected
|
||||||
|
- DHT11
|
||||||
|
- DHT22
|
||||||
|
- AM2302 Packaged DHT22
|
||||||
|
- RHT03 Equivalent to DHT22
|
||||||
|
|
||||||
|
_**`void resetTimer();`**_
|
||||||
|
- Reset last time the sensor was read
|
||||||
|
|
||||||
|
_**`float getTemperature();`**_
|
||||||
|
- Get the temperature in degree Centigrade from the sensor
|
||||||
|
Either one of _`getTemperature()`_ or _`getHumidity()`_ or _`getTempAndHumidity()`_ initiates reading a value from the sensor if the last reading was older than the minimal refresh time of the sensor.
|
||||||
|
See example _`DHT_ESP32.ino`_ or _`DHT_Test.ino`_
|
||||||
|
|
||||||
|
_**`float getHumidity();`**_
|
||||||
|
- Get the humidity from the sensor
|
||||||
|
Either one of _`getTemperature()`_ or _`getHumidity()`_ or _`getTempAndHumidity()`_ initiates reading a value from the sensor if the last reading was older than the minimal refresh time of the sensor.
|
||||||
|
See example _`DHT_ESP32.ino`_ or _`DHT_Test.ino`_
|
||||||
|
|
||||||
|
_**`TempAndHumidity getTempAndHumidity();`**_
|
||||||
|
- Get the temperature and humidity from the sensor
|
||||||
|
Either one of _`getTemperature()`_ or _`getHumidity()`_ or _`getTempAndHumidity()`_ initiates reading a value from the sensor if the last reading was older than the minimal refresh time of the sensor.
|
||||||
|
Return value is a struct of type _`TempAndHumidity`_ with temperature and humidity as float values.
|
||||||
|
See example _`DHT_Multi.ino`_
|
||||||
|
|
||||||
|
_**`DHT_ERROR_t getStatus();`**_
|
||||||
|
- Get last error if reading from the sensor failed. Possible values are:
|
||||||
|
- ERROR_NONE no error occured
|
||||||
|
- ERROR_TIMEOUT timeout reading from the sensor
|
||||||
|
- ERROR_CHECKSUM checksum of received values doesn't match
|
||||||
|
|
||||||
|
_**`const char* getStatusString();`**_
|
||||||
|
- Get last error as a char *
|
||||||
|
|
||||||
|
_**`DHT_MODEL_t getModel()`**_
|
||||||
|
- Get detected (or defined) sensor type
|
||||||
|
|
||||||
|
_**`int getMinimumSamplingPeriod();`**_
|
||||||
|
- Get minimmum possible sampling period. For DHT11 this is 1000ms, for other sensors it is 2000ms
|
||||||
|
|
||||||
|
_**`int8_t getNumberOfDecimalsTemperature();`**_
|
||||||
|
- Get number of decimals in the temperature value. For DHT11 this is 0, for other sensors it is 1
|
||||||
|
|
||||||
|
_**`int8_t getLowerBoundTemperature();`**_
|
||||||
|
- Get lower temperature range of the sensor. For DHT11 this is 0 degree Centigrade, for other sensors this is -40 degree Centrigrade
|
||||||
|
|
||||||
|
_**`int8_t getUpperBoundTemperature();`**_
|
||||||
|
- Get upper temperature range of the sensor. For DHT11 this is 50 degree Centigrade, for other sensors this is 125 degree Centrigrade
|
||||||
|
|
||||||
|
_**`int8_t getNumberOfDecimalsHumidity();`**_
|
||||||
|
- Get number of decimals in the humidity value. This is always 0.
|
||||||
|
|
||||||
|
_**`int8_t getLowerBoundHumidity();`**_
|
||||||
|
- Get lower humidity range of the sensor. For DHT11 this is 20 percent, for other sensors this is 0 percent
|
||||||
|
|
||||||
|
_**`int8_t getUpperBoundHumidity();`**_
|
||||||
|
- Get upper temperature range of the sensor. For DHT11 this is 90 percent, for other sensors this is 100 percent
|
||||||
|
|
||||||
|
_**`static float toFahrenheit(float fromCelcius);`**_
|
||||||
|
- Convert Centrigrade value to Fahrenheit value
|
||||||
|
|
||||||
|
_**`static float toCelsius(float fromFahrenheit) { return (fromFahrenheit - 32.0) / 1.8; };`**_
|
||||||
|
- Convert Fahrenheit value to Centigrade value
|
||||||
|
|
||||||
|
_**`float computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit=false);`**_
|
||||||
|
- Compute the heat index. Default temperature is in Centrigrade.
|
||||||
|
|
||||||
|
_**`float computeDewPoint(float temperature, float percentHumidity, bool isFahrenheit=false);`**_
|
||||||
|
- Compute the dew point. Default temperature is in Centrigrade.
|
||||||
|
|
||||||
|
_**`float getComfortRatio(ComfortState& destComfStatus, float temperature, float percentHumidity, bool isFahrenheit=false);`**_
|
||||||
|
- Compute the comfort ratio. Default temperature is in Centrigrade. Return values:
|
||||||
|
0 -> OK
|
||||||
|
1 -> Too Hot
|
||||||
|
2 -> Too cold
|
||||||
|
4 -> Too dry
|
||||||
|
8 -> Too humid
|
||||||
|
9 -> Hot and humid
|
||||||
|
5 -> Hot and dry
|
||||||
|
10 -> Cold and humid
|
||||||
|
6 -> Cold and dry
|
||||||
|
|
||||||
|
_**`byte computePerception(float temperature, float percentHumidity, bool isFahrenheit=false);`**_
|
||||||
|
- Compute the human perception. Default temperature is in Centrigrade. Return values:
|
||||||
|
0 -> Dry
|
||||||
|
1 -> Very comfortable
|
||||||
|
2 -> Comfortable
|
||||||
|
3 -> Ok
|
||||||
|
4 -> Uncomfortable
|
||||||
|
5 -> Quite uncomfortable
|
||||||
|
6 -> Very uncomfortable
|
||||||
|
7 -> Severe uncomfortable
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
See [examples](https://github.com/beegee-tokyo/DHTesp/blob/master/examples). For all the options, see [dhtesp.h](https://github.com/beegee-tokyo/DHTesp/blob/master/DHTesp.h).
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
In Arduino IDE open Sketch->Include Library->Manage Libraries then search for _**DHT ESP**_
|
||||||
|
In PlatformIO open PlatformIO Home, switch to libraries and search for _**DHT ESP32**_. Or install the library in the terminal with _**`platformio lib install 2029`**_
|
||||||
|
|
||||||
|
For manual installation [download](https://github.com/beegee-tokyo/DHTesp/archive/master.zip) the archive, unzip it and place the DHTesp folder into the library directory.
|
||||||
|
In Arduino IDE this is usually _**`<arduinosketchfolder>/libraries/`**_
|
||||||
|
In PlatformIO this is usually _**`<user/.platformio/lib>`**_
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
#include "DHTesp.h"
|
||||||
|
#include "ESP32Ticker.h"
|
||||||
|
|
||||||
|
/**************************************************************/
|
||||||
|
/* Example how to read DHT sensors from an ESP32 using multi- */
|
||||||
|
/* tasking. */
|
||||||
|
/* This example depends on the ESP32Ticker library to wake up */
|
||||||
|
/* the task every 20 seconds */
|
||||||
|
/* Please install Ticker-esp32 library first */
|
||||||
|
/* bertmelis/Ticker-esp32 */
|
||||||
|
/* https://github.com/bertmelis/Ticker-esp32 */
|
||||||
|
/**************************************************************/
|
||||||
|
|
||||||
|
DHTesp dht;
|
||||||
|
|
||||||
|
void tempTask(void *pvParameters);
|
||||||
|
bool getTemperature();
|
||||||
|
void triggerGetTemp();
|
||||||
|
|
||||||
|
/** Task handle for the light value read task */
|
||||||
|
TaskHandle_t tempTaskHandle = NULL;
|
||||||
|
/** Ticker for temperature reading */
|
||||||
|
Ticker tempTicker;
|
||||||
|
/** Comfort profile */
|
||||||
|
ComfortState cf;
|
||||||
|
/** Flag if task should run */
|
||||||
|
bool tasksEnabled = false;
|
||||||
|
/** Pin number for DHT11 data pin */
|
||||||
|
int dhtPin = 17;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initTemp
|
||||||
|
* Setup DHT library
|
||||||
|
* Setup task and timer for repeated measurement
|
||||||
|
* @return bool
|
||||||
|
* true if task and timer are started
|
||||||
|
* false if task or timer couldn't be started
|
||||||
|
*/
|
||||||
|
bool initTemp() {
|
||||||
|
byte resultValue = 0;
|
||||||
|
// Initialize temperature sensor
|
||||||
|
dht.setup(dhtPin, DHTesp::DHT11);
|
||||||
|
Serial.println("DHT initiated");
|
||||||
|
|
||||||
|
// Start task to get temperature
|
||||||
|
xTaskCreatePinnedToCore(
|
||||||
|
tempTask, /* Function to implement the task */
|
||||||
|
"tempTask ", /* Name of the task */
|
||||||
|
4000, /* Stack size in words */
|
||||||
|
NULL, /* Task input parameter */
|
||||||
|
5, /* Priority of the task */
|
||||||
|
&tempTaskHandle, /* Task handle. */
|
||||||
|
1); /* Core where the task should run */
|
||||||
|
|
||||||
|
if (tempTaskHandle == NULL) {
|
||||||
|
Serial.println("Failed to start task for temperature update");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// Start update of environment data every 20 seconds
|
||||||
|
tempTicker.attach(20, triggerGetTemp);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* triggerGetTemp
|
||||||
|
* Sets flag dhtUpdated to true for handling in loop()
|
||||||
|
* called by Ticker getTempTimer
|
||||||
|
*/
|
||||||
|
void triggerGetTemp() {
|
||||||
|
if (tempTaskHandle != NULL) {
|
||||||
|
xTaskResumeFromISR(tempTaskHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task to reads temperature from DHT11 sensor
|
||||||
|
* @param pvParameters
|
||||||
|
* pointer to task parameters
|
||||||
|
*/
|
||||||
|
void tempTask(void *pvParameters) {
|
||||||
|
Serial.println("tempTask loop started");
|
||||||
|
while (1) // tempTask loop
|
||||||
|
{
|
||||||
|
if (tasksEnabled) {
|
||||||
|
// Get temperature values
|
||||||
|
getTemperature();
|
||||||
|
}
|
||||||
|
// Got sleep again
|
||||||
|
vTaskSuspend(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getTemperature
|
||||||
|
* Reads temperature from DHT11 sensor
|
||||||
|
* @return bool
|
||||||
|
* true if temperature could be aquired
|
||||||
|
* false if aquisition failed
|
||||||
|
*/
|
||||||
|
bool getTemperature() {
|
||||||
|
// Reading temperature for humidity takes about 250 milliseconds!
|
||||||
|
// Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
|
||||||
|
TempAndHumidity newValues = dht.getTempAndHumidity();
|
||||||
|
// Check if any reads failed and exit early (to try again).
|
||||||
|
if (dht.getStatus() != 0) {
|
||||||
|
Serial.println("DHT11 error status: " + String(dht.getStatusString()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float heatIndex = dht.computeHeatIndex(newValues.temperature, newValues.humidity);
|
||||||
|
float dewPoint = dht.computeDewPoint(newValues.temperature, newValues.humidity);
|
||||||
|
float cr = dht.getComfortRatio(cf, newValues.temperature, newValues.humidity);
|
||||||
|
|
||||||
|
String comfortStatus;
|
||||||
|
switch(cf) {
|
||||||
|
case Comfort_OK:
|
||||||
|
comfortStatus = "Comfort_OK";
|
||||||
|
break;
|
||||||
|
case Comfort_TooHot:
|
||||||
|
comfortStatus = "Comfort_TooHot";
|
||||||
|
break;
|
||||||
|
case Comfort_TooCold:
|
||||||
|
comfortStatus = "Comfort_TooCold";
|
||||||
|
break;
|
||||||
|
case Comfort_TooDry:
|
||||||
|
comfortStatus = "Comfort_TooDry";
|
||||||
|
break;
|
||||||
|
case Comfort_TooHumid:
|
||||||
|
comfortStatus = "Comfort_TooHumid";
|
||||||
|
break;
|
||||||
|
case Comfort_HotAndHumid:
|
||||||
|
comfortStatus = "Comfort_HotAndHumid";
|
||||||
|
break;
|
||||||
|
case Comfort_HotAndDry:
|
||||||
|
comfortStatus = "Comfort_HotAndDry";
|
||||||
|
break;
|
||||||
|
case Comfort_ColdAndHumid:
|
||||||
|
comfortStatus = "Comfort_ColdAndHumid";
|
||||||
|
break;
|
||||||
|
case Comfort_ColdAndDry:
|
||||||
|
comfortStatus = "Comfort_ColdAndDry";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
comfortStatus = "Unknown:";
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
Serial.println(" T:" + String(newValues.temperature) + " H:" + String(newValues.humidity) + " I:" + String(heatIndex) + " D:" + String(dewPoint) + " " + comfortStatus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("DHT ESP32 example with tasks");
|
||||||
|
initTemp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (!tasksEnabled) {
|
||||||
|
// Wait 2 seconds to let system settle down
|
||||||
|
delay(2000);
|
||||||
|
// Enable task that will read values from the DHT sensor
|
||||||
|
tasksEnabled = true;
|
||||||
|
if (tempTaskHandle != NULL) {
|
||||||
|
vTaskResume(tempTaskHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield();
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include "ESP32Ticker.h"
|
||||||
|
#include "DHTesp.h"
|
||||||
|
|
||||||
|
/** Initialize DHT sensor 1 */
|
||||||
|
DHTesp dhtSensor1;
|
||||||
|
/** Initialize DHT sensor 2 */
|
||||||
|
DHTesp dhtSensor2;
|
||||||
|
/** Initialize DHT sensor 3 */
|
||||||
|
DHTesp dhtSensor3;
|
||||||
|
/** Task handle for the light value read task */
|
||||||
|
TaskHandle_t tempTaskHandle = NULL;
|
||||||
|
/** Pin number for DHT11 1 data pin */
|
||||||
|
int dhtPin1 = 17;
|
||||||
|
/** Pin number for DHT11 2 data pin */
|
||||||
|
int dhtPin2 = 16;
|
||||||
|
/** Pin number for DHT11 3 data pin */
|
||||||
|
int dhtPin3 = 27;
|
||||||
|
/** Ticker for temperature reading */
|
||||||
|
Ticker tempTicker;
|
||||||
|
/** Flags for temperature readings finished */
|
||||||
|
bool gotNewTemperature = false;
|
||||||
|
/** Data from sensor 1 */
|
||||||
|
TempAndHumidity sensor1Data;
|
||||||
|
/** Data from sensor 2 */
|
||||||
|
TempAndHumidity sensor2Data;
|
||||||
|
/** Data from sensor 3 */
|
||||||
|
TempAndHumidity sensor3Data;
|
||||||
|
|
||||||
|
/* Flag if main loop is running */
|
||||||
|
bool tasksEnabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task to reads temperature from DHT11 sensor
|
||||||
|
* @param pvParameters
|
||||||
|
* pointer to task parameters
|
||||||
|
*/
|
||||||
|
void tempTask(void *pvParameters) {
|
||||||
|
Serial.println("tempTask loop started");
|
||||||
|
while (1) // tempTask loop
|
||||||
|
{
|
||||||
|
if (tasksEnabled && !gotNewTemperature) { // Read temperature only if old data was processed already
|
||||||
|
// Reading temperature for humidity takes about 250 milliseconds!
|
||||||
|
// Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
|
||||||
|
sensor1Data = dhtSensor1.getTempAndHumidity(); // Read values from sensor 1
|
||||||
|
sensor2Data = dhtSensor2.getTempAndHumidity(); // Read values from sensor 1
|
||||||
|
sensor3Data = dhtSensor3.getTempAndHumidity(); // Read values from sensor 1
|
||||||
|
gotNewTemperature = true;
|
||||||
|
}
|
||||||
|
vTaskSuspend(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* triggerGetTemp
|
||||||
|
* Sets flag dhtUpdated to true for handling in loop()
|
||||||
|
* called by Ticker tempTicker
|
||||||
|
*/
|
||||||
|
void triggerGetTemp() {
|
||||||
|
if (tempTaskHandle != NULL) {
|
||||||
|
xTaskResumeFromISR(tempTaskHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arduino setup function (called once after boot/reboot)
|
||||||
|
*/
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("Example for 3 DHT11/22 sensors");
|
||||||
|
|
||||||
|
// Initialize temperature sensor 1
|
||||||
|
dhtSensor1.setup(dhtPin1, DHTesp::DHT11);
|
||||||
|
// Initialize temperature sensor 2
|
||||||
|
dhtSensor2.setup(dhtPin2, DHTesp::DHT11);
|
||||||
|
// Initialize temperature sensor 3
|
||||||
|
dhtSensor3.setup(dhtPin3, DHTesp::DHT11);
|
||||||
|
|
||||||
|
// Start task to get temperature
|
||||||
|
xTaskCreatePinnedToCore(
|
||||||
|
tempTask, /* Function to implement the task */
|
||||||
|
"tempTask ", /* Name of the task */
|
||||||
|
4000, /* Stack size in words */
|
||||||
|
NULL, /* Task input parameter */
|
||||||
|
5, /* Priority of the task */
|
||||||
|
&tempTaskHandle, /* Task handle. */
|
||||||
|
1); /* Core where the task should run */
|
||||||
|
|
||||||
|
if (tempTaskHandle == NULL) {
|
||||||
|
Serial.println("[ERROR] Failed to start task for temperature update");
|
||||||
|
} else {
|
||||||
|
// Start update of environment data every 30 seconds
|
||||||
|
tempTicker.attach(30, triggerGetTemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal end of setup() to tasks
|
||||||
|
tasksEnabled = true;
|
||||||
|
} // End of setup.
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* loop
|
||||||
|
* Arduino loop function, called once 'setup' is complete (your own code
|
||||||
|
* should go here)
|
||||||
|
*/
|
||||||
|
void loop() {
|
||||||
|
if (gotNewTemperature) {
|
||||||
|
Serial.println("Sensor 1 data:");
|
||||||
|
Serial.println("Temp: " + String(sensor1Data.temperature,2) + "'C Humidity: " + String(sensor1Data.humidity,1) + "%");
|
||||||
|
Serial.println("Sensor 2 data:");
|
||||||
|
Serial.println("Temp: " + String(sensor2Data.temperature,2) + "'C Humidity: " + String(sensor2Data.humidity,1) + "%");
|
||||||
|
Serial.println("Sensor 3 data:");
|
||||||
|
Serial.println("Temp: " + String(sensor3Data.temperature,2) + "'C Humidity: " + String(sensor3Data.humidity,1) + "%");
|
||||||
|
gotNewTemperature = false;
|
||||||
|
}
|
||||||
|
} // End of loop
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#include "DHTesp.h"
|
||||||
|
|
||||||
|
DHTesp dht;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("Status\tHumidity (%)\tTemperature (C)\t(F)\tHeatIndex (C)\t(F)");
|
||||||
|
|
||||||
|
dht.setup(22); // Connect DHT sensor to GPIO 17
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
|
||||||
|
//delay(dht.getMinimumSamplingPeriod()*1.2);
|
||||||
|
static uint32_t last_dht_update= 0;
|
||||||
|
uint32_t now_dht = millis();
|
||||||
|
if (now_dht - last_dht_update > dht.getMinimumSamplingPeriod() *1.2) {
|
||||||
|
last_dht_update = now_dht;
|
||||||
|
float humidity = dht.getHumidity();
|
||||||
|
float temperature = dht.getTemperature();
|
||||||
|
|
||||||
|
Serial.print(dht.getStatusString());
|
||||||
|
Serial.print("\t H:");
|
||||||
|
Serial.print(humidity, 1);
|
||||||
|
Serial.print("%\t\T :");
|
||||||
|
Serial.print(temperature, 1);
|
||||||
|
Serial.println("C\t\t");
|
||||||
|
//Serial.print(dht.toFahrenheit(temperature), 1);
|
||||||
|
//Serial.print("\t\t");
|
||||||
|
//Serial.print(dht.computeHeatIndex(temperature, humidity, false), 1);
|
||||||
|
//Serial.print("\t\t");
|
||||||
|
//Serial.println(dht.computeHeatIndex(dht.toFahrenheit(temperature), humidity, true), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
79
libraries/DHT_sensor_library_for_ESPx/keywords.txt
Normal file
79
libraries/DHT_sensor_library_for_ESPx/keywords.txt
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#######################################
|
||||||
|
# Syntax Coloring Map For DHTesp
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Datatypes (KEYWORD1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
DHTesp KEYWORD1
|
||||||
|
TempAndHumidity KEYWORD1
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
setup KEYWORD2
|
||||||
|
getTemperature KEYWORD2
|
||||||
|
getHumidity KEYWORD2
|
||||||
|
getTempAndHumidity KEYWORD2
|
||||||
|
getStatus KEYWORD2
|
||||||
|
getStatusString KEYWORD2
|
||||||
|
getModel KEYWORD2
|
||||||
|
getMinimumSamplingPeriod KEYWORD2
|
||||||
|
toFahrenheit KEYWORD2
|
||||||
|
toCelsius KEYWORD2
|
||||||
|
computeHeatIndex KEYWORD2
|
||||||
|
computeDewPoint KEYWORD2
|
||||||
|
getComfortRatio KEYWORD2
|
||||||
|
getNumberOfDecimalsTemperature KEYWORD2
|
||||||
|
getLowerBoundTemperature KEYWORD2
|
||||||
|
getUpperBoundTemperature KEYWORD2
|
||||||
|
getNumberOfDecimalsHumidity KEYWORD2
|
||||||
|
getLowerBoundHumidity KEYWORD2
|
||||||
|
getUpperBoundHumidity KEYWORD2
|
||||||
|
getComfortProfile KEYWORD2
|
||||||
|
setComfortProfile KEYWORD2
|
||||||
|
isTooHot KEYWORD2
|
||||||
|
isTooHumid KEYWORD2
|
||||||
|
isTooCold KEYWORD2
|
||||||
|
isTooDry KEYWORD2
|
||||||
|
computePerception KEYWORD2
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Instances (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Constants (LITERAL1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
AUTO_DETECT LITERAL1
|
||||||
|
DHT11 LITERAL1
|
||||||
|
DHT22 LITERAL1
|
||||||
|
AM2302 LITERAL1
|
||||||
|
RHT03 LITERAL1
|
||||||
|
|
||||||
|
ERROR_NONE LITERAL1
|
||||||
|
ERROR_TIMEOUT LITERAL1
|
||||||
|
ERROR_CHECKSUM LITERAL1
|
||||||
|
|
||||||
|
Comfort_OK LITERAL1
|
||||||
|
Comfort_TooHot LITERAL1
|
||||||
|
Comfort_TooCold LITERAL1
|
||||||
|
Comfort_TooDry LITERAL1
|
||||||
|
Comfort_TooHumid LITERAL1
|
||||||
|
Comfort_HotAndHumid LITERAL1
|
||||||
|
Comfort_HotAndDry LITERAL1
|
||||||
|
Comfort_ColdAndHumid LITERAL1
|
||||||
|
Comfort_ColdAndDry LITERAL1
|
||||||
|
|
||||||
|
Perception_Dry LITERAL1
|
||||||
|
Perception_VeryComfy LITERAL1
|
||||||
|
Perception_Comfy LITERAL1
|
||||||
|
Perception_Ok LITERAL1
|
||||||
|
Perception_UnComfy LITERAL1
|
||||||
|
Perception_QuiteUnComfy LITERAL1
|
||||||
|
Perception_UnComfy LITERAL1
|
||||||
|
Perception_VeryUncomfy LITERAL1
|
||||||
15
libraries/DHT_sensor_library_for_ESPx/library.json
Normal file
15
libraries/DHT_sensor_library_for_ESPx/library.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "DHT sensor library for ESPx",
|
||||||
|
"keywords": "onewire, 1-wire, bus, sensor, temperature",
|
||||||
|
"description": "Arduino ESP library for DHT11, DHT22, etc Temp & Humidity Sensors. Last changes: Updated example.",
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/beegee-tokyo/DHTesp.git"
|
||||||
|
},
|
||||||
|
"version": "1.0.6",
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": "*",
|
||||||
|
"license": "GPL-3.0-only",
|
||||||
|
"homepage": "http://desire.giesecke.tk/index.php/2018/01/30/esp32-dht11/"
|
||||||
|
}
|
||||||
10
libraries/DHT_sensor_library_for_ESPx/library.properties
Normal file
10
libraries/DHT_sensor_library_for_ESPx/library.properties
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
name=DHT sensor library for ESPx
|
||||||
|
version=1.0.6
|
||||||
|
author=beegee_tokyo
|
||||||
|
maintainer=beegee_tokyo <beegee@giesecke.tk>
|
||||||
|
sentence=Arduino ESP library for DHT11, DHT22, etc Temp & Humidity Sensors
|
||||||
|
paragraph=Optimized libray to match ESP32 requirements. Last changes: Updated example.
|
||||||
|
category=Sensors
|
||||||
|
url=http://desire.giesecke.tk/index.php/2018/01/30/esp32-dht11/
|
||||||
|
architectures=esp8266,esp32,arduino-esp32
|
||||||
|
includes=DHTesp.h
|
||||||
442
libraries/ESP32SSDP/ESP32SSDP.cpp
Normal file
442
libraries/ESP32SSDP/ESP32SSDP.cpp
Normal file
@@ -0,0 +1,442 @@
|
|||||||
|
/*
|
||||||
|
ESP32 Simple Service Discovery
|
||||||
|
Copyright (c) 2015 Hristo Gochkov
|
||||||
|
|
||||||
|
Original (Arduino) version by Filippo Sallemi, July 23, 2014.
|
||||||
|
Can be found at: https://github.com/nomadnt/uSSDP
|
||||||
|
|
||||||
|
License (MIT license):
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include "ESP32SSDP.h"
|
||||||
|
#include "WiFiUdp.h"
|
||||||
|
#include <lwip/ip_addr.h>
|
||||||
|
|
||||||
|
//#define DEBUG_SSDP Serial
|
||||||
|
|
||||||
|
#define SSDP_INTERVAL 1200
|
||||||
|
#define SSDP_PORT 1900
|
||||||
|
#define SSDP_METHOD_SIZE 10
|
||||||
|
#define SSDP_URI_SIZE 2
|
||||||
|
#define SSDP_BUFFER_SIZE 64
|
||||||
|
#define SSDP_MULTICAST_TTL 2
|
||||||
|
static const IPAddress SSDP_MULTICAST_ADDR(239, 255, 255, 250);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const char _ssdp_response_template[] PROGMEM =
|
||||||
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
"EXT:\r\n";
|
||||||
|
|
||||||
|
static const char _ssdp_notify_template[] PROGMEM =
|
||||||
|
"NOTIFY * HTTP/1.1\r\n"
|
||||||
|
"HOST: 239.255.255.250:1900\r\n"
|
||||||
|
"NTS: ssdp:alive\r\n";
|
||||||
|
|
||||||
|
static const char _ssdp_packet_template[] PROGMEM =
|
||||||
|
"%s" // _ssdp_response_template / _ssdp_notify_template
|
||||||
|
"CACHE-CONTROL: max-age=%u\r\n" // SSDP_INTERVAL
|
||||||
|
"SERVER: Arduino/1.0 UPNP/1.1 %s/%s\r\n" // _modelName, _modelNumber
|
||||||
|
"USN: uuid:%s\r\n" // _uuid
|
||||||
|
"%s: %s\r\n" // "NT" or "ST", _deviceType
|
||||||
|
"LOCATION: http://%u.%u.%u.%u:%u/%s\r\n" // WiFi.localIP(), _port, _schemaURL
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
static const char _ssdp_schema_template[] PROGMEM =
|
||||||
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Type: text/xml\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"Access-Control-Allow-Origin: *\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"<?xml version=\"1.0\"?>"
|
||||||
|
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
|
||||||
|
"<specVersion>"
|
||||||
|
"<major>1</major>"
|
||||||
|
"<minor>0</minor>"
|
||||||
|
"</specVersion>"
|
||||||
|
"<URLBase>http://%u.%u.%u.%u:%u/</URLBase>" // WiFi.localIP(), _port
|
||||||
|
"<device>"
|
||||||
|
"<deviceType>%s</deviceType>"
|
||||||
|
"<friendlyName>%s</friendlyName>"
|
||||||
|
"<presentationURL>%s</presentationURL>"
|
||||||
|
"<serialNumber>%s</serialNumber>"
|
||||||
|
"<modelName>%s</modelName>"
|
||||||
|
"<modelNumber>%s</modelNumber>"
|
||||||
|
"<modelURL>%s</modelURL>"
|
||||||
|
"<manufacturer>%s</manufacturer>"
|
||||||
|
"<manufacturerURL>%s</manufacturerURL>"
|
||||||
|
"<UDN>uuid:%s</UDN>"
|
||||||
|
"</device>"
|
||||||
|
// "<iconList>"
|
||||||
|
// "<icon>"
|
||||||
|
// "<mimetype>image/png</mimetype>"
|
||||||
|
// "<height>48</height>"
|
||||||
|
// "<width>48</width>"
|
||||||
|
// "<depth>24</depth>"
|
||||||
|
// "<url>icon48.png</url>"
|
||||||
|
// "</icon>"
|
||||||
|
// "<icon>"
|
||||||
|
// "<mimetype>image/png</mimetype>"
|
||||||
|
// "<height>120</height>"
|
||||||
|
// "<width>120</width>"
|
||||||
|
// "<depth>24</depth>"
|
||||||
|
// "<url>icon120.png</url>"
|
||||||
|
// "</icon>"
|
||||||
|
// "</iconList>"
|
||||||
|
"</root>\r\n"
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
struct SSDPTimer {
|
||||||
|
ETSTimer timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
SSDPClass::SSDPClass() :
|
||||||
|
_server(0),
|
||||||
|
_timer(new SSDPTimer),
|
||||||
|
_port(80),
|
||||||
|
_ttl(SSDP_MULTICAST_TTL),
|
||||||
|
_respondToPort(0),
|
||||||
|
_pending(false),
|
||||||
|
_delay(0),
|
||||||
|
_process_time(0),
|
||||||
|
_notify_time(0)
|
||||||
|
{
|
||||||
|
_uuid[0] = '\0';
|
||||||
|
_modelNumber[0] = '\0';
|
||||||
|
sprintf(_deviceType, "urn:schemas-upnp-org:device:Basic:1");
|
||||||
|
_friendlyName[0] = '\0';
|
||||||
|
_presentationURL[0] = '\0';
|
||||||
|
_serialNumber[0] = '\0';
|
||||||
|
_modelName[0] = '\0';
|
||||||
|
_modelURL[0] = '\0';
|
||||||
|
_manufacturer[0] = '\0';
|
||||||
|
_manufacturerURL[0] = '\0';
|
||||||
|
sprintf(_schemaURL, "ssdp/schema.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
SSDPClass::~SSDPClass(){
|
||||||
|
delete _timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SSDPClass::begin(){
|
||||||
|
_pending = false;
|
||||||
|
|
||||||
|
uint32_t chipId = ((uint16_t) (ESP.getEfuseMac() >> 32));
|
||||||
|
sprintf(_uuid, "38323636-4558-4dda-9188-cda0e6%02x%02x%02x",
|
||||||
|
(uint16_t) ((chipId >> 16) & 0xff),
|
||||||
|
(uint16_t) ((chipId >> 8) & 0xff),
|
||||||
|
(uint16_t) chipId & 0xff );
|
||||||
|
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.printf("SSDP UUID: %s\n", (char *)_uuid);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_server) {
|
||||||
|
delete (_server);
|
||||||
|
_server = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_server = new WiFiUDP;
|
||||||
|
|
||||||
|
if (!(_server->beginMulticast(IPAddress(SSDP_MULTICAST_ADDR), SSDP_PORT))) {
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.println("Error begin");
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_startTimer();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::_send(ssdp_method_t method){
|
||||||
|
char buffer[1460];
|
||||||
|
IPAddress ip = WiFi.localIP();
|
||||||
|
|
||||||
|
char valueBuffer[strlen_P(_ssdp_notify_template)+1];
|
||||||
|
strcpy_P(valueBuffer, (method == NONE)?_ssdp_response_template:_ssdp_notify_template);
|
||||||
|
|
||||||
|
int len = snprintf_P(buffer, sizeof(buffer),
|
||||||
|
_ssdp_packet_template,
|
||||||
|
valueBuffer,
|
||||||
|
SSDP_INTERVAL,
|
||||||
|
_modelName, _modelNumber,
|
||||||
|
_uuid,
|
||||||
|
(method == NONE)?"ST":"NT",
|
||||||
|
_deviceType,
|
||||||
|
ip[0], ip[1], ip[2], ip[3], _port, _schemaURL
|
||||||
|
);
|
||||||
|
|
||||||
|
IPAddress remoteAddr;
|
||||||
|
uint16_t remotePort;
|
||||||
|
if(method == NONE) {
|
||||||
|
remoteAddr = _respondToAddr;
|
||||||
|
remotePort = _respondToPort;
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.print("Sending Response to ");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
remoteAddr = IPAddress(SSDP_MULTICAST_ADDR);
|
||||||
|
remotePort = SSDP_PORT;
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.println("Sending Notify to ");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.print(remoteAddr);
|
||||||
|
DEBUG_SSDP.print(":");
|
||||||
|
DEBUG_SSDP.println(remotePort);
|
||||||
|
#endif
|
||||||
|
_server->beginPacket(remoteAddr, remotePort);
|
||||||
|
_server->println(buffer);
|
||||||
|
_server->endPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::schema(WiFiClient client){
|
||||||
|
IPAddress ip = WiFi.localIP();
|
||||||
|
char buffer[strlen_P(_ssdp_schema_template)+1];
|
||||||
|
strcpy_P(buffer, _ssdp_schema_template);
|
||||||
|
client.printf(buffer,
|
||||||
|
ip[0], ip[1], ip[2], ip[3], _port,
|
||||||
|
_deviceType,
|
||||||
|
_friendlyName,
|
||||||
|
_presentationURL,
|
||||||
|
_serialNumber,
|
||||||
|
_modelName,
|
||||||
|
_modelNumber,
|
||||||
|
_modelURL,
|
||||||
|
_manufacturer,
|
||||||
|
_manufacturerURL,
|
||||||
|
_uuid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::_update(){
|
||||||
|
int nbBytes =0;
|
||||||
|
char * packetBuffer = NULL;
|
||||||
|
|
||||||
|
if(!_pending && _server) {
|
||||||
|
ssdp_method_t method = NONE;
|
||||||
|
nbBytes= _server->parsePacket();
|
||||||
|
typedef enum {METHOD, URI, PROTO, KEY, VALUE, ABORT} states;
|
||||||
|
states state = METHOD;
|
||||||
|
typedef enum {START, MAN, ST, MX} headers;
|
||||||
|
headers header = START;
|
||||||
|
|
||||||
|
uint8_t cursor = 0;
|
||||||
|
uint8_t cr = 0;
|
||||||
|
|
||||||
|
char buffer[SSDP_BUFFER_SIZE] = {0};
|
||||||
|
packetBuffer = new char[nbBytes +1];
|
||||||
|
int message_size=_server->read(packetBuffer,nbBytes);
|
||||||
|
int process_pos = 0;
|
||||||
|
packetBuffer[message_size]='\0';
|
||||||
|
_respondToAddr = _server->remoteIP();
|
||||||
|
_respondToPort = _server->remotePort();
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
if (message_size) {
|
||||||
|
DEBUG_SSDP.println("****************************************************");
|
||||||
|
DEBUG_SSDP.println(_server->remoteIP());
|
||||||
|
DEBUG_SSDP.println(packetBuffer);
|
||||||
|
DEBUG_SSDP.println("****************************************************");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
while(process_pos < message_size){
|
||||||
|
|
||||||
|
char c = packetBuffer[process_pos];
|
||||||
|
process_pos++;
|
||||||
|
(c == '\r' || c == '\n') ? cr++ : cr = 0;
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
if ((c == '\r' || c == '\n') && (cr < 2)) DEBUG_SSDP.println(buffer);
|
||||||
|
#endif
|
||||||
|
switch(state){
|
||||||
|
case METHOD:
|
||||||
|
if(c == ' '){
|
||||||
|
if(strcmp(buffer, "M-SEARCH") == 0) method = SEARCH;
|
||||||
|
|
||||||
|
if(method == NONE) state = ABORT;
|
||||||
|
else state = URI;
|
||||||
|
cursor = 0;
|
||||||
|
|
||||||
|
} else if(cursor < SSDP_METHOD_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; }
|
||||||
|
break;
|
||||||
|
case URI:
|
||||||
|
if(c == ' '){
|
||||||
|
if(strcmp(buffer, "*")) state = ABORT;
|
||||||
|
else state = PROTO;
|
||||||
|
cursor = 0;
|
||||||
|
} else if(cursor < SSDP_URI_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; }
|
||||||
|
break;
|
||||||
|
case PROTO:
|
||||||
|
if(cr == 2){ state = KEY; cursor = 0; }
|
||||||
|
break;
|
||||||
|
case KEY:
|
||||||
|
if(cr == 4){ _pending = true; _process_time = millis(); }
|
||||||
|
else if(c == ' '){ cursor = 0; state = VALUE; }
|
||||||
|
else if(c != '\r' && c != '\n' && c != ':' && cursor < SSDP_BUFFER_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; }
|
||||||
|
break;
|
||||||
|
case VALUE:
|
||||||
|
if(cr == 2){
|
||||||
|
switch(header){
|
||||||
|
case START:
|
||||||
|
break;
|
||||||
|
case MAN:
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.printf("MAN: %s\n", (char *)buffer);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case ST:
|
||||||
|
if(strcmp(buffer, "ssdp:all")){
|
||||||
|
state = ABORT;
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.printf("REJECT: %s\n", (char *)buffer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// if the search type matches our type, we should respond instead of ABORT
|
||||||
|
if(strcasecmp(buffer, _deviceType) == 0){
|
||||||
|
_pending = true;
|
||||||
|
_process_time = 0;
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.println("the search type matches our type");
|
||||||
|
#endif
|
||||||
|
state = KEY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MX:
|
||||||
|
_delay = random(0, atoi(buffer)) * 1000L;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state != ABORT){ state = KEY; header = START; cursor = 0; }
|
||||||
|
} else if(c != '\r' && c != '\n'){
|
||||||
|
if(header == START){
|
||||||
|
if(strncmp(buffer, "MA", 2) == 0) header = MAN;
|
||||||
|
else if(strcmp(buffer, "ST") == 0) header = ST;
|
||||||
|
else if(strcmp(buffer, "MX") == 0) header = MX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cursor < SSDP_BUFFER_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ABORT:
|
||||||
|
_pending = false; _delay = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(packetBuffer) delete packetBuffer;
|
||||||
|
if(_pending && (millis() - _process_time) > _delay){
|
||||||
|
_pending = false; _delay = 0;
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.println("Send None");
|
||||||
|
#endif
|
||||||
|
_send(NONE);
|
||||||
|
} else if(_notify_time == 0 || (millis() - _notify_time) > (SSDP_INTERVAL * 1000L)){
|
||||||
|
_notify_time = millis();
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.println("Send Notify");
|
||||||
|
#endif
|
||||||
|
_send(NOTIFY);
|
||||||
|
} else {
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.println("Do not sent");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pending) {
|
||||||
|
_server->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setSchemaURL(const char *url){
|
||||||
|
strlcpy(_schemaURL, url, sizeof(_schemaURL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setHTTPPort(uint16_t port){
|
||||||
|
_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setDeviceType(const char *deviceType){
|
||||||
|
strlcpy(_deviceType, deviceType, sizeof(_deviceType));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setName(const char *name){
|
||||||
|
strlcpy(_friendlyName, name, sizeof(_friendlyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setURL(const char *url){
|
||||||
|
strlcpy(_presentationURL, url, sizeof(_presentationURL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setSerialNumber(const char *serialNumber){
|
||||||
|
strlcpy(_serialNumber, serialNumber, sizeof(_serialNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setSerialNumber(const uint32_t serialNumber){
|
||||||
|
snprintf(_serialNumber, sizeof(uint32_t)*2+1, "%08X", serialNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setModelName(const char *name){
|
||||||
|
strlcpy(_modelName, name, sizeof(_modelName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setModelNumber(const char *num){
|
||||||
|
strlcpy(_modelNumber, num, sizeof(_modelNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setModelURL(const char *url){
|
||||||
|
strlcpy(_modelURL, url, sizeof(_modelURL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setManufacturer(const char *name){
|
||||||
|
strlcpy(_manufacturer, name, sizeof(_manufacturer));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setManufacturerURL(const char *url){
|
||||||
|
strlcpy(_manufacturerURL, url, sizeof(_manufacturerURL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setTTL(const uint8_t ttl){
|
||||||
|
_ttl = ttl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::_onTimerStatic(SSDPClass* self) {
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.println("Update");
|
||||||
|
#endif
|
||||||
|
self->_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::_startTimer() {
|
||||||
|
ETSTimer* tm = &(_timer->timer);
|
||||||
|
const int interval = 1000;
|
||||||
|
ets_timer_disarm(tm);
|
||||||
|
ets_timer_setfn(tm, reinterpret_cast<ETSTimerFunc*>(&SSDPClass::_onTimerStatic), reinterpret_cast<void*>(this));
|
||||||
|
ets_timer_arm(tm, interval, 1 /* repeat */);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SSDP)
|
||||||
|
SSDPClass SSDP;
|
||||||
|
#endif
|
||||||
126
libraries/ESP32SSDP/ESP32SSDP.h
Normal file
126
libraries/ESP32SSDP/ESP32SSDP.h
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
ESP32 Simple Service Discovery
|
||||||
|
Copyright (c) 2015 Hristo Gochkov
|
||||||
|
|
||||||
|
Original (Arduino) version by Filippo Sallemi, July 23, 2014.
|
||||||
|
Can be found at: https://github.com/nomadnt/uSSDP
|
||||||
|
|
||||||
|
License (MIT license):
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ESP32SSDP_H
|
||||||
|
#define ESP32SSDP_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
|
||||||
|
#define SSDP_UUID_SIZE 37
|
||||||
|
#define SSDP_SCHEMA_URL_SIZE 64
|
||||||
|
#define SSDP_DEVICE_TYPE_SIZE 64
|
||||||
|
#define SSDP_FRIENDLY_NAME_SIZE 64
|
||||||
|
#define SSDP_SERIAL_NUMBER_SIZE 32
|
||||||
|
#define SSDP_PRESENTATION_URL_SIZE 128
|
||||||
|
#define SSDP_MODEL_NAME_SIZE 64
|
||||||
|
#define SSDP_MODEL_URL_SIZE 128
|
||||||
|
#define SSDP_MODEL_VERSION_SIZE 32
|
||||||
|
#define SSDP_MANUFACTURER_SIZE 64
|
||||||
|
#define SSDP_MANUFACTURER_URL_SIZE 128
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NONE,
|
||||||
|
SEARCH,
|
||||||
|
NOTIFY
|
||||||
|
} ssdp_method_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct SSDPTimer;
|
||||||
|
|
||||||
|
class SSDPClass{
|
||||||
|
public:
|
||||||
|
SSDPClass();
|
||||||
|
~SSDPClass();
|
||||||
|
|
||||||
|
bool begin();
|
||||||
|
|
||||||
|
void schema(WiFiClient client);
|
||||||
|
|
||||||
|
void setDeviceType(const String& deviceType) { setDeviceType(deviceType.c_str()); }
|
||||||
|
void setDeviceType(const char *deviceType);
|
||||||
|
void setName(const String& name) { setName(name.c_str()); }
|
||||||
|
void setName(const char *name);
|
||||||
|
void setURL(const String& url) { setURL(url.c_str()); }
|
||||||
|
void setURL(const char *url);
|
||||||
|
void setSchemaURL(const String& url) { setSchemaURL(url.c_str()); }
|
||||||
|
void setSchemaURL(const char *url);
|
||||||
|
void setSerialNumber(const String& serialNumber) { setSerialNumber(serialNumber.c_str()); }
|
||||||
|
void setSerialNumber(const char *serialNumber);
|
||||||
|
void setSerialNumber(const uint32_t serialNumber);
|
||||||
|
void setModelName(const String& name) { setModelName(name.c_str()); }
|
||||||
|
void setModelName(const char *name);
|
||||||
|
void setModelNumber(const String& num) { setModelNumber(num.c_str()); }
|
||||||
|
void setModelNumber(const char *num);
|
||||||
|
void setModelURL(const String& url) { setModelURL(url.c_str()); }
|
||||||
|
void setModelURL(const char *url);
|
||||||
|
void setManufacturer(const String& name) { setManufacturer(name.c_str()); }
|
||||||
|
void setManufacturer(const char *name);
|
||||||
|
void setManufacturerURL(const String& url) { setManufacturerURL(url.c_str()); }
|
||||||
|
void setManufacturerURL(const char *url);
|
||||||
|
void setHTTPPort(uint16_t port);
|
||||||
|
void setTTL(uint8_t ttl);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _send(ssdp_method_t method);
|
||||||
|
void _update();
|
||||||
|
void _startTimer();
|
||||||
|
static void _onTimerStatic(SSDPClass* self);
|
||||||
|
|
||||||
|
WiFiUDP *_server;
|
||||||
|
SSDPTimer* _timer;
|
||||||
|
uint16_t _port;
|
||||||
|
uint8_t _ttl;
|
||||||
|
|
||||||
|
IPAddress _respondToAddr;
|
||||||
|
uint16_t _respondToPort;
|
||||||
|
|
||||||
|
bool _pending;
|
||||||
|
unsigned short _delay;
|
||||||
|
unsigned long _process_time;
|
||||||
|
unsigned long _notify_time;
|
||||||
|
|
||||||
|
char _schemaURL[SSDP_SCHEMA_URL_SIZE];
|
||||||
|
char _uuid[SSDP_UUID_SIZE];
|
||||||
|
char _deviceType[SSDP_DEVICE_TYPE_SIZE];
|
||||||
|
char _friendlyName[SSDP_FRIENDLY_NAME_SIZE];
|
||||||
|
char _serialNumber[SSDP_SERIAL_NUMBER_SIZE];
|
||||||
|
char _presentationURL[SSDP_PRESENTATION_URL_SIZE];
|
||||||
|
char _manufacturer[SSDP_MANUFACTURER_SIZE];
|
||||||
|
char _manufacturerURL[SSDP_MANUFACTURER_URL_SIZE];
|
||||||
|
char _modelName[SSDP_MODEL_NAME_SIZE];
|
||||||
|
char _modelURL[SSDP_MODEL_URL_SIZE];
|
||||||
|
char _modelNumber[SSDP_MODEL_VERSION_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SSDP)
|
||||||
|
extern SSDPClass SSDP;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
22
libraries/ESP32SSDP/README.rst
Normal file
22
libraries/ESP32SSDP/README.rst
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
ESP32 Simple Service Discovery Copyright (c) 2015 Hristo Gochkov
|
||||||
|
Original (Arduino) version by Filippo Sallemi, July 23, 2014. Can be
|
||||||
|
found at: https://github.com/nomadnt/uSSDP
|
||||||
|
|
||||||
|
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.
|
||||||
51
libraries/ESP32SSDP/examples/SSDP/SSDP.ino
Normal file
51
libraries/ESP32SSDP/examples/SSDP/SSDP.ino
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#include <WiFi.h>
|
||||||
|
#include <WebServer.h>
|
||||||
|
#include <ESP32SSDP.h>
|
||||||
|
|
||||||
|
const char* ssid = "********";
|
||||||
|
const char* password = "********";
|
||||||
|
|
||||||
|
WebServer HTTP(80);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("Starting WiFi...");
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
if(WiFi.waitForConnectResult() == WL_CONNECTED){
|
||||||
|
|
||||||
|
Serial.printf("Starting HTTP...\n");
|
||||||
|
HTTP.on("/index.html", HTTP_GET, [](){
|
||||||
|
HTTP.send(200, "text/plain", "Hello World!");
|
||||||
|
});
|
||||||
|
HTTP.on("/description.xml", HTTP_GET, [](){
|
||||||
|
SSDP.schema(HTTP.client());
|
||||||
|
});
|
||||||
|
HTTP.begin();
|
||||||
|
|
||||||
|
Serial.printf("Starting SSDP...\n");
|
||||||
|
SSDP.setSchemaURL("description.xml");
|
||||||
|
SSDP.setHTTPPort(80);
|
||||||
|
SSDP.setName("Philips hue clone");
|
||||||
|
SSDP.setSerialNumber("001788102201");
|
||||||
|
SSDP.setURL("index.html");
|
||||||
|
SSDP.setModelName("Philips hue bridge 2012");
|
||||||
|
SSDP.setModelNumber("929000226503");
|
||||||
|
SSDP.setModelURL("http://www.meethue.com");
|
||||||
|
SSDP.setManufacturer("Royal Philips Electronics");
|
||||||
|
SSDP.setManufacturerURL("http://www.philips.com");
|
||||||
|
SSDP.begin();
|
||||||
|
|
||||||
|
Serial.printf("Ready!\n");
|
||||||
|
} else {
|
||||||
|
Serial.printf("WiFi Failed\n");
|
||||||
|
while(1) delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
HTTP.handleClient();
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
53
libraries/ESP32SSDP/keywords.txt
Normal file
53
libraries/ESP32SSDP/keywords.txt
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#######################################
|
||||||
|
# Syntax Coloring Map For Ultrasound
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Datatypes (KEYWORD1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
ESP8266SSDP KEYWORD1
|
||||||
|
SSDP KEYWORD1
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
begin KEYWORD2
|
||||||
|
schema KEYWORD2
|
||||||
|
setName KEYWORD2
|
||||||
|
setURL KEYWORD2
|
||||||
|
setHTTPPort KEYWORD2
|
||||||
|
setSchemaURL KEYWORD2
|
||||||
|
setSerialNumber KEYWORD2
|
||||||
|
setModelName KEYWORD2
|
||||||
|
setModelNumber KEYWORD2
|
||||||
|
setModelURL KEYWORD2
|
||||||
|
setManufacturer KEYWORD2
|
||||||
|
setManufacturerURL KEYWORD2
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Constants (LITERAL1)
|
||||||
|
#######################################
|
||||||
|
SSDP_INTERVAL LITERAL1
|
||||||
|
SSDP_PORT LITERAL1
|
||||||
|
SSDP_METHOD_SIZE LITERAL1
|
||||||
|
SSDP_URI_SIZE LITERAL1
|
||||||
|
SSDP_BUFFER_SIZE LITERAL1
|
||||||
|
SSDP_BASE_SIZE LITERAL1
|
||||||
|
SSDP_FRIENDLY_NAME_SIZE LITERAL1
|
||||||
|
SSDP_SERIAL_NUMBER_SIZE LITERAL1
|
||||||
|
SSDP_PRESENTATION_URL_SIZE LITERAL1
|
||||||
|
SSDP_MODEL_NAME_SIZE LITERAL1
|
||||||
|
SSDP_MODEL_URL_SIZE LITERAL1
|
||||||
|
SSDP_MODEL_VERSION_SIZE LITERAL1
|
||||||
|
SSDP_MANUFACTURER_SIZE LITERAL1
|
||||||
|
SSDP_MANUFACTURER_URL_SIZE LITERAL1
|
||||||
|
SEARCH LITERAL1
|
||||||
|
NOTIFY LITERAL1
|
||||||
|
BASIC LITERAL1
|
||||||
|
MANAGEABLE LITERAL1
|
||||||
|
SOLARPROTECTIONBLIND LITERAL1
|
||||||
|
DIGITALSECURITYCAMERA LITERAL1
|
||||||
|
HVAC LITERAL1
|
||||||
|
LIGHTINGCONTROL LITERAL1
|
||||||
9
libraries/ESP32SSDP/library.properties
Normal file
9
libraries/ESP32SSDP/library.properties
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
name=ESP32SSPD
|
||||||
|
version=1.0
|
||||||
|
author=Me-No-Dev
|
||||||
|
maintainer=Me-No-Dev
|
||||||
|
sentence=Simple SSDP library for ESP32
|
||||||
|
paragraph=Only for ESP32
|
||||||
|
category=Communication
|
||||||
|
url=
|
||||||
|
architectures=esp32
|
||||||
2
libraries/ESPAsyncTCP/.gitignore
vendored
Normal file
2
libraries/ESPAsyncTCP/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
.DS_Store
|
||||||
37
libraries/ESPAsyncTCP/.travis.yml
Normal file
37
libraries/ESPAsyncTCP/.travis.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
sudo: false
|
||||||
|
language: bash
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
|
||||||
|
script:
|
||||||
|
- /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
|
||||||
|
- wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz
|
||||||
|
- tar xf arduino-1.6.5-linux64.tar.xz
|
||||||
|
- mv arduino-1.6.5 $HOME/arduino_ide
|
||||||
|
- export PATH="$HOME/arduino_ide:$PATH"
|
||||||
|
- which arduino
|
||||||
|
- mkdir -p $HOME/Arduino/libraries
|
||||||
|
- cp -r $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/ESPAsyncTCP
|
||||||
|
- cd $HOME/arduino_ide/hardware
|
||||||
|
- mkdir esp8266com
|
||||||
|
- cd esp8266com
|
||||||
|
- git clone https://github.com/esp8266/Arduino.git esp8266
|
||||||
|
- cd esp8266/tools
|
||||||
|
- python get.py
|
||||||
|
- source $TRAVIS_BUILD_DIR/travis/common.sh
|
||||||
|
- arduino --board esp8266com:esp8266:generic --save-prefs
|
||||||
|
- arduino --get-pref sketchbook.path
|
||||||
|
- build_sketches arduino $HOME/Arduino/libraries/ESPAsyncTCP esp8266
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email:
|
||||||
|
on_success: change
|
||||||
|
on_failure: change
|
||||||
|
webhooks:
|
||||||
|
urls:
|
||||||
|
- https://webhooks.gitter.im/e/60e65d0c78ea0a920347
|
||||||
|
on_success: change # options: [always|never|change] default: always
|
||||||
|
on_failure: always # options: [always|never|change] default: always
|
||||||
|
on_start: false # default: false
|
||||||
165
libraries/ESPAsyncTCP/LICENSE.txt
Normal file
165
libraries/ESPAsyncTCP/LICENSE.txt
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
GNU LESSER 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.
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
30
libraries/ESPAsyncTCP/README.md
Normal file
30
libraries/ESPAsyncTCP/README.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# ESPAsyncTCP [](https://travis-ci.org/me-no-dev/ESPAsyncTCP)
|
||||||
|
Async TCP Library for ESP8266 Arduino
|
||||||
|
|
||||||
|
For ESP32 look [HERE](https://github.com/me-no-dev/AsyncTCP)
|
||||||
|
|
||||||
|
[](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
|
This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP8266 MCUs.
|
||||||
|
|
||||||
|
This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer)
|
||||||
|
|
||||||
|
## AsyncClient and AsyncServer
|
||||||
|
The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use.
|
||||||
|
|
||||||
|
## AsyncPrinter
|
||||||
|
This class can be used to send data like any other ```Print``` interface (```Serial``` for example).
|
||||||
|
The object then can be used outside of the Async callbacks (the loop) and receive asynchronously data using ```onData```. The object can be checked if the underlying ```AsyncClient```is connected, or hook to the ```onDisconnect``` callback.
|
||||||
|
|
||||||
|
## AsyncTCPbuffer
|
||||||
|
This class is really similar to the ```AsyncPrinter```, but it differs in the fact that it can buffer some of the incoming data.
|
||||||
|
|
||||||
|
## SyncClient
|
||||||
|
It is exactly what it sounds like. This is a standard, blocking TCP Client, similar to the one included in ```ESP8266WiFi```
|
||||||
|
|
||||||
|
## Libraries and projects that use AsyncTCP
|
||||||
|
- [ESP Async Web Server](https://github.com/me-no-dev/ESPAsyncWebServer)
|
||||||
|
- [Async MQTT client](https://github.com/marvinroger/async-mqtt-client)
|
||||||
|
- [arduinoWebSockets](https://github.com/Links2004/arduinoWebSockets)
|
||||||
|
- [ESP8266 Smart Home](https://github.com/baruch/esp8266_smart_home)
|
||||||
|
- [KBox Firmware](https://github.com/sarfata/kbox-firmware)
|
||||||
54
libraries/ESPAsyncTCP/examples/SyncClient/SyncClient.ino
Normal file
54
libraries/ESPAsyncTCP/examples/SyncClient/SyncClient.ino
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#ifdef ESP8266
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266mDNS.h>
|
||||||
|
#include <ArduinoOTA.h>
|
||||||
|
#else
|
||||||
|
#include <ESP31BWiFi.h>
|
||||||
|
#endif
|
||||||
|
#include "ESPAsyncTCP.h"
|
||||||
|
#include "SyncClient.h"
|
||||||
|
|
||||||
|
const char* ssid = "**********";
|
||||||
|
const char* password = "************";
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(115200);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||||
|
Serial.printf("WiFi Failed!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Serial.printf("WiFi Connected!\n");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
#ifdef ESP8266
|
||||||
|
ArduinoOTA.begin();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SyncClient client;
|
||||||
|
if(!client.connect("www.google.com", 80)){
|
||||||
|
Serial.println("Connect Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
client.setTimeout(2);
|
||||||
|
if(client.printf("GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n") > 0){
|
||||||
|
while(client.connected() && client.available() == 0){
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
while(client.available()){
|
||||||
|
Serial.write(client.read());
|
||||||
|
}
|
||||||
|
if(client.connected()){
|
||||||
|
client.stop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
client.stop();
|
||||||
|
Serial.println("Send Failed");
|
||||||
|
while(client.connected()) delay(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
#ifdef ESP8266
|
||||||
|
ArduinoOTA.handle();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
19
libraries/ESPAsyncTCP/library.json
Normal file
19
libraries/ESPAsyncTCP/library.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name":"ESPAsyncTCP",
|
||||||
|
"description":"Asynchronous TCP Library for ESP8266",
|
||||||
|
"keywords":"async,tcp",
|
||||||
|
"authors":
|
||||||
|
{
|
||||||
|
"name": "Hristo Gochkov",
|
||||||
|
"maintainer": true
|
||||||
|
},
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/me-no-dev/ESPAsyncTCP.git"
|
||||||
|
},
|
||||||
|
"version": "1.1.1",
|
||||||
|
"license": "LGPL-3.0",
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms":"espressif8266"
|
||||||
|
}
|
||||||
9
libraries/ESPAsyncTCP/library.properties
Normal file
9
libraries/ESPAsyncTCP/library.properties
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
name=ESP AsyncTCP
|
||||||
|
version=1.1.0
|
||||||
|
author=Me-No-Dev
|
||||||
|
maintainer=Me-No-Dev
|
||||||
|
sentence=Async TCP Library for ESP8266 and ESP31B
|
||||||
|
paragraph=Async TCP Library for ESP8266 and ESP31B
|
||||||
|
category=Other
|
||||||
|
url=https://github.com/me-no-dev/ESPAsyncTCP
|
||||||
|
architectures=*
|
||||||
187
libraries/ESPAsyncTCP/src/AsyncPrinter.cpp
Normal file
187
libraries/ESPAsyncTCP/src/AsyncPrinter.cpp
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous TCP library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "AsyncPrinter.h"
|
||||||
|
|
||||||
|
AsyncPrinter::AsyncPrinter()
|
||||||
|
: _client(NULL)
|
||||||
|
, _data_cb(NULL)
|
||||||
|
, _data_arg(NULL)
|
||||||
|
, _close_cb(NULL)
|
||||||
|
, _close_arg(NULL)
|
||||||
|
, _tx_buffer(NULL)
|
||||||
|
, _tx_buffer_size(1460)
|
||||||
|
, next(NULL)
|
||||||
|
{}
|
||||||
|
|
||||||
|
AsyncPrinter::AsyncPrinter(AsyncClient *client, size_t txBufLen)
|
||||||
|
: _client(client)
|
||||||
|
, _data_cb(NULL)
|
||||||
|
, _data_arg(NULL)
|
||||||
|
, _close_cb(NULL)
|
||||||
|
, _close_arg(NULL)
|
||||||
|
, _tx_buffer(NULL)
|
||||||
|
, _tx_buffer_size(txBufLen)
|
||||||
|
, next(NULL)
|
||||||
|
{
|
||||||
|
_attachCallbacks();
|
||||||
|
_tx_buffer = new cbuf(_tx_buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncPrinter::~AsyncPrinter(){
|
||||||
|
_on_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncPrinter::onData(ApDataHandler cb, void *arg){
|
||||||
|
_data_cb = cb;
|
||||||
|
_data_arg = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncPrinter::onClose(ApCloseHandler cb, void *arg){
|
||||||
|
_close_cb = cb;
|
||||||
|
_close_arg = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsyncPrinter::connect(IPAddress ip, uint16_t port){
|
||||||
|
if(_client != NULL && connected())
|
||||||
|
return 0;
|
||||||
|
_client = new AsyncClient();
|
||||||
|
_client->onConnect([](void *obj, AsyncClient *c){ ((AsyncPrinter*)(obj))->_onConnect(c); }, this);
|
||||||
|
if(_client->connect(ip, port)){
|
||||||
|
while(_client->state() < 4)
|
||||||
|
delay(1);
|
||||||
|
return connected();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsyncPrinter::connect(const char *host, uint16_t port){
|
||||||
|
if(_client != NULL && connected())
|
||||||
|
return 0;
|
||||||
|
_client = new AsyncClient();
|
||||||
|
_client->onConnect([](void *obj, AsyncClient *c){ ((AsyncPrinter*)(obj))->_onConnect(c); }, this);
|
||||||
|
if(_client->connect(host, port)){
|
||||||
|
while(_client->state() < 4)
|
||||||
|
delay(1);
|
||||||
|
return connected();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncPrinter::_onConnect(AsyncClient *c){
|
||||||
|
if(_tx_buffer != NULL){
|
||||||
|
cbuf *b = _tx_buffer;
|
||||||
|
_tx_buffer = NULL;
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
_tx_buffer = new cbuf(_tx_buffer_size);
|
||||||
|
_attachCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncPrinter::operator bool(){ return connected(); }
|
||||||
|
|
||||||
|
AsyncPrinter & AsyncPrinter::operator=(const AsyncPrinter &other){
|
||||||
|
if(_client != NULL){
|
||||||
|
_client->close(true);
|
||||||
|
_client = NULL;
|
||||||
|
}
|
||||||
|
_tx_buffer_size = other._tx_buffer_size;
|
||||||
|
if(_tx_buffer != NULL){
|
||||||
|
cbuf *b = _tx_buffer;
|
||||||
|
_tx_buffer = NULL;
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
_tx_buffer = new cbuf(other._tx_buffer_size);
|
||||||
|
_client = other._client;
|
||||||
|
_attachCallbacks();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncPrinter::write(uint8_t data){
|
||||||
|
return write(&data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncPrinter::write(const uint8_t *data, size_t len){
|
||||||
|
if(_tx_buffer == NULL || !connected())
|
||||||
|
return 0;
|
||||||
|
size_t toWrite = 0;
|
||||||
|
size_t toSend = len;
|
||||||
|
while(_tx_buffer->room() < toSend){
|
||||||
|
toWrite = _tx_buffer->room();
|
||||||
|
_tx_buffer->write((const char*)data, toWrite);
|
||||||
|
while(!_client->canSend())
|
||||||
|
delay(0);
|
||||||
|
_sendBuffer();
|
||||||
|
toSend -= toWrite;
|
||||||
|
}
|
||||||
|
_tx_buffer->write((const char*)(data+(len - toSend)), toSend);
|
||||||
|
while(!_client->canSend()) delay(0);
|
||||||
|
_sendBuffer();
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AsyncPrinter::connected(){
|
||||||
|
return (_client != NULL && _client->connected());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncPrinter::close(){
|
||||||
|
if(_client != NULL)
|
||||||
|
_client->close(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncPrinter::_sendBuffer(){
|
||||||
|
size_t available = _tx_buffer->available();
|
||||||
|
if(!connected() || !_client->canSend() || available == 0)
|
||||||
|
return 0;
|
||||||
|
size_t sendable = _client->space();
|
||||||
|
if(sendable < available)
|
||||||
|
available= sendable;
|
||||||
|
char *out = new char[available];
|
||||||
|
_tx_buffer->read(out, available);
|
||||||
|
size_t sent = _client->write(out, available);
|
||||||
|
delete out;
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncPrinter::_onData(void *data, size_t len){
|
||||||
|
if(_data_cb)
|
||||||
|
_data_cb(_data_arg, this, (uint8_t*)data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncPrinter::_on_close(){
|
||||||
|
if(_client != NULL){
|
||||||
|
_client = NULL;
|
||||||
|
}
|
||||||
|
if(_tx_buffer != NULL){
|
||||||
|
cbuf *b = _tx_buffer;
|
||||||
|
_tx_buffer = NULL;
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
if(_close_cb)
|
||||||
|
_close_cb(_close_arg, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncPrinter::_attachCallbacks(){
|
||||||
|
_client->onPoll([](void *obj, AsyncClient* c){ ((AsyncPrinter*)(obj))->_sendBuffer(); }, this);
|
||||||
|
_client->onAck([](void *obj, AsyncClient* c, size_t len, uint32_t time){ ((AsyncPrinter*)(obj))->_sendBuffer(); }, this);
|
||||||
|
_client->onDisconnect([](void *obj, AsyncClient* c){ ((AsyncPrinter*)(obj))->_on_close(); delete c; }, this);
|
||||||
|
_client->onData([](void *obj, AsyncClient* c, void *data, size_t len){ ((AsyncPrinter*)(obj))->_onData(data, len); }, this);
|
||||||
|
}
|
||||||
73
libraries/ESPAsyncTCP/src/AsyncPrinter.h
Normal file
73
libraries/ESPAsyncTCP/src/AsyncPrinter.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous TCP library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ASYNCPRINTER_H_
|
||||||
|
#define ASYNCPRINTER_H_
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "ESPAsyncTCP.h"
|
||||||
|
#include "cbuf.h"
|
||||||
|
|
||||||
|
class AsyncPrinter;
|
||||||
|
|
||||||
|
typedef std::function<void(void*, AsyncPrinter*, uint8_t*, size_t)> ApDataHandler;
|
||||||
|
typedef std::function<void(void*, AsyncPrinter*)> ApCloseHandler;
|
||||||
|
|
||||||
|
class AsyncPrinter: public Print {
|
||||||
|
private:
|
||||||
|
AsyncClient *_client;
|
||||||
|
ApDataHandler _data_cb;
|
||||||
|
void *_data_arg;
|
||||||
|
ApCloseHandler _close_cb;
|
||||||
|
void *_close_arg;
|
||||||
|
cbuf *_tx_buffer;
|
||||||
|
size_t _tx_buffer_size;
|
||||||
|
|
||||||
|
void _onConnect(AsyncClient *c);
|
||||||
|
public:
|
||||||
|
AsyncPrinter *next;
|
||||||
|
|
||||||
|
AsyncPrinter();
|
||||||
|
AsyncPrinter(AsyncClient *client, size_t txBufLen = 1460);
|
||||||
|
virtual ~AsyncPrinter();
|
||||||
|
|
||||||
|
int connect(IPAddress ip, uint16_t port);
|
||||||
|
int connect(const char *host, uint16_t port);
|
||||||
|
|
||||||
|
void onData(ApDataHandler cb, void *arg);
|
||||||
|
void onClose(ApCloseHandler cb, void *arg);
|
||||||
|
|
||||||
|
operator bool();
|
||||||
|
AsyncPrinter & operator=(const AsyncPrinter &other);
|
||||||
|
|
||||||
|
size_t write(uint8_t data);
|
||||||
|
size_t write(const uint8_t *data, size_t len);
|
||||||
|
|
||||||
|
bool connected();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
size_t _sendBuffer();
|
||||||
|
void _onData(void *data, size_t len);
|
||||||
|
void _on_close();
|
||||||
|
void _attachCallbacks();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ASYNCPRINTER_H_ */
|
||||||
1066
libraries/ESPAsyncTCP/src/ESPAsyncTCP.cpp
Normal file
1066
libraries/ESPAsyncTCP/src/ESPAsyncTCP.cpp
Normal file
File diff suppressed because it is too large
Load Diff
249
libraries/ESPAsyncTCP/src/ESPAsyncTCP.h
Normal file
249
libraries/ESPAsyncTCP/src/ESPAsyncTCP.h
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous TCP library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ASYNCTCP_H_
|
||||||
|
#define ASYNCTCP_H_
|
||||||
|
|
||||||
|
#include <async_config.h>
|
||||||
|
#include "IPAddress.h"
|
||||||
|
#include <functional>
|
||||||
|
#include "lwip/init.h"
|
||||||
|
|
||||||
|
class AsyncClient;
|
||||||
|
|
||||||
|
#define ASYNC_MAX_ACK_TIME 5000
|
||||||
|
#define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given)
|
||||||
|
#define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react.
|
||||||
|
|
||||||
|
typedef std::function<void(void*, AsyncClient*)> AcConnectHandler;
|
||||||
|
typedef std::function<void(void*, AsyncClient*, size_t len, uint32_t time)> AcAckHandler;
|
||||||
|
typedef std::function<void(void*, AsyncClient*, int8_t error)> AcErrorHandler;
|
||||||
|
typedef std::function<void(void*, AsyncClient*, void *data, size_t len)> AcDataHandler;
|
||||||
|
typedef std::function<void(void*, AsyncClient*, uint32_t time)> AcTimeoutHandler;
|
||||||
|
|
||||||
|
struct tcp_pcb;
|
||||||
|
struct pbuf;
|
||||||
|
struct ip_addr;
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
struct SSL_;
|
||||||
|
typedef struct SSL_ SSL;
|
||||||
|
struct SSL_CTX_;
|
||||||
|
typedef struct SSL_CTX_ SSL_CTX;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class AsyncClient {
|
||||||
|
protected:
|
||||||
|
friend class AsyncTCPbuffer;
|
||||||
|
tcp_pcb* _pcb;
|
||||||
|
AcConnectHandler _connect_cb;
|
||||||
|
void* _connect_cb_arg;
|
||||||
|
AcConnectHandler _discard_cb;
|
||||||
|
void* _discard_cb_arg;
|
||||||
|
AcAckHandler _sent_cb;
|
||||||
|
void* _sent_cb_arg;
|
||||||
|
AcErrorHandler _error_cb;
|
||||||
|
void* _error_cb_arg;
|
||||||
|
AcDataHandler _recv_cb;
|
||||||
|
void* _recv_cb_arg;
|
||||||
|
AcTimeoutHandler _timeout_cb;
|
||||||
|
void* _timeout_cb_arg;
|
||||||
|
AcConnectHandler _poll_cb;
|
||||||
|
void* _poll_cb_arg;
|
||||||
|
bool _pcb_busy;
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
bool _pcb_secure;
|
||||||
|
bool _handshake_done;
|
||||||
|
#endif
|
||||||
|
uint32_t _pcb_sent_at;
|
||||||
|
bool _close_pcb;
|
||||||
|
bool _ack_pcb;
|
||||||
|
uint32_t _tx_unacked_len;
|
||||||
|
uint32_t _tx_acked_len;
|
||||||
|
uint32_t _tx_unsent_len;
|
||||||
|
uint32_t _rx_ack_len;
|
||||||
|
uint32_t _rx_last_packet;
|
||||||
|
uint32_t _rx_since_timeout;
|
||||||
|
uint32_t _ack_timeout;
|
||||||
|
uint16_t _connect_port;
|
||||||
|
|
||||||
|
int8_t _close();
|
||||||
|
long _connected(void* pcb, long err);
|
||||||
|
void _error(long err);
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
void _ssl_error(int8_t err);
|
||||||
|
#endif
|
||||||
|
long _poll(tcp_pcb* pcb);
|
||||||
|
long _sent(tcp_pcb* pcb, uint16_t len);
|
||||||
|
#if LWIP_VERSION_MAJOR == 1
|
||||||
|
void _dns_found(struct ip_addr *ipaddr);
|
||||||
|
#else
|
||||||
|
void _dns_found(const ip_addr *ipaddr);
|
||||||
|
#endif
|
||||||
|
static long _s_poll(void *arg, struct tcp_pcb *tpcb);
|
||||||
|
static long _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, long err);
|
||||||
|
static void _s_error(void *arg, long err);
|
||||||
|
static long _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len);
|
||||||
|
static long _s_connected(void* arg, void* tpcb, long err);
|
||||||
|
#if LWIP_VERSION_MAJOR == 1
|
||||||
|
static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg);
|
||||||
|
#else
|
||||||
|
static void _s_dns_found(const char *name, const ip_addr *ipaddr, void *arg);
|
||||||
|
#endif
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
static void _s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len);
|
||||||
|
static void _s_handshake(void *arg, struct tcp_pcb *tcp, SSL *ssl);
|
||||||
|
static void _s_ssl_error(void *arg, struct tcp_pcb *tcp, int8_t err);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsyncClient* prev;
|
||||||
|
AsyncClient* next;
|
||||||
|
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
AsyncClient(tcp_pcb* pcb = 0, SSL_CTX * ssl_ctx = NULL);
|
||||||
|
#else
|
||||||
|
AsyncClient(tcp_pcb* pcb = 0);
|
||||||
|
#endif
|
||||||
|
~AsyncClient();
|
||||||
|
|
||||||
|
AsyncClient & operator=(const AsyncClient &other);
|
||||||
|
AsyncClient & operator+=(const AsyncClient &other);
|
||||||
|
|
||||||
|
bool operator==(const AsyncClient &other);
|
||||||
|
|
||||||
|
bool operator!=(const AsyncClient &other) {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
bool connect(IPAddress ip, uint16_t port, bool secure=false);
|
||||||
|
bool connect(const char* host, uint16_t port, bool secure=false);
|
||||||
|
#else
|
||||||
|
bool connect(IPAddress ip, uint16_t port);
|
||||||
|
bool connect(const char* host, uint16_t port);
|
||||||
|
#endif
|
||||||
|
void close(bool now = false);
|
||||||
|
void stop();
|
||||||
|
int8_t abort();
|
||||||
|
bool free();
|
||||||
|
|
||||||
|
bool canSend();//ack is not pending
|
||||||
|
size_t space();
|
||||||
|
size_t add(const char* data, size_t size, uint8_t apiflags=0);//add for sending
|
||||||
|
bool send();//send all data added with the method above
|
||||||
|
size_t ack(size_t len); //ack data that you have not acked using the method below
|
||||||
|
void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData
|
||||||
|
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
SSL *getSSL();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t write(const char* data);
|
||||||
|
size_t write(const char* data, size_t size, uint8_t apiflags=0); //only when canSend() == true
|
||||||
|
|
||||||
|
uint8_t state();
|
||||||
|
bool connecting();
|
||||||
|
bool connected();
|
||||||
|
bool disconnecting();
|
||||||
|
bool disconnected();
|
||||||
|
bool freeable();//disconnected or disconnecting
|
||||||
|
|
||||||
|
uint16_t getMss();
|
||||||
|
uint32_t getRxTimeout();
|
||||||
|
void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds
|
||||||
|
uint32_t getAckTimeout();
|
||||||
|
void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds
|
||||||
|
void setNoDelay(bool nodelay);
|
||||||
|
bool getNoDelay();
|
||||||
|
uint32_t getRemoteAddress();
|
||||||
|
uint16_t getRemotePort();
|
||||||
|
uint32_t getLocalAddress();
|
||||||
|
uint16_t getLocalPort();
|
||||||
|
|
||||||
|
IPAddress remoteIP();
|
||||||
|
uint16_t remotePort();
|
||||||
|
IPAddress localIP();
|
||||||
|
uint16_t localPort();
|
||||||
|
|
||||||
|
void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect
|
||||||
|
void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected
|
||||||
|
void onAck(AcAckHandler cb, void* arg = 0); //ack received
|
||||||
|
void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error
|
||||||
|
void onData(AcDataHandler cb, void* arg = 0); //data received
|
||||||
|
void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout
|
||||||
|
void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected
|
||||||
|
|
||||||
|
const char * errorToString(int8_t error);
|
||||||
|
const char * stateToString();
|
||||||
|
|
||||||
|
long _recv(tcp_pcb* pcb, pbuf* pb, long err);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
typedef std::function<int(void* arg, const char *filename, uint8_t **buf)> AcSSlFileHandler;
|
||||||
|
struct pending_pcb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class AsyncServer {
|
||||||
|
protected:
|
||||||
|
uint16_t _port;
|
||||||
|
IPAddress _addr;
|
||||||
|
bool _noDelay;
|
||||||
|
tcp_pcb* _pcb;
|
||||||
|
AcConnectHandler _connect_cb;
|
||||||
|
void* _connect_cb_arg;
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
struct pending_pcb * _pending;
|
||||||
|
SSL_CTX * _ssl_ctx;
|
||||||
|
AcSSlFileHandler _file_cb;
|
||||||
|
void* _file_cb_arg;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
AsyncServer(IPAddress addr, uint16_t port);
|
||||||
|
AsyncServer(uint16_t port);
|
||||||
|
~AsyncServer();
|
||||||
|
void onClient(AcConnectHandler cb, void* arg);
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
void onSslFileRequest(AcSSlFileHandler cb, void* arg);
|
||||||
|
void beginSecure(const char *cert, const char *private_key_file, const char *password);
|
||||||
|
#endif
|
||||||
|
void begin();
|
||||||
|
void end();
|
||||||
|
void setNoDelay(bool nodelay);
|
||||||
|
bool getNoDelay();
|
||||||
|
uint8_t status();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
long _accept(tcp_pcb* newpcb, long err);
|
||||||
|
static long _s_accept(void *arg, tcp_pcb* newpcb, long err);
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
int _cert(const char *filename, uint8_t **buf);
|
||||||
|
long _poll(tcp_pcb* pcb);
|
||||||
|
long _recv(tcp_pcb *pcb, struct pbuf *pb, long err);
|
||||||
|
static int _s_cert(void *arg, const char *filename, uint8_t **buf);
|
||||||
|
static long _s_poll(void *arg, struct tcp_pcb *tpcb);
|
||||||
|
static long _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, long err);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ASYNCTCP_H_ */
|
||||||
541
libraries/ESPAsyncTCP/src/ESPAsyncTCPbuffer.cpp
Normal file
541
libraries/ESPAsyncTCP/src/ESPAsyncTCPbuffer.cpp
Normal file
@@ -0,0 +1,541 @@
|
|||||||
|
/**
|
||||||
|
* @file ESPAsyncTCPbuffer.cpp
|
||||||
|
* @date 22.01.2016
|
||||||
|
* @author Markus Sattler
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Markus Sattler. All rights reserved.
|
||||||
|
* This file is part of the Asynv TCP for ESP.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "ESPAsyncTCPbuffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
AsyncTCPbuffer::AsyncTCPbuffer(AsyncClient* client) {
|
||||||
|
if(client == NULL) {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] client is null!!!\n");
|
||||||
|
panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
_client = client;
|
||||||
|
_TXbufferWrite = new cbuf(1460);
|
||||||
|
_TXbufferRead = _TXbufferWrite;
|
||||||
|
_RXbuffer = new cbuf(100);
|
||||||
|
_RXmode = ATB_RX_MODE_FREE;
|
||||||
|
_rxSize = 0;
|
||||||
|
_rxTerminator = 0x00;
|
||||||
|
_rxReadBytesPtr = NULL;
|
||||||
|
_rxReadStringPtr = NULL;
|
||||||
|
_cbDisconnect = NULL;
|
||||||
|
|
||||||
|
_cbRX = NULL;
|
||||||
|
_cbDone = NULL;
|
||||||
|
_attachCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncTCPbuffer::~AsyncTCPbuffer() {
|
||||||
|
if(_client) {
|
||||||
|
_client->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_RXbuffer) {
|
||||||
|
delete _RXbuffer;
|
||||||
|
_RXbuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_TXbufferWrite) {
|
||||||
|
// will be deleted in _TXbufferRead chain
|
||||||
|
_TXbufferWrite = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_TXbufferRead) {
|
||||||
|
cbuf * next = _TXbufferRead->next;
|
||||||
|
delete _TXbufferRead;
|
||||||
|
while(next != NULL) {
|
||||||
|
_TXbufferRead = next;
|
||||||
|
next = _TXbufferRead->next;
|
||||||
|
delete _TXbufferRead;
|
||||||
|
}
|
||||||
|
_TXbufferRead = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncTCPbuffer::write(String & data) {
|
||||||
|
return write(data.c_str(), data.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncTCPbuffer::write(uint8_t data) {
|
||||||
|
return write(&data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncTCPbuffer::write(const char* data) {
|
||||||
|
return write((const uint8_t *) data, strlen(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncTCPbuffer::write(const char *data, size_t len) {
|
||||||
|
return write((const uint8_t *) data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write data in to buffer and try to send the data
|
||||||
|
* @param data
|
||||||
|
* @param len
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
size_t AsyncTCPbuffer::write(const uint8_t *data, size_t len) {
|
||||||
|
if(_TXbufferWrite == NULL || _client == NULL || !_client->connected() || data == NULL || len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bytesLeft = len;
|
||||||
|
while(bytesLeft) {
|
||||||
|
size_t w = _TXbufferWrite->write((const char*) data, bytesLeft);
|
||||||
|
bytesLeft -= w;
|
||||||
|
data += w;
|
||||||
|
_sendBuffer();
|
||||||
|
|
||||||
|
// add new buffer since we have more data
|
||||||
|
if(_TXbufferWrite->full() && bytesLeft > 0) {
|
||||||
|
|
||||||
|
// to less ram!!!
|
||||||
|
if(ESP.getFreeHeap() < 4096) {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] run out of Heap can not send all Data!\n");
|
||||||
|
return (len - bytesLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
cbuf * next = new cbuf(1460);
|
||||||
|
|
||||||
|
if(next == NULL) {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] run out of Heap!\n");
|
||||||
|
panic();
|
||||||
|
} else {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] new cbuf\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// add new buffer to chain (current cbuf)
|
||||||
|
_TXbufferWrite->next = next;
|
||||||
|
|
||||||
|
// move ptr for next data
|
||||||
|
_TXbufferWrite = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wait until all data has send out
|
||||||
|
*/
|
||||||
|
void AsyncTCPbuffer::flush() {
|
||||||
|
while(!_TXbufferWrite->empty()) {
|
||||||
|
while(!_client->canSend()) {
|
||||||
|
delay(0);
|
||||||
|
}
|
||||||
|
_sendBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncTCPbuffer::noCallback() {
|
||||||
|
_RXmode = ATB_RX_MODE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncTCPbuffer::readStringUntil(char terminator, String * str, AsyncTCPbufferDoneCb done) {
|
||||||
|
if(_client == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] readStringUntil terminator: %02X\n", terminator);
|
||||||
|
_RXmode = ATB_RX_MODE_NONE;
|
||||||
|
_cbDone = done;
|
||||||
|
_rxReadStringPtr = str;
|
||||||
|
_rxTerminator = terminator;
|
||||||
|
_rxSize = 0;
|
||||||
|
_RXmode = ATB_RX_MODE_TERMINATOR_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void AsyncTCPbuffer::readBytesUntil(char terminator, char *buffer, size_t length, AsyncTCPbufferDoneCb done) {
|
||||||
|
_RXmode = ATB_RX_MODE_NONE;
|
||||||
|
_cbDone = done;
|
||||||
|
_rxReadBytesPtr = (uint8_t *) buffer;
|
||||||
|
_rxTerminator = terminator;
|
||||||
|
_rxSize = length;
|
||||||
|
_RXmode = ATB_RX_MODE_TERMINATOR;
|
||||||
|
_handleRxBuffer(NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncTCPbuffer::readBytesUntil(char terminator, uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done) {
|
||||||
|
readBytesUntil(terminator, (char *) buffer, length, done);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void AsyncTCPbuffer::readBytes(char *buffer, size_t length, AsyncTCPbufferDoneCb done) {
|
||||||
|
if(_client == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] readBytes length: %d\n", length);
|
||||||
|
_RXmode = ATB_RX_MODE_NONE;
|
||||||
|
_cbDone = done;
|
||||||
|
_rxReadBytesPtr = (uint8_t *) buffer;
|
||||||
|
_rxSize = length;
|
||||||
|
_RXmode = ATB_RX_MODE_READ_BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncTCPbuffer::readBytes(uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done) {
|
||||||
|
readBytes((char *) buffer, length, done);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncTCPbuffer::onData(AsyncTCPbufferDataCb cb) {
|
||||||
|
if(_client == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] onData\n");
|
||||||
|
_RXmode = ATB_RX_MODE_NONE;
|
||||||
|
_cbDone = NULL;
|
||||||
|
_cbRX = cb;
|
||||||
|
_RXmode = ATB_RX_MODE_FREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncTCPbuffer::onDisconnect(AsyncTCPbufferDisconnectCb cb) {
|
||||||
|
_cbDisconnect = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress AsyncTCPbuffer::remoteIP() {
|
||||||
|
if(!_client) {
|
||||||
|
return IPAddress(0U);
|
||||||
|
}
|
||||||
|
return _client->remoteIP();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t AsyncTCPbuffer::remotePort() {
|
||||||
|
if(!_client) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return _client->remotePort();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AsyncTCPbuffer::connected() {
|
||||||
|
if(!_client) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _client->connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncTCPbuffer::stop() {
|
||||||
|
|
||||||
|
if(!_client) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_client->stop();
|
||||||
|
_client = NULL;
|
||||||
|
|
||||||
|
if(_cbDone) {
|
||||||
|
switch(_RXmode) {
|
||||||
|
case ATB_RX_MODE_READ_BYTES:
|
||||||
|
case ATB_RX_MODE_TERMINATOR:
|
||||||
|
case ATB_RX_MODE_TERMINATOR_STRING:
|
||||||
|
_RXmode = ATB_RX_MODE_NONE;
|
||||||
|
_cbDone(false, NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_RXmode = ATB_RX_MODE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncTCPbuffer::close() {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///--------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* attachCallbacks to AsyncClient class
|
||||||
|
*/
|
||||||
|
void AsyncTCPbuffer::_attachCallbacks() {
|
||||||
|
if(!_client) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] attachCallbacks\n");
|
||||||
|
|
||||||
|
_client->onPoll([](void *obj, AsyncClient* c) {
|
||||||
|
AsyncTCPbuffer* b = ((AsyncTCPbuffer*)(obj));
|
||||||
|
if((b->_TXbufferRead != NULL) && !b->_TXbufferRead->empty()) {
|
||||||
|
b->_sendBuffer();
|
||||||
|
}
|
||||||
|
// if(!b->_RXbuffer->empty()) {
|
||||||
|
// b->_handleRxBuffer(NULL, 0);
|
||||||
|
// }
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
_client->onAck([](void *obj, AsyncClient* c, size_t len, uint32_t time) {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] onAck\n");
|
||||||
|
((AsyncTCPbuffer*)(obj))->_sendBuffer();
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
_client->onDisconnect([](void *obj, AsyncClient* c) {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] onDisconnect\n");
|
||||||
|
AsyncTCPbuffer* b = ((AsyncTCPbuffer*)(obj));
|
||||||
|
b->_client = NULL;
|
||||||
|
bool del = true;
|
||||||
|
if(b->_cbDisconnect) {
|
||||||
|
del = b->_cbDisconnect(b);
|
||||||
|
}
|
||||||
|
delete c;
|
||||||
|
if(del) {
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
_client->onData([](void *obj, AsyncClient* c, void *buf, size_t len) {
|
||||||
|
AsyncTCPbuffer* b = ((AsyncTCPbuffer*)(obj));
|
||||||
|
b->_rxData((uint8_t *)buf, len);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
_client->onTimeout([](void *obj, AsyncClient* c, uint32_t time){
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] onTimeout\n");
|
||||||
|
c->close();
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] attachCallbacks Done.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* send TX buffer if possible
|
||||||
|
*/
|
||||||
|
void AsyncTCPbuffer::_sendBuffer() {
|
||||||
|
//DEBUG_ASYNC_TCP("[A-TCP] _sendBuffer...\n");
|
||||||
|
size_t available = _TXbufferRead->available();
|
||||||
|
if(available == 0 || _client == NULL || !_client->connected() || !_client->canSend()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while((_client->space() > 0) && (_TXbufferRead->available() > 0) && _client->canSend()) {
|
||||||
|
|
||||||
|
available = _TXbufferRead->available();
|
||||||
|
|
||||||
|
if(available > _client->space()) {
|
||||||
|
available = _client->space();
|
||||||
|
}
|
||||||
|
|
||||||
|
char *out = new char[available];
|
||||||
|
if(out == NULL) {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] to less heap, try later.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read data from buffer
|
||||||
|
_TXbufferRead->peek(out, available);
|
||||||
|
|
||||||
|
// send data
|
||||||
|
size_t send = _client->write((const char*) out, available);
|
||||||
|
if(send != available) {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] write failed send: %d available: %d \n", send, available);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove really send data from buffer
|
||||||
|
_TXbufferRead->remove(send);
|
||||||
|
|
||||||
|
// if buffer is empty and there is a other buffer in chain delete the empty one
|
||||||
|
if(_TXbufferRead->available() == 0 && _TXbufferRead->next != NULL) {
|
||||||
|
cbuf * old = _TXbufferRead;
|
||||||
|
_TXbufferRead = _TXbufferRead->next;
|
||||||
|
delete old;
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] delete cbuf\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
delete out;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called on incoming data
|
||||||
|
* @param buf
|
||||||
|
* @param len
|
||||||
|
*/
|
||||||
|
void AsyncTCPbuffer::_rxData(uint8_t *buf, size_t len) {
|
||||||
|
if(!_client || !_client->connected()) {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] not connected!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!_RXbuffer) {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] _rxData no _RXbuffer!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] _rxData len: %d RXmode: %d\n", len, _RXmode);
|
||||||
|
|
||||||
|
size_t handled = 0;
|
||||||
|
|
||||||
|
if(_RXmode != ATB_RX_MODE_NONE) {
|
||||||
|
handled = _handleRxBuffer((uint8_t *) buf, len);
|
||||||
|
buf += handled;
|
||||||
|
len -= handled;
|
||||||
|
|
||||||
|
// handle as much as possible before using the buffer
|
||||||
|
if(_RXbuffer->empty()) {
|
||||||
|
while(_RXmode != ATB_RX_MODE_NONE && handled != 0 && len > 0) {
|
||||||
|
handled = _handleRxBuffer(buf, len);
|
||||||
|
buf += handled;
|
||||||
|
len -= handled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len > 0) {
|
||||||
|
|
||||||
|
if(_RXbuffer->room() < len) {
|
||||||
|
// to less space
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] _rxData buffer full try resize\n");
|
||||||
|
_RXbuffer->resizeAdd((len + _RXbuffer->room()));
|
||||||
|
|
||||||
|
if(_RXbuffer->room() < len) {
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] _rxData buffer to full can only handle %d!!!\n", _RXbuffer->room());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_RXbuffer->write((const char *) (buf), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_RXbuffer->empty() && _RXmode != ATB_RX_MODE_NONE) {
|
||||||
|
// handle as much as possible data in buffer
|
||||||
|
handled = _handleRxBuffer(NULL, 0);
|
||||||
|
while(_RXmode != ATB_RX_MODE_NONE && handled != 0) {
|
||||||
|
handled = _handleRxBuffer(NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up ram
|
||||||
|
if(_RXbuffer->empty() && _RXbuffer->room() != 100) {
|
||||||
|
_RXbuffer->resize(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
size_t AsyncTCPbuffer::_handleRxBuffer(uint8_t *buf, size_t len) {
|
||||||
|
if(!_client || !_client->connected() || _RXbuffer == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_ASYNC_TCP("[A-TCP] _handleRxBuffer len: %d RXmode: %d\n", len, _RXmode);
|
||||||
|
|
||||||
|
size_t BufferAvailable = _RXbuffer->available();
|
||||||
|
size_t r = 0;
|
||||||
|
|
||||||
|
if(_RXmode == ATB_RX_MODE_NONE) {
|
||||||
|
return 0;
|
||||||
|
} else if(_RXmode == ATB_RX_MODE_FREE) {
|
||||||
|
if(_cbRX == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(BufferAvailable > 0) {
|
||||||
|
uint8_t * b = new uint8_t[BufferAvailable];
|
||||||
|
_RXbuffer->peek((char *) b, BufferAvailable);
|
||||||
|
r = _cbRX(b, BufferAvailable);
|
||||||
|
_RXbuffer->remove(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(r == BufferAvailable && buf && (len > 0)) {
|
||||||
|
return _cbRX(buf, len);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if(_RXmode == ATB_RX_MODE_READ_BYTES) {
|
||||||
|
if(_rxReadBytesPtr == NULL || _cbDone == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t newReadCount = 0;
|
||||||
|
|
||||||
|
if(BufferAvailable) {
|
||||||
|
r = _RXbuffer->read((char *) _rxReadBytesPtr, _rxSize);
|
||||||
|
_rxSize -= r;
|
||||||
|
_rxReadBytesPtr += r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_RXbuffer->empty() && (len > 0) && buf) {
|
||||||
|
r = len;
|
||||||
|
if(r > _rxSize) {
|
||||||
|
r = _rxSize;
|
||||||
|
}
|
||||||
|
memcpy(_rxReadBytesPtr, buf, r);
|
||||||
|
_rxReadBytesPtr += r;
|
||||||
|
_rxSize -= r;
|
||||||
|
newReadCount += r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_rxSize == 0) {
|
||||||
|
_RXmode = ATB_RX_MODE_NONE;
|
||||||
|
_cbDone(true, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add left over bytes to Buffer
|
||||||
|
return newReadCount;
|
||||||
|
|
||||||
|
} else if(_RXmode == ATB_RX_MODE_TERMINATOR) {
|
||||||
|
// TODO implement read terminator non string
|
||||||
|
|
||||||
|
} else if(_RXmode == ATB_RX_MODE_TERMINATOR_STRING) {
|
||||||
|
if(_rxReadStringPtr == NULL || _cbDone == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle Buffer
|
||||||
|
if(BufferAvailable > 0) {
|
||||||
|
while(!_RXbuffer->empty()) {
|
||||||
|
char c = _RXbuffer->read();
|
||||||
|
if(c == _rxTerminator || c == 0x00) {
|
||||||
|
_RXmode = ATB_RX_MODE_NONE;
|
||||||
|
_cbDone(true, _rxReadStringPtr);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
(*_rxReadStringPtr) += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_RXbuffer->empty() && (len > 0) && buf) {
|
||||||
|
size_t newReadCount = 0;
|
||||||
|
while(newReadCount < len) {
|
||||||
|
char c = (char) *buf;
|
||||||
|
buf++;
|
||||||
|
newReadCount++;
|
||||||
|
if(c == _rxTerminator || c == 0x00) {
|
||||||
|
_RXmode = ATB_RX_MODE_NONE;
|
||||||
|
_cbDone(true, _rxReadStringPtr);
|
||||||
|
return newReadCount;
|
||||||
|
} else {
|
||||||
|
(*_rxReadStringPtr) += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newReadCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
118
libraries/ESPAsyncTCP/src/ESPAsyncTCPbuffer.h
Normal file
118
libraries/ESPAsyncTCP/src/ESPAsyncTCPbuffer.h
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* @file ESPAsyncTCPbuffer.h
|
||||||
|
* @date 22.01.2016
|
||||||
|
* @author Markus Sattler
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Markus Sattler. All rights reserved.
|
||||||
|
* This file is part of the Asynv TCP for ESP.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ESPASYNCTCPBUFFER_H_
|
||||||
|
#define ESPASYNCTCPBUFFER_H_
|
||||||
|
|
||||||
|
//#define DEBUG_ASYNC_TCP(...) while(((U0S >> USTXC) & 0x7F) != 0x00); os_printf( __VA_ARGS__ ); while(((U0S >> USTXC) & 0x7F) != 0x00)
|
||||||
|
|
||||||
|
#ifndef DEBUG_ASYNC_TCP
|
||||||
|
#define DEBUG_ASYNC_TCP(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <cbuf.h>
|
||||||
|
|
||||||
|
#include "ESPAsyncTCP.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ATB_RX_MODE_NONE,
|
||||||
|
ATB_RX_MODE_FREE,
|
||||||
|
ATB_RX_MODE_READ_BYTES,
|
||||||
|
ATB_RX_MODE_TERMINATOR,
|
||||||
|
ATB_RX_MODE_TERMINATOR_STRING
|
||||||
|
} atbRxMode_t;
|
||||||
|
|
||||||
|
class AsyncTCPbuffer: public Print {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::function<size_t(uint8_t * payload, size_t length)> AsyncTCPbufferDataCb;
|
||||||
|
typedef std::function<void(bool ok, void * ret)> AsyncTCPbufferDoneCb;
|
||||||
|
typedef std::function<bool(AsyncTCPbuffer * obj)> AsyncTCPbufferDisconnectCb;
|
||||||
|
|
||||||
|
AsyncTCPbuffer(AsyncClient* c);
|
||||||
|
virtual ~AsyncTCPbuffer();
|
||||||
|
|
||||||
|
size_t write(String & data);
|
||||||
|
size_t write(uint8_t data);
|
||||||
|
size_t write(const char* data);
|
||||||
|
size_t write(const char *data, size_t len);
|
||||||
|
size_t write(const uint8_t *data, size_t len);
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
|
||||||
|
void noCallback();
|
||||||
|
|
||||||
|
void readStringUntil(char terminator, String * str, AsyncTCPbufferDoneCb done);
|
||||||
|
|
||||||
|
// TODO implement read terminator non string
|
||||||
|
//void readBytesUntil(char terminator, char *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||||
|
//void readBytesUntil(char terminator, uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||||
|
|
||||||
|
void readBytes(char *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||||
|
void readBytes(uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||||
|
|
||||||
|
// TODO implement
|
||||||
|
// void setTimeout(size_t timeout);
|
||||||
|
|
||||||
|
void onData(AsyncTCPbufferDataCb cb);
|
||||||
|
void onDisconnect(AsyncTCPbufferDisconnectCb cb);
|
||||||
|
|
||||||
|
IPAddress remoteIP();
|
||||||
|
uint16_t remotePort();
|
||||||
|
IPAddress localIP();
|
||||||
|
uint16_t localPort();
|
||||||
|
|
||||||
|
bool connected();
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AsyncClient* _client;
|
||||||
|
cbuf * _TXbufferRead;
|
||||||
|
cbuf * _TXbufferWrite;
|
||||||
|
cbuf * _RXbuffer;
|
||||||
|
atbRxMode_t _RXmode;
|
||||||
|
size_t _rxSize;
|
||||||
|
char _rxTerminator;
|
||||||
|
uint8_t * _rxReadBytesPtr;
|
||||||
|
String * _rxReadStringPtr;
|
||||||
|
|
||||||
|
AsyncTCPbufferDataCb _cbRX;
|
||||||
|
AsyncTCPbufferDoneCb _cbDone;
|
||||||
|
AsyncTCPbufferDisconnectCb _cbDisconnect;
|
||||||
|
|
||||||
|
void _attachCallbacks();
|
||||||
|
void _sendBuffer();
|
||||||
|
void _on_close();
|
||||||
|
void _rxData(uint8_t *buf, size_t len);
|
||||||
|
size_t _handleRxBuffer(uint8_t *buf, size_t len);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ESPASYNCTCPBUFFER_H_ */
|
||||||
286
libraries/ESPAsyncTCP/src/SyncClient.cpp
Normal file
286
libraries/ESPAsyncTCP/src/SyncClient.cpp
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous TCP library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "SyncClient.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "ESPAsyncTCP.h"
|
||||||
|
#include "cbuf.h"
|
||||||
|
|
||||||
|
|
||||||
|
SyncClient::SyncClient(size_t txBufLen)
|
||||||
|
: _client(NULL)
|
||||||
|
, _tx_buffer(NULL)
|
||||||
|
, _tx_buffer_size(txBufLen)
|
||||||
|
, _rx_buffer(NULL)
|
||||||
|
{}
|
||||||
|
|
||||||
|
SyncClient::SyncClient(AsyncClient *client, size_t txBufLen)
|
||||||
|
: _client(client)
|
||||||
|
, _tx_buffer(new cbuf(txBufLen))
|
||||||
|
, _tx_buffer_size(txBufLen)
|
||||||
|
, _rx_buffer(NULL)
|
||||||
|
{
|
||||||
|
_attachCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncClient::~SyncClient(){
|
||||||
|
if(_tx_buffer != NULL){
|
||||||
|
cbuf *b = _tx_buffer;
|
||||||
|
_tx_buffer = NULL;
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
while(_rx_buffer != NULL){
|
||||||
|
cbuf *b = _rx_buffer;
|
||||||
|
_rx_buffer = _rx_buffer->next;
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
int SyncClient::connect(IPAddress ip, uint16_t port, bool secure){
|
||||||
|
#else
|
||||||
|
int SyncClient::connect(IPAddress ip, uint16_t port){
|
||||||
|
#endif
|
||||||
|
if(_client != NULL && connected())
|
||||||
|
return 0;
|
||||||
|
_client = new AsyncClient();
|
||||||
|
_client->onConnect([](void *obj, AsyncClient *c){ ((SyncClient*)(obj))->_onConnect(c); }, this);
|
||||||
|
_attachCallbacks_Disconnect();
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
if(_client->connect(ip, port, secure)){
|
||||||
|
#else
|
||||||
|
if(_client->connect(ip, port)){
|
||||||
|
#endif
|
||||||
|
while(_client != NULL && !_client->connected() && !_client->disconnecting())
|
||||||
|
delay(1);
|
||||||
|
return connected();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
int SyncClient::connect(const char *host, uint16_t port, bool secure){
|
||||||
|
#else
|
||||||
|
int SyncClient::connect(const char *host, uint16_t port){
|
||||||
|
#endif
|
||||||
|
if(_client != NULL && connected()){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_client = new AsyncClient();
|
||||||
|
_client->onConnect([](void *obj, AsyncClient *c){ ((SyncClient*)(obj))->_onConnect(c); }, this);
|
||||||
|
_attachCallbacks_Disconnect();
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
if(_client->connect(host, port, secure)){
|
||||||
|
#else
|
||||||
|
if(_client->connect(host, port)){
|
||||||
|
#endif
|
||||||
|
while(_client != NULL && !_client->connected() && !_client->disconnecting())
|
||||||
|
delay(1);
|
||||||
|
return connected();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncClient & SyncClient::operator=(const SyncClient &other){
|
||||||
|
if(_client != NULL){
|
||||||
|
_client->abort();
|
||||||
|
_client->free();
|
||||||
|
_client = NULL;
|
||||||
|
}
|
||||||
|
_tx_buffer_size = other._tx_buffer_size;
|
||||||
|
if(_tx_buffer != NULL){
|
||||||
|
cbuf *b = _tx_buffer;
|
||||||
|
_tx_buffer = NULL;
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
while(_rx_buffer != NULL){
|
||||||
|
cbuf *b = _rx_buffer;
|
||||||
|
_rx_buffer = b->next;
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
_tx_buffer = new cbuf(other._tx_buffer_size);
|
||||||
|
_client = other._client;
|
||||||
|
_attachCallbacks();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncClient::setTimeout(uint32_t seconds){
|
||||||
|
if(_client != NULL)
|
||||||
|
_client->setRxTimeout(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SyncClient::status(){
|
||||||
|
if(_client == NULL)
|
||||||
|
return 0;
|
||||||
|
return _client->state();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SyncClient::connected(){
|
||||||
|
return (_client != NULL && _client->connected());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncClient::stop(){
|
||||||
|
if(_client != NULL)
|
||||||
|
_client->close(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SyncClient::_sendBuffer(){
|
||||||
|
size_t available = _tx_buffer->available();
|
||||||
|
if(!connected() || !_client->canSend() || available == 0)
|
||||||
|
return 0;
|
||||||
|
size_t sendable = _client->space();
|
||||||
|
if(sendable < available)
|
||||||
|
available= sendable;
|
||||||
|
char *out = new char[available];
|
||||||
|
_tx_buffer->read(out, available);
|
||||||
|
size_t sent = _client->write(out, available);
|
||||||
|
delete[] out;
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncClient::_onData(void *data, size_t len){
|
||||||
|
_client->ackLater();
|
||||||
|
cbuf *b = new cbuf(len+1);
|
||||||
|
if(b != NULL){
|
||||||
|
b->write((const char *)data, len);
|
||||||
|
if(_rx_buffer == NULL)
|
||||||
|
_rx_buffer = b;
|
||||||
|
else {
|
||||||
|
cbuf *p = _rx_buffer;
|
||||||
|
while(p->next != NULL)
|
||||||
|
p = p->next;
|
||||||
|
p->next = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncClient::_onDisconnect(){
|
||||||
|
if(_client != NULL){
|
||||||
|
_client = NULL;
|
||||||
|
}
|
||||||
|
if(_tx_buffer != NULL){
|
||||||
|
cbuf *b = _tx_buffer;
|
||||||
|
_tx_buffer = NULL;
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncClient::_onConnect(AsyncClient *c){
|
||||||
|
_client = c;
|
||||||
|
if(_tx_buffer != NULL){
|
||||||
|
cbuf *b = _tx_buffer;
|
||||||
|
_tx_buffer = NULL;
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
_tx_buffer = new cbuf(_tx_buffer_size);
|
||||||
|
_attachCallbacks_AfterConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncClient::_attachCallbacks(){
|
||||||
|
_attachCallbacks_Disconnect();
|
||||||
|
_attachCallbacks_AfterConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncClient::_attachCallbacks_AfterConnected(){
|
||||||
|
_client->onAck([](void *obj, AsyncClient* c, size_t len, uint32_t time){ ((SyncClient*)(obj))->_sendBuffer(); }, this);
|
||||||
|
_client->onData([](void *obj, AsyncClient* c, void *data, size_t len){ ((SyncClient*)(obj))->_onData(data, len); }, this);
|
||||||
|
_client->onTimeout([](void *obj, AsyncClient* c, uint32_t time){ c->close(); }, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncClient::_attachCallbacks_Disconnect(){
|
||||||
|
_client->onDisconnect([](void *obj, AsyncClient* c){ ((SyncClient*)(obj))->_onDisconnect(); delete c; }, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SyncClient::write(uint8_t data){
|
||||||
|
return write(&data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SyncClient::write(const uint8_t *data, size_t len){
|
||||||
|
if(_tx_buffer == NULL || !connected()){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t toWrite = 0;
|
||||||
|
size_t toSend = len;
|
||||||
|
while(_tx_buffer->room() < toSend){
|
||||||
|
toWrite = _tx_buffer->room();
|
||||||
|
_tx_buffer->write((const char*)data, toWrite);
|
||||||
|
while(!_client->canSend() && connected())
|
||||||
|
delay(0);
|
||||||
|
_sendBuffer();
|
||||||
|
toSend -= toWrite;
|
||||||
|
}
|
||||||
|
_tx_buffer->write((const char*)(data+(len - toSend)), toSend);
|
||||||
|
if(_client->canSend() && connected())
|
||||||
|
_sendBuffer();
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SyncClient::available(){
|
||||||
|
if(_rx_buffer == NULL) return 0;
|
||||||
|
size_t a = 0;
|
||||||
|
cbuf *b = _rx_buffer;
|
||||||
|
while(b != NULL){
|
||||||
|
a += b->available();
|
||||||
|
b = b->next;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SyncClient::peek(){
|
||||||
|
if(_rx_buffer == NULL) return -1;
|
||||||
|
return _rx_buffer->peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SyncClient::read(uint8_t *data, size_t len){
|
||||||
|
if(_rx_buffer == NULL) return -1;
|
||||||
|
|
||||||
|
size_t readSoFar = 0;
|
||||||
|
while(_rx_buffer != NULL && (len - readSoFar) >= _rx_buffer->available()){
|
||||||
|
cbuf *b = _rx_buffer;
|
||||||
|
_rx_buffer = _rx_buffer->next;
|
||||||
|
size_t toRead = b->available();
|
||||||
|
readSoFar += b->read((char*)(data+readSoFar), toRead);
|
||||||
|
if(connected()){
|
||||||
|
_client->ack(b->size() - 1);
|
||||||
|
}
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
if(_rx_buffer != NULL && readSoFar < len){
|
||||||
|
readSoFar += _rx_buffer->read((char*)(data+readSoFar), (len - readSoFar));
|
||||||
|
}
|
||||||
|
return readSoFar;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SyncClient::read(){
|
||||||
|
uint8_t res = 0;
|
||||||
|
if(read(&res, 1) != 1)
|
||||||
|
return -1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncClient::flush(){
|
||||||
|
if(_tx_buffer == NULL || !connected())
|
||||||
|
return;
|
||||||
|
if(_tx_buffer->available()){
|
||||||
|
while(!_client->canSend() && connected())
|
||||||
|
delay(0);
|
||||||
|
_sendBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
82
libraries/ESPAsyncTCP/src/SyncClient.h
Normal file
82
libraries/ESPAsyncTCP/src/SyncClient.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous TCP library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SYNCCLIENT_H_
|
||||||
|
#define SYNCCLIENT_H_
|
||||||
|
|
||||||
|
#include "Client.h"
|
||||||
|
#include <async_config.h>
|
||||||
|
class cbuf;
|
||||||
|
class AsyncClient;
|
||||||
|
|
||||||
|
class SyncClient: public Client {
|
||||||
|
private:
|
||||||
|
AsyncClient *_client;
|
||||||
|
cbuf *_tx_buffer;
|
||||||
|
size_t _tx_buffer_size;
|
||||||
|
cbuf *_rx_buffer;
|
||||||
|
|
||||||
|
size_t _sendBuffer();
|
||||||
|
void _onData(void *data, size_t len);
|
||||||
|
void _onConnect(AsyncClient *c);
|
||||||
|
void _onDisconnect();
|
||||||
|
void _attachCallbacks();
|
||||||
|
void _attachCallbacks_Disconnect();
|
||||||
|
void _attachCallbacks_AfterConnected();
|
||||||
|
|
||||||
|
public:
|
||||||
|
SyncClient(size_t txBufLen = 1460);
|
||||||
|
SyncClient(AsyncClient *client, size_t txBufLen = 1460);
|
||||||
|
virtual ~SyncClient();
|
||||||
|
|
||||||
|
operator bool(){ return connected(); }
|
||||||
|
SyncClient & operator=(const SyncClient &other);
|
||||||
|
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
int connect(IPAddress ip, uint16_t port, bool secure);
|
||||||
|
int connect(const char *host, uint16_t port, bool secure);
|
||||||
|
int connect(IPAddress ip, uint16_t port){
|
||||||
|
return connect(ip, port, false);
|
||||||
|
}
|
||||||
|
int connect(const char *host, uint16_t port){
|
||||||
|
return connect(host, port, false);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int connect(IPAddress ip, uint16_t port);
|
||||||
|
int connect(const char *host, uint16_t port);
|
||||||
|
#endif
|
||||||
|
void setTimeout(uint32_t seconds);
|
||||||
|
|
||||||
|
uint8_t status();
|
||||||
|
uint8_t connected();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
size_t write(uint8_t data);
|
||||||
|
size_t write(const uint8_t *data, size_t len);
|
||||||
|
|
||||||
|
int available();
|
||||||
|
int peek();
|
||||||
|
int read();
|
||||||
|
int read(uint8_t *data, size_t len);
|
||||||
|
void flush();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SYNCCLIENT_H_ */
|
||||||
11
libraries/ESPAsyncTCP/src/async_config.h
Normal file
11
libraries/ESPAsyncTCP/src/async_config.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef LIBRARIES_ESPASYNCTCP_SRC_ASYNC_CONFIG_H_
|
||||||
|
#define LIBRARIES_ESPASYNCTCP_SRC_ASYNC_CONFIG_H_
|
||||||
|
|
||||||
|
#ifndef ASYNC_TCP_SSL_ENABLED
|
||||||
|
#define ASYNC_TCP_SSL_ENABLED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ASYNC_TCP_DEBUG(...) //ets_printf(__VA_ARGS__)
|
||||||
|
#define TCP_SSL_DEBUG(...) //ets_printf(__VA_ARGS__)
|
||||||
|
|
||||||
|
#endif /* LIBRARIES_ESPASYNCTCP_SRC_ASYNC_CONFIG_H_ */
|
||||||
586
libraries/ESPAsyncTCP/src/tcp_axtls.c
Normal file
586
libraries/ESPAsyncTCP/src/tcp_axtls.c
Normal file
@@ -0,0 +1,586 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous TCP library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Compatibility for AxTLS with LWIP raw tcp mode (http://lwip.wikia.com/wiki/Raw/TCP)
|
||||||
|
* Original Code and Inspiration: Slavey Karadzhov
|
||||||
|
*/
|
||||||
|
#include <async_config.h>
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/tcp.h"
|
||||||
|
#include "lwip/inet.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <tcp_axtls.h>
|
||||||
|
|
||||||
|
uint8_t * default_private_key = NULL;
|
||||||
|
uint16_t default_private_key_len = 0;
|
||||||
|
|
||||||
|
uint8_t * default_certificate = NULL;
|
||||||
|
uint16_t default_certificate_len = 0;
|
||||||
|
|
||||||
|
static uint8_t _tcp_ssl_has_client = 0;
|
||||||
|
|
||||||
|
SSL_CTX * tcp_ssl_new_server_ctx(const char *cert, const char *private_key_file, const char *password){
|
||||||
|
uint32_t options = SSL_CONNECT_IN_PARTS;
|
||||||
|
SSL_CTX *ssl_ctx;
|
||||||
|
|
||||||
|
if(private_key_file){
|
||||||
|
options |= SSL_NO_DEFAULT_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_SVR_SESS)) == NULL){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: failed to allocate context\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (private_key_file){
|
||||||
|
int obj_type = SSL_OBJ_RSA_KEY;
|
||||||
|
if (strstr(private_key_file, ".p8"))
|
||||||
|
obj_type = SSL_OBJ_PKCS8;
|
||||||
|
else if (strstr(private_key_file, ".p12"))
|
||||||
|
obj_type = SSL_OBJ_PKCS12;
|
||||||
|
|
||||||
|
if (ssl_obj_load(ssl_ctx, obj_type, private_key_file, password)){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: load private key '%s' failed\n", private_key_file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cert){
|
||||||
|
if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert, NULL)){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: load certificate '%s' failed\n", cert);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ssl_ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tcp_ssl_pcb {
|
||||||
|
struct tcp_pcb *tcp;
|
||||||
|
int fd;
|
||||||
|
SSL_CTX* ssl_ctx;
|
||||||
|
SSL *ssl;
|
||||||
|
uint8_t type;
|
||||||
|
int handshake;
|
||||||
|
void * arg;
|
||||||
|
tcp_ssl_data_cb_t on_data;
|
||||||
|
tcp_ssl_handshake_cb_t on_handshake;
|
||||||
|
tcp_ssl_error_cb_t on_error;
|
||||||
|
int last_wr;
|
||||||
|
struct pbuf *tcp_pbuf;
|
||||||
|
int pbuf_offset;
|
||||||
|
struct tcp_ssl_pcb * next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct tcp_ssl_pcb tcp_ssl_t;
|
||||||
|
|
||||||
|
static tcp_ssl_t * tcp_ssl_array = NULL;
|
||||||
|
static int tcp_ssl_next_fd = 0;
|
||||||
|
|
||||||
|
uint8_t tcp_ssl_has_client(){
|
||||||
|
return _tcp_ssl_has_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_ssl_t * tcp_ssl_new(struct tcp_pcb *tcp) {
|
||||||
|
|
||||||
|
if(tcp_ssl_next_fd < 0){
|
||||||
|
tcp_ssl_next_fd = 0;//overflow
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_ssl_t * new_item = (tcp_ssl_t*)malloc(sizeof(tcp_ssl_t));
|
||||||
|
if(!new_item){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_new: failed to allocate tcp_ssl\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_item->tcp = tcp;
|
||||||
|
new_item->handshake = SSL_NOT_OK;
|
||||||
|
new_item->arg = NULL;
|
||||||
|
new_item->on_data = NULL;
|
||||||
|
new_item->on_handshake = NULL;
|
||||||
|
new_item->on_error = NULL;
|
||||||
|
new_item->tcp_pbuf = NULL;
|
||||||
|
new_item->pbuf_offset = 0;
|
||||||
|
new_item->next = NULL;
|
||||||
|
new_item->ssl_ctx = NULL;
|
||||||
|
new_item->ssl = NULL;
|
||||||
|
new_item->type = TCP_SSL_TYPE_CLIENT;
|
||||||
|
new_item->fd = tcp_ssl_next_fd++;
|
||||||
|
|
||||||
|
if(tcp_ssl_array == NULL){
|
||||||
|
tcp_ssl_array = new_item;
|
||||||
|
} else {
|
||||||
|
tcp_ssl_t * item = tcp_ssl_array;
|
||||||
|
while(item->next != NULL)
|
||||||
|
item = item->next;
|
||||||
|
item->next = new_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_new: %d\n", new_item->fd);
|
||||||
|
return new_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_ssl_t* tcp_ssl_get(struct tcp_pcb *tcp) {
|
||||||
|
if(tcp == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tcp_ssl_t * item = tcp_ssl_array;
|
||||||
|
while(item && item->tcp != tcp){
|
||||||
|
item = item->next;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_ssl_new_client(struct tcp_pcb *tcp){
|
||||||
|
SSL_CTX* ssl_ctx;
|
||||||
|
tcp_ssl_t * tcp_ssl;
|
||||||
|
|
||||||
|
if(tcp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tcp_ssl_get(tcp) != NULL){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_new_client: tcp_ssl already exists\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl_ctx = ssl_ctx_new(SSL_CONNECT_IN_PARTS | SSL_SERVER_VERIFY_LATER, 1);
|
||||||
|
if(ssl_ctx == NULL){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_new_client: failed to allocate ssl context\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_ssl = tcp_ssl_new(tcp);
|
||||||
|
if(tcp_ssl == NULL){
|
||||||
|
ssl_ctx_free(ssl_ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_ssl->ssl_ctx = ssl_ctx;
|
||||||
|
|
||||||
|
tcp_ssl->ssl = ssl_client_new(ssl_ctx, tcp_ssl->fd, NULL, 0, NULL);
|
||||||
|
if(tcp_ssl->ssl == NULL){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_new_client: failed to allocate ssl\n");
|
||||||
|
tcp_ssl_free(tcp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tcp_ssl->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_ssl_new_server(struct tcp_pcb *tcp, SSL_CTX* ssl_ctx){
|
||||||
|
tcp_ssl_t * tcp_ssl;
|
||||||
|
|
||||||
|
if(tcp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ssl_ctx == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tcp_ssl_get(tcp) != NULL){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_new_server: tcp_ssl already exists\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_ssl = tcp_ssl_new(tcp);
|
||||||
|
if(tcp_ssl == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_ssl->type = TCP_SSL_TYPE_SERVER;
|
||||||
|
tcp_ssl->ssl_ctx = ssl_ctx;
|
||||||
|
|
||||||
|
_tcp_ssl_has_client = 1;
|
||||||
|
tcp_ssl->ssl = ssl_server_new(ssl_ctx, tcp_ssl->fd);
|
||||||
|
if(tcp_ssl->ssl == NULL){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_new_server: failed to allocate ssl\n");
|
||||||
|
tcp_ssl_free(tcp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tcp_ssl->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_ssl_free(struct tcp_pcb *tcp) {
|
||||||
|
|
||||||
|
if(tcp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_ssl_t * item = tcp_ssl_array;
|
||||||
|
|
||||||
|
if(item->tcp == tcp){
|
||||||
|
tcp_ssl_array = tcp_ssl_array->next;
|
||||||
|
if(item->tcp_pbuf != NULL){
|
||||||
|
pbuf_free(item->tcp_pbuf);
|
||||||
|
}
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_free: %d\n", item->fd);
|
||||||
|
if(item->ssl)
|
||||||
|
ssl_free(item->ssl);
|
||||||
|
if(item->type == TCP_SSL_TYPE_CLIENT && item->ssl_ctx)
|
||||||
|
ssl_ctx_free(item->ssl_ctx);
|
||||||
|
if(item->type == TCP_SSL_TYPE_SERVER)
|
||||||
|
_tcp_ssl_has_client = 0;
|
||||||
|
free(item);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(item->next && item->next->tcp != tcp)
|
||||||
|
item = item->next;
|
||||||
|
|
||||||
|
if(item->next == NULL){
|
||||||
|
return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;//item not found
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_ssl_t * i = item->next;
|
||||||
|
item->next = i->next;
|
||||||
|
if(i->tcp_pbuf != NULL){
|
||||||
|
pbuf_free(i->tcp_pbuf);
|
||||||
|
}
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_free: %d\n", i->fd);
|
||||||
|
if(i->ssl)
|
||||||
|
ssl_free(i->ssl);
|
||||||
|
if(i->type == TCP_SSL_TYPE_CLIENT && i->ssl_ctx)
|
||||||
|
ssl_ctx_free(i->ssl_ctx);
|
||||||
|
if(i->type == TCP_SSL_TYPE_SERVER)
|
||||||
|
_tcp_ssl_has_client = 0;
|
||||||
|
free(i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef AXTLS_2_0_0_SNDBUF
|
||||||
|
int tcp_ssl_sndbuf(struct tcp_pcb *tcp){
|
||||||
|
int expected;
|
||||||
|
int available;
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
if(tcp == NULL) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||||
|
if(!tcp_ssl){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_ssl is NULL\n");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
available = tcp_sndbuf(tcp);
|
||||||
|
if(!available){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_sndbuf is zero\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
result = available;
|
||||||
|
while((expected = ssl_calculate_write_length(tcp_ssl->ssl, result)) > available){
|
||||||
|
result -= (expected - available) + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(expected > 0){
|
||||||
|
//TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_sndbuf is %d from %d\n", result, available);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len) {
|
||||||
|
if(tcp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||||
|
if(!tcp_ssl){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_write: tcp_ssl is NULL\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
tcp_ssl->last_wr = 0;
|
||||||
|
|
||||||
|
#ifdef AXTLS_2_0_0_SNDBUF
|
||||||
|
int expected_len = ssl_calculate_write_length(tcp_ssl->ssl, len);
|
||||||
|
int available_len = tcp_sndbuf(tcp);
|
||||||
|
if(expected_len < 0 || expected_len > available_len){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_write: data will not fit! %u < %d(%u)\r\n", available_len, expected_len, len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int rc = ssl_write(tcp_ssl->ssl, data, len);
|
||||||
|
|
||||||
|
//TCP_SSL_DEBUG("tcp_ssl_write: %u -> %d (%d)\r\n", len, tcp_ssl->last_wr, rc);
|
||||||
|
|
||||||
|
if (rc < 0){
|
||||||
|
if(rc != SSL_CLOSE_NOTIFY) {
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_write error: %d\r\n", rc);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tcp_ssl->last_wr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads data from the SSL over TCP stream. Returns decrypted data.
|
||||||
|
* @param tcp_pcb *tcp - pointer to the raw tcp object
|
||||||
|
* @param pbuf *p - pointer to the buffer with the TCP packet data
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
* 0 - when everything is fine but there are no symbols to process yet
|
||||||
|
* < 0 - when there is an error
|
||||||
|
* > 0 - the length of the clear text characters that were read
|
||||||
|
*/
|
||||||
|
int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) {
|
||||||
|
if(tcp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tcp_ssl_t* fd_data = NULL;
|
||||||
|
|
||||||
|
int read_bytes = 0;
|
||||||
|
int total_bytes = 0;
|
||||||
|
uint8_t *read_buf;
|
||||||
|
|
||||||
|
fd_data = tcp_ssl_get(tcp);
|
||||||
|
if(fd_data == NULL) {
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_read: tcp_ssl is NULL\n");
|
||||||
|
return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p == NULL) {
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_read:p == NULL\n");
|
||||||
|
return ERR_TCP_SSL_INVALID_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TCP_SSL_DEBUG("READY TO READ SOME DATA\n");
|
||||||
|
|
||||||
|
fd_data->tcp_pbuf = p;
|
||||||
|
fd_data->pbuf_offset = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
read_bytes = ssl_read(fd_data->ssl, &read_buf);
|
||||||
|
//TCP_SSL_DEBUG("tcp_ssl_ssl_read: %d\n", read_bytes);
|
||||||
|
if(read_bytes < SSL_OK) {
|
||||||
|
if(read_bytes != SSL_CLOSE_NOTIFY) {
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_read: read error: %d\n", read_bytes);
|
||||||
|
}
|
||||||
|
total_bytes = read_bytes;
|
||||||
|
break;
|
||||||
|
} else if(read_bytes > 0){
|
||||||
|
if(fd_data->on_data){
|
||||||
|
fd_data->on_data(fd_data->arg, tcp, read_buf, read_bytes);
|
||||||
|
}
|
||||||
|
total_bytes+= read_bytes;
|
||||||
|
} else {
|
||||||
|
if(fd_data->handshake != SSL_OK) {
|
||||||
|
fd_data->handshake = ssl_handshake_status(fd_data->ssl);
|
||||||
|
if(fd_data->handshake == SSL_OK){
|
||||||
|
//TCP_SSL_DEBUG("tcp_ssl_read: handshake OK\n");
|
||||||
|
if(fd_data->on_handshake)
|
||||||
|
fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data->ssl);
|
||||||
|
} else if(fd_data->handshake != SSL_NOT_OK){
|
||||||
|
TCP_SSL_DEBUG("tcp_ssl_read: handshake error: %d\n", fd_data->handshake);
|
||||||
|
if(fd_data->on_error)
|
||||||
|
fd_data->on_error(fd_data->arg, fd_data->tcp, fd_data->handshake);
|
||||||
|
return fd_data->handshake;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (p->tot_len - fd_data->pbuf_offset > 0);
|
||||||
|
|
||||||
|
tcp_recved(tcp, p->tot_len);
|
||||||
|
pbuf_free(p);
|
||||||
|
|
||||||
|
return total_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL * tcp_ssl_get_ssl(struct tcp_pcb *tcp){
|
||||||
|
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||||
|
if(tcp_ssl){
|
||||||
|
return tcp_ssl->ssl;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tcp_ssl_has(struct tcp_pcb *tcp){
|
||||||
|
return tcp_ssl_get(tcp) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcp_ssl_is_server(struct tcp_pcb *tcp){
|
||||||
|
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||||
|
if(tcp_ssl){
|
||||||
|
return tcp_ssl->type;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcp_ssl_arg(struct tcp_pcb *tcp, void * arg){
|
||||||
|
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||||
|
if(item) {
|
||||||
|
item->arg = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcp_ssl_data(struct tcp_pcb *tcp, tcp_ssl_data_cb_t arg){
|
||||||
|
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||||
|
if(item) {
|
||||||
|
item->on_data = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcp_ssl_handshake(struct tcp_pcb *tcp, tcp_ssl_handshake_cb_t arg){
|
||||||
|
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||||
|
if(item) {
|
||||||
|
item->on_handshake = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg){
|
||||||
|
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||||
|
if(item) {
|
||||||
|
item->on_error = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static tcp_ssl_file_cb_t _tcp_ssl_file_cb = NULL;
|
||||||
|
static void * _tcp_ssl_file_arg = NULL;
|
||||||
|
|
||||||
|
void tcp_ssl_file(tcp_ssl_file_cb_t cb, void * arg){
|
||||||
|
_tcp_ssl_file_cb = cb;
|
||||||
|
_tcp_ssl_file_arg = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ax_get_file(const char *filename, uint8_t **buf) {
|
||||||
|
//TCP_SSL_DEBUG("ax_get_file: %s\n", filename);
|
||||||
|
if(_tcp_ssl_file_cb){
|
||||||
|
return _tcp_ssl_file_cb(_tcp_ssl_file_arg, filename, buf);
|
||||||
|
}
|
||||||
|
*buf = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_ssl_t* tcp_ssl_get_by_fd(int fd) {
|
||||||
|
tcp_ssl_t * item = tcp_ssl_array;
|
||||||
|
while(item && item->fd != fd){
|
||||||
|
item = item->next;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The LWIP tcp raw version of the SOCKET_WRITE(A, B, C)
|
||||||
|
*/
|
||||||
|
int ax_port_write(int fd, uint8_t *data, uint16_t len) {
|
||||||
|
tcp_ssl_t *fd_data = NULL;
|
||||||
|
int tcp_len = 0;
|
||||||
|
err_t err = ERR_OK;
|
||||||
|
|
||||||
|
//TCP_SSL_DEBUG("ax_port_write: %d, %d\n", fd, len);
|
||||||
|
|
||||||
|
fd_data = tcp_ssl_get_by_fd(fd);
|
||||||
|
if(fd_data == NULL) {
|
||||||
|
//TCP_SSL_DEBUG("ax_port_write: tcp_ssl[%d] is NULL\n", fd);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data == NULL || len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcp_sndbuf(fd_data->tcp) < len) {
|
||||||
|
tcp_len = tcp_sndbuf(fd_data->tcp);
|
||||||
|
if(tcp_len == 0) {
|
||||||
|
TCP_SSL_DEBUG("ax_port_write: tcp_sndbuf is zero: %d\n", len);
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tcp_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcp_len > 2 * fd_data->tcp->mss) {
|
||||||
|
tcp_len = 2 * fd_data->tcp->mss;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tcp_write(fd_data->tcp, data, tcp_len, TCP_WRITE_FLAG_COPY);
|
||||||
|
if(err < ERR_OK) {
|
||||||
|
if (err == ERR_MEM) {
|
||||||
|
TCP_SSL_DEBUG("ax_port_write: No memory %d (%d)\n", tcp_len, len);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
TCP_SSL_DEBUG("ax_port_write: tcp_write error: %d\n", err);
|
||||||
|
return err;
|
||||||
|
} else if (err == ERR_OK) {
|
||||||
|
//TCP_SSL_DEBUG("ax_port_write: tcp_output: %d / %d\n", tcp_len, len);
|
||||||
|
err = tcp_output(fd_data->tcp);
|
||||||
|
if(err != ERR_OK) {
|
||||||
|
TCP_SSL_DEBUG("ax_port_write: tcp_output err: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fd_data->last_wr += tcp_len;
|
||||||
|
|
||||||
|
return tcp_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The LWIP tcp raw version of the SOCKET_READ(A, B, C)
|
||||||
|
*/
|
||||||
|
int ax_port_read(int fd, uint8_t *data, int len) {
|
||||||
|
tcp_ssl_t *fd_data = NULL;
|
||||||
|
uint8_t *read_buf = NULL;
|
||||||
|
uint8_t *pread_buf = NULL;
|
||||||
|
u16_t recv_len = 0;
|
||||||
|
|
||||||
|
//TCP_SSL_DEBUG("ax_port_read: %d, %d\n", fd, len);
|
||||||
|
|
||||||
|
fd_data = tcp_ssl_get_by_fd(fd);
|
||||||
|
if (fd_data == NULL) {
|
||||||
|
TCP_SSL_DEBUG("ax_port_read: tcp_ssl[%d] is NULL\n", fd);
|
||||||
|
return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fd_data->tcp_pbuf == NULL || fd_data->tcp_pbuf->tot_len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_buf =(uint8_t*)calloc(fd_data->tcp_pbuf->len + 1, sizeof(uint8_t));
|
||||||
|
pread_buf = read_buf;
|
||||||
|
if (pread_buf != NULL){
|
||||||
|
recv_len = pbuf_copy_partial(fd_data->tcp_pbuf, read_buf, len, fd_data->pbuf_offset);
|
||||||
|
fd_data->pbuf_offset += recv_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recv_len != 0) {
|
||||||
|
memcpy(data, read_buf, recv_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len < recv_len) {
|
||||||
|
TCP_SSL_DEBUG("ax_port_read: got %d bytes more than expected\n", recv_len - len);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pread_buf);
|
||||||
|
pread_buf = NULL;
|
||||||
|
|
||||||
|
return recv_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ax_wdt_feed() {}
|
||||||
|
|
||||||
|
#endif
|
||||||
97
libraries/ESPAsyncTCP/src/tcp_axtls.h
Normal file
97
libraries/ESPAsyncTCP/src/tcp_axtls.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous TCP library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Compatibility for AxTLS with LWIP raw tcp mode (http://lwip.wikia.com/wiki/Raw/TCP)
|
||||||
|
* Original Code and Inspiration: Slavey Karadzhov
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LWIPR_COMPAT_H
|
||||||
|
#define LWIPR_COMPAT_H
|
||||||
|
|
||||||
|
#include <async_config.h>
|
||||||
|
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
|
||||||
|
#include "lwipopts.h"
|
||||||
|
/*
|
||||||
|
* All those functions will run only if LWIP tcp raw mode is used
|
||||||
|
*/
|
||||||
|
#if LWIP_RAW==1
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "include/ssl.h"
|
||||||
|
|
||||||
|
#define ERR_TCP_SSL_INVALID_SSL -101
|
||||||
|
#define ERR_TCP_SSL_INVALID_TCP -102
|
||||||
|
#define ERR_TCP_SSL_INVALID_CLIENTFD -103
|
||||||
|
#define ERR_TCP_SSL_INVALID_CLIENTFD_DATA -104
|
||||||
|
#define ERR_TCP_SSL_INVALID_DATA -105
|
||||||
|
|
||||||
|
#define TCP_SSL_TYPE_CLIENT 0
|
||||||
|
#define TCP_SSL_TYPE_SERVER 1
|
||||||
|
|
||||||
|
#define tcp_ssl_ssl_write(A, B, C) tcp_ssl_write(A, B, C)
|
||||||
|
#define tcp_ssl_ssl_read(A, B) tcp_ssl_read(A, B)
|
||||||
|
|
||||||
|
typedef void (* tcp_ssl_data_cb_t)(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len);
|
||||||
|
typedef void (* tcp_ssl_handshake_cb_t)(void *arg, struct tcp_pcb *tcp, SSL *ssl);
|
||||||
|
typedef void (* tcp_ssl_error_cb_t)(void *arg, struct tcp_pcb *tcp, int8_t error);
|
||||||
|
typedef int (* tcp_ssl_file_cb_t)(void *arg, const char *filename, uint8_t **buf);
|
||||||
|
|
||||||
|
uint8_t tcp_ssl_has_client();
|
||||||
|
|
||||||
|
int tcp_ssl_new_client(struct tcp_pcb *tcp);
|
||||||
|
|
||||||
|
SSL_CTX * tcp_ssl_new_server_ctx(const char *cert, const char *private_key_file, const char *password);
|
||||||
|
int tcp_ssl_new_server(struct tcp_pcb *tcp, SSL_CTX* ssl_ctx);
|
||||||
|
int tcp_ssl_is_server(struct tcp_pcb *tcp);
|
||||||
|
|
||||||
|
int tcp_ssl_free(struct tcp_pcb *tcp);
|
||||||
|
int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p);
|
||||||
|
|
||||||
|
#ifdef AXTLS_2_0_0_SNDBUF
|
||||||
|
int tcp_ssl_sndbuf(struct tcp_pcb *tcp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len);
|
||||||
|
|
||||||
|
void tcp_ssl_file(tcp_ssl_file_cb_t cb, void * arg);
|
||||||
|
|
||||||
|
void tcp_ssl_arg(struct tcp_pcb *tcp, void * arg);
|
||||||
|
void tcp_ssl_data(struct tcp_pcb *tcp, tcp_ssl_data_cb_t arg);
|
||||||
|
void tcp_ssl_handshake(struct tcp_pcb *tcp, tcp_ssl_handshake_cb_t arg);
|
||||||
|
void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg);
|
||||||
|
|
||||||
|
SSL * tcp_ssl_get_ssl(struct tcp_pcb *tcp);
|
||||||
|
bool tcp_ssl_has(struct tcp_pcb *tcp);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* LWIP_RAW==1 */
|
||||||
|
|
||||||
|
#endif /* ASYNC_TCP_SSL_ENABLED */
|
||||||
|
|
||||||
|
#endif /* LWIPR_COMPAT_H */
|
||||||
36
libraries/ESPAsyncTCP/ssl/gen_server_cert.sh
Normal file
36
libraries/ESPAsyncTCP/ssl/gen_server_cert.sh
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cat > ca_cert.conf << EOF
|
||||||
|
[ req ]
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
prompt = no
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
O = Espressif Systems
|
||||||
|
EOF
|
||||||
|
|
||||||
|
openssl genrsa -out axTLS.ca_key.pem 2048
|
||||||
|
openssl req -new -config ./ca_cert.conf -key axTLS.ca_key.pem -out axTLS.ca_x509.req
|
||||||
|
openssl x509 -req -sha1 -days 5000 -signkey axTLS.ca_key.pem -CAkey axTLS.ca_key.pem -in axTLS.ca_x509.req -out axTLS.ca_x509.pem
|
||||||
|
|
||||||
|
cat > certs.conf << EOF
|
||||||
|
[ req ]
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
prompt = no
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
O = axTLS on ESP8266
|
||||||
|
CN = esp8266.local
|
||||||
|
EOF
|
||||||
|
|
||||||
|
openssl genrsa -out axTLS.key_1024.pem 1024
|
||||||
|
openssl req -new -config ./certs.conf -key axTLS.key_1024.pem -out axTLS.x509_1024.req
|
||||||
|
openssl x509 -req -sha1 -CAcreateserial -days 5000 -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem -in axTLS.x509_1024.req -out axTLS.x509_1024.pem
|
||||||
|
|
||||||
|
openssl rsa -outform DER -in axTLS.key_1024.pem -out axTLS.key_1024
|
||||||
|
openssl x509 -outform DER -in axTLS.x509_1024.pem -out axTLS.x509_1024.cer
|
||||||
|
|
||||||
|
cat axTLS.key_1024 > server.key
|
||||||
|
cat axTLS.x509_1024.cer > server.cer
|
||||||
|
|
||||||
|
rm axTLS.* ca_cert.conf certs.conf
|
||||||
BIN
libraries/ESPAsyncTCP/ssl/server.cer
Normal file
BIN
libraries/ESPAsyncTCP/ssl/server.cer
Normal file
Binary file not shown.
BIN
libraries/ESPAsyncTCP/ssl/server.key
Normal file
BIN
libraries/ESPAsyncTCP/ssl/server.key
Normal file
Binary file not shown.
23
libraries/ESPAsyncTCP/travis/common.sh
Normal file
23
libraries/ESPAsyncTCP/travis/common.sh
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function build_sketches()
|
||||||
|
{
|
||||||
|
local arduino=$1
|
||||||
|
local srcpath=$2
|
||||||
|
local platform=$3
|
||||||
|
local sketches=$(find $srcpath -name *.ino)
|
||||||
|
for sketch in $sketches; do
|
||||||
|
local sketchdir=$(dirname $sketch)
|
||||||
|
if [[ -f "$sketchdir/.$platform.skip" ]]; then
|
||||||
|
echo -e "\n\n ------------ Skipping $sketch ------------ \n\n";
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo -e "\n\n ------------ Building $sketch ------------ \n\n";
|
||||||
|
$arduino --verify $sketch;
|
||||||
|
local result=$?
|
||||||
|
if [ $result -ne 0 ]; then
|
||||||
|
echo "Build failed ($1)"
|
||||||
|
return $result
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
39
libraries/ESPAsyncWebServer/.travis.yml
Normal file
39
libraries/ESPAsyncWebServer/.travis.yml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
sudo: false
|
||||||
|
language: bash
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
|
||||||
|
script:
|
||||||
|
- /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
|
||||||
|
- wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz
|
||||||
|
- tar xf arduino-1.6.5-linux64.tar.xz
|
||||||
|
- mv arduino-1.6.5 $HOME/arduino_ide
|
||||||
|
- export PATH="$HOME/arduino_ide:$PATH"
|
||||||
|
- which arduino
|
||||||
|
- mkdir -p $HOME/Arduino/libraries
|
||||||
|
- cp -r $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/ESPAsyncWebServer
|
||||||
|
- git clone https://github.com/bblanchon/ArduinoJson $HOME/Arduino/libraries/ArduinoJson
|
||||||
|
- git clone https://github.com/me-no-dev/ESPAsyncTCP $HOME/Arduino/libraries/ESPAsyncTCP
|
||||||
|
- cd $HOME/arduino_ide/hardware
|
||||||
|
- mkdir esp8266com
|
||||||
|
- cd esp8266com
|
||||||
|
- git clone https://github.com/esp8266/Arduino.git esp8266
|
||||||
|
- cd esp8266/tools
|
||||||
|
- python get.py
|
||||||
|
- source $TRAVIS_BUILD_DIR/travis/common.sh
|
||||||
|
- arduino --board esp8266com:esp8266:generic --save-prefs
|
||||||
|
- arduino --get-pref sketchbook.path
|
||||||
|
- build_sketches arduino $HOME/Arduino/libraries/ESPAsyncWebServer esp8266
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email:
|
||||||
|
on_success: change
|
||||||
|
on_failure: change
|
||||||
|
webhooks:
|
||||||
|
urls:
|
||||||
|
- https://webhooks.gitter.im/e/60e65d0c78ea0a920347
|
||||||
|
on_success: change # options: [always|never|change] default: always
|
||||||
|
on_failure: always # options: [always|never|change] default: always
|
||||||
|
on_start: false # default: false
|
||||||
1368
libraries/ESPAsyncWebServer/README.md
Normal file
1368
libraries/ESPAsyncWebServer/README.md
Normal file
File diff suppressed because it is too large
Load Diff
3
libraries/ESPAsyncWebServer/component.mk
Normal file
3
libraries/ESPAsyncWebServer/component.mk
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
COMPONENT_ADD_INCLUDEDIRS := src
|
||||||
|
COMPONENT_SRCDIRS := src
|
||||||
|
CXXFLAGS += -fno-rtti
|
||||||
23
libraries/ESPAsyncWebServer/espressif32_library.json
Normal file
23
libraries/ESPAsyncWebServer/espressif32_library.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name":"AsyncWebServer",
|
||||||
|
"description":"Asynchronous HTTP and WebSocket Server Library for ESP32",
|
||||||
|
"keywords":"http,async,websocket,webserver",
|
||||||
|
"authors":
|
||||||
|
{
|
||||||
|
"name": "Hristo Gochkov",
|
||||||
|
"maintainer": true
|
||||||
|
},
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/me-no-dev/ESPAsyncWebServer.git"
|
||||||
|
},
|
||||||
|
"version": "1.1.0",
|
||||||
|
"license": "LGPL-3.0",
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": ["espressif32", "espressif32_stage"],
|
||||||
|
"dependencies":
|
||||||
|
{
|
||||||
|
"name": "AsyncTCP"
|
||||||
|
}
|
||||||
|
}
|
||||||
23
libraries/ESPAsyncWebServer/espressif8266_library.json
Normal file
23
libraries/ESPAsyncWebServer/espressif8266_library.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name":"ESPAsyncWebServer",
|
||||||
|
"description":"Asynchronous HTTP and WebSocket Server Library for ESP8266",
|
||||||
|
"keywords":"http,async,websocket,webserver",
|
||||||
|
"authors":
|
||||||
|
{
|
||||||
|
"name": "Hristo Gochkov",
|
||||||
|
"maintainer": true
|
||||||
|
},
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/me-no-dev/ESPAsyncWebServer.git"
|
||||||
|
},
|
||||||
|
"version": "1.1.0",
|
||||||
|
"license": "LGPL-3.0",
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": ["espressif8266", "espressif8266_stage"],
|
||||||
|
"dependencies":
|
||||||
|
{
|
||||||
|
"name": "ESPAsyncTCP"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266mDNS.h>
|
||||||
|
#include <ArduinoOTA.h>
|
||||||
|
#include <FS.h>
|
||||||
|
#include <Hash.h>
|
||||||
|
#include <ESPAsyncTCP.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <SPIFFSEditor.h>
|
||||||
|
#include <ESP8266SSDP.h>
|
||||||
|
// SKETCH BEGIN
|
||||||
|
AsyncWebServer server(80);
|
||||||
|
AsyncWebSocket ws("/ws");
|
||||||
|
AsyncEventSource events("/events");
|
||||||
|
|
||||||
|
void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
|
||||||
|
if(type == WS_EVT_CONNECT){
|
||||||
|
Serial.printf("ws[%s][%u] connect\n", server->url(), client->id());
|
||||||
|
client->printf("Hello Client %u :)", client->id());
|
||||||
|
client->ping();
|
||||||
|
} else if(type == WS_EVT_DISCONNECT){
|
||||||
|
Serial.printf("ws[%s][%u] disconnect: %u\n", server->url(), client->id());
|
||||||
|
} else if(type == WS_EVT_ERROR){
|
||||||
|
Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data);
|
||||||
|
} else if(type == WS_EVT_PONG){
|
||||||
|
Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:"");
|
||||||
|
} else if(type == WS_EVT_DATA){
|
||||||
|
AwsFrameInfo * info = (AwsFrameInfo*)arg;
|
||||||
|
String msg = "";
|
||||||
|
if(info->final && info->index == 0 && info->len == len){
|
||||||
|
//the whole message is in a single frame and we got all of it's data
|
||||||
|
Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len);
|
||||||
|
|
||||||
|
if(info->opcode == WS_TEXT){
|
||||||
|
for(size_t i=0; i < info->len; i++) {
|
||||||
|
msg += (char) data[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char buff[3];
|
||||||
|
for(size_t i=0; i < info->len; i++) {
|
||||||
|
sprintf(buff, "%02x ", (uint8_t) data[i]);
|
||||||
|
msg += buff ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.printf("%s\n",msg.c_str());
|
||||||
|
|
||||||
|
if(info->opcode == WS_TEXT)
|
||||||
|
client->text("I got your text message");
|
||||||
|
else
|
||||||
|
client->binary("I got your binary message");
|
||||||
|
} else {
|
||||||
|
//message is comprised of multiple frames or the frame is split into multiple packets
|
||||||
|
if(info->index == 0){
|
||||||
|
if(info->num == 0)
|
||||||
|
Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary");
|
||||||
|
Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len);
|
||||||
|
|
||||||
|
if(info->opcode == WS_TEXT){
|
||||||
|
for(size_t i=0; i < info->len; i++) {
|
||||||
|
msg += (char) data[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char buff[3];
|
||||||
|
for(size_t i=0; i < info->len; i++) {
|
||||||
|
sprintf(buff, "%02x ", (uint8_t) data[i]);
|
||||||
|
msg += buff ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.printf("%s\n",msg.c_str());
|
||||||
|
|
||||||
|
if((info->index + len) == info->len){
|
||||||
|
Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len);
|
||||||
|
if(info->final){
|
||||||
|
Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary");
|
||||||
|
if(info->message_opcode == WS_TEXT)
|
||||||
|
client->text("I got your text message");
|
||||||
|
else
|
||||||
|
client->binary("I got your binary message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* ssid = "*******";
|
||||||
|
const char* password = "*******";
|
||||||
|
const char * hostName = "esp-async";
|
||||||
|
const char* http_username = "admin";
|
||||||
|
const char* http_password = "admin";
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.setDebugOutput(true);
|
||||||
|
WiFi.hostname(hostName);
|
||||||
|
WiFi.mode(WIFI_AP_STA);
|
||||||
|
WiFi.softAP(hostName);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||||
|
Serial.printf("STA: Failed!\n");
|
||||||
|
WiFi.disconnect(false);
|
||||||
|
delay(1000);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send OTA events to the browser
|
||||||
|
ArduinoOTA.onStart([]() { events.send("Update Start", "ota"); });
|
||||||
|
ArduinoOTA.onEnd([]() { events.send("Update End", "ota"); });
|
||||||
|
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||||
|
char p[32];
|
||||||
|
sprintf(p, "Progress: %u%%\n", (progress/(total/100)));
|
||||||
|
events.send(p, "ota");
|
||||||
|
});
|
||||||
|
ArduinoOTA.onError([](ota_error_t error) {
|
||||||
|
if(error == OTA_AUTH_ERROR) events.send("Auth Failed", "ota");
|
||||||
|
else if(error == OTA_BEGIN_ERROR) events.send("Begin Failed", "ota");
|
||||||
|
else if(error == OTA_CONNECT_ERROR) events.send("Connect Failed", "ota");
|
||||||
|
else if(error == OTA_RECEIVE_ERROR) events.send("Recieve Failed", "ota");
|
||||||
|
else if(error == OTA_END_ERROR) events.send("End Failed", "ota");
|
||||||
|
});
|
||||||
|
ArduinoOTA.setHostname(hostName);
|
||||||
|
ArduinoOTA.begin();
|
||||||
|
|
||||||
|
MDNS.addService("http","tcp",80);
|
||||||
|
|
||||||
|
SPIFFS.begin();
|
||||||
|
|
||||||
|
ws.onEvent(onWsEvent);
|
||||||
|
server.addHandler(&ws);
|
||||||
|
|
||||||
|
events.onConnect([](AsyncEventSourceClient *client){
|
||||||
|
client->send("hello!",NULL,millis(),1000);
|
||||||
|
});
|
||||||
|
server.addHandler(&events);
|
||||||
|
|
||||||
|
server.addHandler(new SPIFFSEditor(http_username,http_password));
|
||||||
|
|
||||||
|
server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
|
request->send(200, "text/plain", String(ESP.getFreeHeap()));
|
||||||
|
});
|
||||||
|
|
||||||
|
server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm");
|
||||||
|
|
||||||
|
server.onNotFound([](AsyncWebServerRequest *request){
|
||||||
|
Serial.printf("NOT_FOUND: ");
|
||||||
|
if(request->method() == HTTP_GET)
|
||||||
|
Serial.printf("GET");
|
||||||
|
else if(request->method() == HTTP_POST)
|
||||||
|
Serial.printf("POST");
|
||||||
|
else if(request->method() == HTTP_DELETE)
|
||||||
|
Serial.printf("DELETE");
|
||||||
|
else if(request->method() == HTTP_PUT)
|
||||||
|
Serial.printf("PUT");
|
||||||
|
else if(request->method() == HTTP_PATCH)
|
||||||
|
Serial.printf("PATCH");
|
||||||
|
else if(request->method() == HTTP_HEAD)
|
||||||
|
Serial.printf("HEAD");
|
||||||
|
else if(request->method() == HTTP_OPTIONS)
|
||||||
|
Serial.printf("OPTIONS");
|
||||||
|
else
|
||||||
|
Serial.printf("UNKNOWN");
|
||||||
|
Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str());
|
||||||
|
|
||||||
|
if(request->contentLength()){
|
||||||
|
Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str());
|
||||||
|
Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
int headers = request->headers();
|
||||||
|
int i;
|
||||||
|
for(i=0;i<headers;i++){
|
||||||
|
AsyncWebHeader* h = request->getHeader(i);
|
||||||
|
Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
int params = request->params();
|
||||||
|
for(i=0;i<params;i++){
|
||||||
|
AsyncWebParameter* p = request->getParam(i);
|
||||||
|
if(p->isFile()){
|
||||||
|
Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
|
||||||
|
} else if(p->isPost()){
|
||||||
|
Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
||||||
|
} else {
|
||||||
|
Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request->send(404);
|
||||||
|
});
|
||||||
|
server.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){
|
||||||
|
if(!index)
|
||||||
|
Serial.printf("UploadStart: %s\n", filename.c_str());
|
||||||
|
Serial.printf("%s", (const char*)data);
|
||||||
|
if(final)
|
||||||
|
Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index+len);
|
||||||
|
});
|
||||||
|
server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){
|
||||||
|
if(!index)
|
||||||
|
Serial.printf("BodyStart: %u\n", total);
|
||||||
|
Serial.printf("%s", (const char*)data);
|
||||||
|
if(index + len == total)
|
||||||
|
Serial.printf("BodyEnd: %u\n", total);
|
||||||
|
});
|
||||||
|
server.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
ArduinoOTA.handle();
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
/*.js.gz
|
||||||
|
/.exclude.files
|
||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,131 @@
|
|||||||
|
<!--
|
||||||
|
FSWebServer - Example Index Page
|
||||||
|
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the ESP8266WebServer library for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
-->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||||
|
<title>WebSocketTester</title>
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
body {
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dbg, #input_div, #input_el {
|
||||||
|
font-family: monaco;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 13px;
|
||||||
|
color: #AAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dbg, #input_div {
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
padding-left:4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#input_el {
|
||||||
|
width:98%;
|
||||||
|
background-color: rgba(0,0,0,0);
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
#input_el:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var ws = null;
|
||||||
|
function ge(s){ return document.getElementById(s);}
|
||||||
|
function ce(s){ return document.createElement(s);}
|
||||||
|
function stb(){ window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight); }
|
||||||
|
function sendBlob(str){
|
||||||
|
var buf = new Uint8Array(str.length);
|
||||||
|
for (var i = 0; i < str.length; ++i) buf[i] = str.charCodeAt(i);
|
||||||
|
ws.send(buf);
|
||||||
|
}
|
||||||
|
function addMessage(m){
|
||||||
|
var msg = ce("div");
|
||||||
|
msg.innerText = m;
|
||||||
|
ge("dbg").appendChild(msg);
|
||||||
|
stb();
|
||||||
|
}
|
||||||
|
function startSocket(){
|
||||||
|
ws = new WebSocket('ws://'+document.location.host+'/ws',['arduino']);
|
||||||
|
ws.binaryType = "arraybuffer";
|
||||||
|
ws.onopen = function(e){
|
||||||
|
addMessage("Connected");
|
||||||
|
};
|
||||||
|
ws.onclose = function(e){
|
||||||
|
addMessage("Disconnected");
|
||||||
|
};
|
||||||
|
ws.onerror = function(e){
|
||||||
|
console.log("ws error", e);
|
||||||
|
addMessage("Error");
|
||||||
|
};
|
||||||
|
ws.onmessage = function(e){
|
||||||
|
var msg = "";
|
||||||
|
if(e.data instanceof ArrayBuffer){
|
||||||
|
msg = "BIN:";
|
||||||
|
var bytes = new Uint8Array(e.data);
|
||||||
|
for (var i = 0; i < bytes.length; i++) {
|
||||||
|
msg += String.fromCharCode(bytes[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msg = "TXT:"+e.data;
|
||||||
|
}
|
||||||
|
addMessage(msg);
|
||||||
|
};
|
||||||
|
ge("input_el").onkeydown = function(e){
|
||||||
|
stb();
|
||||||
|
if(e.keyCode == 13 && ge("input_el").value != ""){
|
||||||
|
ws.send(ge("input_el").value);
|
||||||
|
ge("input_el").value = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function startEvents(){
|
||||||
|
var es = new EventSource('/events');
|
||||||
|
es.onopen = function(e) {
|
||||||
|
addMessage("Events Opened");
|
||||||
|
};
|
||||||
|
es.onerror = function(e) {
|
||||||
|
if (e.target.readyState != EventSource.OPEN) {
|
||||||
|
addMessage("Events Closed");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
es.onmessage = function(e) {
|
||||||
|
addMessage("Event: " + e.data);
|
||||||
|
};
|
||||||
|
es.addEventListener('ota', function(e) {
|
||||||
|
addMessage("Event[ota]: " + e.data);
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
function onBodyLoad(){
|
||||||
|
startSocket();
|
||||||
|
startEvents();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body id="body" onload="onBodyLoad()">
|
||||||
|
<pre id="dbg"></pre>
|
||||||
|
<div id="input_div">
|
||||||
|
$<input type="text" value="" id="input_el">
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
3
libraries/ESPAsyncWebServer/keywords.txt
Normal file
3
libraries/ESPAsyncWebServer/keywords.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
JsonArray KEYWORD1
|
||||||
|
add KEYWORD2
|
||||||
|
createArray KEYWORD3
|
||||||
9
libraries/ESPAsyncWebServer/library.properties
Normal file
9
libraries/ESPAsyncWebServer/library.properties
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
name=ESP Async WebServer
|
||||||
|
version=1.1.0
|
||||||
|
author=Me-No-Dev
|
||||||
|
maintainer=Me-No-Dev
|
||||||
|
sentence=Async Web Server for ESP8266 and ESP31B
|
||||||
|
paragraph=Async Web Server for ESP8266 and ESP31B
|
||||||
|
category=Other
|
||||||
|
url=https://github.com/me-no-dev/ESPAsyncWebServer
|
||||||
|
architectures=*
|
||||||
345
libraries/ESPAsyncWebServer/src/AsyncEventSource.cpp
Normal file
345
libraries/ESPAsyncWebServer/src/AsyncEventSource.cpp
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous WebServer library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "AsyncEventSource.h"
|
||||||
|
|
||||||
|
static String generateEventMessage(const char *message, const char *event, uint32_t id, uint32_t reconnect){
|
||||||
|
String ev = "";
|
||||||
|
|
||||||
|
if(reconnect){
|
||||||
|
ev += "retry: ";
|
||||||
|
ev += String(reconnect);
|
||||||
|
ev += "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(id){
|
||||||
|
ev += "id: ";
|
||||||
|
ev += String(id);
|
||||||
|
ev += "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event != NULL){
|
||||||
|
ev += "event: ";
|
||||||
|
ev += String(event);
|
||||||
|
ev += "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(message != NULL){
|
||||||
|
size_t messageLen = strlen(message);
|
||||||
|
char * lineStart = (char *)message;
|
||||||
|
char * lineEnd;
|
||||||
|
do {
|
||||||
|
char * nextN = strchr(lineStart, '\n');
|
||||||
|
char * nextR = strchr(lineStart, '\r');
|
||||||
|
if(nextN == NULL && nextR == NULL){
|
||||||
|
size_t llen = ((char *)message + messageLen) - lineStart;
|
||||||
|
char * ldata = (char *)malloc(llen+1);
|
||||||
|
if(ldata != NULL){
|
||||||
|
memcpy(ldata, lineStart, llen);
|
||||||
|
ldata[llen] = 0;
|
||||||
|
ev += "data: ";
|
||||||
|
ev += ldata;
|
||||||
|
ev += "\r\n\r\n";
|
||||||
|
free(ldata);
|
||||||
|
}
|
||||||
|
lineStart = (char *)message + messageLen;
|
||||||
|
} else {
|
||||||
|
char * nextLine = NULL;
|
||||||
|
if(nextN != NULL && nextR != NULL){
|
||||||
|
if(nextR < nextN){
|
||||||
|
lineEnd = nextR;
|
||||||
|
if(nextN == (nextR + 1))
|
||||||
|
nextLine = nextN + 1;
|
||||||
|
else
|
||||||
|
nextLine = nextR + 1;
|
||||||
|
} else {
|
||||||
|
lineEnd = nextN;
|
||||||
|
if(nextR == (nextN + 1))
|
||||||
|
nextLine = nextR + 1;
|
||||||
|
else
|
||||||
|
nextLine = nextN + 1;
|
||||||
|
}
|
||||||
|
} else if(nextN != NULL){
|
||||||
|
lineEnd = nextN;
|
||||||
|
nextLine = nextN + 1;
|
||||||
|
} else {
|
||||||
|
lineEnd = nextR;
|
||||||
|
nextLine = nextR + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t llen = lineEnd - lineStart;
|
||||||
|
char * ldata = (char *)malloc(llen+1);
|
||||||
|
if(ldata != NULL){
|
||||||
|
memcpy(ldata, lineStart, llen);
|
||||||
|
ldata[llen] = 0;
|
||||||
|
ev += "data: ";
|
||||||
|
ev += ldata;
|
||||||
|
ev += "\r\n";
|
||||||
|
free(ldata);
|
||||||
|
}
|
||||||
|
lineStart = nextLine;
|
||||||
|
if(lineStart == ((char *)message + messageLen))
|
||||||
|
ev += "\r\n";
|
||||||
|
}
|
||||||
|
} while(lineStart < ((char *)message + messageLen));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message
|
||||||
|
|
||||||
|
AsyncEventSourceMessage::AsyncEventSourceMessage(const char * data, size_t len)
|
||||||
|
: _data(nullptr), _len(len), _sent(0), _acked(0)
|
||||||
|
{
|
||||||
|
_data = (uint8_t*)malloc(_len+1);
|
||||||
|
if(_data == nullptr){
|
||||||
|
_len = 0;
|
||||||
|
} else {
|
||||||
|
memcpy(_data, data, len);
|
||||||
|
_data[_len] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncEventSourceMessage::~AsyncEventSourceMessage() {
|
||||||
|
if(_data != NULL)
|
||||||
|
free(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncEventSourceMessage::ack(size_t len, uint32_t time) {
|
||||||
|
// If the whole message is now acked...
|
||||||
|
if(_acked + len > _len){
|
||||||
|
// Return the number of extra bytes acked (they will be carried on to the next message)
|
||||||
|
const size_t extra = _acked + len - _len;
|
||||||
|
_acked = _len;
|
||||||
|
return extra;
|
||||||
|
}
|
||||||
|
// Return that no extra bytes left.
|
||||||
|
_acked += len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncEventSourceMessage::send(AsyncClient *client) {
|
||||||
|
const size_t len = _len - _sent;
|
||||||
|
if(client->space() < len){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t sent = client->add((const char *)_data, len);
|
||||||
|
if(client->canSend())
|
||||||
|
client->send();
|
||||||
|
_sent += sent;
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client
|
||||||
|
|
||||||
|
AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server)
|
||||||
|
: _messageQueue(LinkedList<AsyncEventSourceMessage *>([](AsyncEventSourceMessage *m){ delete m; }))
|
||||||
|
{
|
||||||
|
_client = request->client();
|
||||||
|
_server = server;
|
||||||
|
_lastId = 0;
|
||||||
|
if(request->hasHeader("Last-Event-ID"))
|
||||||
|
_lastId = atoi(request->getHeader("Last-Event-ID")->value().c_str());
|
||||||
|
|
||||||
|
_client->setRxTimeout(0);
|
||||||
|
_client->onError(NULL, NULL);
|
||||||
|
_client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ ((AsyncEventSourceClient*)(r))->_onAck(len, time); }, this);
|
||||||
|
_client->onPoll([](void *r, AsyncClient* c){ ((AsyncEventSourceClient*)(r))->_onPoll(); }, this);
|
||||||
|
_client->onData(NULL, NULL);
|
||||||
|
_client->onTimeout([this](void *r, AsyncClient* c __attribute__((unused)), uint32_t time){ ((AsyncEventSourceClient*)(r))->_onTimeout(time); }, this);
|
||||||
|
_client->onDisconnect([this](void *r, AsyncClient* c){ ((AsyncEventSourceClient*)(r))->_onDisconnect(); delete c; }, this);
|
||||||
|
|
||||||
|
_server->_addClient(this);
|
||||||
|
delete request;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncEventSourceClient::~AsyncEventSourceClient(){
|
||||||
|
_messageQueue.free();
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSourceClient::_queueMessage(AsyncEventSourceMessage *dataMessage){
|
||||||
|
if(dataMessage == NULL)
|
||||||
|
return;
|
||||||
|
if(!connected()){
|
||||||
|
delete dataMessage;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_messageQueue.add(dataMessage);
|
||||||
|
|
||||||
|
_runQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSourceClient::_onAck(size_t len, uint32_t time){
|
||||||
|
while(len && !_messageQueue.isEmpty()){
|
||||||
|
len = _messageQueue.front()->ack(len, time);
|
||||||
|
if(_messageQueue.front()->finished())
|
||||||
|
_messageQueue.remove(_messageQueue.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
_runQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSourceClient::_onPoll(){
|
||||||
|
if(!_messageQueue.isEmpty()){
|
||||||
|
_runQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused))){
|
||||||
|
_client->close(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSourceClient::_onDisconnect(){
|
||||||
|
_client = NULL;
|
||||||
|
_server->_handleDisconnect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSourceClient::close(){
|
||||||
|
if(_client != NULL)
|
||||||
|
_client->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSourceClient::write(const char * message, size_t len){
|
||||||
|
_queueMessage(new AsyncEventSourceMessage(message, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSourceClient::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){
|
||||||
|
String ev = generateEventMessage(message, event, id, reconnect);
|
||||||
|
_queueMessage(new AsyncEventSourceMessage(ev.c_str(), ev.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSourceClient::_runQueue(){
|
||||||
|
while(!_messageQueue.isEmpty() && _messageQueue.front()->finished()){
|
||||||
|
_messageQueue.remove(_messageQueue.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto i = _messageQueue.begin(); i != _messageQueue.end(); ++i)
|
||||||
|
{
|
||||||
|
if(!(*i)->sent())
|
||||||
|
(*i)->send(_client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Handler
|
||||||
|
|
||||||
|
AsyncEventSource::AsyncEventSource(const String& url)
|
||||||
|
: _url(url)
|
||||||
|
, _clients(LinkedList<AsyncEventSourceClient *>([](AsyncEventSourceClient *c){ delete c; }))
|
||||||
|
, _connectcb(NULL)
|
||||||
|
{}
|
||||||
|
|
||||||
|
AsyncEventSource::~AsyncEventSource(){
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSource::onConnect(ArEventHandlerFunction cb){
|
||||||
|
_connectcb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSource::_addClient(AsyncEventSourceClient * client){
|
||||||
|
/*char * temp = (char *)malloc(2054);
|
||||||
|
if(temp != NULL){
|
||||||
|
memset(temp+1,' ',2048);
|
||||||
|
temp[0] = ':';
|
||||||
|
temp[2049] = '\r';
|
||||||
|
temp[2050] = '\n';
|
||||||
|
temp[2051] = '\r';
|
||||||
|
temp[2052] = '\n';
|
||||||
|
temp[2053] = 0;
|
||||||
|
client->write((const char *)temp, 2053);
|
||||||
|
free(temp);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
_clients.add(client);
|
||||||
|
if(_connectcb)
|
||||||
|
_connectcb(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){
|
||||||
|
_clients.remove(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSource::close(){
|
||||||
|
for(const auto &c: _clients){
|
||||||
|
if(c->connected())
|
||||||
|
c->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSource::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){
|
||||||
|
if(_clients.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
String ev = generateEventMessage(message, event, id, reconnect);
|
||||||
|
for(const auto &c: _clients){
|
||||||
|
if(c->connected()) {
|
||||||
|
c->write(ev.c_str(), ev.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncEventSource::count() const {
|
||||||
|
return _clients.count_if([](AsyncEventSourceClient *c){
|
||||||
|
return c->connected();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){
|
||||||
|
if(request->method() != HTTP_GET || !request->url().equals(_url) || !request->isExpectedRequestedConnType(RCT_EVENT))
|
||||||
|
return false;
|
||||||
|
request->addInterestingHeader("Last-Event-ID");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSource::handleRequest(AsyncWebServerRequest *request){
|
||||||
|
if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str()))
|
||||||
|
return request->requestAuthentication();
|
||||||
|
request->send(new AsyncEventSourceResponse(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response
|
||||||
|
|
||||||
|
AsyncEventSourceResponse::AsyncEventSourceResponse(AsyncEventSource *server){
|
||||||
|
_server = server;
|
||||||
|
_code = 200;
|
||||||
|
_contentType = "text/event-stream";
|
||||||
|
_sendContentLength = false;
|
||||||
|
addHeader("Cache-Control", "no-cache");
|
||||||
|
addHeader("Connection","keep-alive");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncEventSourceResponse::_respond(AsyncWebServerRequest *request){
|
||||||
|
String out = _assembleHead(request->version());
|
||||||
|
request->client()->write(out.c_str(), _headLength);
|
||||||
|
_state = RESPONSE_WAIT_ACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AsyncEventSourceResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time __attribute__((unused))){
|
||||||
|
if(len){
|
||||||
|
new AsyncEventSourceClient(request, _server);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
114
libraries/ESPAsyncWebServer/src/AsyncEventSource.h
Normal file
114
libraries/ESPAsyncWebServer/src/AsyncEventSource.h
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous WebServer library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef ASYNCEVENTSOURCE_H_
|
||||||
|
#define ASYNCEVENTSOURCE_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#ifdef ESP32
|
||||||
|
#include <AsyncTCP.h>
|
||||||
|
#else
|
||||||
|
#include <ESPAsyncTCP.h>
|
||||||
|
#endif
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|
||||||
|
class AsyncEventSource;
|
||||||
|
class AsyncEventSourceResponse;
|
||||||
|
class AsyncEventSourceClient;
|
||||||
|
typedef std::function<void(AsyncEventSourceClient *client)> ArEventHandlerFunction;
|
||||||
|
|
||||||
|
class AsyncEventSourceMessage {
|
||||||
|
private:
|
||||||
|
uint8_t * _data;
|
||||||
|
size_t _len;
|
||||||
|
size_t _sent;
|
||||||
|
//size_t _ack;
|
||||||
|
size_t _acked;
|
||||||
|
public:
|
||||||
|
AsyncEventSourceMessage(const char * data, size_t len);
|
||||||
|
~AsyncEventSourceMessage();
|
||||||
|
size_t ack(size_t len, uint32_t time __attribute__((unused)));
|
||||||
|
size_t send(AsyncClient *client);
|
||||||
|
bool finished(){ return _acked == _len; }
|
||||||
|
bool sent() { return _sent == _len; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncEventSourceClient {
|
||||||
|
private:
|
||||||
|
AsyncClient *_client;
|
||||||
|
AsyncEventSource *_server;
|
||||||
|
uint32_t _lastId;
|
||||||
|
LinkedList<AsyncEventSourceMessage *> _messageQueue;
|
||||||
|
void _queueMessage(AsyncEventSourceMessage *dataMessage);
|
||||||
|
void _runQueue();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server);
|
||||||
|
~AsyncEventSourceClient();
|
||||||
|
|
||||||
|
AsyncClient* client(){ return _client; }
|
||||||
|
void close();
|
||||||
|
void write(const char * message, size_t len);
|
||||||
|
void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0);
|
||||||
|
bool connected() const { return (_client != NULL) && _client->connected(); }
|
||||||
|
uint32_t lastId() const { return _lastId; }
|
||||||
|
|
||||||
|
//system callbacks (do not call)
|
||||||
|
void _onAck(size_t len, uint32_t time);
|
||||||
|
void _onPoll();
|
||||||
|
void _onTimeout(uint32_t time);
|
||||||
|
void _onDisconnect();
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncEventSource: public AsyncWebHandler {
|
||||||
|
private:
|
||||||
|
String _url;
|
||||||
|
LinkedList<AsyncEventSourceClient *> _clients;
|
||||||
|
ArEventHandlerFunction _connectcb;
|
||||||
|
public:
|
||||||
|
AsyncEventSource(const String& url);
|
||||||
|
~AsyncEventSource();
|
||||||
|
|
||||||
|
const char * url() const { return _url.c_str(); }
|
||||||
|
void close();
|
||||||
|
void onConnect(ArEventHandlerFunction cb);
|
||||||
|
void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0);
|
||||||
|
size_t count() const; //number clinets connected
|
||||||
|
|
||||||
|
//system callbacks (do not call)
|
||||||
|
void _addClient(AsyncEventSourceClient * client);
|
||||||
|
void _handleDisconnect(AsyncEventSourceClient * client);
|
||||||
|
virtual bool canHandle(AsyncWebServerRequest *request) override final;
|
||||||
|
virtual void handleRequest(AsyncWebServerRequest *request) override final;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncEventSourceResponse: public AsyncWebServerResponse {
|
||||||
|
private:
|
||||||
|
String _content;
|
||||||
|
AsyncEventSource *_server;
|
||||||
|
public:
|
||||||
|
AsyncEventSourceResponse(AsyncEventSource *server);
|
||||||
|
void _respond(AsyncWebServerRequest *request);
|
||||||
|
size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
|
||||||
|
bool _sourceValid() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ASYNCEVENTSOURCE_H_ */
|
||||||
83
libraries/ESPAsyncWebServer/src/AsyncJson.h
Normal file
83
libraries/ESPAsyncWebServer/src/AsyncJson.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
// ESPasyncJson.h
|
||||||
|
/*
|
||||||
|
Async Response to use with arduinoJson and asyncwebserver
|
||||||
|
Written by Andrew Melvin (SticilFace) with help from me-no-dev and BBlanchon.
|
||||||
|
|
||||||
|
example of callback in use
|
||||||
|
|
||||||
|
server.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) {
|
||||||
|
|
||||||
|
AsyncJsonResponse * response = new AsyncJsonResponse();
|
||||||
|
JsonObject& root = response->getRoot();
|
||||||
|
root["key1"] = "key number one";
|
||||||
|
JsonObject& nested = root.createNestedObject("nested");
|
||||||
|
nested["key1"] = "key number one";
|
||||||
|
|
||||||
|
response->setLength();
|
||||||
|
request->send(response);
|
||||||
|
});
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifndef ASYNC_JSON_H_
|
||||||
|
#define ASYNC_JSON_H_
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Json Response
|
||||||
|
* */
|
||||||
|
|
||||||
|
class ChunkPrint : public Print {
|
||||||
|
private:
|
||||||
|
uint8_t* _destination;
|
||||||
|
size_t _to_skip;
|
||||||
|
size_t _to_write;
|
||||||
|
size_t _pos;
|
||||||
|
public:
|
||||||
|
ChunkPrint(uint8_t* destination, size_t from, size_t len)
|
||||||
|
: _destination(destination), _to_skip(from), _to_write(len), _pos{0} {}
|
||||||
|
virtual ~ChunkPrint(){}
|
||||||
|
size_t write(uint8_t c){
|
||||||
|
if (_to_skip > 0) {
|
||||||
|
_to_skip--;
|
||||||
|
return 1;
|
||||||
|
} else if (_to_write > 0) {
|
||||||
|
_to_write--;
|
||||||
|
_destination[_pos++] = c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncJsonResponse: public AsyncAbstractResponse {
|
||||||
|
private:
|
||||||
|
DynamicJsonBuffer _jsonBuffer;
|
||||||
|
JsonVariant _root;
|
||||||
|
bool _isValid;
|
||||||
|
public:
|
||||||
|
AsyncJsonResponse(bool isArray=false): _isValid{false} {
|
||||||
|
_code = 200;
|
||||||
|
_contentType = "text/json";
|
||||||
|
if(isArray)
|
||||||
|
_root = _jsonBuffer.createArray();
|
||||||
|
else
|
||||||
|
_root = _jsonBuffer.createObject();
|
||||||
|
}
|
||||||
|
~AsyncJsonResponse() {}
|
||||||
|
JsonVariant & getRoot() { return _root; }
|
||||||
|
bool _sourceValid() const { return _isValid; }
|
||||||
|
size_t setLength() {
|
||||||
|
_contentLength = _root.measureLength();
|
||||||
|
if (_contentLength) { _isValid = true; }
|
||||||
|
return _contentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() { return _jsonBuffer.size(); }
|
||||||
|
|
||||||
|
size_t _fillBuffer(uint8_t *data, size_t len){
|
||||||
|
ChunkPrint dest(data, _sentLength, len);
|
||||||
|
_root.printTo( dest ) ;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
1206
libraries/ESPAsyncWebServer/src/AsyncWebSocket.cpp
Normal file
1206
libraries/ESPAsyncWebServer/src/AsyncWebSocket.cpp
Normal file
File diff suppressed because it is too large
Load Diff
306
libraries/ESPAsyncWebServer/src/AsyncWebSocket.h
Normal file
306
libraries/ESPAsyncWebServer/src/AsyncWebSocket.h
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous WebServer library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef ASYNCWEBSOCKET_H_
|
||||||
|
#define ASYNCWEBSOCKET_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#ifdef ESP32
|
||||||
|
#include <AsyncTCP.h>
|
||||||
|
#else
|
||||||
|
#include <ESPAsyncTCP.h>
|
||||||
|
#endif
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|
||||||
|
class AsyncWebSocket;
|
||||||
|
class AsyncWebSocketResponse;
|
||||||
|
class AsyncWebSocketClient;
|
||||||
|
class AsyncWebSocketControl;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t message_opcode;
|
||||||
|
uint32_t num;
|
||||||
|
uint8_t final;
|
||||||
|
uint8_t masked;
|
||||||
|
uint8_t opcode;
|
||||||
|
uint64_t len;
|
||||||
|
uint8_t mask[4];
|
||||||
|
uint64_t index;
|
||||||
|
} AwsFrameInfo;
|
||||||
|
|
||||||
|
typedef enum { WS_DISCONNECTED, WS_CONNECTED, WS_DISCONNECTING } AwsClientStatus;
|
||||||
|
typedef enum { WS_CONTINUATION, WS_TEXT, WS_BINARY, WS_DISCONNECT = 0x08, WS_PING, WS_PONG } AwsFrameType;
|
||||||
|
typedef enum { WS_MSG_SENDING, WS_MSG_SENT, WS_MSG_ERROR } AwsMessageStatus;
|
||||||
|
typedef enum { WS_EVT_CONNECT, WS_EVT_DISCONNECT, WS_EVT_PONG, WS_EVT_ERROR, WS_EVT_DATA } AwsEventType;
|
||||||
|
|
||||||
|
class AsyncWebSocketMessageBuffer {
|
||||||
|
private:
|
||||||
|
uint8_t * _data;
|
||||||
|
size_t _len;
|
||||||
|
bool _lock;
|
||||||
|
uint32_t _count;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsyncWebSocketMessageBuffer();
|
||||||
|
AsyncWebSocketMessageBuffer(size_t size);
|
||||||
|
AsyncWebSocketMessageBuffer(uint8_t * data, size_t size);
|
||||||
|
AsyncWebSocketMessageBuffer(const AsyncWebSocketMessageBuffer &);
|
||||||
|
AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBuffer &&);
|
||||||
|
~AsyncWebSocketMessageBuffer();
|
||||||
|
void operator ++(int i) { _count++; }
|
||||||
|
void operator --(int i) { if (_count > 0) { _count--; } ; }
|
||||||
|
bool reserve(size_t size);
|
||||||
|
void lock() { _lock = true; }
|
||||||
|
void unlock() { _lock = false; }
|
||||||
|
uint8_t * get() { return _data; }
|
||||||
|
size_t length() { return _len; }
|
||||||
|
uint32_t count() { return _count; }
|
||||||
|
bool canDelete() { return (!_count && !_lock); }
|
||||||
|
|
||||||
|
friend AsyncWebSocket;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncWebSocketMessage {
|
||||||
|
protected:
|
||||||
|
uint8_t _opcode;
|
||||||
|
bool _mask;
|
||||||
|
AwsMessageStatus _status;
|
||||||
|
public:
|
||||||
|
AsyncWebSocketMessage():_opcode(WS_TEXT),_mask(false),_status(WS_MSG_ERROR){}
|
||||||
|
virtual ~AsyncWebSocketMessage(){}
|
||||||
|
virtual void ack(size_t len __attribute__((unused)), uint32_t time __attribute__((unused))){}
|
||||||
|
virtual size_t send(AsyncClient *client __attribute__((unused))){ return 0; }
|
||||||
|
virtual bool finished(){ return _status != WS_MSG_SENDING; }
|
||||||
|
virtual bool betweenFrames() const { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage {
|
||||||
|
private:
|
||||||
|
size_t _len;
|
||||||
|
size_t _sent;
|
||||||
|
size_t _ack;
|
||||||
|
size_t _acked;
|
||||||
|
uint8_t * _data;
|
||||||
|
public:
|
||||||
|
AsyncWebSocketBasicMessage(const char * data, size_t len, uint8_t opcode=WS_TEXT, bool mask=false);
|
||||||
|
AsyncWebSocketBasicMessage(uint8_t opcode=WS_TEXT, bool mask=false);
|
||||||
|
virtual ~AsyncWebSocketBasicMessage() override;
|
||||||
|
virtual bool betweenFrames() const override { return _acked == _ack; }
|
||||||
|
virtual void ack(size_t len, uint32_t time) override ;
|
||||||
|
virtual size_t send(AsyncClient *client) override ;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncWebSocketMultiMessage: public AsyncWebSocketMessage {
|
||||||
|
private:
|
||||||
|
uint8_t * _data;
|
||||||
|
size_t _len;
|
||||||
|
size_t _sent;
|
||||||
|
size_t _ack;
|
||||||
|
size_t _acked;
|
||||||
|
AsyncWebSocketMessageBuffer * _WSbuffer;
|
||||||
|
public:
|
||||||
|
AsyncWebSocketMultiMessage(AsyncWebSocketMessageBuffer * buffer, uint8_t opcode=WS_TEXT, bool mask=false);
|
||||||
|
virtual ~AsyncWebSocketMultiMessage() override;
|
||||||
|
virtual bool betweenFrames() const override { return _acked == _ack; }
|
||||||
|
virtual void ack(size_t len, uint32_t time) override ;
|
||||||
|
virtual size_t send(AsyncClient *client) override ;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AsyncWebSocketClient {
|
||||||
|
private:
|
||||||
|
AsyncClient *_client;
|
||||||
|
AsyncWebSocket *_server;
|
||||||
|
uint32_t _clientId;
|
||||||
|
AwsClientStatus _status;
|
||||||
|
|
||||||
|
LinkedList<AsyncWebSocketControl *> _controlQueue;
|
||||||
|
LinkedList<AsyncWebSocketMessage *> _messageQueue;
|
||||||
|
|
||||||
|
uint8_t _pstate;
|
||||||
|
AwsFrameInfo _pinfo;
|
||||||
|
|
||||||
|
uint32_t _lastMessageTime;
|
||||||
|
uint32_t _keepAlivePeriod;
|
||||||
|
|
||||||
|
void _queueMessage(AsyncWebSocketMessage *dataMessage);
|
||||||
|
void _queueControl(AsyncWebSocketControl *controlMessage);
|
||||||
|
void _runQueue();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void *_tempObject;
|
||||||
|
|
||||||
|
AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server);
|
||||||
|
~AsyncWebSocketClient();
|
||||||
|
|
||||||
|
//client id increments for the given server
|
||||||
|
uint32_t id(){ return _clientId; }
|
||||||
|
AwsClientStatus status(){ return _status; }
|
||||||
|
AsyncClient* client(){ return _client; }
|
||||||
|
|
||||||
|
IPAddress remoteIP();
|
||||||
|
uint16_t remotePort();
|
||||||
|
|
||||||
|
//control frames
|
||||||
|
void close(uint16_t code=0, const char * message=NULL);
|
||||||
|
void ping(uint8_t *data=NULL, size_t len=0);
|
||||||
|
|
||||||
|
//set auto-ping period in seconds. disabled if zero (default)
|
||||||
|
void keepAlivePeriod(uint16_t seconds){
|
||||||
|
_keepAlivePeriod = seconds * 1000;
|
||||||
|
}
|
||||||
|
uint16_t keepAlivePeriod(){
|
||||||
|
return (uint16_t)(_keepAlivePeriod / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
//data packets
|
||||||
|
void message(AsyncWebSocketMessage *message){ _queueMessage(message); }
|
||||||
|
|
||||||
|
size_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
|
#ifndef ESP32
|
||||||
|
size_t printf_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
|
#endif
|
||||||
|
void text(const char * message, size_t len);
|
||||||
|
void text(const char * message);
|
||||||
|
void text(uint8_t * message, size_t len);
|
||||||
|
void text(char * message);
|
||||||
|
void text(const String &message);
|
||||||
|
void text(const __FlashStringHelper *data);
|
||||||
|
void text(AsyncWebSocketMessageBuffer *buffer);
|
||||||
|
|
||||||
|
void binary(const char * message, size_t len);
|
||||||
|
void binary(const char * message);
|
||||||
|
void binary(uint8_t * message, size_t len);
|
||||||
|
void binary(char * message);
|
||||||
|
void binary(const String &message);
|
||||||
|
void binary(const __FlashStringHelper *data, size_t len);
|
||||||
|
void binary(AsyncWebSocketMessageBuffer *buffer);
|
||||||
|
|
||||||
|
//system callbacks (do not call)
|
||||||
|
void _onAck(size_t len, uint32_t time);
|
||||||
|
void _onError(int8_t);
|
||||||
|
void _onPoll();
|
||||||
|
void _onTimeout(uint32_t time);
|
||||||
|
void _onDisconnect();
|
||||||
|
void _onData(void *buf, size_t plen);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::function<void(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len)> AwsEventHandler;
|
||||||
|
|
||||||
|
//WebServer Handler implementation that plays the role of a socket server
|
||||||
|
class AsyncWebSocket: public AsyncWebHandler {
|
||||||
|
private:
|
||||||
|
String _url;
|
||||||
|
LinkedList<AsyncWebSocketClient *> _clients;
|
||||||
|
uint32_t _cNextId;
|
||||||
|
AwsEventHandler _eventHandler;
|
||||||
|
bool _enabled;
|
||||||
|
public:
|
||||||
|
AsyncWebSocket(const String& url);
|
||||||
|
~AsyncWebSocket();
|
||||||
|
const char * url() const { return _url.c_str(); }
|
||||||
|
void enable(bool e){ _enabled = e; }
|
||||||
|
bool enabled() const { return _enabled; }
|
||||||
|
|
||||||
|
size_t count() const;
|
||||||
|
AsyncWebSocketClient * client(uint32_t id);
|
||||||
|
bool hasClient(uint32_t id){ return client(id) != NULL; }
|
||||||
|
|
||||||
|
void close(uint32_t id, uint16_t code=0, const char * message=NULL);
|
||||||
|
void closeAll(uint16_t code=0, const char * message=NULL);
|
||||||
|
|
||||||
|
void ping(uint32_t id, uint8_t *data=NULL, size_t len=0);
|
||||||
|
void pingAll(uint8_t *data=NULL, size_t len=0); // done
|
||||||
|
|
||||||
|
void text(uint32_t id, const char * message, size_t len);
|
||||||
|
void text(uint32_t id, const char * message);
|
||||||
|
void text(uint32_t id, uint8_t * message, size_t len);
|
||||||
|
void text(uint32_t id, char * message);
|
||||||
|
void text(uint32_t id, const String &message);
|
||||||
|
void text(uint32_t id, const __FlashStringHelper *message);
|
||||||
|
|
||||||
|
void textAll(const char * message, size_t len);
|
||||||
|
void textAll(const char * message);
|
||||||
|
void textAll(uint8_t * message, size_t len);
|
||||||
|
void textAll(char * message);
|
||||||
|
void textAll(const String &message);
|
||||||
|
void textAll(const __FlashStringHelper *message); // need to convert
|
||||||
|
void textAll(AsyncWebSocketMessageBuffer * buffer);
|
||||||
|
|
||||||
|
void binary(uint32_t id, const char * message, size_t len);
|
||||||
|
void binary(uint32_t id, const char * message);
|
||||||
|
void binary(uint32_t id, uint8_t * message, size_t len);
|
||||||
|
void binary(uint32_t id, char * message);
|
||||||
|
void binary(uint32_t id, const String &message);
|
||||||
|
void binary(uint32_t id, const __FlashStringHelper *message, size_t len);
|
||||||
|
|
||||||
|
void binaryAll(const char * message, size_t len);
|
||||||
|
void binaryAll(const char * message);
|
||||||
|
void binaryAll(uint8_t * message, size_t len);
|
||||||
|
void binaryAll(char * message);
|
||||||
|
void binaryAll(const String &message);
|
||||||
|
void binaryAll(const __FlashStringHelper *message, size_t len);
|
||||||
|
void binaryAll(AsyncWebSocketMessageBuffer * buffer);
|
||||||
|
|
||||||
|
void message(uint32_t id, AsyncWebSocketMessage *message);
|
||||||
|
void messageAll(AsyncWebSocketMultiMessage *message);
|
||||||
|
|
||||||
|
size_t printf(uint32_t id, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||||
|
size_t printfAll(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
|
#ifndef ESP32
|
||||||
|
size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__ ((format (printf, 3, 4)));
|
||||||
|
#endif
|
||||||
|
size_t printfAll_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
|
|
||||||
|
//event listener
|
||||||
|
void onEvent(AwsEventHandler handler){
|
||||||
|
_eventHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
//system callbacks (do not call)
|
||||||
|
uint32_t _getNextId(){ return _cNextId++; }
|
||||||
|
void _addClient(AsyncWebSocketClient * client);
|
||||||
|
void _handleDisconnect(AsyncWebSocketClient * client);
|
||||||
|
void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len);
|
||||||
|
virtual bool canHandle(AsyncWebServerRequest *request) override final;
|
||||||
|
virtual void handleRequest(AsyncWebServerRequest *request) override final;
|
||||||
|
|
||||||
|
|
||||||
|
// messagebuffer functions/objects.
|
||||||
|
AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0);
|
||||||
|
AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size);
|
||||||
|
LinkedList<AsyncWebSocketMessageBuffer *> _buffers;
|
||||||
|
void _cleanBuffers();
|
||||||
|
};
|
||||||
|
|
||||||
|
//WebServer response to authenticate the socket and detach the tcp client from the web server request
|
||||||
|
class AsyncWebSocketResponse: public AsyncWebServerResponse {
|
||||||
|
private:
|
||||||
|
String _content;
|
||||||
|
AsyncWebSocket *_server;
|
||||||
|
public:
|
||||||
|
AsyncWebSocketResponse(const String& key, AsyncWebSocket *server);
|
||||||
|
void _respond(AsyncWebServerRequest *request);
|
||||||
|
size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
|
||||||
|
bool _sourceValid() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ASYNCWEBSOCKET_H_ */
|
||||||
448
libraries/ESPAsyncWebServer/src/ESPAsyncWebServer.h
Normal file
448
libraries/ESPAsyncWebServer/src/ESPAsyncWebServer.h
Normal file
@@ -0,0 +1,448 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous WebServer library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef _ESPAsyncWebServer_H_
|
||||||
|
#define _ESPAsyncWebServer_H_
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include "FS.h"
|
||||||
|
|
||||||
|
#include "StringArray.h"
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <AsyncTCP.h>
|
||||||
|
#elif defined(ESP8266)
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESPAsyncTCP.h>
|
||||||
|
#else
|
||||||
|
#error Platform not supported
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEBUGF(...) //Serial.printf(__VA_ARGS__)
|
||||||
|
|
||||||
|
class AsyncWebServer;
|
||||||
|
class AsyncWebServerRequest;
|
||||||
|
class AsyncWebServerResponse;
|
||||||
|
class AsyncWebHeader;
|
||||||
|
class AsyncWebParameter;
|
||||||
|
class AsyncWebRewrite;
|
||||||
|
class AsyncWebHandler;
|
||||||
|
class AsyncStaticWebHandler;
|
||||||
|
class AsyncCallbackWebHandler;
|
||||||
|
class AsyncResponseStream;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HTTP_GET = 0b00000001,
|
||||||
|
HTTP_POST = 0b00000010,
|
||||||
|
HTTP_DELETE = 0b00000100,
|
||||||
|
HTTP_PUT = 0b00001000,
|
||||||
|
HTTP_PATCH = 0b00010000,
|
||||||
|
HTTP_HEAD = 0b00100000,
|
||||||
|
HTTP_OPTIONS = 0b01000000,
|
||||||
|
HTTP_ANY = 0b01111111,
|
||||||
|
} WebRequestMethod;
|
||||||
|
typedef uint8_t WebRequestMethodComposite;
|
||||||
|
typedef std::function<void(void)> ArDisconnectHandler;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PARAMETER :: Chainable object to hold GET/POST and FILE parameters
|
||||||
|
* */
|
||||||
|
|
||||||
|
class AsyncWebParameter {
|
||||||
|
private:
|
||||||
|
String _name;
|
||||||
|
String _value;
|
||||||
|
size_t _size;
|
||||||
|
bool _isForm;
|
||||||
|
bool _isFile;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
AsyncWebParameter(const String& name, const String& value, bool form=false, bool file=false, size_t size=0): _name(name), _value(value), _size(size), _isForm(form), _isFile(file){}
|
||||||
|
const String& name() const { return _name; }
|
||||||
|
const String& value() const { return _value; }
|
||||||
|
size_t size() const { return _size; }
|
||||||
|
bool isPost() const { return _isForm; }
|
||||||
|
bool isFile() const { return _isFile; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HEADER :: Chainable object to hold the headers
|
||||||
|
* */
|
||||||
|
|
||||||
|
class AsyncWebHeader {
|
||||||
|
private:
|
||||||
|
String _name;
|
||||||
|
String _value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsyncWebHeader(const String& name, const String& value): _name(name), _value(value){}
|
||||||
|
AsyncWebHeader(const String& data): _name(), _value(){
|
||||||
|
if(!data) return;
|
||||||
|
int index = data.indexOf(':');
|
||||||
|
if (index < 0) return;
|
||||||
|
_name = data.substring(0, index);
|
||||||
|
_value = data.substring(index + 2);
|
||||||
|
}
|
||||||
|
~AsyncWebHeader(){}
|
||||||
|
const String& name() const { return _name; }
|
||||||
|
const String& value() const { return _value; }
|
||||||
|
String toString() const { return String(_name+": "+_value+"\r\n"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* REQUEST :: Each incoming Client is wrapped inside a Request and both live together until disconnect
|
||||||
|
* */
|
||||||
|
|
||||||
|
typedef enum { RCT_NOT_USED = -1, RCT_DEFAULT = 0, RCT_HTTP, RCT_WS, RCT_EVENT, RCT_MAX } RequestedConnectionType;
|
||||||
|
|
||||||
|
typedef std::function<size_t(uint8_t*, size_t, size_t)> AwsResponseFiller;
|
||||||
|
typedef std::function<String(const String&)> AwsTemplateProcessor;
|
||||||
|
|
||||||
|
class AsyncWebServerRequest {
|
||||||
|
using File = fs::File;
|
||||||
|
using FS = fs::FS;
|
||||||
|
friend class AsyncWebServer;
|
||||||
|
private:
|
||||||
|
AsyncClient* _client;
|
||||||
|
AsyncWebServer* _server;
|
||||||
|
AsyncWebHandler* _handler;
|
||||||
|
AsyncWebServerResponse* _response;
|
||||||
|
StringArray _interestingHeaders;
|
||||||
|
ArDisconnectHandler _onDisconnectfn;
|
||||||
|
String _temp;
|
||||||
|
uint8_t _parseState;
|
||||||
|
|
||||||
|
uint8_t _version;
|
||||||
|
WebRequestMethodComposite _method;
|
||||||
|
String _url;
|
||||||
|
String _host;
|
||||||
|
String _contentType;
|
||||||
|
String _boundary;
|
||||||
|
String _authorization;
|
||||||
|
RequestedConnectionType _reqconntype;
|
||||||
|
void _removeNotInterestingHeaders();
|
||||||
|
bool _isDigest;
|
||||||
|
bool _isMultipart;
|
||||||
|
bool _isPlainPost;
|
||||||
|
bool _expectingContinue;
|
||||||
|
size_t _contentLength;
|
||||||
|
size_t _parsedLength;
|
||||||
|
|
||||||
|
LinkedList<AsyncWebHeader *> _headers;
|
||||||
|
LinkedList<AsyncWebParameter *> _params;
|
||||||
|
|
||||||
|
uint8_t _multiParseState;
|
||||||
|
uint8_t _boundaryPosition;
|
||||||
|
size_t _itemStartIndex;
|
||||||
|
size_t _itemSize;
|
||||||
|
String _itemName;
|
||||||
|
String _itemFilename;
|
||||||
|
String _itemType;
|
||||||
|
String _itemValue;
|
||||||
|
uint8_t *_itemBuffer;
|
||||||
|
size_t _itemBufferIndex;
|
||||||
|
bool _itemIsFile;
|
||||||
|
|
||||||
|
void _onPoll();
|
||||||
|
void _onAck(size_t len, uint32_t time);
|
||||||
|
void _onError(int8_t error);
|
||||||
|
void _onTimeout(uint32_t time);
|
||||||
|
void _onDisconnect();
|
||||||
|
void _onData(void *buf, size_t len);
|
||||||
|
|
||||||
|
void _addParam(AsyncWebParameter*);
|
||||||
|
|
||||||
|
bool _parseReqHead();
|
||||||
|
bool _parseReqHeader();
|
||||||
|
void _parseLine();
|
||||||
|
void _parsePlainPostChar(uint8_t data);
|
||||||
|
void _parseMultipartPostByte(uint8_t data, bool last);
|
||||||
|
void _addGetParams(const String& params);
|
||||||
|
|
||||||
|
void _handleUploadStart();
|
||||||
|
void _handleUploadByte(uint8_t data, bool last);
|
||||||
|
void _handleUploadEnd();
|
||||||
|
|
||||||
|
public:
|
||||||
|
File _tempFile;
|
||||||
|
void *_tempObject;
|
||||||
|
|
||||||
|
AsyncWebServerRequest(AsyncWebServer*, AsyncClient*);
|
||||||
|
~AsyncWebServerRequest();
|
||||||
|
|
||||||
|
AsyncClient* client(){ return _client; }
|
||||||
|
uint8_t version() const { return _version; }
|
||||||
|
WebRequestMethodComposite method() const { return _method; }
|
||||||
|
const String& url() const { return _url; }
|
||||||
|
const String& host() const { return _host; }
|
||||||
|
const String& contentType() const { return _contentType; }
|
||||||
|
size_t contentLength() const { return _contentLength; }
|
||||||
|
bool multipart() const { return _isMultipart; }
|
||||||
|
const char * methodToString() const;
|
||||||
|
const char * requestedConnTypeToString() const;
|
||||||
|
RequestedConnectionType requestedConnType() const { return _reqconntype; }
|
||||||
|
bool isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2 = RCT_NOT_USED, RequestedConnectionType erct3 = RCT_NOT_USED);
|
||||||
|
void onDisconnect (ArDisconnectHandler fn);
|
||||||
|
//hash is the string representation of:
|
||||||
|
// base64(user:pass) for basic or
|
||||||
|
// user:realm:md5(user:realm:pass) for digest
|
||||||
|
bool authenticate(const char * hash);
|
||||||
|
bool authenticate(const char * username, const char * password, const char * realm = NULL, bool passwordIsHash = false);
|
||||||
|
void requestAuthentication(const char * realm = NULL, bool isDigest = true);
|
||||||
|
|
||||||
|
void setHandler(AsyncWebHandler *handler){ _handler = handler; }
|
||||||
|
void addInterestingHeader(const String& name);
|
||||||
|
|
||||||
|
void redirect(const String& url);
|
||||||
|
|
||||||
|
void send(AsyncWebServerResponse *response);
|
||||||
|
void send(int code, const String& contentType=String(), const String& content=String());
|
||||||
|
void send(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr);
|
||||||
|
void send(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr);
|
||||||
|
void send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr);
|
||||||
|
void send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr);
|
||||||
|
void sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr);
|
||||||
|
void send_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr);
|
||||||
|
void send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr);
|
||||||
|
|
||||||
|
AsyncWebServerResponse *beginResponse(int code, const String& contentType=String(), const String& content=String());
|
||||||
|
AsyncWebServerResponse *beginResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr);
|
||||||
|
AsyncWebServerResponse *beginResponse(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr);
|
||||||
|
AsyncWebServerResponse *beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr);
|
||||||
|
AsyncWebServerResponse *beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr);
|
||||||
|
AsyncWebServerResponse *beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr);
|
||||||
|
AsyncResponseStream *beginResponseStream(const String& contentType, size_t bufferSize=1460);
|
||||||
|
AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr);
|
||||||
|
AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr);
|
||||||
|
|
||||||
|
size_t headers() const; // get header count
|
||||||
|
bool hasHeader(const String& name) const; // check if header exists
|
||||||
|
bool hasHeader(const __FlashStringHelper * data) const; // check if header exists
|
||||||
|
|
||||||
|
AsyncWebHeader* getHeader(const String& name) const;
|
||||||
|
AsyncWebHeader* getHeader(const __FlashStringHelper * data) const;
|
||||||
|
AsyncWebHeader* getHeader(size_t num) const;
|
||||||
|
|
||||||
|
size_t params() const; // get arguments count
|
||||||
|
bool hasParam(const String& name, bool post=false, bool file=false) const;
|
||||||
|
bool hasParam(const __FlashStringHelper * data, bool post=false, bool file=false) const;
|
||||||
|
|
||||||
|
AsyncWebParameter* getParam(const String& name, bool post=false, bool file=false) const;
|
||||||
|
AsyncWebParameter* getParam(const __FlashStringHelper * data, bool post, bool file) const;
|
||||||
|
AsyncWebParameter* getParam(size_t num) const;
|
||||||
|
|
||||||
|
size_t args() const { return params(); } // get arguments count
|
||||||
|
const String& arg(const String& name) const; // get request argument value by name
|
||||||
|
const String& arg(const __FlashStringHelper * data) const; // get request argument value by F(name)
|
||||||
|
const String& arg(size_t i) const; // get request argument value by number
|
||||||
|
const String& argName(size_t i) const; // get request argument name by number
|
||||||
|
bool hasArg(const char* name) const; // check if argument exists
|
||||||
|
bool hasArg(const __FlashStringHelper * data) const; // check if F(argument) exists
|
||||||
|
|
||||||
|
const String& header(const char* name) const;// get request header value by name
|
||||||
|
const String& header(const __FlashStringHelper * data) const;// get request header value by F(name)
|
||||||
|
const String& header(size_t i) const; // get request header value by number
|
||||||
|
const String& headerName(size_t i) const; // get request header name by number
|
||||||
|
String urlDecode(const String& text) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FILTER :: Callback to filter AsyncWebRewrite and AsyncWebHandler (done by the Server)
|
||||||
|
* */
|
||||||
|
|
||||||
|
typedef std::function<bool(AsyncWebServerRequest *request)> ArRequestFilterFunction;
|
||||||
|
|
||||||
|
bool ON_STA_FILTER(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
|
bool ON_AP_FILTER(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* REWRITE :: One instance can be handle any Request (done by the Server)
|
||||||
|
* */
|
||||||
|
|
||||||
|
class AsyncWebRewrite {
|
||||||
|
protected:
|
||||||
|
String _from;
|
||||||
|
String _toUrl;
|
||||||
|
String _params;
|
||||||
|
ArRequestFilterFunction _filter;
|
||||||
|
public:
|
||||||
|
AsyncWebRewrite(const char* from, const char* to): _from(from), _toUrl(to), _params(String()), _filter(NULL){
|
||||||
|
int index = _toUrl.indexOf('?');
|
||||||
|
if (index > 0) {
|
||||||
|
_params = _toUrl.substring(index +1);
|
||||||
|
_toUrl = _toUrl.substring(0, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AsyncWebRewrite& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; }
|
||||||
|
bool filter(AsyncWebServerRequest *request) const { return _filter == NULL || _filter(request); }
|
||||||
|
const String& from(void) const { return _from; }
|
||||||
|
const String& toUrl(void) const { return _toUrl; }
|
||||||
|
const String& params(void) const { return _params; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HANDLER :: One instance can be attached to any Request (done by the Server)
|
||||||
|
* */
|
||||||
|
|
||||||
|
class AsyncWebHandler {
|
||||||
|
protected:
|
||||||
|
ArRequestFilterFunction _filter;
|
||||||
|
String _username;
|
||||||
|
String _password;
|
||||||
|
public:
|
||||||
|
AsyncWebHandler():_username(""), _password(""){}
|
||||||
|
AsyncWebHandler& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; }
|
||||||
|
AsyncWebHandler& setAuthentication(const char *username, const char *password){ _username = String(username);_password = String(password); return *this; };
|
||||||
|
bool filter(AsyncWebServerRequest *request){ return _filter == NULL || _filter(request); }
|
||||||
|
virtual ~AsyncWebHandler(){}
|
||||||
|
virtual bool canHandle(AsyncWebServerRequest *request __attribute__((unused))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual void handleRequest(AsyncWebServerRequest *request __attribute__((unused))){}
|
||||||
|
virtual void handleUpload(AsyncWebServerRequest *request __attribute__((unused)), const String& filename __attribute__((unused)), size_t index __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), bool final __attribute__((unused))){}
|
||||||
|
virtual void handleBody(AsyncWebServerRequest *request __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), size_t index __attribute__((unused)), size_t total __attribute__((unused))){}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RESPONSE :: One instance is created for each Request (attached by the Handler)
|
||||||
|
* */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RESPONSE_SETUP, RESPONSE_HEADERS, RESPONSE_CONTENT, RESPONSE_WAIT_ACK, RESPONSE_END, RESPONSE_FAILED
|
||||||
|
} WebResponseState;
|
||||||
|
|
||||||
|
class AsyncWebServerResponse {
|
||||||
|
protected:
|
||||||
|
int _code;
|
||||||
|
LinkedList<AsyncWebHeader *> _headers;
|
||||||
|
String _contentType;
|
||||||
|
size_t _contentLength;
|
||||||
|
bool _sendContentLength;
|
||||||
|
bool _chunked;
|
||||||
|
size_t _headLength;
|
||||||
|
size_t _sentLength;
|
||||||
|
size_t _ackedLength;
|
||||||
|
size_t _writtenLength;
|
||||||
|
WebResponseState _state;
|
||||||
|
const char* _responseCodeToString(int code);
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsyncWebServerResponse();
|
||||||
|
virtual ~AsyncWebServerResponse();
|
||||||
|
virtual void setCode(int code);
|
||||||
|
virtual void setContentLength(size_t len);
|
||||||
|
virtual void setContentType(const String& type);
|
||||||
|
virtual void addHeader(const String& name, const String& value);
|
||||||
|
virtual String _assembleHead(uint8_t version);
|
||||||
|
virtual bool _started() const;
|
||||||
|
virtual bool _finished() const;
|
||||||
|
virtual bool _failed() const;
|
||||||
|
virtual bool _sourceValid() const;
|
||||||
|
virtual void _respond(AsyncWebServerRequest *request);
|
||||||
|
virtual size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SERVER :: One instance
|
||||||
|
* */
|
||||||
|
|
||||||
|
typedef std::function<void(AsyncWebServerRequest *request)> ArRequestHandlerFunction;
|
||||||
|
typedef std::function<void(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final)> ArUploadHandlerFunction;
|
||||||
|
typedef std::function<void(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)> ArBodyHandlerFunction;
|
||||||
|
|
||||||
|
class AsyncWebServer {
|
||||||
|
protected:
|
||||||
|
AsyncServer _server;
|
||||||
|
LinkedList<AsyncWebRewrite*> _rewrites;
|
||||||
|
LinkedList<AsyncWebHandler*> _handlers;
|
||||||
|
AsyncCallbackWebHandler* _catchAllHandler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsyncWebServer(uint16_t port);
|
||||||
|
~AsyncWebServer();
|
||||||
|
|
||||||
|
void begin();
|
||||||
|
|
||||||
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
void onSslFileRequest(AcSSlFileHandler cb, void* arg);
|
||||||
|
void beginSecure(const char *cert, const char *private_key_file, const char *password);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
AsyncWebRewrite& addRewrite(AsyncWebRewrite* rewrite);
|
||||||
|
bool removeRewrite(AsyncWebRewrite* rewrite);
|
||||||
|
AsyncWebRewrite& rewrite(const char* from, const char* to);
|
||||||
|
|
||||||
|
AsyncWebHandler& addHandler(AsyncWebHandler* handler);
|
||||||
|
bool removeHandler(AsyncWebHandler* handler);
|
||||||
|
|
||||||
|
AsyncCallbackWebHandler& on(const char* uri, ArRequestHandlerFunction onRequest);
|
||||||
|
AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest);
|
||||||
|
AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload);
|
||||||
|
AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody);
|
||||||
|
|
||||||
|
AsyncStaticWebHandler& serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_control = NULL);
|
||||||
|
|
||||||
|
void onNotFound(ArRequestHandlerFunction fn); //called when handler is not assigned
|
||||||
|
void onFileUpload(ArUploadHandlerFunction fn); //handle file uploads
|
||||||
|
void onRequestBody(ArBodyHandlerFunction fn); //handle posts with plain body content (JSON often transmitted this way as a request)
|
||||||
|
|
||||||
|
void reset(); //remove all writers and handlers, with onNotFound/onFileUpload/onRequestBody
|
||||||
|
|
||||||
|
void _handleDisconnect(AsyncWebServerRequest *request);
|
||||||
|
void _attachHandler(AsyncWebServerRequest *request);
|
||||||
|
void _rewriteRequest(AsyncWebServerRequest *request);
|
||||||
|
};
|
||||||
|
|
||||||
|
class DefaultHeaders {
|
||||||
|
using headers_t = LinkedList<AsyncWebHeader *>;
|
||||||
|
headers_t _headers;
|
||||||
|
|
||||||
|
DefaultHeaders()
|
||||||
|
:_headers(headers_t([](AsyncWebHeader *h){ delete h; }))
|
||||||
|
{}
|
||||||
|
public:
|
||||||
|
using ConstIterator = headers_t::ConstIterator;
|
||||||
|
|
||||||
|
void addHeader(const String& name, const String& value){
|
||||||
|
_headers.add(new AsyncWebHeader(name, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstIterator begin() const { return _headers.begin(); }
|
||||||
|
ConstIterator end() const { return _headers.end(); }
|
||||||
|
|
||||||
|
DefaultHeaders(DefaultHeaders const &) = delete;
|
||||||
|
DefaultHeaders &operator=(DefaultHeaders const &) = delete;
|
||||||
|
static DefaultHeaders &Instance() {
|
||||||
|
static DefaultHeaders instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "WebResponseImpl.h"
|
||||||
|
#include "WebHandlerImpl.h"
|
||||||
|
#include "AsyncWebSocket.h"
|
||||||
|
#include "AsyncEventSource.h"
|
||||||
|
|
||||||
|
#endif /* _AsyncWebServer_H_ */
|
||||||
544
libraries/ESPAsyncWebServer/src/SPIFFSEditor.cpp
Normal file
544
libraries/ESPAsyncWebServer/src/SPIFFSEditor.cpp
Normal file
@@ -0,0 +1,544 @@
|
|||||||
|
#include "SPIFFSEditor.h"
|
||||||
|
#include <FS.h>
|
||||||
|
|
||||||
|
//File: edit.htm.gz, Size: 4151
|
||||||
|
#define edit_htm_gz_len 4151
|
||||||
|
const uint8_t edit_htm_gz[] PROGMEM = {
|
||||||
|
0x1F, 0x8B, 0x08, 0x08, 0xB8, 0x94, 0xB1, 0x59, 0x00, 0x03, 0x65, 0x64, 0x69, 0x74, 0x2E, 0x68,
|
||||||
|
0x74, 0x6D, 0x00, 0xB5, 0x3A, 0x0B, 0x7B, 0xDA, 0xB8, 0xB2, 0x7F, 0xC5, 0x71, 0xCF, 0x66, 0xED,
|
||||||
|
0x83, 0x31, 0x90, 0xA4, 0xD9, 0xD6, 0xC4, 0xC9, 0x42, 0x92, 0x36, 0x6D, 0xF3, 0x6A, 0x80, 0xB6,
|
||||||
|
0x69, 0x4F, 0xEE, 0x7E, 0xC2, 0x16, 0xA0, 0xC6, 0x96, 0x5D, 0x5B, 0x0E, 0x49, 0x59, 0xFE, 0xFB,
|
||||||
|
0x9D, 0x91, 0x6C, 0xB0, 0x09, 0x69, 0x77, 0xCF, 0xBD, 0xBB, 0xDD, 0x2D, 0x92, 0x46, 0x33, 0x9A,
|
||||||
|
0x19, 0xCD, 0x53, 0xDE, 0xBD, 0x8D, 0xA3, 0x8B, 0xC3, 0xFE, 0xF5, 0xE5, 0xB1, 0x36, 0x11, 0x61,
|
||||||
|
0xB0, 0xBF, 0x87, 0x7F, 0x6B, 0x01, 0xE1, 0x63, 0x97, 0xF2, 0xFD, 0x3D, 0xC1, 0x44, 0x40, 0xF7,
|
||||||
|
0x8F, 0x7B, 0x97, 0xDA, 0xB1, 0xCF, 0x44, 0x94, 0xEC, 0x35, 0xD4, 0xCA, 0x5E, 0x2A, 0x1E, 0x02,
|
||||||
|
0xAA, 0x85, 0xD4, 0x67, 0xC4, 0x4D, 0xBD, 0x84, 0xC2, 0x66, 0xDB, 0x0B, 0x67, 0xDF, 0xEB, 0x8C,
|
||||||
|
0xFB, 0xF4, 0xDE, 0xD9, 0x6E, 0x36, 0xDB, 0x71, 0x94, 0x32, 0xC1, 0x22, 0xEE, 0x90, 0x61, 0x1A,
|
||||||
|
0x05, 0x99, 0xA0, 0xED, 0x80, 0x8E, 0x84, 0xF3, 0x3C, 0xBE, 0x6F, 0x0F, 0xA3, 0xC4, 0xA7, 0x89,
|
||||||
|
0xD3, 0x8A, 0xEF, 0x35, 0x00, 0x31, 0x5F, 0x7B, 0xB6, 0xB3, 0xB3, 0xD3, 0x1E, 0x12, 0xEF, 0x76,
|
||||||
|
0x9C, 0x44, 0x19, 0xF7, 0xEB, 0x5E, 0x14, 0x44, 0x89, 0xF3, 0x6C, 0xF4, 0x1C, 0xFF, 0xB4, 0x7D,
|
||||||
|
0x96, 0xC6, 0x01, 0x79, 0x70, 0x78, 0xC4, 0x29, 0xE0, 0xDE, 0xD7, 0xD3, 0x09, 0xF1, 0xA3, 0xA9,
|
||||||
|
0xD3, 0xD4, 0x9A, 0x5A, 0xAB, 0x09, 0x44, 0x92, 0xF1, 0x90, 0x18, 0x4D, 0x0B, 0xFF, 0xD8, 0x3B,
|
||||||
|
0x66, 0x7B, 0x14, 0x71, 0x51, 0x4F, 0xD9, 0x77, 0xEA, 0xB4, 0xB6, 0xE0, 0x34, 0x39, 0x1D, 0x91,
|
||||||
|
0x90, 0x05, 0x0F, 0x4E, 0x4A, 0x78, 0x5A, 0x4F, 0x69, 0xC2, 0x46, 0x6A, 0x79, 0x4A, 0xD9, 0x78,
|
||||||
|
0x22, 0x9C, 0xDF, 0x9A, 0xCD, 0x39, 0xF0, 0xAF, 0x65, 0xC1, 0x2C, 0x60, 0x29, 0x20, 0xA3, 0x78,
|
||||||
|
0xEA, 0x3C, 0x11, 0xC5, 0x4E, 0x53, 0xB1, 0xDE, 0x6C, 0x87, 0x24, 0x19, 0x33, 0x0E, 0x83, 0x98,
|
||||||
|
0xF8, 0x3E, 0xE3, 0x63, 0x47, 0xA1, 0x05, 0x6C, 0xB6, 0x90, 0x36, 0xA1, 0x01, 0x11, 0xEC, 0x8E,
|
||||||
|
0xB6, 0x43, 0xC6, 0xEB, 0x53, 0xE6, 0x8B, 0x89, 0xB3, 0x0B, 0x3C, 0xB6, 0xBD, 0x2C, 0x49, 0x41,
|
||||||
|
0xA6, 0x38, 0x62, 0x5C, 0xD0, 0x44, 0xA2, 0xA5, 0x31, 0xE1, 0xB3, 0x5C, 0x54, 0x54, 0x40, 0x21,
|
||||||
|
0x27, 0xE3, 0x01, 0xE3, 0xB4, 0x3E, 0x0C, 0x22, 0xEF, 0x76, 0x71, 0xD2, 0x6E, 0x7C, 0x9F, 0x9F,
|
||||||
|
0xE5, 0x4C, 0xA2, 0x3B, 0x9A, 0xCC, 0x96, 0xEA, 0x92, 0xD8, 0x15, 0x60, 0x85, 0x34, 0xA5, 0x74,
|
||||||
|
0x6E, 0x8B, 0xBB, 0x0C, 0xA0, 0x96, 0xFC, 0x05, 0x29, 0x17, 0xFC, 0x2F, 0x45, 0x5A, 0x11, 0x5C,
|
||||||
|
0xA1, 0x30, 0x1E, 0x67, 0x62, 0xF6, 0xF8, 0x2A, 0xA3, 0x98, 0x78, 0x4C, 0x3C, 0xA0, 0xFC, 0xB0,
|
||||||
|
0x6D, 0x86, 0xBA, 0x04, 0xAC, 0x24, 0x24, 0x81, 0x86, 0x3A, 0xD7, 0x3E, 0xD0, 0xC4, 0x27, 0x9C,
|
||||||
|
0x58, 0x9D, 0x84, 0x91, 0xC0, 0xEA, 0x2D, 0xB5, 0x5E, 0x0F, 0xA3, 0xEF, 0xF5, 0x0C, 0xC6, 0x30,
|
||||||
|
0x0F, 0xA8, 0x27, 0x94, 0x92, 0xE1, 0x1E, 0x86, 0xB7, 0x4C, 0x3C, 0x06, 0x3C, 0x5A, 0x28, 0xA9,
|
||||||
|
0x4B, 0x2A, 0x69, 0xA2, 0x2E, 0xB0, 0x25, 0xD5, 0x83, 0x1C, 0x4B, 0xC9, 0x95, 0x50, 0xF5, 0x61,
|
||||||
|
0x24, 0x44, 0x14, 0x4A, 0x93, 0x5B, 0x08, 0xAC, 0x49, 0xAB, 0x79, 0xF1, 0xE8, 0x46, 0xD6, 0x6B,
|
||||||
|
0xBF, 0x44, 0xBE, 0x0D, 0x7A, 0x15, 0xCC, 0x23, 0x41, 0x9D, 0x04, 0x6C, 0xCC, 0x9D, 0x90, 0xF9,
|
||||||
|
0x7E, 0x40, 0x4B, 0x56, 0xEB, 0x64, 0x49, 0x60, 0xF8, 0x44, 0x10, 0x87, 0x85, 0x64, 0x4C, 0x1B,
|
||||||
|
0x31, 0x1F, 0x03, 0x34, 0xA5, 0xBB, 0x3B, 0x16, 0xFB, 0xD0, 0xBD, 0xB8, 0x9A, 0x36, 0xDF, 0xBD,
|
||||||
|
0x1E, 0x47, 0x1D, 0xF8, 0xE7, 0xBC, 0x37, 0x98, 0x1C, 0x0F, 0xC6, 0x30, 0xEA, 0xE2, 0xB4, 0xF3,
|
||||||
|
0xFE, 0xB0, 0xF3, 0x1E, 0x7E, 0x0E, 0x5B, 0xB5, 0xAF, 0xA3, 0x6F, 0xB8, 0xD0, 0x7D, 0xED, 0x77,
|
||||||
|
0xFB, 0x83, 0xE3, 0x4E, 0xE7, 0x5D, 0xE3, 0xCD, 0xF9, 0xF4, 0xE3, 0xBB, 0x5D, 0x04, 0x77, 0x83,
|
||||||
|
0xE6, 0xD5, 0x87, 0x49, 0x73, 0xB0, 0xF5, 0x32, 0xF4, 0x4F, 0xFC, 0x89, 0x17, 0x0E, 0x3A, 0xEF,
|
||||||
|
0x3F, 0x5E, 0xDD, 0x5D, 0x87, 0x83, 0x71, 0xEF, 0x63, 0x6B, 0xF2, 0x79, 0xEB, 0x43, 0xEF, 0xF3,
|
||||||
|
0xC7, 0x57, 0xB7, 0xF4, 0xD3, 0xC9, 0xDB, 0xCF, 0xFD, 0x29, 0x20, 0x1C, 0x45, 0xBD, 0xC1, 0x55,
|
||||||
|
0xF7, 0x43, 0x77, 0xFC, 0xB9, 0xEB, 0x1D, 0xDF, 0x0F, 0x83, 0xF3, 0xEE, 0xEB, 0xCE, 0xB0, 0xB3,
|
||||||
|
0xE5, 0x51, 0x3A, 0xEE, 0x5F, 0x75, 0xB3, 0x37, 0xEF, 0x2E, 0xC6, 0x8C, 0x4D, 0x7A, 0x9F, 0xCF,
|
||||||
|
0xFB, 0xDE, 0xE1, 0xF3, 0xD3, 0xC1, 0x49, 0x87, 0x4D, 0xCE, 0xDF, 0x5E, 0x35, 0x6F, 0x5F, 0xBF,
|
||||||
|
0x3B, 0x3C, 0xF2, 0xAE, 0xDF, 0x5E, 0xEF, 0x1E, 0x6D, 0x37, 0x7E, 0xFB, 0xED, 0xCC, 0xBF, 0x60,
|
||||||
|
0xBC, 0x7F, 0xF7, 0xBD, 0x33, 0x3E, 0x9C, 0xBE, 0x78, 0x48, 0xFB, 0x93, 0x37, 0x77, 0xBC, 0xF1,
|
||||||
|
0x21, 0xFA, 0xFA, 0xE6, 0xE1, 0x0C, 0xFE, 0xBB, 0xBC, 0xAC, 0x0D, 0x7B, 0xAD, 0x74, 0xF0, 0xFE,
|
||||||
|
0xCD, 0x87, 0xAD, 0xF4, 0xE5, 0xF3, 0xB8, 0x7B, 0x74, 0x74, 0x17, 0x0E, 0x2F, 0x1B, 0xA1, 0x7F,
|
||||||
|
0x3B, 0x12, 0x2F, 0xB6, 0x45, 0x7C, 0x3D, 0xCE, 0x3E, 0x7F, 0x7B, 0xFE, 0x76, 0xD2, 0xB8, 0xA0,
|
||||||
|
0xE4, 0x7A, 0x52, 0x7B, 0xF8, 0xFE, 0xF0, 0x62, 0xD2, 0x3F, 0xB9, 0x3B, 0x0F, 0xC8, 0xFD, 0xF9,
|
||||||
|
0xB9, 0xF7, 0x3D, 0xAC, 0x05, 0xE4, 0xE5, 0x45, 0x3F, 0x20, 0x49, 0x6B, 0xE0, 0x77, 0x1A, 0xB5,
|
||||||
|
0xC3, 0xAD, 0xCE, 0x8E, 0x48, 0xAE, 0x0E, 0xF9, 0xD1, 0xF6, 0xD7, 0xDE, 0x8B, 0x6E, 0xB7, 0x15,
|
||||||
|
0x0D, 0xBF, 0x6D, 0xBD, 0xBE, 0xDD, 0x7D, 0x3D, 0xD8, 0x7D, 0x3F, 0x7C, 0xDF, 0xE9, 0xED, 0x74,
|
||||||
|
0x07, 0xE4, 0xBA, 0xF7, 0xBE, 0x33, 0xDA, 0x19, 0x4E, 0x26, 0xEF, 0xDE, 0xF5, 0x5F, 0xF9, 0x9D,
|
||||||
|
0xEF, 0x49, 0xE7, 0x62, 0xDA, 0xB9, 0x3F, 0x1E, 0x74, 0x4E, 0x6A, 0xEF, 0x8E, 0xCF, 0x9A, 0xAD,
|
||||||
|
0xDE, 0xF5, 0xF6, 0xF8, 0x6C, 0x77, 0xDA, 0x4D, 0x8F, 0x3B, 0xEF, 0xBB, 0xCD, 0xF1, 0xDB, 0x5A,
|
||||||
|
0x48, 0x3E, 0x47, 0x87, 0xDB, 0xE3, 0x37, 0xBB, 0xEC, 0xF2, 0x9A, 0x74, 0xDE, 0x74, 0xDF, 0xA6,
|
||||||
|
0xEC, 0x2A, 0x3C, 0x19, 0x34, 0x3B, 0x9D, 0xD3, 0x0B, 0xFA, 0xEA, 0x70, 0x9B, 0xBC, 0xDB, 0xF2,
|
||||||
|
0x3E, 0x82, 0xFE, 0x07, 0x9F, 0xE8, 0x6F, 0xB5, 0xCE, 0xF4, 0xA2, 0x19, 0x78, 0x2F, 0x69, 0xFF,
|
||||||
|
0xE4, 0xBA, 0x2F, 0x6F, 0xE7, 0x38, 0x78, 0xD5, 0xBF, 0xED, 0x65, 0xEF, 0xC3, 0xC3, 0x43, 0x53,
|
||||||
|
0xE3, 0x51, 0x3D, 0xA1, 0x31, 0x25, 0xA2, 0x1C, 0xAE, 0x16, 0xFE, 0x01, 0xB6, 0xB5, 0xB4, 0xC2,
|
||||||
|
0xDC, 0x4F, 0x05, 0xBD, 0x17, 0x75, 0x9F, 0x7A, 0x51, 0x42, 0xE4, 0x1E, 0x40, 0xA0, 0x09, 0x9A,
|
||||||
|
0xD8, 0xFC, 0x77, 0x19, 0x3F, 0x35, 0x15, 0x3F, 0x35, 0xC2, 0x7D, 0xCD, 0x28, 0x1C, 0x01, 0x83,
|
||||||
|
0x87, 0x4F, 0xEF, 0x98, 0x47, 0xEB, 0x31, 0xBB, 0xA7, 0x41, 0x5D, 0x22, 0x3B, 0x4D, 0x73, 0x26,
|
||||||
|
0xFD, 0xAD, 0xD8, 0x46, 0x38, 0x98, 0x9A, 0xA4, 0x5A, 0x2C, 0xF8, 0x5F, 0x89, 0x47, 0x21, 0xB0,
|
||||||
|
0x81, 0xCB, 0x84, 0xF8, 0xAB, 0x7C, 0x27, 0x4A, 0xEA, 0xC3, 0x6C, 0x3C, 0x62, 0xF7, 0xE0, 0xD0,
|
||||||
|
0x23, 0xC6, 0x99, 0xA0, 0x5A, 0x2B, 0x9D, 0xFF, 0x5E, 0x90, 0xB9, 0xA5, 0x0F, 0xA3, 0x84, 0x84,
|
||||||
|
0x34, 0xD5, 0xFE, 0x22, 0x99, 0xD9, 0x28, 0x89, 0xC2, 0x65, 0x10, 0x99, 0x8B, 0xA8, 0x34, 0x99,
|
||||||
|
0xCF, 0x9F, 0x65, 0x71, 0x10, 0x11, 0x10, 0x73, 0x4D, 0xE4, 0x50, 0xF1, 0x34, 0x91, 0x6E, 0xB5,
|
||||||
|
0x88, 0xAB, 0xB9, 0x9B, 0x6D, 0xA1, 0x5B, 0x96, 0xDD, 0x7A, 0x6B, 0x67, 0xE9, 0xBA, 0x75, 0xB9,
|
||||||
|
0x17, 0xE3, 0xFD, 0x9A, 0x4C, 0x81, 0xF1, 0xA0, 0x14, 0xEE, 0x9E, 0x09, 0x50, 0xE9, 0x13, 0x87,
|
||||||
|
0xCB, 0x43, 0xF2, 0xC8, 0xB0, 0x60, 0x40, 0x05, 0xEA, 0x96, 0x8C, 0xD4, 0x85, 0x24, 0xB0, 0x6F,
|
||||||
|
0xFE, 0x8C, 0xCA, 0xBC, 0x67, 0x3D, 0x8B, 0x13, 0xB8, 0x0D, 0x3A, 0xFD, 0x11, 0xCD, 0x42, 0xA6,
|
||||||
|
0x2A, 0x6D, 0x45, 0x53, 0x65, 0xBC, 0x5C, 0x84, 0x65, 0xDA, 0x93, 0xBC, 0x16, 0xA4, 0x1F, 0x4B,
|
||||||
|
0x05, 0xE0, 0x05, 0x37, 0xCF, 0x91, 0x9B, 0x1F, 0x6A, 0x75, 0x7B, 0xF7, 0x97, 0x9C, 0x87, 0x9D,
|
||||||
|
0xE6, 0x2F, 0x73, 0x3B, 0xDF, 0x5B, 0xA4, 0xE4, 0x56, 0x13, 0xFE, 0x29, 0x32, 0xEF, 0x8B, 0x25,
|
||||||
|
0x0B, 0xC3, 0xE7, 0xF8, 0xA7, 0x60, 0x10, 0xE9, 0x94, 0x80, 0xDB, 0x3B, 0x2F, 0x5F, 0xF8, 0xC3,
|
||||||
|
0x02, 0x98, 0x0B, 0xF6, 0x24, 0x3C, 0x21, 0x3E, 0xCB, 0x52, 0xE7, 0x79, 0xF3, 0x97, 0x5C, 0x9F,
|
||||||
|
0x5B, 0x3B, 0x28, 0xFB, 0xE2, 0x2E, 0x71, 0xB2, 0xB4, 0xD8, 0x34, 0x66, 0x5C, 0xDB, 0x4A, 0x35,
|
||||||
|
0xBC, 0x6F, 0x92, 0x2C, 0x0C, 0xB3, 0x92, 0xED, 0xE7, 0xBF, 0x2F, 0x4D, 0x13, 0xF7, 0xCF, 0x9A,
|
||||||
|
0xBF, 0xCC, 0x44, 0x02, 0xD9, 0x64, 0x04, 0xB9, 0xC6, 0x49, 0x22, 0x41, 0x04, 0x35, 0x9A, 0xE6,
|
||||||
|
0x1C, 0x84, 0x5B, 0x03, 0xD8, 0xDE, 0x6D, 0xFA, 0x74, 0x6C, 0xCE, 0xE7, 0x7B, 0x0D, 0x99, 0xD7,
|
||||||
|
0xA0, 0x6C, 0xF1, 0x12, 0x16, 0x8B, 0xFD, 0x51, 0xC6, 0x3D, 0xE4, 0x41, 0x1B, 0x53, 0x83, 0x9A,
|
||||||
|
0xB3, 0x84, 0x8A, 0x2C, 0xE1, 0x9A, 0x1F, 0x79, 0x19, 0x1A, 0xBB, 0x3D, 0xA6, 0xE2, 0x58, 0xD9,
|
||||||
|
0x7D, 0xF7, 0xE1, 0x8D, 0x0F, 0x3B, 0xE6, 0x0B, 0x04, 0x6F, 0x2D, 0x02, 0x38, 0x30, 0x9C, 0x97,
|
||||||
|
0xE3, 0x54, 0xF6, 0x43, 0x82, 0x01, 0x22, 0xEF, 0xE8, 0x83, 0x41, 0x2D, 0xB1, 0x40, 0xA4, 0x36,
|
||||||
|
0xAE, 0x1B, 0xC5, 0x2E, 0x80, 0x71, 0x73, 0x76, 0x07, 0x4A, 0x20, 0x2E, 0xFD, 0x22, 0x6E, 0x2C,
|
||||||
|
0xE6, 0x72, 0xF8, 0x69, 0xE7, 0xBB, 0xC9, 0x1E, 0x3B, 0xA8, 0xB7, 0x1C, 0xB2, 0xCF, 0x0E, 0x5A,
|
||||||
|
0xE0, 0x5E, 0x65, 0x6E, 0xE4, 0xB9, 0xAF, 0x58, 0x40, 0x07, 0xB9, 0xC3, 0xE1, 0x31, 0x48, 0x6C,
|
||||||
|
0xB1, 0x85, 0x28, 0xE2, 0x5B, 0xCD, 0xE6, 0x86, 0x4B, 0x0F, 0x48, 0x00, 0x39, 0xCC, 0xD0, 0x8F,
|
||||||
|
0xAF, 0xAE, 0x2E, 0xAE, 0xBE, 0xE8, 0x35, 0x5A, 0xD3, 0x6F, 0x1C, 0x4D, 0xAF, 0x71, 0xD3, 0x11,
|
||||||
|
0x76, 0x42, 0x47, 0x09, 0x4D, 0x27, 0x97, 0x44, 0x4C, 0x8C, 0xD4, 0xBE, 0x23, 0x41, 0x56, 0x16,
|
||||||
|
0x84, 0xA1, 0xDC, 0xC8, 0xA2, 0x70, 0x39, 0x9D, 0x6A, 0xAF, 0x40, 0xCD, 0x47, 0x90, 0xEA, 0xDA,
|
||||||
|
0xC2, 0x26, 0x71, 0x4C, 0xB9, 0x6F, 0xE8, 0x31, 0x20, 0xEA, 0x16, 0x35, 0xAD, 0x84, 0x7E, 0xCB,
|
||||||
|
0x68, 0x2A, 0x52, 0x1B, 0x2C, 0xD7, 0xD0, 0x2F, 0x07, 0x7D, 0xDD, 0xD2, 0x1B, 0xE8, 0x47, 0x3A,
|
||||||
|
0xF0, 0x46, 0xCC, 0x39, 0x52, 0x89, 0x5C, 0xD0, 0xA4, 0x3E, 0xCC, 0xC0, 0xA0, 0xB8, 0x6E, 0xB6,
|
||||||
|
0x23, 0x9B, 0x71, 0x4E, 0x93, 0x93, 0xFE, 0xD9, 0xA9, 0xAB, 0x5F, 0x29, 0x46, 0xB4, 0x53, 0x28,
|
||||||
|
0x48, 0x74, 0x4B, 0x5E, 0x51, 0x7E, 0xC8, 0xE1, 0x84, 0x05, 0xBE, 0x11, 0x99, 0x6D, 0x24, 0xE1,
|
||||||
|
0x49, 0x12, 0xB2, 0x40, 0x01, 0x0A, 0x9E, 0x2D, 0x1E, 0x62, 0xEA, 0xEA, 0x23, 0x50, 0x86, 0x6E,
|
||||||
|
0x79, 0x76, 0x98, 0x05, 0x82, 0xC5, 0x01, 0x75, 0x37, 0x5A, 0x30, 0xE3, 0x60, 0x41, 0xAE, 0x8E,
|
||||||
|
0xB9, 0x19, 0x61, 0xCC, 0x77, 0x75, 0x15, 0xA1, 0xF2, 0xB8, 0xB6, 0xEE, 0x14, 0x4F, 0x9D, 0x92,
|
||||||
|
0x56, 0x4E, 0x49, 0xCB, 0xB8, 0x4A, 0xE0, 0x34, 0x3F, 0x18, 0xC3, 0x3C, 0xCE, 0xD4, 0x51, 0x05,
|
||||||
|
0xCC, 0xA7, 0x23, 0x02, 0x9C, 0x7C, 0x40, 0x6D, 0xBA, 0x7A, 0x63, 0xDD, 0x41, 0xA9, 0x3A, 0xC8,
|
||||||
|
0xAF, 0x6A, 0xC4, 0x2F, 0x6B, 0x44, 0xDD, 0xEE, 0x3A, 0x64, 0x5F, 0x21, 0x07, 0x55, 0xE4, 0xA0,
|
||||||
|
0x8C, 0x7C, 0x28, 0x8D, 0x64, 0x1D, 0x72, 0xA0, 0x90, 0x93, 0x8A, 0x88, 0x89, 0x14, 0x51, 0x85,
|
||||||
|
0xBD, 0x3A, 0x6A, 0x13, 0x05, 0xD2, 0xAD, 0xA4, 0x22, 0x66, 0x62, 0x83, 0x97, 0x92, 0x61, 0x40,
|
||||||
|
0x7D, 0x77, 0xA3, 0x09, 0x33, 0x2C, 0xB6, 0xDD, 0xAD, 0xE6, 0x9A, 0x33, 0x12, 0x75, 0x46, 0x56,
|
||||||
|
0x65, 0x30, 0x2B, 0x33, 0xA8, 0xF5, 0xC8, 0x1D, 0xD5, 0xD6, 0x31, 0x98, 0x99, 0x56, 0x60, 0x47,
|
||||||
|
0xDC, 0x0B, 0x98, 0x77, 0xEB, 0x2E, 0xBD, 0xC5, 0x9C, 0xB1, 0x85, 0x85, 0x5A, 0x5C, 0x06, 0xBA,
|
||||||
|
0x01, 0x94, 0x5E, 0x8B, 0xA5, 0x7C, 0x80, 0xFA, 0x9E, 0x5B, 0xD9, 0x5A, 0x02, 0xDC, 0xA6, 0xF7,
|
||||||
|
0xD4, 0x3B, 0x8C, 0xC2, 0x90, 0xA0, 0xED, 0xA6, 0xC0, 0x41, 0x3E, 0xD1, 0xCD, 0xB9, 0x15, 0xAD,
|
||||||
|
0xC5, 0x79, 0xC2, 0x45, 0x2C, 0x7F, 0x3D, 0x8B, 0x23, 0x03, 0x5C, 0xCE, 0xF5, 0x6C, 0xD4, 0x61,
|
||||||
|
0x6A, 0x83, 0x1E, 0xC7, 0x62, 0xF2, 0x13, 0x17, 0x2A, 0x0C, 0x54, 0xA2, 0x7C, 0x69, 0xDE, 0x58,
|
||||||
|
0x0B, 0x91, 0x56, 0x7C, 0xEA, 0xA2, 0xB7, 0xE2, 0x54, 0xA8, 0xBC, 0x8A, 0x5D, 0x9A, 0x4B, 0x1D,
|
||||||
|
0x94, 0x61, 0xB9, 0xBD, 0x2F, 0xA0, 0xFA, 0x7C, 0x0E, 0xE7, 0x01, 0xFF, 0x13, 0x68, 0xF9, 0xE8,
|
||||||
|
0x5F, 0x17, 0x60, 0xC9, 0xA3, 0x34, 0x78, 0x8B, 0xBB, 0x0D, 0xE3, 0xC0, 0xF9, 0x8F, 0x6D, 0x7C,
|
||||||
|
0xF9, 0x1F, 0xFB, 0xA6, 0x66, 0x9A, 0x07, 0xFF, 0x6A, 0x48, 0x0D, 0x1B, 0xC2, 0xFC, 0xD2, 0xBA,
|
||||||
|
0xB1, 0x08, 0x80, 0xED, 0x7F, 0x9B, 0xFF, 0xB1, 0x25, 0xB8, 0x02, 0x6B, 0xDF, 0x45, 0x90, 0x49,
|
||||||
|
0xF0, 0x24, 0x34, 0xB0, 0x68, 0xA4, 0x91, 0xCD, 0x4D, 0x43, 0xB8, 0xA4, 0x72, 0x8D, 0x35, 0x51,
|
||||||
|
0xD3, 0x6D, 0x88, 0x53, 0x50, 0x5B, 0xAC, 0x04, 0xBF, 0x3E, 0x24, 0x7A, 0x15, 0x5B, 0x17, 0x00,
|
||||||
|
0xC9, 0x3D, 0xCA, 0x0C, 0x3D, 0x22, 0x97, 0x52, 0xCB, 0x0C, 0x02, 0x42, 0xA7, 0x89, 0xE7, 0x2A,
|
||||||
|
0xAD, 0x1D, 0x14, 0x30, 0x17, 0xA2, 0xE0, 0xBC, 0x1C, 0x2D, 0x15, 0xEA, 0xAA, 0xFD, 0x17, 0x0A,
|
||||||
|
0xA3, 0xD6, 0x12, 0x8A, 0x04, 0x31, 0xAD, 0xD8, 0x79, 0xC6, 0x72, 0x75, 0x4C, 0x59, 0xBA, 0x35,
|
||||||
|
0x59, 0x5D, 0x96, 0xAD, 0x04, 0xAE, 0x2F, 0x8D, 0xFE, 0xD7, 0x3D, 0x16, 0x8E, 0xB5, 0x12, 0x3F,
|
||||||
|
0xF8, 0x97, 0xFB, 0x2B, 0x46, 0xE4, 0xCD, 0x3F, 0xBC, 0x21, 0x70, 0x05, 0xA6, 0x41, 0x6D, 0x1E,
|
||||||
|
0x4D, 0x0D, 0xB3, 0xF6, 0xAB, 0xAE, 0x49, 0x8A, 0xAE, 0x1E, 0x92, 0xFB, 0xBC, 0xA7, 0xC4, 0x8C,
|
||||||
|
0xD7, 0xD6, 0x70, 0x5E, 0xB4, 0x28, 0xF9, 0x82, 0xEC, 0xE6, 0x48, 0x26, 0xA2, 0xB6, 0x56, 0x64,
|
||||||
|
0x52, 0xD5, 0xCA, 0xE8, 0x5A, 0x63, 0xFF, 0xD7, 0x4A, 0x40, 0xB7, 0x98, 0xBA, 0x4E, 0x15, 0x8C,
|
||||||
|
0xB3, 0x00, 0x1C, 0x93, 0x3E, 0x1D, 0x69, 0x03, 0x26, 0x03, 0x75, 0x35, 0x46, 0x5A, 0x81, 0xC1,
|
||||||
|
0xCC, 0x03, 0xC3, 0x2B, 0xFB, 0xF3, 0x1E, 0x16, 0xBF, 0xFB, 0x97, 0xAA, 0xAA, 0x81, 0xD4, 0x8B,
|
||||||
|
0x33, 0x5D, 0x59, 0x59, 0xD5, 0x4B, 0xE0, 0xD2, 0x08, 0xA0, 0x5B, 0x8B, 0x3C, 0x3A, 0x8C, 0xFC,
|
||||||
|
0x87, 0x52, 0xF6, 0x4D, 0xBB, 0x0F, 0x87, 0x01, 0x49, 0xD3, 0x73, 0xB8, 0x01, 0x43, 0xF7, 0x42,
|
||||||
|
0x50, 0xB8, 0xB2, 0xC2, 0xFD, 0xE6, 0xE6, 0x66, 0x15, 0x29, 0xA1, 0x21, 0x14, 0xDB, 0x8A, 0x2B,
|
||||||
|
0xF0, 0x49, 0xD3, 0xF1, 0x81, 0x30, 0x18, 0xD2, 0x1A, 0xC6, 0xF0, 0x25, 0xE3, 0x47, 0x5C, 0x71,
|
||||||
|
0xF4, 0xF4, 0x22, 0xA6, 0xFC, 0x33, 0xDC, 0x95, 0x32, 0xCB, 0x1A, 0xAD, 0xA6, 0x68, 0xFA, 0x8F,
|
||||||
|
0xD8, 0x3E, 0xCA, 0x0D, 0x76, 0xC1, 0x7A, 0xBA, 0x56, 0xA1, 0xFC, 0x9F, 0x61, 0xB9, 0x94, 0x28,
|
||||||
|
0xD6, 0x70, 0x9C, 0x40, 0x80, 0x5A, 0xC3, 0x31, 0xC4, 0x1A, 0x41, 0x17, 0xFC, 0x26, 0x6B, 0xF9,
|
||||||
|
0xCD, 0xFE, 0x19, 0x7E, 0x97, 0x76, 0x1E, 0x15, 0x25, 0x91, 0xAA, 0xAF, 0x50, 0x02, 0x9F, 0xDD,
|
||||||
|
0xE9, 0xA6, 0x15, 0xB9, 0x55, 0x0A, 0x50, 0x1B, 0x46, 0x41, 0xD0, 0x8F, 0xE2, 0x83, 0x27, 0xD6,
|
||||||
|
0x9D, 0xC5, 0x7A, 0x31, 0xC8, 0xD9, 0x5C, 0x6E, 0xB1, 0xBC, 0xB5, 0x44, 0x4F, 0xA1, 0xEC, 0x5F,
|
||||||
|
0x4B, 0x15, 0x01, 0x3F, 0x23, 0x8B, 0x7B, 0xAC, 0xD4, 0xA5, 0x36, 0x28, 0x0F, 0x56, 0x3F, 0xD5,
|
||||||
|
0x3C, 0xCB, 0x5F, 0xCC, 0xAE, 0x6B, 0x51, 0x9B, 0xC0, 0x38, 0x57, 0x92, 0x8B, 0x4A, 0xB2, 0xC8,
|
||||||
|
0x13, 0x01, 0xA8, 0x58, 0xC7, 0x2E, 0xC4, 0x4D, 0x6B, 0x7A, 0x7C, 0xBF, 0x5C, 0x83, 0xC2, 0xDF,
|
||||||
|
0xF5, 0xD5, 0x12, 0x33, 0x08, 0xC4, 0xD3, 0x95, 0x4B, 0x29, 0x5F, 0x37, 0x29, 0x8A, 0x0E, 0x62,
|
||||||
|
0x47, 0xA3, 0x51, 0x4A, 0xC5, 0x47, 0x0C, 0x49, 0x56, 0xB2, 0x98, 0x9F, 0xC8, 0x90, 0x04, 0x8C,
|
||||||
|
0x45, 0x3C, 0x8C, 0xB2, 0x94, 0x46, 0x99, 0xA8, 0xA4, 0x16, 0x63, 0x21, 0xCC, 0x5E, 0xFA, 0xE7,
|
||||||
|
0x9F, 0x8B, 0xC9, 0x7E, 0x5A, 0x0B, 0x96, 0xD3, 0xEB, 0x3D, 0xBF, 0x34, 0xD9, 0xF7, 0x6B, 0x89,
|
||||||
|
0xB9, 0x7A, 0xE9, 0xFF, 0x67, 0x4B, 0x21, 0x65, 0x4B, 0xF1, 0xB0, 0x54, 0x2E, 0x62, 0x62, 0x29,
|
||||||
|
0xE6, 0xC9, 0x82, 0x91, 0x97, 0x7C, 0x16, 0x0D, 0x1A, 0x2B, 0x25, 0x55, 0x9E, 0x97, 0x7D, 0x95,
|
||||||
|
0x43, 0x40, 0x59, 0x71, 0xE5, 0x35, 0x11, 0x06, 0x34, 0xE0, 0x63, 0x64, 0xF2, 0x41, 0xEB, 0xA7,
|
||||||
|
0xD1, 0x94, 0x26, 0x87, 0x24, 0xA5, 0x06, 0x24, 0xCD, 0x65, 0xDC, 0x41, 0xA8, 0xE9, 0x04, 0xEB,
|
||||||
|
0x76, 0x6D, 0x6E, 0x12, 0x05, 0xCE, 0x33, 0x77, 0xC4, 0xB1, 0x26, 0x03, 0xF9, 0xB2, 0xCA, 0x09,
|
||||||
|
0xD4, 0xC6, 0xBE, 0x12, 0xA4, 0x3E, 0x52, 0x25, 0xA8, 0x61, 0x5A, 0xD0, 0x76, 0xC0, 0x35, 0x5F,
|
||||||
|
0x26, 0x51, 0x4C, 0xC6, 0xB2, 0x07, 0x83, 0x35, 0x74, 0x0F, 0xA4, 0x66, 0x6D, 0x34, 0x91, 0x60,
|
||||||
|
0xA9, 0x73, 0x29, 0xFC, 0x66, 0xD9, 0xC2, 0x70, 0x4B, 0x57, 0xC9, 0xB0, 0xBD, 0xF4, 0xA5, 0x35,
|
||||||
|
0x59, 0x83, 0xE0, 0x0B, 0x6C, 0x62, 0xE0, 0x1E, 0x68, 0x64, 0xF2, 0x7B, 0x00, 0x77, 0x6B, 0xB6,
|
||||||
|
0xA3, 0x3D, 0xD6, 0x8E, 0x6A, 0x35, 0x53, 0x55, 0xE9, 0xAE, 0x0B, 0x6D, 0x4E, 0x74, 0x23, 0x0B,
|
||||||
|
0x4B, 0x10, 0xAA, 0x9A, 0x59, 0x0C, 0x38, 0x1B, 0x81, 0xAA, 0xBA, 0xC0, 0x11, 0xD6, 0x98, 0x66,
|
||||||
|
0xA9, 0x23, 0xF1, 0x97, 0x1D, 0xC9, 0x13, 0xB5, 0x07, 0x95, 0xF5, 0x05, 0xD4, 0x31, 0xAB, 0x25,
|
||||||
|
0x86, 0x30, 0xD3, 0x29, 0x13, 0xDE, 0x04, 0x03, 0x90, 0x07, 0x5A, 0xD5, 0x05, 0x14, 0xB5, 0x8E,
|
||||||
|
0x1C, 0x4D, 0x44, 0xB8, 0x1C, 0x05, 0xF9, 0xF0, 0x6B, 0x9A, 0x0F, 0xBC, 0xB4, 0x18, 0xDD, 0x97,
|
||||||
|
0x80, 0x50, 0xD2, 0xE6, 0xE0, 0x88, 0x8F, 0xF2, 0x21, 0xF4, 0xB2, 0x05, 0x9D, 0x02, 0x58, 0xFC,
|
||||||
|
0xC6, 0x71, 0x3E, 0x8A, 0x27, 0xC5, 0x68, 0x42, 0xEF, 0x17, 0x78, 0x51, 0x01, 0xF5, 0xA9, 0xEE,
|
||||||
|
0x28, 0x1B, 0xDB, 0x68, 0xCE, 0xF3, 0x41, 0x6B, 0x29, 0x7F, 0xF0, 0xFF, 0x28, 0x7F, 0xCC, 0xC7,
|
||||||
|
0x85, 0x34, 0x71, 0x31, 0x1A, 0xB3, 0x42, 0x96, 0x61, 0x18, 0xFF, 0x90, 0x93, 0xA4, 0xD4, 0x13,
|
||||||
|
0x97, 0x7A, 0x5A, 0xF1, 0xB3, 0xB6, 0x53, 0x98, 0x8E, 0x31, 0xAA, 0xF8, 0xE3, 0xC8, 0xF6, 0xF0,
|
||||||
|
0xF7, 0x3C, 0xF2, 0x65, 0x6D, 0x69, 0x5A, 0xA1, 0x31, 0x82, 0x3A, 0x57, 0x37, 0xCB, 0x7E, 0x9A,
|
||||||
|
0xFD, 0xB7, 0xAD, 0xE8, 0xD1, 0xF1, 0xE9, 0x71, 0xFF, 0xB8, 0x5C, 0x38, 0x23, 0xE7, 0x25, 0x93,
|
||||||
|
0x8A, 0x2B, 0x5D, 0xFA, 0xB2, 0x22, 0x80, 0x02, 0x1B, 0x45, 0x01, 0x7B, 0xDD, 0xDC, 0x54, 0x7E,
|
||||||
|
0xF1, 0xB6, 0x77, 0x71, 0x6E, 0xC7, 0x24, 0x01, 0x8F, 0x24, 0x15, 0xE6, 0xC2, 0x82, 0x44, 0xF9,
|
||||||
|
0xE0, 0xD7, 0xC7, 0xA5, 0x72, 0x5D, 0x7E, 0x61, 0x70, 0xC4, 0xDC, 0x52, 0xA7, 0xA9, 0x7E, 0x78,
|
||||||
|
0xE2, 0x62, 0x5D, 0x99, 0xBF, 0x04, 0x41, 0x72, 0x1A, 0x2D, 0x13, 0x55, 0x11, 0x67, 0x46, 0xE5,
|
||||||
|
0x30, 0x2F, 0xEE, 0xB2, 0x75, 0x0D, 0xD3, 0xC8, 0xB4, 0xC4, 0x84, 0xA5, 0xE5, 0x46, 0xA5, 0x12,
|
||||||
|
0x14, 0xFE, 0xA2, 0xB6, 0xE7, 0x8B, 0x91, 0x24, 0xB7, 0x5A, 0x73, 0xAB, 0x6F, 0x41, 0x2A, 0x3E,
|
||||||
|
0x58, 0x04, 0x23, 0x66, 0x39, 0xDB, 0x16, 0x77, 0xA3, 0x43, 0xEE, 0x61, 0x5C, 0x7F, 0xBA, 0x35,
|
||||||
|
0x78, 0xD2, 0x3C, 0x79, 0x61, 0x9E, 0xFC, 0xB1, 0x7B, 0x2E, 0x1C, 0x45, 0xF9, 0xDA, 0xE2, 0x98,
|
||||||
|
0xF6, 0x10, 0x58, 0xBB, 0x6D, 0x2F, 0x7D, 0x18, 0x20, 0xD2, 0x83, 0xCB, 0x00, 0xF4, 0x63, 0x58,
|
||||||
|
0xFF, 0x4A, 0xEE, 0x88, 0x7A, 0x09, 0xAA, 0xA2, 0xAD, 0x73, 0x54, 0xD8, 0xEE, 0xFD, 0x81, 0xA3,
|
||||||
|
0xF2, 0xCE, 0x65, 0x18, 0x48, 0x97, 0xC3, 0x92, 0x37, 0x8B, 0x75, 0xC1, 0x61, 0x19, 0x31, 0x64,
|
||||||
|
0x6C, 0x00, 0xE3, 0xCD, 0x5D, 0x49, 0x13, 0xD5, 0x1C, 0xB4, 0xF0, 0x1B, 0x08, 0x8A, 0x4F, 0x39,
|
||||||
|
0xCE, 0x9A, 0x38, 0xAD, 0x62, 0x72, 0xC5, 0x23, 0xC8, 0x4A, 0x67, 0x89, 0xC0, 0x6E, 0x10, 0x0D,
|
||||||
|
0x0D, 0x7C, 0x64, 0x9A, 0xA1, 0xB6, 0x1D, 0x3E, 0x37, 0xD7, 0xBC, 0xD9, 0x54, 0xFA, 0x4B, 0x62,
|
||||||
|
0x79, 0xD5, 0xB0, 0x8B, 0x1C, 0x56, 0xCC, 0x75, 0x7D, 0x1F, 0xF4, 0xA3, 0x4E, 0x29, 0xAF, 0x48,
|
||||||
|
0xA4, 0x53, 0xD1, 0x83, 0xC4, 0x86, 0xA2, 0x41, 0xBE, 0x91, 0x40, 0x44, 0x72, 0x4A, 0x33, 0x5D,
|
||||||
|
0xC7, 0xCA, 0xD2, 0x0B, 0x28, 0x49, 0x7A, 0xB2, 0x73, 0x95, 0x49, 0x6B, 0x25, 0x06, 0xFE, 0xC8,
|
||||||
|
0xD7, 0xF0, 0xC7, 0xA1, 0xD0, 0xA3, 0x83, 0x9B, 0x49, 0x2B, 0x83, 0xA4, 0x23, 0x64, 0x83, 0xA9,
|
||||||
|
0x37, 0xE4, 0xBB, 0xA8, 0x2D, 0x2F, 0xCB, 0xB4, 0x16, 0x50, 0x70, 0x71, 0x83, 0xBB, 0x11, 0x30,
|
||||||
|
0x52, 0x5A, 0xC4, 0x9E, 0x94, 0xA8, 0xC7, 0x8F, 0x10, 0x1F, 0x53, 0x4A, 0x20, 0x06, 0x20, 0xA6,
|
||||||
|
0x40, 0xD0, 0xA7, 0x42, 0x8A, 0x54, 0xE6, 0x92, 0x53, 0x2A, 0x20, 0xCA, 0x48, 0xCD, 0xE2, 0xC1,
|
||||||
|
0x85, 0x78, 0xD4, 0x46, 0xD6, 0x80, 0xFD, 0xDC, 0xBD, 0x73, 0x33, 0xDE, 0x90, 0x68, 0x09, 0x56,
|
||||||
|
0x36, 0x3D, 0x9A, 0xA6, 0x52, 0x5C, 0x54, 0xC7, 0x19, 0xF8, 0xA8, 0xA1, 0x03, 0x5A, 0x23, 0x84,
|
||||||
|
0x11, 0x1E, 0x84, 0x8A, 0x01, 0x40, 0x7F, 0x42, 0xC3, 0x1C, 0x22, 0x70, 0x08, 0x20, 0x82, 0xA0,
|
||||||
|
0x7F, 0x49, 0x0D, 0xF7, 0x64, 0x05, 0xC9, 0xF8, 0xD8, 0x6D, 0x35, 0xF0, 0x9D, 0x66, 0x95, 0xEC,
|
||||||
|
0x20, 0xA5, 0xBD, 0x68, 0x24, 0xFA, 0x64, 0x98, 0x1A, 0x50, 0x00, 0xAC, 0xD9, 0x01, 0xA0, 0x1E,
|
||||||
|
0x24, 0x5E, 0x63, 0x2B, 0x3F, 0xEF, 0x04, 0x2A, 0xBB, 0x00, 0xAB, 0xBB, 0x8E, 0x87, 0x5F, 0x39,
|
||||||
|
0x4F, 0x19, 0xA7, 0x39, 0x26, 0x00, 0x7B, 0x93, 0x68, 0x7A, 0x99, 0x30, 0x2E, 0xCE, 0x64, 0x1B,
|
||||||
|
0x6A, 0x6C, 0xB4, 0xE4, 0xF5, 0xA9, 0x87, 0x15, 0x79, 0x3F, 0xC5, 0x8B, 0xCB, 0x0C, 0xF3, 0xBA,
|
||||||
|
0x53, 0x79, 0x77, 0xB1, 0x86, 0x70, 0x21, 0x50, 0x66, 0x38, 0xB3, 0x29, 0x74, 0xB0, 0xFA, 0xA1,
|
||||||
|
0x48, 0x82, 0x7A, 0x4F, 0xB7, 0x42, 0xE2, 0xC1, 0x44, 0xED, 0x81, 0xF9, 0xDC, 0xC2, 0xD8, 0xE1,
|
||||||
|
0x94, 0x83, 0x5A, 0x0A, 0xB5, 0x02, 0x45, 0xC6, 0x95, 0xCD, 0x98, 0x35, 0x1D, 0x6A, 0x58, 0x88,
|
||||||
|
0x61, 0xE0, 0xAF, 0xFE, 0x05, 0x0F, 0x1E, 0x1C, 0xC8, 0x55, 0x3F, 0xE1, 0x23, 0xE3, 0x7E, 0xF4,
|
||||||
|
0x23, 0x3E, 0x3E, 0xAF, 0xF0, 0xF1, 0x79, 0x1D, 0x1F, 0xB4, 0xAA, 0x3C, 0x98, 0x0C, 0x80, 0xEC,
|
||||||
|
0x19, 0xE1, 0x64, 0x4C, 0x13, 0x58, 0xC0, 0x43, 0x50, 0x25, 0x7F, 0x8B, 0xB3, 0x84, 0xFE, 0x98,
|
||||||
|
0xB3, 0xDE, 0x84, 0x8D, 0xC4, 0x23, 0xFE, 0x8A, 0xD5, 0xFF, 0x82, 0x4B, 0x3C, 0x70, 0x3D, 0x97,
|
||||||
|
0x79, 0x6D, 0x5A, 0x49, 0x28, 0x3F, 0x7E, 0x2B, 0x91, 0x7E, 0xE4, 0x42, 0x78, 0xA9, 0x38, 0xC8,
|
||||||
|
0xDF, 0xB7, 0xF4, 0x00, 0xBC, 0x11, 0xF8, 0x29, 0x35, 0x75, 0xBC, 0x0B, 0xA5, 0xFC, 0x29, 0x30,
|
||||||
|
0x64, 0xA8, 0xC0, 0x47, 0xDD, 0xD9, 0xDC, 0x12, 0xAE, 0x01, 0x8A, 0xF1, 0xA3, 0x29, 0xB0, 0xEA,
|
||||||
|
0xC9, 0x02, 0xD7, 0x9E, 0x40, 0x26, 0x04, 0x91, 0xE0, 0x48, 0xC8, 0xA7, 0x8D, 0x2F, 0x07, 0x9B,
|
||||||
|
0x37, 0x35, 0xC8, 0x43, 0x2E, 0xFC, 0x98, 0x2E, 0x0C, 0x36, 0x6F, 0xFE, 0x6D, 0x36, 0xC6, 0xCC,
|
||||||
|
0x5A, 0x76, 0xA4, 0x96, 0x4C, 0xF6, 0xF4, 0x0B, 0xBF, 0x71, 0x09, 0x48, 0x5D, 0x49, 0x78, 0x45,
|
||||||
|
0x34, 0x03, 0x6B, 0x43, 0x61, 0xE1, 0x07, 0xFF, 0x47, 0x09, 0xF8, 0x91, 0x9E, 0x07, 0xCE, 0xBD,
|
||||||
|
0xE6, 0x3D, 0x5E, 0x2F, 0x3E, 0x85, 0xE9, 0x56, 0xE9, 0xC1, 0x4A, 0xC7, 0xEF, 0x53, 0x3A, 0x76,
|
||||||
|
0x59, 0xA2, 0x14, 0x4A, 0x14, 0x59, 0x88, 0x1A, 0x6A, 0x50, 0x0E, 0x51, 0x98, 0x89, 0x17, 0xCD,
|
||||||
|
0x81, 0x02, 0x9B, 0x73, 0x34, 0x5B, 0x3A, 0x02, 0x0F, 0xF4, 0xF5, 0x45, 0xEE, 0xFC, 0x74, 0x76,
|
||||||
|
0x7A, 0x22, 0x44, 0x7C, 0xA5, 0x62, 0x22, 0xD0, 0xAA, 0x2E, 0x2C, 0x2F, 0xCF, 0x9C, 0x89, 0xE4,
|
||||||
|
0xA1, 0x28, 0x75, 0x30, 0x31, 0x28, 0x87, 0xFE, 0x74, 0x31, 0xFC, 0x0A, 0x71, 0xD6, 0xD0, 0xCF,
|
||||||
|
0x52, 0x48, 0x58, 0x5B, 0x36, 0xA2, 0xF7, 0xFB, 0x97, 0xF6, 0xAE, 0xDD, 0x84, 0xBA, 0x00, 0xB4,
|
||||||
|
0x0A, 0x69, 0x19, 0xEE, 0x7D, 0xFE, 0xB7, 0x90, 0xB7, 0xFF, 0x1E, 0x32, 0x83, 0xA8, 0x95, 0x42,
|
||||||
|
0x58, 0x2A, 0xF0, 0xAB, 0xB8, 0x93, 0x24, 0x9A, 0x4A, 0xB4, 0xE3, 0x24, 0xC1, 0x4B, 0xE9, 0x43,
|
||||||
|
0x85, 0xA2, 0x0D, 0x61, 0x31, 0xA5, 0x89, 0xE6, 0x47, 0x34, 0xD5, 0x78, 0x24, 0xB4, 0x34, 0x8B,
|
||||||
|
0x63, 0x68, 0x5C, 0x56, 0xF4, 0x61, 0xEB, 0xC5, 0xEB, 0xCB, 0xFB, 0x8C, 0x66, 0xD4, 0xCF, 0x97,
|
||||||
|
0x69, 0x52, 0xD1, 0x0B, 0x56, 0x50, 0xDF, 0x10, 0xEE, 0x7E, 0xB9, 0xC9, 0xEB, 0xA9, 0x8C, 0x73,
|
||||||
|
0x8C, 0xA2, 0x1B, 0x2D, 0x35, 0x07, 0xE9, 0x26, 0x40, 0xD5, 0xE5, 0x59, 0x10, 0xCC, 0xDB, 0x2B,
|
||||||
|
0xB4, 0xA0, 0xF1, 0x8A, 0x44, 0x24, 0x9F, 0xCB, 0x67, 0x7F, 0xE4, 0xC9, 0xA9, 0xE2, 0x82, 0x50,
|
||||||
|
0xF2, 0x54, 0xA9, 0x36, 0xAD, 0x0D, 0x63, 0x83, 0x6A, 0x8C, 0xA7, 0x82, 0x70, 0x0F, 0xAF, 0x51,
|
||||||
|
0xE9, 0xC2, 0x2C, 0x6A, 0x29, 0xDC, 0xDE, 0x46, 0x5F, 0xCB, 0x6D, 0xE9, 0x89, 0x7C, 0x2A, 0x25,
|
||||||
|
0xE3, 0xAE, 0xAE, 0x63, 0x55, 0x45, 0xB1, 0x3E, 0x25, 0x61, 0x5A, 0x26, 0x5B, 0x54, 0x06, 0x26,
|
||||||
|
0x77, 0x0B, 0x70, 0x9B, 0x06, 0x29, 0x1C, 0xBD, 0x7E, 0x7F, 0xCE, 0x46, 0xD1, 0xCE, 0x11, 0x80,
|
||||||
|
0x69, 0xC5, 0x3E, 0x93, 0xD7, 0xE0, 0x24, 0xCC, 0x73, 0x07, 0x32, 0xE9, 0x4A, 0x03, 0x0E, 0xA9,
|
||||||
|
0x98, 0x44, 0xFE, 0x81, 0x7E, 0xA0, 0x3B, 0x3A, 0xFC, 0xBB, 0x09, 0x35, 0x47, 0xCD, 0xA5, 0xD0,
|
||||||
|
0xA4, 0xFA, 0x74, 0x70, 0xF5, 0x06, 0xC2, 0x53, 0x0C, 0xA5, 0x01, 0x17, 0x50, 0x34, 0xD7, 0x74,
|
||||||
|
0x7C, 0x7A, 0x7D, 0x0C, 0x29, 0xC8, 0x7F, 0x21, 0x37, 0x66, 0xBB, 0xAA, 0x6C, 0xB8, 0xF3, 0xEA,
|
||||||
|
0x75, 0x56, 0x2E, 0x03, 0x7A, 0x61, 0x8C, 0x58, 0x0F, 0x29, 0x7E, 0xFB, 0x7B, 0xF4, 0x9E, 0x8D,
|
||||||
|
0x15, 0xD2, 0x6A, 0x5D, 0x6F, 0xCE, 0x76, 0x90, 0x67, 0x89, 0xD5, 0x43, 0x2C, 0x70, 0x97, 0x1F,
|
||||||
|
0x29, 0x59, 0x95, 0x35, 0xDC, 0xF6, 0x48, 0x10, 0xE0, 0xC7, 0x5A, 0x03, 0x1B, 0x6A, 0x22, 0xB2,
|
||||||
|
0xD4, 0x42, 0x22, 0x29, 0x08, 0x90, 0xD2, 0x3E, 0x84, 0x39, 0xD3, 0x92, 0x65, 0x86, 0xB2, 0xA1,
|
||||||
|
0xBC, 0xFF, 0xC5, 0x9A, 0xA3, 0x64, 0x46, 0xE8, 0xCE, 0xF9, 0x6C, 0x73, 0x53, 0xD8, 0x85, 0x99,
|
||||||
|
0x18, 0x05, 0x52, 0x8A, 0x01, 0x1C, 0x9A, 0x7D, 0x68, 0x2D, 0x8C, 0xB2, 0x90, 0x58, 0xAB, 0x3D,
|
||||||
|
0xD2, 0xB6, 0x51, 0x55, 0x03, 0x54, 0x7C, 0x46, 0x01, 0x03, 0xCE, 0xB2, 0x24, 0x80, 0xA8, 0x8B,
|
||||||
|
0x39, 0xBA, 0xB2, 0x2D, 0xC5, 0xBA, 0xD0, 0x84, 0x0E, 0xEC, 0x67, 0xC8, 0x12, 0x95, 0x97, 0xAD,
|
||||||
|
0xA2, 0x27, 0x12, 0xC5, 0x77, 0x95, 0x9E, 0xC8, 0x6F, 0xE5, 0x84, 0xAA, 0xC8, 0x77, 0x88, 0x2F,
|
||||||
|
0x13, 0x5C, 0xD4, 0xD1, 0x13, 0xA0, 0x24, 0x83, 0x52, 0x34, 0x60, 0x2A, 0x2C, 0x37, 0xEE, 0xEB,
|
||||||
|
0xD3, 0xE9, 0xB4, 0x8E, 0xDF, 0x6A, 0xEB, 0x70, 0x82, 0xB2, 0x02, 0x5F, 0x5F, 0xC7, 0x21, 0x47,
|
||||||
|
0x15, 0x58, 0xF8, 0x6E, 0xE1, 0xAC, 0xBA, 0xE8, 0x42, 0x7F, 0x2B, 0xDE, 0xD4, 0xAA, 0xD2, 0x59,
|
||||||
|
0xE1, 0x73, 0x79, 0xDB, 0x7B, 0x3B, 0x2B, 0x20, 0x32, 0xC4, 0xAF, 0xB2, 0x90, 0x69, 0x20, 0x0D,
|
||||||
|
0x3B, 0xE5, 0x46, 0x56, 0x25, 0x85, 0x65, 0x5C, 0xB0, 0xE3, 0x2C, 0x9D, 0x18, 0x33, 0x60, 0xDD,
|
||||||
|
0x11, 0x96, 0xD2, 0x95, 0x43, 0x2D, 0x65, 0xB7, 0x0E, 0xB7, 0x0A, 0xFB, 0x70, 0x30, 0x83, 0x94,
|
||||||
|
0x79, 0xFB, 0xF3, 0x4F, 0x39, 0x5B, 0xDE, 0xF6, 0x92, 0x62, 0x71, 0xE1, 0xF3, 0xFC, 0xA9, 0x35,
|
||||||
|
0xAF, 0x69, 0xA5, 0xD1, 0xAF, 0xC4, 0x97, 0xBD, 0x46, 0xFE, 0x19, 0x3B, 0xFF, 0x9C, 0xAD, 0x81,
|
||||||
|
0xB1, 0x43, 0x23, 0x2A, 0xDC, 0x4C, 0x8C, 0xEA, 0x2F, 0x34, 0xE6, 0x63, 0x79, 0x29, 0xBF, 0x2D,
|
||||||
|
0xA0, 0x54, 0xA9, 0xD3, 0x68, 0x78, 0x3E, 0xFF, 0x9A, 0x42, 0x19, 0x1D, 0x65, 0xFE, 0x28, 0x20,
|
||||||
|
0x09, 0xC5, 0x82, 0xA3, 0x41, 0xBE, 0x92, 0xFB, 0x46, 0xC0, 0x86, 0x69, 0x03, 0x93, 0x6D, 0xCB,
|
||||||
|
0xDE, 0xB2, 0x77, 0x71, 0x64, 0x7F, 0x4D, 0xF7, 0x57, 0x4F, 0xD8, 0x5F, 0x34, 0x69, 0x58, 0x0B,
|
||||||
|
0xE7, 0xB5, 0xAB, 0x8A, 0x4D, 0x6A, 0x83, 0xFB, 0xC4, 0xA7, 0x70, 0x3D, 0x6F, 0xB3, 0xCC, 0xB6,
|
||||||
|
0x1A, 0xE4, 0x5F, 0x60, 0xD4, 0x31, 0xBA, 0x95, 0x2F, 0x92, 0xF4, 0x81, 0x7B, 0x18, 0x5B, 0x17,
|
||||||
|
0x54, 0x26, 0x70, 0x49, 0xD5, 0x87, 0x34, 0xB9, 0xD3, 0x9C, 0x2F, 0x39, 0xC3, 0xB7, 0x3C, 0xA8,
|
||||||
|
0x03, 0xE4, 0x37, 0x9C, 0x72, 0x39, 0xB0, 0xBF, 0x07, 0x5D, 0x33, 0x2A, 0x41, 0x79, 0xB1, 0x26,
|
||||||
|
0x9B, 0xE6, 0x7C, 0x02, 0x82, 0x01, 0x70, 0xB1, 0xA3, 0x48, 0xCD, 0x2B, 0xCB, 0x98, 0x9B, 0x57,
|
||||||
|
0x96, 0x54, 0xE2, 0x5F, 0x59, 0xCC, 0xDB, 0x9F, 0xFC, 0xDB, 0x4C, 0xF9, 0x7F, 0x5B, 0x28, 0x36,
|
||||||
|
0x32, 0xF9, 0xE1, 0x09, 0xF7, 0x56, 0x3F, 0x45, 0xAD, 0x47, 0x51, 0xBB, 0xF7, 0xFF, 0x17, 0x53,
|
||||||
|
0xE8, 0x9D, 0x36, 0x92, 0x29, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SPIFFS_MAXLENGTH_FILEPATH 32
|
||||||
|
const char *excludeListFile = "/.exclude.files";
|
||||||
|
|
||||||
|
typedef struct ExcludeListS {
|
||||||
|
char *item;
|
||||||
|
ExcludeListS *next;
|
||||||
|
} ExcludeList;
|
||||||
|
|
||||||
|
static ExcludeList *excludes = NULL;
|
||||||
|
|
||||||
|
static bool matchWild(const char *pattern, const char *testee) {
|
||||||
|
const char *nxPat = NULL, *nxTst = NULL;
|
||||||
|
|
||||||
|
while (*testee) {
|
||||||
|
if (( *pattern == '?' ) || (*pattern == *testee)){
|
||||||
|
pattern++;testee++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*pattern=='*'){
|
||||||
|
nxPat=pattern++; nxTst=testee;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nxPat){
|
||||||
|
pattern = nxPat+1; testee=++nxTst;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (*pattern=='*'){pattern++;}
|
||||||
|
return (*pattern == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool addExclude(const char *item){
|
||||||
|
size_t len = strlen(item);
|
||||||
|
if(!len){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ExcludeList *e = (ExcludeList *)malloc(sizeof(ExcludeList));
|
||||||
|
if(!e){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
e->item = (char *)malloc(len+1);
|
||||||
|
if(!e->item){
|
||||||
|
free(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(e->item, item, len+1);
|
||||||
|
e->next = excludes;
|
||||||
|
excludes = e;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loadExcludeList(fs::FS &_fs, const char *filename){
|
||||||
|
static char linebuf[SPIFFS_MAXLENGTH_FILEPATH];
|
||||||
|
fs::File excludeFile=_fs.open(filename, "r");
|
||||||
|
if(!excludeFile){
|
||||||
|
//addExclude("/*.js.gz");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef ESP32
|
||||||
|
if(excludeFile.isDirectory()){
|
||||||
|
excludeFile.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (excludeFile.size() > 0){
|
||||||
|
uint8_t idx;
|
||||||
|
bool isOverflowed = false;
|
||||||
|
while (excludeFile.available()){
|
||||||
|
linebuf[0] = '\0';
|
||||||
|
idx = 0;
|
||||||
|
int lastChar;
|
||||||
|
do {
|
||||||
|
lastChar = excludeFile.read();
|
||||||
|
if(lastChar != '\r'){
|
||||||
|
linebuf[idx++] = (char) lastChar;
|
||||||
|
}
|
||||||
|
} while ((lastChar >= 0) && (lastChar != '\n') && (idx < SPIFFS_MAXLENGTH_FILEPATH));
|
||||||
|
|
||||||
|
if(isOverflowed){
|
||||||
|
isOverflowed = (lastChar != '\n');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
isOverflowed = (idx >= SPIFFS_MAXLENGTH_FILEPATH);
|
||||||
|
linebuf[idx-1] = '\0';
|
||||||
|
if(!addExclude(linebuf)){
|
||||||
|
excludeFile.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
excludeFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isExcluded(fs::FS &_fs, const char *filename) {
|
||||||
|
if(excludes == NULL){
|
||||||
|
loadExcludeList(_fs, excludeListFile);
|
||||||
|
}
|
||||||
|
ExcludeList *e = excludes;
|
||||||
|
while(e){
|
||||||
|
if (matchWild(e->item, filename)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
e = e->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WEB HANDLER IMPLEMENTATION
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
SPIFFSEditor::SPIFFSEditor(const fs::FS& fs, const String& username, const String& password)
|
||||||
|
#else
|
||||||
|
SPIFFSEditor::SPIFFSEditor(const String& username, const String& password, const fs::FS& fs)
|
||||||
|
#endif
|
||||||
|
:_fs(fs)
|
||||||
|
,_username(username)
|
||||||
|
,_password(password)
|
||||||
|
,_authenticated(false)
|
||||||
|
,_startTime(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool SPIFFSEditor::canHandle(AsyncWebServerRequest *request){
|
||||||
|
if(request->url().equalsIgnoreCase("/edit")){
|
||||||
|
if(request->method() == HTTP_GET){
|
||||||
|
if(request->hasParam("list"))
|
||||||
|
return true;
|
||||||
|
if(request->hasParam("edit")){
|
||||||
|
request->_tempFile = _fs.open(request->arg("edit"), "r");
|
||||||
|
if(!request->_tempFile){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#ifdef ESP32
|
||||||
|
if(request->_tempFile.isDirectory()){
|
||||||
|
request->_tempFile.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if(request->hasParam("download")){
|
||||||
|
request->_tempFile = _fs.open(request->arg("download"), "r");
|
||||||
|
if(!request->_tempFile){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#ifdef ESP32
|
||||||
|
if(request->_tempFile.isDirectory()){
|
||||||
|
request->_tempFile.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
request->addInterestingHeader("If-Modified-Since");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(request->method() == HTTP_POST)
|
||||||
|
return true;
|
||||||
|
else if(request->method() == HTTP_DELETE)
|
||||||
|
return true;
|
||||||
|
else if(request->method() == HTTP_PUT)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SPIFFSEditor::handleRequest(AsyncWebServerRequest *request){
|
||||||
|
if(_username.length() && _password.length() && !request->authenticate(_username.c_str(), _password.c_str()))
|
||||||
|
return request->requestAuthentication();
|
||||||
|
|
||||||
|
if(request->method() == HTTP_GET){
|
||||||
|
if(request->hasParam("list")){
|
||||||
|
String path = request->getParam("list")->value();
|
||||||
|
#ifdef ESP32
|
||||||
|
File dir = _fs.open(path);
|
||||||
|
#else
|
||||||
|
Dir dir = _fs.openDir(path);
|
||||||
|
#endif
|
||||||
|
path = String();
|
||||||
|
String output = "[";
|
||||||
|
#ifdef ESP32
|
||||||
|
File entry = dir.openNextFile();
|
||||||
|
while(entry){
|
||||||
|
#else
|
||||||
|
while(dir.next()){
|
||||||
|
fs::File entry = dir.openFile("r");
|
||||||
|
#endif
|
||||||
|
if (isExcluded(_fs, entry.name())) {
|
||||||
|
#ifdef ESP32
|
||||||
|
entry = dir.openNextFile();
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (output != "[") output += ',';
|
||||||
|
output += "{\"type\":\"";
|
||||||
|
output += "file";
|
||||||
|
output += "\",\"name\":\"";
|
||||||
|
output += String(entry.name());
|
||||||
|
output += "\",\"size\":";
|
||||||
|
output += String(entry.size());
|
||||||
|
output += "}";
|
||||||
|
#ifdef ESP32
|
||||||
|
entry = dir.openNextFile();
|
||||||
|
#else
|
||||||
|
entry.close();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef ESP32
|
||||||
|
dir.close();
|
||||||
|
#endif
|
||||||
|
output += "]";
|
||||||
|
request->send(200, "text/json", output);
|
||||||
|
output = String();
|
||||||
|
}
|
||||||
|
else if(request->hasParam("edit") || request->hasParam("download")){
|
||||||
|
request->send(request->_tempFile, request->_tempFile.name(), String(), request->hasParam("download"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const char * buildTime = __DATE__ " " __TIME__ " GMT";
|
||||||
|
if (request->header("If-Modified-Since").equals(buildTime)) {
|
||||||
|
request->send(304);
|
||||||
|
} else {
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", edit_htm_gz, edit_htm_gz_len);
|
||||||
|
response->addHeader("Content-Encoding", "gzip");
|
||||||
|
response->addHeader("Last-Modified", buildTime);
|
||||||
|
request->send(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(request->method() == HTTP_DELETE){
|
||||||
|
if(request->hasParam("path", true)){
|
||||||
|
_fs.remove(request->getParam("path", true)->value());
|
||||||
|
request->send(200, "", "DELETE: "+request->getParam("path", true)->value());
|
||||||
|
} else
|
||||||
|
request->send(404);
|
||||||
|
} else if(request->method() == HTTP_POST){
|
||||||
|
if(request->hasParam("data", true, true) && _fs.exists(request->getParam("data", true, true)->value()))
|
||||||
|
request->send(200, "", "UPLOADED: "+request->getParam("data", true, true)->value());
|
||||||
|
else
|
||||||
|
request->send(500);
|
||||||
|
} else if(request->method() == HTTP_PUT){
|
||||||
|
if(request->hasParam("path", true)){
|
||||||
|
String filename = request->getParam("path", true)->value();
|
||||||
|
if(_fs.exists(filename)){
|
||||||
|
request->send(200);
|
||||||
|
} else {
|
||||||
|
fs::File f = _fs.open(filename, "w");
|
||||||
|
if(f){
|
||||||
|
f.write((uint8_t)0x00);
|
||||||
|
f.close();
|
||||||
|
request->send(200, "", "CREATE: "+filename);
|
||||||
|
} else {
|
||||||
|
request->send(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
request->send(400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPIFFSEditor::handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){
|
||||||
|
if(!index){
|
||||||
|
if(!_username.length() || request->authenticate(_username.c_str(),_password.c_str())){
|
||||||
|
_authenticated = true;
|
||||||
|
request->_tempFile = _fs.open(filename, "w");
|
||||||
|
_startTime = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(_authenticated && request->_tempFile){
|
||||||
|
if(len){
|
||||||
|
request->_tempFile.write(data,len);
|
||||||
|
}
|
||||||
|
if(final){
|
||||||
|
request->_tempFile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
libraries/ESPAsyncWebServer/src/SPIFFSEditor.h
Normal file
23
libraries/ESPAsyncWebServer/src/SPIFFSEditor.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef SPIFFSEditor_H_
|
||||||
|
#define SPIFFSEditor_H_
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|
||||||
|
class SPIFFSEditor: public AsyncWebHandler {
|
||||||
|
private:
|
||||||
|
fs::FS _fs;
|
||||||
|
String _username;
|
||||||
|
String _password;
|
||||||
|
bool _authenticated;
|
||||||
|
uint32_t _startTime;
|
||||||
|
public:
|
||||||
|
#ifdef ESP32
|
||||||
|
SPIFFSEditor(const fs::FS& fs, const String& username=String(), const String& password=String());
|
||||||
|
#else
|
||||||
|
SPIFFSEditor(const String& username=String(), const String& password=String(), const fs::FS& fs=SPIFFS);
|
||||||
|
#endif
|
||||||
|
virtual bool canHandle(AsyncWebServerRequest *request) override final;
|
||||||
|
virtual void handleRequest(AsyncWebServerRequest *request) override final;
|
||||||
|
virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
193
libraries/ESPAsyncWebServer/src/StringArray.h
Normal file
193
libraries/ESPAsyncWebServer/src/StringArray.h
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
Asynchronous WebServer library for Espressif MCUs
|
||||||
|
|
||||||
|
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef STRINGARRAY_H_
|
||||||
|
#define STRINGARRAY_H_
|
||||||
|
|
||||||
|
#include "stddef.h"
|
||||||
|
#include "WString.h"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class LinkedListNode {
|
||||||
|
T _value;
|
||||||
|
public:
|
||||||
|
LinkedListNode<T>* next;
|
||||||
|
LinkedListNode(const T val): _value(val), next(nullptr) {}
|
||||||
|
~LinkedListNode(){}
|
||||||
|
const T& value() const { return _value; };
|
||||||
|
T& value(){ return _value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, template<typename> class Item = LinkedListNode>
|
||||||
|
class LinkedList {
|
||||||
|
public:
|
||||||
|
typedef Item<T> ItemType;
|
||||||
|
typedef std::function<void(const T&)> OnRemove;
|
||||||
|
typedef std::function<bool(const T&)> Predicate;
|
||||||
|
private:
|
||||||
|
ItemType* _root;
|
||||||
|
OnRemove _onRemove;
|
||||||
|
|
||||||
|
class Iterator {
|
||||||
|
ItemType* _node;
|
||||||
|
public:
|
||||||
|
Iterator(ItemType* current = nullptr) : _node(current) {}
|
||||||
|
Iterator(const Iterator& i) : _node(i._node) {}
|
||||||
|
Iterator& operator ++() { _node = _node->next; return *this; }
|
||||||
|
bool operator != (const Iterator& i) const { return _node != i._node; }
|
||||||
|
const T& operator * () const { return _node->value(); }
|
||||||
|
const T* operator -> () const { return &_node->value(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef const Iterator ConstIterator;
|
||||||
|
ConstIterator begin() const { return ConstIterator(_root); }
|
||||||
|
ConstIterator end() const { return ConstIterator(nullptr); }
|
||||||
|
|
||||||
|
LinkedList(OnRemove onRemove) : _root(nullptr), _onRemove(onRemove) {}
|
||||||
|
~LinkedList(){}
|
||||||
|
void add(const T& t){
|
||||||
|
auto it = new ItemType(t);
|
||||||
|
if(!_root){
|
||||||
|
_root = it;
|
||||||
|
} else {
|
||||||
|
auto i = _root;
|
||||||
|
while(i->next) i = i->next;
|
||||||
|
i->next = it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
T& front() const {
|
||||||
|
return _root->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const {
|
||||||
|
return _root == nullptr;
|
||||||
|
}
|
||||||
|
size_t length() const {
|
||||||
|
size_t i = 0;
|
||||||
|
auto it = _root;
|
||||||
|
while(it){
|
||||||
|
i++;
|
||||||
|
it = it->next;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
size_t count_if(Predicate predicate) const {
|
||||||
|
size_t i = 0;
|
||||||
|
auto it = _root;
|
||||||
|
while(it){
|
||||||
|
if (!predicate){
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (predicate(it->value())) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
it = it->next;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
const T* nth(size_t N) const {
|
||||||
|
size_t i = 0;
|
||||||
|
auto it = _root;
|
||||||
|
while(it){
|
||||||
|
if(i++ == N)
|
||||||
|
return &(it->value());
|
||||||
|
it = it->next;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
bool remove(const T& t){
|
||||||
|
auto it = _root;
|
||||||
|
auto pit = _root;
|
||||||
|
while(it){
|
||||||
|
if(it->value() == t){
|
||||||
|
if(it == _root){
|
||||||
|
_root = _root->next;
|
||||||
|
} else {
|
||||||
|
pit->next = it->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_onRemove) {
|
||||||
|
_onRemove(it->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
delete it;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
pit = it;
|
||||||
|
it = it->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool remove_first(Predicate predicate){
|
||||||
|
auto it = _root;
|
||||||
|
auto pit = _root;
|
||||||
|
while(it){
|
||||||
|
if(predicate(it->value())){
|
||||||
|
if(it == _root){
|
||||||
|
_root = _root->next;
|
||||||
|
} else {
|
||||||
|
pit->next = it->next;
|
||||||
|
}
|
||||||
|
if (_onRemove) {
|
||||||
|
_onRemove(it->value());
|
||||||
|
}
|
||||||
|
delete it;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
pit = it;
|
||||||
|
it = it->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(){
|
||||||
|
while(_root != nullptr){
|
||||||
|
auto it = _root;
|
||||||
|
_root = _root->next;
|
||||||
|
if (_onRemove) {
|
||||||
|
_onRemove(it->value());
|
||||||
|
}
|
||||||
|
delete it;
|
||||||
|
}
|
||||||
|
_root = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class StringArray : public LinkedList<String> {
|
||||||
|
public:
|
||||||
|
|
||||||
|
StringArray() : LinkedList(nullptr) {}
|
||||||
|
|
||||||
|
bool containsIgnoreCase(const String& str){
|
||||||
|
for (const auto& s : *this) {
|
||||||
|
if (str.equalsIgnoreCase(s)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* STRINGARRAY_H_ */
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user