mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-08-11 05:59:02 +08:00
Merge Development version to master
This commit is contained in:
parent
628436cb9c
commit
13ee5e19e8
31
.travis.yml
31
.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.0-linux64.tar.xz
|
||||
- tar xf arduino-1.8.0-linux64.tar.xz
|
||||
- mv arduino-1.8.0 $HOME/arduino_ide
|
||||
- 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
|
||||
- cd $HOME/arduino_ide/hardware
|
||||
- mkdir esp8266com
|
||||
- cd esp8266com
|
||||
@ -21,13 +21,22 @@ before_script:
|
||||
- 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
|
||||
- cat ./platform.txt >> pt.txt
|
||||
- rm -fr platform.txt
|
||||
- mv pt.txt platform.txt
|
||||
- echo 'build.flash_ld=eagle.flash.4m.ld' >> platform.txt
|
||||
- echo 'build.flash_freq=40' >> platform.txt
|
||||
- echo 'build.flash_size=4M' >> platform.txt
|
||||
- echo 'build.flash_mode=dio' >> platform.txt
|
||||
- echo 'build.f_cpu=160000000L' >> platform.txt
|
||||
- sed -i "s/generic.build.f_cpu=80000000L/generic.build.f_cpu=160000000L/g" ./boards.txt
|
||||
- cd $HOME/arduino_ide/hardware
|
||||
- mkdir esp32
|
||||
- cd esp32
|
||||
- git clone https://github.com/espressif/arduino-esp32.git esp32
|
||||
- cd esp32/tools
|
||||
- python get.py
|
||||
- cd ..
|
||||
- echo 'build.flash_freq=40m' >> platform.txt
|
||||
- mv $TRAVIS_BUILD_DIR/libraries/WebServer $HOME/arduino_ide/hardware/esp32/esp32/libraries/
|
||||
- mv $TRAVIS_BUILD_DIR/libraries/DNSServer $HOME/arduino_ide/hardware/esp32/esp32/libraries/
|
||||
|
||||
|
||||
script:
|
||||
@ -37,6 +46,8 @@ script:
|
||||
- arduino --board esp8266com:esp8266:generic --save-prefs
|
||||
- arduino --get-pref sketchbook.path
|
||||
- build_sketch esp3d/esp3d.ino
|
||||
- arduino --board esp32:esp32:esp32 --save-prefs
|
||||
- build_sketch esp3d/esp3d.ino
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
294
README.md
294
README.md
@ -1,29 +1,32 @@
|
||||
# ESP3D[](https://codeclimate.com/github/luc-github/ESP3D)
|
||||
|
||||
Firmware for ESP8266/ESP8285 used with 3D printer using [arduino core version](https://github.com/esp8266/Arduino)
|
||||
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)
|
||||
|
||||
This firmware allows not only to have a cheap bridge between Wifi and serial, but also to have a web UI to configure wifi, to monitor 3D printer and even control it, and to make things easy,
|
||||
UI is fully customizable without reflashing FW.
|
||||
Firmware should work with any 3D printer firmware (repetier/marlin/etc..) if serial connection has correct setup.
|
||||
I currently use it with my personnal flavor of [repetier for Due based boards](https://github.com/luc-github/Repetier-Firmware-0.92).
|
||||
Please use ESP with at least 1M flash, for ESP with 512K there is limited version [here](https://github.com/luc-github/ESP3D/tree/ESP-512K-64KSPIFFS)
|
||||
|
||||
<u>Stable version:</u>
|
||||
Firmware should work with any 3D printer firmware (repetier/marlin/smoothieware using GCODE) if serial connection has a correct setup.
|
||||
I currently use it with my personnal flavor of [repetier for Due based boards](https://github.com/luc-github/Repetier-Firmware-0.92).
|
||||
|
||||
The web interface files are present in data directory but UI has it's own repository [ESP3D-WEBUI](https://github.com/luc-github/ESP3D-WEBUI).
|
||||
* be aware ESP3D-WEBUI is for firmware 0.9.99 minimum - previous released version use tpl files which are no more used.
|
||||
|
||||
<u>Stable version (ESP8266 only):</u>
|
||||
Arduino ide 1.6.5 with stable [2.0.0](http://arduino.esp8266.com/versions/2.0.0/package_esp8266com_index.json) from ESP8266, please use https://github.com/luc-github/ESP3D/releases/tag/v0.5.1
|
||||
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
|
||||
|
||||
<u>Development version:</u>
|
||||
Arduino ide 1.8.0 with git from ESP8266 : [](https://travis-ci.org/luc-github/ESP3D)
|
||||
<u>RC version for 1.0(master branch) very stable but waiting for 2.4 release of ESP8266:</u>
|
||||
Arduino ide 1.8.4 with git version from ESP8266 or ESP32 : [](https://travis-ci.org/luc-github/ESP3D)
|
||||
|
||||
<u>Development version for 2.0 (asyncwebserver branch) pre alpha :</u>
|
||||
Arduino ide 1.8.4 with git version from ESP8266 or ESP32 : [](https://travis-ci.org/luc-github/ESP3D)
|
||||
|
||||
[All releases](https://github.com/luc-github/ESP3D/wiki)
|
||||
|
||||
:question:Any question ? check [Wiki](https://github.com/luc-github/ESP3D/wiki/Install-Instructions) or [](https://gitter.im/luc-github/ESP3D?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
:exclamation:Any issue ? check [Wiki](https://github.com/luc-github/ESP3D/wiki/Install-Instructions) and [FAQ](https://github.com/luc-github/ESP3D/issues?utf8=%E2%9C%93&q=label%3AFAQ+) or [submit ticket](https://github.com/luc-github/ESP3D/issues)
|
||||
|
||||
|
||||
:+1:Thanks
|
||||
* to @disneysw for bringing this module idea
|
||||
* to @lkarlslund for suggestion about independent reset using GPIO2
|
||||
* to all contributors (treepleks, j0hnlittle, openhardwarecoza, TRoager, all feedbacks owners and donations)
|
||||
* to all contributors, feedbacks owners and donations.
|
||||
|
||||
Every support is welcome: [<img src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG_global.gif" border="0" alt="PayPal – The safer, easier way to pay online.">](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Y8FFE7NA4LJWQ)
|
||||
Especially if need to buy new modules for testing.
|
||||
@ -31,7 +34,7 @@ Especially if need to buy new modules for testing.
|
||||
##Features
|
||||
* Serial/Wifi bridge using configurable port 8888, here to enable/disable [TCP_IP_DATA_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
||||
* Use GPIO2 to ground to reset all settings in hard way - 2-6 sec after boot / not before!! Set GPIO2 to ground before boot change boot mode and go to special boot that do not reach FW. Currently boot take 10 sec - giving 8 seconds to connect GPIO2 to GND and do an hard recovery for settings, here to enable/disable [RECOVERY_FEATURE](https://github.com/luc-github/ESP8266/blob/master/esp8266/config.h)
|
||||
* Wifi configuration by web browser (Station or Access point)
|
||||
* Complete configuration by web browser (Station or Access point) or by Serial commands
|
||||
* 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)
|
||||
@ -41,6 +44,8 @@ Especially if need to buy new modules for testing.
|
||||
* 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.
|
||||
* The web ui add even more feature : https://github.com/luc-github/ESP3D-WEBUI/blob/master/README.md#features
|
||||
|
||||
|
||||
##Web configuration
|
||||
*Wifi Mode : Access point / Client station
|
||||
@ -63,7 +68,7 @@ IP Mode: Static IP
|
||||
IP: 192.168.0.1
|
||||
Mask: 255.255.255.0
|
||||
GW:192.168.0.1
|
||||
Baud rate: 9600
|
||||
Baud rate: 115200
|
||||
Web port:80
|
||||
Data port: 8888
|
||||
Web Page refresh: 3 secondes
|
||||
@ -72,168 +77,163 @@ Password: admin
|
||||
User:user
|
||||
Password: user
|
||||
|
||||
These are the pages defined using template:
|
||||
Home page :
|
||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/UI/Page1.png><br>
|
||||
System Configuration Page:
|
||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/UI/Page2.png><br>
|
||||
Access Point Configuration Page:
|
||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/UI/Page3.png><br>
|
||||
Client Configuration Page:
|
||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/UI/Page4.png><br>
|
||||
Printer Status Page for 64K SPIFFS, due to limited space available no fancy:
|
||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/UI/Page5-2.png><br>
|
||||
Printer Status Page for more than 64K SPIFFS, fancy one:
|
||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/UI/page5.png><br>
|
||||
Extra Settings Page, for web UI and for printer:
|
||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/UI/Page6.png><br>
|
||||
Change password Page:
|
||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/UI/Page7.png><br>
|
||||
Login Page:
|
||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/UI/Page8.png><br>
|
||||
the template files are stored on SPIFFS:
|
||||
<img src=https://raw.githubusercontent.com/luc-github/ESP3D/master/images/UI/files.png><br>
|
||||
and uploaded using [pluggin IDE](http://esp8266.github.io/Arduino/versions/2.1.0/doc/filesystem.html#uploading-files-to-file-system)
|
||||
Any files on SPIFFS can be called on web interface without having the path hard coded, this give more flexibility, favicon.ico is a good example of it.
|
||||
So UI is kind of separated from FW which allow easier modifications. For this a light file manager is available in extra settings page, it allows to upload/download/delete files.
|
||||
Because SPIFFS is flat filesystem, no directory management is necessary, so it is very simple.
|
||||
|
||||
Additionally 404.tpl (the page not found) and restart.tpl(restart page when applying changes) are not mandatory, a fail safe version is embedded if they are not present.
|
||||
|
||||
##Direct commands:
|
||||
```
|
||||
* Change STA SSID
|
||||
[ESP100]<SSID>
|
||||
if authentication is on, need admin password
|
||||
[ESP100]<SSID>pwd=<admin password>
|
||||
* Change STA SSID
|
||||
[ESP100]<SSID>
|
||||
if authentication is on, need admin password
|
||||
[ESP100]<SSID>pwd=<admin password>
|
||||
|
||||
* Change STA Password
|
||||
[ESP101]<Password>
|
||||
if authentication is on, need admin password
|
||||
[ESP101]<Password>pwd=<admin password>
|
||||
* Change STA Password
|
||||
[ESP101]<Password>
|
||||
if authentication is on, need admin password
|
||||
[ESP101]<Password>pwd=<admin password>
|
||||
|
||||
* Change Hostname
|
||||
[ESP102]<hostname>
|
||||
if authentication is on, need admin password
|
||||
[ESP102]<hostname>pwd=<admin password>
|
||||
* Change Hostname
|
||||
[ESP102]<hostname>
|
||||
if authentication is on, need admin password
|
||||
[ESP102]<hostname>pwd=<admin password>
|
||||
|
||||
* Change Wifi mode (STA/AP)
|
||||
[ESP103]<mode>
|
||||
if authentication is on, need admin password
|
||||
[ESP103]<mode>pwd=<admin password>
|
||||
* Change Wifi mode (STA/AP)
|
||||
[ESP103]<mode>
|
||||
if authentication is on, need admin password
|
||||
[ESP103]<mode>pwd=<admin password>
|
||||
|
||||
* Change STA IP mode (DHCP/STATIC)
|
||||
[ESP104]<mode>
|
||||
if authentication is on, need admin password
|
||||
[ESP104]<mode>pwd=<admin password>
|
||||
* Change STA IP mode (DHCP/STATIC)
|
||||
[ESP104]<mode>
|
||||
if authentication is on, need admin password
|
||||
[ESP104]<mode>pwd=<admin password>
|
||||
|
||||
* Change AP SSID
|
||||
[ESP105]<SSID>
|
||||
if authentication is on, need admin password
|
||||
[ESP105]<SSID>pwd=<admin password>
|
||||
* Change AP SSID
|
||||
[ESP105]<SSID>
|
||||
if authentication is on, need admin password
|
||||
[ESP105]<SSID>pwd=<admin password>
|
||||
|
||||
* Change AP Password
|
||||
[ESP106]<Password>
|
||||
if authentication is on, need admin password
|
||||
[ESP106]<Password>pwd=<admin password>
|
||||
* Change AP Password
|
||||
[ESP106]<Password>
|
||||
if authentication is on, need admin password
|
||||
[ESP106]<Password>pwd=<admin password>
|
||||
|
||||
* Change AP IP mode (DHCP/STATIC)
|
||||
[ESP107]<mode>
|
||||
if authentication is on, need admin password
|
||||
[ESP107]<mode>pwd=<admin password>
|
||||
* Change AP IP mode (DHCP/STATIC)
|
||||
[ESP107]<mode>
|
||||
if authentication is on, need admin password
|
||||
[ESP107]<mode>pwd=<admin password>
|
||||
|
||||
* Get current IP
|
||||
[ESP111]<header answer>
|
||||
* Set wifi on/off
|
||||
[ESP110]<state>
|
||||
state can be ON, OFF, RESTART
|
||||
if authentication is on, need admin password
|
||||
[ESP110]<state>pwd=<admin password>
|
||||
|
||||
* Get hostname
|
||||
[ESP112]<header answer>
|
||||
* Get current IP
|
||||
[ESP111]<header answer>
|
||||
|
||||
* Get/Set ESP mode
|
||||
cmd can be RESET, SAFEMODE, CONFIG, RESTART
|
||||
[ESP444]<cmd>
|
||||
if authentication is on, need admin password for RESET, RESTART and SAFEMODE
|
||||
[ESP444]<cmd>pwd=<admin password>
|
||||
* Get hostname
|
||||
[ESP112]<header answer>
|
||||
|
||||
* Change / Reset user password
|
||||
[ESP555]<password>pwd=<admin password>
|
||||
if no password set it use default one
|
||||
|
||||
* Read SPIFFS file and send each line to serial
|
||||
[ESP700]<filename>
|
||||
*Get/Set pin value
|
||||
[ESP201]P<pin> V<value> [PULLUP=YES RAW=YES]
|
||||
if no V<value> get P<pin> value
|
||||
if V<value> 0/1 set INPUT_PULLUP value, but for GPIO16 INPUT_PULLDOWN_16
|
||||
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
|
||||
|
||||
* Get fw version
|
||||
[ESP800]<header answer>
|
||||
|
||||
* Clear status/error/info list
|
||||
cmd can be ALL, ERROR, INFO, STATUS
|
||||
[ESP999]<cmd>
|
||||
|
||||
*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
|
||||
can filter if only need wifi or printer
|
||||
[ESP400]<network/printer>
|
||||
|
||||
*Set EEPROM setting
|
||||
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>
|
||||
|
||||
*Get available AP list (limited to 30)
|
||||
output is JSON or plain text according parameter
|
||||
[ESP410]<plain>
|
||||
|
||||
*Get current settings of ESP3D
|
||||
output is JSON or plain text according parameter
|
||||
[ESP420]<plain>
|
||||
|
||||
* Get/Set ESP mode
|
||||
cmd can be RESET, SAFEMODE, CONFIG, RESTART
|
||||
[ESP444]<cmd>
|
||||
if authentication is on, need admin password for RESET, RESTART and SAFEMODE
|
||||
[ESP444]<cmd>pwd=<admin password>
|
||||
|
||||
* Change / Reset user password
|
||||
[ESP555]<password>pwd=<admin password>
|
||||
if no password set it use default one
|
||||
|
||||
* Read SPIFFS file and send each line to serial
|
||||
[ESP700]<filename>
|
||||
|
||||
* Format SPIFFS
|
||||
[ESP710]FORMAT pwd=<admin password>
|
||||
|
||||
* SPIFFS total size and used size
|
||||
[ESP720]<header answer>
|
||||
|
||||
* Get fw version and basic information
|
||||
[ESP800]<header answer>
|
||||
|
||||
* Get fw target
|
||||
[ESP801]<header answer>
|
||||
|
||||
* Clear status/error/info list
|
||||
cmd can be ALL, ERROR, INFO, STATUS
|
||||
[ESP999]<cmd>
|
||||
|
||||
```
|
||||
##Installation
|
||||
* For stable:
|
||||
Please use [Arduino IDE 1.6.5](http://arduino.cc/en/Main/Software) with the esp8266 module from board manager use 2.0.0 stable version by adding in your preferences http://arduino.esp8266.com/version/2.0.0/package_esp8266com_index.json
|
||||
with https://github.com/luc-github/ESP3D/releases/tag/v0.5.1
|
||||
or
|
||||
use [Arduino IDE 1.6.8](http://arduino.cc/en/Main/Software) with the esp8266 module from board manager use 2.2.0 stable version by adding in your preferences http://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
with https://github.com/luc-github/ESP3D/releases/tag/v0.6.2
|
||||
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.
|
||||
* 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
|
||||
* 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>
|
||||
|
||||
* For development:
|
||||
Please use [Arduino IDE 1.6.8](http://arduino.cc/en/Main/Software) and [git version of esp8266 module](http://esp8266.github.io/Arduino/versions/2.2.0/doc/installing.html#using-git-version)
|
||||
##Update
|
||||
* Generate a binary using the export binary menu from Arduino IDE and upload it using ESP-WEBUI or embedded interface
|
||||
|
||||
* To flash the module :
|
||||
You must define the targeted FW, can be REPETIER (Original Repetier)/ REPETIER4DV (Repetier for Davinci) / MARLIN (Marlin)/ SMOOTHIEWARE (Smoothieware) in config.h and enable/disable any others features
|
||||
```
|
||||
//MDNS_FEATURE: this feature allow type the name defined
|
||||
//in web browser by default: http:\\esp8266.local and connect
|
||||
//#define MDNS_FEATURE
|
||||
|
||||
//SSDD_FEATURE: this feature is a discovery protocol, supported on Windows out of the box
|
||||
#define SSDP_FEATURE
|
||||
|
||||
//CAPTIVE_PORTAL_FEATURE: In SoftAP redirect all unknow call to main page
|
||||
#define CAPTIVE_PORTAL_FEATURE
|
||||
|
||||
//AUTHENTICATION_FEATURE: protect pages by login password
|
||||
#define AUTHENTICATION_FEATURE
|
||||
|
||||
//WEB_UPDATE_FEATURE: allow to flash fw using web UI
|
||||
#define WEB_UPDATE_FEATURE
|
||||
|
||||
//SERIAL_COMMAND_FEATURE: allow to send command by serial
|
||||
#define SERIAL_COMMAND_FEATURE
|
||||
|
||||
//TCP_IP_DATA_FEATURE: allow to connect serial from TCP/IP
|
||||
#define TCP_IP_DATA_FEATURE
|
||||
|
||||
//RECOVERY_FEATURE: allow to use GPIO2 pin as hardware reset for EEPROM, add 8s to boot time to let user to jump GPIO2 to GND
|
||||
#define RECOVERY_FEATURE
|
||||
|
||||
//FIRMWARE_TARGET: the targeted FW, can be REPETIER (Original Repetier)/ REPETIER4DV (Repetier for Davinci) / MARLIN (Marlin)/ SMOOTHIEWARE (Smoothieware)
|
||||
#define FIRMWARE_TARGET REPETIER4DV
|
||||
|
||||
//DEBUG Flag
|
||||
//#define DEBUG_ESP3D
|
||||
```
|
||||
|
||||
For better performance select CPU Frequency to be 160MHz instead of default 80MHz
|
||||
Use IDE to upload directly (latest version of board manager module generate one binary)
|
||||
* To flash the html files present in data directory you need to use another tool, installation and usage is explained [here](https://github.com/esp8266/Arduino/blob/master/doc/filesystem.md#uploading-files-to-file-system)
|
||||
Once flashed you also can use the web updater to flash new FW in System Configuration Page or go to settings to change html files
|
||||
|
||||
<H3>:warning:Do not flash Printer fw with ESP connected - it bring troubles, at least on DaVinci</H3>
|
||||
<H3>:warning:Do not flash your Printer fw with ESP connected - it bring troubles, at least on DaVinci</H3>
|
||||
|
||||
##Contribution/customization
|
||||
To modifying and Testing tpl files a local tool has been created by [j0hnlittle](https://github.com/j0hnlittle) to avoid to upload every time your tpl files just to see the results of your modifications. It is a python script (2.7+) located in tools directory, launch it: python server.py, then open browser: http://localhost:8080
|
||||
It will display the web ui and allow some navigation
|
||||
* To style the code before pushing PR please use [astyle --style=otbs *.h *.cpp *.ino](http://astyle.sourceforge.net/)
|
||||
* The embedded page is created using nodejs then gulp to generate a compressed html page (tool.html.gz), all necessary modules can be installed using the install.bat file content, then it is included using bin2c (https://sourceforge.net/projects/bin2c/) to generate the h file used to create the file nofile.h, update the array and size according new out.h.
|
||||
* 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
|
||||
|
||||
To style the code before pushing PR please use [astyle --style=otbs *.h *.cpp *.ino](http://astyle.sourceforge.net/)
|
||||
|
||||
Feedback/suggestion/discussions are always welcome
|
||||
Feedback/suggestion/discussions are always welcome
|
||||
|
||||
##Need more information about board or wiring ?
|
||||
##Need more information about supported boards or wiring ?
|
||||
[Check the wiki](https://github.com/luc-github/ESP3D/wiki)
|
||||
|
||||
##:question:Any question ?
|
||||
Check [Wiki](https://github.com/luc-github/ESP3D/wiki/Install-Instructions) or [](https://gitter.im/luc-github/ESP3D?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
##:exclamation:Any issue/feedback ?
|
||||
Check [Wiki](https://github.com/luc-github/ESP3D/wiki/Install-Instructions) and [FAQ](https://github.com/luc-github/ESP3D/issues?utf8=%E2%9C%93&q=label%3AFAQ+) or [submit ticket](https://github.com/luc-github/ESP3D/issues)
|
||||
|
||||
|
||||
##TODO
|
||||
-- Close open topics
|
||||
-- Do testing (a lot)
|
||||
-- UI Improvement
|
||||
-- ESP3D V2
|
||||
|
150
UI/mousediv.html
150
UI/mousediv.html
@ -1,150 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
.sliderthumb{
|
||||
position : absolute;
|
||||
cursor : pointer;
|
||||
}
|
||||
|
||||
.sliderrange{
|
||||
cursor : pointer;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
var offset = 0;
|
||||
var isDown = false;
|
||||
var active_control = null;
|
||||
|
||||
document.addEventListener('mouseup', function() {
|
||||
isDown = false;
|
||||
}, true);
|
||||
|
||||
//position is based on screen position value
|
||||
function movethumb(pos)
|
||||
{
|
||||
var p = pos + offset;
|
||||
var minpos =0;
|
||||
var maxpos = 0;
|
||||
var minvalue =0;
|
||||
var maxvalue = 100;
|
||||
var value=0;
|
||||
var rangeelement =null;
|
||||
if (active_control.hasAttribute('customrange')){
|
||||
rangeelement = document.getElementById(active_control.getAttribute('customrange'));
|
||||
var r = rangeelement.getBoundingClientRect();
|
||||
minpos = r.left;
|
||||
maxpos = r.right;
|
||||
if (rangeelement.hasAttribute('min')){
|
||||
minvalue = parseFloat(rangeelement.getAttribute('min'))
|
||||
}
|
||||
if (rangeelement.hasAttribute('max')){
|
||||
maxvalue = parseFloat(rangeelement.getAttribute('max'))
|
||||
}
|
||||
}
|
||||
var r2 = active_control.getBoundingClientRect();
|
||||
if ( p >maxpos - (r2.right-r2.left)) p = maxpos - (r2.right-r2.left);
|
||||
if ( p <minpos) p =minpos ;
|
||||
active_control.style.left = p+ 'px';
|
||||
if (active_control.hasAttribute('render')){
|
||||
value = (((p-minpos) * (maxvalue-minvalue))/((maxpos-minpos)- (r2.right-r2.left)))
|
||||
document.getElementById(active_control.getAttribute('render')).value = Math.round(value + minvalue) ;
|
||||
active_control.style.cursor='pointer';
|
||||
}
|
||||
}
|
||||
|
||||
//position is based on range value
|
||||
function movethumbat(thumbcursor, value){
|
||||
var minvalue =0;
|
||||
var maxvalue = 100;
|
||||
var minpos =0;
|
||||
var maxpos = 0;
|
||||
var rangeelement =null;
|
||||
if (thumbcursor.hasAttribute('customrange')){
|
||||
rangeelement = document.getElementById(thumbcursor.getAttribute('customrange'));
|
||||
var r = rangeelement.getBoundingClientRect();
|
||||
minpos = r.left;
|
||||
maxpos = r.right;
|
||||
if (rangeelement.hasAttribute('min')){
|
||||
minvalue = parseFloat(rangeelement.getAttribute('min'))
|
||||
}
|
||||
if (rangeelement.hasAttribute('max')){
|
||||
maxvalue = parseFloat(rangeelement.getAttribute('max'))
|
||||
}
|
||||
}
|
||||
if (value > maxvalue) value = maxvalue;
|
||||
if (value < minvalue) value = minvalue;
|
||||
var r2 = thumbcursor.getBoundingClientRect();
|
||||
var pos=0;
|
||||
pos = ((value-minvalue)*((maxpos-minpos)-(r2.right-r2.left))/(maxvalue-minvalue))+minpos;
|
||||
thumbcursor.style.left = pos+ 'px';
|
||||
if (thumbcursor.hasAttribute('render')){
|
||||
document.getElementById(thumbcursor.getAttribute('render')).value =value;
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', function(event) {
|
||||
event.preventDefault();
|
||||
if (isDown) {
|
||||
movethumb(event.clientX);
|
||||
}
|
||||
}, true);
|
||||
|
||||
function rangeclicked(event,element)
|
||||
{
|
||||
|
||||
if (element.hasAttribute('customthumb')){
|
||||
active_control = document.getElementById(element.getAttribute('customthumb'));
|
||||
offset = 0;
|
||||
movethumb(event.clientX);
|
||||
}
|
||||
}
|
||||
|
||||
function initthumb( element)
|
||||
{
|
||||
element.addEventListener('mousedown', function(e) {
|
||||
isDown = true;
|
||||
offset = element.offsetLeft - e.clientX;
|
||||
active_control = this;
|
||||
}, true);
|
||||
if (element.hasAttribute('bgimage')){
|
||||
element.innerHTML = element.getAttribute('bgimage');
|
||||
}
|
||||
if (element.hasAttribute('customrange')){
|
||||
var r = document.getElementById(element.getAttribute('customrange')).getBoundingClientRect();
|
||||
element.style.top = r.top;
|
||||
element.style.left = r.left;
|
||||
}
|
||||
}
|
||||
|
||||
function initrange( element)
|
||||
{
|
||||
if (element.hasAttribute('bgimage')){
|
||||
element.innerHTML = element.getAttribute('bgimage');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
<table border=1>
|
||||
<tr>
|
||||
<td><div id='range1' min="-10" max="270" class='sliderrange' onclick ="rangeclicked(event,this);"bgimage="<svg width='310' height='10' viewbox='0 0 310 10'><rect width='310' height='10' style='fill:rgb(255,0,255);stroke-width:3;stroke:rgb(0,0,0)' />" customthumb='thumb1'></div>
|
||||
<div id='thumb1' class='sliderthumb' render='v1' bgimage="<svg width='10' height='10' viewbox='0 0 10 10'><circle cx='5' cy='5' r='5'/></svg>" customrange='range1'></div>
|
||||
</td><td><input id='v1' type='number' value='0'/></td></tr>
|
||||
<tr>
|
||||
<td><div id='range2' min="50" max="300" onclick ="rangeclicked(event,this);" bgimage="<svg width='310' height='10' viewbox='0 0 310 10'><rect width='310' height='10' style='fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)' />" customthumb='thumb2'></div>
|
||||
<div id='thumb2' class='sliderthumb' render='v2' bgimage="<svg width='10' height='10' viewbox='0 0 10 10'><circle cx='5' cy='5' r='5'/></svg>" customrange='range2'></div>
|
||||
</td><td><input id='v2' type='number' value='0'/></td></tr>
|
||||
</table>
|
||||
<input type='button' onclick='movethumbat(thumb1, inputtest.value)' value='push me' > <input id='inputtest' type='number' />
|
||||
<script>
|
||||
|
||||
initrange( range1);
|
||||
initrange( range2);
|
||||
initthumb( thumb1);
|
||||
initthumb( thumb2);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -522,7 +522,7 @@ function initrange( element)
|
||||
<g id=''centerze">
|
||||
<circle class="bg" cx="354" cy="122" r="34" filter="url(#shadow)" />
|
||||
<circle class="bg" cx="354" cy="122" r="34" class="bg" opacity='0.7' filter="url(#light)" />
|
||||
<text id="centeretext" class="centerjog" x="353" y="132" opacity="0">Z</text>
|
||||
<text id="centeretext" class="centerjog" x="353" y="132" opacity="0"></text>
|
||||
<g id="extruder">
|
||||
<path class='sign' d="M350,108 L360,108 L360,128 L355,136 L350,128 z"/>
|
||||
<path class='sign' d="M335,110 L338,109 L340,111 L341,111 L343,109 L346,110 L346,113 L349,113 L350,116 L348,118 L348,119 L350,121 L349,124 L346,124 L346,127 L343,128 L341,126 L340,126 L338,128 L335,127 L335,124 L332,124 L331,121 L333,119 L333,118 L331,116 L332,113 L335,113 z"/>
|
@ -38,12 +38,20 @@ if authentication is on, need admin password
|
||||
if authentication is on, need admin password
|
||||
[ESP107]<mode>pwd=<admin password>
|
||||
|
||||
* Set wifi on/off
|
||||
[ESP110]<state>
|
||||
state can be ON, OFF, RESTART
|
||||
if authentication is on, need admin password
|
||||
[ESP110]<state>pwd=<admin password>
|
||||
|
||||
* Get current IP
|
||||
[ESP111]<header answer>
|
||||
|
||||
* Get hostname
|
||||
[ESP112]<header answer>
|
||||
|
||||
* Restart time client
|
||||
[ESP114]
|
||||
|
||||
*Get/Set pin value
|
||||
[ESP201]P<pin> V<value> [PULLUP=YES RAW=YES]
|
||||
@ -53,6 +61,29 @@ 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
|
||||
|
||||
|
||||
*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
|
||||
can filter if only need wifi or printer
|
||||
[ESP400]<network/printer>
|
||||
|
||||
*Set EEPROM setting
|
||||
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>
|
||||
|
||||
*Get available AP list (limited to 30)
|
||||
output is JSON or plain text according parameter
|
||||
[ESP410]<plain>
|
||||
|
||||
*Get current settings of ESP3D
|
||||
output is JSON or plain text according parameter
|
||||
[ESP420]<plain>
|
||||
|
||||
* Get/Set ESP mode
|
||||
cmd can be RESET, SAFEMODE, CONFIG, RESTART
|
||||
[ESP444]<cmd>
|
||||
@ -66,7 +97,13 @@ if no password set it use default one
|
||||
* Read SPIFFS file and send each line to serial
|
||||
[ESP700]<filename>
|
||||
|
||||
* Get fw version
|
||||
* Format SPIFFS
|
||||
[ESP710]FORMAT pwd=<admin password>
|
||||
|
||||
* SPIFFS total size and used size
|
||||
[ESP720]<header answer>
|
||||
|
||||
* Get fw version and basic information
|
||||
[ESP800]<header answer>
|
||||
|
||||
* Get fw target
|
||||
|
@ -1,122 +0,0 @@
|
||||
EPR:0 1028 7 Language
|
||||
EPR:2 75 230400 Baudrate
|
||||
EPR:0 1125 1 Display Mode:
|
||||
EPR:0 1119 1 Light On:
|
||||
EPR:0 1127 1 Keep Light On:
|
||||
EPR:0 1126 0 Filament Sensor On:
|
||||
EPR:0 1176 0 Top Sensor On:
|
||||
EPR:0 1120 1 Sound On:
|
||||
EPR:0 1177 1 Wifi On:
|
||||
EPR:3 129 0.000 Filament printed [m]
|
||||
EPR:2 125 0 Printer active [s]
|
||||
EPR:2 79 0 Max. inactive time [ms,0=off]
|
||||
EPR:2 83 360000 Stop stepper after inactivity [ms,0=off]
|
||||
EPR:2 1121 0 Powersave after [ms,0=off]:
|
||||
EPR:3 1160 180.000 Temp Ext PLA:
|
||||
EPR:3 1164 230.000 Temp Ext ABS:
|
||||
EPR:3 1168 60.000 Temp Bed PLA:
|
||||
EPR:3 1172 90.000 Temp Bed ABS:
|
||||
EPR:3 1179 2.000 Load Feed Rate:
|
||||
EPR:3 1183 4.000 Unload Feed Rate:
|
||||
EPR:3 1187 60.000 Unload/Load Distance:
|
||||
EPR:3 3 80.0000 X-axis steps per mm
|
||||
EPR:3 7 80.0000 Y-axis steps per mm
|
||||
EPR:3 11 2560.0000 Z-axis steps per mm
|
||||
EPR:3 15 200.000 X-axis max. feedrate [mm/s]
|
||||
EPR:3 19 200.000 Y-axis max. feedrate [mm/s]
|
||||
EPR:3 23 5.000 Z-axis max. feedrate [mm/s]
|
||||
EPR:3 27 40.000 X-axis homing feedrate [mm/s]
|
||||
EPR:3 31 40.000 Y-axis homing feedrate [mm/s]
|
||||
EPR:3 35 4.000 Z-axis homing feedrate [mm/s]
|
||||
EPR:3 39 20.000 Max. jerk [mm/s]
|
||||
EPR:3 47 0.342 Max. Z-jerk [mm/s]
|
||||
EPR:3 133 0.000 X min pos [mm]
|
||||
EPR:3 137 0.000 Y min pos [mm]
|
||||
EPR:3 141 0.000 Z min pos [mm]
|
||||
EPR:3 145 199.000 X max length [mm]
|
||||
EPR:3 149 204.000 Y max length [mm]
|
||||
EPR:3 153 200.000 Z max length [mm]
|
||||
EPR:3 51 1000.000 X-axis acceleration [mm/s^2]
|
||||
EPR:3 55 1000.000 Y-axis acceleration [mm/s^2]
|
||||
EPR:3 59 100.000 Z-axis acceleration [mm/s^2]
|
||||
EPR:3 63 1000.000 X-axis travel acceleration [mm/s^2]
|
||||
EPR:3 67 1000.000 Y-axis travel acceleration [mm/s^2]
|
||||
EPR:3 71 150.000 Z-axis travel acceleration [mm/s^2]
|
||||
EPR:3 1024 0.000 Coating thickness [mm]
|
||||
EPR:3 1128 100.000 Manual-probe X1 [mm]
|
||||
EPR:3 1132 180.000 Manual-probe Y1 [mm]
|
||||
EPR:3 1136 100.000 Manual-probe X2 [mm]
|
||||
EPR:3 1140 10.000 Manual-probe Y2 [mm]
|
||||
EPR:3 1144 50.000 Manual-probe X3 [mm]
|
||||
EPR:3 1148 95.000 Manual-probe Y3 [mm]
|
||||
EPR:3 1152 150.000 Manual-probe X4 [mm]
|
||||
EPR:3 1156 95.000 Manual-probe Y4 [mm]
|
||||
EPR:3 808 0.280 Z-probe height [mm]
|
||||
EPR:3 929 5.000 Max. z-probe - bed dist. [mm]
|
||||
EPR:3 812 1.000 Z-probe speed [mm/s]
|
||||
EPR:3 840 30.000 Z-probe x-y-speed [mm/s]
|
||||
EPR:3 800 0.000 Z-probe offset x [mm]
|
||||
EPR:3 804 0.000 Z-probe offset y [mm]
|
||||
EPR:3 816 36.000 Z-probe X1 [mm]
|
||||
EPR:3 820 -7.000 Z-probe Y1 [mm]
|
||||
EPR:3 824 36.000 Z-probe X2 [mm]
|
||||
EPR:3 828 203.000 Z-probe Y2 [mm]
|
||||
EPR:3 832 171.000 Z-probe X3 [mm]
|
||||
EPR:3 836 203.000 Z-probe Y3 [mm]
|
||||
EPR:3 1036 0.000 Z-probe bending correction A [mm]
|
||||
EPR:3 1040 0.000 Z-probe bending correction B [mm]
|
||||
EPR:3 1044 0.000 Z-probe bending correction C [mm]
|
||||
EPR:0 880 0 Autolevel active (1/0)
|
||||
EPR:0 106 2 Bed Heat Manager [0-3]
|
||||
EPR:0 107 255 Bed PID drive max
|
||||
EPR:0 124 80 Bed PID drive min
|
||||
EPR:3 108 196.000 Bed PID P-gain
|
||||
EPR:3 112 33.000 Bed PID I-gain
|
||||
EPR:3 116 290.000 Bed PID D-gain
|
||||
EPR:0 120 255 Bed PID max value [0-255]
|
||||
EPR:0 1020 0 Enable retraction conversion [0/1]
|
||||
EPR:3 992 3.000 Retraction length [mm]
|
||||
EPR:3 996 13.000 Retraction length extruder switch [mm]
|
||||
EPR:3 1000 40.000 Retraction speed [mm/s]
|
||||
EPR:3 1004 0.000 Retraction z-lift [mm]
|
||||
EPR:3 1008 0.000 Extra extrusion on undo retract [mm]
|
||||
EPR:3 1012 0.000 Extra extrusion on undo switch retract [mm]
|
||||
EPR:3 1016 20.000 Retraction undo speed
|
||||
EPR:3 200 99.000 Extr.1 steps per mm
|
||||
EPR:3 204 50.000 Extr.1 max. feedrate [mm/s]
|
||||
EPR:3 208 20.000 Extr.1 start feedrate [mm/s]
|
||||
EPR:3 212 5000.000 Extr.1 acceleration [mm/s^2]
|
||||
EPR:0 216 3 Extr.1 heat manager [0-3]
|
||||
EPR:0 217 230 Extr.1 PID drive max
|
||||
EPR:0 245 40 Extr.1 PID drive min
|
||||
EPR:3 218 3.0000 Extr.1 PID P-gain/dead-time
|
||||
EPR:3 222 2.0000 Extr.1 PID I-gain
|
||||
EPR:3 226 40.0000 Extr.1 PID D-gain
|
||||
EPR:0 230 255 Extr.1 PID max value [0-255]
|
||||
EPR:2 231 0 Extr.1 X-offset [steps]
|
||||
EPR:2 235 0 Extr.1 Y-offset [steps]
|
||||
EPR:2 290 0 Extr.1 Z-offset [steps]
|
||||
EPR:1 239 1 Extr.1 temp. stabilize time [s]
|
||||
EPR:1 250 150 Extr.1 temp. for retraction when heating [C]
|
||||
EPR:1 252 0 Extr.1 distance to retract when heating [mm]
|
||||
EPR:0 254 255 Extr.1 extruder cooler speed [0-255]
|
||||
EPR:3 246 0.000 Extr.1 advance L [0=off]
|
||||
EPR:3 300 99.000 Extr.2 steps per mm
|
||||
EPR:3 304 50.000 Extr.2 max. feedrate [mm/s]
|
||||
EPR:3 308 20.000 Extr.2 start feedrate [mm/s]
|
||||
EPR:3 312 5000.000 Extr.2 acceleration [mm/s^2]
|
||||
EPR:0 316 3 Extr.2 heat manager [0-3]
|
||||
EPR:0 317 230 Extr.2 PID drive max
|
||||
EPR:0 345 40 Extr.2 PID drive min
|
||||
EPR:3 318 3.0000 Extr.2 PID P-gain/dead-time
|
||||
EPR:3 322 2.0000 Extr.2 PID I-gain
|
||||
EPR:3 326 40.0000 Extr.2 PID D-gain
|
||||
EPR:0 330 255 Extr.2 PID max value [0-255]
|
||||
EPR:2 331 -2852 Extr.2 X-offset [steps]
|
||||
EPR:2 335 12 Extr.2 Y-offset [steps]
|
||||
EPR:2 390 0 Extr.2 Z-offset [steps]
|
||||
EPR:1 339 1 Extr.2 temp. stabilize time [s]
|
||||
EPR:1 350 150 Extr.2 temp. for retraction when heating [C]
|
||||
EPR:1 352 0 Extr.2 distance to retract when heating [mm]
|
||||
EPR:0 354 255 Extr.2 extruder cooler speed [0-255]
|
||||
EPR:3 346 0.000 Extr.2 advance L [0=off]
|
@ -1,150 +0,0 @@
|
||||
[COMMON]
|
||||
$INCLUDE[<filename>] : only one per line and alone, others will be ignored
|
||||
$IP$ : current active ip
|
||||
$WEB_ADDRESS$: current active ip , if port is not 80 it will add port like xxx.xxx.xxxx.xxx:XX
|
||||
$MENU_HOME$/$MENU_SYSTEM$/$MENU_AP$/$MENU_STA$/$MENU_PRINTER$/$MENU_SETTINGS$: to highlight menu of active page (css use class active for active menu)
|
||||
$SERVICE_PAGE$ : to add extra code like redirection or anything not managed by page
|
||||
$PAGE_TILE$ : page title
|
||||
$FILENAME$ : file name of tpl
|
||||
$SHORT_FILENAME$ : file name of tpl without extension
|
||||
$MODE$ : the mode when displaying page AP/STA/AP_STA
|
||||
$FW_VER$ : Firmware version
|
||||
|
||||
[HOME]
|
||||
$HOSTNAME$: Hostname
|
||||
$HOSTNAME_VISIBLE$ : if AP mode then hostname is not applicable so set to hidden, if in STA mode set to visible
|
||||
$CHIP_ID$ : Chip ID
|
||||
$CPU_FREQ$ : CPU Frequency
|
||||
$FREE_MEM$ : Free memory on heap
|
||||
$SDK_VER$ : SDK version
|
||||
$MDNS_VISIBLE$: set to hidden if no MDNS and visible if present
|
||||
$MDNS_NAME$ : mDNS name if enabled or "Not enabled" if not enabled
|
||||
$SSDP_VISIBLE$ : set to hidden if no MDNS and visible if present
|
||||
$SSDP_STATUS$ : set to Enabled / Not enabled according compilation settings
|
||||
$CAPTIVE_PORTAL_VISIBLE$: set to hidden if no Captive portal and visible if present
|
||||
$CAPTIVE_PORTAL_STATUS$: set to Enabled / Not enabled according compilation settings
|
||||
$NET_PHY$ : Network type (b/g/n)
|
||||
$SLEEP_MODE$ : Sleep Mode
|
||||
$BOOT_VER$ : Boot version
|
||||
$BAUD_RATE$ : Baud rates for serial communication
|
||||
$WEB_PORT$ : Port for web access
|
||||
$DATA_PORT$ : Port for tcp ip connection
|
||||
$DATA_PORT_VISIBILITY$ : set to hidden if no enabled and visible if enabled
|
||||
|
||||
$AP_STATUS_ENABLED$ : is Access Point enabled or disabled
|
||||
$AP_VISIBILITY$ : if Access Point is enabled set visible, else set to hidden
|
||||
$AP_MAC$ : Mac address of AP
|
||||
$AP_SSID$ : SSID of AP
|
||||
$AP_IS_VISIBLE$ : Is AP visible
|
||||
$AP_CHANNEL$ : Channel
|
||||
$AP_AUTH$ : Autehntification mode
|
||||
$AP_MAX_CON$ : Maximum connections allowed
|
||||
$AP_DHCP_STATUS$ : AP DHCP server status (started/stopped)
|
||||
$AP_IP$ : AP IP address
|
||||
$AP_GW$ : AP gateway address
|
||||
$AP_SUBNET$ : AP mask of subnet
|
||||
|
||||
$CONNECTED_STATIONS[ Repetive template using $ROW_NUMBER$ $MAC_CONNECTED$ $IP_CONNECTED$ ]$
|
||||
$CONNECTED_STATIONS_NB_ITEMS$ : number of item for connected stations list
|
||||
or can get variables in direct access:
|
||||
$ROW_NUMBER[0]$
|
||||
$MAC_CONNECTED[0]$
|
||||
$IP_CONNECTED[0]$
|
||||
until
|
||||
$ROW_NUMBER[$CONNECTED_STATIONS_NB_ITEMS$ -1]$
|
||||
$MAC_CONNECTED[$CONNECTED_STATIONS_NB_ITEMS$ -1]$
|
||||
$IP_CONNECTED[$CONNECTED_STATIONS_NB_ITEMS$ -1]$
|
||||
|
||||
$STA_STATUS_ENABLED$ : is Station enabled or disabled
|
||||
$STA_VISIBILITY$ : if Station is enabled set visible, else set to hidden
|
||||
$STA_MAC$ : Mac address of Station
|
||||
$STA_SSID$ : SSID used by STA
|
||||
$STA_CHANNEL$ : Channel
|
||||
$STA_STATUS$ : Connection Status
|
||||
$STA_SIGNAL$ : Signal strength
|
||||
$STA_DHCP_STATUS$ : DHCP Client status
|
||||
$STA_IP$ : STA IP
|
||||
$STA_GW$ : STA Gateway
|
||||
$STA_SUBNET$ : STA Mask
|
||||
|
||||
[SYSTEM CONFIGURATION]
|
||||
$BAUD_RATE_OPTIONS_LIST$ : Baud rate list
|
||||
$SLEEP_MODE_OPTIONS_LIST$ : Sleep mode list
|
||||
$POLLING_OPTIONS_LIST$ : Refresh delay list
|
||||
$WEB_PORT$ : Port for web access
|
||||
$DATA_PORT$ : Port for tcp ip connection
|
||||
$DATA_PORT_VISIBILITY$ : set to hidden if no enabled and visible if enabled
|
||||
$ERROR_MSG$ : Error message if any
|
||||
$SUCCESS_MSG$ : Success message announcing restart
|
||||
$ERROR_MSG_VISIBILITY$ : Show/Hide Error message
|
||||
$SUCCESS_MSG_VISIBILITY$ : Show/Hide Success message
|
||||
$SUBMIT_BUTTON_VISIBILITY$ : Show if no submission or any error, hide if submission is successful
|
||||
$BAUD_RATE_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$SLEEP_MODE_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$WEB_PORT_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$DATA_PORT_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
|
||||
[AP CONFIGURATION]
|
||||
$AP_SSID$ : Access point SSID
|
||||
$AP_PASSWORD$ Access point password
|
||||
$IS_SSID_VISIBLE$ : set to checked if SSID is visible
|
||||
$NETWORK_OPTION_LIST$ : Option list for network for AP
|
||||
$CHANNEL_OPTION_LIST$ : Channel list
|
||||
$AUTH_OPTION_LIST$ Authentification methods list
|
||||
$IS_STATIC_IP$ : set to checked if use static address
|
||||
$AP_IP$ : Access point IP if static address
|
||||
$AP_GW$ : Access point Gaieway if static address
|
||||
$AP_SUBNET$ : : Access point network mask if static address
|
||||
$ERROR_MSG$ : Error message if any
|
||||
$SUCCESS_MSG$ : Success message announcing restart
|
||||
$ERROR_MSG_VISIBILITY$ : Show/Hide Error message
|
||||
$SUCCESS_MSG_VISIBILITY$ : Show/Hide Success message
|
||||
$SUBMIT_BUTTON_VISIBILITY$ : Show if no submission or any error, hide if submission is successful
|
||||
$AP_SSID_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$AP_PASSWORD_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$IS_SSID_VISIBLE_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$NETWORK_OPTION_LIST_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$CHANNEL_OPTION_LIST_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$AUTH_OPTION_LIST_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$AP_STATIC_IP_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$AP_IP_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$AP_GW_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$AP_SUBNET_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
|
||||
[STATION CONFIGURATION]
|
||||
$STA_SSID$ : Access point SSID
|
||||
$STA_PASSWORD$ Access point password
|
||||
$NETWORK_OPTION_LIST$ : Option list for network for AP
|
||||
$IS_STATIC_IP$ : set to checked if use static address
|
||||
$STA_IP$ : Access point IP if static address
|
||||
$STA_GW$ : Access point Gaieway if static address
|
||||
$STA_SUBNET$ : : Access point network mask if static address
|
||||
$ERROR_MSG$ : Error message if any
|
||||
$SUCCESS_MSG$ : Success message announcing restart
|
||||
$ERROR_MSG_VISIBILITY$ : Show/Hide Error message
|
||||
$SUCCESS_MSG_VISIBILITY$ : Show/Hide Success message
|
||||
$SUBMIT_BUTTON_VISIBILITY$ : Show if no submission or any error, hide if submission is successful
|
||||
$STA_SSID_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$STA_PASSWORD_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$NETWORK_OPTION_LIST_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$STA_STATIC_IP_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$STA_IP_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$STA_GW_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$STA_SUBNET_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$AP_SCAN_VISIBILITY$ : Hide scan table which is not executed when saving to EEPROM
|
||||
|
||||
[PRINTER STATUS]
|
||||
$REFRESH_PAGE$ : Delay for refreshing pages
|
||||
$XY_FEEDRATE$ : XY axis feedrate
|
||||
$Z_FEEDRATE$ : Z axis feedrate
|
||||
$E_FEEDRATE$ : Extruder feedrate
|
||||
|
||||
[PRINTER SETTINGS]
|
||||
$REFRESH_PAGE$ : Delay for refreshing pages
|
||||
$XY_FEEDRATE$ : XY axis feedrate
|
||||
$Z_FEEDRATE$ : Z axis feedrate
|
||||
$E_FEEDRATE$ : Extruder feedrate
|
||||
$REFRESH_PAGE_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$XY_FEEDRATE_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$Z_FEEDRATE_STATUS$ : change to has-error if issue, or has-success if ok
|
||||
$E_FEEDRATE_STATUS$ : change to has-error if issue, or has-success if ok
|
1
embedded/build.bat
Normal file
1
embedded/build.bat
Normal file
@ -0,0 +1 @@
|
||||
bin2c /infile tool.html.gz /outfile out.h /targetfolder .
|
125
embedded/gulpfile.js
Normal file
125
embedded/gulpfile.js
Normal file
@ -0,0 +1,125 @@
|
||||
var gulp = require('gulp'),
|
||||
jshint = require('gulp-jshint'),
|
||||
gulpif = require('gulp-if'),
|
||||
concat = require('gulp-concat'),
|
||||
uglify = require('gulp-uglify'),
|
||||
cleanCSS = require('gulp-clean-css'),
|
||||
removeCode = require('gulp-remove-code'),
|
||||
merge = require('merge-stream'),
|
||||
del = require('del'),
|
||||
zip = require('gulp-zip'),
|
||||
gzip = require('gulp-gzip'),
|
||||
htmlmin = require('gulp-htmlmin'),
|
||||
replace = require('gulp-replace'),
|
||||
fs = require('fs'),
|
||||
smoosher = require('gulp-smoosher');
|
||||
|
||||
var demoMode = false;
|
||||
var testMode = false;
|
||||
|
||||
function clean() {
|
||||
return del(['dist']);
|
||||
}
|
||||
|
||||
function clean2() {
|
||||
return del(['dist/js', 'dist/css']);
|
||||
}
|
||||
function lint() {
|
||||
return gulp.src('www/js/**/script.js')
|
||||
.pipe(jshint())
|
||||
.pipe(jshint.reporter('default'));
|
||||
}
|
||||
|
||||
function Copytest() {
|
||||
return merge(
|
||||
gulp.src(['www/tool.html'])
|
||||
.pipe(removeCode({production: false}))
|
||||
.pipe(gulp.dest('dist')),
|
||||
gulp.src(['www/images/**/*.*'])
|
||||
.pipe(gulp.dest('dist/images'))
|
||||
)
|
||||
}
|
||||
|
||||
function Copy() {
|
||||
return merge(
|
||||
gulp.src(['www/tool.html'])
|
||||
.pipe(removeCode({production: true}))
|
||||
.pipe(gulp.dest('dist')),
|
||||
gulp.src(['www/images/**/*.*'])
|
||||
.pipe(gulp.dest('dist/images'))
|
||||
)
|
||||
}
|
||||
|
||||
function concatApptest() {
|
||||
return merge(
|
||||
gulp.src([ 'www/js/**/*.js'])
|
||||
.pipe(concat('script.js'))
|
||||
.pipe(removeCode({production: false}))
|
||||
.pipe(gulp.dest('./dist/js')),
|
||||
|
||||
gulp.src([ 'www/css/**/*.css'])
|
||||
.pipe(concat('style.css'))
|
||||
.pipe(gulp.dest('./dist/css/'))
|
||||
)
|
||||
}
|
||||
|
||||
function concatApp() {
|
||||
return merge(
|
||||
gulp.src([ 'www/js/**/*.js'])
|
||||
.pipe(concat('script.js'))
|
||||
.pipe(removeCode({production: true}))
|
||||
.pipe(gulp.dest('./dist/js')),
|
||||
|
||||
gulp.src([ 'www/css/**/*.css'])
|
||||
.pipe(concat('style.css'))
|
||||
.pipe(gulp.dest('./dist/css/'))
|
||||
)
|
||||
}
|
||||
|
||||
function minifyApp() {
|
||||
return merge(
|
||||
gulp.src(['dist/js/script.js'])
|
||||
.pipe(uglify({mangle: true}))
|
||||
.pipe(gulp.dest('./dist/js/')),
|
||||
|
||||
gulp.src('dist/css/style.css')
|
||||
.pipe(cleanCSS({debug: true}, function(details) {
|
||||
console.log(details.name + ': ' + details.stats.originalSize);
|
||||
console.log(details.name + ': ' + details.stats.minifiedSize);
|
||||
}))
|
||||
.pipe(gulp.dest('./dist/css/')),
|
||||
|
||||
gulp.src('dist/tool.html')
|
||||
.pipe(htmlmin({collapseWhitespace: true, minifyCSS: true}))
|
||||
.pipe(gulp.dest('dist'))
|
||||
)
|
||||
}
|
||||
|
||||
function smoosh() {
|
||||
return gulp.src('dist/tool.html')
|
||||
.pipe(smoosher())
|
||||
.pipe(gulp.dest('dist'))
|
||||
}
|
||||
|
||||
function compress() {
|
||||
return gulp.src('dist/tool.html')
|
||||
.pipe(gzip())
|
||||
.pipe(gulp.dest('.'));
|
||||
}
|
||||
|
||||
gulp.task(clean);
|
||||
gulp.task(lint);
|
||||
gulp.task(Copy);
|
||||
gulp.task(Copytest);
|
||||
gulp.task(concatApp);
|
||||
gulp.task(concatApptest);
|
||||
gulp.task(minifyApp);
|
||||
gulp.task(smoosh);
|
||||
gulp.task(clean2);
|
||||
|
||||
var defaultSeries = gulp.series(clean, lint, Copy, concatApp, smoosh);
|
||||
var packageSeries = gulp.series(clean, lint, Copy, concatApp,minifyApp, smoosh, compress, clean2);
|
||||
|
||||
gulp.task('default', defaultSeries);
|
||||
gulp.task('package', packageSeries);
|
||||
|
15
embedded/install.bat
Normal file
15
embedded/install.bat
Normal file
@ -0,0 +1,15 @@
|
||||
npm install --global gulp-cli
|
||||
npm install --save-dev gulp
|
||||
npm install --save-dev gulp-jshint
|
||||
npm install --save-dev jshint
|
||||
npm install --save-dev gulp-if
|
||||
npm install --save-dev gulp-concat
|
||||
npm install --save-dev gulp-uglify
|
||||
npm install --save-dev gulp-clean-css
|
||||
npm install --save-dev gulp-remove-code
|
||||
npm install --save-dev del
|
||||
npm install --save-dev gulp-zip
|
||||
npm install --save-dev gulp-gzip
|
||||
npm install --save-dev gulp-htmlmin
|
||||
npm install --save-dev gulp-replace
|
||||
npm install --save-dev gulp-smoosher
|
30
embedded/package.json
Normal file
30
embedded/package.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "embedded4ESP3D",
|
||||
"description": "Embedded files for ESP3D",
|
||||
"devDependencies": {
|
||||
"del": "^2.2.2",
|
||||
"deprecated": "0.0.1",
|
||||
"fs": "0.0.1-security",
|
||||
"gulp": "github:gulpjs/gulp#4.0",
|
||||
"gulp-bytediff": "^1.0.0",
|
||||
"gulp-cdnizer": "^1.1.7",
|
||||
"gulp-clean-css": "^2.4.0",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-gzip": "^1.4.0",
|
||||
"gulp-htmlmin": "^3.0.0",
|
||||
"gulp-if": "^2.0.2",
|
||||
"gulp-jshint": "^2.0.4",
|
||||
"gulp-ng-annotate": "^2.0.0",
|
||||
"gulp-remove-code": "^1.0.2",
|
||||
"gulp-replace": "^0.5.4",
|
||||
"gulp-smoosher": "0.0.9",
|
||||
"gulp-uglify": "^2.1.2",
|
||||
"gulp-util": "^3.0.1",
|
||||
"gulp-zip": "^3.2.0",
|
||||
"jshint": "^2.9.5",
|
||||
"merge-stream": "^1.0.1"
|
||||
},
|
||||
"repository": "https://github.com/luc-github/ESP3D",
|
||||
"author": "Luc LEBOSSE",
|
||||
"license": "(ISC OR GPL-3.0)"
|
||||
}
|
BIN
embedded/tool.html.gz
Normal file
BIN
embedded/tool.html.gz
Normal file
Binary file not shown.
@ -50,3 +50,90 @@ caption{padding-top:8px;padding-bottom:8px;color:#777777;text-align:left;}
|
||||
.btnroundimg:hover{background-color:#F0F0F0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;}
|
||||
.blacklink {color:#000000;}
|
||||
.blacklink:hover, .filelink:focus {color:#0094FF;}
|
||||
input[type="file"]::-webkit-file-upload-button{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation; touch-action:manipulation;cursor:pointer;
|
||||
background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;
|
||||
* -webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none; color: #ffffff;background-color: #5bc0de;border-color: #46b8da;}
|
||||
input[type="file"]::-webkit-file-upload-button:focus{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation; touch-action:manipulation;cursor:pointer;
|
||||
background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;
|
||||
* -webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none; color: #ffffff;background-color: #31b0d5;border-color: #1b6d85;}
|
||||
input[type="file"]::-webkit-file-upload-button:hover{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation; touch-action:manipulation;cursor:pointer;
|
||||
background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;
|
||||
* -webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none; color: #ffffff;background-color: #31b0d5;border-color: #269abc;}
|
||||
.filelink {color:#000000;}
|
||||
.filelink:hover, .filelink:focus {color:#0094FF;}
|
||||
.panel-footer{padding:10px 15px;color:#31708f;background-color:#f5f5f5;border-color:#dddddd;border-top:1px solid #dddddd;}
|
||||
.loader {
|
||||
border: 4px solid #f3f3f3; /* Light grey */
|
||||
border-top: 4px solid #3498db; /* Blue */
|
||||
border-radius: 50%;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
.panel-footer{padding:10px 15px;color:#31708f;background-color:#f5f5f5;border-color:#dddddd;border-top:1px solid #dddddd;}
|
||||
|
||||
.modal {
|
||||
display: none; /* Hidden by default */
|
||||
position: fixed; /* Stay in place */
|
||||
z-index: 10000; /* Sit on top */
|
||||
padding-top: 100px; /* Location of the box */
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%; /* Full width */
|
||||
height: 100%; /* Full height */
|
||||
overflow: auto; /* Enable scroll if needed */
|
||||
background-color: rgb(0,0,0); /* Fallback color */
|
||||
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
|
||||
}
|
||||
|
||||
/* Modal Content */
|
||||
.modal-content {
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom-left-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
border: 2px solid #337AB7;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
position: relative;
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
background-color: #fefefe;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 2px 16px;
|
||||
color: #0f0f0f;
|
||||
background-color: #f2f2f2;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom: 1px solid #cfcfcf;
|
||||
}
|
||||
|
||||
.modal-body {padding: 10px 16px;}
|
||||
|
||||
.modal-footer {
|
||||
padding: 16px 16px;
|
||||
height: 4.5em;
|
||||
color: #0f0f0f;
|
||||
background-color: #f2f2f2;
|
||||
border-top: 1px solid #cfcfcf;
|
||||
border-bottom-left-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.modal-content {
|
||||
width: 580px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.modal-content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
@ -1,52 +1,3 @@
|
||||
$INCLUDE[header.inc]$
|
||||
$INCLUDE[css2.inc]$
|
||||
<style>
|
||||
.panel-footer{padding:10px 15px;color:#31708f;background-color:#f5f5f5;border-color:#dddddd;border-top:1px solid #dddddd;}
|
||||
</style>
|
||||
<div class="panel">
|
||||
<div class="panel-heading">Extra Settings</div>
|
||||
<div class="panel-body">
|
||||
<form method="POST">
|
||||
<div class="form-group $REFRESH_PAGE_STATUS$"><label class="control-label" for="CONFIG1">Refresh page time: </label><br>
|
||||
<input type="number" class="form-control" id="CONFIG1" name="REFRESH_PAGE" placeholder="Time in minutes 0~120, 0 = disabled " value="$REFRESH_PAGE$" min="0"max="120" step="1"style="width: auto;"></div>
|
||||
<div class="form-group $XY_FEEDRATE_STATUS$"><label class="control-label" for="CONFIG2">XY axis feedrate: </label><br>
|
||||
<input type="number" class="form-control" id="CONFIG2" name="XY_FEEDRATE" placeholder="1~9999 " value="$XY_FEEDRATE$" min="1"max="9999" step="1"style="width: auto;"></div>
|
||||
<div class="form-group $Z_FEEDRATE_STATUS$"><label class="control-label" for="CONFIG3">Z axis feedrate: </label><br>
|
||||
<input type="number" class="form-control" id="CONFIG3" name="Z_FEEDRATE" placeholder="1~9999 " value="$Z_FEEDRATE$" min="1"max="9999" step="1"style="width: auto;"></div>
|
||||
<div class="form-group $E_FEEDRATE_STATUS$"><label class="control-label" for="CONFIG4">Extruder feedrate: </label><br>
|
||||
<input type="number" class="form-control" id="CONFIG4" name="E_FEEDRATE" placeholder="1~9999 " value="$E_FEEDRATE$" min="1"max="9999" step="1"style="width: auto;"></div>
|
||||
|
||||
<div class="alert alert-danger" role="alert" style="$ERROR_MSG_VISIBILITY$" >
|
||||
$ERROR_MSG$
|
||||
</div>
|
||||
<hr><input style="$SUBMIT_BUTTON_VISIBILITY$" type="submit" class="btn btn-primary" name="SUBMIT" value="Apply">
|
||||
</form>
|
||||
<div class="alert alert-success" role="alert" style="$SUCCESS_MSG_VISIBILITY$" >
|
||||
$SUCCESS_MSG$
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="panel-heading">Flash Filesystem</div>
|
||||
<div class="panel-body">
|
||||
<input type="file" id="file-select" name="myfiles[]" multiple />
|
||||
<input class="btn btn-primary" type="button" id="upload-button" onclick="Sendfile();" value="Upload"/> <progress style="visibility:hidden;" name='prg' id='prg' max='100'></progress>
|
||||
<br><br><div class="panel">
|
||||
<div class="panel-body">
|
||||
<table><tr><td width="0%">
|
||||
<div onclick="Createdir()" class="btnimg"><svg width="40" height="40" viewBox="0 0 40 40"><rect x="5" y="10" width="30" height="20" rx="2" ry="2" fill="#31b0d5" />
|
||||
<rect x="20" y="5" width="15" height="15" rx="2" ry="2" fill="#31b0d5" /><text x="15" y="25" font-size="18" font-weight="800" fill="white">+</text></svg>
|
||||
</div>
|
||||
</td><td><div id="loader" class="loader"></div></td><td width="100%"><div id="path" class="info" > </div>
|
||||
</td>
|
||||
</tr></table>
|
||||
<table class="table table-striped" style="border:1px;solid #dddddd;margin-bottom:20px;" ><thead><tr><th width='0%'>Type</th><th>Name</th><th>Size</th><th width='0%'></th><th width='100%'></th></tr></thead><tbody id="file_list"><tbody></table>
|
||||
</div>
|
||||
<div class="panel-footer " id="status"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var currentpath = "/";
|
||||
function navbar(){
|
||||
var content="<table><tr>";
|
||||
@ -101,39 +52,39 @@ document.getElementById('status').innerHTML=content;
|
||||
content ="";
|
||||
if (currentpath!="/")
|
||||
{
|
||||
var pos = currentpath.lastIndexOf("/",currentpath.length-2)
|
||||
var pos = currentpath.lastIndexOf("/",currentpath.length-2);
|
||||
var previouspath = currentpath.slice(0,pos+1);
|
||||
content +="<tr style='cursor:hand;' onclick=\"currentpath='"+previouspath+"'; SendCommand('list','all');\"><td >"+back_icon()+"</td><td colspan='4'> Up..</td></tr>";
|
||||
}
|
||||
jsonresponse.files.sort(function(a, b) {
|
||||
return compareStrings(a.name, b.name);
|
||||
});
|
||||
for (var i=0;i <jsonresponse.files.length;i++){
|
||||
for (var i1=0;i1 <jsonresponse.files.length;i1++){
|
||||
//first display files
|
||||
if (String(jsonresponse.files[i].size) != "-1")
|
||||
if (String(jsonresponse.files[i1].size) != "-1")
|
||||
{
|
||||
content +="<TR>";
|
||||
content +="<td><svg height='24' width='24' viewBox='0 0 24 24' > <path d='M1,2 L1,21 L2,22 L16,22 L17,21 L17,6 L12,6 L12,1 L2,1 z' stroke='black' fill='white' /><line x1='12' y1='1' x2='17' y2='6' stroke='black' stroke-width='1'/>";
|
||||
content +="<line x1='5' y1='10' x2='13' y2='10' stroke='black' stroke-width='1'/> <line x1='5' y1='14' x2='13' y2='14' stroke='black' stroke-width='1'/> <line x1='5' y1='18' x2='13' y2='18' stroke='black' stroke-width='1'/></svg></td>";
|
||||
content +="<TD class='btnimg' style=\"padding:0px;\"><a href=\""+jsonresponse.path+jsonresponse.files[i].name+"\" target=_blank><div class=\"blacklink\">";
|
||||
content +=jsonresponse.files[i].name;
|
||||
content +="<TD class='btnimg' style=\"padding:0px;\"><a href=\""+jsonresponse.path+jsonresponse.files[i1].name+"\" target=_blank><div class=\"blacklink\">";
|
||||
content +=jsonresponse.files[i1].name;
|
||||
content +="</div></a></TD><TD>";
|
||||
content +=jsonresponse.files[i].size;
|
||||
content +="</TD><TD width='0%'><div class=\"btnimg\" onclick=\"Delete('"+jsonresponse.files[i].name+"')\">";
|
||||
content +=jsonresponse.files[i1].size;
|
||||
content +="</TD><TD width='0%'><div class=\"btnimg\" onclick=\"Delete('"+jsonresponse.files[i1].name+"')\">";
|
||||
content +=trash_icon();
|
||||
content +="</div></TD><td></td></TR>";
|
||||
}
|
||||
}
|
||||
//then display directories
|
||||
for (var i=0;i <jsonresponse.files.length;i++){
|
||||
if (String(jsonresponse.files[i].size) == "-1")
|
||||
for (var i2=0;i2 <jsonresponse.files.length;i2++){
|
||||
if (String(jsonresponse.files[i2].size) == "-1")
|
||||
{
|
||||
content +="<TR>";
|
||||
content+="<td><svg height='24' width='24' viewBox='0 0 24 24' ><path d='M19,11 L19,8 L18,7 L8,7 L8,5 L7,4 L2,4 L1,5 L1,22 L19,22 L20,21 L23,11 L5,11 L2,21 L1,22' stroke='black' fill='white' /></svg></td>";
|
||||
content +="<TD class='btnimg blacklink' style='padding:10px 15px;' onclick=\"select_dir('" + jsonresponse.files[i].name+"');\">";
|
||||
content +=jsonresponse.files[i].name;
|
||||
content +="<TD class='btnimg blacklink' style='padding:10px 15px;' onclick=\"select_dir('" + jsonresponse.files[i2].name+"');\">";
|
||||
content +=jsonresponse.files[i2].name;
|
||||
content +="</TD><TD>";
|
||||
content +="</TD><TD width='0%'><div class=\"btnimg\" onclick=\"Deletedir('"+jsonresponse.files[i].name+"')\">";
|
||||
content +="</TD><TD width='0%'><div class=\"btnimg\" onclick=\"Deletedir('"+jsonresponse.files[i2].name+"')\">";
|
||||
content +=trash_icon();
|
||||
content +="</div></TD><td></td></TR>";
|
||||
}
|
||||
@ -155,16 +106,19 @@ if (filename != null) {
|
||||
}
|
||||
function SendCommand(action,filename){
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
var url = "/FILES?action="+action;
|
||||
var url = "/files?action="+action;
|
||||
url += "&filename="+encodeURI(filename);
|
||||
url += "&path="+encodeURI(currentpath);
|
||||
document.getElementById('loader').style.visibility="visible";
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||
var jsonresponse = JSON.parse(xmlhttp.responseText);
|
||||
document.getElementById('loader').style.visibility="hidden";
|
||||
dispatchfilestatus(jsonresponse);}
|
||||
}
|
||||
if (xmlhttp.readyState == 4 ) {
|
||||
if(xmlhttp.status == 200) {
|
||||
var jsonresponse = JSON.parse(xmlhttp.responseText);
|
||||
document.getElementById('loader').style.visibility="hidden";
|
||||
dispatchfilestatus(jsonresponse);}
|
||||
else SubmitRequest ()
|
||||
}
|
||||
};
|
||||
xmlhttp.open("GET", url, true);
|
||||
xmlhttp.send();
|
||||
}
|
||||
@ -175,11 +129,11 @@ document.getElementById('upload-button').value = "Uploading...";
|
||||
document.getElementById('prg').style.visibility = "visible";
|
||||
var formData = new FormData();
|
||||
formData.append('path', currentpath);
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var file = files[i];
|
||||
for (var i3 = 0; i3 < files.length; i3++) {
|
||||
var file = files[i3];
|
||||
formData.append('myfiles[]', file, currentpath+file.name);}
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open('POST', '/FILES', true);
|
||||
xmlhttp.open('POST', '/files', true);
|
||||
//progress upload event
|
||||
xmlhttp.upload.addEventListener("progress", updateProgress, false);
|
||||
//progress function
|
||||
@ -201,15 +155,95 @@ document.getElementById('file-select').value="";
|
||||
var jsonresponse = JSON.parse(xmlhttp.responseText);
|
||||
dispatchfilestatus(jsonresponse);
|
||||
} else alert('An error occurred!');
|
||||
}
|
||||
};
|
||||
xmlhttp.send(formData);
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
SendCommand('list','all');
|
||||
};
|
||||
function Uploadfile(){
|
||||
if (!confirm("Confirm Firmware Update ?"))return;
|
||||
var files = document.getElementById('fw-select').files;
|
||||
if (files.length==0)return;
|
||||
document.getElementById('uploadfw-button').style.visibility = 'hidden';
|
||||
document.getElementById('fw-select').style.visibility = 'hidden';
|
||||
document.getElementById('msg').style.visibility = "visible";
|
||||
document.getElementById('msg').innerHTML="";
|
||||
document.getElementById('SPIFFS').style.display = "none";
|
||||
document.getElementById('prgfw').style.visibility = "visible";
|
||||
var formData = new FormData();
|
||||
for (var i4 = 0; i4 < files.length; i4++) {
|
||||
var file = files[i4];
|
||||
formData.append('myfile[]', file, "/"+file.name);}
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open('POST', '/updatefw', true);
|
||||
//progress upload event
|
||||
xmlhttp.upload.addEventListener("progress", updateProgress, false);
|
||||
//progress function
|
||||
function updateProgress (oEvent) {
|
||||
if (oEvent.lengthComputable) {
|
||||
var percentComplete = (oEvent.loaded / oEvent.total)*100;
|
||||
document.getElementById('prgfw').value=percentComplete;
|
||||
document.getElementById('msg').innerHTML = "Uploading ..." + percentComplete.toFixed(0)+"%" ;
|
||||
} else {
|
||||
// Impossible because size is unknown
|
||||
}
|
||||
}
|
||||
xmlhttp.onload = function () {
|
||||
if (xmlhttp.status === 200) {
|
||||
document.getElementById('uploadfw-button').value = 'Upload';
|
||||
document.getElementById('msg').innerHTML="Restarting, please wait....";
|
||||
document.getElementById('counter').style.visibility = "visible";
|
||||
document.getElementById('uploadfw-button').style.visibility = 'hidden';
|
||||
document.getElementById('uploadfw-button').style.width = '0px';
|
||||
document.getElementById('fw-select').value="";
|
||||
document.getElementById('fw-select').style.visibility = 'hidden';
|
||||
document.getElementById('fw-select').style.width = '0px';
|
||||
|
||||
var jsonresponse = JSON.parse(xmlhttp.responseText);
|
||||
if (jsonresponse.status=='1' || jsonresponse.status=='4' || jsonresponse.status=='1')alert("Update failed");
|
||||
if (jsonresponse.status=='2')alert('Update canceled!');
|
||||
else if (jsonresponse.status=='3')
|
||||
{
|
||||
var i5 = 0;
|
||||
var interval;
|
||||
var x = document.getElementById("prgfw");
|
||||
x.max=40;
|
||||
interval = setInterval(function(){
|
||||
i5=i5+1;
|
||||
var x = document.getElementById("prgfw");
|
||||
x.value=i5;
|
||||
document.getElementById('counter').innerHTML=41-i5;
|
||||
if (i5>40)
|
||||
{
|
||||
clearInterval(interval);
|
||||
location.reload();
|
||||
}
|
||||
},1000);
|
||||
}
|
||||
else alert('Update failed!');
|
||||
} else alert('An error occurred!');
|
||||
};
|
||||
xmlhttp.send(formData);
|
||||
}
|
||||
|
||||
</script>
|
||||
$INCLUDE[footer.inc]$
|
||||
|
||||
function RequestLogin(){
|
||||
document.getElementById('loader').style.visibility="hidden";
|
||||
document.getElementById('loginpage').style.display='block';
|
||||
}
|
||||
|
||||
function SubmitRequest (){
|
||||
document.getElementById('loginpage').style.display='none';
|
||||
var user = document.getElementById('login_user_text').value.trim();
|
||||
var password = document.getElementById('login_password_text').value.trim();
|
||||
var url = "/login?USER="+encodeURIComponent(user) + "&PASSWORD=" + encodeURIComponent(password) + "&SUBMIT=yes" ;
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
|
||||
RequestLogin();
|
||||
}
|
||||
};
|
||||
xmlhttp.open("GET", url, true);
|
||||
xmlhttp.send();
|
||||
}
|
100
embedded/www/tool.html
Normal file
100
embedded/www/tool.html
Normal file
@ -0,0 +1,100 @@
|
||||
<html>
|
||||
<head>
|
||||
<!-- smoosh -->
|
||||
<link href="css/style.css" rel="stylesheet">
|
||||
<!-- endsmoosh -->
|
||||
</head>
|
||||
<body>
|
||||
<div style="position:absolute;top:0;right:0;">
|
||||
V1.1
|
||||
|
||||
</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>
|
||||
</center>
|
||||
|
||||
<div class="panel" id="SPIFFS">
|
||||
<div class="panel-heading">Flash Filesystem</div>
|
||||
<div class="panel-body">
|
||||
<input type="file" id="file-select" name="myfiles[]" multiple />
|
||||
<input class="btn btn-primary" type="button" id="upload-button" onclick="Sendfile();" value="Upload"/> <progress style="visibility:hidden;" name='prg' id='prg' max='100'></progress>
|
||||
<br><br>
|
||||
<div class="panel">
|
||||
<div class="panel-body">
|
||||
<table>
|
||||
<tr>
|
||||
<td width="0%">
|
||||
<input class="btn btn-primary" type="button" onclick="SendCommand('list','all');" value="Refresh"/>
|
||||
</td>
|
||||
<td width="0%">
|
||||
<div onclick="Createdir()" class="btnimg"><svg width="40" height="40" viewBox="0 0 40 40"><rect x="5" y="10" width="30" height="20" rx="2" ry="2" fill="#31b0d5" />
|
||||
<rect x="20" y="5" width="15" height="15" rx="2" ry="2" fill="#31b0d5" /><text x="15" y="25" font-size="18" font-weight="800" fill="white">+</text></svg>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div id="loader" class="loader"></div>
|
||||
</td>
|
||||
<td width="100%">
|
||||
<div id="path" class="info" > </div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="table table-striped" style="border:1px;solid #dddddd;margin-bottom:20px;" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th width='0%'>Type</th>
|
||||
<th>Name</th>
|
||||
<th>Size</th>
|
||||
<th width='0%'></th>
|
||||
<th width='100%'></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="file_list"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="panel-footer " id="status"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="panel-heading">Firmware Update</div>
|
||||
<div class="panel-body">
|
||||
<table>
|
||||
<tr>
|
||||
<td><input type="file" id="fw-select" name="myfiles[]" /></td>
|
||||
<td><input class="btn btn-primary" type="button" id="uploadfw-button" onclick="Uploadfile();" value="Update"/></td>
|
||||
<td><progress style="visibility:hidden;" name='prgfw' id='prgfw' max='100'></progress></td>
|
||||
<td><span id='msg' style='visibility:hidden;'>Restarting, please wait....</span><span id='counter'></span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div id="loginpage"class="modal">
|
||||
<div class="modal-content" >
|
||||
<div class="modal-header">
|
||||
<h3>Identification</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<span>
|
||||
<span class="modal-text" translate>User:</span>
|
||||
<input class='form-control' type="text" id="login_user_text" style="width:auto"/>
|
||||
</span>
|
||||
<hr>
|
||||
<span>
|
||||
<span class="modal-text" translate>Password:</span>
|
||||
<input class='form-control' type="password" id="login_password_text" style="width:auto"/>
|
||||
</span>
|
||||
<br>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<input type="button" class="btn btn-primary" onclick="SubmitRequest()" value="Submit"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- smoosh -->
|
||||
<script src="js/script.js"></script>
|
||||
<!-- endsmoosh -->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
138
esp3d/bridge.cpp
138
esp3d/bridge.cpp
@ -18,6 +18,7 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "bridge.h"
|
||||
#include "command.h"
|
||||
#include "webinterface.h"
|
||||
@ -29,92 +30,91 @@ WiFiClient serverClients[MAX_SRV_CLIENTS];
|
||||
|
||||
bool BRIDGE::header_sent = false;
|
||||
String BRIDGE::buffer_web = "";
|
||||
void BRIDGE::print (const __FlashStringHelper *data, tpipe output){
|
||||
void BRIDGE::print (const __FlashStringHelper *data, tpipe output)
|
||||
{
|
||||
String tmp = data;
|
||||
BRIDGE::print(tmp.c_str(), output);
|
||||
}
|
||||
void BRIDGE::print (String & data, tpipe 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;
|
||||
Serial.print(data);
|
||||
break;
|
||||
case SERIAL1_PIPE:
|
||||
header_sent = false;
|
||||
Serial1.print(data);
|
||||
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);
|
||||
case TCP_PIPE:
|
||||
header_sent = false;
|
||||
BRIDGE::send2TCP(data);
|
||||
break;
|
||||
#endif
|
||||
case WEB_PIPE:
|
||||
if (!header_sent){
|
||||
web_interface->WebServer.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
web_interface->WebServer.sendHeader("Content-Type","text/html");
|
||||
web_interface->WebServer.sendHeader("Cache-Control","no-cache");
|
||||
web_interface->WebServer.send(200);
|
||||
header_sent = true;
|
||||
}
|
||||
buffer_web+=data;
|
||||
if (buffer_web.length() > 1200)
|
||||
{
|
||||
//send data
|
||||
web_interface->WebServer.sendContent(buffer_web);
|
||||
//reset buffer
|
||||
buffer_web="";
|
||||
}
|
||||
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:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void BRIDGE::println (const __FlashStringHelper *data, tpipe output){
|
||||
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){
|
||||
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){
|
||||
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:
|
||||
Serial.flush();
|
||||
break;
|
||||
case SERIAL1_PIPE:
|
||||
Serial1.flush();
|
||||
void BRIDGE::flush (tpipe output)
|
||||
{
|
||||
switch(output) {
|
||||
case SERIAL_PIPE:
|
||||
ESP_SERIAL_OUT.flush();
|
||||
break;
|
||||
#ifdef TCP_IP_DATA_FEATURE
|
||||
case TCP_PIPE:
|
||||
case TCP_PIPE:
|
||||
break;
|
||||
#endif
|
||||
case WEB_PIPE:
|
||||
if(header_sent){
|
||||
//send data
|
||||
web_interface->WebServer.sendContent(buffer_web);
|
||||
//close line
|
||||
web_interface->WebServer.sendContent("");
|
||||
}
|
||||
case WEB_PIPE:
|
||||
if(header_sent) {
|
||||
//send data
|
||||
web_interface->web_server.sendContent(buffer_web);
|
||||
//close line
|
||||
web_interface->web_server.sendContent("");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
header_sent = false;
|
||||
@ -123,36 +123,42 @@ void BRIDGE::flush (tpipe output){
|
||||
|
||||
|
||||
#ifdef TCP_IP_DATA_FEATURE
|
||||
void BRIDGE::send2TCP(const __FlashStringHelper *data){
|
||||
void BRIDGE::send2TCP(const __FlashStringHelper *data)
|
||||
{
|
||||
String tmp = data;
|
||||
BRIDGE::send2TCP(tmp.c_str());
|
||||
}
|
||||
void BRIDGE::send2TCP(String data){
|
||||
void BRIDGE::send2TCP(String data)
|
||||
{
|
||||
BRIDGE::send2TCP(data.c_str());
|
||||
}
|
||||
void BRIDGE::send2TCP(const char * data){
|
||||
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);
|
||||
}
|
||||
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(Serial.available()) {
|
||||
size_t len = Serial.available();
|
||||
if(ESP_SERIAL_OUT.available()) {
|
||||
size_t len = ESP_SERIAL_OUT.available();
|
||||
uint8_t sbuf[len];
|
||||
Serial.readBytes(sbuf, len);
|
||||
ESP_SERIAL_OUT.readBytes(sbuf, len);
|
||||
#ifdef TCP_IP_DATA_FEATURE
|
||||
//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);
|
||||
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
|
||||
@ -192,7 +198,7 @@ void BRIDGE::processFromTCP2Serial()
|
||||
//get data from the tcp client and push it to the UART
|
||||
while(serverClients[i].available()) {
|
||||
data = serverClients[i].read();
|
||||
Serial.write(data);
|
||||
ESP_SERIAL_OUT.write(data);
|
||||
COMMAND::read_buffer_tcp(data);
|
||||
}
|
||||
}
|
||||
|
1314
esp3d/command.cpp
1314
esp3d/command.cpp
File diff suppressed because it is too large
Load Diff
@ -34,10 +34,10 @@ public:
|
||||
static void read_buffer_tcp(uint8_t b);
|
||||
#endif
|
||||
static bool check_command(String buffer, tpipe output, bool handlelockserial = true);
|
||||
static void execute_command(int cmd,String cmd_params, tpipe output);
|
||||
static bool execute_command(int cmd,String cmd_params, tpipe output, level_authenticate_type auth_level = LEVEL_GUEST);
|
||||
static String get_param(String & cmd_params, const char * id, bool withspace = false);
|
||||
static bool isadmin(String & cmd_params);
|
||||
|
||||
static bool isuser(String & cmd_params);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
1627
esp3d/config.cpp
1627
esp3d/config.cpp
File diff suppressed because it is too large
Load Diff
270
esp3d/config.h
270
esp3d/config.h
@ -19,15 +19,47 @@
|
||||
*/
|
||||
|
||||
//definition
|
||||
#define REPETIER 0
|
||||
#define REPETIER4DV 1
|
||||
#define UNKNOWN_FW 0
|
||||
#define REPETIER4DV 1
|
||||
#define MARLIN 2
|
||||
#define MARLINKIMBRA 3
|
||||
#define SMOOTHIEWARE 4
|
||||
#define SMOOTHIEWARE 4
|
||||
#define REPETIER 5
|
||||
|
||||
//FIRMWARE_TARGET: the targeted FW, can be REPETIER (Original Repetier)/ REPETIER4DV (Repetier for Davinci) / MARLIN (Marlin)/ SMOOTHIEWARE (Smoothieware)
|
||||
#define FIRMWARE_TARGET MARLIN
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "FS.h"
|
||||
#include "SPIFFS.h"
|
||||
#define WIFI_NONE_SLEEP WIFI_PS_NONE
|
||||
#define WIFI_MODEM_SLEEP WIFI_PS_MODEM
|
||||
#define WIFI_PHY_MODE_11B WIFI_PROTOCOL_11B
|
||||
#define WIFI_PHY_MODE_11G WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G
|
||||
#define WIFI_PHY_MODE_11N WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N
|
||||
#define AUTH_OPEN WIFI_AUTH_OPEN
|
||||
#define AUTH_WEP WIFI_AUTH_WEP
|
||||
#define AUTH_WPA_PSK WIFI_AUTH_WPA_PSK
|
||||
#define AUTH_WPA2_PSK WIFI_AUTH_WPA2_PSK
|
||||
#define AUTH_WPA_WPA2_PSK WIFI_AUTH_WPA_WPA2_PSK
|
||||
#define ENC_TYPE_NONE AUTH_OPEN
|
||||
#define FS_FILE File
|
||||
#define FS_DIR File
|
||||
#define ESP_SERIAL_OUT Serial
|
||||
#define SD_FILE_READ FILE_READ
|
||||
#define SPIFFS_FILE_READ FILE_READ
|
||||
#define SD_FILE_WRITE FILE_WRITE
|
||||
#define SPIFFS_FILE_WRITE FILE_WRITE
|
||||
|
||||
extern HardwareSerial Serial2;
|
||||
#else
|
||||
#define FS_DIR fs::Dir
|
||||
#define FS_FILE fs::File
|
||||
#define ESP_SERIAL_OUT Serial
|
||||
#define SD_FILE_READ FILE_READ
|
||||
#define SPIFFS_FILE_READ "r"
|
||||
#define SD_FILE_WRITE FILE_WRITE
|
||||
#define SPIFFS_FILE_WRITE "w"
|
||||
#endif
|
||||
|
||||
#define MAX_FW_ID REPETIER
|
||||
|
||||
//number of clients allowed to use data port at once
|
||||
#define MAX_SRV_CLIENTS 1
|
||||
@ -41,7 +73,16 @@
|
||||
#define SSDP_FEATURE
|
||||
|
||||
//NETBIOS_FEATURE: this feature is a discovery protocol, supported on Windows out of the box
|
||||
//#define NETBIOS_FEATURE
|
||||
#define NETBIOS_FEATURE
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef SSDP_FEATURE
|
||||
#undef SSDP_FEATURE
|
||||
#endif
|
||||
#ifdef NETBIOS_FEATURE
|
||||
#undef NETBIOS_FEATURE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//CAPTIVE_PORTAL_FEATURE: In SoftAP redirect all unknow call to main page
|
||||
#define CAPTIVE_PORTAL_FEATURE
|
||||
@ -78,86 +119,97 @@
|
||||
//STATUS_MSG_FEATURE: catch the status msg and filter it to specific table
|
||||
#define STATUS_MSG_FEATURE
|
||||
|
||||
//TEMP_MONITORING_FEATURE : catch the specific answer and store it to variable
|
||||
#define TEMP_MONITORING_FEATURE
|
||||
//SPEED_MONITORING_FEATURE : catch the specific answer and store it to variable
|
||||
#define SPEED_MONITORING_FEATURE
|
||||
//POS_MONITORING_FEATURE : catch the specific answer and store it to variable
|
||||
#define POS_MONITORING_FEATURE
|
||||
//FLOW_MONITORING_FEATURE : catch the specific answer and store it to variable
|
||||
#define FLOW_MONITORING_FEATURE
|
||||
|
||||
|
||||
//Serial rx buffer size is 256 but can be extended
|
||||
#define SERIAL_RX_BUFFER_SIZE 512
|
||||
|
||||
//DEBUG Flag do not do this when connected to printer unless you know what you are doing!!!
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef SSDP_FEATURE
|
||||
#undef SSDP_FEATURE
|
||||
#endif
|
||||
#ifdef NETBIOS_FEATURE
|
||||
#undef NETBIOS_FEATURE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//DEBUG Flag do not do this when connected to printer !!!
|
||||
//be noted all upload may failed if enabled
|
||||
//#define DEBUG_ESP3D
|
||||
//#define DEBUG_OUTPUT_SPIFFS
|
||||
//#define DEBUG_OUTPUT_SD
|
||||
//#define DEBUG_OUTPUT_SERIAL
|
||||
//#define DEBUG_OUTPUT_TCP
|
||||
|
||||
//store performance result in storestring variable : info_msg / status_msg
|
||||
//#define DEBUG_PERFORMANCE
|
||||
#define DEBUG_PERF_VARIABLE (web_interface->info_msg)
|
||||
/*
|
||||
#ifndef FS_NO_GLOBALS
|
||||
#define FS_NO_GLOBALS
|
||||
#endif
|
||||
#include <FS.h>
|
||||
#define DEBUG_ESP3D(string) { FS_FILE logfile = SPIFFS.open("/log.txt", "a+");logfile.print(string);logfile.close();}
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_ESP3D
|
||||
#ifdef DEBUG_OUTPUT_SPIFFS
|
||||
/*#ifdef SDCARD_FEATURE
|
||||
#ifndef FS_NO_GLOBALS
|
||||
#define FS_NO_GLOBALS
|
||||
#endif
|
||||
#endif*/
|
||||
#include <FS.h>
|
||||
#define DEBUG_PIPE NO_PIPE
|
||||
#define LOG(string) {FSFILE logfile = SPIFFS.open("/log.txt", "a+");logfile.print(string);logfile.close();}
|
||||
#ifndef FS_NO_GLOBALS
|
||||
#define FS_NO_GLOBALS
|
||||
#endif
|
||||
#include <FS.h>
|
||||
#define DEBUG_PIPE NO_PIPE
|
||||
#define LOG(string) { FS_FILE logfile = SPIFFS.open("/log.txt", "a+");logfile.print(string);logfile.close();}
|
||||
#endif
|
||||
#ifdef DEBUG_OUTPUT_SERIAL
|
||||
#define LOG(string) {Serial.print(string);}
|
||||
#define DEBUG_PIPE SERIAL_PIPE
|
||||
#define LOG(string) {ESP_SERIAL_OUT.print(string);}
|
||||
#define DEBUG_PIPE SERIAL_PIPE
|
||||
#endif
|
||||
#ifdef DEBUG_OUTPUT_TCP
|
||||
#include "bridge.h"
|
||||
#define LOG(string) {BRIDGE::send2TCP(string);}
|
||||
#define DEBUG_PIPE TCP_PIPE
|
||||
#include "bridge.h"
|
||||
#define LOG(string) {BRIDGE::send2TCP(string);}
|
||||
#define DEBUG_PIPE TCP_PIPE
|
||||
#endif
|
||||
#else
|
||||
#define LOG(string) {}
|
||||
#define DEBUG_PIPE NO_PIPE
|
||||
#endif
|
||||
|
||||
#ifdef SDCARD_FEATURE
|
||||
#define FSFILE fs::File
|
||||
#define FSDIR fs::Dir
|
||||
#define FSINFO fs::FSInfo
|
||||
#else
|
||||
#define FSFILE File
|
||||
#define FSDIR fs::Dir
|
||||
#define FSINFO FSInfo
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_h
|
||||
#define CONFIG_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
#include "wifi.h"
|
||||
#else
|
||||
//Nothing here
|
||||
#endif
|
||||
#include "wificonf.h"
|
||||
//version and sources location
|
||||
#define FW_VERSION "0.9.78"
|
||||
#define FW_VERSION "0.9.99"
|
||||
#define REPOSITORY "https://github.com/luc-github/ESP3D"
|
||||
|
||||
typedef enum {
|
||||
NO_PIPE = 0,
|
||||
SERIAL_PIPE = 2,
|
||||
NO_PIPE = 0,
|
||||
SERIAL_PIPE = 2,
|
||||
SERIAL1_PIPE = 3,
|
||||
#ifdef TCP_IP_DATA_FEATURE
|
||||
TCP_PIPE = 4,
|
||||
TCP_PIPE = 4,
|
||||
#endif
|
||||
WEB_PIPE = 5
|
||||
} tpipe;
|
||||
} tpipe;
|
||||
|
||||
typedef enum {
|
||||
LEVEL_GUEST = 0,
|
||||
LEVEL_USER = 1,
|
||||
LEVEL_ADMIN = 2
|
||||
} level_authenticate_type;
|
||||
|
||||
|
||||
#define NO_SD 0
|
||||
#define SD_DIRECTORY 1
|
||||
#define EXT_DIRECTORY 2
|
||||
|
||||
|
||||
//flags
|
||||
#define AP_MODE 1
|
||||
@ -196,14 +248,29 @@ typedef enum {
|
||||
#define EP_AP_GATEWAY_VALUE 324 //4 bytes xxx.xxx.xxx.xxx
|
||||
#define EP_AP_IP_MODE 329 //1 byte = flag
|
||||
#define EP_AP_PHY_MODE 330 //1 byte = flag
|
||||
//next available is 330
|
||||
//space left 512 - 330 = 18
|
||||
#define EP_DATA_STRING 331 //129 bytes 128+1 = string ; warning does not support multibyte char like chinese
|
||||
#define EP_REFRESH_PAGE_TIME2 460 //1 bytes = flag
|
||||
#define EP_TARGET_FW 461 //1 bytes = flag
|
||||
#define EP_TIMEZONE 462//1 bytes = flag
|
||||
#define EP_TIME_ISDST 463//1 bytes = flag
|
||||
#define EP_TIME_SERVER1 464//129 bytes 128+1 = string ; warning does not support multibyte char like chinese
|
||||
#define EP_TIME_SERVER2 593 //129 bytes 128+1 = string ; warning does not support multibyte char like chinese
|
||||
#define EP_TIME_SERVER3 722 //129 bytes 128+1 = string ; warning does not support multibyte char like chinese
|
||||
#define EP_IS_DIRECT_SD 850//1 bytes = flag
|
||||
#define EP_PRIMARY_SD 851//1 bytes = flag
|
||||
#define EP_SECONDARY_SD 852//1 bytes = flag
|
||||
#define EP_DIRECT_SD_CHECK 853//1 bytes = flag
|
||||
#define EP_SD_CHECK_UPDATE_AT_BOOT 854//1 bytes = flag
|
||||
|
||||
#define LAST_EEPROM_ADDRESS 855
|
||||
//next available is 855
|
||||
//space left 1024 - 855 = 169
|
||||
|
||||
//default values
|
||||
#define DEFAULT_WIFI_MODE AP_MODE
|
||||
const char DEFAULT_AP_SSID [] PROGMEM = "ESP8266";
|
||||
const char DEFAULT_AP_SSID [] PROGMEM = "ESP3D";
|
||||
const char DEFAULT_AP_PASSWORD [] PROGMEM = "12345678";
|
||||
const char DEFAULT_STA_SSID [] PROGMEM = "ESP8266";
|
||||
const char DEFAULT_STA_SSID [] PROGMEM = "ESP3D";
|
||||
const char DEFAULT_STA_PASSWORD [] PROGMEM = "12345678";
|
||||
const byte DEFAULT_STA_IP_MODE = DHCP_MODE;
|
||||
const byte DEFAULT_AP_IP_MODE = STATIC_IP_MODE;
|
||||
@ -229,24 +296,105 @@ const char DEFAULT_ADMIN_PWD [] PROGMEM = "admin";
|
||||
const char DEFAULT_USER_PWD [] PROGMEM = "user";
|
||||
const char DEFAULT_ADMIN_LOGIN [] PROGMEM = "admin";
|
||||
const char DEFAULT_USER_LOGIN [] PROGMEM = "user";
|
||||
const char DEFAULT_TIME_SERVER1 [] PROGMEM = "time.nist.gov";
|
||||
const char DEFAULT_TIME_SERVER2 [] PROGMEM = "0.pool.ntp.org";
|
||||
const char DEFAULT_TIME_SERVER3 [] PROGMEM = "1.pool.ntp.org";
|
||||
#define DEFAULT_TIME_ZONE 1
|
||||
#define DEFAULT_TIME_DST 0
|
||||
#define DEFAULT_PRIMARY_SD 1
|
||||
#define DEFAULT_SECONDARY_SD 2
|
||||
#define DEFAULT_DIRECT_SD_CHECK 0
|
||||
#define DEFAULT_SD_CHECK_UPDATE_AT_BOOT 1
|
||||
|
||||
|
||||
#define DEFAULT_IS_DIRECT_SD 0
|
||||
|
||||
|
||||
|
||||
|
||||
const uint16_t Setting[][2] = {
|
||||
{EP_WIFI_MODE, LEVEL_ADMIN},//0
|
||||
{EP_STA_SSID, LEVEL_ADMIN},//1
|
||||
{EP_STA_PASSWORD, LEVEL_ADMIN},//2
|
||||
{EP_STA_IP_MODE, LEVEL_ADMIN},//3
|
||||
{EP_STA_IP_VALUE, LEVEL_ADMIN},//4
|
||||
{EP_STA_MASK_VALUE, LEVEL_ADMIN},//5
|
||||
{EP_STA_GATEWAY_VALUE, LEVEL_ADMIN},//6
|
||||
{EP_BAUD_RATE, LEVEL_ADMIN},//7
|
||||
{EP_STA_PHY_MODE, LEVEL_ADMIN},//8
|
||||
{EP_SLEEP_MODE, LEVEL_ADMIN},//9
|
||||
{EP_CHANNEL, LEVEL_ADMIN},//10
|
||||
{EP_AUTH_TYPE, LEVEL_ADMIN},//11
|
||||
{EP_SSID_VISIBLE, LEVEL_ADMIN},//12
|
||||
{EP_WEB_PORT, LEVEL_ADMIN},//13
|
||||
{EP_DATA_PORT, LEVEL_ADMIN},//14
|
||||
{EP_REFRESH_PAGE_TIME, LEVEL_USER},//15
|
||||
{EP_HOSTNAME, LEVEL_ADMIN},//16
|
||||
{EP_XY_FEEDRATE, LEVEL_USER},//17
|
||||
{EP_Z_FEEDRATE, LEVEL_USER},//18
|
||||
{EP_E_FEEDRATE, LEVEL_USER},//19
|
||||
{EP_ADMIN_PWD, LEVEL_ADMIN},//20
|
||||
{EP_USER_PWD, LEVEL_USER},//21
|
||||
{EP_AP_SSID, LEVEL_ADMIN},//22
|
||||
{EP_AP_PASSWORD, LEVEL_ADMIN},//23
|
||||
{EP_AP_IP_VALUE, LEVEL_ADMIN},//24
|
||||
{EP_AP_MASK_VALUE, LEVEL_ADMIN},//25
|
||||
{EP_AP_GATEWAY_VALUE, LEVEL_ADMIN},//26
|
||||
{EP_AP_IP_MODE, LEVEL_ADMIN},//27
|
||||
{EP_AP_PHY_MODE, LEVEL_ADMIN},//28
|
||||
{EP_DATA_STRING, LEVEL_USER},//29
|
||||
{EP_REFRESH_PAGE_TIME2, LEVEL_USER},//30
|
||||
{EP_TARGET_FW, LEVEL_USER},//31
|
||||
{EP_TIMEZONE, LEVEL_USER},//32
|
||||
{EP_TIME_ISDST, LEVEL_USER},//33
|
||||
{EP_TIME_SERVER1, LEVEL_USER},//34
|
||||
{EP_TIME_SERVER2, LEVEL_USER},//35
|
||||
{EP_TIME_SERVER3, LEVEL_USER},//36
|
||||
{EP_IS_DIRECT_SD, LEVEL_USER},//37
|
||||
{EP_PRIMARY_SD, LEVEL_USER},//38
|
||||
{EP_SECONDARY_SD, LEVEL_USER},//39
|
||||
{EP_DIRECT_SD_CHECK, LEVEL_USER}, //40
|
||||
{EP_SD_CHECK_UPDATE_AT_BOOT, LEVEL_USER} //41
|
||||
};
|
||||
#define AUTH_ENTRY_NB 42
|
||||
//values
|
||||
#define DEFAULT_MAX_REFRESH 120
|
||||
#define DEFAULT_MIN_REFRESH 0
|
||||
#define DEFAULT_MAX_XY_FEEDRATE 9999
|
||||
#define DEFAULT_MIN_XY_FEEDRATE 1
|
||||
#define DEFAULT_MAX_Z_FEEDRATE 9999
|
||||
#define DEFAULT_MIN_Z_FEEDRATE 1
|
||||
#define DEFAULT_MAX_E_FEEDRATE 9999
|
||||
#define DEFAULT_MIN_E_FEEDRATE 1
|
||||
#define DEFAULT_MAX_WEB_PORT 65001
|
||||
#define DEFAULT_MIN_WEB_PORT 1
|
||||
#define DEFAULT_MAX_DATA_PORT 65001
|
||||
#define DEFAULT_MIN_DATA_PORT 1
|
||||
|
||||
#define MAX_TRY 2000
|
||||
|
||||
//sizes
|
||||
#define EEPROM_SIZE 512 //max is 512
|
||||
#define EEPROM_SIZE 1024 //max is 1024
|
||||
#define MAX_SSID_LENGTH 32
|
||||
#define MIN_SSID_LENGTH 1
|
||||
#define MAX_PASSWORD_LENGTH 64
|
||||
#define MIN_PASSWORD_LENGTH 8
|
||||
//min size of password is 0 or upper than 8 char
|
||||
//so let set min is 0
|
||||
#define MIN_PASSWORD_LENGTH 0
|
||||
#define MAX_LOCAL_PASSWORD_LENGTH 16
|
||||
#define MIN_LOCAL_PASSWORD_LENGTH 1
|
||||
#define MAX_DATA_LENGTH 128
|
||||
#define MIN_DATA_LENGTH 0
|
||||
#define IP_LENGTH 4
|
||||
#define INTEGER_LENGTH 4
|
||||
#define MAX_HOSTNAME_LENGTH 32
|
||||
#define MIN_HOSTNAME_LENGTH 1
|
||||
#define WL_MAC_ADDR_LENGTH 6
|
||||
|
||||
class CONFIG
|
||||
{
|
||||
public:
|
||||
static bool is_direct_sd;
|
||||
static bool read_string(int pos, char byte_buffer[], int size_max);
|
||||
static bool read_string(int pos, String & sbuffer, int size_max);
|
||||
static bool read_buffer(int pos, byte byte_buffer[], int size_buffer);
|
||||
@ -256,18 +404,30 @@ public:
|
||||
static bool write_buffer(int pos, const byte * byte_buffer, int size_buffer);
|
||||
static bool write_byte(int pos, const byte value);
|
||||
static bool reset_config();
|
||||
static void print_config(tpipe output);
|
||||
static void print_config(tpipe output, bool plaintext);
|
||||
static bool SetFirmwareTarget(uint8_t fw);
|
||||
static void InitFirmwareTarget();
|
||||
static void InitDirectSD();
|
||||
static void InitPins();
|
||||
static bool InitBaudrate();
|
||||
static bool InitExternalPorts();
|
||||
static bool check_update_presence();
|
||||
static uint8_t GetFirmwareTarget();
|
||||
static const char* GetFirmwareTargetName();
|
||||
static const char* GetFirmwareTargetShortName();
|
||||
static bool isHostnameValid(const char * hostname);
|
||||
static bool isSSIDValid(const char * ssid);
|
||||
static bool isPasswordValid(const char * password);
|
||||
static bool isLocalPasswordValid(const char * password);
|
||||
static bool isIPValid(const char * IP);
|
||||
static char * intTostr(int value);
|
||||
static String formatBytes(size_t bytes);
|
||||
static String formatBytes(uint32_t bytes);
|
||||
static char * mac2str(uint8_t mac [WL_MAC_ADDR_LENGTH]);
|
||||
static byte split_ip (const char * ptr,byte * part);
|
||||
static void esp_restart();
|
||||
static void flashfromSD(const char * Filename, int flashtype);
|
||||
private:
|
||||
static uint8_t FirmwareTarget;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
18
esp3d/data/404.htm
Normal file
18
esp3d/data/404.htm
Normal file
@ -0,0 +1,18 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<title>404 page</title>
|
||||
</HEAD>
|
||||
<BODY STYLE="background-color: lightblue;">
|
||||
<CENTER>
|
||||
<H1>
|
||||
<svg width='24' height='24' viewBox='0 0 1300 1200'>
|
||||
<g transform='translate(50,1200) scale(1, -1)'>
|
||||
<path fill='red' d='M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z' />
|
||||
</g>
|
||||
</svg>404 Error, unknown page!</H1>
|
||||
<H2>What are you doing here ?</H2>
|
||||
You are not supposed to find this location...
|
||||
</CENTER>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
@ -1,30 +0,0 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<title>Redirecting...</title>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<CENTER>Unknown page - you will be redirected...
|
||||
<BR><BR>
|
||||
if not redirected, <a href='http://$WEB_ADDRESS$'>click here</a>
|
||||
<BR><BR>
|
||||
<PROGRESS name='prg' id='prg'></PROGRESS>
|
||||
|
||||
<script>
|
||||
var i = 0;
|
||||
var x = document.getElementById("prg");
|
||||
x.max=5;
|
||||
var interval=setInterval(function(){
|
||||
i=i+1;
|
||||
var x = document.getElementById("prg");
|
||||
x.value=i;
|
||||
if (i>5)
|
||||
{
|
||||
clearInterval(interval);
|
||||
window.location.href='/';
|
||||
}
|
||||
},1000);
|
||||
</script>
|
||||
</CENTER>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
@ -1,65 +0,0 @@
|
||||
$INCLUDE[header.inc]$
|
||||
<div class="panel">
|
||||
<div class="panel-heading">Access Point</div>
|
||||
<div class="panel-body">
|
||||
<form method="POST">
|
||||
<div class="checkbox"><label class="control-label"><input type="checkbox" name="DEFAULT_MODE" $IS_DEFAULT_MODE$>Default Mode</label></div><br>
|
||||
<div class="form-group $AP_SSID_STATUS$">
|
||||
<label class="control-label" for="CONFIG1">SSID: </label><br>
|
||||
<input type="text" class="form-control" id="CONFIG1" name="SSID" placeholder="SSID (8~32)" max="32" value="$AP_SSID$" style="width: auto;"></div>
|
||||
<div class="form-group $AP_PASSWORD_STATUS$"><label class="control-label" for="CONFIG2">Password:</label><br>
|
||||
<input type="password" class="form-control" id="CONFIG2" name="PASSWORD" placeholder="Password (0~64)" max="64" value="$AP_PASSWORD$" style="width: auto;"></div>
|
||||
<div class="checkbox $IS_SSID_VISIBLE_STATUS$"><label class="control-label"><input type="checkbox" name="SSID_VISIBLE" $IS_SSID_VISIBLE$>Visible</label></div>
|
||||
<div class="form-group $NETWORK_OPTION_LIST_STATUS$"><label class="control-label" for="CONFIG3">Network: </label><br>
|
||||
<select name="NETWORK" id="CONFIG3" class="form-control" style="width:auto;">
|
||||
$NETWORK_OPTION_LIST$
|
||||
</select></div>
|
||||
<div class="form-group $CHANNEL_OPTION_LIST_STATUS$"><label class="control-label" for="CONFIG4">Channel: </label><br>
|
||||
<select name="CHANNEL" id="CONFIG4" class="form-control" style="width:auto;">
|
||||
$CHANNEL_OPTION_LIST$
|
||||
</select></div>
|
||||
<div class="form-group $AUTH_OPTION_LIST_STATUS$"><label class="control-label" for="CONFIG5">Authentification: </label><br>
|
||||
<select name="AUTHENTIFICATION" id="CONFIG5" class="form-control" style="width:auto;">
|
||||
$AUTH_OPTION_LIST$
|
||||
</select></div>
|
||||
<script type="text/javascript">
|
||||
function update_ip_set()
|
||||
{
|
||||
if (document.getElementById("STATIC_IP").checked)
|
||||
{
|
||||
document.getElementById("IP_SET").style.visibility="visible";
|
||||
document.getElementById("IP_SET").style.width="auto";
|
||||
document.getElementById("IP_SET").style.height="auto";
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("IP_SET").style.visibility="hidden";
|
||||
document.getElementById("IP_SET").style.width="0px";
|
||||
document.getElementById("IP_SET").style.height="0px";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<div class="checkbox $AP_STATIC_IP_STATUS$"><label class="control-label"><input type="checkbox" id="STATIC_IP" name="STATIC_IP" onclick="update_ip_set();" $IS_STATIC_IP$>Static IP</label></div>
|
||||
<div id="IP_SET" name="IP_SET">
|
||||
<div class="form-group $AP_IP_STATUS$"><label class="control-label" for="CONFIG6">IP: </label><br>
|
||||
<input type="text" class="form-control" id="CONFIG6" name="IP" placeholder="IP" value="$AP_IP$" max="15" style="width: auto;"></div>
|
||||
<div class="form-group $AP_GW_STATUS$"><label class="control-label" for="CONFIG7">Gateway: </label><br>
|
||||
<input type="text" class="form-control" id="CONFIG7" name="GATEWAY" placeholder="Gateway" value="$AP_GW$" max="15" style="width: auto;"></div>
|
||||
<div class="form-group $AP_SUBNET_STATUS$"><label class="control-label" for="CONFIG8">Subnet: </label><br>
|
||||
<input type="text" class="form-control" id="CONFIG8" name="SUBNET" placeholder="Subnet" value="$AP_SUBNET$" max="15" style="width: auto;"></div>
|
||||
</div>
|
||||
<div class="alert alert-danger" role="alert" style="$ERROR_MSG_VISIBILITY$" >
|
||||
$ERROR_MSG$
|
||||
</div>
|
||||
<hr><input style="$SUBMIT_BUTTON_VISIBILITY$" type="submit" class="btn btn-primary" name="SUBMIT" value="Apply">
|
||||
</form>
|
||||
<div class="alert alert-success" role="alert" style="$SUCCESS_MSG_VISIBILITY$" >
|
||||
$SUCCESS_MSG$
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
update_ip_set();
|
||||
</script>
|
||||
$INCLUDE[footer.inc]$
|
||||
|
@ -1,66 +0,0 @@
|
||||
$INCLUDE[header.inc]$
|
||||
<div class="panel">
|
||||
<div class="panel-heading">Station</div>
|
||||
<div class="panel-body">
|
||||
<form method="POST">
|
||||
<DIV style="$AP_SCAN_VISIBILITY$">
|
||||
<table class="table table-bordered table-striped" >
|
||||
<caption>$AVAILABLE_AP_NB_ITEMS$ AP(s) available</caption>
|
||||
<thead><tr><th>#</th><th>SSID</th><th>Signal</th><th>Protected</th></tr></thead>
|
||||
<tbody>$AVAILABLE_AP[<tr><th>#$ROW_NUMBER$</th><td style="cursor:hand;" onclick="document.getElementById('CONFIG1').value='$AP_SSID$';">$AP_SSID$</td><td>$AP_SIGNAL$</td><td>$IS_PROTECTED$</td></tr>]$</tbody>
|
||||
</table>
|
||||
</DIV>
|
||||
<div class="checkbox"><label class="control-label"><input type="checkbox" name="DEFAULT_MODE" $IS_DEFAULT_MODE$>Default Mode</label></div><br>
|
||||
<div class="form-group $STA_SSID_STATUS$" ><label class="control-label" for="CONFIG1">SSID: </label><br>
|
||||
<input type="text" class="form-control" id="CONFIG1" name="SSID" placeholder="SSID (8~32)" value="$STA_SSID$" max="32" style="width: auto;"></div>
|
||||
<div class="form-group $STA_PASSWORD_STATUS$"><label class="control-label"for="CONFIG2">Password:</label><br>
|
||||
<input type="password" class="form-control" id="CONFIG2" name="PASSWORD" placeholder="Password (0~64)" max="64" value="$STA_PASSWORD$" style="width: auto;"></div>
|
||||
<div class="form-group $HOSTNAME_STATUS$" ><label class="control-label" for="CONFIG7">Hostname: </label><br>
|
||||
<input type="text" class="form-control" id="CONFIG7" name="HOSTNAME" placeholder="Hostname (1~32)" value="$HOSTNAME$" max="32" style="width: auto;"></div>
|
||||
<div class="form-group $NETWORK_OPTION_LIST_STATUS$"><label class="control-label"for="CONFIG3">Network: </label><br>
|
||||
<select name="NETWORK" id="CONFIG3" class="form-control control-label" style="width:auto;">
|
||||
$NETWORK_OPTION_LIST$
|
||||
</select></div>
|
||||
<script type="text/javascript">
|
||||
function update_ip_set()
|
||||
{
|
||||
if (document.getElementById("STATIC_IP").checked)
|
||||
{
|
||||
document.getElementById("IP_SET").style.visibility="visible";
|
||||
document.getElementById("IP_SET").style.width="auto";
|
||||
document.getElementById("IP_SET").style.height="auto";
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("IP_SET").style.visibility="hidden";
|
||||
document.getElementById("IP_SET").style.width="0px";
|
||||
document.getElementById("IP_SET").style.height="0px";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<div class="checkbox $STA_STATIC_IP_STATUS$"><label class="control-label">
|
||||
<input type="checkbox" id="STATIC_IP" name="STATIC_IP" onclick="update_ip_set();" $IS_STATIC_IP$ >Static IP
|
||||
</label>
|
||||
</div>
|
||||
<div id="IP_SET" name="IP_SET">
|
||||
<div class="form-group $STA_IP_STATUS$"><label class="control-label" for="CONFIG4">IP: </label><br>
|
||||
<input type="text" class="form-control" id="CONFIG4" name="IP" placeholder="IP" value="$STA_IP$" max="15" style="width: auto;"></div>
|
||||
<div class="form-group $STA_GW_STATUS$"><label class="control-label"for="CONFIG5">Gateway: </label><br>
|
||||
<input type="text" class="form-control" id="CONFIG5" name="GATEWAY" placeholder="Gateway" value="$STA_GW$" max="15" style="width: auto;"></div>
|
||||
<div class="form-group $STA_SUBNET_STATUS$"><label class="control-label" for="CONFIG6">Subnet: </label><br>
|
||||
<input type="text" class="form-control" id="CONFIG6" name="SUBNET" placeholder="Subnet" value="$STA_SUBNET$" max="15" style="width: auto;"></div>
|
||||
</div>
|
||||
<div class="alert alert-danger" role="alert" style="$ERROR_MSG_VISIBILITY$" >
|
||||
$ERROR_MSG$
|
||||
</div>
|
||||
<hr><input style="$SUBMIT_BUTTON_VISIBILITY$" type="submit" class="btn btn-primary" name="SUBMIT" value="Apply">
|
||||
</form>
|
||||
<div class="alert alert-success" role="alert" style="$SUCCESS_MSG_VISIBILITY$" >
|
||||
$SUCCESS_MSG$
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
update_ip_set();
|
||||
</script>
|
||||
$INCLUDE[footer.inc]$
|
@ -1,27 +0,0 @@
|
||||
<STYLE>
|
||||
input[type="file"]::-webkit-file-upload-button{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation; touch-action:manipulation;cursor:pointer;
|
||||
background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;
|
||||
* -webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none; color: #ffffff;background-color: #5bc0de;border-color: #46b8da;}
|
||||
input[type="file"]::-webkit-file-upload-button:focus{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation; touch-action:manipulation;cursor:pointer;
|
||||
background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;
|
||||
* -webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none; color: #ffffff;background-color: #31b0d5;border-color: #1b6d85;}
|
||||
input[type="file"]::-webkit-file-upload-button:hover{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation; touch-action:manipulation;cursor:pointer;
|
||||
background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;
|
||||
* -webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none; color: #ffffff;background-color: #31b0d5;border-color: #269abc;}
|
||||
.filelink {color:#000000;}
|
||||
.filelink:hover, .filelink:focus {color:#0094FF;}
|
||||
.panel-footer{padding:10px 15px;color:#31708f;background-color:#f5f5f5;border-color:#dddddd;border-top:1px solid #dddddd;}
|
||||
.loader {
|
||||
border: 4px solid #f3f3f3; /* Light grey */
|
||||
border-top: 4px solid #3498db; /* Blue */
|
||||
border-radius: 50%;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
</STYLE>
|
@ -1,6 +0,0 @@
|
||||
$SERVICE_PAGE$
|
||||
<hr><br>
|
||||
<div class="panel">
|
||||
<center><table><tr><td><a class='blacklink' href='https://github.com/luc-github/ESP3D'>ESP3D powered</a></td><td>-</td><td><a class='blacklink' href='http://www.gnu.org/licenses/gpl-2.0.html'>GPL licensed</a></td></center></div>
|
||||
</body>
|
||||
</html>
|
@ -1,30 +0,0 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
$INCLUDE[css.inc]$
|
||||
</style>
|
||||
<title>$PAGE_TITLE$</title> </head>
|
||||
<body>
|
||||
<div class="container"><table class="nav">
|
||||
<tr width=100%>
|
||||
<td class="$MENU_HOME$"><a href="http://$WEB_ADDRESS$/HOME">Home</a></td>
|
||||
<td class="$MENU_SYSTEM$"><a href="http://$WEB_ADDRESS$/CONFIGSYS">System</a></td>
|
||||
<td class="$MENU_AP$"><a href="http://$WEB_ADDRESS$/CONFIGAP">Access Point</a></td>
|
||||
<td class="$MENU_STA$"><a href="http://$WEB_ADDRESS$/CONFIGSTA">Station</a></td>
|
||||
<td class="$MENU_PRINTER$"><a href="http://$WEB_ADDRESS$/PRINTER">3D Printer</a></td>
|
||||
<td class="$MENU_SETTINGS$"><a href="http://$WEB_ADDRESS$/SETTINGS">Extra Settings</a></td>
|
||||
<td width=100%> </td>
|
||||
<td class="$MENU_ADMIN$"><a href="/PASSWORD" style="$DISCONNECT_VISIBILITY$">$LOGIN_ID$</a></td>
|
||||
<td style="padding:0px;"><a href="/LOGIN?DISCONNECT=YES"><div class="btnroundimg" style="$DISCONNECT_VISIBILITY$"><svg width="30" height="30" viewBox="0 0 40 40">
|
||||
<circle style="fill:white" cx="20" cy="20" r="20"/>
|
||||
<circle style="fill:white;stroke:black;stroke-width:4" cx="20" cy="15" r="10"/>
|
||||
<rect style="fill:black;stroke-width:4;stroke:black" width="20" height="15" x="10" y="17" />
|
||||
<circle style="fill:white" cx="20" cy="22" r="2.5"/>
|
||||
<polygon points="20,23 16,30 24,30" style="fill:white"/></svg></div></a></td>
|
||||
<td>FW: V$FW_VER$</td>
|
||||
<td><a href="https://github.com/luc-github/ESP3D">ESP3D</a></td>
|
||||
</tr>
|
||||
</table>
|
@ -1,55 +0,0 @@
|
||||
$INCLUDE[header.inc]$
|
||||
<div class="panel">
|
||||
<div class="panel-heading">System</div>
|
||||
<div class="panel-body"><label>Chip ID: </label><label class="text-info">$CHIP_ID$</label><BR>
|
||||
<label>CPU Frequency: </label><label class="text-info">$CPU_FREQ$ MHz</label><BR>
|
||||
<label>Free Memory: </label><label class="text-info">$FREE_MEM$ bytes</label><BR>
|
||||
<label>SDK Version: </label><label class="text-info">$SDK_VER$</label><BR>
|
||||
<DIV style ="$HOSTNAME_VISIBLE$"><label>Hostname: </label><label class="text-info">$HOSTNAME$</label><BR></DIV>
|
||||
<DIV style ="$MDNS_VISIBLE$;"><label>mDNS name: </label><label class="text-info">$MDNS_NAME$</label><BR></DIV>
|
||||
<DIV style ="$SSDP_VISIBLE$;"><label>SSDP Protocol: </label><label class="text-info">$SSDP_STATUS$</label><BR></DIV>
|
||||
<DIV style ="$CAPTIVE_PORTAL_VISIBLE$;"><label>Captive Portal: </label><label class="text-info">$CAPTIVE_PORTAL_STATUS$</label><BR></DIV>
|
||||
<label>Network: </label><label class="text-info">$NET_PHY$</label><BR>
|
||||
<label>Sleep mode: </label><label class="text-info">$SLEEP_MODE$</label><BR>
|
||||
<label>Boot version: </label><label class="text-info">$BOOT_VER$</label><BR>
|
||||
<label>Baud rate: </label><label class="text-info">$BAUD_RATE$</label><BR>
|
||||
<label>Web port:</label><label class="text-info">$WEB_PORT$</label><BR>
|
||||
<label>Data port:</label><label class="text-info">$DATA_PORT$</label><BR>
|
||||
</div></div>
|
||||
<div class="panel"><div class="panel-heading">Access Point ($AP_STATUS_ENABLED$)</div>
|
||||
<div class="panel-body"><label>Mac address: </label><label class="text-info">$AP_MAC$</label><BR>
|
||||
<div style="$AP_VISIBILITY$;">
|
||||
<label>SSID: </label><label class="text-info">$AP_SSID$</label><BR>
|
||||
<label>Visible: </label><label class="text-info">$AP_IS_VISIBLE$</label><BR>
|
||||
<label>Channel: </label><label class="text-info">$AP_CHANNEL$</label><BR>
|
||||
<label>Authentification: </label><label class="text-info">$AP_AUTH$</label><BR>
|
||||
<label>Maximum connections: </label><label class="text-info">$AP_MAX_CON$</label><BR>
|
||||
<label>DHCP Server: </label><label class="text-info">$AP_DHCP_STATUS$</label><BR>
|
||||
<label>IP: </label><label class="text-info">$AP_IP$</label><BR>
|
||||
<label>Gateway: </label><label class="text-info">$AP_GW$</label><BR>
|
||||
<label>Subnet: </label><label class="text-info">$AP_SUBNET$</label><BR>
|
||||
<table class="table table-bordered table-striped">
|
||||
<caption>$CONNECTED_STATIONS_NB_ITEMS$ connected station(s)</caption>
|
||||
<thead><tr><th>#</th><th>Mac</th><th>IP</th></tr></thead>
|
||||
<tbody>$CONNECTED_STATIONS[<TR><th>#$ROW_NUMBER$</th><td>$MAC_CONNECTED$</td><td>$IP_CONNECTED$</td></TR>]$</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="panel-heading">Station ($STA_STATUS_ENABLED$)</div>
|
||||
<div class="panel-body"><label>Mac address: </label><label class="text-info">$STA_MAC$</label><BR>
|
||||
<div style="$STA_VISIBILITY$;">
|
||||
<label>Connection to: </label><label class="text-info">$STA_SSID$</label><BR>
|
||||
<label>Channel: </label><label class="text-info">$STA_CHANNEL$</label><BR>
|
||||
<label>Status: </label><label class="text-info">$STA_STATUS$</label><BR>
|
||||
<label>Signal strength: </label><label class="text-info">$STA_SIGNAL$%</label><BR>
|
||||
<label>DHCP Client: </label><label class="text-info">$STA_DHCP_STATUS$</label><BR>
|
||||
<label>IP: </label><label class="text-info">$STA_IP$</label><BR>
|
||||
<label>Gateway: </label><label class="text-info">$STA_GW$</label><BR>
|
||||
<label>Subnet: </label><label class="text-info">$STA_SUBNET$</label><BR>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
$INCLUDE[footer.inc]$
|
||||
|
BIN
esp3d/data/index.html.gz
Normal file
BIN
esp3d/data/index.html.gz
Normal file
Binary file not shown.
@ -1,21 +0,0 @@
|
||||
$INCLUDE[header.inc]$
|
||||
<div class="panel">
|
||||
<div class="panel-heading">Log in</div>
|
||||
<div class="panel-body">
|
||||
<form method="POST">
|
||||
<div class="form-group $USER_STATUS$"><label class="control-label" for="USER">User :</label><br>
|
||||
<input type="hidden" name="return" value="$RETURN$">
|
||||
<input type="text" class="form-control" id="USER" name="USER" placeholder="User (1~16)" min="1" max="16" value="$USER$" style="width: auto;"></div>
|
||||
<div class="form-group $USER_PASSWORD_STATUS$"><label class="control-label" for="PASSWORD">Password :</label><br>
|
||||
<input type="password" class="form-control" id="PASSWORD" name="PASSWORD" placeholder="Password (1~16)" min="1" max="16" value="$USER_PASSWORD$" style="width: auto;"></div>
|
||||
<div class="alert alert-danger" role="alert" style="$ERROR_MSG_VISIBILITY$" >
|
||||
$ERROR_MSG$
|
||||
</div>
|
||||
<hr><input style="$SUBMIT_BUTTON_VISIBILITY$" type="submit" class="btn btn-primary" name="SUBMIT" value="Apply">
|
||||
</form>
|
||||
<div class="alert alert-success" role="alert" style="$SUCCESS_MSG_VISIBILITY$" >
|
||||
$SUCCESS_MSG$
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
$INCLUDE[footer.inc]$
|
74
esp3d/data/macrocfg.json
Normal file
74
esp3d/data/macrocfg.json
Normal file
@ -0,0 +1,74 @@
|
||||
[
|
||||
{
|
||||
"name": "",
|
||||
"glyph": "",
|
||||
"filename": "",
|
||||
"target": "",
|
||||
"class": "",
|
||||
"index": 0
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"glyph": "",
|
||||
"filename": "",
|
||||
"target": "",
|
||||
"class": "",
|
||||
"index": 1
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"glyph": "",
|
||||
"filename": "",
|
||||
"target": "",
|
||||
"class": "",
|
||||
"index": 2
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"glyph": "",
|
||||
"filename": "",
|
||||
"target": "",
|
||||
"class": "",
|
||||
"index": 3
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"glyph": "",
|
||||
"filename": "",
|
||||
"target": "",
|
||||
"class": "",
|
||||
"index": 4
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"glyph": "",
|
||||
"filename": "",
|
||||
"target": "",
|
||||
"class": "",
|
||||
"index": 5
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"glyph": "",
|
||||
"filename": "",
|
||||
"target": "",
|
||||
"class": "",
|
||||
"index": 6
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"glyph": "",
|
||||
"filename": "",
|
||||
"target": "",
|
||||
"class": "",
|
||||
"index": 7
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"glyph": "",
|
||||
"filename": "",
|
||||
"target": "",
|
||||
"class": "",
|
||||
"index": 8
|
||||
}
|
||||
]
|
@ -1,111 +0,0 @@
|
||||
$INCLUDE[header.inc]$
|
||||
<div class="panel">
|
||||
<div class="panel-heading">Change Password</div>
|
||||
<div class="panel-body">
|
||||
<form method="POST">
|
||||
<div id="divpassword1" class="form-group $USER_PASSWORD_STATUS$" ><label class="control-label" for="PASSWORD1">Password: </label><br>
|
||||
<input type="password" class="form-control" onkeyup="checkpassword()" id="PASSWORD1" name="PASSWORD" placeholder="Password (1~16)" value="$USER_PASSWORD$" max="16" m1n="1" style="width: auto;"></div>
|
||||
<div id="divpassword2" class="form-group $USER_PASSWORD_STATUS2$"><label class="control-label"for="PASSWORD2">Confirm Password :</label><br>
|
||||
<input type="password" class="form-control" onkeyup="checkpassword()" id="PASSWORD2" name="PASSWORD2" placeholder="Password (1~16)" max="16" minn="1" value="$USER_PASSWORD2$" style="width: auto;"></div>
|
||||
<div class="alert alert-danger" role="alert" id="alerterror" style="$ERROR_MSG_VISIBILITY$" >
|
||||
$ERROR_MSG$
|
||||
</div>
|
||||
<hr><input style="$SUBMIT_BUTTON_VISIBILITY$" type="submit" class="btn btn-primary" id="BTNSUBMIT" name="SUBMIT" value="Apply">
|
||||
</form>
|
||||
<div class="alert alert-success" id="alertsuccess" role="alert" style="$SUCCESS_MSG_VISIBILITY$" >
|
||||
$SUCCESS_MSG$
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function checkpassword()
|
||||
{
|
||||
var msg="";
|
||||
var haserror=false;
|
||||
var hassuccess=false;
|
||||
var password1 = document.getElementById('PASSWORD1').value;
|
||||
var password2 = document.getElementById('PASSWORD2').value;
|
||||
if (password1.length<1)
|
||||
{
|
||||
msg+="Password too short<br>";
|
||||
document.getElementById("divpassword1").className = "form-group has-error";
|
||||
haserror=true;
|
||||
hassuccess=false;
|
||||
}
|
||||
|
||||
if (password1.length>16)
|
||||
{
|
||||
msg+="Password too long<br>";
|
||||
document.getElementById("divpassword1").className = "form-group has-error";
|
||||
haserror=true;
|
||||
hassuccess=false;
|
||||
}
|
||||
|
||||
if (password2.length<1)
|
||||
{
|
||||
msg+="Confirmation Password too short<br>";
|
||||
document.getElementById("divpassword1").className = "form-group has-error";
|
||||
haserror=true;
|
||||
hassuccess=false;
|
||||
}
|
||||
|
||||
if (password2.length>16)
|
||||
{
|
||||
msg+="Confirmation Password too long<br>";
|
||||
document.getElementById("divpassword1").className = "form-group has-error";
|
||||
haserror=true;
|
||||
hassuccess=false;
|
||||
}
|
||||
|
||||
if (password2!=password1)
|
||||
{
|
||||
msg+="Passwords do not matches<br>";
|
||||
document.getElementById("divpassword2").className = "form-group has-error";
|
||||
haserror=true;
|
||||
hassuccess=false;
|
||||
}
|
||||
if (password1.length>0 && password1.length<17)
|
||||
{
|
||||
document.getElementById("divpassword1").className = "form-group has-success";
|
||||
}
|
||||
if (password2==password1 && password1.length>0 && password1.length<17)
|
||||
{
|
||||
haserror=false;
|
||||
hassuccess=true;
|
||||
document.getElementById("divpassword1").className = "form-group has-success";
|
||||
document.getElementById("divpassword2").className = "form-group has-success";
|
||||
msg="Passwords matches"
|
||||
}
|
||||
if (haserror)
|
||||
{
|
||||
document.getElementById("alerterror").style.visibility="visible";
|
||||
document.getElementById("alerterror").style.width="auto";
|
||||
document.getElementById("alerterror").style.height="auto";
|
||||
document.getElementById("alerterror").style.padding="15px";
|
||||
document.getElementById("alerterror").style.marginBottom="20px";
|
||||
document.getElementById("alertsuccess").style.visibility="hidden";
|
||||
document.getElementById("alertsuccess").style.width="0px";
|
||||
document.getElementById("alertsuccess").style.height="0px";
|
||||
document.getElementById("alertsuccess").style.padding="0px";
|
||||
document.getElementById("alertsuccess").style.margin="0px";
|
||||
document.getElementById("BTNSUBMIT").style.visibility="hidden";
|
||||
document.getElementById("alerterror").innerHTML=msg;
|
||||
}
|
||||
if (hassuccess)
|
||||
{
|
||||
document.getElementById("alertsuccess").style.visibility="visible";
|
||||
document.getElementById("alertsuccess").style.width="auto";
|
||||
document.getElementById("alertsuccess").style.height="auto";
|
||||
document.getElementById("alertsuccess").style.padding="15px";
|
||||
document.getElementById("alertsuccess").style.marginBottom="20px";
|
||||
document.getElementById("alerterror").style.visibility="hidden";
|
||||
document.getElementById("alerterror").style.width="0px";
|
||||
document.getElementById("alerterror").style.height="0px";
|
||||
document.getElementById("alerterror").style.padding="0px";
|
||||
document.getElementById("alerterror").style.margin="0px";
|
||||
document.getElementById("BTNSUBMIT").style.visibility="visible";
|
||||
document.getElementById("alertsuccess").innerHTML=msg;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
$INCLUDE[footer.inc]$
|
@ -1,870 +0,0 @@
|
||||
$INCLUDE[header.inc]$
|
||||
$INCLUDE[css2.inc]$
|
||||
<div class="panel">
|
||||
<div class="panel-heading" ><div class="btnimg" style="float:left;" onclick="control_expanded = expand_collapse(control_expanded,'pin_control','control')" id="pin_control">▼</div> Control</div>
|
||||
<div class="panel-body" id="control">
|
||||
<table>
|
||||
<tr><td style="padding:0px;">
|
||||
<div id="Extruder1" style="visibility:hidden;height:0px;">
|
||||
<table><tr><td><label>E1: </label></td>
|
||||
<td id="data_extruder1" style="overflow: hidden;"></td><td>0<input id="rangeinput1" type="range" min=0 max=270 onchange="Updatenumber('1');">270</td>
|
||||
<td><input class="form-control" id="numberinput1" type="number" min=0 max=270 step=1 value=0 onchange="Updaterange('1');"></td><td> °C
|
||||
<td><input type="button" class="btn btn-primary" value="Set" onclick="SendValue( 'M104 T0 S', '1');"></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</td></tr>
|
||||
<tr ><td style="padding:0px;">
|
||||
<div id="Extruder2" style="visibility:hidden;height:0px;">
|
||||
<table><tr><td><label>E2: </label></td>
|
||||
<td id="data_extruder2" style="overflow: hidden;"></td><td>0<input id="rangeinput2" type="range" min=0 max=270 onchange="Updatenumber('2');">270</td>
|
||||
<td><input class="form-control" id="numberinput2" type="number" min=0 max=270 step=1 value=0 onchange="Updaterange('2');"></td><td>°C
|
||||
<input type="button" class="btn btn-primary" value="Set" onclick="SendValue( 'M104 T1 S', '2');">
|
||||
</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</td></tr>
|
||||
<tr><td style="padding:0px;">
|
||||
<div id="Bed" style="visibility:hidden;height:0px;">
|
||||
<table><tr><td><label>Bed:</label></td>
|
||||
<td id="data_bed" style="overflow: hidden;"></td><td>0<input id="rangeinputbed" type="range" min=0 max=130 onchange="Updatenumber('bed');">130</td>
|
||||
<td><input class="form-control" id="numberinputbed"type="number" min=0 max=270 step=1 value=0 onchange="Updaterange('bed');"></td><td>°C
|
||||
<input type="button" class="btn btn-primary" value="Set" onclick="SendValue( 'M140 S', 'bed');">
|
||||
</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</td></tr>
|
||||
<tr><td id="speed">
|
||||
<table>
|
||||
<tr>
|
||||
<td><label>Speed:</label></td><td><label class="text-info" id="currentspeed"></label></td>
|
||||
<td>0<input id="rangeinputspeed" type="range" min=0 max=300 onchange="Updatenumber('speed');">300</td>
|
||||
<td><input class="form-control" id="numberinputspeed" type="number" size="3" min=0 max=300 step=1 value=0 onchange="Updaterange('speed');"></td><td>%
|
||||
<input type="button" class="btn btn-primary" class="btn btn-primary" value="Set" onclick="SendValue( 'M220 S', 'speed');"></td>
|
||||
<td> </td>
|
||||
<td colspan=3>
|
||||
<div id="autostatus">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Status:</td>
|
||||
<td id="status" align="center" valign="middle"><svg width="20" height="20"><circle cx="10" cy="10" r="8" stroke="black" stroke-width="2" fill="white"></circle></svg></td>
|
||||
<td id="status-text" style="width:100px;"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="manualstatus"><input type="button" class="btn btn-primary" value="Refresh" onclick="getstatus();" ></div>
|
||||
</td>
|
||||
<td> </td><td class="btnimg" onclick="OnclickEmergency();">
|
||||
<svg width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="18" stroke="black" stroke-width="2" fill="red" />
|
||||
<circle cx="20" cy="20" r="10" stroke="black" stroke-width="4" fill="red" /><rect x="15" y="8" width="10" height="10" style="fill:red;stroke-width:1;stroke:red" />
|
||||
<rect x="18" y="6" rx="1" ry="1" width="4" height="14" style="fill:black;stroke-width:1;stroke:black" /></svg></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
<tr><td id="flow">
|
||||
<table>
|
||||
<tr>
|
||||
<td><label>Flow:</label></td><td><label class="text-info" id="currentflow"></label></td>
|
||||
<td>0<input id="rangeinputflow" type="range" min=0 max=300 onchange="Updatenumber('flow');">300</td>
|
||||
<td><input class="form-control" id="numberinputflow" size="3" type="number" min=0 max=300 step=1 value=0 onchange="Updaterange('flow');"></td><td>%
|
||||
<input type="button" class="btn btn-primary" value="Set" onclick="SendValue( 'M221 S', 'flow');"></td><td> </td>
|
||||
<td><label>X:</label></td><td><label class="text-info" id="posx"></label></td><td> </td>
|
||||
<td><label>Y:</label></td><td><label class="text-info" id="posy"></label></td><td> </td>
|
||||
<td><label>Z:</label></td><td><label class="text-info" id="posz" ></label></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-heading"><div class="btnimg" style="float:left;" onclick="command_expanded = expand_collapse(command_expanded,'pin_command','command')" id="pin_command">▼</div> Command</div>
|
||||
<div class="panel-body" id="command">
|
||||
<table width="100%"><tr>
|
||||
<td width="100%"><input class="form-control" id="cmd" type="text" style="width: 100%;"></td>
|
||||
<td width="auto"><input type="button" class="btn btn-primary" value="Send" onclick="Sendcustomcommand();"></td></tr></table>
|
||||
<textarea style="overflow: scroll;width: 100%" rows="10" id="logwindow" readonly></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-heading"><div class="btnimg" style="float:left;" onclick="information_expanded = expand_collapse(information_expanded,'pin_information','information')" id="pin_information">▼</div> Information</div>
|
||||
<div class="panel-body" id="information">
|
||||
<table><tr><td>
|
||||
<center><table><tr><td><div class="btnimg" onclick="if(confirm('Clear Info log ?'))Sendcommand('[ESP999]INFO');">
|
||||
<svg height="20" width="20" viewBox="0 0 40 40" >";
|
||||
<circle cx="20" cy="20" r="17" stroke="black" stroke-width="1" fill="red" />
|
||||
<line x1="11" y1="11" x2="29" y2="29" style="stroke:white;stroke-width:6" />
|
||||
<line x1="29" y1="11" x2="11" y2="29" style="stroke:white;stroke-width:6" /></svg></div></td></tr></table></center>
|
||||
</td><td width=100% id="infomsg" class="text-info"></td></tr></table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="panel-heading"><div class="btnimg" style="float:left;" onclick="error_expanded = expand_collapse(error_expanded,'pin_error','error')" id="pin_error">▼</div> Error</div>
|
||||
<div class="panel-body" id="error">
|
||||
<table><tr><td>
|
||||
<center><table><tr><td><div class="btnimg" onclick="if(confirm('Clear Error log ?'))Sendcommand('[ESP999]ERROR');">
|
||||
<svg height="20" width="20" viewBox="0 0 40 40" >";
|
||||
<circle cx="20" cy="20" r="17" stroke="black" stroke-width="1" fill="red" />
|
||||
<line x1="11" y1="11" x2="29" y2="29" style="stroke:white;stroke-width:6" />
|
||||
<line x1="29" y1="11" x2="11" y2="29" style="stroke:white;stroke-width:6" /></svg></div></td></tr></table></center>
|
||||
</td><td width=100% id="errormsg" class="text-info"></td></tr></table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="panel-heading"><div class="btnimg" style="float:left;" onclick="status_expanded = expand_collapse(status_expanded,'pin_status','statusdisplay')" id="pin_status">▼</div> Status</div>
|
||||
<div class="panel-body" id="statusdisplay">
|
||||
<table><tr><td>
|
||||
<center><table><tr><td><div class="btnimg" onclick="if(confirm('Clear Status log ?'))Sendcommand('[ESP999]STATUS');">
|
||||
<svg height="20" width="20" viewBox="0 0 40 40" >";
|
||||
<circle cx="20" cy="20" r="17" stroke="black" stroke-width="1" fill="red" />
|
||||
<line x1="11" y1="11" x2="29" y2="29" style="stroke:white;stroke-width:6" />
|
||||
<line x1="29" y1="11" x2="11" y2="29" style="stroke:white;stroke-width:6" /></svg></div></td></tr></table></center>
|
||||
</td><td width=100% id="statusmsg" class="text-info"></td></tr></table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="panel-heading"><div class="btnimg" style="float:left;" onclick="printcommands_expanded = expand_collapse(printcommands_expanded,'pin_printcommands','printcommands')" id="pin_printcommands">▼</div> Print</div>
|
||||
<div class="panel-body" id="printcommands">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="Sendcommand('M24');">
|
||||
<svg width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="18" stroke="black" stroke-width="2" fill="white" /><polygon points="15,10 30,20 15,30" fill:"white" stroke:"white" stroke-width:"1" /></svg></td>
|
||||
<td class="btnimg" onclick="Sendcommand('M25');"><svg width="40" height="40" viewBox="0 0 40 40"> <circle cx="20" cy="20" r="18" stroke="black" stroke-width="2" fill="white" />
|
||||
<rect x="10" y="10" width="7" height="20" rx="2" ry="2" style="fill:rgb(0,0,0);stroke-width:1;stroke:rgb(0,0,0)" /> <rect x="23" y="10" width="7" height="20" rx="2" ry="2" style="fill:rgb(0,0,0);stroke-width:1;stroke:rgb(0,0,0)" /></svg></td>
|
||||
<td class="btnimg" onclick="Sendcommand('M50');"><svg width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="18" stroke="black" stroke-width="2" fill="white" />
|
||||
<rect x="10" y="10" width="20" height="20" rx="2" ry="2" style="fill:rgb(0,0,0);stroke-width:1;stroke:rgb(0,0,0)" /></svg></td>
|
||||
<td> </td>
|
||||
<td id="SDLIST"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="panel-heading"><div class="btnimg" style="float:left;" onclick="jog_expanded = expand_collapse(jog_expanded,'pin_jog','jogcommands')" id="pin_jog">▼</div> Jog</div>
|
||||
<div class="panel-body" id="jogcommands">
|
||||
<table>
|
||||
<tr align="center" valign="middle">
|
||||
<td class="btnimg" onclick=" Sendcommand('G28 X');">
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" ><polygon points="7,40 7,25 4,28 0,24 20,4 26,10 26,6 32,6 32,16 40,24 36,28 33,25 33,40" fill="black" stroke-width:"1" stroke:"black" />
|
||||
<line x1="25" y1="8" x2="33" y2="16" style="stroke:white;stroke-width:1" /><polyline points="4,28 20,12 36,28" style="fill:none;stroke:white;stroke-width:1" />
|
||||
<text x="15" y="35" font-family="Verdana" font-size="14" fill="white">X</text></svg></td><td>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Y-10',XYfeedrate);"><svg width="40" height="20" viewBox="0 0 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:blue;stroke-width:7"/><text x="13" y="20" font-family="Verdana" font-size="7" fill="black">-10</text></svg></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Y-1',XYfeedrate);"><svg width="40" height="20" viewBox="0 2 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:blue;stroke-width:5"/><text x="15" y="20" font-family="Verdana" font-size="7" fill="black">-1</text></svg></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Y-0.1',XYfeedrate);"><svg width="40" height="20" viewBox="0 4 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:blue;stroke-width:2"/><text x="12" y="20" font-family="Verdana" font-size="7" fill="black">-0.1</text></svg></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="btnimg" onclick=" Sendcommand('G28 Y');"><svg width="40" height="40" viewBox="0 0 40 40">
|
||||
<polygon points="7,40 7,25 4,28 0,24 20,4 26,10 26,6 32,6 32,16 40,24 36,28 33,25 33,40" fill="blue" stroke-width:"1" stroke:"black" /><line x1="25" y1="8" x2="33" y2="16" style="stroke:white;stroke-width:1" />
|
||||
<polyline points="4,28 20,12 36,28" style="fill:none;stroke:white;stroke-width:1" /><text x="15" y="35" font-family="Verdana" font-size="14" fill="white">Y</text></svg>
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Z-10',Zfeedrate);"><svg width="40" height="20" viewBox="0 0 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:green;stroke-width:7"/><text x="13" y="20" font-family="Verdana" font-size="7" fill="black">-10</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Z-1',Zfeedrate);"><svg width="40" height="20" viewBox="0 2 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:green;stroke-width:5"/><text x="15" y="20" font-family="Verdana" font-size="7" fill="black">-1</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Z-0.1',Zfeedrate);"><svg width="40" height="20" viewBox="0 4 40 20"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:green;stroke-width:2"/>
|
||||
<text x="12" y="20" font-family="Verdana" font-size="7" fill="black">-0.1</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td></td>
|
||||
<td id="JogExtruder1-1" style="visibility:hidden;">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E-50',Efeedrate,'T0');"><svg width="40" height="20" viewBox="0 0 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:orange;stroke-width:7"/><text x="13" y="20" font-family="Verdana" font-size="7" fill="black">-50</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E-10',Efeedrate,'T0');"><svg width="40" height="20" viewBox="0 2 40 20"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:orange;stroke-width:5"/>
|
||||
<text x="14" y="20" font-family="Verdana" font-size="7" fill="black">-10</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E-1',Efeedrate,'T0');"><svg width="40" height="20" viewBox="0 4 40 20"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:orange;stroke-width:2"/>
|
||||
<text x="14" y="20" font-family="Verdana" font-size="7" fill="black">-1</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td></td>
|
||||
<td id="JogExtruder2-1" style="visibility:hidden;">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E-50',Efeedrate,'T1');"><svg width="40" height="20" viewBox="0 0 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:pink;stroke-width:7"/><text x="13" y="20" font-family="Verdana" font-size="7" fill="black">-50</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E-10',Efeedrate,'T1');"><svg width="40" height="20" viewBox="0 2 40 20"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:pink;stroke-width:5"/>
|
||||
<text x="14" y="20" font-family="Verdana" font-size="7" fill="black">-10</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E-1',Efeedrate,'T1');"><svg width="40" height="20" viewBox="0 4 40 20"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:pink;stroke-width:2"/>
|
||||
<text x="15" y="20" font-family="Verdana" font-size="7" fill="black">-1</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr align="center" valign="middle">
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'X10',XYfeedrate);"><svg width="20" height="40" viewBox="12 -10 20 40">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:black;stroke-width:7" transform="rotate(-90 20 10)"/><text x="22" y="13" font-family="Verdana" font-size="7" fill="black">10</text></svg></td>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'X1',XYfeedrate);"><svg width="20" height="40" viewBox="10 -10 20 40"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:black;stroke-width:5" transform="rotate(-90 20 10)"/>
|
||||
<text x="21" y="13" font-family="Verdana" font-size="7" fill="black">1</text></svg></td>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'X0.1',XYfeedrate);"><svg width="20" height="40" viewBox="14 -10 20 40">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:black;stroke-width:2" transform="rotate(-90 20 10)"/><text x="19" y="13" font-family="Verdana" font-size="7" fill="black">0.1</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'X-0.1',XYfeedrate);"><svg width="20" height="40" viewBox="6 -10 20 40">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:black;stroke-width:3" transform="rotate(90 20 10)"/><text x="7" y="12" font-family="Verdana" font-size="7" fill="black">-0.1</text></svg></td>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'X-1',XYfeedrate);"><svg width="20" height="40" viewBox="8 -10 20 40"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:black;stroke-width:5" transform="rotate(90 20 10)"/>
|
||||
<text x="11" y="13" font-family="Verdana" font-size="7" fill="black">-1</text></svg></td><td class="btnimg" onclick="SendJogcommand( 'X-10',XYfeedrate);">
|
||||
<svg width="20" height="40" viewBox="8 -10 20 40"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:black;stroke-width:7" transform="rotate(90 20 10)"/>
|
||||
<text x="7" y="12" font-size="7" fill="black">-10</text></svg>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td></td>
|
||||
<td><svg width="20" height="20" viewBox="0 0 20 20"><text x="1" y="18" font-family="Verdana" font-size="22" fill="green">Z</text></svg></td>
|
||||
<td></td>
|
||||
<td id="JogExtruder1-2" style="visibility:hidden;"><svg width="20" height="20" viewBox="0 0 20 20"><text x="1" y="18" font-family="Verdana" font-size="22" fill="orange">1</text></svg></td>
|
||||
<td></td>
|
||||
<td id="JogExtruder2-2" style="visibility:hidden;"><svg width="20" height="20" viewBox="0 0 20 20"><text x="1" y="18" font-family="Verdana" font-size="22" fill="pink">2</text></svg></td>
|
||||
</tr>
|
||||
<tr align="center" valign="middle">
|
||||
<td class="btnimg" onclick=" Sendcommand('G28');"><svg width="40" height="40" viewBox="0 0 40 40"><polygon points="7,40 7,25 4,28 0,24 20,4 26,10 26,6 32,6 32,16 40,24 36,28 33,25 33,40" fill="purple" stroke-width:"1" stroke:"black" />
|
||||
<line x1="25" y1="8" x2="33" y2="16" style="stroke:white;stroke-width:1" /><polyline points="4,28 20,12 36,28" style="fill:none;stroke:white;stroke-width:1" /></svg></td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Y0.1',XYfeedrate);"><svg width="40" height="20" viewBox="0 -4 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:blue;stroke-width:3" transform="rotate(180 20 10)"/><text x="15" y="6" font-family="Verdana" font-size="7" fill="black">0.1</text></svg></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Y1',XYfeedrate);"><svg width="40" height="20" viewBox="0 -2 40 20"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:blue;stroke-width:5" transform="rotate(180 20 10)"/>
|
||||
<text x="17" y="7" font-family="Verdana" font-size="7" fill="black">1</text></svg></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Y10',XYfeedrate);"><svg width="40" height="20" viewBox="0 0 40 20"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:blue;stroke-width:7" transform="rotate(180 20 10)"/>
|
||||
<text x="15" y="6" font-family="Verdana" font-size="7" fill="black">10</text></svg></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="btnimg" onclick=" Sendcommand('G28 Z');"><svg width="40" height="40" viewBox="0 0 40 40"><polygon points="7,40 7,25 4,28 0,24 20,4 26,10 26,6 32,6 32,16 40,24 36,28 33,25 33,40" fill="green" stroke-width:"1" stroke:"black" />
|
||||
<line x1="25" y1="8" x2="33" y2="16" style="stroke:white;stroke-width:1" /><polyline points="4,28 20,12 36,28" style="fill:none;stroke:white;stroke-width:1" /><text x="15" y="35" font-family="Verdana" font-size="14" fill="white">Z</text></svg></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Z0.1',Zfeedrate);"><svg width="40" height="20" viewBox="0 -4 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:green;stroke-width:3" transform="rotate(180 20 10)"/><text x="14" y="6" font-family="Verdana" font-size="7" fill="black">0.1</text></svg></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Z1',Zfeedrate);"><svg width="40" height="20" viewBox="0 -2 40 20"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:green;stroke-width:5" transform="rotate(180 20 10)"/>
|
||||
<text x="18" y="7" font-family="Verdana" font-size="7" fill="black">1</text></svg></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'Z10',Zfeedrate);"><svg width="40" height="20" viewBox="0 0 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:green;stroke-width:7" transform="rotate(180 20 10)"/><text x="15" y="6" font-family="Verdana" font-size="7" fill="black">10</text></svg></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td></td>
|
||||
<td id="JogExtruder1-3" style="visibility:hidden;">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E1',Efeedrate,'T0');"><svg width="40" height="20" viewBox="0 -4 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:orange;stroke-width:3" transform="rotate(180 20 10)"/><text x="18" y="6" font-family="Verdana" font-size="7" fill="black">1</text></svg></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E10',Efeedrate,'T0');"><svg width="40" height="20" viewBox="0 -2 40 20"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:orange;stroke-width:5" transform="rotate(180 20 10)"/>
|
||||
<text x="14" y="7" font-family="Verdana" font-size="7" fill="black">10</text></svg></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E50',Efeedrate,'T0');"><svg width="40" height="20" viewBox="0 0 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:orange;stroke-width:7" transform="rotate(180 20 10)"/><text x="15" y="6" font-family="Verdana" font-size="7" fill="black">50</text></svg></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td></td>
|
||||
<td id="JogExtruder2-3" style="visibility:hidden;">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E1',Efeedrate,'T1');"><svg width="40" height="20" viewBox="0 -4 40 20">
|
||||
<polyline points="5,18 20,5 35,18" style="fill:none;stroke:pink;stroke-width:3" transform="rotate(180 20 10)"/><text x="18" y="6" font-family="Verdana" font-size="7" fill="black">1</text></svg></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E10',Efeedrate,'T1');"><svg width="40" height="20" viewBox="0 -2 40 20"><polyline points="5,18 20,5 35,18" style="fill:none;stroke:pink;stroke-width:5" transform="rotate(180 20 10)"/>
|
||||
<text x="14" y="7" font-family="Verdana" font-size="7" fill="black">10</text></svg></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="btnimg" onclick="SendJogcommand( 'E50',Efeedrate,'T1');"><svg width="40" height="20" viewBox="0 0 40 20" ><polyline points="5,18 20,5 35,18" style="fill:none;stroke:pink;stroke-width:7" transform="rotate(180 20 10)"/>
|
||||
<text x="15" y="6" font-family="Verdana" font-size="7" fill="black">50</text></svg></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="panel-heading"><div class="btnimg" style="float:left;" onclick="filemanager_expanded = expand_collapse(filemanager_expanded,'pin_filemanager','filemanager')" id="pin_filemanager">▼</div> SD Files</div>
|
||||
<div class="panel-body" id="filemanager">
|
||||
<input type="file" id="file-select" name="myfiles[]" multiple/>
|
||||
<input class="btn btn-primary" type="button" id="upload-button" onclick="Sendfile();" value="Upload"/> <progress style="visibility:hidden;" name='prg' id='prg' max='100'></progress>
|
||||
<br><br><div class="panel">
|
||||
<div class="panel-body">
|
||||
<table><tr><td width="0%">
|
||||
<div onclick="Createdir()" class="btnimg" id="iconcreatedir" style="display:none;"><svg width="40" height="40" viewBox="0 0 40 40"><rect x="5" y="10" width="30" height="20" rx="2" ry="2" fill="#31b0d5" />
|
||||
<rect x="20" y="5" width="15" height="15" rx="2" ry="2" fill="#31b0d5" /><text x="15" y="25" font-size="18" font-weight="800" fill="white">+</text></svg>
|
||||
</div>
|
||||
</td><td><div id="loader" class="loader"></div></td><td width="100%"><div id="path" class="info" > </div>
|
||||
</td>
|
||||
</tr></table>
|
||||
<table class="table table-striped" style="border:1px;solid #dddddd;margin-bottom:20px;" ><thead><tr><th width='0%'>Type</th><th>Name</th><th>Size</th><th width='0%'></th><th width='0%'></th><th width='100%'></th></tr></thead><tbody id="file_list"><tbody></table>
|
||||
</div>
|
||||
<div class="panel-footer " id="filestatus"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var control_expanded = true;
|
||||
var command_expanded = true;
|
||||
var information_expanded = true;
|
||||
var status_expanded = true;
|
||||
var error_expanded = true;
|
||||
var filemanager_expanded = true;
|
||||
var printcommands_expanded = true;
|
||||
var jog_expanded = true;
|
||||
function expand_collapse(flag, targetpin,targetdiv){
|
||||
if (flag) {
|
||||
document.getElementById(targetpin).innerHTML = '►';
|
||||
document.getElementById(targetdiv).style.display = 'none';
|
||||
return false;
|
||||
} else {
|
||||
document.getElementById(targetpin).innerHTML = '▼';
|
||||
document.getElementById(targetdiv).style.display = 'block';
|
||||
return true;
|
||||
}
|
||||
}
|
||||
var XYfeedrate=$XY_FEEDRATE$;
|
||||
var Zfeedrate=$Z_FEEDRATE$;
|
||||
var Efeedrate=$E_FEEDRATE$;
|
||||
|
||||
function Sendcommand(commandtxt, showresult){
|
||||
if (typeof showresult === 'undefined')showresult=false
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
var url = "/command?plain="+encodeURIComponent(commandtxt);
|
||||
if (!showresult)url = "/command_silent?plain="+encodeURIComponent(commandtxt);
|
||||
if (showresult){
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == 4 && xmlhttp.status === 200) {
|
||||
var textarea = document.getElementById("logwindow");
|
||||
textarea.innerHTML = textarea.innerHTML + xmlhttp.responseText;
|
||||
textarea.scrollTop = textarea.scrollHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlhttp.open("GET", url, true);
|
||||
xmlhttp.send();
|
||||
}
|
||||
|
||||
function delay(ms) {
|
||||
ms += new Date().getTime();
|
||||
while (new Date() < ms){}
|
||||
}
|
||||
|
||||
function SendJogcommand( cmd, feedrate, extra){
|
||||
if (typeof extra === 'undefined')extra=""
|
||||
if (extra != ""){
|
||||
Sendcommand(extra);
|
||||
delay(100);
|
||||
}
|
||||
Sendcommand("G91");
|
||||
delay(100);
|
||||
Sendcommand("G1 "+cmd + " F"+feedrate);
|
||||
delay(100);
|
||||
Sendcommand("G90");
|
||||
}
|
||||
function SendValue( cmd, item){
|
||||
Sendcommand(cmd + document.getElementById("numberinput"+item).value);
|
||||
}
|
||||
function Sendcustomcommand(){
|
||||
var cmd = document.getElementById("cmd").value;
|
||||
if (cmd.trim().length > 0) Sendcommand(cmd,true);
|
||||
document.getElementById("cmd").value="";
|
||||
}
|
||||
function OnclickEmergency(){
|
||||
Sendcommand("M112");
|
||||
}
|
||||
function Updatenumber(item){
|
||||
document.getElementById("numberinput"+item).value=document.getElementById("rangeinput"+item).value;
|
||||
}
|
||||
function Updaterange(item){
|
||||
document.getElementById("rangeinput"+item).value=document.getElementById("numberinput"+item).value;
|
||||
}
|
||||
Updaterange('1');
|
||||
Updaterange('2');
|
||||
Updaterange('bed');
|
||||
Updaterange('speed');
|
||||
Updaterange('flow');
|
||||
var pulse=true;
|
||||
var initialization_done = false;
|
||||
var pos=0;
|
||||
function displaytemp(temperature, target,item,factor){
|
||||
var displaypicture = "<svg width='300' height='30' viewBox='0 0 300 30'>\n";
|
||||
if (temperature.length ==0)temperature=0;
|
||||
if (target.length ==0)target=0;
|
||||
var description = String (temperature) + "/";
|
||||
if (target>0)description += String (target);
|
||||
else description += "Off ";
|
||||
displaypicture+="<defs><linearGradient id='grad1' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#0007FE;stop-opacity:1' />\n";
|
||||
displaypicture+="<stop offset='100%' style='stop-color:#00FAFE;stop-opacity:1' /></linearGradient>/n";
|
||||
displaypicture+="<linearGradient id='grad2' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#00FAFE;stop-opacity:1' />\n";
|
||||
displaypicture+="<stop offset='100%' style='stop-color:#00FF00;stop-opacity:1' /></linearGradient>\n";
|
||||
displaypicture+="<linearGradient id='grad3' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#00FF00;stop-opacity:1' />\n"
|
||||
displaypicture+="<stop offset='100%' style='stop-color:#FAFD00;stop-opacity:1' /></linearGradient>\n";
|
||||
displaypicture+="<linearGradient id='grad4' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#FAFD00;stop-opacity:1' />\n";
|
||||
displaypicture+="<stop offset='100%' style='stop-color:#FE0700;stop-opacity:1' /></linearGradient></defs>\n";
|
||||
displaypicture+="<rect x='10' y='4' width='70' height='21' fill='url(#grad1)' /><rect x='80' y='4' width='70' height='21' fill='url(#grad2)' />\n";
|
||||
displaypicture+="<rect x='150' y='4' width='70' height='21' fill='url(#grad3)' /><rect x='220' y='4' width='70' height='21' fill='url(#grad4)' />\n";
|
||||
displaypicture+="<rect x='10' y='4' width='280' height='21' fill='none' stroke-width='1' stroke='#C3BDB5' />\n";
|
||||
displaypicture+="<line x1=\"";
|
||||
displaypicture+=String(parseFloat(target)*factor+10);
|
||||
displaypicture+="\" y1=\"4\" x2=\"";
|
||||
displaypicture+=String(parseFloat(target)*factor+10);
|
||||
displaypicture+="\" y2=\"25\" style=\"stroke:rgb(255,255,255);stroke-width:1\" />\n<path d=\"M";
|
||||
displaypicture+=String(parseFloat(temperature)*factor+5);
|
||||
displaypicture+=" 0 L";
|
||||
displaypicture+=String(parseFloat(temperature)*factor+15);
|
||||
displaypicture+=" 0 L";
|
||||
displaypicture+=String(parseFloat(temperature)*factor+10);
|
||||
displaypicture+=" 8 Z\" stroke=\"white\" stroke-width=\"1\" />\n<path d=\"M";
|
||||
displaypicture+=String(parseFloat(temperature)*factor+5);
|
||||
displaypicture+=" 30 L";
|
||||
displaypicture+=String(parseFloat(temperature)*factor+15);
|
||||
displaypicture+=" 30 L";
|
||||
displaypicture+=String(parseFloat(temperature)*factor+10);
|
||||
displaypicture+=" 22 Z\" stroke=\"white\" stroke-width=\"1\"/>\n<text x=\"30\" y=\"19\" fill=\"black\" style=\"font-family: calibri; font-size:10pt;\">\n";
|
||||
displaypicture+=description;
|
||||
displaypicture+=" °C</text>\n";
|
||||
displaypicture+=" </svg>\n";
|
||||
document.getElementById(item).innerHTML=displaypicture;
|
||||
}
|
||||
function displaystatus(status){
|
||||
var content ="<svg width=\"20\" height=\"20\"><circle cx=\"10\" cy=\"10\" r=\"8\" stroke=\"black\" stroke-width=\"2\" fill=\"";
|
||||
if (status=="Connected"){
|
||||
if (pulse)content +="#00FF00";
|
||||
else content +="#007F0E";}
|
||||
else if (status=="Busy"){
|
||||
if (pulse)content +="#FFD800";
|
||||
else content +="#7F6A00";}
|
||||
else{
|
||||
if (pulse)content +="#FF0000";
|
||||
else content +="#7F0000";}
|
||||
content +="\"></circle></svg>";
|
||||
pulse=!pulse;
|
||||
document.getElementById("status").innerHTML=content;
|
||||
document.getElementById("status-text").innerHTML=status;
|
||||
}
|
||||
|
||||
function dispatchstatus(jsonresponse){
|
||||
var temp=0;
|
||||
if(jsonresponse.heater[0].active==1){
|
||||
document.getElementById("Extruder1").style.visibility="visible";
|
||||
document.getElementById("Extruder1").style.height="auto";
|
||||
document.getElementById("JogExtruder1-1").style.visibility="visible";
|
||||
document.getElementById("JogExtruder1-2").style.visibility="visible";
|
||||
document.getElementById("JogExtruder1-3").style.visibility="visible";
|
||||
displaytemp(jsonresponse.heater[0].temperature, jsonresponse.heater[0].target,"data_extruder1",1.03);
|
||||
Updaterange('1');}
|
||||
else {
|
||||
document.getElementById("Extruder1").style.visibility="hidden";
|
||||
document.getElementById("Extruder1").style.height="0px";
|
||||
document.getElementById("JogExtruder1-1").style.visibility="hidden";
|
||||
document.getElementById("JogExtruder1-2").style.visibility="hidden";
|
||||
document.getElementById("JogExtruder1-3").style.visibility="hidden";}
|
||||
if(jsonresponse.heater[1].active==1){
|
||||
document.getElementById("Extruder2").style.visibility="visible";
|
||||
document.getElementById("Extruder2").style.height="auto";
|
||||
document.getElementById("JogExtruder2-1").style.visibility="visible";
|
||||
document.getElementById("JogExtruder2-2").style.visibility="visible";
|
||||
document.getElementById("JogExtruder2-3").style.visibility="visible";
|
||||
displaytemp(jsonresponse.heater[1].temperature, jsonresponse.heater[1].target,"data_extruder2",1.03);
|
||||
Updaterange('2');}
|
||||
else {
|
||||
document.getElementById("Extruder2").style.visibility="hidden";
|
||||
document.getElementById("Extruder2").style.height="0px";
|
||||
document.getElementById("JogExtruder2-1").style.visibility="hidden";
|
||||
document.getElementById("JogExtruder2-2").style.visibility="hidden";
|
||||
document.getElementById("JogExtruder2-3").style.visibility="hidden";}
|
||||
if(jsonresponse.heater[2].active==1){
|
||||
document.getElementById("Bed").style.visibility="visible";
|
||||
document.getElementById("Bed").style.height="auto";
|
||||
displaytemp(jsonresponse.heater[2].temperature, jsonresponse.heater[2].target,"data_bed",2.15);
|
||||
Updaterange('bed');}
|
||||
else {
|
||||
document.getElementById("Bed").style.visibility="hidden";
|
||||
document.getElementById("Bed").style.height="0px";}
|
||||
document.getElementById("posx").innerHTML=jsonresponse.Xpos;
|
||||
document.getElementById("posy").innerHTML=jsonresponse.Ypos;
|
||||
document.getElementById("posz").innerHTML=jsonresponse.Zpos;
|
||||
displaystatus(jsonresponse.status);
|
||||
var content="";
|
||||
for (i = 0; i < jsonresponse.InformationMsg.length; i++) {
|
||||
if (i==jsonresponse.InformationMsg.length-1)content +="<li style='list-style-type: disc;'><b>" +jsonresponse.InformationMsg[i].line+ "</b>";
|
||||
else content +="<li style='list-style-type: circle;'>"+jsonresponse.InformationMsg[i].line;
|
||||
content += "</li>";}
|
||||
document.getElementById("infomsg").innerHTML=content;
|
||||
content="";
|
||||
for (i = 0; i < jsonresponse.ErrorMsg.length; i++){
|
||||
if (i==jsonresponse.ErrorMsg.length-1)content +="<li style='list-style-type: disc;'><b>" +jsonresponse.ErrorMsg[i].line+ "</b>";
|
||||
else content +="<li style='list-style-type: circle;'>"+jsonresponse.ErrorMsg[i].line;
|
||||
content +="</li>";}
|
||||
document.getElementById("errormsg").innerHTML=content;
|
||||
content="";
|
||||
for (i = 0; i < jsonresponse.StatusMsg.length; i++)
|
||||
{
|
||||
if (i==jsonresponse.StatusMsg.length-1)content +="<li style='list-style-type: disc;'><b>" +jsonresponse.StatusMsg[i].line+ "</b>";
|
||||
else content +="<li style='list-style-type: circle;'>"+jsonresponse.StatusMsg[i].line;
|
||||
content +="</li>";
|
||||
}
|
||||
document.getElementById("statusmsg").innerHTML=content;
|
||||
if (!initialization_done){
|
||||
document.getElementById("numberinputspeed").value=jsonresponse.speed;
|
||||
Updaterange('speed');
|
||||
document.getElementById("numberinputflow").value=jsonresponse.flow;
|
||||
Updaterange('flow');
|
||||
if(jsonresponse.heater[0].active==1){
|
||||
if (jsonresponse.heater[0].target.length==0)temp=0;
|
||||
else temp = parseInt(jsonresponse.heater[0].target);
|
||||
document.getElementById("numberinput1").value= temp;
|
||||
Updaterange('1');}
|
||||
if(jsonresponse.heater[1].active==1){
|
||||
if (jsonresponse.heater[1].target.length==0)temp=0;
|
||||
else temp = parseInt(jsonresponse.heater[1].target);
|
||||
document.getElementById("numberinput2").value=temp;
|
||||
Updaterange('2');}
|
||||
if(jsonresponse.heater[2].active==1){
|
||||
if (jsonresponse.heater[2].target.length==0)temp=0;
|
||||
else temp = parseInt(jsonresponse.heater[2].target);
|
||||
document.getElementById("numberinputbed").value=temp;
|
||||
Updaterange('bed');}
|
||||
initialization_done=true;}
|
||||
document.getElementById("currentspeed").innerHTML=jsonresponse.speed + "%";
|
||||
document.getElementById("currentflow").innerHTML=jsonresponse.flow + "%";
|
||||
}
|
||||
var canrefresh = true;
|
||||
function getstatus(){
|
||||
if (canrefresh){
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
var url = "http://$WEB_ADDRESS$/STATUS";
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||
var jsonresponse = JSON.parse(xmlhttp.responseText);
|
||||
dispatchstatus(jsonresponse);}
|
||||
}
|
||||
xmlhttp.open("GET", url, true);
|
||||
xmlhttp.send();
|
||||
}
|
||||
}
|
||||
|
||||
var currentpath = "/";
|
||||
function navbar(){
|
||||
var content="<table><tr>";
|
||||
var tlist = currentpath.split("/");
|
||||
var path="/";
|
||||
var nb = 1;
|
||||
content+="<td class='btnimg' onclick=\"currentpath='/'; refreshSDfiles();\">/</td>";
|
||||
while (nb < (tlist.length-1))
|
||||
{
|
||||
path+=tlist[nb] + "/";
|
||||
content+="<td class='btnimg' onclick=\"currentpath='"+path+"'; SendFileCommand('list','all');\">"+tlist[nb] +"</td><td>/</td>";
|
||||
nb++;
|
||||
}
|
||||
content+="</tr></table>";
|
||||
return content;
|
||||
}
|
||||
|
||||
function print_icon(){
|
||||
var content ="<svg width='24' height='24' viewBox='-10 -10 138 138'>";
|
||||
content +="<rect x='20' y='0' rx='10' ry='10' width='88' height='127' style='fill:black;' />";
|
||||
content +="<rect x='0' y='40' rx='10' ry='10' width='127' height='58' style='fill:black;' />";
|
||||
content +="<rect x='29' y='9' rx='10' ry='10' width='70' height='109' style='fill:white;' />";
|
||||
content +="<rect x='29' y='40' width='88' height='32' style='fill:black;' />";
|
||||
content +="<line x1='20' y1='72' x2='20' y2='98' style='stroke:white;stroke-width:1' />";
|
||||
content +="<line x1='108' y1='72' x2='108' y2='98' style='stroke:white;stroke-width:1' />";
|
||||
content +="<circle cx='105' cy='56' r='7' fill='white' />";
|
||||
content +="<rect x='38' y='82' width='51' height='10' style='fill:black;' />";
|
||||
content +="<rect x='38' y='98' width='32' height='10' style='fill:black;' />";
|
||||
content +="</svg>";
|
||||
return content;
|
||||
}
|
||||
|
||||
function trash_icon(){
|
||||
var content ="<svg width='24' height='24' viewBox='0 0 128 128'>";
|
||||
content +="<rect x='52' y='12' rx='6' ry='6' width='25' height='7' style='fill:red;' />";
|
||||
content +="<rect x='52' y='16' width='25' height='2' style='fill:white;' />";
|
||||
content +="<rect x='30' y='18' rx='6' ry='6' width='67' height='100' style='fill:red;' />";
|
||||
content +="<rect x='20' y='18' rx='10' ry='10' width='87' height='14' style='fill:red;' />";
|
||||
content +="<rect x='20' y='29' width='87' height='3' style='fill:white;' />";
|
||||
content +="<rect x='40' y='43' rx='7' ry='7' width='7' height='63' style='fill:white;' />";
|
||||
content +="<rect x='60' y='43' rx='7' ry='7' width='7' height='63' style='fill:white;' />";
|
||||
content +="<rect x='80' y='43' rx='7' ry='7' width='7' height='63' style='fill:white;' /></svg>";
|
||||
return content;
|
||||
}
|
||||
function back_icon(){
|
||||
var content ="<svg width='24' height='24' viewBox='0 0 24 24'><path d='M7,3 L2,8 L7,13 L7,10 L17,10 L18,11 L18,15 L17,16 L10,16 L9,17 L9,19 L10,20 L20,20 L22,18 L22,8 L20,6 L7,6 z' stroke='black' fill='white' /></svg>";
|
||||
return content;
|
||||
}
|
||||
function select_dir(directoryname){
|
||||
currentpath+=directoryname + "/";
|
||||
SendFileCommand('list','all');
|
||||
}
|
||||
|
||||
function compareStrings(a, b) {
|
||||
// case-insensitive comparison
|
||||
a = a.toLowerCase();
|
||||
b = b.toLowerCase();
|
||||
return (a < b) ? -1 : (a > b) ? 1 : 0;
|
||||
}
|
||||
|
||||
var retry = 0;
|
||||
var serialsdmode = true;
|
||||
|
||||
function refreshSDfiles(){
|
||||
document.getElementById("SDLIST").innerHTML="";
|
||||
if (serialsdmode){
|
||||
Sendcommand("M20");
|
||||
delay(1000);
|
||||
}
|
||||
retry = 0;
|
||||
SendFileCommand("list","all");
|
||||
}
|
||||
|
||||
function dispatchfilestatus(jsonresponse)
|
||||
{
|
||||
var content ="";
|
||||
|
||||
if (!jsonresponse.status) {
|
||||
document.getElementById('filestatus').innerHTML=" Status: Error!";
|
||||
return;
|
||||
}
|
||||
if (jsonresponse.status == "processing"){
|
||||
document.getElementById('filestatus').innerHTML=" Status: Processing";
|
||||
delay(1000);
|
||||
retry = retry +1;
|
||||
if (retry < 6) SendFileCommand("list","all");
|
||||
else document.getElementById('filestatus').innerHTML=" Status: No answer";
|
||||
return;
|
||||
}
|
||||
if (jsonresponse.mode){
|
||||
if (jsonresponse.mode == "direct") {
|
||||
serialsdmode=false;
|
||||
document.getElementById('iconcreatedir').style.display='block';
|
||||
}
|
||||
}
|
||||
content =" Status: "+jsonresponse.status;
|
||||
retry = 0;
|
||||
if (jsonresponse.files){
|
||||
if (jsonresponse.total && !serialsdmode){
|
||||
content +=" | Total space: "+jsonresponse.total;
|
||||
content +=" | Used space: "+jsonresponse.used;
|
||||
content +=" | Occupation: ";
|
||||
content +="<meter min='0' max='100' high='90' value='"+jsonresponse.occupation +"'></meter> "+jsonresponse.occupation +"%";
|
||||
}
|
||||
}
|
||||
document.getElementById('filestatus').innerHTML=content;
|
||||
content ="";
|
||||
if (serialsdmode)currentpath="/";
|
||||
if (currentpath!="/")
|
||||
{
|
||||
var pos = currentpath.lastIndexOf("/",currentpath.length-2)
|
||||
var previouspath = currentpath.slice(0,pos+1);
|
||||
content +="<tr style='cursor:hand;' onclick=\"currentpath='"+previouspath+"'; SendFileCommand('list','all');\"><td >"+back_icon()+"</td><td colspan='4'> Up..</td></tr>";
|
||||
}
|
||||
if (jsonresponse.files){
|
||||
jsonresponse.files.sort(function(a, b) {
|
||||
return compareStrings(a.name, b.name);
|
||||
});
|
||||
var linenumber=1;
|
||||
for (var i=0;i <jsonresponse.files.length;i++){
|
||||
//first display files
|
||||
if (String(jsonresponse.files[i].size) != "-1")
|
||||
{
|
||||
content +="<TR>";
|
||||
content +="<td id='line"+linenumber+"'><svg height='24' width='24' viewBox='0 0 24 24' > <path d='M1,2 L1,21 L2,22 L16,22 L17,21 L17,6 L12,6 L12,1 L2,1 z' stroke='black' fill='white' /><line x1='12' y1='1' x2='17' y2='6' stroke='black' stroke-width='1'/>";
|
||||
content +="<line x1='5' y1='10' x2='13' y2='10' stroke='black' stroke-width='1'/> <line x1='5' y1='14' x2='13' y2='14' stroke='black' stroke-width='1'/> <line x1='5' y1='18' x2='13' y2='18' stroke='black' stroke-width='1'/></svg></td>";
|
||||
if (serialsdmode) content +="<TD>";
|
||||
else content +="<TD class='btnimg' style=\"padding:0px;\"><a href=\"/SD"+jsonresponse.path+jsonresponse.files[i].name+"\" target=_blank><div class=\"blacklink\">";
|
||||
content +=jsonresponse.files[i].name;
|
||||
if (serialsdmode) content +="</TD>";
|
||||
else content +="</div></a></TD>";
|
||||
content +="<TD>";
|
||||
content +=jsonresponse.files[i].size;
|
||||
content +="</TD><TD width='0%'><div class=\"btnimg\" onclick=\"Delete('"+jsonresponse.files[i].name+"','line"+linenumber+"')\">";
|
||||
content +=trash_icon();
|
||||
content +="</div></TD><td><div class=\"btnimg\" onclick=\"if(confirm('Print "+jsonresponse.files[i].name+"?'))printfile('"+jsonresponse.files[i].name+"')\">";
|
||||
content +=print_icon();
|
||||
content +="</div></td><td></td></TR>";
|
||||
linenumber++;
|
||||
}
|
||||
}
|
||||
//then display directories
|
||||
for (var i=0;i <jsonresponse.files.length;i++){
|
||||
if (String(jsonresponse.files[i].size) == "-1")
|
||||
{
|
||||
content +="<TR>";
|
||||
content+="<td id='line"+linenumber+"'><svg height='24' width='24' viewBox='0 0 24 24' ><path d='M19,11 L19,8 L18,7 L8,7 L8,5 L7,4 L2,4 L1,5 L1,22 L19,22 L20,21 L23,11 L5,11 L2,21 L1,22' stroke='black' fill='white' /></svg></td>";
|
||||
if (serialsdmode) content +="<TD>";
|
||||
else content +="<TD class='btnimg blacklink' style='padding:10px 15px;' onclick=\"select_dir('" + jsonresponse.files[i].name+"');\">";
|
||||
content +=jsonresponse.files[i].name;
|
||||
content +="</TD><TD></TD>";
|
||||
if (serialsdmode) content +="<TD></TD>";
|
||||
else {
|
||||
content +="<TD width='0%'><div class=\"btnimg\" onclick=\"Deletedir('"+jsonresponse.files[i].name+"','line"+linenumber+"')\">";
|
||||
content +=trash_icon();
|
||||
content +="</div></TD>";
|
||||
}
|
||||
content +="<td></td><td></td></TR>";
|
||||
linenumber++;
|
||||
}
|
||||
}
|
||||
}
|
||||
document.getElementById('file_list').innerHTML=content;
|
||||
document.getElementById('path').innerHTML=navbar();}
|
||||
|
||||
function Delete(filename,icon){
|
||||
if (confirm("Confirm deletion of file: " + filename)) {
|
||||
document.getElementById(icon).innerHTML = "<div id=\"loader\" class=\"loader\"></div>";
|
||||
if (serialsdmode)
|
||||
{
|
||||
Sendcommand("M30 " + filename);
|
||||
refreshSDfiles();
|
||||
}
|
||||
else{
|
||||
SendFileCommand("delete",filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
function Deletedir(filename,icon){
|
||||
if (confirm("Confirm deletion of directory: " + filename)){
|
||||
document.getElementById(icon).innerHTML = "<div id=\"loader\" class=\"loader\"></div>";
|
||||
SendFileCommand("deletedir",filename);
|
||||
}
|
||||
}
|
||||
function Createdir(){
|
||||
var filename = prompt("Please enter directory name", "");
|
||||
if (filename != null) {
|
||||
SendFileCommand("createdir",filename.trim());
|
||||
}
|
||||
}
|
||||
function SendFileCommand(action,filename){
|
||||
canrefresh = false;
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
var url = "/SDFILES?action="+action;
|
||||
url += "&filename="+encodeURI(filename);
|
||||
url += "&path="+encodeURI(currentpath);
|
||||
document.getElementById('loader').style.visibility="visible";
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||
var jsonresponse = JSON.parse(xmlhttp.responseText);
|
||||
dispatchfilestatus(jsonresponse);document.getElementById('loader').style.visibility="hidden";
|
||||
canrefresh = true;}
|
||||
}
|
||||
xmlhttp.open("GET", url, true);
|
||||
xmlhttp.send();
|
||||
}
|
||||
|
||||
function Sendfile(){
|
||||
var files = document.getElementById('file-select').files;
|
||||
if (files.length==0)return;
|
||||
canrefresh = false;
|
||||
document.getElementById('upload-button').value = "Uploading...";
|
||||
document.getElementById('prg').style.visibility = "visible";
|
||||
var formData = new FormData();
|
||||
formData.append('path', currentpath);
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var file = files[i];
|
||||
formData.append('myfiles[]', file, currentpath+file.name);}
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open('POST', '/SDFILES', true);
|
||||
//progress upload event
|
||||
xmlhttp.upload.addEventListener("progress", updateProgress, false);
|
||||
//progress function
|
||||
function updateProgress (oEvent) {
|
||||
if (oEvent.lengthComputable) {
|
||||
var percentComplete = (oEvent.loaded / oEvent.total)*100;
|
||||
document.getElementById('prg').value=percentComplete;
|
||||
document.getElementById('upload-button').value = "Uploading ..." + percentComplete.toFixed(0)+"%" ;
|
||||
} else {
|
||||
// Impossible because size is unknown
|
||||
}
|
||||
}
|
||||
xmlhttp.onload = function () {
|
||||
if (xmlhttp.status === 200) {
|
||||
document.getElementById('upload-button').value = 'Upload';
|
||||
document.getElementById('prg').style.visibility = "hidden";
|
||||
document.getElementById('file-select').value="";
|
||||
var jsonresponse = JSON.parse(xmlhttp.responseText);
|
||||
dispatchfilestatus(jsonresponse);
|
||||
canrefresh = true;
|
||||
refreshSDfiles();
|
||||
} else alert('An error occurred!');
|
||||
}
|
||||
xmlhttp.send(formData);
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
refreshSDfiles();
|
||||
if ($REFRESH_PAGE$){
|
||||
setInterval(function(){getstatus();},$REFRESH_PAGE$);
|
||||
document.getElementById('manualstatus').style.display = "none";
|
||||
}
|
||||
else {
|
||||
document.getElementById('autostatus').style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
function printfile(filename){
|
||||
if (filename.length>0){
|
||||
Sendcommand("M23 " + currentpath + filename);
|
||||
delay(100);
|
||||
Sendcommand("M24");}
|
||||
}
|
||||
</script>
|
||||
$INCLUDE[footer.inc]$
|
@ -1,27 +0,0 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<title>Restarting...</title>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<CENTER>Restarting, please wait....
|
||||
<BR>
|
||||
<PROGRESS name='prg' id='prg'></PROGRESS>
|
||||
</CENTER>
|
||||
<script>
|
||||
var i = 0;
|
||||
var interval;
|
||||
var x = document.getElementById("prg");
|
||||
x.max=40;
|
||||
interval = setInterval(function(){
|
||||
i=i+1;
|
||||
var x = document.getElementById("prg");
|
||||
x.value=i;
|
||||
if (i>40)
|
||||
{
|
||||
clearInterval(interval);
|
||||
window.location.href='/';
|
||||
}
|
||||
},1000);
|
||||
</script>
|
||||
</BODY>
|
||||
</HTML>
|
@ -1,108 +0,0 @@
|
||||
$INCLUDE[header.inc]$
|
||||
$INCLUDE[css2.inc]$
|
||||
<div id='system' class="panel">
|
||||
<div class="panel-heading">System</div>
|
||||
<div class="panel-body">
|
||||
<form method="POST">
|
||||
<div class="form-group $BAUD_RATE_STATUS$">
|
||||
<label class="control-label" for="CONFIG1" >Baud rate</label><br>
|
||||
<select name="BAUD_RATE" id="CONFIG1" class="form-control">
|
||||
$BAUD_RATE_OPTIONS_LIST$
|
||||
</select></div>
|
||||
<div class="form-group $SLEEP_MODE_STATUS$">
|
||||
<label class="control-label" for="CONFIG2">Sleep Mode</label><br>
|
||||
<select name="SLEEP_MODE" id="CONFIG2" class="form-control">
|
||||
$SLEEP_MODE_OPTIONS_LIST$
|
||||
</select></div>
|
||||
<div class="form-group $WEB_PORT_STATUS$"><label class="control-label" for="CONFIG3">Web port:</label><br>
|
||||
<input type="number" class="form-control" id="CONFIG3" name="WEBPORT" min="1" max="65000" step="1" placeholder="1~65000" value="$WEB_PORT$" style="width: auto;"></div>
|
||||
<div id='dataport' class="form-group $DATA_PORT_STATUS$" style="$DATA_PORT_VISIBILITY$"><label class="control-label" for="CONFIG4">Data port:</label><br>
|
||||
<input type="number" class="form-control" id="CONFIG4" name="DATAPORT" min="1" max="65000" step="1" placeholder="1~65000" value="$DATA_PORT$" style="width: auto;"></div>
|
||||
<div class="alert alert-danger" role="alert" style="$ERROR_MSG_VISIBILITY$" >
|
||||
$ERROR_MSG$
|
||||
</div>
|
||||
<hr><input id='btnsubmit' style="$SUBMIT_BUTTON_VISIBILITY$" type="submit" class="btn btn-primary" name="SUBMIT" value="Apply">
|
||||
</form>
|
||||
<div class="alert alert-success" role="alert" style="$SUCCESS_MSG_VISIBILITY$" >
|
||||
$SUCCESS_MSG$
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel" style="$WEB_UPDATE_VISIBILITY$">
|
||||
<div class="panel-heading">Firmware Update</div>
|
||||
<div class="panel-body">
|
||||
<table><tr>
|
||||
<td><input type="file" id="file-select" name="myfiles[]" /></td>
|
||||
<td><input class="btn btn-primary" type="button" id="upload-button" onclick="Sendfile();" value="Update"/></td>
|
||||
<td><progress style="visibility:hidden;" name='prg' id='prg' max='100'></progress></td>
|
||||
<td><div id='msg' style='visibility:hidden;'>Restarting, please wait....</div></td></tr></table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
function Sendfile(){
|
||||
if (!confirm("Confirm Firmware Update ?"))return;
|
||||
var files = document.getElementById('file-select').files;
|
||||
if (files.length==0)return;
|
||||
document.getElementById('upload-button').value = "Uploading...";
|
||||
document.getElementById('prg').style.visibility = "visible";
|
||||
var formData = new FormData();
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var file = files[i];
|
||||
formData.append('myfiles[]', file, "/"+file.name);}
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open('POST', '/UPDATE', true);
|
||||
//progress upload event
|
||||
xmlhttp.upload.addEventListener("progress", updateProgress, false);
|
||||
//progress function
|
||||
function updateProgress (oEvent) {
|
||||
if (oEvent.lengthComputable) {
|
||||
var percentComplete = (oEvent.loaded / oEvent.total)*100;
|
||||
document.getElementById('prg').value=percentComplete;
|
||||
document.getElementById('upload-button').value = "Uploading ..." + percentComplete.toFixed(0)+"%" ;
|
||||
} else {
|
||||
// Impossible because size is unknown
|
||||
}
|
||||
}
|
||||
xmlhttp.onload = function () {
|
||||
if (xmlhttp.status === 200) {
|
||||
document.getElementById('upload-button').value = 'Upload';
|
||||
document.getElementById('upload-button').style.visibility = 'hidden';
|
||||
document.getElementById('upload-button').style.width = '0px';
|
||||
document.getElementById('system').style.visibility = 'hidden';
|
||||
document.getElementById('system').style.height = '0px';
|
||||
document.getElementById('dataport').style.visibility = 'hidden';
|
||||
document.getElementById('dataport').style.height = '0px';
|
||||
document.getElementById('msg').style.visibility = "visible";
|
||||
document.getElementById('file-select').value="";
|
||||
document.getElementById('file-select').style.visibility = 'hidden';
|
||||
document.getElementById('file-select').style.width = '0px';
|
||||
document.getElementById('btnsubmit').style.visibility = 'hidden';
|
||||
|
||||
var jsonresponse = JSON.parse(xmlhttp.responseText);
|
||||
if (jsonresponse.status=='1' || jsonresponse.status=='4' || jsonresponse.status=='1')alert("Update failed");
|
||||
if (jsonresponse.status=='2')alert('Update canceled!');
|
||||
else if (jsonresponse.status=='3')
|
||||
{
|
||||
var i = 0;
|
||||
var interval;
|
||||
var x = document.getElementById("prg");
|
||||
x.max=40;
|
||||
interval = setInterval(function(){
|
||||
i=i+1;
|
||||
var x = document.getElementById("prg");
|
||||
x.value=i;
|
||||
if (i>40)
|
||||
{
|
||||
clearInterval(interval);
|
||||
location.reload();
|
||||
}
|
||||
},1000);
|
||||
}
|
||||
else alert('Update failed!');
|
||||
} else alert('An error occurred!');
|
||||
}
|
||||
xmlhttp.send(formData);
|
||||
}
|
||||
</script>
|
||||
$INCLUDE[footer.inc]$
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"WEB_ADDRESS":"localhost",
|
||||
"PAGE_TITLE":"Testing things..."
|
||||
}
|
172
esp3d/esp3d.ino
172
esp3d/esp3d.ino
@ -23,71 +23,87 @@
|
||||
Main author: luc lebosse
|
||||
|
||||
*/
|
||||
//be sure correct IDE and settings are used for ESP8266
|
||||
#ifndef ARDUINO_ARCH_ESP8266
|
||||
#error Oops! Make sure you have 'ESP8266' compatible board selected from the 'Tools -> Boards' menu.
|
||||
//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 "wifi.h"
|
||||
#include "wificonf.h"
|
||||
#include "bridge.h"
|
||||
#include "webinterface.h"
|
||||
#include "command.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServer.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>
|
||||
const byte DNS_PORT = 53;
|
||||
DNSServer dnsServer;
|
||||
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;
|
||||
long baud_rate=0;
|
||||
bool directsd_check = false;
|
||||
web_interface = NULL;
|
||||
#ifdef TCP_IP_DATA_FEATURE
|
||||
data_server = NULL;
|
||||
#endif
|
||||
// init:
|
||||
#ifdef DEBUG_ESP3D
|
||||
Serial.begin(DEFAULT_BAUD_RATE);
|
||||
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
|
||||
pinMode(RESET_CONFIG_PIN, INPUT);
|
||||
if (digitalRead(RESET_CONFIG_PIN)==0) {
|
||||
breset_config=true; //if requested =>reset settings
|
||||
}
|
||||
#endif
|
||||
//check if EEPROM has value
|
||||
if ( CONFIG::read_buffer(EP_BAUD_RATE, (byte *)&baud_rate , INTEGER_LENGTH)&&CONFIG::read_buffer(EP_WEB_PORT, (byte *)&(wifi_config.iweb_port) , INTEGER_LENGTH)&&CONFIG::read_buffer(EP_DATA_PORT, (byte *)&(wifi_config.idata_port) , INTEGER_LENGTH)) {
|
||||
//check if baud value is one of allowed ones
|
||||
if ( ! (baud_rate==9600 || baud_rate==19200 ||baud_rate==38400 ||baud_rate==57600 ||baud_rate==115200 ||baud_rate==230400 ||baud_rate==250000) ) {
|
||||
LOG("Error for EEPROM baud rate\r\n")
|
||||
breset_config=true; //baud rate is incorrect =>reset settings
|
||||
}
|
||||
if (wifi_config.iweb_port<1 ||wifi_config.iweb_port>65001 || wifi_config.idata_port <1 || wifi_config.idata_port >65001) {
|
||||
breset_config=true; //out of range =>reset settings
|
||||
LOG("Error for EEPROM port values\r\n")
|
||||
}
|
||||
|
||||
} else {
|
||||
if ( !CONFIG::InitBaudrate() || !CONFIG::InitExternalPorts()) {
|
||||
breset_config=true; //cannot access to config settings=> reset settings
|
||||
LOG("Error no EEPROM access\r\n")
|
||||
}
|
||||
@ -95,114 +111,78 @@ void setup()
|
||||
//reset is requested
|
||||
if(breset_config) {
|
||||
//update EEPROM with default settings
|
||||
Serial.begin(DEFAULT_BAUD_RATE);
|
||||
Serial.setRxBufferSize(SERIAL_RX_BUFFER_SIZE);
|
||||
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);
|
||||
Serial.println(F("M117 ESP EEPROM reset"));
|
||||
ESP_SERIAL_OUT.println(F("M117 ESP EEPROM reset"));
|
||||
#ifdef DEBUG_ESP3D
|
||||
CONFIG::print_config(DEBUG_PIPE);
|
||||
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);
|
||||
Serial.flush();
|
||||
ESP_SERIAL_OUT.flush();
|
||||
#endif
|
||||
//setup serial
|
||||
Serial.begin(baud_rate);
|
||||
Serial.setRxBufferSize(SERIAL_RX_BUFFER_SIZE);
|
||||
delay(1000);
|
||||
LOG("Serial Set\r\n");
|
||||
wifi_config.baud_rate=baud_rate;
|
||||
//get target FW
|
||||
CONFIG::InitFirmwareTarget();
|
||||
//Update is done if any so should be Ok
|
||||
SPIFFS.begin();
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
SPIFFS.begin(true);
|
||||
#else
|
||||
SPIFFS.begin();
|
||||
#endif
|
||||
|
||||
//setup wifi according settings
|
||||
if (!wifi_config.Setup()) {
|
||||
Serial.println(F("M117 Safe mode 1"));
|
||||
ESP_SERIAL_OUT.println(F("M117 Safe mode 1"));
|
||||
//try again in AP mode
|
||||
if (!wifi_config.Setup(true)) {
|
||||
Serial.println(F("M117 Safe mode 2"));
|
||||
if (!wifi_config.Setup(true)) {
|
||||
ESP_SERIAL_OUT.println(F("M117 Safe mode 2"));
|
||||
wifi_config.Safe_Setup();
|
||||
}
|
||||
}
|
||||
delay(1000);
|
||||
//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->WebServer.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.start(DNS_PORT, "*", WiFi.softAPIP());
|
||||
//setup servers
|
||||
if (!wifi_config.Enable_servers()) {
|
||||
ESP_SERIAL_OUT.println(F("M117 Error enabling servers"));
|
||||
}
|
||||
#endif
|
||||
web_interface->WebServer.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
|
||||
// Check for any mDNS queries and send responses
|
||||
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");
|
||||
SSDP.begin();
|
||||
#endif
|
||||
#ifdef NETBIOS_FEATURE
|
||||
NBNS.begin(shost.c_str());
|
||||
#endif
|
||||
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();
|
||||
}
|
||||
if (WiFi.getMode()!=WIFI_STA ) {
|
||||
dnsServer.processNextRequest();
|
||||
}
|
||||
#endif
|
||||
//web requests
|
||||
web_interface->WebServer.handleClient();
|
||||
web_interface->web_server.handleClient();
|
||||
#ifdef TCP_IP_DATA_FEATURE
|
||||
BRIDGE::processFromTCP2Serial();
|
||||
BRIDGE::processFromTCP2Serial();
|
||||
#endif
|
||||
BRIDGE::processFromSerial2TCP();
|
||||
}
|
||||
BRIDGE::processFromSerial2TCP();
|
||||
//in case of restart requested
|
||||
if (web_interface->restartmodule) {
|
||||
CONFIG::esp_restart();
|
||||
}
|
||||
|
Binary file not shown.
326
esp3d/nofile.h
Normal file
326
esp3d/nofile.h
Normal file
@ -0,0 +1,326 @@
|
||||
/*
|
||||
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
|
||||
};
|
@ -19,7 +19,7 @@
|
||||
*/
|
||||
#include "storestrings.h"
|
||||
//Constructor
|
||||
STORESTRINGS_CLASS::STORESTRINGS_CLASS (int maxsize , int maxstringlength)
|
||||
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
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#ifndef STORESTRINGS_h
|
||||
#define STORESTRINGS_h
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <Arduino.h>
|
||||
#include "GenLinkedList.h"
|
||||
class STORESTRINGS_CLASS
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,26 +23,25 @@
|
||||
#include <Arduino.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WiFiServer.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#ifdef SDCARD_FEATURE
|
||||
#ifndef FS_NO_GLOBALS
|
||||
#define FS_NO_GLOBALS
|
||||
#endif
|
||||
#endif
|
||||
#include <FS.h>
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
#include <ESP8266WebServer.h>
|
||||
#else
|
||||
#include <WebServer.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "storestrings.h"
|
||||
|
||||
#define MAX_EXTRUDERS 4
|
||||
|
||||
typedef enum {
|
||||
LEVEL_GUEST = 0,
|
||||
LEVEL_USER = 1,
|
||||
LEVEL_ADMIN = 2
|
||||
} level_authenticate_type;
|
||||
|
||||
struct auth_ip {
|
||||
IPAddress ip;
|
||||
level_authenticate_type level;
|
||||
char userID[17];
|
||||
char sessionID[17];
|
||||
uint32_t last_time;
|
||||
auth_ip * _next;
|
||||
@ -53,24 +52,12 @@ class WEBINTERFACE_CLASS
|
||||
public:
|
||||
WEBINTERFACE_CLASS (int port = 80);
|
||||
~WEBINTERFACE_CLASS();
|
||||
ESP8266WebServer WebServer;
|
||||
FSFILE fsUploadFile;
|
||||
#ifdef TEMP_MONITORING_FEATURE
|
||||
String answer4M105;
|
||||
uint32_t last_temp;
|
||||
#endif
|
||||
#ifdef POS_MONITORING_FEATURE
|
||||
String answer4M114;
|
||||
#endif
|
||||
#ifdef SPEED_MONITORING_FEATURE
|
||||
String answer4M220;
|
||||
#endif
|
||||
#ifdef FLOW_MONITORING_FEATURE
|
||||
String answer4M221;
|
||||
#endif
|
||||
#ifndef DIRECT_SDCARD_FEATURE
|
||||
STORESTRINGS_CLASS fileslist;
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
ESP8266WebServer web_server;
|
||||
#else
|
||||
WebServer web_server;
|
||||
#endif
|
||||
FS_FILE fsUploadFile;
|
||||
#ifdef ERROR_MSG_FEATURE
|
||||
STORESTRINGS_CLASS error_msg;
|
||||
#endif
|
||||
@ -81,25 +68,14 @@ public:
|
||||
STORESTRINGS_CLASS status_msg;
|
||||
#endif
|
||||
bool restartmodule;
|
||||
bool generateJSON(STORESTRINGS_CLASS & KeysList , STORESTRINGS_CLASS & ValuesList );
|
||||
bool processTemplate(const char * filename, STORESTRINGS_CLASS & KeysList , STORESTRINGS_CLASS & ValuesList );
|
||||
void GetFreeMem(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList);
|
||||
void GetLogin(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList,level_authenticate_type auth_level, bool ishtmloutput);
|
||||
void GetIpWeb(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList);
|
||||
void GetMode(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList);
|
||||
void GetPorts(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList, bool ishtmloutput);
|
||||
void SetPageProp(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList,
|
||||
const __FlashStringHelper *title, const __FlashStringHelper *filename);
|
||||
void GetDHCPStatus(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList);
|
||||
void ProcessAlertError(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList, String & smsg, bool ishtmloutput);
|
||||
void ProcessAlertSuccess(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList, String & smsg, bool ishtmloutput);
|
||||
void ProcessNoAlert(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList, bool ishtmloutput);
|
||||
String getContentType(String filename);
|
||||
level_authenticate_type is_authenticated();
|
||||
bool AddAuthIP(auth_ip * item);
|
||||
bool blockserial;
|
||||
#ifdef AUTHENTICATION_FEATURE
|
||||
level_authenticate_type ResetAuthIP(IPAddress ip,const char * sessionID);
|
||||
auth_ip * GetAuth(IPAddress ip,const char * sessionID);
|
||||
bool ClearAuthIP(IPAddress ip, const char * sessionID);
|
||||
char * create_session_ID();
|
||||
#endif
|
||||
uint8_t _upload_status;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
wifi.cpp - ESP3D configuration class
|
||||
wificonf.cpp - ESP3D configuration class
|
||||
|
||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||
|
||||
@ -17,21 +17,53 @@
|
||||
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 "wifi.h"
|
||||
#include "config.h"
|
||||
#include "wificonf.h"
|
||||
#include "bridge.h"
|
||||
#include "webinterface.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "IPAddress.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>
|
||||
extern DNSServer dnsServer;
|
||||
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;
|
||||
@ -54,12 +86,18 @@ int32_t WIFI_CONFIG::getSignal(int32_t RSSI)
|
||||
|
||||
const char * WIFI_CONFIG::get_hostname()
|
||||
{
|
||||
if (WiFi.hostname().length()==0) {
|
||||
if (!CONFIG::read_string(EP_HOSTNAME, _hostname , MAX_HOSTNAME_LENGTH)) {
|
||||
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,WiFi.hostname().c_str());
|
||||
strcpy(_hostname,hname.c_str());
|
||||
}
|
||||
return _hostname;
|
||||
}
|
||||
@ -95,7 +133,7 @@ void WIFI_CONFIG::Safe_Setup()
|
||||
delay(500);
|
||||
WiFi.softAPConfig( local_ip, gateway, subnet);
|
||||
delay(1000);
|
||||
Serial.println(F("M117 Safe mode started"));
|
||||
ESP_SERIAL_OUT.println(F("M117 Safe mode started"));
|
||||
}
|
||||
|
||||
//Read configuration settings and apply them
|
||||
@ -114,7 +152,11 @@ bool WIFI_CONFIG::Setup(bool force_ap)
|
||||
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;
|
||||
@ -125,21 +167,21 @@ bool WIFI_CONFIG::Setup(bool force_ap)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!CONFIG::read_string(EP_HOSTNAME, hostname , MAX_HOSTNAME_LENGTH)) {
|
||||
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)) {
|
||||
if(!CONFIG::read_string(EP_AP_SSID, sbuf, MAX_SSID_LENGTH)) {
|
||||
return false;
|
||||
}
|
||||
if(!CONFIG::read_string(EP_AP_PASSWORD, pwd , MAX_PASSWORD_LENGTH)) {
|
||||
if(!CONFIG::read_string(EP_AP_PASSWORD, pwd, MAX_PASSWORD_LENGTH)) {
|
||||
return false;
|
||||
}
|
||||
Serial.print(FPSTR(M117_));
|
||||
Serial.print(F("SSID "));
|
||||
Serial.println(sbuf);
|
||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
||||
ESP_SERIAL_OUT.print(F("SSID "));
|
||||
ESP_SERIAL_OUT.println(sbuf);
|
||||
LOG("SSID ")
|
||||
LOG(sbuf)
|
||||
LOG("\r\n")
|
||||
@ -156,7 +198,7 @@ bool WIFI_CONFIG::Setup(bool force_ap)
|
||||
LOG("Static mode\r\n")
|
||||
//get the IP
|
||||
LOG("IP value:")
|
||||
if (!CONFIG::read_buffer(EP_AP_IP_VALUE,ip_buf , IP_LENGTH)) {
|
||||
if (!CONFIG::read_buffer(EP_AP_IP_VALUE,ip_buf, IP_LENGTH)) {
|
||||
LOG("Error\r\n")
|
||||
return false;
|
||||
}
|
||||
@ -164,7 +206,7 @@ bool WIFI_CONFIG::Setup(bool force_ap)
|
||||
LOG(local_ip.toString())
|
||||
LOG("\r\nGW value:")
|
||||
//get the gateway
|
||||
if (!CONFIG::read_buffer(EP_AP_GATEWAY_VALUE,ip_buf , IP_LENGTH)) {
|
||||
if (!CONFIG::read_buffer(EP_AP_GATEWAY_VALUE,ip_buf, IP_LENGTH)) {
|
||||
LOG("Error\r\n")
|
||||
return false;
|
||||
}
|
||||
@ -172,7 +214,7 @@ bool WIFI_CONFIG::Setup(bool force_ap)
|
||||
LOG(gateway.toString())
|
||||
LOG("\r\nMask value:")
|
||||
//get the mask
|
||||
if (!CONFIG::read_buffer(EP_AP_MASK_VALUE,ip_buf , IP_LENGTH)) {
|
||||
if (!CONFIG::read_buffer(EP_AP_MASK_VALUE,ip_buf, IP_LENGTH)) {
|
||||
LOG("Error Mask value\r\n")
|
||||
return false;
|
||||
}
|
||||
@ -187,57 +229,89 @@ bool WIFI_CONFIG::Setup(bool force_ap)
|
||||
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);
|
||||
LOG("Set phy mode\r\n")
|
||||
//setup PHY_MODE
|
||||
if (!CONFIG::read_byte(EP_AP_PHY_MODE, &bflag )) {
|
||||
return false;
|
||||
}
|
||||
#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)) {
|
||||
Serial.println(F("M117 Error Wifi AP!"));
|
||||
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)) {
|
||||
if(!CONFIG::read_string(EP_STA_SSID, sbuf, MAX_SSID_LENGTH)) {
|
||||
return false;
|
||||
}
|
||||
if(!CONFIG::read_string(EP_STA_PASSWORD, pwd , MAX_PASSWORD_LENGTH)) {
|
||||
if(!CONFIG::read_string(EP_STA_PASSWORD, pwd, MAX_PASSWORD_LENGTH)) {
|
||||
return false;
|
||||
}
|
||||
Serial.print(FPSTR(M117_));
|
||||
Serial.print(F("SSID "));
|
||||
Serial.println(sbuf);
|
||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
||||
ESP_SERIAL_OUT.print(F("SSID "));
|
||||
ESP_SERIAL_OUT.println(sbuf);
|
||||
LOG("SSID ")
|
||||
LOG(sbuf)
|
||||
LOG("\r\n")
|
||||
@ -247,17 +321,17 @@ bool WIFI_CONFIG::Setup(bool force_ap)
|
||||
if (bflag==STATIC_IP_MODE) {
|
||||
byte ip_buf[4];
|
||||
//get the IP
|
||||
if (!CONFIG::read_buffer(EP_STA_IP_VALUE,ip_buf , IP_LENGTH)) {
|
||||
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)) {
|
||||
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)) {
|
||||
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]);
|
||||
@ -266,62 +340,167 @@ bool WIFI_CONFIG::Setup(bool force_ap)
|
||||
}
|
||||
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);
|
||||
WiFi.begin(sbuf, pwd);
|
||||
delay(100);
|
||||
//setup PHY_MODE
|
||||
if (!CONFIG::read_byte(EP_STA_PHY_MODE, &bflag )) {
|
||||
return false;
|
||||
}
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
WiFi.setPhyMode((WiFiPhyMode_t)bflag);
|
||||
#endif
|
||||
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:
|
||||
Serial.print(FPSTR(M117_));
|
||||
Serial.println(F("No SSID found!"));
|
||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
||||
ESP_SERIAL_OUT.println(F("No SSID found!"));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
Serial.print(FPSTR(M117_));
|
||||
Serial.println(F("No Connection!"));
|
||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
||||
ESP_SERIAL_OUT.println(F("No Connection!"));
|
||||
break;
|
||||
|
||||
default:
|
||||
Serial.print(FPSTR(M117_));
|
||||
Serial.println(F("Connecting..."));
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#ifdef MDNS_FEATURE
|
||||
// Set up mDNS responder:
|
||||
if (!mdns.begin(hostname)) {
|
||||
Serial.print(FPSTR(M117_));
|
||||
Serial.println(F("Error with mDNS!"));
|
||||
delay(1000);
|
||||
}
|
||||
#else
|
||||
WiFi.setHostname(hostname);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Get IP
|
||||
if (WiFi.getMode()==WIFI_STA) {
|
||||
currentIP=WiFi.localIP();
|
||||
} else {
|
||||
currentIP=WiFi.softAPIP();
|
||||
}
|
||||
Serial.print(FPSTR(M117_));
|
||||
Serial.println(currentIP);
|
||||
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,5 +1,5 @@
|
||||
/*
|
||||
wifi.h - ESP3D configuration class
|
||||
wificonf.h - ESP3D configuration class
|
||||
|
||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||
|
||||
@ -18,16 +18,22 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef WIFI_h
|
||||
#define WIFI_h
|
||||
#ifndef WIFICONF_H
|
||||
#define WIFICONF_H
|
||||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
#include "IPAddress.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
#include "ESP8266WiFi.h"
|
||||
#ifdef MDNS_FEATURE
|
||||
#include <ESP8266mDNS.h>
|
||||
#endif
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#ifdef MDNS_FEATURE
|
||||
#include <ESPmDNS.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class WIFI_CONFIG
|
||||
{
|
||||
@ -44,6 +50,8 @@ public:
|
||||
int32_t getSignal(int32_t RSSI);
|
||||
bool Setup(bool force_ap = false);
|
||||
void Safe_Setup();
|
||||
bool Enable_servers();
|
||||
bool Disable_servers();
|
||||
const char * get_default_hostname();
|
||||
const char * get_hostname();
|
||||
private:
|
BIN
images/docs/embedded.png
Normal file
BIN
images/docs/embedded.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
32
libraries/DNSServer/.gitignore
vendored
Normal file
32
libraries/DNSServer/.gitignore
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
83
libraries/DNSServer/.travis.yml
Normal file
83
libraries/DNSServer/.travis.yml
Normal file
@ -0,0 +1,83 @@
|
||||
sudo: false
|
||||
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
||||
env:
|
||||
- TESTCASE="1.8.3|esp8266|stable|esp8266:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M"
|
||||
- TESTCASE="1.8.3|esp8266|devel|esp8266com:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M"
|
||||
- TESTCASE="1.8.3|esp32|devel|espressif:esp32:esp32:FlashFreq=40"
|
||||
|
||||
script:
|
||||
- echo -e "travis_fold:start:sketch_test_env_prepare"
|
||||
- pip install pyserial
|
||||
- IFS='|' read -r -a array <<< "${TESTCASE}"
|
||||
- |
|
||||
for index in "${!array[@]}"
|
||||
do
|
||||
case $index in
|
||||
0) IDEVER="${array[index]}" ;;
|
||||
1) PLATFORM="${array[index]}" ;;
|
||||
2) RELEASE="${array[index]}" ;;
|
||||
3) BOARD="${array[index]}" ;;
|
||||
esac
|
||||
done
|
||||
- cd $HOME
|
||||
- wget -O arduino.tar.xz https://downloads.arduino.cc/arduino-${IDEVER}-linux64.tar.xz
|
||||
- tar xf arduino.tar.xz
|
||||
- mv arduino-${IDEVER} $HOME/arduino_ide
|
||||
- mkdir -p $HOME/Arduino/libraries
|
||||
- IDEDIR="${HOME}/arduino_ide"
|
||||
- export PATH="$IDEDIR:$PATH"
|
||||
- cd ${IDEDIR}
|
||||
- which arduino
|
||||
- |
|
||||
if [[ $PLATFORM == "esp8266" ]] && [[ $RELEASE == "stable" ]]
|
||||
then
|
||||
arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs
|
||||
arduino --install-boards "esp8266:esp8266"
|
||||
fi
|
||||
- |
|
||||
if [[ $PLATFORM == "esp8266" ]] && [[ $RELEASE == "devel" ]]
|
||||
then
|
||||
mkdir -p hardware/esp8266com
|
||||
cd hardware/esp8266com
|
||||
git clone https://github.com/esp8266/Arduino.git esp8266
|
||||
cd esp8266/tools
|
||||
python get.py
|
||||
fi
|
||||
- |
|
||||
if [[ $PLATFORM == "esp32" ]] && [[ $RELEASE == "devel" ]]
|
||||
then
|
||||
mkdir -p hardware/espressif
|
||||
cd hardware/espressif
|
||||
git clone https://github.com/espressif/arduino-esp32.git esp32
|
||||
cd esp32/tools/
|
||||
python get.py
|
||||
fi
|
||||
- arduino --pref "compiler.warning_level=all" --save-prefs
|
||||
- echo -e "travis_fold:end:sketch_test_env_prepare"
|
||||
- echo -e "travis_fold:start:install_library"
|
||||
- cd $HOME/Arduino/libraries
|
||||
- git clone https://github.com/bbx10/WebServer_tng ${HOME}/Arduino/libraries/WebServer
|
||||
- git clone https://github.com/bbx10/DNSServer_tng ${HOME}/Arduino/libraries/DNSServer
|
||||
- echo -e "travis_fold:end:install_library"
|
||||
- echo -e "travis_fold:start:CaptivePortalAdvanced"
|
||||
- cd DNSServer/examples
|
||||
- arduino --verbose-build --verify --board $BOARD CaptivePortalAdvanced/CaptivePortalAdvanced.ino
|
||||
- echo -e "travis_fold:end:CaptivePortalAdvanced"
|
||||
- echo -e "travis_fold:start:CaptivePortal"
|
||||
- arduino --verbose-build --verify --board $BOARD CaptivePortal/CaptivePortal.ino
|
||||
- echo -e "travis_fold:end:CaptivePortal"
|
||||
- echo -e "travis_fold:start:DNSServer"
|
||||
- arduino --verbose-build --verify --board $BOARD DNSServer/DNSServer.ino
|
||||
- echo -e "travis_fold:end:DNSServer"
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: change
|
7
libraries/DNSServer/README.md
Normal file
7
libraries/DNSServer/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# DNSServer
|
||||
ESP8266/ESP32 DNSServer library
|
||||
|
||||
This is an experimental port of the DNSServer library that should work on
|
||||
ESP8266 and ESP32. This is NOT an official repo supported by Espressif. Do not
|
||||
depend on this code for anything important or expect it to be updated. Once the
|
||||
official repo is created, this repo will be deleted.
|
41
libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino
Normal file
41
libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino
Normal file
@ -0,0 +1,41 @@
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <DNSServer.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
ESP8266WebServer webServer(80);
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include <DNSServer.h>
|
||||
#include <WebServer.h>
|
||||
WebServer webServer(80);
|
||||
#endif
|
||||
|
||||
const byte DNS_PORT = 53;
|
||||
IPAddress apIP(192, 168, 1, 1);
|
||||
DNSServer dnsServer;
|
||||
|
||||
String responseHTML = ""
|
||||
"<!DOCTYPE html><html><head><title>CaptivePortal</title></head><body>"
|
||||
"<h1>Hello World!</h1><p>This is a captive portal example. All requests will "
|
||||
"be redirected here.</p></body></html>";
|
||||
|
||||
void setup() {
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
|
||||
WiFi.softAP("DNSServer CaptivePortal example");
|
||||
|
||||
// if DNSServer is started with "*" for domain name, it will reply with
|
||||
// provided IP to all DNS request
|
||||
dnsServer.start(DNS_PORT, "*", apIP);
|
||||
|
||||
// replay to all requests with same HTML
|
||||
webServer.onNotFound([]() {
|
||||
webServer.send(200, "text/html", responseHTML);
|
||||
});
|
||||
webServer.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
dnsServer.processNextRequest();
|
||||
webServer.handleClient();
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <DNSServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <EEPROM.h>
|
||||
// Web server
|
||||
ESP8266WebServer server(80);
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WebServer.h>
|
||||
#include <DNSServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include <Preferences.h>
|
||||
// Web server
|
||||
WebServer server(80);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This example serves a "hello world" on a WLAN and a SoftAP at the same time.
|
||||
* The SoftAP allow you to configure WLAN parameters at run time. They are not setup in the sketch but saved on EEPROM.
|
||||
*
|
||||
* Connect your computer or cell phone to wifi network ESP_ap with password 12345678. A popup may appear and it allow you to go to WLAN config. If it does not then navigate to http://192.168.4.1/wifi and config it there.
|
||||
* Then wait for the module to connect to your wifi and take note of the WLAN IP it got. Then you can disconnect from ESP_ap and return to your regular WLAN.
|
||||
*
|
||||
* Now the ESP8266/ESP32 is in your network. You can reach it through http://192.168.x.x/ (the IP you took note of) or maybe at http://esp8266.local too.
|
||||
*
|
||||
* This is a captive portal because through the softAP it will redirect any http request to http://192.168.4.1/
|
||||
*/
|
||||
|
||||
/* Set these to your desired softAP credentials. They are not configurable at runtime */
|
||||
const char *softAP_ssid = "ESP_ap";
|
||||
const char *softAP_password = "12345678";
|
||||
|
||||
/* hostname for mDNS. Should work at least on windows. Try http://esp8266.local */
|
||||
#ifdef ESP8266
|
||||
const char *myHostname = "esp8266";
|
||||
#else
|
||||
const char *myHostname = "esp32mambo";
|
||||
#endif
|
||||
|
||||
/* Don't set this wifi credentials. They are configurated at runtime and stored on EEPROM */
|
||||
char ssid[32] = "";
|
||||
char password[32] = "";
|
||||
|
||||
// DNS server
|
||||
const byte DNS_PORT = 53;
|
||||
DNSServer dnsServer;
|
||||
|
||||
#ifdef ESP32
|
||||
/* Storage for SSID and password */
|
||||
Preferences preferences;
|
||||
#endif
|
||||
|
||||
/* Soft AP network parameters */
|
||||
IPAddress apIP(192, 168, 4, 1);
|
||||
IPAddress netMsk(255, 255, 255, 0);
|
||||
|
||||
|
||||
/** Should I connect to WLAN asap? */
|
||||
boolean connect;
|
||||
|
||||
/** Last time I tried to connect to WLAN */
|
||||
long lastConnectTry = 0;
|
||||
|
||||
/** Current WLAN status */
|
||||
int status = WL_IDLE_STATUS;
|
||||
|
||||
void setup() {
|
||||
delay(1000);
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
#ifdef ESP32
|
||||
preferences.begin("CapPortAdv", false);
|
||||
#endif
|
||||
Serial.print("Configuring access point...");
|
||||
/* You can remove the password parameter if you want the AP to be open. */
|
||||
WiFi.softAPConfig(apIP, apIP, netMsk);
|
||||
WiFi.softAP(softAP_ssid, softAP_password);
|
||||
delay(500); // Without delay I've seen the IP address blank
|
||||
Serial.print("AP IP address: ");
|
||||
Serial.println(WiFi.softAPIP());
|
||||
|
||||
/* Setup the DNS server redirecting all the domains to the apIP */
|
||||
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
|
||||
dnsServer.start(DNS_PORT, "*", apIP);
|
||||
|
||||
/* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */
|
||||
server.on("/", handleRoot);
|
||||
server.on("/wifi", handleWifi);
|
||||
server.on("/wifisave", handleWifiSave);
|
||||
server.on("/generate_204", handleRoot); //Android captive portal. Maybe not needed. Might be handled by notFound handler.
|
||||
server.on("/fwlink", handleRoot); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
|
||||
server.onNotFound ( handleNotFound );
|
||||
server.begin(); // Web server start
|
||||
Serial.println("HTTP server started");
|
||||
loadCredentials(); // Load WLAN credentials from network
|
||||
connect = strlen(ssid) > 0; // Request WLAN connect if there is a SSID
|
||||
}
|
||||
|
||||
void connectWifi() {
|
||||
Serial.println("Connecting as wifi client...");
|
||||
WiFi.disconnect();
|
||||
WiFi.begin ( ssid, password );
|
||||
int connRes = WiFi.waitForConnectResult();
|
||||
Serial.print ( "connRes: " );
|
||||
Serial.println ( connRes );
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (connect) {
|
||||
Serial.println ( "Connect requested" );
|
||||
connect = false;
|
||||
connectWifi();
|
||||
lastConnectTry = millis();
|
||||
}
|
||||
{
|
||||
int s = WiFi.status();
|
||||
if (s == 0 && millis() > (lastConnectTry + 60000) ) {
|
||||
/* If WLAN disconnected and idle try to connect */
|
||||
/* Don't set retry time too low as retry interfere the softAP operation */
|
||||
connect = true;
|
||||
}
|
||||
if (status != s) { // WLAN status change
|
||||
Serial.print ( "Status: " );
|
||||
Serial.println ( s );
|
||||
status = s;
|
||||
if (s == WL_CONNECTED) {
|
||||
/* Just connected to WLAN */
|
||||
Serial.println ( "" );
|
||||
Serial.print ( "Connected to " );
|
||||
Serial.println ( ssid );
|
||||
Serial.print ( "IP address: " );
|
||||
Serial.println ( WiFi.localIP() );
|
||||
|
||||
// Setup MDNS responder
|
||||
if (!MDNS.begin(myHostname)) {
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
} else {
|
||||
Serial.println("mDNS responder started");
|
||||
// Add service to MDNS-SD
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
}
|
||||
} else if (s == WL_NO_SSID_AVAIL) {
|
||||
WiFi.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Do work:
|
||||
//DNS
|
||||
dnsServer.processNextRequest();
|
||||
//HTTP
|
||||
server.handleClient();
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
#ifdef ESP8266
|
||||
/** Load WLAN credentials from EEPROM */
|
||||
void loadCredentials() {
|
||||
EEPROM.begin(512);
|
||||
EEPROM.get(0, ssid);
|
||||
EEPROM.get(0+sizeof(ssid), password);
|
||||
char ok[2+1];
|
||||
EEPROM.get(0+sizeof(ssid)+sizeof(password), ok);
|
||||
EEPROM.end();
|
||||
if (String(ok) != String("OK")) {
|
||||
ssid[0] = 0;
|
||||
password[0] = 0;
|
||||
}
|
||||
Serial.println("Recovered credentials:");
|
||||
Serial.println(ssid);
|
||||
Serial.println(strlen(password)>0?"********":"<no password>");
|
||||
}
|
||||
|
||||
/** Store WLAN credentials to EEPROM */
|
||||
void saveCredentials() {
|
||||
EEPROM.begin(512);
|
||||
EEPROM.put(0, ssid);
|
||||
EEPROM.put(0+sizeof(ssid), password);
|
||||
char ok[2+1] = "OK";
|
||||
EEPROM.put(0+sizeof(ssid)+sizeof(password), ok);
|
||||
EEPROM.commit();
|
||||
EEPROM.end();
|
||||
}
|
||||
#else
|
||||
/** Load WLAN credentials from Preferences */
|
||||
void loadCredentials() {
|
||||
preferences.getString("ssid", ssid, sizeof(ssid));
|
||||
preferences.getString("password", password, sizeof(password));
|
||||
Serial.println("Recovered credentials:");
|
||||
Serial.println(ssid);
|
||||
Serial.println(strlen(password)>0?"********":"<no password>");
|
||||
}
|
||||
|
||||
/** Store WLAN credentials to Preference */
|
||||
void saveCredentials() {
|
||||
preferences.putString("ssid", ssid);
|
||||
preferences.putString("password", password);
|
||||
Serial.println("Saved credentials:");
|
||||
Serial.println(ssid);
|
||||
Serial.println(strlen(password)>0?"********":"<no password>");
|
||||
}
|
||||
#endif
|
@ -0,0 +1,137 @@
|
||||
/** Handle root or redirect to captive portal */
|
||||
void handleRoot() {
|
||||
if (captivePortal()) { // If caprive portal redirect instead of displaying the page.
|
||||
return;
|
||||
}
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
server.send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
||||
server.sendContent(
|
||||
"<html><head></head><body>"
|
||||
"<h1>HELLO WORLD!!</h1>"
|
||||
);
|
||||
if (server.client().localIP() == apIP) {
|
||||
server.sendContent(String("<p>You are connected through the soft AP: ") + softAP_ssid + "</p>");
|
||||
} else {
|
||||
server.sendContent(String("<p>You are connected through the wifi network: ") + ssid + "</p>");
|
||||
}
|
||||
server.sendContent(
|
||||
"<p>You may want to <a href='/wifi'>config the wifi connection</a>.</p>"
|
||||
"</body></html>"
|
||||
);
|
||||
server.sendContent("");
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
}
|
||||
|
||||
/** Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */
|
||||
boolean captivePortal() {
|
||||
if (!isIp(server.hostHeader()) && server.hostHeader() != (String(myHostname)+".local")) {
|
||||
Serial.print("Request redirected to captive portal");
|
||||
server.sendHeader("Location", String("http://") + toStringIp(server.client().localIP()), true);
|
||||
server.send ( 302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Wifi config page handler */
|
||||
void handleWifi() {
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
server.send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
||||
server.sendContent(
|
||||
"<html><head></head><body>"
|
||||
"<h1>Wifi config</h1>"
|
||||
);
|
||||
if (server.client().localIP() == apIP) {
|
||||
server.sendContent(String("<p>You are connected through the soft AP: ") + softAP_ssid + "</p>");
|
||||
} else {
|
||||
server.sendContent(String("<p>You are connected through the wifi network: ") + ssid + "</p>");
|
||||
}
|
||||
server.sendContent(
|
||||
"\r\n<br />"
|
||||
"<table><tr><th align='left'>SoftAP config</th></tr>"
|
||||
);
|
||||
server.sendContent(String() + "<tr><td>SSID " + String(softAP_ssid) + "</td></tr>");
|
||||
server.sendContent(String() + "<tr><td>IP " + toStringIp(WiFi.softAPIP()) + "</td></tr>");
|
||||
server.sendContent(
|
||||
"</table>"
|
||||
"\r\n<br />"
|
||||
"<table><tr><th align='left'>WLAN config</th></tr>"
|
||||
);
|
||||
server.sendContent(String() + "<tr><td>SSID " + String(ssid) + "</td></tr>");
|
||||
server.sendContent(String() + "<tr><td>IP " + toStringIp(WiFi.localIP()) + "</td></tr>");
|
||||
server.sendContent(
|
||||
"</table>"
|
||||
"\r\n<br />"
|
||||
"<table><tr><th align='left'>WLAN list (refresh if any missing)</th></tr>"
|
||||
);
|
||||
Serial.println("scan start");
|
||||
int n = WiFi.scanNetworks();
|
||||
Serial.println("scan done");
|
||||
if (n > 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
#ifdef ESP8266
|
||||
server.sendContent(String() + "\r\n<tr><td>SSID " + WiFi.SSID(i) + String((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":" *") + " (" + WiFi.RSSI(i) + ")</td></tr>");
|
||||
#else
|
||||
server.sendContent(String() + "\r\n<tr><td>SSID " + WiFi.SSID(i) + String((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":" *") + " (" + WiFi.RSSI(i) + ")</td></tr>");
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
server.sendContent(String() + "<tr><td>No WLAN found</td></tr>");
|
||||
}
|
||||
server.sendContent(
|
||||
"</table>"
|
||||
"\r\n<br /><form method='POST' action='wifisave'><h4>Connect to network:</h4>"
|
||||
"<input type='text' placeholder='network' name='n'/>"
|
||||
"<br /><input type='password' placeholder='password' name='p'/>"
|
||||
"<br /><input type='submit' value='Connect/Disconnect'/></form>"
|
||||
"<p>You may want to <a href='/'>return to the home page</a>.</p>"
|
||||
"</body></html>"
|
||||
);
|
||||
server.sendContent("");
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
}
|
||||
|
||||
/** Handle the WLAN save form and redirect to WLAN config page again */
|
||||
void handleWifiSave() {
|
||||
Serial.println("wifi save");
|
||||
server.arg("n").toCharArray(ssid, sizeof(ssid) - 1);
|
||||
server.arg("p").toCharArray(password, sizeof(password) - 1);
|
||||
server.sendHeader("Location", "wifi", true);
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
server.send ( 302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
saveCredentials();
|
||||
connect = strlen(ssid) > 0; // Request WLAN connect with new credentials if there is a SSID
|
||||
}
|
||||
|
||||
void handleNotFound() {
|
||||
if (captivePortal()) { // If caprive portal redirect instead of displaying the error page.
|
||||
return;
|
||||
}
|
||||
String message = "File Not Found\n\n";
|
||||
message += "URI: ";
|
||||
message += server.uri();
|
||||
message += "\nMethod: ";
|
||||
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
|
||||
for ( uint8_t i = 0; i < server.args(); i++ ) {
|
||||
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
|
||||
}
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
server.send ( 404, "text/plain", message );
|
||||
}
|
||||
|
21
libraries/DNSServer/examples/CaptivePortalAdvanced/tools.ino
Normal file
21
libraries/DNSServer/examples/CaptivePortalAdvanced/tools.ino
Normal file
@ -0,0 +1,21 @@
|
||||
/** Is this an IP? */
|
||||
boolean isIp(String str) {
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
int c = str.charAt(i);
|
||||
if (c != '.' && (c < '0' || c > '9')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** IP to String? */
|
||||
String toStringIp(IPAddress ip) {
|
||||
String res = "";
|
||||
for (int i = 0; i < 3; i++) {
|
||||
res += String((ip >> (8 * i)) & 0xFF) + ".";
|
||||
}
|
||||
res += String(((ip >> 8 * 3)) & 0xFF);
|
||||
return res;
|
||||
}
|
||||
|
48
libraries/DNSServer/examples/DNSServer/DNSServer.ino
Normal file
48
libraries/DNSServer/examples/DNSServer/DNSServer.ino
Normal file
@ -0,0 +1,48 @@
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <DNSServer.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
ESP8266WebServer webServer(80);
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include <DNSServer.h>
|
||||
#include <WebServer.h>
|
||||
WebServer webServer(80);
|
||||
#endif
|
||||
|
||||
const byte DNS_PORT = 53;
|
||||
IPAddress apIP(192, 168, 1, 1);
|
||||
DNSServer dnsServer;
|
||||
|
||||
void setup() {
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
|
||||
WiFi.softAP("DNSServer example");
|
||||
|
||||
// modify TTL associated with the domain name (in seconds)
|
||||
// default is 60 seconds
|
||||
dnsServer.setTTL(300);
|
||||
// set which return code will be used for all other domains (e.g. sending
|
||||
// ServerFailure instead of NonExistentDomain will reduce number of queries
|
||||
// sent by clients)
|
||||
// default is DNSReplyCode::NonExistentDomain
|
||||
dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure);
|
||||
|
||||
// start DNS server for a specific domain name
|
||||
dnsServer.start(DNS_PORT, "www.example.com", apIP);
|
||||
|
||||
// simple HTTP server to see that DNS server is working
|
||||
webServer.onNotFound([]() {
|
||||
String message = "Hello World!\n\n";
|
||||
message += "URI: ";
|
||||
message += webServer.uri();
|
||||
|
||||
webServer.send(200, "text/plain", message);
|
||||
});
|
||||
webServer.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
dnsServer.processNextRequest();
|
||||
webServer.handleClient();
|
||||
}
|
9
libraries/DNSServer/library.properties
Normal file
9
libraries/DNSServer/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=DNSServer
|
||||
version=1.1.0
|
||||
author=Kristijan Novoselić
|
||||
maintainer=Kristijan Novoselić, <kristijan.novoselic@gmail.com>
|
||||
sentence=A simple DNS server for ESP8266.
|
||||
paragraph=This library implements a simple DNS server.
|
||||
category=Communication
|
||||
url=
|
||||
architectures=esp8266,esp32
|
171
libraries/DNSServer/src/DNSServer.cpp
Normal file
171
libraries/DNSServer/src/DNSServer.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
#include "DNSServer.h"
|
||||
#include <lwip/def.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
DNSServer::DNSServer()
|
||||
{
|
||||
_ttl = htonl(60);
|
||||
_errorReplyCode = DNSReplyCode::NonExistentDomain;
|
||||
}
|
||||
|
||||
bool DNSServer::start(const uint16_t &port, const String &domainName,
|
||||
const IPAddress &resolvedIP)
|
||||
{
|
||||
_port = port;
|
||||
_buffer = NULL;
|
||||
_domainName = domainName;
|
||||
_resolvedIP[0] = resolvedIP[0];
|
||||
_resolvedIP[1] = resolvedIP[1];
|
||||
_resolvedIP[2] = resolvedIP[2];
|
||||
_resolvedIP[3] = resolvedIP[3];
|
||||
downcaseAndRemoveWwwPrefix(_domainName);
|
||||
return _udp.begin(_port) == 1;
|
||||
}
|
||||
|
||||
void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
|
||||
{
|
||||
_errorReplyCode = replyCode;
|
||||
}
|
||||
|
||||
void DNSServer::setTTL(const uint32_t &ttl)
|
||||
{
|
||||
_ttl = htonl(ttl);
|
||||
}
|
||||
|
||||
void DNSServer::stop()
|
||||
{
|
||||
_udp.stop();
|
||||
free(_buffer);
|
||||
_buffer = NULL;
|
||||
}
|
||||
|
||||
void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
|
||||
{
|
||||
domainName.toLowerCase();
|
||||
domainName.replace("www.", "");
|
||||
}
|
||||
|
||||
void DNSServer::processNextRequest()
|
||||
{
|
||||
_currentPacketSize = _udp.parsePacket();
|
||||
if (_currentPacketSize)
|
||||
{
|
||||
if (_buffer != NULL) free(_buffer);
|
||||
_buffer = (unsigned char*)malloc(_currentPacketSize * sizeof(char));
|
||||
if (_buffer == NULL) return;
|
||||
_udp.read(_buffer, _currentPacketSize);
|
||||
_dnsHeader = (DNSHeader*) _buffer;
|
||||
|
||||
if (_dnsHeader->QR == DNS_QR_QUERY &&
|
||||
_dnsHeader->OPCode == DNS_OPCODE_QUERY &&
|
||||
requestIncludesOnlyOneQuestion() &&
|
||||
(_domainName == "*" || getDomainNameWithoutWwwPrefix() == _domainName)
|
||||
)
|
||||
{
|
||||
replyWithIP();
|
||||
}
|
||||
else if (_dnsHeader->QR == DNS_QR_QUERY)
|
||||
{
|
||||
replyWithCustomCode();
|
||||
}
|
||||
|
||||
free(_buffer);
|
||||
_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool DNSServer::requestIncludesOnlyOneQuestion()
|
||||
{
|
||||
return ntohs(_dnsHeader->QDCount) == 1 &&
|
||||
_dnsHeader->ANCount == 0 &&
|
||||
_dnsHeader->NSCount == 0 &&
|
||||
_dnsHeader->ARCount == 0;
|
||||
}
|
||||
|
||||
String DNSServer::getDomainNameWithoutWwwPrefix()
|
||||
{
|
||||
String parsedDomainName = "";
|
||||
if (_buffer == NULL) return parsedDomainName;
|
||||
unsigned char *start = _buffer + 12;
|
||||
if (*start == 0)
|
||||
{
|
||||
return parsedDomainName;
|
||||
}
|
||||
int pos = 0;
|
||||
while(true)
|
||||
{
|
||||
unsigned char labelLength = *(start + pos);
|
||||
for(int i = 0; i < labelLength; i++)
|
||||
{
|
||||
pos++;
|
||||
parsedDomainName += (char)*(start + pos);
|
||||
}
|
||||
pos++;
|
||||
if (*(start + pos) == 0)
|
||||
{
|
||||
downcaseAndRemoveWwwPrefix(parsedDomainName);
|
||||
return parsedDomainName;
|
||||
}
|
||||
else
|
||||
{
|
||||
parsedDomainName += ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DNSServer::replyWithIP()
|
||||
{
|
||||
if (_buffer == NULL) return;
|
||||
_dnsHeader->QR = DNS_QR_RESPONSE;
|
||||
_dnsHeader->ANCount = _dnsHeader->QDCount;
|
||||
_dnsHeader->QDCount = _dnsHeader->QDCount;
|
||||
//_dnsHeader->RA = 1;
|
||||
|
||||
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
||||
_udp.write(_buffer, _currentPacketSize);
|
||||
|
||||
_udp.write((uint8_t)192); // answer name is a pointer
|
||||
_udp.write((uint8_t)12); // pointer to offset at 0x00c
|
||||
|
||||
_udp.write((uint8_t)0); // 0x0001 answer is type A query (host address)
|
||||
_udp.write((uint8_t)1);
|
||||
|
||||
_udp.write((uint8_t)0); //0x0001 answer is class IN (internet address)
|
||||
_udp.write((uint8_t)1);
|
||||
|
||||
_udp.write((unsigned char*)&_ttl, 4);
|
||||
|
||||
// Length of RData is 4 bytes (because, in this case, RData is IPv4)
|
||||
_udp.write((uint8_t)0);
|
||||
_udp.write((uint8_t)4);
|
||||
_udp.write(_resolvedIP, sizeof(_resolvedIP));
|
||||
_udp.endPacket();
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
DEBUG_OUTPUT.print("DNS responds: ");
|
||||
DEBUG_OUTPUT.print(_resolvedIP[0]);
|
||||
DEBUG_OUTPUT.print(".");
|
||||
DEBUG_OUTPUT.print(_resolvedIP[1]);
|
||||
DEBUG_OUTPUT.print(".");
|
||||
DEBUG_OUTPUT.print(_resolvedIP[2]);
|
||||
DEBUG_OUTPUT.print(".");
|
||||
DEBUG_OUTPUT.print(_resolvedIP[3]);
|
||||
DEBUG_OUTPUT.print(" for ");
|
||||
DEBUG_OUTPUT.println(getDomainNameWithoutWwwPrefix());
|
||||
#endif
|
||||
}
|
||||
|
||||
void DNSServer::replyWithCustomCode()
|
||||
{
|
||||
if (_buffer == NULL) return;
|
||||
_dnsHeader->QR = DNS_QR_RESPONSE;
|
||||
_dnsHeader->RCode = (unsigned char)_errorReplyCode;
|
||||
_dnsHeader->QDCount = 0;
|
||||
|
||||
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
||||
_udp.write(_buffer, sizeof(DNSHeader));
|
||||
_udp.endPacket();
|
||||
}
|
71
libraries/DNSServer/src/DNSServer.h
Normal file
71
libraries/DNSServer/src/DNSServer.h
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef DNSServer_h
|
||||
#define DNSServer_h
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#define DNS_QR_QUERY 0
|
||||
#define DNS_QR_RESPONSE 1
|
||||
#define DNS_OPCODE_QUERY 0
|
||||
|
||||
enum class DNSReplyCode
|
||||
{
|
||||
NoError = 0,
|
||||
FormError = 1,
|
||||
ServerFailure = 2,
|
||||
NonExistentDomain = 3,
|
||||
NotImplemented = 4,
|
||||
Refused = 5,
|
||||
YXDomain = 6,
|
||||
YXRRSet = 7,
|
||||
NXRRSet = 8
|
||||
};
|
||||
|
||||
struct DNSHeader
|
||||
{
|
||||
uint16_t ID; // identification number
|
||||
unsigned char RD : 1; // recursion desired
|
||||
unsigned char TC : 1; // truncated message
|
||||
unsigned char AA : 1; // authoritive answer
|
||||
unsigned char OPCode : 4; // message_type
|
||||
unsigned char QR : 1; // query/response flag
|
||||
unsigned char RCode : 4; // response code
|
||||
unsigned char Z : 3; // its z! reserved
|
||||
unsigned char RA : 1; // recursion available
|
||||
uint16_t QDCount; // number of question entries
|
||||
uint16_t ANCount; // number of answer entries
|
||||
uint16_t NSCount; // number of authority entries
|
||||
uint16_t ARCount; // number of resource entries
|
||||
};
|
||||
|
||||
class DNSServer
|
||||
{
|
||||
public:
|
||||
DNSServer();
|
||||
void processNextRequest();
|
||||
void setErrorReplyCode(const DNSReplyCode &replyCode);
|
||||
void setTTL(const uint32_t &ttl);
|
||||
|
||||
// Returns true if successful, false if there are no sockets available
|
||||
bool start(const uint16_t &port,
|
||||
const String &domainName,
|
||||
const IPAddress &resolvedIP);
|
||||
// stops the DNS server
|
||||
void stop();
|
||||
|
||||
private:
|
||||
WiFiUDP _udp;
|
||||
uint16_t _port;
|
||||
String _domainName;
|
||||
unsigned char _resolvedIP[4];
|
||||
int _currentPacketSize;
|
||||
unsigned char* _buffer;
|
||||
DNSHeader* _dnsHeader;
|
||||
uint32_t _ttl;
|
||||
DNSReplyCode _errorReplyCode;
|
||||
|
||||
void downcaseAndRemoveWwwPrefix(String &domainName);
|
||||
String getDomainNameWithoutWwwPrefix();
|
||||
bool requestIncludesOnlyOneQuestion();
|
||||
void replyWithIP();
|
||||
void replyWithCustomCode();
|
||||
};
|
||||
#endif
|
32
libraries/WebServer/.gitignore
vendored
Normal file
32
libraries/WebServer/.gitignore
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
99
libraries/WebServer/.travis.yml
Normal file
99
libraries/WebServer/.travis.yml
Normal file
@ -0,0 +1,99 @@
|
||||
sudo: false
|
||||
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
||||
env:
|
||||
- TESTCASE="1.8.3|esp8266|stable|esp8266:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M"
|
||||
- TESTCASE="1.8.3|esp8266|devel|esp8266com:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M"
|
||||
- TESTCASE="1.8.3|esp32|devel|espressif:esp32:esp32:FlashFreq=40"
|
||||
|
||||
script:
|
||||
- echo -e "travis_fold:start:sketch_test_env_prepare"
|
||||
- pip install pyserial
|
||||
- IFS='|' read -r -a array <<< "${TESTCASE}"
|
||||
- |
|
||||
for index in "${!array[@]}"
|
||||
do
|
||||
case $index in
|
||||
0) IDEVER="${array[index]}" ;;
|
||||
1) PLATFORM="${array[index]}" ;;
|
||||
2) RELEASE="${array[index]}" ;;
|
||||
3) BOARD="${array[index]}" ;;
|
||||
esac
|
||||
done
|
||||
- cd $HOME
|
||||
- wget -O arduino.tar.xz https://downloads.arduino.cc/arduino-${IDEVER}-linux64.tar.xz
|
||||
- tar xf arduino.tar.xz
|
||||
- mv arduino-${IDEVER} $HOME/arduino_ide
|
||||
- mkdir -p $HOME/Arduino/libraries
|
||||
- IDEDIR="${HOME}/arduino_ide"
|
||||
- export PATH="$IDEDIR:$PATH"
|
||||
- cd ${IDEDIR}
|
||||
- which arduino
|
||||
- |
|
||||
if [[ $PLATFORM == "esp8266" ]] && [[ $RELEASE == "stable" ]]
|
||||
then
|
||||
arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs
|
||||
arduino --install-boards "esp8266:esp8266"
|
||||
fi
|
||||
- |
|
||||
if [[ $PLATFORM == "esp8266" ]] && [[ $RELEASE == "devel" ]]
|
||||
then
|
||||
mkdir -p hardware/esp8266com
|
||||
cd hardware/esp8266com
|
||||
git clone https://github.com/esp8266/Arduino.git esp8266
|
||||
cd esp8266/tools
|
||||
python get.py
|
||||
fi
|
||||
- |
|
||||
if [[ $PLATFORM == "esp32" ]] && [[ $RELEASE == "devel" ]]
|
||||
then
|
||||
mkdir -p hardware/espressif
|
||||
cd hardware/espressif
|
||||
git clone https://github.com/espressif/arduino-esp32.git esp32
|
||||
cd esp32/tools/
|
||||
python get.py
|
||||
fi
|
||||
- arduino --pref "compiler.warning_level=all" --save-prefs
|
||||
- echo -e "travis_fold:end:sketch_test_env_prepare"
|
||||
- echo -e "travis_fold:start:install_library"
|
||||
- cd $HOME/Arduino/libraries
|
||||
- git clone https://github.com/bbx10/WebServer_tng ${HOME}/Arduino/libraries/WebServer
|
||||
- echo -e "travis_fold:end:install_library"
|
||||
- echo -e "travis_fold:start:AdvancedWebServer"
|
||||
- cd ${HOME}/Arduino/libraries/WebServer/examples
|
||||
- arduino --verbose-build --verify --board ${BOARD} AdvancedWebServer/AdvancedWebServer.ino
|
||||
- echo -e "travis_fold:end:AdvancedWebServer"
|
||||
- echo -e "travis_fold:start:HelloServer"
|
||||
- arduino --verbose-build --verify --board ${BOARD} HelloServer/HelloServer.ino
|
||||
- echo -e "travis_fold:end:HelloServer"
|
||||
- echo -e "travis_fold:start:HttpBasicAuth"
|
||||
- arduino --verbose-build --verify --board ${BOARD} HttpBasicAuth/HttpBasicAuth.ino
|
||||
- echo -e "travis_fold:end:HttpBasicAuth"
|
||||
- echo -e "travis_fold:start:SDWebServer"
|
||||
- arduino --verbose-build --verify --board ${BOARD} SDWebServer/SDWebServer.ino
|
||||
- echo -e "travis_fold:end:SDWebServer"
|
||||
- echo -e "travis_fold:start:SimpleAuthentification"
|
||||
- arduino --verbose-build --verify --board ${BOARD} SimpleAuthentification/SimpleAuthentification.ino
|
||||
- echo -e "travis_fold:end:SimpleAuthentification"
|
||||
- |
|
||||
if [[ $PLATFORM == "esp8266" ]]
|
||||
then
|
||||
echo -e "travis_fold:start:FSBrowser"
|
||||
arduino --verbose-build --verify --board ${BOARD} FSBrowser/FSBrowser.ino
|
||||
echo -e "travis_fold:end:FSBrowser"
|
||||
echo -e "travis_fold:start:WebUpdate"
|
||||
arduino --verbose-build --verify --board ${BOARD} WebUpdate/WebUpdate.ino
|
||||
echo -e "travis_fold:end:WebUpdate"
|
||||
fi
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: change
|
||||
|
504
libraries/WebServer/LICENSE
Normal file
504
libraries/WebServer/LICENSE
Normal file
@ -0,0 +1,504 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
(This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.)
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. 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 not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the 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
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
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 Street, Fifth Floor, Boston, MA 02110-1301
|
||||
USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random
|
||||
Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
9
libraries/WebServer/README.md
Normal file
9
libraries/WebServer/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# WebServer
|
||||
ESP8266/ESP32 WebServer library
|
||||
|
||||
This is an experimental port of the ESP8266WebServer library that should work
|
||||
on ESP8266 and ESP32. This is NOT an official repo supported by Espressif. Do
|
||||
not depend on this code for anything important or expect it to be updated. Once
|
||||
the official repo is created, this repo will be deleted.
|
||||
|
||||
Added Travis CI
|
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Majenko Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Majenko Technologies nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
ESP8266WebServer server ( 80 );
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WebServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
WebServer server ( 80 );
|
||||
#endif
|
||||
|
||||
const char *ssid = "YourSSIDHere";
|
||||
const char *password = "YourPSKHere";
|
||||
|
||||
#ifdef LED_BUILTIN
|
||||
const int led = LED_BUILTIN;
|
||||
#else
|
||||
const int led = 13;
|
||||
#endif
|
||||
|
||||
void handleRoot() {
|
||||
digitalWrite ( led, 1 );
|
||||
char temp[400];
|
||||
int sec = millis() / 1000;
|
||||
int min = sec / 60;
|
||||
int hr = min / 60;
|
||||
|
||||
snprintf ( temp, 400,
|
||||
|
||||
"<html>\
|
||||
<head>\
|
||||
<meta http-equiv='refresh' content='5'/>\
|
||||
<title>ESP8266/ESP32 Demo</title>\
|
||||
<style>\
|
||||
body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
|
||||
</style>\
|
||||
</head>\
|
||||
<body>\
|
||||
<h1>Hello from ESP8266/ESP32!</h1>\
|
||||
<p>Uptime: %02d:%02d:%02d</p>\
|
||||
<img src=\"/test.svg\" />\
|
||||
</body>\
|
||||
</html>",
|
||||
|
||||
hr, min % 60, sec % 60
|
||||
);
|
||||
server.send ( 200, "text/html", temp );
|
||||
digitalWrite ( led, 0 );
|
||||
}
|
||||
|
||||
void handleNotFound() {
|
||||
digitalWrite ( led, 1 );
|
||||
String message = "File Not Found\n\n";
|
||||
message += "URI: ";
|
||||
message += server.uri();
|
||||
message += "\nMethod: ";
|
||||
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
|
||||
for ( uint8_t i = 0; i < server.args(); i++ ) {
|
||||
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
|
||||
}
|
||||
|
||||
server.send ( 404, "text/plain", message );
|
||||
digitalWrite ( led, 0 );
|
||||
}
|
||||
|
||||
void setup ( void ) {
|
||||
pinMode ( led, OUTPUT );
|
||||
digitalWrite ( led, 0 );
|
||||
Serial.begin ( 115200 );
|
||||
WiFi.begin ( ssid, password );
|
||||
Serial.println ( "" );
|
||||
|
||||
// Wait for connection
|
||||
while ( WiFi.status() != WL_CONNECTED ) {
|
||||
delay ( 500 );
|
||||
Serial.print ( "." );
|
||||
}
|
||||
|
||||
Serial.println ( "" );
|
||||
Serial.print ( "Connected to " );
|
||||
Serial.println ( ssid );
|
||||
Serial.print ( "IP address: " );
|
||||
Serial.println ( WiFi.localIP() );
|
||||
|
||||
#ifdef ESP8266
|
||||
if ( MDNS.begin ( "esp8266" ) ) {
|
||||
#else
|
||||
if ( MDNS.begin ( "esp32" ) ) {
|
||||
#endif
|
||||
Serial.println ( "MDNS responder started" );
|
||||
}
|
||||
|
||||
server.on ( "/", handleRoot );
|
||||
server.on ( "/test.svg", drawGraph );
|
||||
server.on ( "/inline", []() {
|
||||
server.send ( 200, "text/plain", "this works as well" );
|
||||
} );
|
||||
server.onNotFound ( handleNotFound );
|
||||
server.begin();
|
||||
Serial.println ( "HTTP server started" );
|
||||
}
|
||||
|
||||
void loop ( void ) {
|
||||
server.handleClient();
|
||||
}
|
||||
|
||||
void drawGraph() {
|
||||
String out = "";
|
||||
char temp[100];
|
||||
out += "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"400\" height=\"150\">\n";
|
||||
out += "<rect width=\"400\" height=\"150\" fill=\"rgb(250, 230, 210)\" stroke-width=\"1\" stroke=\"rgb(0, 0, 0)\" />\n";
|
||||
out += "<g stroke=\"black\">\n";
|
||||
int y = rand() % 130;
|
||||
for (int x = 10; x < 390; x+= 10) {
|
||||
int y2 = rand() % 130;
|
||||
sprintf(temp, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke-width=\"1\" />\n", x, 140 - y, x + 10, 140 - y2);
|
||||
out += temp;
|
||||
y = y2;
|
||||
}
|
||||
out += "</g>\n</svg>\n";
|
||||
|
||||
server.send ( 200, "image/svg+xml", out);
|
||||
}
|
345
libraries/WebServer/examples/FSBrowser/FSBrowser.ino
Normal file
345
libraries/WebServer/examples/FSBrowser/FSBrowser.ino
Normal file
@ -0,0 +1,345 @@
|
||||
/*
|
||||
FSWebServer - Example WebServer with SPIFFS backend for esp8266
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the ESP8266/ESP32 WebServer 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
|
||||
|
||||
upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
|
||||
or you can upload the contents of a folder if you CD in that folder and run the following command:
|
||||
for file in `ls -A1`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done
|
||||
|
||||
access the sample web page at http://esp8266fs.local
|
||||
edit the page by going to http://esp8266fs.local/edit
|
||||
*/
|
||||
/*
|
||||
* Uploading html, css, javascript, etc.
|
||||
* Use curl to upload the files from the SPIFFS data directory.
|
||||
* cd data/
|
||||
* curl -X POST -F "data=@index.htm" http://<ESP32 IP address>/edit >/dev/null
|
||||
* curl -X POST -F "data=@graphs.js.gz" http://<ESP32 IP address>/edit >/dev/null
|
||||
* curl -X POST -F "data=@favicon.ico" http://<ESP32 IP address>/edit >/dev/null
|
||||
* curl -X POST -F "data=@edit.htm.gz" http://<ESP32 IP address>/edit >/dev/null
|
||||
*/
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <FS.h>
|
||||
ESP8266WebServer server(80);
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WebServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include <SPIFFS.h>
|
||||
WebServer server(80);
|
||||
#endif
|
||||
|
||||
#define DBG_OUTPUT_PORT Serial
|
||||
|
||||
const char* ssid = "wifi-ssid";
|
||||
const char* password = "wifi-password";
|
||||
const char* host = "esp8266fs";
|
||||
|
||||
//holds the current upload
|
||||
File fsUploadFile;
|
||||
|
||||
//format bytes
|
||||
String formatBytes(size_t bytes){
|
||||
if (bytes < 1024){
|
||||
return String(bytes)+"B";
|
||||
} else if(bytes < (1024 * 1024)){
|
||||
return String(bytes/1024.0)+"KB";
|
||||
} else if(bytes < (1024 * 1024 * 1024)){
|
||||
return String(bytes/1024.0/1024.0)+"MB";
|
||||
} else {
|
||||
return String(bytes/1024.0/1024.0/1024.0)+"GB";
|
||||
}
|
||||
}
|
||||
|
||||
String getContentType(String filename){
|
||||
if(server.hasArg("download")) return "application/octet-stream";
|
||||
else if(filename.endsWith(".htm")) return "text/html";
|
||||
else if(filename.endsWith(".html")) return "text/html";
|
||||
else if(filename.endsWith(".css")) return "text/css";
|
||||
else if(filename.endsWith(".js")) return "application/javascript";
|
||||
else if(filename.endsWith(".png")) return "image/png";
|
||||
else if(filename.endsWith(".gif")) return "image/gif";
|
||||
else if(filename.endsWith(".jpg")) return "image/jpeg";
|
||||
else if(filename.endsWith(".ico")) return "image/x-icon";
|
||||
else if(filename.endsWith(".xml")) return "text/xml";
|
||||
else if(filename.endsWith(".pdf")) return "application/x-pdf";
|
||||
else if(filename.endsWith(".zip")) return "application/x-zip";
|
||||
else if(filename.endsWith(".gz")) return "application/x-gzip";
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
bool handleFileRead(String path){
|
||||
DBG_OUTPUT_PORT.println("handleFileRead: " + path);
|
||||
if(path.endsWith("/")) path += "index.htm";
|
||||
String contentType = getContentType(path);
|
||||
String pathWithGz = path + ".gz";
|
||||
if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){
|
||||
if(SPIFFS.exists(pathWithGz))
|
||||
path += ".gz";
|
||||
File file = SPIFFS.open(path, "r");
|
||||
size_t sent = server.streamFile(file, contentType);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void handleFileUpload(){
|
||||
if(server.uri() != "/edit") return;
|
||||
HTTPUpload& upload = server.upload();
|
||||
if(upload.status == UPLOAD_FILE_START){
|
||||
String filename = upload.filename;
|
||||
if(!filename.startsWith("/")) filename = "/"+filename;
|
||||
DBG_OUTPUT_PORT.print("handleFileUpload Name: "); DBG_OUTPUT_PORT.println(filename);
|
||||
fsUploadFile = SPIFFS.open(filename, "w");
|
||||
filename = String();
|
||||
} else if(upload.status == UPLOAD_FILE_WRITE){
|
||||
//DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize);
|
||||
if(fsUploadFile)
|
||||
fsUploadFile.write(upload.buf, upload.currentSize);
|
||||
} else if(upload.status == UPLOAD_FILE_END){
|
||||
if(fsUploadFile)
|
||||
fsUploadFile.close();
|
||||
DBG_OUTPUT_PORT.print("handleFileUpload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
|
||||
}
|
||||
}
|
||||
|
||||
void handleFileDelete(){
|
||||
if(server.args() == 0) return server.send(500, "text/plain", "BAD ARGS");
|
||||
String path = server.arg(0);
|
||||
DBG_OUTPUT_PORT.println("handleFileDelete: " + path);
|
||||
if(path == "/")
|
||||
return server.send(500, "text/plain", "BAD PATH");
|
||||
if(!SPIFFS.exists(path))
|
||||
return server.send(404, "text/plain", "FileNotFound");
|
||||
SPIFFS.remove(path);
|
||||
server.send(200, "text/plain", "");
|
||||
path = String();
|
||||
}
|
||||
|
||||
void handleFileCreate(){
|
||||
if(server.args() == 0)
|
||||
return server.send(500, "text/plain", "BAD ARGS");
|
||||
String path = server.arg(0);
|
||||
DBG_OUTPUT_PORT.println("handleFileCreate: " + path);
|
||||
if(path == "/")
|
||||
return server.send(500, "text/plain", "BAD PATH");
|
||||
if(SPIFFS.exists(path))
|
||||
return server.send(500, "text/plain", "FILE EXISTS");
|
||||
File file = SPIFFS.open(path, "w");
|
||||
if(file)
|
||||
file.close();
|
||||
else
|
||||
return server.send(500, "text/plain", "CREATE FAILED");
|
||||
server.send(200, "text/plain", "");
|
||||
path = String();
|
||||
}
|
||||
|
||||
void returnFail(String msg) {
|
||||
server.send(500, "text/plain", msg + "\r\n");
|
||||
}
|
||||
|
||||
#ifdef ESP8266
|
||||
void handleFileList() {
|
||||
if(!server.hasArg("dir")) {
|
||||
returnFail("BAD ARGS");
|
||||
return;
|
||||
}
|
||||
|
||||
String path = server.arg("dir");
|
||||
DBG_OUTPUT_PORT.println("handleFileList: " + path);
|
||||
Dir dir = SPIFFS.openDir(path);
|
||||
path = String();
|
||||
|
||||
String output = "[";
|
||||
while(dir.next()){
|
||||
File entry = dir.openFile("r");
|
||||
if (output != "[") output += ',';
|
||||
bool isDir = false;
|
||||
output += "{\"type\":\"";
|
||||
output += (isDir)?"dir":"file";
|
||||
output += "\",\"name\":\"";
|
||||
output += String(entry.name()).substring(1);
|
||||
output += "\"}";
|
||||
entry.close();
|
||||
}
|
||||
|
||||
output += "]";
|
||||
server.send(200, "text/json", output);
|
||||
}
|
||||
#else
|
||||
void handleFileList() {
|
||||
if(!server.hasArg("dir")) {
|
||||
returnFail("BAD ARGS");
|
||||
return;
|
||||
}
|
||||
String path = server.arg("dir");
|
||||
if(path != "/" && !SPIFFS.exists((char *)path.c_str())) {
|
||||
returnFail("BAD PATH");
|
||||
return;
|
||||
}
|
||||
File dir = SPIFFS.open((char *)path.c_str());
|
||||
path = String();
|
||||
if(!dir.isDirectory()){
|
||||
dir.close();
|
||||
returnFail("NOT DIR");
|
||||
return;
|
||||
}
|
||||
dir.rewindDirectory();
|
||||
|
||||
String output = "[";
|
||||
for (int cnt = 0; true; ++cnt) {
|
||||
File entry = dir.openNextFile();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
if (cnt > 0)
|
||||
output += ',';
|
||||
|
||||
output += "{\"type\":\"";
|
||||
output += (entry.isDirectory()) ? "dir" : "file";
|
||||
output += "\",\"name\":\"";
|
||||
// Ignore '/' prefix
|
||||
output += entry.name()+1;
|
||||
output += "\"";
|
||||
output += "}";
|
||||
entry.close();
|
||||
}
|
||||
output += "]";
|
||||
server.send(200, "text/json", output);
|
||||
dir.close();
|
||||
}
|
||||
|
||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
|
||||
DBG_OUTPUT_PORT.printf("Listing directory: %s\n", dirname);
|
||||
|
||||
File root = fs.open(dirname);
|
||||
if (!root) {
|
||||
DBG_OUTPUT_PORT.println("Failed to open directory");
|
||||
return;
|
||||
}
|
||||
if (!root.isDirectory()) {
|
||||
DBG_OUTPUT_PORT.println("Not a directory");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
while (file) {
|
||||
if (file.isDirectory()) {
|
||||
DBG_OUTPUT_PORT.print(" DIR : ");
|
||||
DBG_OUTPUT_PORT.println(file.name());
|
||||
if (levels) {
|
||||
listDir(fs, file.name(), levels - 1);
|
||||
}
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.print(" FILE: ");
|
||||
DBG_OUTPUT_PORT.print(file.name());
|
||||
DBG_OUTPUT_PORT.print(" SIZE: ");
|
||||
DBG_OUTPUT_PORT.println(file.size());
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void setup(void){
|
||||
DBG_OUTPUT_PORT.begin(115200);
|
||||
DBG_OUTPUT_PORT.print("\n");
|
||||
DBG_OUTPUT_PORT.setDebugOutput(true);
|
||||
SPIFFS.begin();
|
||||
{
|
||||
#ifdef ESP8266
|
||||
Dir dir = SPIFFS.openDir("/");
|
||||
while (dir.next()) {
|
||||
String fileName = dir.fileName();
|
||||
size_t fileSize = dir.fileSize();
|
||||
DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
|
||||
}
|
||||
#else
|
||||
listDir(SPIFFS, "/", 0);
|
||||
#endif
|
||||
DBG_OUTPUT_PORT.printf("\n");
|
||||
}
|
||||
|
||||
|
||||
//WIFI INIT
|
||||
DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid);
|
||||
if (String(WiFi.SSID()) != String(ssid)) {
|
||||
WiFi.begin(ssid, password);
|
||||
}
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
DBG_OUTPUT_PORT.print(".");
|
||||
}
|
||||
DBG_OUTPUT_PORT.println("");
|
||||
DBG_OUTPUT_PORT.print("Connected! IP address: ");
|
||||
DBG_OUTPUT_PORT.println(WiFi.localIP());
|
||||
|
||||
MDNS.begin(host);
|
||||
DBG_OUTPUT_PORT.print("Open http://");
|
||||
DBG_OUTPUT_PORT.print(host);
|
||||
DBG_OUTPUT_PORT.println(".local/edit to see the file browser");
|
||||
|
||||
|
||||
//SERVER INIT
|
||||
//list directory
|
||||
server.on("/list", HTTP_GET, handleFileList);
|
||||
//load editor
|
||||
server.on("/edit", HTTP_GET, [](){
|
||||
if(!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound");
|
||||
});
|
||||
//create file
|
||||
server.on("/edit", HTTP_PUT, handleFileCreate);
|
||||
//delete file
|
||||
server.on("/edit", HTTP_DELETE, handleFileDelete);
|
||||
//first callback is called after the request has ended with all parsed arguments
|
||||
//second callback handles file uploads at that location
|
||||
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload);
|
||||
|
||||
//called when the url is not defined here
|
||||
//use it to load content from SPIFFS
|
||||
server.onNotFound([](){
|
||||
if(!handleFileRead(server.uri()))
|
||||
server.send(404, "text/plain", "FileNotFound");
|
||||
});
|
||||
|
||||
//get heap status, analog input value and all GPIO statuses in one json call
|
||||
server.on("/all", HTTP_GET, [](){
|
||||
String json = "{";
|
||||
json += "\"heap\":"+String(ESP.getFreeHeap());
|
||||
json += ", \"analog\":"+String(analogRead(A0));
|
||||
#ifdef ESP8266
|
||||
json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
|
||||
#endif
|
||||
json += "}";
|
||||
server.send(200, "text/json", json);
|
||||
json = String();
|
||||
});
|
||||
server.begin();
|
||||
DBG_OUTPUT_PORT.println("HTTP server started");
|
||||
|
||||
}
|
||||
|
||||
void loop(void){
|
||||
server.handleClient();
|
||||
}
|
BIN
libraries/WebServer/examples/FSBrowser/data/edit.htm.gz
Normal file
BIN
libraries/WebServer/examples/FSBrowser/data/edit.htm.gz
Normal file
Binary file not shown.
BIN
libraries/WebServer/examples/FSBrowser/data/favicon.ico
Normal file
BIN
libraries/WebServer/examples/FSBrowser/data/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
libraries/WebServer/examples/FSBrowser/data/graphs.js.gz
Normal file
BIN
libraries/WebServer/examples/FSBrowser/data/graphs.js.gz
Normal file
Binary file not shown.
97
libraries/WebServer/examples/FSBrowser/data/index.htm
Normal file
97
libraries/WebServer/examples/FSBrowser/data/index.htm
Normal file
@ -0,0 +1,97 @@
|
||||
<!--
|
||||
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>ESP Monitor</title>
|
||||
<script type="text/javascript" src="graphs.js"></script>
|
||||
<script type="text/javascript">
|
||||
var heap,temp,digi;
|
||||
var reloadPeriod = 1000;
|
||||
var running = false;
|
||||
|
||||
function loadValues(){
|
||||
if(!running) return;
|
||||
var xh = new XMLHttpRequest();
|
||||
xh.onreadystatechange = function(){
|
||||
if (xh.readyState == 4){
|
||||
if(xh.status == 200) {
|
||||
var res = JSON.parse(xh.responseText);
|
||||
heap.add(res.heap);
|
||||
temp.add(res.analog);
|
||||
digi.add(res.gpio);
|
||||
if(running) setTimeout(loadValues, reloadPeriod);
|
||||
} else running = false;
|
||||
}
|
||||
};
|
||||
xh.open("GET", "/all", true);
|
||||
xh.send(null);
|
||||
};
|
||||
|
||||
function run(){
|
||||
if(!running){
|
||||
running = true;
|
||||
loadValues();
|
||||
}
|
||||
}
|
||||
|
||||
function onBodyLoad(){
|
||||
var refreshInput = document.getElementById("refresh-rate");
|
||||
refreshInput.value = reloadPeriod;
|
||||
refreshInput.onchange = function(e){
|
||||
var value = parseInt(e.target.value);
|
||||
reloadPeriod = (value > 0)?value:0;
|
||||
e.target.value = reloadPeriod;
|
||||
}
|
||||
var stopButton = document.getElementById("stop-button");
|
||||
stopButton.onclick = function(e){
|
||||
running = false;
|
||||
}
|
||||
var startButton = document.getElementById("start-button");
|
||||
startButton.onclick = function(e){
|
||||
run();
|
||||
}
|
||||
|
||||
// Example with 10K thermistor
|
||||
//function calcThermistor(v) {
|
||||
// var t = Math.log(((10230000 / v) - 10000));
|
||||
// t = (1/(0.001129148+(0.000234125*t)+(0.0000000876741*t*t*t)))-273.15;
|
||||
// return (t>120)?0:Math.round(t*10)/10;
|
||||
//}
|
||||
//temp = createGraph(document.getElementById("analog"), "Temperature", 100, 128, 10, 40, false, "cyan", calcThermistor);
|
||||
|
||||
temp = createGraph(document.getElementById("analog"), "Analog Input", 100, 128, 0, 1023, false, "cyan");
|
||||
heap = createGraph(document.getElementById("heap"), "Current Heap", 100, 125, 0, 30000, true, "orange");
|
||||
digi = createDigiGraph(document.getElementById("digital"), "GPIO", 100, 146, [0, 4, 5, 16], "gold");
|
||||
run();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body id="index" style="margin:0; padding:0;" onload="onBodyLoad()">
|
||||
<div id="controls" style="display: block; border: 1px solid rgb(68, 68, 68); padding: 5px; margin: 5px; width: 362px; background-color: rgb(238, 238, 238);">
|
||||
<label>Period (ms):</label>
|
||||
<input type="number" id="refresh-rate"/>
|
||||
<input type="button" id="start-button" value="Start"/>
|
||||
<input type="button" id="stop-button" value="Stop"/>
|
||||
</div>
|
||||
<div id="heap"></div>
|
||||
<div id="analog"></div>
|
||||
<div id="digital"></div>
|
||||
</body>
|
||||
</html>
|
91
libraries/WebServer/examples/HelloServer/HelloServer.ino
Normal file
91
libraries/WebServer/examples/HelloServer/HelloServer.ino
Normal file
@ -0,0 +1,91 @@
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
ESP8266WebServer server(80);
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WebServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
WebServer server(80);
|
||||
#endif
|
||||
|
||||
const char* ssid = "........";
|
||||
const char* password = "........";
|
||||
|
||||
#ifdef LED_BUILTIN
|
||||
const int led = LED_BUILTIN;
|
||||
#else
|
||||
const int led = 13;
|
||||
#endif
|
||||
|
||||
void handleRoot() {
|
||||
digitalWrite(led, 1);
|
||||
#ifdef ESP8266
|
||||
server.send(200, "text/plain", "hello from esp8266!");
|
||||
#else
|
||||
server.send(200, "text/plain", "hello from esp32!");
|
||||
#endif
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
|
||||
void handleNotFound(){
|
||||
digitalWrite(led, 1);
|
||||
String message = "File Not Found\n\n";
|
||||
message += "URI: ";
|
||||
message += server.uri();
|
||||
message += "\nMethod: ";
|
||||
message += (server.method() == HTTP_GET)?"GET":"POST";
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i=0; i<server.args(); i++){
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
server.send(404, "text/plain", message);
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
|
||||
void setup(void){
|
||||
pinMode(led, OUTPUT);
|
||||
digitalWrite(led, 0);
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("");
|
||||
|
||||
// Wait for connection
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("Connected to ");
|
||||
Serial.println(ssid);
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
#ifdef ESP8266
|
||||
if (MDNS.begin("esp8266")) {
|
||||
#else
|
||||
if (MDNS.begin("esp32")) {
|
||||
#endif
|
||||
Serial.println("MDNS responder started");
|
||||
}
|
||||
|
||||
server.on("/", handleRoot);
|
||||
|
||||
server.on("/inline", [](){
|
||||
server.send(200, "text/plain", "this works as well");
|
||||
});
|
||||
|
||||
server.onNotFound(handleNotFound);
|
||||
|
||||
server.begin();
|
||||
Serial.println("HTTP server started");
|
||||
}
|
||||
|
||||
void loop(void){
|
||||
server.handleClient();
|
||||
}
|
47
libraries/WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino
Normal file
47
libraries/WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino
Normal file
@ -0,0 +1,47 @@
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
ESP8266WebServer server(80);
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include <WebServer.h>
|
||||
WebServer server(80);
|
||||
#endif
|
||||
|
||||
const char* ssid = "........";
|
||||
const char* password = "........";
|
||||
|
||||
const char* www_username = "admin";
|
||||
const char* www_password = "esp8266esp32";
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
if(WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||
Serial.println("WiFi Connect Failed! Rebooting...");
|
||||
delay(1000);
|
||||
ESP.restart();
|
||||
}
|
||||
ArduinoOTA.begin();
|
||||
|
||||
server.on("/", [](){
|
||||
if(!server.authenticate(www_username, www_password))
|
||||
return server.requestAuthentication();
|
||||
server.send(200, "text/plain", "Login OK");
|
||||
});
|
||||
server.begin();
|
||||
|
||||
Serial.print("Open http://");
|
||||
Serial.print(WiFi.localIP());
|
||||
Serial.println("/ in your browser to see it working");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
ArduinoOTA.handle();
|
||||
server.handleClient();
|
||||
}
|
290
libraries/WebServer/examples/SDWebServer/SDWebServer.ino
Normal file
290
libraries/WebServer/examples/SDWebServer/SDWebServer.ino
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
SDWebServer - Example WebServer with SD Card backend for esp8266/esp32
|
||||
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the ESP8266/ESP32 WebServer 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
|
||||
|
||||
Have a FAT Formatted SD Card connected to the SPI port of the ESP8266
|
||||
The web root is the SD Card root folder
|
||||
File extensions with more than 3 charecters are not supported by the SD Library
|
||||
File Names longer than 8 charecters will be truncated by the SD library, so keep filenames shorter
|
||||
index.htm is the default index (works on subfolders as well)
|
||||
|
||||
upload the contents of SdRoot to the root of the SDcard and access the editor by going to http://esp8266sd.local/edit
|
||||
|
||||
*/
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
ESP8266WebServer server(80);
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WebServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
WebServer server(80);
|
||||
#endif
|
||||
|
||||
#define DBG_OUTPUT_PORT Serial
|
||||
|
||||
const char* ssid = "**********";
|
||||
const char* password = "**********";
|
||||
const char* host = "esp8266sd";
|
||||
|
||||
static bool hasSD = false;
|
||||
File uploadFile;
|
||||
|
||||
|
||||
void returnOK() {
|
||||
server.send(200, "text/plain", "");
|
||||
}
|
||||
|
||||
void returnFail(String msg) {
|
||||
server.send(500, "text/plain", msg + "\r\n");
|
||||
}
|
||||
|
||||
bool loadFromSdCard(String path){
|
||||
String dataType = "text/plain";
|
||||
if(path.endsWith("/")) path += "index.htm";
|
||||
|
||||
if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf("."));
|
||||
else if(path.endsWith(".htm")) dataType = "text/html";
|
||||
else if(path.endsWith(".css")) dataType = "text/css";
|
||||
else if(path.endsWith(".js")) dataType = "application/javascript";
|
||||
else if(path.endsWith(".png")) dataType = "image/png";
|
||||
else if(path.endsWith(".gif")) dataType = "image/gif";
|
||||
else if(path.endsWith(".jpg")) dataType = "image/jpeg";
|
||||
else if(path.endsWith(".ico")) dataType = "image/x-icon";
|
||||
else if(path.endsWith(".xml")) dataType = "text/xml";
|
||||
else if(path.endsWith(".pdf")) dataType = "application/pdf";
|
||||
else if(path.endsWith(".zip")) dataType = "application/zip";
|
||||
|
||||
File dataFile = SD.open(path.c_str());
|
||||
if(dataFile.isDirectory()){
|
||||
path += "/index.htm";
|
||||
dataType = "text/html";
|
||||
dataFile = SD.open(path.c_str());
|
||||
}
|
||||
|
||||
if (!dataFile)
|
||||
return false;
|
||||
|
||||
if (server.hasArg("download")) dataType = "application/octet-stream";
|
||||
|
||||
if (server.streamFile(dataFile, dataType) != dataFile.size()) {
|
||||
DBG_OUTPUT_PORT.println("Sent less data than expected!");
|
||||
}
|
||||
|
||||
dataFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void handleFileUpload(){
|
||||
if(server.uri() != "/edit") return;
|
||||
HTTPUpload& upload = server.upload();
|
||||
if(upload.status == UPLOAD_FILE_START){
|
||||
if(SD.exists((char *)upload.filename.c_str())) SD.remove((char *)upload.filename.c_str());
|
||||
uploadFile = SD.open(upload.filename.c_str(), FILE_WRITE);
|
||||
DBG_OUTPUT_PORT.print("Upload: START, filename: "); DBG_OUTPUT_PORT.println(upload.filename);
|
||||
} else if(upload.status == UPLOAD_FILE_WRITE){
|
||||
if(uploadFile) uploadFile.write(upload.buf, upload.currentSize);
|
||||
DBG_OUTPUT_PORT.print("Upload: WRITE, Bytes: "); DBG_OUTPUT_PORT.println(upload.currentSize);
|
||||
} else if(upload.status == UPLOAD_FILE_END){
|
||||
if(uploadFile) uploadFile.close();
|
||||
DBG_OUTPUT_PORT.print("Upload: END, Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
|
||||
}
|
||||
}
|
||||
|
||||
void deleteRecursive(String path){
|
||||
File file = SD.open((char *)path.c_str());
|
||||
if(!file.isDirectory()){
|
||||
file.close();
|
||||
SD.remove((char *)path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
file.rewindDirectory();
|
||||
while(true) {
|
||||
File entry = file.openNextFile();
|
||||
if (!entry) break;
|
||||
String entryPath = path + "/" +entry.name();
|
||||
if(entry.isDirectory()){
|
||||
entry.close();
|
||||
deleteRecursive(entryPath);
|
||||
} else {
|
||||
entry.close();
|
||||
SD.remove((char *)entryPath.c_str());
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
SD.rmdir((char *)path.c_str());
|
||||
file.close();
|
||||
}
|
||||
|
||||
void handleDelete(){
|
||||
if(server.args() == 0) return returnFail("BAD ARGS");
|
||||
String path = server.arg(0);
|
||||
if(path == "/" || !SD.exists((char *)path.c_str())) {
|
||||
returnFail("BAD PATH");
|
||||
return;
|
||||
}
|
||||
deleteRecursive(path);
|
||||
returnOK();
|
||||
}
|
||||
|
||||
void handleCreate(){
|
||||
if(server.args() == 0) return returnFail("BAD ARGS");
|
||||
String path = server.arg(0);
|
||||
if(path == "/" || SD.exists((char *)path.c_str())) {
|
||||
returnFail("BAD PATH");
|
||||
return;
|
||||
}
|
||||
|
||||
if(path.indexOf('.') > 0){
|
||||
File file = SD.open((char *)path.c_str(), FILE_WRITE);
|
||||
if(file){
|
||||
#ifdef ESP8266
|
||||
file.write((const char *)0);
|
||||
#else
|
||||
// TODO Create file with 0 bytes???
|
||||
file.write(NULL, 0);
|
||||
#endif
|
||||
file.close();
|
||||
}
|
||||
} else {
|
||||
SD.mkdir((char *)path.c_str());
|
||||
}
|
||||
returnOK();
|
||||
}
|
||||
|
||||
void printDirectory() {
|
||||
if(!server.hasArg("dir")) return returnFail("BAD ARGS");
|
||||
String path = server.arg("dir");
|
||||
if(path != "/" && !SD.exists((char *)path.c_str())) return returnFail("BAD PATH");
|
||||
File dir = SD.open((char *)path.c_str());
|
||||
path = String();
|
||||
if(!dir.isDirectory()){
|
||||
dir.close();
|
||||
return returnFail("NOT DIR");
|
||||
}
|
||||
dir.rewindDirectory();
|
||||
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
server.send(200, "text/json", "");
|
||||
WiFiClient client = server.client();
|
||||
|
||||
server.sendContent("[");
|
||||
for (int cnt = 0; true; ++cnt) {
|
||||
File entry = dir.openNextFile();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
String output;
|
||||
if (cnt > 0)
|
||||
output = ',';
|
||||
|
||||
output += "{\"type\":\"";
|
||||
output += (entry.isDirectory()) ? "dir" : "file";
|
||||
output += "\",\"name\":\"";
|
||||
#ifdef ESP8266
|
||||
output += entry.name();
|
||||
#else
|
||||
// Ignore '/' prefix
|
||||
output += entry.name()+1;
|
||||
#endif
|
||||
output += "\"";
|
||||
output += "}";
|
||||
server.sendContent(output);
|
||||
entry.close();
|
||||
}
|
||||
server.sendContent("]");
|
||||
// Send zero length chunk to terminate the HTTP body
|
||||
server.sendContent("");
|
||||
dir.close();
|
||||
}
|
||||
|
||||
void handleNotFound(){
|
||||
if(hasSD && loadFromSdCard(server.uri())) return;
|
||||
String message = "SDCARD Not Detected\n\n";
|
||||
message += "URI: ";
|
||||
message += server.uri();
|
||||
message += "\nMethod: ";
|
||||
message += (server.method() == HTTP_GET)?"GET":"POST";
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i=0; i<server.args(); i++){
|
||||
message += " NAME:"+server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
|
||||
}
|
||||
server.send(404, "text/plain", message);
|
||||
DBG_OUTPUT_PORT.print(message);
|
||||
}
|
||||
|
||||
void setup(void){
|
||||
DBG_OUTPUT_PORT.begin(115200);
|
||||
DBG_OUTPUT_PORT.setDebugOutput(true);
|
||||
DBG_OUTPUT_PORT.print("\n");
|
||||
WiFi.begin(ssid, password);
|
||||
DBG_OUTPUT_PORT.print("Connecting to ");
|
||||
DBG_OUTPUT_PORT.println(ssid);
|
||||
|
||||
// Wait for connection
|
||||
uint8_t i = 0;
|
||||
while (WiFi.status() != WL_CONNECTED && i++ < 20) {//wait 10 seconds
|
||||
delay(500);
|
||||
}
|
||||
if(i == 21){
|
||||
DBG_OUTPUT_PORT.print("Could not connect to ");
|
||||
DBG_OUTPUT_PORT.println(ssid);
|
||||
while(1) delay(500);
|
||||
}
|
||||
DBG_OUTPUT_PORT.print("Connected! IP address: ");
|
||||
DBG_OUTPUT_PORT.println(WiFi.localIP());
|
||||
|
||||
if (MDNS.begin(host)) {
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
DBG_OUTPUT_PORT.println("MDNS responder started");
|
||||
DBG_OUTPUT_PORT.print("You can now connect to http://");
|
||||
DBG_OUTPUT_PORT.print(host);
|
||||
DBG_OUTPUT_PORT.println(".local");
|
||||
}
|
||||
|
||||
|
||||
server.on("/list", HTTP_GET, printDirectory);
|
||||
server.on("/edit", HTTP_DELETE, handleDelete);
|
||||
server.on("/edit", HTTP_PUT, handleCreate);
|
||||
server.on("/edit", HTTP_POST, [](){ returnOK(); }, handleFileUpload);
|
||||
server.onNotFound(handleNotFound);
|
||||
|
||||
server.begin();
|
||||
DBG_OUTPUT_PORT.println("HTTP server started");
|
||||
|
||||
if (SD.begin(SS)){
|
||||
DBG_OUTPUT_PORT.println("SD Card initialized.");
|
||||
hasSD = true;
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void){
|
||||
server.handleClient();
|
||||
}
|
674
libraries/WebServer/examples/SDWebServer/SdRoot/edit/index.htm
Normal file
674
libraries/WebServer/examples/SDWebServer/SdRoot/edit/index.htm
Normal file
@ -0,0 +1,674 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>SD Editor</title>
|
||||
<style type="text/css" media="screen">
|
||||
.contextMenu {
|
||||
z-index: 300;
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
border: 1px solid #444;
|
||||
background-color: #F5F5F5;
|
||||
display: none;
|
||||
box-shadow: 0 0 10px rgba( 0, 0, 0, .4 );
|
||||
font-size: 12px;
|
||||
font-family: sans-serif;
|
||||
font-weight:bold;
|
||||
}
|
||||
.contextMenu ul {
|
||||
list-style: none;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.contextMenu li {
|
||||
position: relative;
|
||||
min-width: 60px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.contextMenu span {
|
||||
color: #444;
|
||||
display: inline-block;
|
||||
padding: 6px;
|
||||
}
|
||||
.contextMenu li:hover { background: #444; }
|
||||
.contextMenu li:hover span { color: #EEE; }
|
||||
|
||||
.css-treeview ul, .css-treeview li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.css-treeview input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.css-treeview {
|
||||
font: normal 11px Verdana, Arial, Sans-serif;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.css-treeview span {
|
||||
color: #00f;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.css-treeview span:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.css-treeview input + label + ul {
|
||||
margin: 0 0 0 22px;
|
||||
}
|
||||
|
||||
.css-treeview input ~ ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.css-treeview label, .css-treeview label::before {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.css-treeview input:disabled + label {
|
||||
cursor: default;
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.css-treeview input:checked:not(:disabled) ~ ul {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.css-treeview label, .css-treeview label::before {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAACgCAYAAAAFOewUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApxJREFUeNrslM1u00AQgGdthyalFFOK+ClIIKQKyqUVQvTEE3DmAhLwAhU8QZoH4A2Q2gMSFace4MCtJ8SPBFwAkRuiHKpA6sRN/Lu7zG5i14kctaUqRGhGXnu9O/Pt7MzsMiklvF+9t2kWTDvyIrAsA0aKRRi1T0C/hJ4LUbt5/8rNpWVlp8RSr9J40b48fxFaTQ9+ft8EZ6MJYb0Ok+dnYGpmPgXwKIAvLx8vYXc5GdMAQJgQEkpjRTh36TS2U+DWW/D17WuYgm8pwJyY1npZsZKOxImOV1I/h4+O6vEg5GCZBpgmA6hX8wHKUHDRBXQYicQ4rlc3Tf0VMs8DHBS864F2YFspjgUYjKX/Az3gsdQd2eeBHwmdGWXHcgBGSkZXOXohcEXebRoQcAgjqediNY+AVyu3Z3sAKqfKoGMsewBeEIOPgQxxPJIjcGH6qtL/0AdADzKGnuuD+2tLK7Q8DhHHbOBW+KEzcHLuYc82MkEUekLiwuvVH+guQBQzOG4XdAb8EOcRcqQvDkY2iCLuxECJ43JobMXoutqGgDa2T7UqLKwt9KRyuxKVByqVXXqIoCCUCAqhUOioTWC7G4TQEOD0APy2/7G2Xpu1J4+lxeQ4TXBbITDpoVelRN/BVFbwu5oMMJUBhoXy5tmdRcMwymP2OLQaLjx9/vnBo6V3K6izATmSnMa0Dq7ferIohJhr1p01zrlz49rZF4OMs8JkX23vVQzYp+wbYGV/KpXKjvspl8tsIKCrMNAYFxj2GKS5ZWxg4ewKsJfaGMIY5KXqPz8LBBj6+yDvVP79+yDp/9F9oIx3OisHWwe7Oal0HxCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgwD8E/BZgAP0qhKj3rXO7AAAAAElFTkSuQmCC") no-repeat;
|
||||
}
|
||||
|
||||
.css-treeview label, .css-treeview span, .css-treeview label::before {
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.css-treeview label {
|
||||
background-position: 18px 0;
|
||||
}
|
||||
|
||||
.css-treeview label::before {
|
||||
content: "";
|
||||
width: 16px;
|
||||
margin: 0 22px 0 0;
|
||||
vertical-align: middle;
|
||||
background-position: 0 -32px;
|
||||
}
|
||||
|
||||
.css-treeview input:checked + label::before {
|
||||
background-position: 0 -16px;
|
||||
}
|
||||
|
||||
/* webkit adjacent element selector bugfix */
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0)
|
||||
{
|
||||
.css-treeview{
|
||||
-webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes webkit-adjacent-element-selector-bugfix
|
||||
{
|
||||
from {
|
||||
padding: 0;
|
||||
}
|
||||
to {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#uploader {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height:28px;
|
||||
line-height: 24px;
|
||||
padding-left: 10px;
|
||||
background-color: #444;
|
||||
color:#EEE;
|
||||
}
|
||||
#tree {
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width:200px;
|
||||
padding: 8px;
|
||||
}
|
||||
#editor, #preview {
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 200px;
|
||||
}
|
||||
#preview {
|
||||
background-color: #EEE;
|
||||
padding:5px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function createFileUploader(element, tree, editor){
|
||||
var xmlHttp;
|
||||
var input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.multiple = false;
|
||||
input.name = "data";
|
||||
document.getElementById(element).appendChild(input);
|
||||
var path = document.createElement("input");
|
||||
path.id = "upload-path";
|
||||
path.type = "text";
|
||||
path.name = "path";
|
||||
path.defaultValue = "/";
|
||||
document.getElementById(element).appendChild(path);
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = 'Upload';
|
||||
document.getElementById(element).appendChild(button);
|
||||
var mkdir = document.createElement("button");
|
||||
mkdir.innerHTML = 'MkDir';
|
||||
document.getElementById(element).appendChild(mkdir);
|
||||
var mkfile = document.createElement("button");
|
||||
mkfile.innerHTML = 'MkFile';
|
||||
document.getElementById(element).appendChild(mkfile);
|
||||
|
||||
function httpPostProcessRequest(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||
else {
|
||||
tree.refreshPath(path.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
function createPath(p){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||
var formData = new FormData();
|
||||
formData.append("path", p);
|
||||
xmlHttp.open("PUT", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
|
||||
mkfile.onclick = function(e){
|
||||
if(path.value.indexOf(".") === -1) return;
|
||||
createPath(path.value);
|
||||
editor.loadUrl(path.value);
|
||||
};
|
||||
mkdir.onclick = function(e){
|
||||
if(path.value.length < 2) return;
|
||||
var dir = path.value
|
||||
if(dir.indexOf(".") !== -1){
|
||||
if(dir.lastIndexOf("/") === 0) return;
|
||||
dir = dir.substring(0, dir.lastIndexOf("/"));
|
||||
}
|
||||
createPath(dir);
|
||||
};
|
||||
button.onclick = function(e){
|
||||
if(input.files.length === 0){
|
||||
return;
|
||||
}
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||
var formData = new FormData();
|
||||
formData.append("data", input.files[0], path.value);
|
||||
xmlHttp.open("POST", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
input.onchange = function(e){
|
||||
if(input.files.length === 0) return;
|
||||
var filename = input.files[0].name;
|
||||
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||
var name = /(.*)\.[^.]+$/.exec(filename)[1];
|
||||
if(typeof name !== undefined){
|
||||
if(name.length > 8) name = name.substring(0, 8);
|
||||
filename = name;
|
||||
}
|
||||
if(typeof ext !== undefined){
|
||||
if(ext === "html") ext = "htm";
|
||||
else if(ext === "jpeg") ext = "jpg";
|
||||
filename = filename + "." + ext;
|
||||
}
|
||||
if(path.value === "/" || path.value.lastIndexOf("/") === 0){
|
||||
path.value = "/"+filename;
|
||||
} else {
|
||||
path.value = path.value.substring(0, path.value.lastIndexOf("/")+1)+filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createTree(element, editor){
|
||||
var preview = document.getElementById("preview");
|
||||
var treeRoot = document.createElement("div");
|
||||
treeRoot.className = "css-treeview";
|
||||
document.getElementById(element).appendChild(treeRoot);
|
||||
|
||||
function loadDownload(path){
|
||||
document.getElementById('download-frame').src = path+"?download=true";
|
||||
}
|
||||
|
||||
function loadPreview(path){
|
||||
document.getElementById("editor").style.display = "none";
|
||||
preview.style.display = "block";
|
||||
preview.innerHTML = '<img src="'+path+'" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
|
||||
}
|
||||
|
||||
function fillFolderMenu(el, path){
|
||||
var list = document.createElement("ul");
|
||||
el.appendChild(list);
|
||||
var action = document.createElement("li");
|
||||
list.appendChild(action);
|
||||
var isChecked = document.getElementById(path).checked;
|
||||
var expnd = document.createElement("li");
|
||||
list.appendChild(expnd);
|
||||
if(isChecked){
|
||||
expnd.innerHTML = "<span>Collapse</span>";
|
||||
expnd.onclick = function(e){
|
||||
document.getElementById(path).checked = false;
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
var refrsh = document.createElement("li");
|
||||
list.appendChild(refrsh);
|
||||
refrsh.innerHTML = "<span>Refresh</span>";
|
||||
refrsh.onclick = function(e){
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
} else {
|
||||
expnd.innerHTML = "<span>Expand</span>";
|
||||
expnd.onclick = function(e){
|
||||
document.getElementById(path).checked = true;
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
var upload = document.createElement("li");
|
||||
list.appendChild(upload);
|
||||
upload.innerHTML = "<span>Upload</span>";
|
||||
upload.onclick = function(e){
|
||||
var pathEl = document.getElementById("upload-path");
|
||||
if(pathEl){
|
||||
var subPath = pathEl.value;
|
||||
if(subPath.lastIndexOf("/") < 1) pathEl.value = path+subPath;
|
||||
else pathEl.value = path.substring(subPath.lastIndexOf("/"))+subPath;
|
||||
}
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
var delFile = document.createElement("li");
|
||||
list.appendChild(delFile);
|
||||
delFile.innerHTML = "<span>Delete</span>";
|
||||
delFile.onclick = function(e){
|
||||
httpDelete(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
|
||||
function fillFileMenu(el, path){
|
||||
var list = document.createElement("ul");
|
||||
el.appendChild(list);
|
||||
var action = document.createElement("li");
|
||||
list.appendChild(action);
|
||||
if(isTextFile(path)){
|
||||
action.innerHTML = "<span>Edit</span>";
|
||||
action.onclick = function(e){
|
||||
editor.loadUrl(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
} else if(isImageFile(path)){
|
||||
action.innerHTML = "<span>Preview</span>";
|
||||
action.onclick = function(e){
|
||||
loadPreview(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
var download = document.createElement("li");
|
||||
list.appendChild(download);
|
||||
download.innerHTML = "<span>Download</span>";
|
||||
download.onclick = function(e){
|
||||
loadDownload(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
var delFile = document.createElement("li");
|
||||
list.appendChild(delFile);
|
||||
delFile.innerHTML = "<span>Delete</span>";
|
||||
delFile.onclick = function(e){
|
||||
httpDelete(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
|
||||
function showContextMenu(e, path, isfile){
|
||||
var divContext = document.createElement("div");
|
||||
var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
|
||||
var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
|
||||
var left = e.clientX + scrollLeft;
|
||||
var top = e.clientY + scrollTop;
|
||||
divContext.className = 'contextMenu';
|
||||
divContext.style.display = 'block';
|
||||
divContext.style.left = left + 'px';
|
||||
divContext.style.top = top + 'px';
|
||||
if(isfile) fillFileMenu(divContext, path);
|
||||
else fillFolderMenu(divContext, path);
|
||||
document.body.appendChild(divContext);
|
||||
var width = divContext.offsetWidth;
|
||||
var height = divContext.offsetHeight;
|
||||
divContext.onmouseout = function(e){
|
||||
if(e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)){
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(divContext);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createTreeLeaf(path, name, size){
|
||||
var leaf = document.createElement("li");
|
||||
leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||
var label = document.createElement("span");
|
||||
label.textContent = name.toLowerCase();
|
||||
leaf.appendChild(label);
|
||||
leaf.onclick = function(e){
|
||||
if(isTextFile(leaf.id)){
|
||||
editor.loadUrl(leaf.id);
|
||||
} else if(isImageFile(leaf.id)){
|
||||
loadPreview(leaf.id);
|
||||
}
|
||||
};
|
||||
leaf.oncontextmenu = function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
showContextMenu(e, leaf.id, true);
|
||||
};
|
||||
return leaf;
|
||||
}
|
||||
|
||||
function createTreeBranch(path, name, disabled){
|
||||
var leaf = document.createElement("li");
|
||||
var check = document.createElement("input");
|
||||
check.type = "checkbox";
|
||||
check.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||
if(typeof disabled !== "undefined" && disabled) check.disabled = "disabled";
|
||||
leaf.appendChild(check);
|
||||
var label = document.createElement("label");
|
||||
label.for = check.id;
|
||||
label.textContent = name.toLowerCase();
|
||||
leaf.appendChild(label);
|
||||
check.onchange = function(e){
|
||||
if(check.checked){
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, check.id);
|
||||
}
|
||||
};
|
||||
label.onclick = function(e){
|
||||
if(!check.checked){
|
||||
check.checked = true;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, check.id);
|
||||
} else {
|
||||
check.checked = false;
|
||||
}
|
||||
};
|
||||
leaf.oncontextmenu = function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
showContextMenu(e, check.id, false);
|
||||
}
|
||||
return leaf;
|
||||
}
|
||||
|
||||
function addList(parent, path, items){
|
||||
var list = document.createElement("ul");
|
||||
parent.appendChild(list);
|
||||
var ll = items.length;
|
||||
for(var i = 0; i < ll; i++){
|
||||
var item = items[i];
|
||||
var itemEl;
|
||||
if(item.type === "file"){
|
||||
itemEl = createTreeLeaf(path, item.name, item.size);
|
||||
} else {
|
||||
itemEl = createTreeBranch(path, item.name);
|
||||
}
|
||||
list.appendChild(itemEl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function isTextFile(path){
|
||||
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||
if(typeof ext !== undefined){
|
||||
switch(ext){
|
||||
case "txt":
|
||||
case "htm":
|
||||
case "html":
|
||||
case "js":
|
||||
case "json":
|
||||
case "c":
|
||||
case "h":
|
||||
case "cpp":
|
||||
case "css":
|
||||
case "xml":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isImageFile(path){
|
||||
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||
if(typeof ext !== undefined){
|
||||
switch(ext){
|
||||
case "png":
|
||||
case "jpg":
|
||||
case "gif":
|
||||
case "ico":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.refreshPath = function(path){
|
||||
if(path.lastIndexOf('/') < 1){
|
||||
path = '/';
|
||||
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||
httpGet(treeRoot, "/");
|
||||
} else {
|
||||
path = path.substring(0, path.lastIndexOf('/'));
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
}
|
||||
};
|
||||
|
||||
function delCb(path){
|
||||
return function(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
if(xmlHttp.status != 200){
|
||||
alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||
} else {
|
||||
if(path.lastIndexOf('/') < 1){
|
||||
path = '/';
|
||||
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||
httpGet(treeRoot, "/");
|
||||
} else {
|
||||
path = path.substring(0, path.lastIndexOf('/'));
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function httpDelete(filename){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = delCb(filename);
|
||||
var formData = new FormData();
|
||||
formData.append("path", filename);
|
||||
xmlHttp.open("DELETE", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
|
||||
function getCb(parent, path){
|
||||
return function(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
//clear loading
|
||||
if(xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function httpGet(parent, path){
|
||||
xmlHttp = new XMLHttpRequest(parent, path);
|
||||
xmlHttp.onreadystatechange = getCb(parent, path);
|
||||
xmlHttp.open("GET", "/list?dir="+path, true);
|
||||
xmlHttp.send(null);
|
||||
//start loading
|
||||
}
|
||||
|
||||
httpGet(treeRoot, "/");
|
||||
return this;
|
||||
}
|
||||
|
||||
function createEditor(element, file, lang, theme, type){
|
||||
function getLangFromFilename(filename){
|
||||
var lang = "plain";
|
||||
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||
if(typeof ext !== undefined){
|
||||
switch(ext){
|
||||
case "txt": lang = "plain"; break;
|
||||
case "htm": lang = "html"; break;
|
||||
case "js": lang = "javascript"; break;
|
||||
case "c": lang = "c_cpp"; break;
|
||||
case "cpp": lang = "c_cpp"; break;
|
||||
case "css":
|
||||
case "scss":
|
||||
case "php":
|
||||
case "html":
|
||||
case "json":
|
||||
case "xml":
|
||||
lang = ext;
|
||||
}
|
||||
}
|
||||
return lang;
|
||||
}
|
||||
|
||||
if(typeof file === "undefined") file = "/index.htm";
|
||||
|
||||
if(typeof lang === "undefined"){
|
||||
lang = getLangFromFilename(file);
|
||||
}
|
||||
|
||||
if(typeof theme === "undefined") theme = "textmate";
|
||||
|
||||
if(typeof type === "undefined"){
|
||||
type = "text/"+lang;
|
||||
if(lang === "c_cpp") type = "text/plain";
|
||||
}
|
||||
|
||||
var xmlHttp = null;
|
||||
var editor = ace.edit(element);
|
||||
|
||||
//post
|
||||
function httpPostProcessRequest(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||
}
|
||||
}
|
||||
function httpPost(filename, data, type){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||
var formData = new FormData();
|
||||
formData.append("data", new Blob([data], { type: type }), filename);
|
||||
xmlHttp.open("POST", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
//get
|
||||
function httpGetProcessRequest(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
document.getElementById("preview").style.display = "none";
|
||||
document.getElementById("editor").style.display = "block";
|
||||
if(xmlHttp.status == 200) editor.setValue(xmlHttp.responseText);
|
||||
else editor.setValue("");
|
||||
editor.clearSelection();
|
||||
}
|
||||
}
|
||||
function httpGet(theUrl){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpGetProcessRequest;
|
||||
xmlHttp.open("GET", theUrl, true);
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
|
||||
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
|
||||
editor.setTheme("ace/theme/"+theme);
|
||||
editor.$blockScrolling = Infinity;
|
||||
editor.getSession().setUseSoftTabs(true);
|
||||
editor.getSession().setTabSize(2);
|
||||
editor.setHighlightActiveLine(true);
|
||||
editor.setShowPrintMargin(false);
|
||||
editor.commands.addCommand({
|
||||
name: 'saveCommand',
|
||||
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
|
||||
exec: function(editor) {
|
||||
httpPost(file, editor.getValue()+"", type);
|
||||
},
|
||||
readOnly: false
|
||||
});
|
||||
editor.commands.addCommand({
|
||||
name: 'undoCommand',
|
||||
bindKey: {win: 'Ctrl-Z', mac: 'Command-Z'},
|
||||
exec: function(editor) {
|
||||
editor.getSession().getUndoManager().undo(false);
|
||||
},
|
||||
readOnly: false
|
||||
});
|
||||
editor.commands.addCommand({
|
||||
name: 'redoCommand',
|
||||
bindKey: {win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z'},
|
||||
exec: function(editor) {
|
||||
editor.getSession().getUndoManager().redo(false);
|
||||
},
|
||||
readOnly: false
|
||||
});
|
||||
httpGet(file);
|
||||
editor.loadUrl = function(filename){
|
||||
file = filename;
|
||||
lang = getLangFromFilename(file);
|
||||
type = "text/"+lang;
|
||||
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
|
||||
httpGet(file);
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
function onBodyLoad(){
|
||||
var vars = {};
|
||||
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
|
||||
var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
|
||||
var tree = createTree("tree", editor);
|
||||
createFileUploader("uploader", tree, editor);
|
||||
};
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
</head>
|
||||
<body onload="onBodyLoad();">
|
||||
<div id="uploader"></div>
|
||||
<div id="tree"></div>
|
||||
<div id="editor"></div>
|
||||
<div id="preview" style="display:none;"></div>
|
||||
<iframe id=download-frame style='display:none;'></iframe>
|
||||
</body>
|
||||
</html>
|
22
libraries/WebServer/examples/SDWebServer/SdRoot/index.htm
Normal file
22
libraries/WebServer/examples/SDWebServer/SdRoot/index.htm
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<title>ESP Index</title>
|
||||
<style>
|
||||
body {
|
||||
background-color:black;
|
||||
color:white;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function onBodyLoad(){
|
||||
console.log("we are loaded!!");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body id="index" onload="onBodyLoad()">
|
||||
<h1>ESP8266 Pin Functions</h1>
|
||||
<img src="pins.png" />
|
||||
</body>
|
||||
</html>
|
BIN
libraries/WebServer/examples/SDWebServer/SdRoot/pins.png
Normal file
BIN
libraries/WebServer/examples/SDWebServer/SdRoot/pins.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 KiB |
@ -0,0 +1,137 @@
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
ESP8266WebServer server(80);
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WebServer.h>
|
||||
WebServer server(80);
|
||||
#endif
|
||||
|
||||
const char* ssid = "........";
|
||||
const char* password = "........";
|
||||
|
||||
//Check if header is present and correct
|
||||
bool is_authentified(){
|
||||
Serial.println("Enter is_authentified");
|
||||
if (server.hasHeader("Cookie")){
|
||||
Serial.print("Found cookie: ");
|
||||
String cookie = server.header("Cookie");
|
||||
Serial.println(cookie);
|
||||
if (cookie.indexOf("ESPSESSIONID=1") != -1) {
|
||||
Serial.println("Authentification Successful");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Serial.println("Authentification Failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
//login page, also called for disconnect
|
||||
void handleLogin(){
|
||||
String msg;
|
||||
if (server.hasHeader("Cookie")){
|
||||
Serial.print("Found cookie: ");
|
||||
String cookie = server.header("Cookie");
|
||||
Serial.println(cookie);
|
||||
}
|
||||
if (server.hasArg("DISCONNECT")){
|
||||
Serial.println("Disconnection");
|
||||
server.sendHeader("Location","/login");
|
||||
server.sendHeader("Cache-Control","no-cache");
|
||||
server.sendHeader("Set-Cookie","ESPSESSIONID=0");
|
||||
server.send(301);
|
||||
return;
|
||||
}
|
||||
if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")){
|
||||
if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin" ){
|
||||
server.sendHeader("Location","/");
|
||||
server.sendHeader("Cache-Control","no-cache");
|
||||
server.sendHeader("Set-Cookie","ESPSESSIONID=1");
|
||||
server.send(301);
|
||||
Serial.println("Log in Successful");
|
||||
return;
|
||||
}
|
||||
msg = "Wrong username/password! try again.";
|
||||
Serial.println("Log in Failed");
|
||||
}
|
||||
String content = "<html><body><form action='/login' method='POST'>To log in, please use : admin/admin<br>";
|
||||
content += "User:<input type='text' name='USERNAME' placeholder='user name'><br>";
|
||||
content += "Password:<input type='password' name='PASSWORD' placeholder='password'><br>";
|
||||
content += "<input type='submit' name='SUBMIT' value='Submit'></form>" + msg + "<br>";
|
||||
content += "You also can go <a href='/inline'>here</a></body></html>";
|
||||
server.send(200, "text/html", content);
|
||||
}
|
||||
|
||||
//root page can be accessed only if authentification is ok
|
||||
void handleRoot(){
|
||||
Serial.println("Enter handleRoot");
|
||||
String header;
|
||||
if (!is_authentified()){
|
||||
server.sendHeader("Location","/login");
|
||||
server.sendHeader("Cache-Control","no-cache");
|
||||
server.send(301);
|
||||
return;
|
||||
}
|
||||
String content = "<html><body><H2>hello, you successfully connected to esp8266/esp32!</H2><br>";
|
||||
if (server.hasHeader("User-Agent")){
|
||||
content += "the user agent used is : " + server.header("User-Agent") + "<br><br>";
|
||||
}
|
||||
content += "You can access this page until you <a href=\"/login?DISCONNECT=YES\">disconnect</a></body></html>";
|
||||
server.send(200, "text/html", content);
|
||||
}
|
||||
|
||||
//no need authentification
|
||||
void handleNotFound(){
|
||||
String message = "File Not Found\n\n";
|
||||
message += "URI: ";
|
||||
message += server.uri();
|
||||
message += "\nMethod: ";
|
||||
message += (server.method() == HTTP_GET)?"GET":"POST";
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i=0; i<server.args(); i++){
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
server.send(404, "text/plain", message);
|
||||
}
|
||||
|
||||
void setup(void){
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("");
|
||||
|
||||
// Wait for connection
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("Connected to ");
|
||||
Serial.println(ssid);
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
|
||||
server.on("/", handleRoot);
|
||||
server.on("/login", handleLogin);
|
||||
server.on("/inline", [](){
|
||||
server.send(200, "text/plain", "this works without need of authentification");
|
||||
});
|
||||
|
||||
server.onNotFound(handleNotFound);
|
||||
//here the list of headers to be recorded
|
||||
const char * headerkeys[] = {"User-Agent","Cookie"} ;
|
||||
size_t headerkeyssize = sizeof(headerkeys)/sizeof(char*);
|
||||
//ask server to track these headers
|
||||
server.collectHeaders(headerkeys, headerkeyssize );
|
||||
server.begin();
|
||||
Serial.println("HTTP server started");
|
||||
}
|
||||
|
||||
void loop(void){
|
||||
server.handleClient();
|
||||
}
|
78
libraries/WebServer/examples/WebUpdate/WebUpdate.ino
Normal file
78
libraries/WebServer/examples/WebUpdate/WebUpdate.ino
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
To upload through terminal you can use: curl -F "image=@firmware.bin" esp8266-webupdate.local/update
|
||||
*/
|
||||
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
ESP8266WebServer server(80);
|
||||
const char* host = "esp8266-webupdate";
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WebServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
WebServer server(80);
|
||||
const char* host = "esp32-webupdate";
|
||||
#endif
|
||||
|
||||
const char* ssid = "........";
|
||||
const char* password = "........";
|
||||
|
||||
const char* serverIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";
|
||||
|
||||
void setup(void){
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println("Booting Sketch...");
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
if(WiFi.waitForConnectResult() == WL_CONNECTED){
|
||||
MDNS.begin(host);
|
||||
server.on("/", HTTP_GET, [](){
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/html", serverIndex);
|
||||
});
|
||||
server.on("/update", HTTP_POST, [](){
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK");
|
||||
ESP.restart();
|
||||
},[](){
|
||||
HTTPUpload& upload = server.upload();
|
||||
if(upload.status == UPLOAD_FILE_START){
|
||||
Serial.setDebugOutput(true);
|
||||
WiFiUDP::stopAll();
|
||||
Serial.printf("Update: %s\n", upload.filename.c_str());
|
||||
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
|
||||
if(!Update.begin(maxSketchSpace)){//start with max available size
|
||||
Update.printError(Serial);
|
||||
}
|
||||
} else if(upload.status == UPLOAD_FILE_WRITE){
|
||||
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){
|
||||
Update.printError(Serial);
|
||||
}
|
||||
} else if(upload.status == UPLOAD_FILE_END){
|
||||
if(Update.end(true)){ //true to set the size to the current progress
|
||||
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
|
||||
} else {
|
||||
Update.printError(Serial);
|
||||
}
|
||||
Serial.setDebugOutput(false);
|
||||
}
|
||||
yield();
|
||||
});
|
||||
server.begin();
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
|
||||
Serial.printf("Ready! Open http://%s.local in your browser\n", host);
|
||||
} else {
|
||||
Serial.println("WiFi Failed");
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void){
|
||||
server.handleClient();
|
||||
delay(1);
|
||||
}
|
36
libraries/WebServer/keywords.txt
Normal file
36
libraries/WebServer/keywords.txt
Normal file
@ -0,0 +1,36 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Ultrasound
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
ESP8266WebServer KEYWORD1
|
||||
HTTPMethod KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
handleClient KEYWORD2
|
||||
on KEYWORD2
|
||||
addHandler KEYWORD2
|
||||
uri KEYWORD2
|
||||
method KEYWORD2
|
||||
client KEYWORD2
|
||||
send KEYWORD2
|
||||
arg KEYWORD2
|
||||
argName KEYWORD2
|
||||
args KEYWORD2
|
||||
hasArg KEYWORD2
|
||||
onNotFound KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
HTTP_GET LITERAL1
|
||||
HTTP_POST LITERAL1
|
||||
HTTP_ANY LITERAL1
|
9
libraries/WebServer/library.properties
Normal file
9
libraries/WebServer/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=WebServer
|
||||
version=1.0
|
||||
author=Ivan Grokhotkov
|
||||
maintainer=Ivan Grokhtkov <ivan@esp8266.com>
|
||||
sentence=Simple web server library
|
||||
paragraph=The library supports HTTP GET and POST requests, provides argument parsing, handles one client at a time.
|
||||
category=Communication
|
||||
url=
|
||||
architectures=esp8266,esp32
|
29
libraries/WebServer/src/ESP8266WebServer.h
Normal file
29
libraries/WebServer/src/ESP8266WebServer.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
ESP8266WebServer.h - Dead simple web-server.
|
||||
Supports only one simultaneous client, knows how to handle GET and POST.
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ESP8266WEBSERVER_H
|
||||
#define ESP8266WEBSERVER_H
|
||||
|
||||
#include <WebServer.h>
|
||||
|
||||
#endif //ESP8266WEBSERVER_H
|
610
libraries/WebServer/src/Parsing.cpp
Normal file
610
libraries/WebServer/src/Parsing.cpp
Normal file
@ -0,0 +1,610 @@
|
||||
/*
|
||||
Parsing.cpp - HTTP request parsing.
|
||||
|
||||
Copyright (c) 2015 Ivan Grokhotkov. 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
|
||||
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "WiFiServer.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "WebServer.h"
|
||||
|
||||
//#define DEBUG_ESP_HTTP_SERVER
|
||||
#ifdef DEBUG_ESP_PORT
|
||||
#define DEBUG_OUTPUT DEBUG_ESP_PORT
|
||||
#else
|
||||
#define DEBUG_OUTPUT Serial
|
||||
#endif
|
||||
|
||||
static char* readBytesWithTimeout(WiFiClient& client, size_t maxLength, size_t& dataLength, int timeout_ms)
|
||||
{
|
||||
char *buf = nullptr;
|
||||
dataLength = 0;
|
||||
while (dataLength < maxLength) {
|
||||
int tries = timeout_ms;
|
||||
size_t newLength;
|
||||
while (!(newLength = client.available()) && tries--) delay(1);
|
||||
if (!newLength) {
|
||||
break;
|
||||
}
|
||||
if (!buf) {
|
||||
buf = (char *) malloc(newLength + 1);
|
||||
if (!buf) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
char* newBuf = (char *) realloc(buf, dataLength + newLength + 1);
|
||||
if (!newBuf) {
|
||||
free(buf);
|
||||
return nullptr;
|
||||
}
|
||||
buf = newBuf;
|
||||
}
|
||||
client.readBytes(buf + dataLength, newLength);
|
||||
dataLength += newLength;
|
||||
buf[dataLength] = '\0';
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool WebServer::_parseRequest(WiFiClient& client) {
|
||||
// Read the first line of HTTP request
|
||||
String req = client.readStringUntil('\r');
|
||||
client.readStringUntil('\n');
|
||||
//reset header value
|
||||
for (int i = 0; i < _headerKeysCount; ++i) {
|
||||
_currentHeaders[i].value =String();
|
||||
}
|
||||
|
||||
// First line of HTTP request looks like "GET /path HTTP/1.1"
|
||||
// Retrieve the "/path" part by finding the spaces
|
||||
int addr_start = req.indexOf(' ');
|
||||
int addr_end = req.indexOf(' ', addr_start + 1);
|
||||
if (addr_start == -1 || addr_end == -1) {
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("Invalid request: ");
|
||||
DEBUG_OUTPUT.println(req);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
String methodStr = req.substring(0, addr_start);
|
||||
String url = req.substring(addr_start + 1, addr_end);
|
||||
String versionEnd = req.substring(addr_end + 8);
|
||||
_currentVersion = atoi(versionEnd.c_str());
|
||||
String searchStr = "";
|
||||
int hasSearch = url.indexOf('?');
|
||||
if (hasSearch != -1){
|
||||
searchStr = url.substring(hasSearch + 1);
|
||||
url = url.substring(0, hasSearch);
|
||||
}
|
||||
_currentUri = url;
|
||||
_chunked = false;
|
||||
|
||||
HTTPMethod method = HTTP_GET;
|
||||
if (methodStr == "POST") {
|
||||
method = HTTP_POST;
|
||||
} else if (methodStr == "DELETE") {
|
||||
method = HTTP_DELETE;
|
||||
} else if (methodStr == "OPTIONS") {
|
||||
method = HTTP_OPTIONS;
|
||||
} else if (methodStr == "PUT") {
|
||||
method = HTTP_PUT;
|
||||
} else if (methodStr == "PATCH") {
|
||||
method = HTTP_PATCH;
|
||||
}
|
||||
_currentMethod = method;
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("method: ");
|
||||
DEBUG_OUTPUT.print(methodStr);
|
||||
DEBUG_OUTPUT.print(" url: ");
|
||||
DEBUG_OUTPUT.print(url);
|
||||
DEBUG_OUTPUT.print(" search: ");
|
||||
DEBUG_OUTPUT.println(searchStr);
|
||||
#endif
|
||||
|
||||
//attach handler
|
||||
RequestHandler* handler;
|
||||
for (handler = _firstHandler; handler; handler = handler->next()) {
|
||||
if (handler->canHandle(_currentMethod, _currentUri))
|
||||
break;
|
||||
}
|
||||
_currentHandler = handler;
|
||||
|
||||
String formData;
|
||||
// below is needed only when POST type request
|
||||
if (method == HTTP_POST || method == HTTP_PUT || method == HTTP_PATCH || method == HTTP_DELETE){
|
||||
String boundaryStr;
|
||||
String headerName;
|
||||
String headerValue;
|
||||
bool isForm = false;
|
||||
bool isEncoded = false;
|
||||
uint32_t contentLength = 0;
|
||||
//parse headers
|
||||
while(1){
|
||||
req = client.readStringUntil('\r');
|
||||
client.readStringUntil('\n');
|
||||
if (req == "") break;//no moar headers
|
||||
int headerDiv = req.indexOf(':');
|
||||
if (headerDiv == -1){
|
||||
break;
|
||||
}
|
||||
headerName = req.substring(0, headerDiv);
|
||||
headerValue = req.substring(headerDiv + 1);
|
||||
headerValue.trim();
|
||||
_collectHeader(headerName.c_str(),headerValue.c_str());
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("headerName: ");
|
||||
DEBUG_OUTPUT.println(headerName);
|
||||
DEBUG_OUTPUT.print("headerValue: ");
|
||||
DEBUG_OUTPUT.println(headerValue);
|
||||
#endif
|
||||
|
||||
if (headerName.equalsIgnoreCase("Content-Type")){
|
||||
if (headerValue.startsWith("text/plain")){
|
||||
isForm = false;
|
||||
} else if (headerValue.startsWith("application/x-www-form-urlencoded")){
|
||||
isForm = false;
|
||||
isEncoded = true;
|
||||
} else if (headerValue.startsWith("multipart/")){
|
||||
boundaryStr = headerValue.substring(headerValue.indexOf('=')+1);
|
||||
isForm = true;
|
||||
}
|
||||
} else if (headerName.equalsIgnoreCase("Content-Length")){
|
||||
contentLength = headerValue.toInt();
|
||||
} else if (headerName.equalsIgnoreCase("Host")){
|
||||
_hostHeader = headerValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isForm){
|
||||
size_t plainLength;
|
||||
char* plainBuf = readBytesWithTimeout(client, contentLength, plainLength, HTTP_MAX_POST_WAIT);
|
||||
if (plainLength < contentLength) {
|
||||
free(plainBuf);
|
||||
return false;
|
||||
}
|
||||
if (contentLength > 0) {
|
||||
if (searchStr != "") searchStr += '&';
|
||||
if(isEncoded){
|
||||
//url encoded form
|
||||
String decoded = urlDecode(plainBuf);
|
||||
size_t decodedLen = decoded.length();
|
||||
memcpy(plainBuf, decoded.c_str(), decodedLen);
|
||||
plainBuf[decodedLen] = 0;
|
||||
searchStr += plainBuf;
|
||||
}
|
||||
_parseArguments(searchStr);
|
||||
if(!isEncoded){
|
||||
//plain post json or other data
|
||||
RequestArgument& arg = _currentArgs[_currentArgCount++];
|
||||
arg.key = "plain";
|
||||
arg.value = String(plainBuf);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("Plain: ");
|
||||
DEBUG_OUTPUT.println(plainBuf);
|
||||
#endif
|
||||
free(plainBuf);
|
||||
} else {
|
||||
// No content - but we can still have arguments in the URL.
|
||||
_parseArguments(searchStr);
|
||||
}
|
||||
}
|
||||
|
||||
if (isForm){
|
||||
_parseArguments(searchStr);
|
||||
if (!_parseForm(client, boundaryStr, contentLength)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String headerName;
|
||||
String headerValue;
|
||||
//parse headers
|
||||
while(1){
|
||||
req = client.readStringUntil('\r');
|
||||
client.readStringUntil('\n');
|
||||
if (req == "") break;//no moar headers
|
||||
int headerDiv = req.indexOf(':');
|
||||
if (headerDiv == -1){
|
||||
break;
|
||||
}
|
||||
headerName = req.substring(0, headerDiv);
|
||||
headerValue = req.substring(headerDiv + 2);
|
||||
_collectHeader(headerName.c_str(),headerValue.c_str());
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("headerName: ");
|
||||
DEBUG_OUTPUT.println(headerName);
|
||||
DEBUG_OUTPUT.print("headerValue: ");
|
||||
DEBUG_OUTPUT.println(headerValue);
|
||||
#endif
|
||||
|
||||
if (headerName.equalsIgnoreCase("Host")){
|
||||
_hostHeader = headerValue;
|
||||
}
|
||||
}
|
||||
_parseArguments(searchStr);
|
||||
}
|
||||
client.flush();
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("Request: ");
|
||||
DEBUG_OUTPUT.println(url);
|
||||
DEBUG_OUTPUT.print(" Arguments: ");
|
||||
DEBUG_OUTPUT.println(searchStr);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebServer::_collectHeader(const char* headerName, const char* headerValue) {
|
||||
for (int i = 0; i < _headerKeysCount; i++) {
|
||||
if (_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
|
||||
_currentHeaders[i].value=headerValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WebServer::_parseArguments(String data) {
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("args: ");
|
||||
DEBUG_OUTPUT.println(data);
|
||||
#endif
|
||||
if (_currentArgs)
|
||||
delete[] _currentArgs;
|
||||
_currentArgs = 0;
|
||||
if (data.length() == 0) {
|
||||
_currentArgCount = 0;
|
||||
_currentArgs = new RequestArgument[1];
|
||||
return;
|
||||
}
|
||||
_currentArgCount = 1;
|
||||
|
||||
for (int i = 0; i < (int)data.length(); ) {
|
||||
i = data.indexOf('&', i);
|
||||
if (i == -1)
|
||||
break;
|
||||
++i;
|
||||
++_currentArgCount;
|
||||
}
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("args count: ");
|
||||
DEBUG_OUTPUT.println(_currentArgCount);
|
||||
#endif
|
||||
|
||||
_currentArgs = new RequestArgument[_currentArgCount+1];
|
||||
int pos = 0;
|
||||
int iarg;
|
||||
for (iarg = 0; iarg < _currentArgCount;) {
|
||||
int equal_sign_index = data.indexOf('=', pos);
|
||||
int next_arg_index = data.indexOf('&', pos);
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("pos ");
|
||||
DEBUG_OUTPUT.print(pos);
|
||||
DEBUG_OUTPUT.print("=@ ");
|
||||
DEBUG_OUTPUT.print(equal_sign_index);
|
||||
DEBUG_OUTPUT.print(" &@ ");
|
||||
DEBUG_OUTPUT.println(next_arg_index);
|
||||
#endif
|
||||
if ((equal_sign_index == -1) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1))) {
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("arg missing value: ");
|
||||
DEBUG_OUTPUT.println(iarg);
|
||||
#endif
|
||||
if (next_arg_index == -1)
|
||||
break;
|
||||
pos = next_arg_index + 1;
|
||||
continue;
|
||||
}
|
||||
RequestArgument& arg = _currentArgs[iarg];
|
||||
arg.key = data.substring(pos, equal_sign_index);
|
||||
arg.value = urlDecode(data.substring(equal_sign_index + 1, next_arg_index));
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("arg ");
|
||||
DEBUG_OUTPUT.print(iarg);
|
||||
DEBUG_OUTPUT.print(" key: ");
|
||||
DEBUG_OUTPUT.print(arg.key);
|
||||
DEBUG_OUTPUT.print(" value: ");
|
||||
DEBUG_OUTPUT.println(arg.value);
|
||||
#endif
|
||||
++iarg;
|
||||
if (next_arg_index == -1)
|
||||
break;
|
||||
pos = next_arg_index + 1;
|
||||
}
|
||||
_currentArgCount = iarg;
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("args count: ");
|
||||
DEBUG_OUTPUT.println(_currentArgCount);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void WebServer::_uploadWriteByte(uint8_t b){
|
||||
if (_currentUpload.currentSize == HTTP_UPLOAD_BUFLEN){
|
||||
if(_currentHandler && _currentHandler->canUpload(_currentUri))
|
||||
_currentHandler->upload(*this, _currentUri, _currentUpload);
|
||||
_currentUpload.totalSize += _currentUpload.currentSize;
|
||||
_currentUpload.currentSize = 0;
|
||||
}
|
||||
_currentUpload.buf[_currentUpload.currentSize++] = b;
|
||||
}
|
||||
|
||||
uint8_t WebServer::_uploadReadByte(WiFiClient& client){
|
||||
int res = client.read();
|
||||
if(res == -1){
|
||||
while(!client.available() && client.connected())
|
||||
yield();
|
||||
res = client.read();
|
||||
}
|
||||
return (uint8_t)res;
|
||||
}
|
||||
|
||||
bool WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t len){
|
||||
(void) len;
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("Parse Form: Boundary: ");
|
||||
DEBUG_OUTPUT.print(boundary);
|
||||
DEBUG_OUTPUT.print(" Length: ");
|
||||
DEBUG_OUTPUT.println(len);
|
||||
#endif
|
||||
String line;
|
||||
int retry = 0;
|
||||
do {
|
||||
line = client.readStringUntil('\r');
|
||||
++retry;
|
||||
} while (line.length() == 0 && retry < 3);
|
||||
|
||||
client.readStringUntil('\n');
|
||||
//start reading the form
|
||||
if (line == ("--"+boundary)){
|
||||
RequestArgument* postArgs = new RequestArgument[32];
|
||||
int postArgsLen = 0;
|
||||
while(1){
|
||||
String argName;
|
||||
String argValue;
|
||||
String argType;
|
||||
String argFilename;
|
||||
bool argIsFile = false;
|
||||
|
||||
line = client.readStringUntil('\r');
|
||||
client.readStringUntil('\n');
|
||||
if (line.length() > 19 && line.substring(0, 19).equalsIgnoreCase("Content-Disposition")){
|
||||
int nameStart = line.indexOf('=');
|
||||
if (nameStart != -1){
|
||||
argName = line.substring(nameStart+2);
|
||||
nameStart = argName.indexOf('=');
|
||||
if (nameStart == -1){
|
||||
argName = argName.substring(0, argName.length() - 1);
|
||||
} else {
|
||||
argFilename = argName.substring(nameStart+2, argName.length() - 1);
|
||||
argName = argName.substring(0, argName.indexOf('"'));
|
||||
argIsFile = true;
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("PostArg FileName: ");
|
||||
DEBUG_OUTPUT.println(argFilename);
|
||||
#endif
|
||||
//use GET to set the filename if uploading using blob
|
||||
if (argFilename == "blob" && hasArg("filename")) argFilename = arg("filename");
|
||||
}
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("PostArg Name: ");
|
||||
DEBUG_OUTPUT.println(argName);
|
||||
#endif
|
||||
argType = "text/plain";
|
||||
line = client.readStringUntil('\r');
|
||||
client.readStringUntil('\n');
|
||||
if (line.length() > 12 && line.substring(0, 12).equalsIgnoreCase("Content-Type")){
|
||||
argType = line.substring(line.indexOf(':')+2);
|
||||
//skip next line
|
||||
client.readStringUntil('\r');
|
||||
client.readStringUntil('\n');
|
||||
}
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("PostArg Type: ");
|
||||
DEBUG_OUTPUT.println(argType);
|
||||
#endif
|
||||
if (!argIsFile){
|
||||
while(1){
|
||||
line = client.readStringUntil('\r');
|
||||
client.readStringUntil('\n');
|
||||
if (line.startsWith("--"+boundary)) break;
|
||||
if (argValue.length() > 0) argValue += "\n";
|
||||
argValue += line;
|
||||
}
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("PostArg Value: ");
|
||||
DEBUG_OUTPUT.println(argValue);
|
||||
DEBUG_OUTPUT.println();
|
||||
#endif
|
||||
|
||||
RequestArgument& arg = postArgs[postArgsLen++];
|
||||
arg.key = argName;
|
||||
arg.value = argValue;
|
||||
|
||||
if (line == ("--"+boundary+"--")){
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("Done Parsing POST");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
_currentUpload.status = UPLOAD_FILE_START;
|
||||
_currentUpload.name = argName;
|
||||
_currentUpload.filename = argFilename;
|
||||
_currentUpload.type = argType;
|
||||
_currentUpload.totalSize = 0;
|
||||
_currentUpload.currentSize = 0;
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("Start File: ");
|
||||
DEBUG_OUTPUT.print(_currentUpload.filename);
|
||||
DEBUG_OUTPUT.print(" Type: ");
|
||||
DEBUG_OUTPUT.println(_currentUpload.type);
|
||||
#endif
|
||||
if(_currentHandler && _currentHandler->canUpload(_currentUri))
|
||||
_currentHandler->upload(*this, _currentUri, _currentUpload);
|
||||
_currentUpload.status = UPLOAD_FILE_WRITE;
|
||||
uint8_t argByte = _uploadReadByte(client);
|
||||
readfile:
|
||||
while(argByte != 0x0D){
|
||||
if (!client.connected()) return _parseFormUploadAborted();
|
||||
_uploadWriteByte(argByte);
|
||||
argByte = _uploadReadByte(client);
|
||||
}
|
||||
|
||||
argByte = _uploadReadByte(client);
|
||||
if (!client.connected()) return _parseFormUploadAborted();
|
||||
if (argByte == 0x0A){
|
||||
argByte = _uploadReadByte(client);
|
||||
if (!client.connected()) return _parseFormUploadAborted();
|
||||
if ((char)argByte != '-'){
|
||||
//continue reading the file
|
||||
_uploadWriteByte(0x0D);
|
||||
_uploadWriteByte(0x0A);
|
||||
goto readfile;
|
||||
} else {
|
||||
argByte = _uploadReadByte(client);
|
||||
if (!client.connected()) return _parseFormUploadAborted();
|
||||
if ((char)argByte != '-'){
|
||||
//continue reading the file
|
||||
_uploadWriteByte(0x0D);
|
||||
_uploadWriteByte(0x0A);
|
||||
_uploadWriteByte((uint8_t)('-'));
|
||||
goto readfile;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t endBuf[boundary.length()];
|
||||
client.readBytes(endBuf, boundary.length());
|
||||
|
||||
if (strstr((const char*)endBuf, boundary.c_str()) != NULL){
|
||||
if(_currentHandler && _currentHandler->canUpload(_currentUri))
|
||||
_currentHandler->upload(*this, _currentUri, _currentUpload);
|
||||
_currentUpload.totalSize += _currentUpload.currentSize;
|
||||
_currentUpload.status = UPLOAD_FILE_END;
|
||||
if(_currentHandler && _currentHandler->canUpload(_currentUri))
|
||||
_currentHandler->upload(*this, _currentUri, _currentUpload);
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("End File: ");
|
||||
DEBUG_OUTPUT.print(_currentUpload.filename);
|
||||
DEBUG_OUTPUT.print(" Type: ");
|
||||
DEBUG_OUTPUT.print(_currentUpload.type);
|
||||
DEBUG_OUTPUT.print(" Size: ");
|
||||
DEBUG_OUTPUT.println(_currentUpload.totalSize);
|
||||
#endif
|
||||
line = client.readStringUntil(0x0D);
|
||||
client.readStringUntil(0x0A);
|
||||
if (line == "--"){
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("Done Parsing POST");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
_uploadWriteByte(0x0D);
|
||||
_uploadWriteByte(0x0A);
|
||||
_uploadWriteByte((uint8_t)('-'));
|
||||
_uploadWriteByte((uint8_t)('-'));
|
||||
uint32_t i = 0;
|
||||
while(i < boundary.length()){
|
||||
_uploadWriteByte(endBuf[i++]);
|
||||
}
|
||||
argByte = _uploadReadByte(client);
|
||||
goto readfile;
|
||||
}
|
||||
} else {
|
||||
_uploadWriteByte(0x0D);
|
||||
goto readfile;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int iarg;
|
||||
int totalArgs = ((32 - postArgsLen) < _currentArgCount)?(32 - postArgsLen):_currentArgCount;
|
||||
for (iarg = 0; iarg < totalArgs; iarg++){
|
||||
RequestArgument& arg = postArgs[postArgsLen++];
|
||||
arg.key = _currentArgs[iarg].key;
|
||||
arg.value = _currentArgs[iarg].value;
|
||||
}
|
||||
if (_currentArgs) delete[] _currentArgs;
|
||||
_currentArgs = new RequestArgument[postArgsLen];
|
||||
for (iarg = 0; iarg < postArgsLen; iarg++){
|
||||
RequestArgument& arg = _currentArgs[iarg];
|
||||
arg.key = postArgs[iarg].key;
|
||||
arg.value = postArgs[iarg].value;
|
||||
}
|
||||
_currentArgCount = iarg;
|
||||
if (postArgs) delete[] postArgs;
|
||||
return true;
|
||||
}
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.print("Error: line: ");
|
||||
DEBUG_OUTPUT.println(line);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
String WebServer::urlDecode(const String& text)
|
||||
{
|
||||
String decoded = "";
|
||||
char temp[] = "0x00";
|
||||
unsigned int len = text.length();
|
||||
unsigned int i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
char decodedChar;
|
||||
char encodedChar = text.charAt(i++);
|
||||
if ((encodedChar == '%') && (i + 1 < len))
|
||||
{
|
||||
temp[2] = text.charAt(i++);
|
||||
temp[3] = text.charAt(i++);
|
||||
|
||||
decodedChar = strtol(temp, NULL, 16);
|
||||
}
|
||||
else {
|
||||
if (encodedChar == '+')
|
||||
{
|
||||
decodedChar = ' ';
|
||||
}
|
||||
else {
|
||||
decodedChar = encodedChar; // normal ascii char
|
||||
}
|
||||
}
|
||||
decoded += decodedChar;
|
||||
}
|
||||
return decoded;
|
||||
}
|
||||
|
||||
bool WebServer::_parseFormUploadAborted(){
|
||||
_currentUpload.status = UPLOAD_FILE_ABORTED;
|
||||
if(_currentHandler && _currentHandler->canUpload(_currentUri))
|
||||
_currentHandler->upload(*this, _currentUri, _currentUpload);
|
||||
return false;
|
||||
}
|
530
libraries/WebServer/src/WebServer.cpp
Normal file
530
libraries/WebServer/src/WebServer.cpp
Normal file
@ -0,0 +1,530 @@
|
||||
/*
|
||||
WebServer.cpp - Dead simple web-server.
|
||||
Supports only one simultaneous client, knows how to handle GET and POST.
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
|
||||
*/
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <libb64/cencode.h>
|
||||
#include "WiFiServer.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "WebServer.h"
|
||||
#include "FS.h"
|
||||
#include "detail/RequestHandlersImpl.h"
|
||||
|
||||
//#define DEBUG_ESP_HTTP_SERVER
|
||||
#ifdef DEBUG_ESP_PORT
|
||||
#define DEBUG_OUTPUT DEBUG_ESP_PORT
|
||||
#else
|
||||
#define DEBUG_OUTPUT Serial
|
||||
#endif
|
||||
|
||||
const char * AUTHORIZATION_HEADER = "Authorization";
|
||||
|
||||
WebServer::WebServer(IPAddress addr, int port)
|
||||
: _server(addr, port)
|
||||
, _currentMethod(HTTP_ANY)
|
||||
, _currentVersion(0)
|
||||
, _currentStatus(HC_NONE)
|
||||
, _statusChange(0)
|
||||
, _currentHandler(0)
|
||||
, _firstHandler(0)
|
||||
, _lastHandler(0)
|
||||
, _currentArgCount(0)
|
||||
, _currentArgs(0)
|
||||
, _headerKeysCount(0)
|
||||
, _currentHeaders(0)
|
||||
, _contentLength(0)
|
||||
, _chunked(false)
|
||||
{
|
||||
}
|
||||
|
||||
WebServer::WebServer(int port)
|
||||
: _server(port)
|
||||
, _currentMethod(HTTP_ANY)
|
||||
, _currentVersion(0)
|
||||
, _currentStatus(HC_NONE)
|
||||
, _statusChange(0)
|
||||
, _currentHandler(0)
|
||||
, _firstHandler(0)
|
||||
, _lastHandler(0)
|
||||
, _currentArgCount(0)
|
||||
, _currentArgs(0)
|
||||
, _headerKeysCount(0)
|
||||
, _currentHeaders(0)
|
||||
, _contentLength(0)
|
||||
, _chunked(false)
|
||||
{
|
||||
}
|
||||
|
||||
WebServer::~WebServer() {
|
||||
if (_currentHeaders)
|
||||
delete[]_currentHeaders;
|
||||
_headerKeysCount = 0;
|
||||
RequestHandler* handler = _firstHandler;
|
||||
while (handler) {
|
||||
RequestHandler* next = handler->next();
|
||||
delete handler;
|
||||
handler = next;
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
void WebServer::begin() {
|
||||
_currentStatus = HC_NONE;
|
||||
_server.begin();
|
||||
if(!_headerKeysCount)
|
||||
collectHeaders(0, 0);
|
||||
}
|
||||
|
||||
bool WebServer::authenticate(const char * username, const char * password){
|
||||
if(hasHeader(AUTHORIZATION_HEADER)){
|
||||
String authReq = header(AUTHORIZATION_HEADER);
|
||||
if(authReq.startsWith("Basic")){
|
||||
authReq = authReq.substring(6);
|
||||
authReq.trim();
|
||||
char toencodeLen = strlen(username)+strlen(password)+1;
|
||||
char *toencode = new char[toencodeLen + 1];
|
||||
if(toencode == NULL){
|
||||
authReq = String();
|
||||
return false;
|
||||
}
|
||||
char *encoded = new char[base64_encode_expected_len(toencodeLen)+1];
|
||||
if(encoded == NULL){
|
||||
authReq = String();
|
||||
delete[] toencode;
|
||||
return false;
|
||||
}
|
||||
sprintf(toencode, "%s:%s", username, password);
|
||||
if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq.equals(encoded)){
|
||||
authReq = String();
|
||||
delete[] toencode;
|
||||
delete[] encoded;
|
||||
return true;
|
||||
}
|
||||
delete[] toencode;
|
||||
delete[] encoded;
|
||||
}
|
||||
authReq = String();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WebServer::requestAuthentication(){
|
||||
sendHeader("WWW-Authenticate", "Basic realm=\"Login Required\"");
|
||||
send(401);
|
||||
}
|
||||
|
||||
void WebServer::on(const String &uri, WebServer::THandlerFunction handler) {
|
||||
on(uri, HTTP_ANY, handler);
|
||||
}
|
||||
|
||||
void WebServer::on(const String &uri, HTTPMethod method, WebServer::THandlerFunction fn) {
|
||||
on(uri, method, fn, _fileUploadHandler);
|
||||
}
|
||||
|
||||
void WebServer::on(const String &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) {
|
||||
_addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method));
|
||||
}
|
||||
|
||||
void WebServer::addHandler(RequestHandler* handler) {
|
||||
_addRequestHandler(handler);
|
||||
}
|
||||
|
||||
void WebServer::_addRequestHandler(RequestHandler* handler) {
|
||||
if (!_lastHandler) {
|
||||
_firstHandler = handler;
|
||||
_lastHandler = handler;
|
||||
}
|
||||
else {
|
||||
_lastHandler->next(handler);
|
||||
_lastHandler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
void WebServer::serveStatic(const char* uri, FS& fs, const char* path, const char* cache_header) {
|
||||
_addRequestHandler(new StaticRequestHandler(fs, path, uri, cache_header));
|
||||
}
|
||||
|
||||
void WebServer::handleClient() {
|
||||
if (_currentStatus == HC_NONE) {
|
||||
WiFiClient client = _server.available();
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("New client");
|
||||
#endif
|
||||
|
||||
_currentClient = client;
|
||||
_currentStatus = HC_WAIT_READ;
|
||||
_statusChange = millis();
|
||||
}
|
||||
|
||||
if (!_currentClient.connected()) {
|
||||
_currentClient = WiFiClient();
|
||||
_currentStatus = HC_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for data from client to become available
|
||||
if (_currentStatus == HC_WAIT_READ) {
|
||||
if (!_currentClient.available()) {
|
||||
if (millis() - _statusChange > HTTP_MAX_DATA_WAIT) {
|
||||
_currentClient = WiFiClient();
|
||||
_currentStatus = HC_NONE;
|
||||
}
|
||||
yield();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_parseRequest(_currentClient)) {
|
||||
_currentClient = WiFiClient();
|
||||
_currentStatus = HC_NONE;
|
||||
return;
|
||||
}
|
||||
_currentClient.setTimeout(HTTP_MAX_SEND_WAIT);
|
||||
_contentLength = CONTENT_LENGTH_NOT_SET;
|
||||
_handleRequest();
|
||||
|
||||
if (!_currentClient.connected()) {
|
||||
_currentClient = WiFiClient();
|
||||
_currentStatus = HC_NONE;
|
||||
return;
|
||||
} else {
|
||||
_currentStatus = HC_WAIT_CLOSE;
|
||||
_statusChange = millis();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_currentStatus == HC_WAIT_CLOSE) {
|
||||
if (millis() - _statusChange > HTTP_MAX_CLOSE_WAIT) {
|
||||
_currentClient = WiFiClient();
|
||||
_currentStatus = HC_NONE;
|
||||
} else {
|
||||
yield();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WebServer::close() {
|
||||
#ifdef ESP8266
|
||||
_server.stop();
|
||||
#else
|
||||
// TODO add ESP32 WiFiServer::stop()
|
||||
_server.end();
|
||||
#endif
|
||||
}
|
||||
|
||||
void WebServer::stop() {
|
||||
close();
|
||||
}
|
||||
|
||||
void WebServer::sendHeader(const String& name, const String& value, bool first) {
|
||||
String headerLine = name;
|
||||
headerLine += ": ";
|
||||
headerLine += value;
|
||||
headerLine += "\r\n";
|
||||
|
||||
if (first) {
|
||||
_responseHeaders = headerLine + _responseHeaders;
|
||||
}
|
||||
else {
|
||||
_responseHeaders += headerLine;
|
||||
}
|
||||
}
|
||||
|
||||
void WebServer::setContentLength(size_t contentLength) {
|
||||
_contentLength = contentLength;
|
||||
}
|
||||
|
||||
void WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) {
|
||||
response = "HTTP/1."+String(_currentVersion)+" ";
|
||||
response += String(code);
|
||||
response += " ";
|
||||
response += _responseCodeToString(code);
|
||||
response += "\r\n";
|
||||
|
||||
if (!content_type)
|
||||
content_type = "text/html";
|
||||
|
||||
sendHeader("Content-Type", content_type, true);
|
||||
if (_contentLength == CONTENT_LENGTH_NOT_SET) {
|
||||
sendHeader("Content-Length", String(contentLength));
|
||||
} else if (_contentLength != CONTENT_LENGTH_UNKNOWN) {
|
||||
sendHeader("Content-Length", String(_contentLength));
|
||||
} else if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ //HTTP/1.1 or above client
|
||||
//let's do chunked
|
||||
_chunked = true;
|
||||
sendHeader("Accept-Ranges","none");
|
||||
sendHeader("Transfer-Encoding","chunked");
|
||||
}
|
||||
sendHeader("Connection", "close");
|
||||
|
||||
response += _responseHeaders;
|
||||
response += "\r\n";
|
||||
_responseHeaders = String();
|
||||
}
|
||||
|
||||
void WebServer::send(int code, const char* content_type, const String& content) {
|
||||
String header;
|
||||
// Can we asume the following?
|
||||
//if(code == 200 && content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET)
|
||||
// _contentLength = CONTENT_LENGTH_UNKNOWN;
|
||||
_prepareHeader(header, code, content_type, content.length());
|
||||
_currentClient.write(header.c_str(), header.length());
|
||||
if(content.length())
|
||||
sendContent(content);
|
||||
}
|
||||
|
||||
void WebServer::send_P(int code, PGM_P content_type, PGM_P content) {
|
||||
size_t contentLength = 0;
|
||||
|
||||
if (content != NULL) {
|
||||
contentLength = strlen_P(content);
|
||||
}
|
||||
|
||||
String header;
|
||||
char type[64];
|
||||
memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type));
|
||||
_prepareHeader(header, code, (const char* )type, contentLength);
|
||||
_currentClient.write(header.c_str(), header.length());
|
||||
sendContent_P(content);
|
||||
}
|
||||
|
||||
void WebServer::send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength) {
|
||||
String header;
|
||||
char type[64];
|
||||
memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type));
|
||||
_prepareHeader(header, code, (const char* )type, contentLength);
|
||||
sendContent(header);
|
||||
sendContent_P(content, contentLength);
|
||||
}
|
||||
|
||||
void WebServer::send(int code, char* content_type, const String& content) {
|
||||
send(code, (const char*)content_type, content);
|
||||
}
|
||||
|
||||
void WebServer::send(int code, const String& content_type, const String& content) {
|
||||
send(code, (const char*)content_type.c_str(), content);
|
||||
}
|
||||
|
||||
void WebServer::sendContent(const String& content) {
|
||||
const char * footer = "\r\n";
|
||||
size_t len = content.length();
|
||||
if(_chunked) {
|
||||
char * chunkSize = (char *)malloc(11);
|
||||
if(chunkSize){
|
||||
sprintf(chunkSize, "%x%s", len, footer);
|
||||
_currentClient.write(chunkSize, strlen(chunkSize));
|
||||
free(chunkSize);
|
||||
}
|
||||
}
|
||||
_currentClient.write(content.c_str(), len);
|
||||
if(_chunked){
|
||||
_currentClient.write(footer, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void WebServer::sendContent_P(PGM_P content) {
|
||||
sendContent_P(content, strlen_P(content));
|
||||
}
|
||||
|
||||
void WebServer::sendContent_P(PGM_P content, size_t size) {
|
||||
const char * footer = "\r\n";
|
||||
if(_chunked) {
|
||||
char * chunkSize = (char *)malloc(11);
|
||||
if(chunkSize){
|
||||
sprintf(chunkSize, "%x%s", size, footer);
|
||||
_currentClient.write(chunkSize, strlen(chunkSize));
|
||||
free(chunkSize);
|
||||
}
|
||||
}
|
||||
_currentClient.write_P(content, size);
|
||||
if(_chunked){
|
||||
_currentClient.write(footer, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String WebServer::arg(String name) {
|
||||
for (int i = 0; i < _currentArgCount; ++i) {
|
||||
if ( _currentArgs[i].key == name )
|
||||
return _currentArgs[i].value;
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
String WebServer::arg(int i) {
|
||||
if (i < _currentArgCount)
|
||||
return _currentArgs[i].value;
|
||||
return String();
|
||||
}
|
||||
|
||||
String WebServer::argName(int i) {
|
||||
if (i < _currentArgCount)
|
||||
return _currentArgs[i].key;
|
||||
return String();
|
||||
}
|
||||
|
||||
int WebServer::args() {
|
||||
return _currentArgCount;
|
||||
}
|
||||
|
||||
bool WebServer::hasArg(String name) {
|
||||
for (int i = 0; i < _currentArgCount; ++i) {
|
||||
if (_currentArgs[i].key == name)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
String WebServer::header(String name) {
|
||||
for (int i = 0; i < _headerKeysCount; ++i) {
|
||||
if (_currentHeaders[i].key.equalsIgnoreCase(name))
|
||||
return _currentHeaders[i].value;
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
void WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
|
||||
_headerKeysCount = headerKeysCount + 1;
|
||||
if (_currentHeaders)
|
||||
delete[]_currentHeaders;
|
||||
_currentHeaders = new RequestArgument[_headerKeysCount];
|
||||
_currentHeaders[0].key = AUTHORIZATION_HEADER;
|
||||
for (int i = 1; i < _headerKeysCount; i++){
|
||||
_currentHeaders[i].key = headerKeys[i-1];
|
||||
}
|
||||
}
|
||||
|
||||
String WebServer::header(int i) {
|
||||
if (i < _headerKeysCount)
|
||||
return _currentHeaders[i].value;
|
||||
return String();
|
||||
}
|
||||
|
||||
String WebServer::headerName(int i) {
|
||||
if (i < _headerKeysCount)
|
||||
return _currentHeaders[i].key;
|
||||
return String();
|
||||
}
|
||||
|
||||
int WebServer::headers() {
|
||||
return _headerKeysCount;
|
||||
}
|
||||
|
||||
bool WebServer::hasHeader(String name) {
|
||||
for (int i = 0; i < _headerKeysCount; ++i) {
|
||||
if ((_currentHeaders[i].key.equalsIgnoreCase(name)) && (_currentHeaders[i].value.length() > 0))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String WebServer::hostHeader() {
|
||||
return _hostHeader;
|
||||
}
|
||||
|
||||
void WebServer::onFileUpload(THandlerFunction fn) {
|
||||
_fileUploadHandler = fn;
|
||||
}
|
||||
|
||||
void WebServer::onNotFound(THandlerFunction fn) {
|
||||
_notFoundHandler = fn;
|
||||
}
|
||||
|
||||
void WebServer::_handleRequest() {
|
||||
bool handled = false;
|
||||
if (!_currentHandler){
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("request handler not found");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
handled = _currentHandler->handle(*this, _currentMethod, _currentUri);
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
if (!handled) {
|
||||
DEBUG_OUTPUT.println("request handler failed to handle request");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
if(_notFoundHandler) {
|
||||
_notFoundHandler();
|
||||
}
|
||||
else {
|
||||
send(404, "text/plain", String("Not found: ") + _currentUri);
|
||||
}
|
||||
}
|
||||
|
||||
_currentUri = String();
|
||||
}
|
||||
|
||||
String WebServer::_responseCodeToString(int code) {
|
||||
switch (code) {
|
||||
case 100: return F("Continue");
|
||||
case 101: return F("Switching Protocols");
|
||||
case 200: return F("OK");
|
||||
case 201: return F("Created");
|
||||
case 202: return F("Accepted");
|
||||
case 203: return F("Non-Authoritative Information");
|
||||
case 204: return F("No Content");
|
||||
case 205: return F("Reset Content");
|
||||
case 206: return F("Partial Content");
|
||||
case 300: return F("Multiple Choices");
|
||||
case 301: return F("Moved Permanently");
|
||||
case 302: return F("Found");
|
||||
case 303: return F("See Other");
|
||||
case 304: return F("Not Modified");
|
||||
case 305: return F("Use Proxy");
|
||||
case 307: return F("Temporary Redirect");
|
||||
case 400: return F("Bad Request");
|
||||
case 401: return F("Unauthorized");
|
||||
case 402: return F("Payment Required");
|
||||
case 403: return F("Forbidden");
|
||||
case 404: return F("Not Found");
|
||||
case 405: return F("Method Not Allowed");
|
||||
case 406: return F("Not Acceptable");
|
||||
case 407: return F("Proxy Authentication Required");
|
||||
case 408: return F("Request Time-out");
|
||||
case 409: return F("Conflict");
|
||||
case 410: return F("Gone");
|
||||
case 411: return F("Length Required");
|
||||
case 412: return F("Precondition Failed");
|
||||
case 413: return F("Request Entity Too Large");
|
||||
case 414: return F("Request-URI Too Large");
|
||||
case 415: return F("Unsupported Media Type");
|
||||
case 416: return F("Requested range not satisfiable");
|
||||
case 417: return F("Expectation Failed");
|
||||
case 500: return F("Internal Server Error");
|
||||
case 501: return F("Not Implemented");
|
||||
case 502: return F("Bad Gateway");
|
||||
case 503: return F("Service Unavailable");
|
||||
case 504: return F("Gateway Time-out");
|
||||
case 505: return F("HTTP Version not supported");
|
||||
default: return "";
|
||||
}
|
||||
}
|
236
libraries/WebServer/src/WebServer.h
Normal file
236
libraries/WebServer/src/WebServer.h
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
WebServer.h - Dead simple web-server.
|
||||
Supports only one simultaneous client, knows how to handle GET and POST.
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WEBSERVER_H
|
||||
#define WEBSERVER_H
|
||||
|
||||
#include <functional>
|
||||
#ifdef ESP8266
|
||||
#define WebServer ESP8266WebServer
|
||||
#include <ESP8266WiFi.h>
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#define write_P write
|
||||
#endif
|
||||
|
||||
enum HTTPMethod { HTTP_ANY, HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS };
|
||||
enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END,
|
||||
UPLOAD_FILE_ABORTED };
|
||||
enum HTTPClientStatus { HC_NONE, HC_WAIT_READ, HC_WAIT_CLOSE };
|
||||
|
||||
#define HTTP_DOWNLOAD_UNIT_SIZE 1460
|
||||
|
||||
#ifndef HTTP_UPLOAD_BUFLEN
|
||||
#define HTTP_UPLOAD_BUFLEN 2048
|
||||
#endif
|
||||
|
||||
#define HTTP_MAX_DATA_WAIT 1000 //ms to wait for the client to send the request
|
||||
#define HTTP_MAX_POST_WAIT 1000 //ms to wait for POST data to arrive
|
||||
#define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed
|
||||
#define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection
|
||||
|
||||
#define CONTENT_LENGTH_UNKNOWN ((size_t) -1)
|
||||
#define CONTENT_LENGTH_NOT_SET ((size_t) -2)
|
||||
|
||||
class WebServer;
|
||||
|
||||
typedef struct {
|
||||
HTTPUploadStatus status;
|
||||
String filename;
|
||||
String name;
|
||||
String type;
|
||||
size_t totalSize; // file size
|
||||
size_t currentSize; // size of data currently in buf
|
||||
uint8_t buf[HTTP_UPLOAD_BUFLEN];
|
||||
} HTTPUpload;
|
||||
|
||||
#include "detail/RequestHandler.h"
|
||||
|
||||
namespace fs {
|
||||
class FS;
|
||||
}
|
||||
|
||||
class WebServer
|
||||
{
|
||||
public:
|
||||
WebServer(IPAddress addr, int port = 80);
|
||||
WebServer(int port = 80);
|
||||
~WebServer();
|
||||
|
||||
void begin();
|
||||
void handleClient();
|
||||
|
||||
void close();
|
||||
void stop();
|
||||
|
||||
bool authenticate(const char * username, const char * password);
|
||||
void requestAuthentication();
|
||||
|
||||
typedef std::function<void(void)> THandlerFunction;
|
||||
void on(const String &uri, THandlerFunction handler);
|
||||
void on(const String &uri, HTTPMethod method, THandlerFunction fn);
|
||||
void on(const String &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn);
|
||||
void addHandler(RequestHandler* handler);
|
||||
void serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header = NULL );
|
||||
void onNotFound(THandlerFunction fn); //called when handler is not assigned
|
||||
void onFileUpload(THandlerFunction fn); //handle file uploads
|
||||
|
||||
String uri() { return _currentUri; }
|
||||
HTTPMethod method() { return _currentMethod; }
|
||||
WiFiClient client() { return _currentClient; }
|
||||
HTTPUpload& upload() { return _currentUpload; }
|
||||
|
||||
String arg(String name); // get request argument value by name
|
||||
String arg(int i); // get request argument value by number
|
||||
String argName(int i); // get request argument name by number
|
||||
int args(); // get arguments count
|
||||
bool hasArg(String name); // check if argument exists
|
||||
void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); // set the request headers to collect
|
||||
String header(String name); // get request header value by name
|
||||
String header(int i); // get request header value by number
|
||||
String headerName(int i); // get request header name by number
|
||||
int headers(); // get header count
|
||||
bool hasHeader(String name); // check if header exists
|
||||
|
||||
String hostHeader(); // get request host header if available or empty String if not
|
||||
|
||||
// send response to the client
|
||||
// code - HTTP response code, can be 200 or 404
|
||||
// content_type - HTTP content type, like "text/plain" or "image/png"
|
||||
// content - actual content body
|
||||
void send(int code, const char* content_type = NULL, const String& content = String(""));
|
||||
void send(int code, char* content_type, const String& content);
|
||||
void send(int code, const String& content_type, const String& content);
|
||||
void send_P(int code, PGM_P content_type, PGM_P content);
|
||||
void send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength);
|
||||
|
||||
void setContentLength(size_t contentLength);
|
||||
void sendHeader(const String& name, const String& value, bool first = false);
|
||||
void sendContent(const String& content);
|
||||
void sendContent_P(PGM_P content);
|
||||
void sendContent_P(PGM_P content, size_t size);
|
||||
|
||||
static String urlDecode(const String& text);
|
||||
|
||||
#ifdef ESP8266
|
||||
template<typename T> size_t streamFile(T &file, const String& contentType){
|
||||
setContentLength(file.size());
|
||||
if (String(file.name()).endsWith(".gz") &&
|
||||
contentType != "application/x-gzip" &&
|
||||
contentType != "application/octet-stream"){
|
||||
sendHeader("Content-Encoding", "gzip");
|
||||
}
|
||||
send(200, contentType, "");
|
||||
return _currentClient.write(file);
|
||||
}
|
||||
#else
|
||||
template<typename T> size_t streamFile(T &file, const String& contentType){
|
||||
#define STREAMFILE_BUFSIZE 2*1460
|
||||
setContentLength(file.size());
|
||||
if (String(file.name()).endsWith(".gz") &&
|
||||
contentType != "application/x-gzip" &&
|
||||
contentType != "application/octet-stream") {
|
||||
sendHeader("Content-Encoding", "gzip");
|
||||
}
|
||||
send(200, contentType, "");
|
||||
uint8_t *buf = (uint8_t *)malloc(STREAMFILE_BUFSIZE);
|
||||
if (buf == NULL) {
|
||||
//DBG_OUTPUT_PORT.printf("streamFile malloc failed");
|
||||
return 0;
|
||||
}
|
||||
size_t totalBytesOut = 0;
|
||||
while (client().connected() && (file.available() > 0)) {
|
||||
int bytesOut;
|
||||
int bytesIn = file.read(buf, STREAMFILE_BUFSIZE);
|
||||
if (bytesIn <= 0) break;
|
||||
while (1) {
|
||||
bytesOut = 0;
|
||||
if (!client().connected()) break;
|
||||
bytesOut = client().write(buf, bytesIn);
|
||||
if (bytesIn == bytesOut) break;
|
||||
|
||||
//DBG_OUTPUT_PORT.printf("bytesIn %d != bytesOut %d\r\n",
|
||||
//bytesIn, bytesOut);
|
||||
delay(1);
|
||||
}
|
||||
totalBytesOut += bytesOut;
|
||||
yield();
|
||||
}
|
||||
if (totalBytesOut != file.size()) {
|
||||
//DBG_OUTPUT_PORT.printf("file size %d bytes out %d\r\n",
|
||||
// file.size(), totalBytesOut);
|
||||
}
|
||||
free(buf);
|
||||
return totalBytesOut;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void _addRequestHandler(RequestHandler* handler);
|
||||
void _handleRequest();
|
||||
bool _parseRequest(WiFiClient& client);
|
||||
void _parseArguments(String data);
|
||||
static String _responseCodeToString(int code);
|
||||
bool _parseForm(WiFiClient& client, String boundary, uint32_t len);
|
||||
bool _parseFormUploadAborted();
|
||||
void _uploadWriteByte(uint8_t b);
|
||||
uint8_t _uploadReadByte(WiFiClient& client);
|
||||
void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength);
|
||||
bool _collectHeader(const char* headerName, const char* headerValue);
|
||||
|
||||
struct RequestArgument {
|
||||
String key;
|
||||
String value;
|
||||
};
|
||||
|
||||
WiFiServer _server;
|
||||
|
||||
WiFiClient _currentClient;
|
||||
HTTPMethod _currentMethod;
|
||||
String _currentUri;
|
||||
uint8_t _currentVersion;
|
||||
HTTPClientStatus _currentStatus;
|
||||
unsigned long _statusChange;
|
||||
|
||||
RequestHandler* _currentHandler;
|
||||
RequestHandler* _firstHandler;
|
||||
RequestHandler* _lastHandler;
|
||||
THandlerFunction _notFoundHandler;
|
||||
THandlerFunction _fileUploadHandler;
|
||||
|
||||
int _currentArgCount;
|
||||
RequestArgument* _currentArgs;
|
||||
HTTPUpload _currentUpload;
|
||||
|
||||
int _headerKeysCount;
|
||||
RequestArgument* _currentHeaders;
|
||||
size_t _contentLength;
|
||||
String _responseHeaders;
|
||||
|
||||
String _hostHeader;
|
||||
bool _chunked;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //WEBSERVER_H
|
19
libraries/WebServer/src/detail/RequestHandler.h
Normal file
19
libraries/WebServer/src/detail/RequestHandler.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef REQUESTHANDLER_H
|
||||
#define REQUESTHANDLER_H
|
||||
|
||||
class RequestHandler {
|
||||
public:
|
||||
virtual ~RequestHandler() { }
|
||||
virtual bool canHandle(HTTPMethod method, String uri) { (void) method; (void) uri; return false; }
|
||||
virtual bool canUpload(String uri) { (void) uri; return false; }
|
||||
virtual bool handle(WebServer& server, HTTPMethod requestMethod, String requestUri) { (void) server; (void) requestMethod; (void) requestUri; return false; }
|
||||
virtual void upload(WebServer& server, String requestUri, HTTPUpload& upload) { (void) server; (void) requestUri; (void) upload; }
|
||||
|
||||
RequestHandler* next() { return _next; }
|
||||
void next(RequestHandler* r) { _next = r; }
|
||||
|
||||
private:
|
||||
RequestHandler* _next = nullptr;
|
||||
};
|
||||
|
||||
#endif //REQUESTHANDLER_H
|
191
libraries/WebServer/src/detail/RequestHandlersImpl.h
Normal file
191
libraries/WebServer/src/detail/RequestHandlersImpl.h
Normal file
@ -0,0 +1,191 @@
|
||||
#ifndef REQUESTHANDLERSIMPL_H
|
||||
#define REQUESTHANDLERSIMPL_H
|
||||
|
||||
#include "RequestHandler.h"
|
||||
|
||||
#ifdef ESP8266
|
||||
// Table of extension->MIME strings stored in PROGMEM, needs to be global due to GCC section typing rules
|
||||
static const struct {const char endsWith[16]; const char mimeType[32];} mimeTable[] ICACHE_RODATA_ATTR = {
|
||||
#else
|
||||
static const struct {const char endsWith[16]; const char mimeType[32];} mimeTable[] = {
|
||||
#endif
|
||||
{ ".html", "text/html" },
|
||||
{ ".htm", "text/html" },
|
||||
{ ".css", "text/css" },
|
||||
{ ".txt", "text/plain" },
|
||||
{ ".js", "application/javascript" },
|
||||
{ ".json", "application/json" },
|
||||
{ ".png", "image/png" },
|
||||
{ ".gif", "image/gif" },
|
||||
{ ".jpg", "image/jpeg" },
|
||||
{ ".ico", "image/x-icon" },
|
||||
{ ".svg", "image/svg+xml" },
|
||||
{ ".ttf", "application/x-font-ttf" },
|
||||
{ ".otf", "application/x-font-opentype" },
|
||||
{ ".woff", "application/font-woff" },
|
||||
{ ".woff2", "application/font-woff2" },
|
||||
{ ".eot", "application/vnd.ms-fontobject" },
|
||||
{ ".sfnt", "application/font-sfnt" },
|
||||
{ ".xml", "text/xml" },
|
||||
{ ".pdf", "application/pdf" },
|
||||
{ ".zip", "application/zip" },
|
||||
{ ".gz", "application/x-gzip" },
|
||||
{ ".appcache", "text/cache-manifest" },
|
||||
{ "", "application/octet-stream" } };
|
||||
|
||||
class FunctionRequestHandler : public RequestHandler {
|
||||
public:
|
||||
FunctionRequestHandler(WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn, const String &uri, HTTPMethod method)
|
||||
: _fn(fn)
|
||||
, _ufn(ufn)
|
||||
, _uri(uri)
|
||||
, _method(method)
|
||||
{
|
||||
}
|
||||
|
||||
bool canHandle(HTTPMethod requestMethod, String requestUri) override {
|
||||
if (_method != HTTP_ANY && _method != requestMethod)
|
||||
return false;
|
||||
|
||||
if (requestUri != _uri)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool canUpload(String requestUri) override {
|
||||
if (!_ufn || !canHandle(HTTP_POST, requestUri))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool handle(WebServer& server, HTTPMethod requestMethod, String requestUri) override {
|
||||
(void) server;
|
||||
if (!canHandle(requestMethod, requestUri))
|
||||
return false;
|
||||
|
||||
_fn();
|
||||
return true;
|
||||
}
|
||||
|
||||
void upload(WebServer& server, String requestUri, HTTPUpload& upload) override {
|
||||
(void) server;
|
||||
(void) upload;
|
||||
if (canUpload(requestUri))
|
||||
_ufn();
|
||||
}
|
||||
|
||||
protected:
|
||||
WebServer::THandlerFunction _fn;
|
||||
WebServer::THandlerFunction _ufn;
|
||||
String _uri;
|
||||
HTTPMethod _method;
|
||||
};
|
||||
|
||||
class StaticRequestHandler : public RequestHandler {
|
||||
public:
|
||||
StaticRequestHandler(FS& fs, const char* path, const char* uri, const char* cache_header)
|
||||
: _fs(fs)
|
||||
, _uri(uri)
|
||||
, _path(path)
|
||||
, _cache_header(cache_header)
|
||||
{
|
||||
_isFile = fs.exists(path);
|
||||
#ifdef ESP8266
|
||||
DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d, cache_header=%s\r\n", path, uri, _isFile, cache_header);
|
||||
#else
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.printf("StaticRequestHandler: path=%s uri=%s isFile=%d, cache_header=%s\r\n", path, uri, _isFile, cache_header);
|
||||
#endif
|
||||
#endif
|
||||
_baseUriLength = _uri.length();
|
||||
}
|
||||
|
||||
bool canHandle(HTTPMethod requestMethod, String requestUri) override {
|
||||
if (requestMethod != HTTP_GET)
|
||||
return false;
|
||||
|
||||
if ((_isFile && requestUri != _uri) || !requestUri.startsWith(_uri))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool handle(WebServer& server, HTTPMethod requestMethod, String requestUri) override {
|
||||
if (!canHandle(requestMethod, requestUri))
|
||||
return false;
|
||||
|
||||
#ifdef ESP8266
|
||||
DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
|
||||
#else
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.printf("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
String path(_path);
|
||||
|
||||
if (!_isFile) {
|
||||
// Base URI doesn't point to a file.
|
||||
// If a directory is requested, look for index file.
|
||||
if (requestUri.endsWith("/")) requestUri += "index.htm";
|
||||
|
||||
// Append whatever follows this URI in request to get the file path.
|
||||
path += requestUri.substring(_baseUriLength);
|
||||
}
|
||||
#ifdef ESP8266
|
||||
DEBUGV("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile);
|
||||
#else
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.printf("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
String contentType = getContentType(path);
|
||||
|
||||
// look for gz file, only if the original specified path is not a gz. So part only works to send gzip via content encoding when a non compressed is asked for
|
||||
// if you point the the path to gzip you will serve the gzip as content type "application/x-gzip", not text or javascript etc...
|
||||
if (!path.endsWith(".gz") && !_fs.exists(path)) {
|
||||
String pathWithGz = path + ".gz";
|
||||
if(_fs.exists(pathWithGz))
|
||||
path += ".gz";
|
||||
}
|
||||
|
||||
File f = _fs.open(path, "r");
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
if (_cache_header.length() != 0)
|
||||
server.sendHeader("Cache-Control", _cache_header);
|
||||
|
||||
server.streamFile(f, contentType);
|
||||
return true;
|
||||
}
|
||||
|
||||
static String getContentType(const String& path) {
|
||||
char buff[sizeof(mimeTable[0].mimeType)];
|
||||
// Check all entries but last one for match, return if found
|
||||
for (size_t i=0; i < sizeof(mimeTable)/sizeof(mimeTable[0])-1; i++) {
|
||||
strcpy_P(buff, mimeTable[i].endsWith);
|
||||
if (path.endsWith(buff)) {
|
||||
strcpy_P(buff, mimeTable[i].mimeType);
|
||||
return String(buff);
|
||||
}
|
||||
}
|
||||
// Fall-through and just return default type
|
||||
strcpy_P(buff, mimeTable[sizeof(mimeTable)/sizeof(mimeTable[0])-1].mimeType);
|
||||
return String(buff);
|
||||
}
|
||||
|
||||
protected:
|
||||
FS _fs;
|
||||
String _uri;
|
||||
String _path;
|
||||
String _cache_header;
|
||||
bool _isFile;
|
||||
size_t _baseUriLength;
|
||||
};
|
||||
|
||||
|
||||
#endif //REQUESTHANDLERSIMPL_H
|
105
tools/server.py
105
tools/server.py
@ -1,105 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#original file and idea come from https://github.com/j0hnlittle
|
||||
|
||||
import SimpleHTTPServer, SocketServer
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
|
||||
#Replace this with a different path if you need to...
|
||||
base_path = os.path.join(os.getcwd(),"..","esp3d","data")
|
||||
tools_path = os.getcwd();
|
||||
server_port=8080
|
||||
|
||||
class MyHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
is_tpl, s = self.process_path(self.path)
|
||||
if is_tpl:
|
||||
self.send_response(301)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
|
||||
data = self.process_tpl(s)
|
||||
self.wfile.write(data)
|
||||
self.wfile.close()
|
||||
return
|
||||
SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
|
||||
|
||||
def process_path(self,s):
|
||||
#A template link is all caps and is associated to a lower().tpl file in base_path
|
||||
if s == "/":
|
||||
return True,"home.tpl"
|
||||
|
||||
ret = False,""
|
||||
s = s.replace("/","")
|
||||
if s.endswith(".tpl"):
|
||||
return True,s
|
||||
|
||||
s = s.lower()+".tpl"
|
||||
|
||||
#these do not exactly match, so let's make them!
|
||||
s = s.replace("configsta","config_sta")
|
||||
s = s.replace("configap","config_ap")
|
||||
s = s.replace("configsys","system")
|
||||
|
||||
if os.path.exists(os.path.join(base_path,s)):
|
||||
ret = True,s
|
||||
|
||||
return ret
|
||||
|
||||
def process_tpl(self,fn):
|
||||
p = re.compile('\$(.*?)\$')
|
||||
if fn.startswith("/") or fn.startswith("\\"):
|
||||
fn = fn[1:]
|
||||
|
||||
fn = os.path.join(base_path,fn)
|
||||
data = open(fn).read()
|
||||
|
||||
fn_json = os.path.join(tools_path,"tags.json")
|
||||
if os.path.exists(fn_json):
|
||||
json_dic = json.loads(open(fn_json).read())
|
||||
else:
|
||||
json_dic = {}
|
||||
|
||||
tags = p.findall(data)
|
||||
i = 0
|
||||
n_tags = len(tags)
|
||||
while i < n_tags:
|
||||
dd = self.process_tag(data,tags[i],json_dic)
|
||||
if dd != data:
|
||||
data = dd
|
||||
tags = p.findall(data)
|
||||
n_tags = len(tags)
|
||||
else:
|
||||
i = i+1
|
||||
return data
|
||||
|
||||
def process_tag(self, data, tag, json_dic={}):
|
||||
print " processing $%s$" % tag
|
||||
if tag in json_dic.keys():
|
||||
data = data.replace("$"+tag+"$",json_dic[tag])
|
||||
elif tag.startswith("INCLUDE[") and tag.endswith("]"):
|
||||
fn = tag[8:-1]
|
||||
fn = os.path.join(base_path,fn)
|
||||
d = open(fn).read()
|
||||
p0 = data.find("$"+tag)
|
||||
p1 = data.find("]",p0)+2
|
||||
data = data[:p0]+d+data[p1:]
|
||||
|
||||
return data
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "="*60
|
||||
print "Serving files from:"
|
||||
print base_path
|
||||
print "\ntags.json is located at:"
|
||||
print tools_path
|
||||
print "\nOpen your browser at http://localhost:" + str(server_port)
|
||||
|
||||
os.chdir(base_path)
|
||||
print "="*60
|
||||
handler = MyHandler
|
||||
server = SocketServer.TCPServer(("",server_port), handler)
|
||||
server.serve_forever()
|
||||
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"WEB_ADDRESS":"localhost:8080",
|
||||
"PAGE_TITLE":"Testing things..."
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user