mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-09-19 13:13:14 +08:00
2.0
This commit is contained in:
parent
c95fe416f0
commit
02bd840a7a
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:
|
||||
- "export DISPLAY=:99.0"
|
||||
- sleep 3 # give xvfb some time to start
|
||||
- wget http://downloads.arduino.cc/arduino-1.8.4-linux64.tar.xz
|
||||
- tar xf arduino-1.8.4-linux64.tar.xz
|
||||
- mv arduino-1.8.4 $HOME/arduino_ide
|
||||
- wget http://downloads.arduino.cc/arduino-1.8.5-linux64.tar.xz
|
||||
- tar xf arduino-1.8.5-linux64.tar.xz
|
||||
- mv arduino-1.8.5 $HOME/arduino_ide
|
||||
- cd $HOME/arduino_ide/hardware
|
||||
- mkdir esp8266com
|
||||
- cd esp8266com
|
||||
@ -35,6 +35,16 @@ before_script:
|
||||
- python get.py
|
||||
- cd ..
|
||||
- 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:
|
||||
@ -43,9 +53,21 @@ script:
|
||||
- export PATH="$HOME/arduino_ide:$PATH"
|
||||
- arduino --board esp8266com:esp8266:generic --save-prefs
|
||||
- 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
|
||||
- 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:
|
||||
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)
|
||||
|
||||
@ -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.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)
|
||||
|
||||
[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)
|
||||
* 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)
|
||||
* 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)
|
||||
* 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)
|
||||
* 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.
|
||||
* 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
|
||||
|
||||
|
||||
@ -70,6 +71,7 @@ Mask: 255.255.255.0
|
||||
GW:192.168.0.1
|
||||
Baud rate: 115200
|
||||
Web port:80
|
||||
On async webserver the websocket is web port => 80+1 : 81
|
||||
Data port: 8888
|
||||
Web Page refresh: 3 secondes
|
||||
User: admin
|
||||
@ -84,14 +86,27 @@ Check wiki : https://github.com/luc-github/ESP3D/wiki/Direct-ESP3D-commands
|
||||
|
||||
## 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)
|
||||
2. Add missing libraries if you target ESP32 present in libraries directory
|
||||
* DNSServer (from https://github.com/bbx10/DNSServer_tng)
|
||||
* WebServer (from https://github.com/bbx10/WebServer_tng)
|
||||
* NetBIOS and SSDP are currently disabled for ESP32 as not yet supported
|
||||
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.
|
||||
2. Add libraries
|
||||
* ESP3D because it is now a library so copy project to your arduino library folder
|
||||
If you want async webserver (currently not recommended for ESP8266, suggested for ESP32):
|
||||
* ESPAsyncWebServer from @me-no-dev
|
||||
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)
|
||||
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
|
||||
or
|
||||
* 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
|
||||
<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
|
||||
* 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
|
||||
* 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)
|
||||
* 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 ?
|
||||
[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 :
|
||||
* 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...
|
||||
|
||||
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
|
||||
[ESP112]<header answer>
|
||||
|
||||
* Restart time client
|
||||
[ESP114]
|
||||
|
||||
*Get/Set pin value
|
||||
[ESP201]P<pin> V<value> [PULLUP=YES RAW=YES]pwd=<admin password>
|
||||
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 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
|
||||
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)
|
||||
[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)
|
||||
output is JSON or plain text according parameter
|
||||
[ESP410]<plain>
|
||||
@ -109,7 +151,7 @@ if no password set it use default one
|
||||
* Get fw target
|
||||
[ESP801]<header answer>
|
||||
|
||||
* Clear status/error/info list
|
||||
cmd can be ALL, ERROR, INFO, STATUS
|
||||
[ESP999]<cmd>
|
||||
* Check SD presence
|
||||
[ESP802]
|
||||
|
||||
|
||||
|
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);
|
||||
for (var i3 = 0; i3 < files.length; 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);}
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open('POST', '/files', true);
|
||||
@ -175,6 +178,9 @@ document.getElementById('prgfw').style.visibility = "visible";
|
||||
var formData = new FormData();
|
||||
for (var i4 = 0; i4 < files.length; 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);}
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open('POST', '/updatefw', true);
|
||||
|
@ -6,11 +6,12 @@
|
||||
</head>
|
||||
<body>
|
||||
<div style="position:absolute;top:0;right:0;">
|
||||
V1.1
|
||||
V1.2
|
||||
|
||||
</div>
|
||||
<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>
|
||||
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>
|
||||
|
||||
<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.
|
||||
Supports only one simultaneous client, knows how to handle GET and POST.
|
||||
basic esp3d sample
|
||||
|
||||
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
|
||||
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
|
||||
License along with this library; if not, write to the Free Software
|
||||
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
|
||||
#define ESP8266WEBSERVER_H
|
||||
//Setup
|
||||
void setup()
|
||||
{
|
||||
myesp3d.begin();
|
||||
}
|
||||
|
||||
#include <WebServer.h>
|
||||
|
||||
#endif //ESP8266WEBSERVER_H
|
||||
//main loop
|
||||
void loop()
|
||||
{
|
||||
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
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
{one line to give the program's name and a brief idea of what it does.}
|
||||
Copyright (C) {year} {name of author}
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -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
|
||||
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 is free software, and you are welcome to redistribute it
|
||||
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
Loading…
x
Reference in New Issue
Block a user