mirror of
				https://github.com/luc-github/ESP3D.git
				synced 2025-10-24 11:50:52 -07:00 
			
		
		
		
	2.0
This commit is contained in:
		
							
								
								
									
										66
									
								
								.gitlab-ci.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								.gitlab-ci.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| before_script: | ||||
|     - cd $HOME | ||||
|     - wget https://pypi.python.org/packages/df/c9/d9da7fafaf2a2b323d20eee050503ab08237c16b0119c7bbf1597d53f793/pyserial-2.7.tar.gz#md5=794506184df83ef2290de0d18803dd11 | ||||
|     - tar -xvf  pyserial-2.7.tar.gz | ||||
|     - cd pyserial-2.7 | ||||
|     - python ./setup.py install | ||||
|     - wget http://downloads.arduino.cc/arduino-1.8.0-linux64.tar.xz | ||||
|     - tar xf ./arduino-1.8.0-linux64.tar.xz | ||||
|     - mv arduino-1.8.0 $HOME/arduino_ide | ||||
|     - cd $HOME/arduino_ide/hardware | ||||
|     - mkdir esp8266com | ||||
|     - cd esp8266com | ||||
|     - git clone https://github.com/esp8266/Arduino.git esp8266 | ||||
|     - cd esp8266/tools | ||||
|     - python get.py | ||||
|     - cd .. | ||||
|     - touch pt.txt | ||||
|     - echo 'build.flash_ld=eagle.flash.4m.ld' >> pt.txt | ||||
|     - echo 'build.flash_freq=40' >> pt.txt | ||||
|     - echo 'build.flash_size=4M' >> pt.txt | ||||
|     - echo 'build.f_cpu=160000000L' >> pt.txt | ||||
|     - echo 'build.flash_mode=dio' >> pt.txt | ||||
|     - cat ./platform.txt >> pt.txt | ||||
|     - rm -fr platform.txt | ||||
|     - mv pt.txt platform.txt | ||||
|     - mv $CI_PROJECT_DIR/libraries/SdFat/SdFat $HOME/arduino_ide/libraries/ | ||||
|     - mv $CI_PROJECT_DIR/libraries/IniFile $HOME/arduino_ide/libraries/ | ||||
|     - mv $CI_PROJECT_DIR/libraries/ESPAsyncWebServer $HOME/arduino_ide/libraries/ | ||||
|     - mv $CI_PROJECT_DIR/libraries/ESPAsyncTCP $HOME/arduino_ide/libraries/ | ||||
|     - mv $CI_PROJECT_DIR/libraries/AsyncTCP $HOME/arduino_ide/libraries/ | ||||
|     - mv $CI_PROJECT_DIR/libraries/oled-ssd1306 $HOME/arduino_ide/libraries/ | ||||
|     - mv $CI_PROJECT_DIR/libraries/ESP32SSDP $HOME/arduino_ide/libraries/ | ||||
|     - mv $CI_PROJECT_DIR/libraries/arduinoWebSockets $HOME/arduino_ide/libraries/ | ||||
|     - mv $CI_PROJECT_DIR/libraries/DHT_sensor_library_for_ESPx $HOME/arduino_ide/libraries/ | ||||
|     - mkdir $HOME/arduino_ide/libraries/ESP3D | ||||
|     - mv $CI_PROJECT_DIR/src $HOME/arduino_ide/libraries/ESP3D | ||||
|     - mv $CI_PROJECT_DIR/library.properties $HOME/arduino_ide/libraries/ESP3D | ||||
|     - cd $HOME/arduino_ide/hardware  | ||||
|     - mkdir esp32 | ||||
|     - cd esp32 | ||||
|     - git clone https://github.com/espressif/arduino-esp32.git esp32 | ||||
|     - cd esp32 | ||||
|     - cd tools | ||||
|     - python get.py | ||||
|     - cd .. | ||||
|     - touch pt.txt | ||||
|     - echo 'build.flash_freq=80m' >> pt.txt | ||||
|     - cat ./platform.txt >> pt.txt | ||||
|     - rm -fr platform.txt | ||||
|     - mv pt.txt platform.txt | ||||
|    | ||||
| job1: | ||||
|     script: | ||||
|       - cd $CI_PROJECT_DIR | ||||
|       - source command.sh | ||||
|       - export PATH="$HOME/arduino_ide:$PATH" | ||||
|       - arduino --get-pref | ||||
|       - arduino --board esp8266com:esp8266:generic --save-prefs | ||||
|       - sed -i "s/\/\/#define SDCARD_FEATURE /#define SDCARD_FEATURE/g" $HOME/arduino_ide/libraries/ESP3D/src/config.h | ||||
|       - echo "build ESP8266" | ||||
|       - build_sketch  $CI_PROJECT_DIR/examples/basicesp3d/basicesp3d.ino | ||||
|       - arduino --board esp32:esp32:esp32 --save-prefs | ||||
|       - echo "build ESP32" | ||||
|       - build_sketch  $CI_PROJECT_DIR/examples/basicesp3d/basicesp3d.ino | ||||
|        | ||||
|  | ||||
							
								
								
									
										32
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -11,9 +11,9 @@ before_install: | ||||
| before_script: | ||||
|   - "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
		Reference in New Issue
	
	Block a user