mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-09-16 00:43:13 +08:00
Prepare branch
This commit is contained in:
parent
c3fbbd3c63
commit
a84d146921
52
.travis.yml
52
.travis.yml
@ -1,53 +1 @@
|
|||||||
sudo: false
|
|
||||||
|
|
||||||
language: bash
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16"
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- "export DISPLAY=:99.0"
|
|
||||||
- sleep 3 # give xvfb some time to start
|
|
||||||
- wget http://downloads.arduino.cc/arduino-1.8.4-linux64.tar.xz
|
|
||||||
- tar xf arduino-1.8.4-linux64.tar.xz
|
|
||||||
- mv arduino-1.8.4 $HOME/arduino_ide
|
|
||||||
- cd $HOME/arduino_ide/hardware
|
|
||||||
- mkdir esp8266com
|
|
||||||
- cd esp8266com
|
|
||||||
- git clone https://github.com/esp8266/Arduino.git esp8266
|
|
||||||
- cd esp8266/tools
|
|
||||||
- python get.py
|
|
||||||
- cd ..
|
|
||||||
- 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
|
|
||||||
|
|
||||||
|
|
||||||
script:
|
|
||||||
- cd $TRAVIS_BUILD_DIR
|
|
||||||
- source command.sh
|
|
||||||
- export PATH="$HOME/arduino_ide:$PATH"
|
|
||||||
- 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:
|
|
||||||
on_success: change
|
|
||||||
on_failure: change
|
|
||||||
|
138
README.md
138
README.md
@ -1,137 +1,3 @@
|
|||||||
# ESP3D[](https://codeclimate.com/github/luc-github/ESP3D)
|
# ESP3D 3.0
|
||||||
|
|
||||||
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)
|
<H1>Coming Soon!</H1>
|
||||||
|
|
||||||
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/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
|
|
||||||
Arduino ide 1.8.5 with stable [2.4.0](http://arduino.esp8266.com/versions/2.4.0/package_esp8266com_index.json) from ESP8266, please use https://github.com/luc-github/ESP3D/releases/tag/1.0 [](https://travis-ci.org/luc-github/ESP3D)
|
|
||||||
|
|
||||||
<u>[Development version for 2.0 (2.0 branch)](https://github.com/luc-github/ESP3D/tree/2.0) & [ESP-WEBUI (2.0 branch)](https://github.com/luc-github/ESP3D-WEBUI/tree/2.0):</u>
|
|
||||||
Arduino ide 1.8.5 with git version from ESP8266 or ESP32 for 100% support of ESP32 : [](https://travis-ci.org/luc-github/ESP3D)
|
|
||||||
|
|
||||||
[All releases](https://github.com/luc-github/ESP3D/wiki)
|
|
||||||
|
|
||||||
:+1:Thanks
|
|
||||||
* to @disneysw for bringing this module idea
|
|
||||||
* to @lkarlslund for suggestion about independent reset using GPIO2
|
|
||||||
* to Roy Cortes from http://www.panucatt.com for supporting and pushing me implementing great features
|
|
||||||
* to all contributors, feedbacks owners and donations.
|
|
||||||
|
|
||||||
## Donate
|
|
||||||
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.
|
|
||||||
|
|
||||||
## 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)
|
|
||||||
* 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)
|
|
||||||
* UI fully constomizable without reflashing FW using html templates, [keywords](https://raw.githubusercontent.com/luc-github/ESP3D/master/docs/keywords.txt) and html files/images
|
|
||||||
* Captive portal in Access point mode which redirect all unknow call to main page, here to enable/disable [CAPTIVE_PORTAL_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
|
||||||
* mDNS which allows to key the name defined in web browser and connect only with bonjour installed on computer, here to enable/disable [MDNS_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
|
||||||
* SSDP, this feature is a discovery protocol, supported on Windows out of the box, here to enable/disable [SSDP_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
|
||||||
* Printer monitoring / control (temperatures/speed/jog/list SDCard content/launch,pause or stop a print/etc...), here to enable/disable [MONITORING_FEATURE/INFO_MSG_FEATURE/ERROR_MSG_FEATURE/STATUS_MSG_FEATURE](https://github.com/luc-github/ESP3D/blob/master/esp3d/config.h)
|
|
||||||
* Fail safe mode (Access point)is enabled if cannot connect to defined station at boot.
|
|
||||||
* 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
|
|
||||||
*IP Generation: DHCP/Static IP
|
|
||||||
*IP/MASK/GATEWAY for static data
|
|
||||||
*Baud Rate for serial (supported : 9600, 19200, 38400, 57600, 115200, 230400, 250000)
|
|
||||||
*web port and data port
|
|
||||||
|
|
||||||
|
|
||||||
## Default Configuration
|
|
||||||
Default Settings:
|
|
||||||
AP:ESP8266
|
|
||||||
PW:12345678
|
|
||||||
Authentification: WPA
|
|
||||||
Mode: g (n is not supported by AP, just by STA)
|
|
||||||
channel: 11
|
|
||||||
AP: visible
|
|
||||||
Sleep Mode: Modem
|
|
||||||
IP Mode: Static IP
|
|
||||||
IP: 192.168.0.1
|
|
||||||
Mask: 255.255.255.0
|
|
||||||
GW:192.168.0.1
|
|
||||||
Baud rate: 115200
|
|
||||||
Web port:80
|
|
||||||
Data port: 8888
|
|
||||||
Web Page refresh: 3 secondes
|
|
||||||
User: admin
|
|
||||||
Password: admin
|
|
||||||
User:user
|
|
||||||
Password: user
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Direct commands:
|
|
||||||
Check wiki : https://github.com/luc-github/ESP3D/wiki/Direct-ESP3D-commands
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
1. Please follow installation of the ESP core you want to use : [ESP8266 core version](https://github.com/esp8266/Arduino) or [ESP32 core version](https://github.com/espressif/arduino-esp32)
|
|
||||||
2. Add missing libraries if you target ESP32 present in libraries directory
|
|
||||||
* DNSServer (from https://github.com/bbx10/DNSServer_tng)
|
|
||||||
* WebServer (from https://github.com/bbx10/WebServer_tng)
|
|
||||||
* NetBIOS and SSDP are currently disabled for ESP32 as not yet supported
|
|
||||||
3. Compile project (ESP3D.ino) according target: ESP8266 board or ESP32 board, please review config.h to enable disable a feature, by default athenticatio is disabled and all others are enabled.
|
|
||||||
* 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>
|
|
||||||
|
|
||||||
## Update
|
|
||||||
* Generate a binary using the export binary menu from Arduino IDE and upload it using ESP-WEBUI or embedded interface
|
|
||||||
|
|
||||||
<H3>:warning:Do not flash your Printer fw with ESP connected - it bring troubles, at least on DaVinci</H3>
|
|
||||||
|
|
||||||
## Contribution/customization
|
|
||||||
* 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
|
|
||||||
|
|
||||||
Feedback/suggestion/discussions are always welcome
|
|
||||||
|
|
||||||
## 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)
|
|
||||||
|
|
||||||
## ESP3D is used by :
|
|
||||||
* Custom version is used on azteeg mini wifi : http://www.panucatt.com/azteeg_X5_mini_reprap_3d_printer_controller_p/ax5mini.htm
|
|
||||||
* GRBL_Esp32 a GRBL port on ESP32 done by @bdring - https://github.com/bdring/Grbl_Esp32
|
|
||||||
[](https://www.youtube.com/watch?v=7vtWNn9jyDs)
|
|
||||||
* Marlin_ESP32 a Marlin port on ESP32 done by @simon-jouet is under sync : https://github.com/luc-github/Marlin/tree/eps32_webui
|
|
||||||
* More to come...
|
|
||||||
|
|
||||||
If you use ESP3D on your product, drop me a message so I can link your product page here.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## TODO/On going :
|
|
||||||
-- Version 2.X
|
|
||||||
-- Close open topics
|
|
||||||
-- Do testing (a lot)
|
|
||||||
-- UI Improvement
|
|
||||||
-- ESP3D V2
|
|
||||||
|
@ -1,840 +0,0 @@
|
|||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<style type="text/css">
|
|
||||||
.sliderthumb{
|
|
||||||
position : absolute;
|
|
||||||
cursor : pointer;
|
|
||||||
}
|
|
||||||
.sliderrange{
|
|
||||||
cursor : pointer;
|
|
||||||
}
|
|
||||||
.extlist{
|
|
||||||
position : absolute;
|
|
||||||
cursor : pointer;
|
|
||||||
}
|
|
||||||
body{
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-khtml-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
.hotspot{
|
|
||||||
cursor:pointer;
|
|
||||||
}
|
|
||||||
text.centerjog {
|
|
||||||
font-weight:600;
|
|
||||||
text-anchor:middle;
|
|
||||||
font-size:26;
|
|
||||||
font-family:sans-serif;
|
|
||||||
pointer-events:none;
|
|
||||||
}
|
|
||||||
text.home {
|
|
||||||
font-weight:800;
|
|
||||||
text-anchor:middle;
|
|
||||||
font-size:14;
|
|
||||||
font-family:sans-serif;
|
|
||||||
pointer-events:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
text.positionbar {
|
|
||||||
font-weight:600;
|
|
||||||
text-anchor:middle;
|
|
||||||
font-size:16;
|
|
||||||
font-family:sans-serif;
|
|
||||||
pointer-events:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
text.textpositionbar {
|
|
||||||
font-weight:400;
|
|
||||||
text-anchor:end;
|
|
||||||
font-size:12;
|
|
||||||
font-family:sans-serif;
|
|
||||||
pointer-events:none;
|
|
||||||
fill:#FF0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
text.textbutton {
|
|
||||||
font-weight:400;
|
|
||||||
text-anchor:middle;
|
|
||||||
font-size:26;
|
|
||||||
font-family:sans-serif;
|
|
||||||
fill:#FFFFFF;
|
|
||||||
filter:url(#emboss);
|
|
||||||
pointer-events:none;
|
|
||||||
}
|
|
||||||
path.msk {
|
|
||||||
fill:#0052E1;
|
|
||||||
}
|
|
||||||
circle.bg2 {
|
|
||||||
stroke:#0D2F38;
|
|
||||||
fill:#B93D3D;
|
|
||||||
pointer-events:none;
|
|
||||||
stroke-width:0.5;
|
|
||||||
}
|
|
||||||
circle.bg ,
|
|
||||||
path.bg {
|
|
||||||
stroke:#0D2F38;
|
|
||||||
fill:#608B98;
|
|
||||||
pointer-events:none;
|
|
||||||
stroke-width:0.5;
|
|
||||||
}
|
|
||||||
rect.bg
|
|
||||||
{
|
|
||||||
stroke:#0D2F38;
|
|
||||||
fill:#608B98;
|
|
||||||
pointer-events:none;
|
|
||||||
stroke-width:1;
|
|
||||||
}
|
|
||||||
rect.bgpositionbar
|
|
||||||
{
|
|
||||||
stroke:#707070;
|
|
||||||
fill:#BCCED3;
|
|
||||||
pointer-events:none;
|
|
||||||
stroke-width:1;
|
|
||||||
}
|
|
||||||
path.sign{
|
|
||||||
pointer-events:none;
|
|
||||||
fill:#000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.mskjog{
|
|
||||||
opacity:0;
|
|
||||||
fill:#0052E1;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</HEAD>
|
|
||||||
<BODY>
|
|
||||||
<script type="text/javascript">
|
|
||||||
function restore_x(e){
|
|
||||||
centerxytext.textContent='X/Y';
|
|
||||||
show_hide(e,0)
|
|
||||||
}
|
|
||||||
|
|
||||||
function changecolor(){
|
|
||||||
if (isDown)return;
|
|
||||||
var len = arguments.length;
|
|
||||||
if(len <2) return;
|
|
||||||
var color = arguments[len-1];
|
|
||||||
for(var i=0; i< len-1; i++)
|
|
||||||
{
|
|
||||||
arguments[i].style.fill=color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function changestroke(){
|
|
||||||
if (isDown)return;
|
|
||||||
var len = arguments.length;
|
|
||||||
if(len <2) return;
|
|
||||||
var color = arguments[len-1];
|
|
||||||
for(var i=0; i< len-1; i++)
|
|
||||||
{
|
|
||||||
arguments[i].style.stroke=color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function restore_z(e){
|
|
||||||
centerztext.textContent='Z';
|
|
||||||
show_hide(e,0);
|
|
||||||
}
|
|
||||||
function restore_e(e){
|
|
||||||
show_hide(extruder,1);
|
|
||||||
show_hide(centeretext,0);
|
|
||||||
show_hide(e,0);
|
|
||||||
}
|
|
||||||
function settext_e(text,e){
|
|
||||||
if (isDown)return;
|
|
||||||
show_hide(extruder,0);
|
|
||||||
centeretext.textContent=text;
|
|
||||||
show_hide(centeretext,1);
|
|
||||||
show_hide(e,0.5);
|
|
||||||
}
|
|
||||||
function show_hide(e,show){
|
|
||||||
e.style.opacity=show;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function settext_x(text,e){
|
|
||||||
if (isDown)return;
|
|
||||||
centerxytext.textContent=text;
|
|
||||||
show_hide(e,0.5)
|
|
||||||
}
|
|
||||||
|
|
||||||
function settext_z(text,e){
|
|
||||||
if (isDown)return;
|
|
||||||
centerztext.textContent=text;
|
|
||||||
show_hide(e,0.5);
|
|
||||||
}
|
|
||||||
var fan_on = 0;
|
|
||||||
var bed_on = 0;
|
|
||||||
var ext1_on = 0;
|
|
||||||
var ext2_on = 0;
|
|
||||||
|
|
||||||
//range functions
|
|
||||||
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) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//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>
|
|
||||||
<div id="positionbar">
|
|
||||||
<svg width="440" height="30" xmlns="http://www.w3.org/2000/svg" version="1.1" >
|
|
||||||
<defs>
|
|
||||||
<filter id="light" >
|
|
||||||
<feGaussianBlur in="SourceAlpha"
|
|
||||||
stdDeviation="2"
|
|
||||||
result="out1" />
|
|
||||||
<feSpecularLighting in="out1"
|
|
||||||
surfaceScale="8"
|
|
||||||
specularConstant="2"
|
|
||||||
specularExponent="12"
|
|
||||||
result="out3">
|
|
||||||
<feDistantLight azimuth="225" elevation="5" />
|
|
||||||
</feSpecularLighting>
|
|
||||||
<feComposite operator="in" in="out3" in2="SourceAlpha" result="out4"/>
|
|
||||||
<feMerge>
|
|
||||||
<feMergeNode in="SourceGraphic" />
|
|
||||||
<feMergeNode in="out4"/>
|
|
||||||
</feMerge>
|
|
||||||
</filter>
|
|
||||||
<filter id="shadow" width="200%" height="200%">
|
|
||||||
<feGaussianBlur in="SourceAlpha"
|
|
||||||
stdDeviation="2"
|
|
||||||
result="out1" />
|
|
||||||
<feOffset in="out1"
|
|
||||||
dx="2" dy="2"
|
|
||||||
result="out2" />
|
|
||||||
<feComposite in="SourceGraphic" in2="out2"
|
|
||||||
operator="over" />
|
|
||||||
</filter>
|
|
||||||
</defs>
|
|
||||||
<g id="posxtext">
|
|
||||||
<rect class="bg" x="0" y="0" width="107" height="27" filter="url(#shadow)"/>
|
|
||||||
<rect class="bg" x="0" y="0" width="107" height="27" opacity="0.7" filter="url(#light)"/>
|
|
||||||
<text x="13" y="19.5" class="positionbar">X</text>
|
|
||||||
<rect class="bgpositionbar" x="25" y="5.5" width="72" height="17" />
|
|
||||||
<text id="posx" x="95" y="19" class="textpositionbar">0.00</text>
|
|
||||||
</g>
|
|
||||||
<g id="posytext">
|
|
||||||
<rect class="bg" x="107" y="0" width="107" height="27" filter="url(#shadow)"/>
|
|
||||||
<rect class="bg" x="107" y="0" width="107" height="27" opacity="0.7" filter="url(#light)"/>
|
|
||||||
<text x="120" y="19.5" class="positionbar">Y</text>
|
|
||||||
<rect class="bgpositionbar" x="132" y="5.5" width="72" height="17" />
|
|
||||||
<text id="posy" x="202" y="19" class="textpositionbar">100.00</text>
|
|
||||||
</g>
|
|
||||||
<g id="posztext">
|
|
||||||
<rect class="bg" x="214" y="0" width="107" height="27" filter="url(#shadow)"/>
|
|
||||||
<rect class="bg" x="214" y="0" width="107" height="27" opacity="0.7" filter="url(#light)"/>
|
|
||||||
<text x="227" y="19.5" class="positionbar">Z</text>
|
|
||||||
<rect class="bgpositionbar" x="239" y="5.5" width="72" height="17" />
|
|
||||||
<text id="posz" x="309" y="19" class="textpositionbar">0.00</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="posextruderlist">
|
|
||||||
<rect class="bg" x="321" y="0" width="107" height="27" filter="url(#shadow)"/>
|
|
||||||
<rect class="bg" x="321" y="0" width="107" height="27" opacity="0.7" filter="url(#light)"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div id="extruderlist" class="extlist">
|
|
||||||
<select id="activeextruder">
|
|
||||||
<option value="0" selected>Extruder 1</option>
|
|
||||||
<option value="1">Extruder 2</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div id="jogPanel">
|
|
||||||
<svg width="440" height="230" xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 440 230">
|
|
||||||
<defs>
|
|
||||||
<filter id="light" >
|
|
||||||
<feGaussianBlur in="SourceAlpha"
|
|
||||||
stdDeviation="2"
|
|
||||||
result="out1" />
|
|
||||||
<feSpecularLighting in="out1"
|
|
||||||
surfaceScale="8"
|
|
||||||
specularConstant="2"
|
|
||||||
specularExponent="12"
|
|
||||||
result="out3">
|
|
||||||
<feDistantLight azimuth="225" elevation="5" />
|
|
||||||
</feSpecularLighting>
|
|
||||||
<feComposite operator="in" in="out3" in2="SourceAlpha" result="out4"/>
|
|
||||||
<feMerge>
|
|
||||||
<feMergeNode in="SourceGraphic" />
|
|
||||||
<feMergeNode in="out4"/>
|
|
||||||
</feMerge>
|
|
||||||
</filter>
|
|
||||||
|
|
||||||
<filter id="shadow" width="200%" height="200%">
|
|
||||||
<feGaussianBlur in="SourceAlpha"
|
|
||||||
stdDeviation="2"
|
|
||||||
result="out1" />
|
|
||||||
<feOffset in="out1"
|
|
||||||
dx="2" dy="2"
|
|
||||||
result="out2" />
|
|
||||||
<feComposite in="SourceGraphic" in2="out2"
|
|
||||||
operator="over" />
|
|
||||||
</filter>
|
|
||||||
|
|
||||||
<filter id="emboss" x0="-50%" y0="-50%" width="200%" height="200%">
|
|
||||||
<feMorphology in="SourceAlpha" operator="dilate" radius="1"/>
|
|
||||||
<feGaussianBlur stdDeviation="1" result="blur"/>
|
|
||||||
|
|
||||||
<feOffset dy="0.2" dx="0.2"/>
|
|
||||||
<feComposite in2="SourceAlpha" operator="arithmetic"
|
|
||||||
k2="1" k3="-1" result="hlDiff"/>
|
|
||||||
<feFlood flood-color="white" flood-opacity=".7"/>
|
|
||||||
<feComposite in2="hlDiff" operator="in"/>
|
|
||||||
<feComposite in2="SourceGraphic" operator="over" result="withGlow"/>
|
|
||||||
|
|
||||||
<feOffset in="blur" dy="-0.2" dx="-0.2"/>
|
|
||||||
<feComposite in2="SourceAlpha" operator="arithmetic"
|
|
||||||
k2="1" k3="-1" result="shadowDiff"/>
|
|
||||||
<feFlood flood-color="black" flood-opacity="1"/>
|
|
||||||
<feComposite in2="shadowDiff" operator="in"/>
|
|
||||||
<feComposite in2="withGlow" operator="over"/>
|
|
||||||
</filter>
|
|
||||||
</defs>
|
|
||||||
<g id="Jog" transform="translate(0,-30)">
|
|
||||||
<g id="homeall" transform="translate(10,175)" onmouseup="alert('all');" onmouseover="changecolor(ha1,ha2,ha3,ha4,'#2F65FF');" onmouseout="changecolor(ha1,ha2,ha3,ha4,'#608B98');">
|
|
||||||
<circle cx='17' cy='17' r='18' fill='white' />
|
|
||||||
<path class="bg" id="ha1" d="M1,15 L14,2 L16,1 L18,1 L20,2 L23,5 L23,2 L24,1 L27,1 L28,2 L28,10 L33,15 L30,18 L19,7 L15,7 L4,18 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" id="ha2" d="M1,15 L14,2 L16,1 L18,1 L20,2 L23,5 L23,2 L24,1 L27,1 L28,2 L28,10 L33,15 L30,18 L19,7 L15,7 L4,18 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path class="bg" id="ha3" d="M6,19 L16,9 L18,9 L28,19 L28,28 L6,28 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" id="ha4" d="M6,19 L16,9 L18,9 L28,19 L28,28 L6,28 z" filter="url(#shadow)" opacity='0.7' filter="url(#light)"/>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="homex" transform="translate(10,35)" onmouseup="alert('X');" onmouseover="changecolor(hx1,hx2,hx3,hx4,'#2F65FF');" onmouseout="changecolor(hx1,hx2,hx3,hx4,'#608B98');">
|
|
||||||
<circle cx='17' cy='17' r='18' fill='white' />
|
|
||||||
<path class="bg" id="hx1" d="M1,15 L14,2 L16,1 L18,1 L20,2 L23,5 L23,2 L24,1 L27,1 L28,2 L28,10 L33,15 L30,18 L19,7 L15,7 L4,18 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" id="hx2" d="M1,15 L14,2 L16,1 L18,1 L20,2 L23,5 L23,2 L24,1 L27,1 L28,2 L28,10 L33,15 L30,18 L19,7 L15,7 L4,18 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path class="bg" id="hx3" d="M6,19 L16,9 L18,9 L28,19 L28,28 L6,28 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" id="hx4" d="M6,19 L16,9 L18,9 L28,19 L28,28 L6,28 z" filter="url(#shadow)" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<text x="17" y="26" class="home">X</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="homey" transform="translate(159,35)" onmouseup="alert('y');" onmouseover="changecolor(hy1,hy2,hy3,hy4,'#2F65FF');" onmouseout="changecolor(hy1,hy2,hy3,hy4,'#608B98');">
|
|
||||||
<circle cx='17' cy='17' r='18' fill='white' />
|
|
||||||
<path class="bg" id="hy1" d="M1,15 L14,2 L16,1 L18,1 L20,2 L23,5 L23,2 L24,1 L27,1 L28,2 L28,10 L33,15 L30,18 L19,7 L15,7 L4,18 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" id="hy2" d="M1,15 L14,2 L16,1 L18,1 L20,2 L23,5 L23,2 L24,1 L27,1 L28,2 L28,10 L33,15 L30,18 L19,7 L15,7 L4,18 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path class="bg" id="hy3" d="M6,19 L16,9 L18,9 L28,19 L28,28 L6,28 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" id="hy4" d="M6,19 L16,9 L18,9 L28,19 L28,28 L6,28 z" filter="url(#shadow)" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<text x="17" y="26" class="home">Y</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="homez" transform="translate(159,175)" onmouseup="alert('z');" onmouseover="changecolor(hz1,hz2,hz3,hz4,'#2F65FF');" onmouseout="changecolor(hz1,hz2,hz3,hz4,'#608B98');">
|
|
||||||
<circle cx='17' cy='17' r='18' fill='white' />
|
|
||||||
<path class="bg" id="hz1" d="M1,15 L14,2 L16,1 L18,1 L20,2 L23,5 L23,2 L24,1 L27,1 L28,2 L28,10 L33,15 L30,18 L19,7 L15,7 L4,18 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" id="hz2" d="M1,15 L14,2 L16,1 L18,1 L20,2 L23,5 L23,2 L24,1 L27,1 L28,2 L28,10 L33,15 L30,18 L19,7 L15,7 L4,18 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path class="bg" id="hz3" d="M6,19 L16,9 L18,9 L28,19 L28,28 L6,28 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" id="hz4" d="M6,19 L16,9 L18,9 L28,19 L28,28 L6,28 z" filter="url(#shadow)" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<text x="17" y="26" class="home">Z</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="topxy">
|
|
||||||
<path class="bg" d="M48,70 A 74,74 0 0,1 154,70 L126,98 A 35,35 0 0 0 76,98 z" filter="url(#shadow)" />
|
|
||||||
<path class="bg" d="M48,70 A 74,74 0 0,1 154,70 L126,98 A 35,35 0 0 0 76,98 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path onmouseup="alert(1);" onmouseover="settext_x('50',this);" onmouseout="restore_x(this);" class="mskjog" d="M48,70 A 74,74 0 0,1 154,70 L126,98 A 35,35 0 0 0 76,98 z" />
|
|
||||||
<path onmouseup="alert(2);" onmouseover="settext_x('10',this);" onmouseout="restore_x(this);" class="mskjog" d="M55,77 A 64,64 0 0,1 147,77 L126,98 A 35,35 0 0 0 76,98 z" />
|
|
||||||
<path onmouseup="alert(3);" onmouseover="settext_x('1',this);" onmouseout="restore_x(this);" class="mskjog" d="M62,84 A 54,54 0 0,1 140,84 L126,98 A 35,35 0 0 0 76,98 z" />
|
|
||||||
<path onmouseup="alert(4);" onmouseover="settext_x('0,1',this);" onmouseout="restore_x(this);" class="mskjog" d="M69,91 A 44,44 0 0,1 133,91 L126,98 A 35,35 0 0 0 76,98 z"/>
|
|
||||||
<path class='sign' d="M101,58 L112,76 L90,76 z" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="rightxy">
|
|
||||||
<path class="bg" d="M154,70 A 74,74 0 0,1 154,174 L126,146 A 35,35 0 0 0 126,98 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" d="M154,70 A 74,74 0 0,1 154,174 L126,146 A 35,35 0 0 0 126,98 z" opacity=0.7 filter="url(#light)"/>
|
|
||||||
<path onmouseup="alert(13);" onmouseover="settext_x('50',this);" onmouseout="restore_x(this);" class="mskjog" d="M154,70 A 74,74 0 0,1 154,174 L126,146 A 35,35 0 0 0 126,98 z"/>
|
|
||||||
<path onmouseup="alert(14);" onmouseover="settext_x('10',this);" onmouseout="restore_x(this);" class="mskjog" d="M147,77 A 64,64 0 0,1 147,167 L126,146 A 35,35 0 0 0 126,98 z"/>
|
|
||||||
<path onmouseup="alert(15);" onmouseover="settext_x('1',this);" onmouseout="restore_x(this);" class="mskjog" d="M140,84 A 54,54 0 0,1 140,160 L126,146 A 35,35 0 0 0 126,98 z"/>
|
|
||||||
<path onmouseup="alert(16);" onmouseover="settext_x('0,1',this);" onmouseout="restore_x(this);" class="mskjog" d="M133,91 A 44,44 0 0,1 133,153 L126,146 A 35,35 0 0 0 126,98 z"/>
|
|
||||||
<path class='sign' d="M165,122 L148,112 L148,132 z" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="bottomxy">
|
|
||||||
<path class="bg" d="M48,174 A 74,74 0 0,0 154,174 L126,146 A 35,35 0 0 1 76,146 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" d="M48,174 A 74,74 0 0,0 154,174 L126,146 A 35,35 0 0 1 76,146 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path onmouseup="alert(8);" onmouseover="settext_x('-50',this);" onmouseout="restore_x(this);" class="mskjog" d="M48,174 A 74,74 0 0,0 154,174 L126,146 A 35,35 0 0 1 76,146 z" />
|
|
||||||
<path onmouseup="alert(7);" onmouseover="settext_x('-10',this);" onmouseout="restore_x(this);" class="mskjog" d="M55,167 A 64,64 0 0,0 147,167 L126,146 A 35,35 0 0 1 76,146 z" />
|
|
||||||
<path onmouseup="alert(6);" onmouseover="settext_x('-1',this);" onmouseout="restore_x(this);" class="mskjog" d="M62,160 A 54,54 0 0,0 140,160 L126,146 A 35,35 0 0 1 76,146 z" />
|
|
||||||
<path onmouseup="alert(5);" onmouseover="settext_x('-0,1',this);" onmouseout="restore_x(this);" class="mskjog" d="M69,153 A 44,44 0 0,0 133,153 L126,146 A 35,35 0 0 1 76,146 z" />
|
|
||||||
<path class='sign' d="M101,186 L112,168 L90,168 z" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="leftxy">
|
|
||||||
<path class="bg" d="M48,174 A 74,74 0 0,1 48,70 L76,98 A 35,35 0 0 0 76,146 z"/>
|
|
||||||
<path class="bg" d="M48,174 A 74,74 0 0,1 48,70 L76,98 A 35,35 0 0 0 76,146 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path onmouseup="alert(9);" onmouseover="settext_x('-50',this);" onmouseout="restore_x(this);" class="mskjog" d="M48,174 A 74,74 0 0,1 48,70 L76,98 A 35,35 0 0 0 76,146 z" />
|
|
||||||
<path onmouseup="alert(10);" onmouseover="settext_x('-10',this);" onmouseout="restore_x(this);" class="mskjog" d="M55,167 A 64,64 0 0,1 55,77 L76,98 A 35,35 0 0 0 76,146 z" />
|
|
||||||
<path onmouseup="alert(11);" onmouseover="settext_x('-1',this);" onmouseout="restore_x(this);" class="mskjog" d="M62,160 A 54,54 0 0,1 62,84 L76,98 A 35,35 0 0 0 76,146 z" />
|
|
||||||
<path onmouseup="alert(12);" onmouseover="settext_x('-0,1',this);" onmouseout="restore_x(this);" class="mskjog" d="M69,153 A 44,44 0 0,1 69,91 L76,98 A 35,35 0 0 0 76,146 z" />
|
|
||||||
<path class='sign' d="M37,122 L54,112 L54,132 z" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id=''centerxy">
|
|
||||||
<circle class="bg" cx="101" cy="122" r="34" " />
|
|
||||||
<circle class="bg" cx="101" cy="122" r="34" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<text id="centerxytext" class="centerjog" x="101" y="132">X/Y</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="topz">
|
|
||||||
<path class="bg" d="M214,56 A 74,74 0 0,1 288,56 L268,92 A 35,35 0 0 0 234,92 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" d="M214,56 A 74,74 0 0,1 288,56 L268,92 A 35,35 0 0 0 234,92 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path onmouseup="alert(17);" onmouseover="settext_z('10',this);" onmouseout="restore_z(this);" class="mskjog" d="M214,56 A 74,74 0 0,1 288,56 L268,92 A 35,35 0 0 0 234,92 z" />
|
|
||||||
<path onmouseup="alert(18);" onmouseover="settext_z('1',this);" onmouseout="restore_z(this);" class="mskjog" d="M219,65 A 64,64 0 0,1 283,65 L268,92 A 35,35 0 0 0 234,92 z" />
|
|
||||||
<path onmouseup="alert(19);" onmouseover="settext_z('0,1',this);" onmouseout="restore_z(this);" class="mskjog" d="M224,74 A 54,54 0 0,1 278,74 L268,92 A 35,35 0 0 0 234,92 z" />
|
|
||||||
<path onmouseup="alert(20);" onmouseover="settext_z('0,01',this);" onmouseout="restore_z(this);" class="mskjog" d="M229,83 A 44,44 0 0,1 273,83 L268,92 A 35,35 0 0 0 234,92 z" />
|
|
||||||
<path class='sign' d="M251,58 L262,76 L240,76 z" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id=''centerz">
|
|
||||||
<circle class="bg" cx="251" cy="122" r="34" filter="url(#shadow)" />
|
|
||||||
<circle class="bg" cx="251" cy="122" r="34" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<text id="centerztext" class="centerjog" x="251" y="132">Z</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="bottomz">
|
|
||||||
<path class="bg" d="M214,188 A 75,75 0 0,0 288,188 L268,152 A 36,36 0 0 1 234,152 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" d="M214,188 A 75,75 0 0,0 288,188 L268,152 A 36,36 0 0 1 234,152 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path onmouseup="alert(21);" onmouseover="settext_z('-10',this);" onmouseout="restore_z(this);" class="mskjog" d="M214,188 A 74,74 0 0,0 288,188 L268,152 A 35,35 0 0 1 234,152 z" />
|
|
||||||
<path onmouseup="alert(22);" onmouseover="settext_z('-1',this);" onmouseout="restore_z(this);" class="mskjog" d="M219,179 A 64,64 0 0,0 283,179 L268,152 A 35,35 0 0 1 234,152 z" />
|
|
||||||
<path onmouseup="alert(23);" onmouseover="settext_z('-0,1',this);" onmouseout="restore_z(this);" class="mskjog" d="M224,170 A 54,54 0 0,0 278,170 L268,152 A 35,35 0 0 1 234,152 z" />
|
|
||||||
<path onmouseup="alert(24);" onmouseover="settext_z('-0,01',this);" onmouseout="restore_z(this);" class="mskjog" d="M229,161 A 44,44 0 0,0 273,161 L268,152 A 35,35 0 0 1 234,152 z" />
|
|
||||||
<path class='sign' d="M251,186 L262,168 L240,168 z"/>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="tope">
|
|
||||||
<path class="bg" d="M317,56 A 74,74 0 0,1 391,56 L371,92 A 35,35 0 0 0 337,92 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" d="M317,56 A 74,74 0 0,1 391,56 L371,92 A 35,35 0 0 0 337,92 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path onmouseup="alert(25);" onmouseover="settext_e('-100',this);" onmouseout="restore_e(this);" class="mskjog" d="M317,56 A 74,74 0 0,1 391,56 L371,92 A 35,35 0 0 0 337,92 z" />
|
|
||||||
<path onmouseup="alert(26);" onmouseover="settext_e('-50',this);" onmouseout="restore_e(this);" class="mskjog" d="M322,65 A 64,64 0 0,1 385,65 L371,92 A 35,35 0 0 0 337,92 z" />
|
|
||||||
<path onmouseup="alert(27);" onmouseover="settext_e('-10',this);" onmouseout="restore_e(this);" class="mskjog" d="M327,74 A 54,54 0 0,1 381,74 L371,92 A 35,35 0 0 0 337,92 z" />
|
|
||||||
<path onmouseup="alert(28);" onmouseover="settext_e('-1',this);" onmouseout="restore_e(this);" class="mskjog" d="M332,83 A 44,44 0 0,1 376,83 L371,92 A 35,35 0 0 0 337,92 z" />
|
|
||||||
<path class='sign' d="M354,58 L365,76 L343,76 z" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<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"></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"/>
|
|
||||||
<circle cx="340.5" cy="118.5" r="3.5" fill="#608B98" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="bottome2">
|
|
||||||
<path class="bg"d="M317,188 A 74,74 0 0,0 354,197 L354,156.5 A 35,35 0 0 1 337,152 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" d="M317,188 A 74,74 0 0,0 354,197 L354,156.5 A 35,35 0 0 1 337,152 z" opacity='0.7' filter="url(#light)" />
|
|
||||||
<path onmouseup="alert(29);" onmouseover="settext_e('100',this);" onmouseout="restore_e(this);" class="mskjog" d="M317,188 A 74,74 0 0,0 354,197 L354,156.5 A 35,35 0 0 1 337,152 z"/>
|
|
||||||
<path onmouseup="alert(30);" onmouseover="settext_e('50',this);" onmouseout="restore_e(this);" class="mskjog" d="M322,179 A 64,64 0 0,0 354,187 L354,156.5 A 35,35 0 0 1 337,152 z" />
|
|
||||||
<path onmouseup="alert(31);" onmouseover="settext_e('10',this);" onmouseout="restore_e(this);" class="mskjog" d="M327,170 A 54,54 0 0,0 354,177 L354,156.5 A 35,35 0 0 1 337,152 z" />
|
|
||||||
<path onmouseup="alert(32);" onmouseover="settext_e('1',this);" onmouseout="restore_e(this);" class="mskjog" d="M332,161 A 44,44 0 0,0 354,167 L354,156.5 A 35,35 0 0 1 337,152 z" />
|
|
||||||
<path class='sign' d="M337,171 L347,174 L339.5,182 z"/>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="bottome1">
|
|
||||||
<path class="bg" d="M354,197 A 74,74 0 0,0 391,188 L371,152 A 35,35 0 0 1 354,156.5 z" filter="url(#shadow)"/>
|
|
||||||
<path class="bg" d="M354,197 A 74,74 0 0,0 391,188 L371,152 A 35,35 0 0 1 354,156.5 z" opacity='0.7' filter="url(#light)" />
|
|
||||||
<path onmouseup="alert(33);" onmouseover="settext_e('100',this);" onmouseout="restore_e(this);" class="mskjog" d="M354,197 A 74,74 0 0,0 391,188 L371,152 A 35,35 0 0 1 354,156.5 z"/>
|
|
||||||
<path onmouseup="alert(34);" onmouseover="settext_e('50',this);" onmouseout="restore_e(this);" class="mskjog" d="M354,187 A 64,64 0 0,0 386,179 L371,152 A 35,35 0 0 1 354,156.5 z" />
|
|
||||||
<path onmouseup="alert(35);" onmouseover="settext_e('10',this);" onmouseout="restore_e(this);" class="mskjog" d="M354,177 A 54,54 0 0,0 381,170 L371,152 A 35,35 0 0 1 354,156.5 z" />
|
|
||||||
<path onmouseup="alert(36);" onmouseover="settext_e('1',this);" onmouseout="restore_e(this);" class="mskjog" d="M354,167 A 54,54 0 0,0 376,161 L371,152 A 35,35 0 0 1 354,156.5 z" />
|
|
||||||
<path class='sign' d="M361,170 L372,167 L369.5,178 z"/>
|
|
||||||
<path class='sign' d="M364,180 L375,177 L372,188 z"/>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="poweroff" transform="translate(11,220)" onmouseup="alert('power');" onmouseover="changecolor(poweroff1,poweroff2,poweroff3,poweroff4,'#2F65FF');" onmouseout="changecolor(poweroff1,poweroff2,poweroff3,poweroff4,'#608B98');">
|
|
||||||
<circle cx='17' cy='18' r='16' fill='white' />
|
|
||||||
<path id="poweroff1" class="bg" d="M8,6 A15 15 0 1 0 26,6 A 3,3 0 0 0 22,10 A 10,10 0 1 1 12,10 A 3,3 0 0 0 8,6z" filter="url(#shadow)"/>
|
|
||||||
<path id="poweroff2" class="bg" d="M8,6 A15 15 0 1 0 26,6 A 3,3 0 0 0 22,10 A 10,10 0 1 1 12,10 A 3,3 0 0 0 8,6z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<path id="poweroff3" class="bg" d="M14,2 A4,4 0 0 1 20,2 L20,15 A4,4 0 0 1 14,15z" filter="url(#shadow)" />
|
|
||||||
<path id="poweroff4" class="bg" d="M14,2 A4,4 0 0 1 20,2 L20,15 A4,4 0 0 1 14,15z" opacity='0.7' filter="url(#light)" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="button_M" transform="translate(56,220)" onmouseup="alert('Button M');" onmouseover="changecolor(buttonM1,buttonM2,buttonM3,buttonM4,buttonM5,buttonM6,'#2F65FF');" onmouseout="changecolor(buttonM1,buttonM2,buttonM3,buttonM4,buttonM5,buttonM6,'#608B98');">
|
|
||||||
<circle cx='17' cy='18' r='16' fill='white' />
|
|
||||||
<circle id="buttonM1" class='bg' cx="16" cy="16" r="15" filter="url(#shadow)"/>
|
|
||||||
<circle id="buttonM2" class='bg' cx="16" cy="16" r="15" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<circle cx="16" cy="16" r="12" fill="white" stroke="#0D2F38"/>
|
|
||||||
<path id="buttonM3" class="bg" d="M5,15 L9,15 L9,12 L11,10 L24,10 L25,11 L25,21 L24,22 L11,22 L9,20 L9,17 L5,17 z" />
|
|
||||||
<path id="buttonM4" class="bg" d="M5,15 L9,15 L9,12 L11,10 L24,10 L25,11 L25,21 L24,22 L11,22 L9,20 L9,17 L5,17 z" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<rect x="13" y="13" width="10" height="1" fill="white" stroke="none"/>
|
|
||||||
<rect x="12" y="16" width="11" height="1" fill="white" stroke="none"/>
|
|
||||||
<rect x="13" y="19" width="10" height="1" fill="white" stroke="none"/>
|
|
||||||
<path id="buttonM5" d="M24,4 L4,24 L7,27 L27,7 z" fill="#608B98" stroke="none" />
|
|
||||||
<path id="buttonM6" d="M24,4 L4,24 L7,27 L27,7 z" fill="#608B98" stroke="none" opacity='0.7' filter="url(#light)"/>
|
|
||||||
<line x1="22" y1="6" x2="6" y2="22" stroke="#0D2F38" />
|
|
||||||
<line x1="8" y1="25.5" x2="25.5" y2="8" stroke="#0D2F38" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="button_P" transform="translate(101,220)" onmouseup="alert('Button P');" onmouseover="changecolor(buttonP1,buttonP2,'#2F65FF');" onmouseout="changecolor(buttonP1,buttonP2,'#608B98');">
|
|
||||||
<circle cx='17' cy='18' r='16' fill='white' />
|
|
||||||
<circle id="buttonP1" class='bg' cx="16" cy="16" r="15" filter="url(#shadow)"/>
|
|
||||||
<circle id="buttonP2" class='bg' cx="16" cy="16" r="15" opacity='0.7' filter="url(#light)" />
|
|
||||||
<text class="textbutton" x="16" y="26" filter="url(#emboss)">P</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="button_1" transform="translate(146,220)" onmouseup="alert('Button 1');" onmouseover="changecolor(button11,button12,'#2F65FF');" onmouseout="changecolor(button11,button12,'#608B98');">
|
|
||||||
<circle cx='17' cy='18' r='16' fill='white' />
|
|
||||||
<circle id="button11" class='bg' cx="16" cy="16" r="15" filter="url(#shadow)"/>
|
|
||||||
<circle id="button12" class='bg' cx="16" cy="16" r="15" opacity='0.7' filter="url(#light)" />
|
|
||||||
<text class="textbutton" x="16" y="26" filter="url(#emboss)">1</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="button_2" transform="translate(191,220)" onmouseup="alert('Button 2');" onmouseover="changecolor(button21,button22,'#2F65FF');" onmouseout="changecolor(button21,button22,'#608B98');">
|
|
||||||
<circle cx='17' cy='18' r='16' fill='white' />
|
|
||||||
<circle id="button21" class='bg' cx="16" cy="16" r="15" filter="url(#shadow)"/>
|
|
||||||
<circle id="button22"class='bg' cx="16" cy="16" r="15" opacity='0.7' filter="url(#light)" />
|
|
||||||
<text class="textbutton" x="16" y="26" filter="url(#emboss)">2</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="button_3" transform="translate(236,220)" onmouseup="alert('Button 3');" onmouseover="changecolor(button31,button32,'#2F65FF');" onmouseout="changecolor(button31,button32,'#608B98');">
|
|
||||||
<circle cx='17' cy='18' r='16' fill='white' />
|
|
||||||
<circle id="button31" class='bg' cx="16" cy="16" r="15" filter="url(#shadow)"/>
|
|
||||||
<circle id="button32" class='bg' cx="16" cy="16" r="15" opacity='0.7' filter="url(#light)" />
|
|
||||||
<text class="textbutton" x="16" y="26" filter="url(#emboss)">3</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="button_4" transform="translate(281,220)" onmouseup="alert('Button 4');" onmouseover="changecolor(button41,button42,'#2F65FF');" onmouseout="changecolor(button41,button42,'#608B98');">
|
|
||||||
<circle cx='17' cy='18' r='16' fill='white' />
|
|
||||||
<circle id="button41" class='bg' cx="16" cy="16" r="15" filter="url(#shadow)"/>
|
|
||||||
<circle id="button42" class='bg' cx="16" cy="16" r="15" opacity='0.7' filter="url(#light)" />
|
|
||||||
<text class="textbutton" x="16" y="26" filter="url(#emboss)">4</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="button_5" transform="translate(326,220)" onmouseup="alert('Button 5');" onmouseover="changecolor(button51,button52,'#2F65FF');" onmouseout="changecolor(button51,button52,'#608B98');">
|
|
||||||
<circle cx='17' cy='18' r='16' fill='white' />
|
|
||||||
<circle id="button51" class='bg' cx="16" cy="16" r="15" filter="url(#shadow)"/>
|
|
||||||
<circle id="button52" class='bg' cx="16" cy="16" r="15" opacity='0.7' filter="url(#light)" />
|
|
||||||
<text class="textbutton" x="16" y="26" filter="url(#emboss)">5</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g id="button_Q" transform="translate(371,220)" onmouseup="alert('Button Q');" onmouseover="changecolor(buttonQ1,buttonQ2,'#2F65FF');" onmouseout="changecolor(buttonQ1,buttonQ2,'#B93D3D');">
|
|
||||||
<circle cx='17' cy='18' r='16' fill='white' />
|
|
||||||
<circle id="buttonQ1" class='bg2' cx="16" cy="16" r="15" filter="url(#shadow)"/>
|
|
||||||
<circle id="buttonQ2" class='bg2' cx="16" cy="16" r="15" opacity='0.7' filter="url(#light)" />
|
|
||||||
<text class="textbutton" x="16" y="26" filter="url(#emboss)">?</text>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div style='margin-left: 0cm;' >
|
|
||||||
<table style='border-spacing: 5px'>
|
|
||||||
<tr ><td width='auto' align='middle'>
|
|
||||||
<svg width="22" height="22" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 300 300">
|
|
||||||
<defs>
|
|
||||||
<filter id="blurMe"><feGaussianBlur in="SourceGraphic" stdDeviation="6" /></filter>
|
|
||||||
</defs>
|
|
||||||
<circle cx="263" cy="38" r="32" />
|
|
||||||
<path d="M150,176 L55,279 A 12,12 0 0 1 36,258 L186,72 L162,50 L123,91 A 9,9 0 0 1 109,74 L145,28 A 20,20 0 0 1 171,22 L229,70 A 20,20 0 0 1 230,81 L230,140 L272,143 A 8,8 0 0 1 274,167 L221,165 A 20,20 0 0 1 205,149 L205,96 L168,144 L231,207 A 20,20 0 0 1 225,234 L132,258 A 9,9 0 0 1 126,231 L188,211 z " />
|
|
||||||
<rect x="7" y="39" width="125" rx="6" ry="6" height="12" fill ="#656565" stroke-width='12' opacity="0.7" filter="url(#blurMe)"/>
|
|
||||||
<rect x="70" y="76" width="30" rx="6" ry="6" height="12" fill ="#656565" stroke-width='12' opacity="0.7" filter="url(#blurMe)"/>
|
|
||||||
<rect x="24" y="130" width="110" rx="6" ry="6" height="12" fill ="#656565" stroke-width='12' opacity="0.7" filter="url(#blurMe)"/>
|
|
||||||
<rect x="66" y="148" width="50" rx="6" ry="6" height="12" fill ="#656565" stroke-width='12' opacity="0.7" filter="url(#blurMe)"/>
|
|
||||||
<rect x="8" y="172" width="90" rx="6" ry="6" height="12" fill ="#656565" stroke-width='12' opacity="0.7" filter="url(#blurMe)"/>
|
|
||||||
</svg></td>
|
|
||||||
<td width='auto' >
|
|
||||||
<div id='rangefeedrate' min="25" max="300" class='sliderrange' onclick ="rangeclicked(event,this);" customthumb='thumbfeedrate'>
|
|
||||||
<svg width='322' height='20' viewbox='0 0 322 20'>
|
|
||||||
<defs>
|
|
||||||
<pattern id='basicPattern' x='10' y='0' width='4' height='20' patternUnits='userSpaceOnUse'>
|
|
||||||
<rect x='0' y='0' width='4' height='20' stroke-width='0.2' stroke= '#0D2F38' fill='#77AEBD'/ >
|
|
||||||
</pattern>
|
|
||||||
</defs>
|
|
||||||
<rect x='1' y='4' width='320' height='12' stroke= '#0D2F38' stroke-width='1' rx='6' ry='6' fill='url(#basicPattern)'/>
|
|
||||||
<text x='13' y='14' style='font-weight:600;font-size:10;font-family:sans-serif;fill:#000000; pointer-events:none;'>Feedrate</text>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div id='thumbfeedrate' class='sliderthumb' render='feedraterender' customrange='rangefeedrate'>
|
|
||||||
<svg width='8' height='20' viewbox='0 0 8 20'><path d='M 3.5,0 L7,5 L7,14 L3.5,19 L0,14 L0,5 z' /></svg>
|
|
||||||
</div>
|
|
||||||
</td><td width='auto'><input id='feedraterender' type='number' min='25' max='300' step='1' style='width: 4em;' onchange='movethumbat(thumbfeedrate, this.value);'/></td></tr>
|
|
||||||
<tr style='margin-top: 50px'><td align='middle'>
|
|
||||||
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
|
||||||
<rect x='2' y='2' width='3' height='10' />
|
|
||||||
<rect x='8' y='4' width='3' height='8' />
|
|
||||||
<rect x='14' y='6' width='3' height='6' />
|
|
||||||
<rect x='20' y='8' width='3' height='4' />
|
|
||||||
<path d="M2,17 L18,17 L18,14 L23,18.5 L18,23 L18,20 L2,20 z" />
|
|
||||||
</svg>
|
|
||||||
</td><td width='auto' >
|
|
||||||
<div id='rangeflowrate' min="50" max="150" class='sliderrange' onclick ="rangeclicked(event,this);" customthumb='thumbflowrate'>
|
|
||||||
<svg width='322' height='20' viewbox='0 0 322 20'>
|
|
||||||
<defs>
|
|
||||||
<pattern id='basicPattern' x='10' y='0' width='4' height='20' patternUnits='userSpaceOnUse'>
|
|
||||||
<rect x='0' y='0' width='4' height='20' stroke-width='0.2' stroke= '#0D2F38' fill='#77AEBD'/ >
|
|
||||||
</pattern>
|
|
||||||
</defs>
|
|
||||||
<rect x='1' y='4' width='320' height='12' stroke= '#0D2F38' stroke-width='1' rx='6' ry='6' fill='url(#basicPattern)'/>
|
|
||||||
<text x='13' y='14' style='font-weight:600;font-size:10;font-family:sans-serif;fill:#000000; pointer-events:none;'>Flowrate</text>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div id='thumbflowrate' class='sliderthumb' render='flowraterender' customrange='rangeflowrate' ><svg width='8' height='20' viewbox='0 0 8 20'><path d='M 3.5,0 L7,5 L7,14 L3.5,19 L0,14 L0,5 z' /></div>
|
|
||||||
|
|
||||||
</td><td width='auto'><input id='flowraterender' min='50' max='150' step='1' type='number' style='width: 4em;' onchange='movethumbat(thumbflowrate, this.value);'></td></tr>
|
|
||||||
<tr><td align='middle'>
|
|
||||||
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
|
||||||
<g id='fan' onmouseup="fan_on = fan_on===0?1:0; show_hide(red_fan,fan_on);" class='hotspot' onmouseover="changecolor(f1,'#0052E1');" onmouseout="changecolor(f1,'#000000');">
|
|
||||||
<rect x='0' y='0' width='24' height='24' fill='#FFFFFF'/>
|
|
||||||
<path id='f1' d="M10,11 L10,10 L6,10 A 7,5 0 0 1 7,1 L8,1 A 3,2.5 0 0 1 9,5 L9,9 L10,9 L10,10 L12,10 L12,6 A 5,7 0 0 1 21,7 L21,8 A 2.5,3 0 0 1 17,9 L13,9 L13,10 L12,10 L12,12 L16,12 A 7,5 0 0 1 15,21 L14,21 A 3,2.5 0 0 1 13,17 L13,13 L12,13 L12,12 L10,12 L10,16 A 5,7 0 0 1 1,15 L1,14 A 2.5,3 0 0 1 5,13 L9,13 L9,12 10,12 z" />
|
|
||||||
<polygon id='red_fan' points="19,0 21,2 2,21 0,19" fill="#FF0000" stroke="#FFFFFF" opacity='0'/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</td><td>
|
|
||||||
<div id='rangefanspeed' min="0" max="100" class='sliderrange' onclick ="rangeclicked(event,this);" customthumb='thumbfanspeed'>
|
|
||||||
<svg width='322' height='20' viewbox='0 0 322 20'>
|
|
||||||
<defs>
|
|
||||||
<pattern id='basicPattern' x='10' y='0' width='4' height='20' patternUnits='userSpaceOnUse'>
|
|
||||||
<rect x='0' y='0' width='4' height='20' stroke-width='0.2' stroke= '#0D2F38' fill='#77AEBD'/ >
|
|
||||||
</pattern>
|
|
||||||
</defs>
|
|
||||||
<rect x='1' y='4' width='320' height='12' stroke= '#0D2F38' stroke-width='1' rx='6' ry='6' fill='url(#basicPattern)'/>
|
|
||||||
<text x='13' y='14' style='font-weight:600;font-size:10;font-family:sans-serif;fill:#000000; pointer-events:none;'>Fan</text>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div id='thumbfanspeed' class='sliderthumb' render='fanspeedrender' customrange='rangefanspeed' >
|
|
||||||
<svg width='8' height='20' viewbox='0 0 8 20'><path d='M 3.5,0 L7,5 L7,14 L3.5,19 L0,14 L0,5 z' /></svg>
|
|
||||||
</div>
|
|
||||||
</td><td width='auto'><input type='number' id='fanspeedrender' min='0' max='100' step='1' style='width: 4em;' onchange='movethumbat(thumbfanspeed, this.value);'></td></tr>
|
|
||||||
<tr><td>
|
|
||||||
<svg width="29" height="25" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
|
||||||
<g id='bed' onmouseup="bed_on = bed_on===0?1:0; show_hide(red_bed,bed_on);" class='hotspot' onmouseover="changestroke(b1,b2,b3,b4,b5,'#0052E1'); " onmouseout="changestroke(b1,b2,b3,b4,b5,'#000000');">
|
|
||||||
<rect x='0' y='0' width='24' height='24' fill='#FFFFFF'/>
|
|
||||||
<polygon id='b1' points="5,0 24,0 28,19 1,19" fill="none" stroke="#000000" stroke-width='2'/>
|
|
||||||
<line id='b2' x1="11" y1="0" x2="10" y2="19" stroke="#000000" stroke-width='2' />
|
|
||||||
<line id='b3' x1="18" y1="0" x2="19" y2="19" stroke="#000000" stroke-width='2' />
|
|
||||||
<line id='b4' x1="3" y1="13" x2="26" y2="13" stroke="#000000" stroke-width='2' />
|
|
||||||
<line id='b5' x1="4" y1="6" x2="25" y2="6" stroke="#000000" stroke-width='2' />
|
|
||||||
<polygon id='red_bed' points="21,0 23,2 4,21 2,19" fill="#FF0000" stroke="#FFFFFF" opacity='0'/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</td><td >
|
|
||||||
<div id='rangebed' min='0' max='150' class='sliderrange' onclick ='rangeclicked(event,this);' customthumb='thumbbed'>
|
|
||||||
<svg width='322' height='22' viewbox='0 0 322 22'>
|
|
||||||
<defs>
|
|
||||||
<linearGradient id='grad1' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#0007FE;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#00FAFE;stop-opacity:1' /></linearGradient>
|
|
||||||
<linearGradient id='grad2' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#00FAFE;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#00FF00;stop-opacity:1' /></linearGradient>
|
|
||||||
<linearGradient id='grad3' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#00FF00;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#FAFD00;stop-opacity:1' /></linearGradient>
|
|
||||||
<linearGradient id='grad4' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#FAFD00;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#FE0700;stop-opacity:1' /></linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect x='1' y='4' width='80' height='14' fill='url(#grad1)' />
|
|
||||||
<rect x='80' y='4' width='80' height='14' fill='url(#grad2)' />
|
|
||||||
<rect x='160' y='4' width='80' height='14' fill='url(#grad3)' />
|
|
||||||
<rect x='240' y='4' width='80' height='14' fill='url(#grad4)' />
|
|
||||||
<rect x='1' y='4' width='320' height='14' fill='none' stroke-width='1' stroke='#C3BDB5' />
|
|
||||||
<text x='13' y='14' style='font-weight:600;font-size:10;font-family:sans-serif;fill:#FFFFFF; '>Bed Temperature</text>
|
|
||||||
<text x='270' y='14' style='font-weight:600;font-size:10;font-family:sans-serif;fill:#FFFFFF; '>60.43°C</text>
|
|
||||||
<path d='M150,5 L153,11 L150,17 L147,11 z' fill='#000000'>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div id='thumbbed' class='sliderthumb' render='bedrender' customrange='rangebed' >
|
|
||||||
<svg width='8' height='24' viewbox='0 0 8 24'><path d='M 0,0 L3,5 L3,17 L0,22 L7,22 L4,17 L4,5 L7,0 z' /></svg>
|
|
||||||
</div>
|
|
||||||
</td><td width='auto'><input type='number' id='bedrender' max='150' min='130' step='1' style='width: 4em;' onchange='movethumbat(thumbbed, this.value);'></td></tr>
|
|
||||||
<tr><td>
|
|
||||||
<svg width="26" height="26" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
|
||||||
<g id='Ext1' onmouseup="ext1_on = ext1_on===0?1:0; show_hide(red_ext1,ext1_on);" class='hotspot' onmouseover="changecolor(e11,e12,'#0052E1');" onmouseout="changecolor(e11,e12,'#000000');">
|
|
||||||
<rect x='0' y='0' width='24' height='24' fill='#FFFFFF'/>
|
|
||||||
<path id='e11' d="M1,0 L8,0 L8,15 L4.5,21 L1,15 z" />
|
|
||||||
<text id='e12' x="10" y="15.5" class="slide">1</text>
|
|
||||||
<polygon id='red_ext1' points="21,0 23,2 4,21 2,19" fill="#FF0000" stroke="#FFFFFF" opacity='0'/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</td><td >
|
|
||||||
<div id='rangeext1' min="0" max="300" class='sliderrange' onclick ="rangeclicked(event,this);" customthumb='thumbext1'>
|
|
||||||
<svg width='322' height='22' viewbox='0 0 322 22'>
|
|
||||||
<defs>
|
|
||||||
<linearGradient id='grad1' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#0007FE;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#00FAFE;stop-opacity:1' /></linearGradient>
|
|
||||||
<linearGradient id='grad2' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#00FAFE;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#00FF00;stop-opacity:1' /></linearGradient>
|
|
||||||
<linearGradient id='grad3' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#00FF00;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#FAFD00;stop-opacity:1' /></linearGradient>
|
|
||||||
<linearGradient id='grad4' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#FAFD00;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#FE0700;stop-opacity:1' /></linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect x='1' y='4' width='80' height='14' fill='url(#grad1)' />
|
|
||||||
<rect x='80' y='4' width='80' height='14' fill='url(#grad2)' />
|
|
||||||
<rect x='160' y='4' width='80' height='14' fill='url(#grad3)' />
|
|
||||||
<rect x='240' y='4' width='80' height='14' fill='url(#grad4)' />
|
|
||||||
<rect x='1' y='4' width='320' height='14' fill='none' stroke-width='1' stroke='#C3BDB5' />
|
|
||||||
<text x='13' y='14' style='font-weight:600;font-size:10;font-family:sans-serif;fill:#FFFFFF; '>Extruder 1</text>
|
|
||||||
<text x='270' y='14' style='font-weight:600;font-size:10;font-family:sans-serif;fill:#FFFFFF; '>180.03°C</text>
|
|
||||||
<path d='M150,5 L153,11 L150,17 L147,11 z' fill='#000000'>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div id='thumbext1' class='sliderthumb' render='ext1render' customrange='rangeext1' >
|
|
||||||
<svg width='8' height='24' viewbox='0 0 8 24'><path d='M 0,0 L3,5 L3,17 L0,22 L7,22 L4,17 L4,5 L7,0 z' /></svg></div>
|
|
||||||
</td><td width='auto'><input type='number' id='ext1render' min='0' max='300' step='1' style='width: 4em;' onchange='movethumbat(thumbext1, this.value);'></td></tr>
|
|
||||||
<tr><td>
|
|
||||||
<svg width="26" height="26" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
|
||||||
<g id='Ext2' onmouseup="ext2_on = ext2_on===0?1:0; show_hide(red_ext2,ext2_on);" class='hotspot' onmouseover="changecolor(e21,e22,'#0052E1');" onmouseout="changecolor(e21,e22,'#000000');">
|
|
||||||
<rect x='0' y='0' width='24' height='24' fill='#FFFFFF'/>
|
|
||||||
<path id='e21' d="M1,0 L8,0 L8,15 L4.5,21 L1,15 z" />
|
|
||||||
<text id='e22' x="10" y="15.5" class="slide">2</text>
|
|
||||||
<polygon id='red_ext2' points="21,0 23,2 4,21 2,19" fill="#FF0000" stroke="#FFFFFF" opacity='0'/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</td>
|
|
||||||
<td >
|
|
||||||
<div id='rangeext2' min="0" max="300" class='sliderrange' onclick ="rangeclicked(event,this);" customthumb='thumbext2'>
|
|
||||||
<svg width='322' height='22' viewbox='0 0 322 22'>
|
|
||||||
<defs>
|
|
||||||
<linearGradient id='grad1' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#0007FE;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#00FAFE;stop-opacity:1' /></linearGradient>
|
|
||||||
<linearGradient id='grad2' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#00FAFE;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#00FF00;stop-opacity:1' /></linearGradient>
|
|
||||||
<linearGradient id='grad3' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#00FF00;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#FAFD00;stop-opacity:1' /></linearGradient>
|
|
||||||
<linearGradient id='grad4' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:#FAFD00;stop-opacity:1' />
|
|
||||||
<stop offset='100%' style='stop-color:#FE0700;stop-opacity:1' /></linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect x='1' y='4' width='80' height='14' fill='url(#grad1)' />
|
|
||||||
<rect x='80' y='4' width='80' height='14' fill='url(#grad2)' />
|
|
||||||
<rect x='160' y='4' width='80' height='14' fill='url(#grad3)' />
|
|
||||||
<rect x='240' y='4' width='80' height='14' fill='url(#grad4)' />
|
|
||||||
<rect x='1' y='4' width='320' height='14' fill='none' stroke-width='1' stroke='#C3BDB5' />
|
|
||||||
<text x='13' y='14' style='font-weight:600;font-size:10;font-family:sans-serif;fill:#FFFFFF; '>Extruder 2</text>
|
|
||||||
<text x='270' y='14' style='font-weight:600;font-size:10;font-family:sans-serif;fill:#FFFFFF; '>180.03°C</text>
|
|
||||||
<path d='M150,5 L153,11 L150,17 L147,11 z' fill='#000000'>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div id='thumbext2' class='sliderthumb' render='ext2render' customrange='rangeext2' >
|
|
||||||
<svg width='8' height='24' viewbox='0 0 8 24'><path d='M 0,0 L3,5 L3,17 L0,22 L7,22 L4,17 L4,5 L7,0 z' /></svg> </div>
|
|
||||||
</td><td width='auto'><input type='number' id='ext2render' min='0' max='300' step='1' style='width: 4em;' onchange='movethumbat(thumbext2, this.value);'></td></tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
initrange( rangefeedrate);
|
|
||||||
initthumb( thumbfeedrate);
|
|
||||||
initrange( rangeflowrate);
|
|
||||||
initthumb( thumbflowrate);
|
|
||||||
initrange( rangefanspeed);
|
|
||||||
initthumb( thumbfanspeed);
|
|
||||||
initrange( rangebed);
|
|
||||||
initthumb( thumbbed);
|
|
||||||
initrange( rangeext1);
|
|
||||||
initthumb( thumbext1);
|
|
||||||
initrange( rangeext2);
|
|
||||||
initthumb(thumbext2);
|
|
||||||
extruderlist.style.left=342;
|
|
||||||
var rb = positionbar.getBoundingClientRect();
|
|
||||||
var re = extruderlist.getBoundingClientRect();
|
|
||||||
extruderlist.style.top = rb.top + (( (rb.bottom-rb.top) - (re.bottom-re.top))/2);
|
|
||||||
</script>
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
@ -1,115 +0,0 @@
|
|||||||
* 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 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 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 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>
|
|
||||||
|
|
||||||
* 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]pwd=<admin password>
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
*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>
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
bin2c /infile tool.html.gz /outfile out.h /targetfolder .
|
|
@ -1,125 +0,0 @@
|
|||||||
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);
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
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
|
|
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"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)"
|
|
||||||
}
|
|
Binary file not shown.
@ -1,139 +0,0 @@
|
|||||||
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%; font-size:10px;}
|
|
||||||
body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333333;background-color:#ffffff;}
|
|
||||||
.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px;}
|
|
||||||
table{border:0px;border-spacing:0;max-width:100%;}
|
|
||||||
.table-bordered{ width:100%; border:1px solid #dddddd;margin-bottom:20px;}
|
|
||||||
td{white-space:nowrap; padding:2mm;}
|
|
||||||
th{text-align:left;}
|
|
||||||
.table>thead>tr>th,.table>tbody>tr>th,.table>thead>tr>td,.table>tbody>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #dddddd;}
|
|
||||||
.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td{border:1px solid #dddddd;}
|
|
||||||
.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px;}
|
|
||||||
.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9;}
|
|
||||||
@media (min-width:768px){.container{width:750px;}}
|
|
||||||
@media (min-width:992px){.container{width:970px;}}
|
|
||||||
@media (min-width:1200px){.container{width:1170px;}}
|
|
||||||
.nav{ width:100%; color:#cccccc;padding-left:10;padding-right:10;list-style:none;background-color:#333333;border-radius:6px ;margin-bottom:20px;}
|
|
||||||
a{position:relative;display:block;padding:10px 15px;text-decoration:none;color:#cccccc;}
|
|
||||||
.active{color:#ffffff;background-color:#000000;}
|
|
||||||
.active a,a:hover,a:focus{color:#FFFFFF;}
|
|
||||||
.panel{margin-bottom:20px;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05);}
|
|
||||||
.panel-body{padding:15px;}
|
|
||||||
.panel-heading{padding:10px 15px;color:#333333;background-color:#f5f5f5;border-color:#dddddd;border-top-right-radius:3px;border-top-left-radius:3px;border-bottom:1px solid #dddddd;}
|
|
||||||
label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold;}
|
|
||||||
.text-info{color:#31708f;}
|
|
||||||
.form-control{display:block;width:auto;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555555;background-color:#ffffff
|
|
||||||
;background-image:none;border:1px solid #cccccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);
|
|
||||||
* -webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;
|
|
||||||
* transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6);
|
|
||||||
* box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6);}
|
|
||||||
.form-group{margin-bottom:15px;}
|
|
||||||
.btn{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;}
|
|
||||||
.btn-primary{color:#ffffff;background-color:#337ab7;border-color:#2e6da4;}
|
|
||||||
.btn-primary:focus,.btn-primary:active,.btn-primary:hover,.btn-primary.focus,.btn-primary.active,.btn-primary.hover{color:#ffffff;background-color:#286090;border-color:#122b40;}
|
|
||||||
caption{padding-top:8px;padding-bottom:8px;color:#777777;text-align:left;}
|
|
||||||
.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px;}
|
|
||||||
.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d;}
|
|
||||||
.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442;}
|
|
||||||
.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);}
|
|
||||||
.has-error .form-control:focus{border-color:#843534;-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;}
|
|
||||||
.has-error .control-label{color:#a94442;}
|
|
||||||
.has-success .form-control {border-color: #3c763d;-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);}
|
|
||||||
.has-success .form-control:focus {border-color: #2b542c;-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;}
|
|
||||||
.has-success .control-label{color: #3c763d;}
|
|
||||||
.btn-danger{color:#ffffff;background-color:#d9534f;border-color:#d43f3a;}
|
|
||||||
.btn-danger:focus,.btn-danger:active,.btn-danger:hover,.btn-danger.focus,.btn-danger.active,.btn-danger.hover{color: #ffffff;background-color:#c9302c;border-color:#761c19;}
|
|
||||||
.btnimg {cursor:hand; border-radius:6px ;;border:1px solid #FFFFFF;}
|
|
||||||
.btnimg:hover{background-color:#F0F0F0;border-color:#00FFFF;-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;}
|
|
||||||
.btnroundimg {cursor:hand; border-radius:30px;}
|
|
||||||
.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,249 +0,0 @@
|
|||||||
var currentpath = "/";
|
|
||||||
function navbar(){
|
|
||||||
var content="<table><tr>";
|
|
||||||
var tlist = currentpath.split("/");
|
|
||||||
var path="/";
|
|
||||||
var nb = 1;
|
|
||||||
content+="<td class='btnimg' onclick=\"currentpath='/'; SendCommand('list','all');\">/</td>";
|
|
||||||
while (nb < (tlist.length-1))
|
|
||||||
{
|
|
||||||
path+=tlist[nb] + "/";
|
|
||||||
content+="<td class='btnimg' onclick=\"currentpath='"+path+"'; SendCommand('list','all');\">"+tlist[nb] +"</td><td>/</td>";
|
|
||||||
nb++;
|
|
||||||
}
|
|
||||||
content+="</tr></table>";
|
|
||||||
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 + "/";
|
|
||||||
SendCommand('list','all');
|
|
||||||
}
|
|
||||||
function compareStrings(a, b) {
|
|
||||||
// case-insensitive comparison
|
|
||||||
a = a.toLowerCase();
|
|
||||||
b = b.toLowerCase();
|
|
||||||
return (a < b) ? -1 : (a > b) ? 1 : 0;
|
|
||||||
}
|
|
||||||
function dispatchfilestatus(jsonresponse)
|
|
||||||
{
|
|
||||||
var content ="";
|
|
||||||
content =" Status: "+jsonresponse.status;
|
|
||||||
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('status').innerHTML=content;
|
|
||||||
content ="";
|
|
||||||
if (currentpath!="/")
|
|
||||||
{
|
|
||||||
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 i1=0;i1 <jsonresponse.files.length;i1++){
|
|
||||||
//first display files
|
|
||||||
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[i1].name+"\" target=_blank><div class=\"blacklink\">";
|
|
||||||
content +=jsonresponse.files[i1].name;
|
|
||||||
content +="</div></a></TD><TD>";
|
|
||||||
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 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[i2].name+"');\">";
|
|
||||||
content +=jsonresponse.files[i2].name;
|
|
||||||
content +="</TD><TD>";
|
|
||||||
content +="</TD><TD width='0%'><div class=\"btnimg\" onclick=\"Deletedir('"+jsonresponse.files[i2].name+"')\">";
|
|
||||||
content +=trash_icon();
|
|
||||||
content +="</div></TD><td></td></TR>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('file_list').innerHTML=content;
|
|
||||||
document.getElementById('path').innerHTML=navbar();}
|
|
||||||
function Delete(filename){
|
|
||||||
if (confirm("Confirm deletion of file: " + filename))SendCommand("delete",filename);
|
|
||||||
}
|
|
||||||
function Deletedir(filename){
|
|
||||||
if (confirm("Confirm deletion of directory: " + filename))SendCommand("deletedir",filename);
|
|
||||||
}
|
|
||||||
function Createdir(){
|
|
||||||
var filename = prompt("Please enter directory name", "");
|
|
||||||
if (filename != null) {
|
|
||||||
SendCommand("createdir",filename.trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function SendCommand(action,filename){
|
|
||||||
var xmlhttp = new XMLHttpRequest();
|
|
||||||
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 ) {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
function Sendfile(){
|
|
||||||
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();
|
|
||||||
formData.append('path', currentpath);
|
|
||||||
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);
|
|
||||||
//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);
|
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
<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>
|
|
||||||
|
|
||||||
|
|
@ -1,340 +0,0 @@
|
|||||||
/*
|
|
||||||
GenLinkedList.h - V1.1 - Generic LinkedList implementation
|
|
||||||
Works better with FIFO, because LIFO will need to
|
|
||||||
search the entire List to find the last one;
|
|
||||||
|
|
||||||
For instructions, go to https://github.com/ivanseidel/LinkedList
|
|
||||||
|
|
||||||
Created by Ivan Seidel Gomes, March, 2013.
|
|
||||||
Released into the public domain.
|
|
||||||
Changelog: 2015/10/05: [Luc] Change false to NULL for pointers
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef GenLinkedList_h
|
|
||||||
#define GenLinkedList_h
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct ListNode {
|
|
||||||
T data;
|
|
||||||
ListNode<T> *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class GenLinkedList
|
|
||||||
{
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int _size;
|
|
||||||
ListNode<T> *root;
|
|
||||||
ListNode<T> *last;
|
|
||||||
|
|
||||||
// Helps "get" method, by saving last position
|
|
||||||
ListNode<T> *lastNodeGot;
|
|
||||||
int lastIndexGot;
|
|
||||||
// isCached should be set to FALSE
|
|
||||||
// every time the list suffer changes
|
|
||||||
bool isCached;
|
|
||||||
|
|
||||||
ListNode<T>* getNode(int index);
|
|
||||||
|
|
||||||
public:
|
|
||||||
GenLinkedList();
|
|
||||||
~GenLinkedList();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Returns current size of GenLinkedList
|
|
||||||
*/
|
|
||||||
virtual int size();
|
|
||||||
/*
|
|
||||||
Adds a T object in the specified index;
|
|
||||||
Unlink and link the GenLinkedList correcly;
|
|
||||||
Increment _size
|
|
||||||
*/
|
|
||||||
virtual bool add(int index, T);
|
|
||||||
/*
|
|
||||||
Adds a T object in the end of the GenLinkedList;
|
|
||||||
Increment _size;
|
|
||||||
*/
|
|
||||||
virtual bool add(T);
|
|
||||||
/*
|
|
||||||
Adds a T object in the start of the GenLinkedList;
|
|
||||||
Increment _size;
|
|
||||||
*/
|
|
||||||
virtual bool unshift(T);
|
|
||||||
/*
|
|
||||||
Set the object at index, with T;
|
|
||||||
Increment _size;
|
|
||||||
*/
|
|
||||||
virtual bool set(int index, T);
|
|
||||||
/*
|
|
||||||
Remove object at index;
|
|
||||||
If index is not reachable, returns false;
|
|
||||||
else, decrement _size
|
|
||||||
*/
|
|
||||||
virtual T remove(int index);
|
|
||||||
/*
|
|
||||||
Remove last object;
|
|
||||||
*/
|
|
||||||
virtual T pop();
|
|
||||||
/*
|
|
||||||
Remove first object;
|
|
||||||
*/
|
|
||||||
virtual T shift();
|
|
||||||
/*
|
|
||||||
Get the index'th element on the list;
|
|
||||||
Return Element if accessible,
|
|
||||||
else, return false;
|
|
||||||
*/
|
|
||||||
virtual T get(int index);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Clear the entire array
|
|
||||||
*/
|
|
||||||
virtual void clear();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize GenLinkedList with false values
|
|
||||||
template<typename T>
|
|
||||||
GenLinkedList<T>::GenLinkedList()
|
|
||||||
{
|
|
||||||
root=NULL;
|
|
||||||
last=NULL;
|
|
||||||
_size=0;
|
|
||||||
|
|
||||||
lastNodeGot = root;
|
|
||||||
lastIndexGot = 0;
|
|
||||||
isCached = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear Nodes and free Memory
|
|
||||||
template<typename T>
|
|
||||||
GenLinkedList<T>::~GenLinkedList()
|
|
||||||
{
|
|
||||||
ListNode<T>* tmp;
|
|
||||||
while(root!=NULL) {
|
|
||||||
tmp=root;
|
|
||||||
root=root->next;
|
|
||||||
delete tmp;
|
|
||||||
}
|
|
||||||
last = NULL;
|
|
||||||
_size=0;
|
|
||||||
isCached = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Actually "logic" coding
|
|
||||||
*/
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
ListNode<T>* GenLinkedList<T>::getNode(int index)
|
|
||||||
{
|
|
||||||
|
|
||||||
int _pos = 0;
|
|
||||||
ListNode<T>* current = root;
|
|
||||||
|
|
||||||
// Check if the node trying to get is
|
|
||||||
// immediately AFTER the previous got one
|
|
||||||
if(isCached && lastIndexGot <= index) {
|
|
||||||
_pos = lastIndexGot;
|
|
||||||
current = lastNodeGot;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(_pos < index && current) {
|
|
||||||
current = current->next;
|
|
||||||
|
|
||||||
_pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the object index got is the same as the required
|
|
||||||
if(_pos == index) {
|
|
||||||
isCached = true;
|
|
||||||
lastIndexGot = index;
|
|
||||||
lastNodeGot = current;
|
|
||||||
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
int GenLinkedList<T>::size()
|
|
||||||
{
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool GenLinkedList<T>::add(int index, T _t)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(index >= _size) {
|
|
||||||
return add(_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(index == 0) {
|
|
||||||
return unshift(_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
ListNode<T> *tmp = new ListNode<T>(),
|
|
||||||
*_prev = getNode(index-1);
|
|
||||||
tmp->data = _t;
|
|
||||||
tmp->next = _prev->next;
|
|
||||||
_prev->next = tmp;
|
|
||||||
|
|
||||||
_size++;
|
|
||||||
isCached = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool GenLinkedList<T>::add(T _t)
|
|
||||||
{
|
|
||||||
|
|
||||||
ListNode<T> *tmp = new ListNode<T>();
|
|
||||||
tmp->data = _t;
|
|
||||||
tmp->next = NULL;
|
|
||||||
|
|
||||||
if(root) {
|
|
||||||
// Already have elements inserted
|
|
||||||
last->next = tmp;
|
|
||||||
last = tmp;
|
|
||||||
} else {
|
|
||||||
// First element being inserted
|
|
||||||
root = tmp;
|
|
||||||
last = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
_size++;
|
|
||||||
isCached = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool GenLinkedList<T>::unshift(T _t)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(_size == 0) {
|
|
||||||
return add(_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
ListNode<T> *tmp = new ListNode<T>();
|
|
||||||
tmp->next = root;
|
|
||||||
tmp->data = _t;
|
|
||||||
root = tmp;
|
|
||||||
|
|
||||||
_size++;
|
|
||||||
isCached = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool GenLinkedList<T>::set(int index, T _t)
|
|
||||||
{
|
|
||||||
// Check if index position is in bounds
|
|
||||||
if(index < 0 || index >= _size) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
getNode(index)->data = _t;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T GenLinkedList<T>::pop()
|
|
||||||
{
|
|
||||||
if(_size <= 0) {
|
|
||||||
return T();
|
|
||||||
}
|
|
||||||
|
|
||||||
isCached = false;
|
|
||||||
|
|
||||||
if(_size >= 2) {
|
|
||||||
ListNode<T> *tmp = getNode(_size - 2);
|
|
||||||
T ret = tmp->next->data;
|
|
||||||
delete(tmp->next);
|
|
||||||
tmp->next = NULL;
|
|
||||||
last = tmp;
|
|
||||||
_size--;
|
|
||||||
return ret;
|
|
||||||
} else {
|
|
||||||
// Only one element left on the list
|
|
||||||
T ret = root->data;
|
|
||||||
delete(root);
|
|
||||||
root = NULL;
|
|
||||||
last = NULL;
|
|
||||||
_size = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T GenLinkedList<T>::shift()
|
|
||||||
{
|
|
||||||
if(_size <= 0) {
|
|
||||||
return T();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_size > 1) {
|
|
||||||
ListNode<T> *_next = root->next;
|
|
||||||
T ret = root->data;
|
|
||||||
delete(root);
|
|
||||||
root = _next;
|
|
||||||
_size --;
|
|
||||||
isCached = false;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
} else {
|
|
||||||
// Only one left, then pop()
|
|
||||||
return pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T GenLinkedList<T>::remove(int index)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= _size) {
|
|
||||||
return T();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(index == 0) {
|
|
||||||
return shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == _size-1) {
|
|
||||||
return pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
ListNode<T> *tmp = getNode(index - 1);
|
|
||||||
ListNode<T> *toDelete = tmp->next;
|
|
||||||
T ret = toDelete->data;
|
|
||||||
tmp->next = tmp->next->next;
|
|
||||||
delete(toDelete);
|
|
||||||
_size--;
|
|
||||||
isCached = false;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T GenLinkedList<T>::get(int index)
|
|
||||||
{
|
|
||||||
ListNode<T> *tmp = getNode(index);
|
|
||||||
|
|
||||||
return (tmp ? tmp->data : T());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void GenLinkedList<T>::clear()
|
|
||||||
{
|
|
||||||
while(size() > 0) {
|
|
||||||
shift();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
209
esp3d/bridge.cpp
209
esp3d/bridge.cpp
@ -1,209 +0,0 @@
|
|||||||
/*
|
|
||||||
bridge.cpp - esp3d bridge serial/tcp class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "bridge.h"
|
|
||||||
#include "command.h"
|
|
||||||
#include "webinterface.h"
|
|
||||||
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
WiFiServer * data_server;
|
|
||||||
WiFiClient serverClients[MAX_SRV_CLIENTS];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool BRIDGE::header_sent = false;
|
|
||||||
String BRIDGE::buffer_web = "";
|
|
||||||
void BRIDGE::print (const __FlashStringHelper *data, tpipe output)
|
|
||||||
{
|
|
||||||
String tmp = data;
|
|
||||||
BRIDGE::print(tmp.c_str(), output);
|
|
||||||
}
|
|
||||||
void BRIDGE::print (String & data, tpipe output)
|
|
||||||
{
|
|
||||||
BRIDGE::print(data.c_str(), output);
|
|
||||||
}
|
|
||||||
void BRIDGE::print (const char * data, tpipe output)
|
|
||||||
{
|
|
||||||
switch(output) {
|
|
||||||
case SERIAL_PIPE:
|
|
||||||
header_sent = false;
|
|
||||||
ESP_SERIAL_OUT.print(data);
|
|
||||||
break;
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
case TCP_PIPE:
|
|
||||||
header_sent = false;
|
|
||||||
BRIDGE::send2TCP(data);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case WEB_PIPE:
|
|
||||||
if (!header_sent) {
|
|
||||||
web_interface->web_server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
|
||||||
web_interface->web_server.sendHeader("Content-Type","text/html");
|
|
||||||
web_interface->web_server.sendHeader("Cache-Control","no-cache");
|
|
||||||
web_interface->web_server.send(200);
|
|
||||||
header_sent = true;
|
|
||||||
}
|
|
||||||
buffer_web+=data;
|
|
||||||
if (buffer_web.length() > 1200) {
|
|
||||||
//send data
|
|
||||||
web_interface->web_server.sendContent(buffer_web);
|
|
||||||
//reset buffer
|
|
||||||
buffer_web="";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void BRIDGE::println (const __FlashStringHelper *data, tpipe output)
|
|
||||||
{
|
|
||||||
BRIDGE::print(data,output);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
BRIDGE::print("\r",output);
|
|
||||||
#endif
|
|
||||||
BRIDGE::print("\n",output);
|
|
||||||
}
|
|
||||||
void BRIDGE::println (String & data, tpipe output)
|
|
||||||
{
|
|
||||||
BRIDGE::print(data,output);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
BRIDGE::print("\r",output);
|
|
||||||
#endif
|
|
||||||
BRIDGE::print("\n",output);
|
|
||||||
}
|
|
||||||
void BRIDGE::println (const char * data, tpipe output)
|
|
||||||
{
|
|
||||||
BRIDGE::print(data,output);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
BRIDGE::print("\r",output);
|
|
||||||
#endif
|
|
||||||
BRIDGE::print("\n",output);
|
|
||||||
}
|
|
||||||
void BRIDGE::flush (tpipe output)
|
|
||||||
{
|
|
||||||
switch(output) {
|
|
||||||
case SERIAL_PIPE:
|
|
||||||
ESP_SERIAL_OUT.flush();
|
|
||||||
break;
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
case TCP_PIPE:
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case WEB_PIPE:
|
|
||||||
if(header_sent) {
|
|
||||||
//send data
|
|
||||||
web_interface->web_server.sendContent(buffer_web);
|
|
||||||
//close line
|
|
||||||
web_interface->web_server.sendContent("");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
header_sent = false;
|
|
||||||
buffer_web = String();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
void BRIDGE::send2TCP(const __FlashStringHelper *data)
|
|
||||||
{
|
|
||||||
String tmp = data;
|
|
||||||
BRIDGE::send2TCP(tmp.c_str());
|
|
||||||
}
|
|
||||||
void BRIDGE::send2TCP(String data)
|
|
||||||
{
|
|
||||||
BRIDGE::send2TCP(data.c_str());
|
|
||||||
}
|
|
||||||
void BRIDGE::send2TCP(const char * data)
|
|
||||||
{
|
|
||||||
for(uint8_t i = 0; i < MAX_SRV_CLIENTS; i++) {
|
|
||||||
if (serverClients[i] && serverClients[i].connected()) {
|
|
||||||
serverClients[i].write(data, strlen(data));
|
|
||||||
delay(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool BRIDGE::processFromSerial2TCP()
|
|
||||||
{
|
|
||||||
uint8_t i;
|
|
||||||
//check UART for data
|
|
||||||
if(ESP_SERIAL_OUT.available()) {
|
|
||||||
size_t len = ESP_SERIAL_OUT.available();
|
|
||||||
uint8_t sbuf[len];
|
|
||||||
ESP_SERIAL_OUT.readBytes(sbuf, len);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
if (WiFi.getMode()!=WIFI_OFF ) {
|
|
||||||
//push UART data to all connected tcp clients
|
|
||||||
for(i = 0; i < MAX_SRV_CLIENTS; i++) {
|
|
||||||
if (serverClients[i] && serverClients[i].connected()) {
|
|
||||||
serverClients[i].write(sbuf, len);
|
|
||||||
delay(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
//process data if any
|
|
||||||
COMMAND::read_buffer_serial(sbuf, len);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
void BRIDGE::processFromTCP2Serial()
|
|
||||||
{
|
|
||||||
uint8_t i,data;
|
|
||||||
//check if there are any new clients
|
|
||||||
if (data_server->hasClient()) {
|
|
||||||
for(i = 0; i < MAX_SRV_CLIENTS; i++) {
|
|
||||||
//find free/disconnected spot
|
|
||||||
if (!serverClients[i] || !serverClients[i].connected()) {
|
|
||||||
if(serverClients[i]) {
|
|
||||||
serverClients[i].stop();
|
|
||||||
}
|
|
||||||
serverClients[i] = data_server->available();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//no free/disconnected spot so reject
|
|
||||||
WiFiClient serverClient = data_server->available();
|
|
||||||
serverClient.stop();
|
|
||||||
}
|
|
||||||
//check clients for data
|
|
||||||
//to avoid any pollution if Uploading file to SDCard
|
|
||||||
if ((web_interface->blockserial) == false) {
|
|
||||||
for(i = 0; i < MAX_SRV_CLIENTS; i++) {
|
|
||||||
if (serverClients[i] && serverClients[i].connected()) {
|
|
||||||
if(serverClients[i].available()) {
|
|
||||||
//get data from the tcp client and push it to the UART
|
|
||||||
while(serverClients[i].available()) {
|
|
||||||
data = serverClients[i].read();
|
|
||||||
ESP_SERIAL_OUT.write(data);
|
|
||||||
COMMAND::read_buffer_tcp(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
bridge.h - esp3d bridge serial/tcp class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BRIDGE_H
|
|
||||||
#define BRIDGE_H
|
|
||||||
#include <WiFiServer.h>
|
|
||||||
#include "config.h"
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
extern WiFiServer * data_server;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class BRIDGE
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static bool header_sent;
|
|
||||||
static String buffer_web;
|
|
||||||
static bool processFromSerial2TCP();
|
|
||||||
static void print (const __FlashStringHelper *data, tpipe output);
|
|
||||||
static void print (String & data, tpipe output);
|
|
||||||
static void print (const char * data, tpipe output);
|
|
||||||
static void println (const __FlashStringHelper *data, tpipe output);
|
|
||||||
static void println (String & data, tpipe output);
|
|
||||||
static void println (const char * data, tpipe output);
|
|
||||||
static void flush (tpipe output);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
static void processFromTCP2Serial();
|
|
||||||
static void send2TCP(const __FlashStringHelper *data);
|
|
||||||
static void send2TCP(String data);
|
|
||||||
static void send2TCP(const char * data);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
#endif
|
|
1600
esp3d/command.cpp
1600
esp3d/command.cpp
File diff suppressed because it is too large
Load Diff
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
command.h - ESP3D configuration class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef COMMAND_h
|
|
||||||
#define COMMAND_h
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include "bridge.h"
|
|
||||||
|
|
||||||
class COMMAND
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static String buffer_serial;
|
|
||||||
static String buffer_tcp;
|
|
||||||
static void read_buffer_serial(uint8_t *b, size_t len);
|
|
||||||
static void read_buffer_serial(uint8_t b);
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
static void read_buffer_tcp(uint8_t b);
|
|
||||||
#endif
|
|
||||||
static bool check_command(String buffer, tpipe output, bool handlelockserial = true);
|
|
||||||
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
|
|
1865
esp3d/config.cpp
1865
esp3d/config.cpp
File diff suppressed because it is too large
Load Diff
430
esp3d/config.h
430
esp3d/config.h
@ -1,430 +0,0 @@
|
|||||||
/*
|
|
||||||
config.h - ESP3D configuration class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
//definition
|
|
||||||
#define UNKNOWN_FW 0
|
|
||||||
#define REPETIER4DV 1
|
|
||||||
#define MARLIN 2
|
|
||||||
#define MARLINKIMBRA 3
|
|
||||||
#define SMOOTHIEWARE 4
|
|
||||||
#define REPETIER 5
|
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
#include "FS.h"
|
|
||||||
#include "SPIFFS.h"
|
|
||||||
#define WIFI_NONE_SLEEP WIFI_PS_NONE
|
|
||||||
#define WIFI_MODEM_SLEEP WIFI_PS_MAX_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
|
|
||||||
#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
|
|
||||||
|
|
||||||
//comment to disable
|
|
||||||
//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
|
|
||||||
|
|
||||||
//NETBIOS_FEATURE: this feature is a discovery protocol, supported on Windows out of the box
|
|
||||||
#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
|
|
||||||
|
|
||||||
//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
|
|
||||||
|
|
||||||
#ifdef RECOVERY_FEATURE
|
|
||||||
//pin used to reset setting
|
|
||||||
#define RESET_CONFIG_PIN 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//DIRECT_PIN_FEATURE: allow to access pin using ESP201 command
|
|
||||||
#define DIRECT_PIN_FEATURE
|
|
||||||
|
|
||||||
//INFO_MSG_FEATURE: catch the Info msg and filter it to specific table
|
|
||||||
#define INFO_MSG_FEATURE
|
|
||||||
|
|
||||||
//ERROR_MSG_FEATURE: catch the error msg and filter it to specific table
|
|
||||||
#define ERROR_MSG_FEATURE
|
|
||||||
|
|
||||||
//STATUS_MSG_FEATURE: catch the status msg and filter it to specific table
|
|
||||||
#define STATUS_MSG_FEATURE
|
|
||||||
|
|
||||||
//Serial rx buffer size is 256 but can be extended
|
|
||||||
#define SERIAL_RX_BUFFER_SIZE 512
|
|
||||||
|
|
||||||
#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_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
|
|
||||||
#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) {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
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define LOG(string) {}
|
|
||||||
#define DEBUG_PIPE NO_PIPE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CONFIG_h
|
|
||||||
#define CONFIG_h
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
extern "C" {
|
|
||||||
#include "user_interface.h"
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
//Nothing here
|
|
||||||
#endif
|
|
||||||
#include "wificonf.h"
|
|
||||||
//version and sources location
|
|
||||||
#define FW_VERSION "1.0"
|
|
||||||
#define REPOSITORY "https://github.com/luc-github/ESP3D"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NO_PIPE = 0,
|
|
||||||
SERIAL_PIPE = 2,
|
|
||||||
SERIAL1_PIPE = 3,
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
TCP_PIPE = 4,
|
|
||||||
#endif
|
|
||||||
WEB_PIPE = 5
|
|
||||||
} 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
|
|
||||||
#define CLIENT_MODE 2
|
|
||||||
#define DHCP_MODE 1
|
|
||||||
#define STATIC_IP_MODE 2
|
|
||||||
|
|
||||||
//position in EEPROM
|
|
||||||
//AP mode = 1; Station client mode = 2
|
|
||||||
#define EP_WIFI_MODE 0 //1 byte = flag
|
|
||||||
#define EP_STA_SSID 1 //33 bytes 32+1 = string ; warning does not support multibyte char like chinese
|
|
||||||
#define EP_STA_PASSWORD 34 //65 bytes 64 +1 = string ;warning does not support multibyte char like chinese
|
|
||||||
#define EP_STA_IP_MODE 99 //1 byte = flag
|
|
||||||
#define EP_STA_IP_VALUE 100 //4 bytes xxx.xxx.xxx.xxx
|
|
||||||
#define EP_STA_MASK_VALUE 104 //4 bytes xxx.xxx.xxx.xxx
|
|
||||||
#define EP_STA_GATEWAY_VALUE 108 //4 bytes xxx.xxx.xxx.xxx
|
|
||||||
#define EP_BAUD_RATE 112 //4 bytes = int
|
|
||||||
#define EP_STA_PHY_MODE 116 //1 byte = flag
|
|
||||||
#define EP_SLEEP_MODE 117 //1 byte = flag
|
|
||||||
#define EP_CHANNEL 118 //1 byte = flag
|
|
||||||
#define EP_AUTH_TYPE 119 //1 byte = flag
|
|
||||||
#define EP_SSID_VISIBLE 120 //1 byte = flag
|
|
||||||
#define EP_WEB_PORT 121 //4 bytes = int
|
|
||||||
#define EP_DATA_PORT 125 //4 bytes = int
|
|
||||||
#define EP_REFRESH_PAGE_TIME 129 //1 bytes = flag
|
|
||||||
#define EP_HOSTNAME 130//33 bytes 32+1 = string ; warning does not support multibyte char like chinese
|
|
||||||
#define EP_XY_FEEDRATE 164//4 bytes = int
|
|
||||||
#define EP_Z_FEEDRATE 168//4 bytes = int
|
|
||||||
#define EP_E_FEEDRATE 172//4 bytes = int
|
|
||||||
#define EP_ADMIN_PWD 176//21 bytes 20+1 = string ; warning does not support multibyte char like chinese
|
|
||||||
#define EP_USER_PWD 197//21 bytes 20+1 = string ; warning does not support multibyte char like chinese
|
|
||||||
#define EP_AP_SSID 218 //33 bytes 32+1 = string ; warning does not support multibyte char like chinese
|
|
||||||
#define EP_AP_PASSWORD 251 //65 bytes 64 +1 = string ;warning does not support multibyte char like chinese
|
|
||||||
#define EP_AP_IP_VALUE 316 //4 bytes xxx.xxx.xxx.xxx
|
|
||||||
#define EP_AP_MASK_VALUE 320 //4 bytes xxx.xxx.xxx.xxx
|
|
||||||
#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
|
|
||||||
#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 = "ESP3D";
|
|
||||||
const char DEFAULT_AP_PASSWORD [] PROGMEM = "12345678";
|
|
||||||
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;
|
|
||||||
const byte DEFAULT_IP_VALUE[] = {192, 168, 0, 1};
|
|
||||||
const byte DEFAULT_MASK_VALUE[] = {255, 255, 255, 0};
|
|
||||||
#define DEFAULT_GATEWAY_VALUE DEFAULT_IP_VALUE
|
|
||||||
const long DEFAULT_BAUD_RATE = 115200;
|
|
||||||
const char M117_[] PROGMEM = "M117 ";
|
|
||||||
#define DEFAULT_PHY_MODE WIFI_PHY_MODE_11G
|
|
||||||
#define DEFAULT_SLEEP_MODE WIFI_MODEM_SLEEP
|
|
||||||
#define DEFAULT_CHANNEL 11
|
|
||||||
#define DEFAULT_AUTH_TYPE AUTH_WPA_PSK
|
|
||||||
#define DEFAULT_SSID_VISIBLE 1
|
|
||||||
#define DEFAULT_MAX_CONNECTIONS 4
|
|
||||||
#define DEFAULT_BEACON_INTERVAL 100
|
|
||||||
const int DEFAULT_WEB_PORT = 80;
|
|
||||||
const int DEFAULT_DATA_PORT = 8888;
|
|
||||||
#define DEFAULT_REFRESH_PAGE_TIME 3
|
|
||||||
const int DEFAULT_XY_FEEDRATE=1000;
|
|
||||||
const int DEFAULT_Z_FEEDRATE =100;
|
|
||||||
const int DEFAULT_E_FEEDRATE=400;
|
|
||||||
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 0
|
|
||||||
#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 1024 //max is 1024
|
|
||||||
#define MAX_SSID_LENGTH 32
|
|
||||||
#define MIN_SSID_LENGTH 1
|
|
||||||
#define MAX_PASSWORD_LENGTH 64
|
|
||||||
//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);
|
|
||||||
static bool read_byte(int pos, byte * value);
|
|
||||||
static bool write_string(int pos, const char * byte_buffer);
|
|
||||||
static bool write_string(int pos, const __FlashStringHelper *str);
|
|
||||||
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, 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(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();
|
|
||||||
private:
|
|
||||||
static uint8_t FirmwareTarget;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||||||
<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>
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
@ -1,74 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
]
|
|
189
esp3d/esp3d.ino
189
esp3d/esp3d.ino
@ -1,189 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of ESP3D Firmware for 3D printer.
|
|
||||||
|
|
||||||
ESP3D Firmware for 3D printer is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
ESP3D Firmware for 3D printer is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this Firmware. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
This firmware is using the standard arduino IDE with module to support ESP8266:
|
|
||||||
https://github.com/esp8266/Arduino from Bootmanager
|
|
||||||
|
|
||||||
Latest version of the code and documentation can be found here :
|
|
||||||
https://github.com/luc-github/ESP3D
|
|
||||||
|
|
||||||
Main author: luc lebosse
|
|
||||||
|
|
||||||
*/
|
|
||||||
//be sure correct IDE and settings are used for ESP8266 or ESP32
|
|
||||||
#if !(defined( ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32))
|
|
||||||
#error Oops! Make sure you have 'ESP8266 or ESP32' compatible board selected from the 'Tools -> Boards' menu.
|
|
||||||
#endif
|
|
||||||
#include <EEPROM.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "wificonf.h"
|
|
||||||
#include "bridge.h"
|
|
||||||
#include "webinterface.h"
|
|
||||||
#include "command.h"
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include "ESP8266WiFi.h"
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
#include <ESP8266mDNS.h>
|
|
||||||
#endif
|
|
||||||
#include <ESP8266WebServer.h>
|
|
||||||
#else
|
|
||||||
#include <WiFi.h>
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
#include <ESPmDNS.h>
|
|
||||||
#endif
|
|
||||||
#include "esp_wifi.h"
|
|
||||||
#include <WebServer.h>
|
|
||||||
#include "FS.h"
|
|
||||||
#include "SPIFFS.h"
|
|
||||||
#include "Update.h"
|
|
||||||
#endif
|
|
||||||
#include <WiFiClient.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
#include <DNSServer.h>
|
|
||||||
extern DNSServer dnsServer;
|
|
||||||
#endif
|
|
||||||
#ifdef SSDP_FEATURE
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include <ESP8266SSDP.h>
|
|
||||||
#else
|
|
||||||
//#include <ESPSSDP.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifdef NETBIOS_FEATURE
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include <ESP8266NetBIOS.h>
|
|
||||||
#else
|
|
||||||
//#include <ESPNetBIOS.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifndef FS_NO_GLOBALS
|
|
||||||
#define FS_NO_GLOBALS
|
|
||||||
#endif
|
|
||||||
#include <FS.h>
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
bool breset_config=false;
|
|
||||||
bool directsd_check = false;
|
|
||||||
web_interface = NULL;
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
data_server = NULL;
|
|
||||||
#endif
|
|
||||||
// init:
|
|
||||||
#ifdef DEBUG_ESP3D
|
|
||||||
if (ESP_SERIAL_OUT.baudRate() != DEFAULT_BAUD_RATE)ESP_SERIAL_OUT.begin(DEFAULT_BAUD_RATE);
|
|
||||||
delay(2000);
|
|
||||||
LOG("\r\nDebug Serial set\r\n")
|
|
||||||
#endif
|
|
||||||
//WiFi.disconnect();
|
|
||||||
WiFi.mode(WIFI_OFF);
|
|
||||||
delay(8000);
|
|
||||||
CONFIG::InitDirectSD();
|
|
||||||
CONFIG::InitPins();
|
|
||||||
#ifdef RECOVERY_FEATURE
|
|
||||||
delay(8000);
|
|
||||||
//check if reset config is requested
|
|
||||||
if (digitalRead(RESET_CONFIG_PIN)==0) {
|
|
||||||
breset_config=true; //if requested =>reset settings
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
//check if EEPROM has value
|
|
||||||
if ( !CONFIG::InitBaudrate() || !CONFIG::InitExternalPorts()) {
|
|
||||||
breset_config=true; //cannot access to config settings=> reset settings
|
|
||||||
LOG("Error no EEPROM access\r\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
//reset is requested
|
|
||||||
if(breset_config) {
|
|
||||||
//update EEPROM with default settings
|
|
||||||
if (ESP_SERIAL_OUT.baudRate() != DEFAULT_BAUD_RATE)ESP_SERIAL_OUT.begin(DEFAULT_BAUD_RATE);
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
ESP_SERIAL_OUT.setRxBufferSize(SERIAL_RX_BUFFER_SIZE);
|
|
||||||
#endif
|
|
||||||
delay(2000);
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 ESP EEPROM reset"));
|
|
||||||
#ifdef DEBUG_ESP3D
|
|
||||||
CONFIG::print_config(DEBUG_PIPE, true);
|
|
||||||
delay(1000);
|
|
||||||
#endif
|
|
||||||
CONFIG::reset_config();
|
|
||||||
delay(1000);
|
|
||||||
//put some default value to a void some exception at first start
|
|
||||||
WiFi.mode(WIFI_AP);
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
WiFi.setPhyMode(WIFI_PHY_MODE_11G);
|
|
||||||
#else
|
|
||||||
esp_wifi_set_protocol(ESP_IF_WIFI_AP, WIFI_PHY_MODE_11G);
|
|
||||||
#endif
|
|
||||||
CONFIG::esp_restart();
|
|
||||||
}
|
|
||||||
#if defined(DEBUG_ESP3D) && defined(DEBUG_OUTPUT_SERIAL)
|
|
||||||
LOG("\r\n");
|
|
||||||
delay(500);
|
|
||||||
ESP_SERIAL_OUT.flush();
|
|
||||||
#endif
|
|
||||||
//get target FW
|
|
||||||
CONFIG::InitFirmwareTarget();
|
|
||||||
//Update is done if any so should be Ok
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
SPIFFS.begin(true);
|
|
||||||
#else
|
|
||||||
SPIFFS.begin();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//setup wifi according settings
|
|
||||||
if (!wifi_config.Setup()) {
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Safe mode 1"));
|
|
||||||
//try again in AP mode
|
|
||||||
if (!wifi_config.Setup(true)) {
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Safe mode 2"));
|
|
||||||
wifi_config.Safe_Setup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delay(1000);
|
|
||||||
//setup servers
|
|
||||||
if (!wifi_config.Enable_servers()) {
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Error enabling servers"));
|
|
||||||
}
|
|
||||||
LOG("Setup Done\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//main loop
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
//be sure wifi is on to proceed wifi function
|
|
||||||
if (WiFi.getMode()!=WIFI_OFF ) {
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
if (WiFi.getMode()!=WIFI_STA ) {
|
|
||||||
dnsServer.processNextRequest();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
//web requests
|
|
||||||
web_interface->web_server.handleClient();
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
BRIDGE::processFromTCP2Serial();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
BRIDGE::processFromSerial2TCP();
|
|
||||||
//in case of restart requested
|
|
||||||
if (web_interface->restartmodule) {
|
|
||||||
CONFIG::esp_restart();
|
|
||||||
}
|
|
||||||
}
|
|
326
esp3d/nofile.h
326
esp3d/nofile.h
@ -1,326 +0,0 @@
|
|||||||
/*
|
|
||||||
nofile.h - ESP3D data file
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
//data generated by https://github.com/AraHaan/bin2c
|
|
||||||
//bin2c Conversion Tool v0.14.0 - Windows - [FINAL].
|
|
||||||
#define PAGE_NOFILES_SIZE 4776
|
|
||||||
const char PAGE_NOFILES [] PROGMEM =
|
|
||||||
{
|
|
||||||
|
|
||||||
0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xED, 0x5C, 0x7D, 0x93, 0xDA, 0x46,
|
|
||||||
0x93, 0xFF, 0x2A, 0xB2, 0x52, 0x36, 0x70, 0x2B, 0x58, 0x49, 0xBC, 0xA3, 0x05, 0x3F, 0x49, 0x1C,
|
|
||||||
0x5F, 0x7C, 0xE5, 0xC4, 0x2E, 0xEF, 0xFA, 0xEE, 0xAA, 0xE2, 0x94, 0x4B, 0x48, 0x03, 0xE8, 0xB1,
|
|
||||||
0x90, 0x74, 0xD2, 0xB0, 0xBB, 0x98, 0xF0, 0xDD, 0xAF, 0x7B, 0x5E, 0xA4, 0x91, 0x10, 0x2C, 0xBB,
|
|
||||||
0x49, 0x9E, 0x3C, 0x7F, 0x24, 0x78, 0x11, 0xCC, 0x4C, 0xF7, 0xF4, 0xF4, 0x74, 0xFF, 0xBA, 0xA7,
|
|
||||||
0x87, 0xCA, 0xD5, 0x8A, 0xAE, 0xC3, 0xD9, 0xD5, 0x8A, 0xB8, 0xFE, 0xEC, 0x2A, 0xA3, 0xDB, 0x90,
|
|
||||||
0xCC, 0xB0, 0x65, 0xB7, 0x88, 0x23, 0xDA, 0x5E, 0xB8, 0xEB, 0x20, 0xDC, 0x4E, 0x32, 0x37, 0xCA,
|
|
||||||
0xDA, 0x19, 0x49, 0x83, 0x85, 0xD3, 0x5E, 0x67, 0x6D, 0x4A, 0xEE, 0x69, 0x3B, 0x0B, 0xBE, 0x92,
|
|
||||||
0xB6, 0xEB, 0xFF, 0x73, 0x93, 0xD1, 0x89, 0x65, 0x9A, 0xCF, 0x9D, 0xF6, 0x1D, 0x99, 0x7F, 0x09,
|
|
||||||
0xE8, 0x91, 0x5E, 0xC6, 0x0E, 0x5B, 0xE1, 0x6B, 0x72, 0xBF, 0x9F, 0xC7, 0xFE, 0xB6, 0x34, 0x85,
|
|
||||||
0xFE, 0x23, 0x09, 0x6F, 0x09, 0x0D, 0x3C, 0x57, 0xFB, 0x99, 0x6C, 0x88, 0x6E, 0xE4, 0xDF, 0x8D,
|
|
||||||
0x6F, 0xD3, 0xC0, 0x0D, 0x0D, 0x45, 0x06, 0x85, 0x57, 0x2F, 0xB9, 0x77, 0xC2, 0x20, 0x22, 0xED,
|
|
||||||
0x15, 0x09, 0x96, 0x2B, 0x98, 0xAB, 0xD3, 0xB3, 0x47, 0xFD, 0xA1, 0xD5, 0xEB, 0x3A, 0x5E, 0x1C,
|
|
||||||
0xC6, 0xE9, 0xE4, 0x9B, 0x6E, 0xB7, 0xEB, 0xCC, 0x5D, 0xEF, 0xCB, 0x32, 0x8D, 0x37, 0x91, 0xDF,
|
|
||||||
0x16, 0xAD, 0x8B, 0xC5, 0x62, 0xDF, 0xF1, 0x80, 0x8F, 0x0B, 0xC4, 0xE9, 0x6E, 0xED, 0xA6, 0xCB,
|
|
||||||
0x20, 0x6A, 0xA7, 0x8C, 0x87, 0xBB, 0xA1, 0xB1, 0x23, 0x5A, 0x42, 0xB2, 0x10, 0x0D, 0x89, 0xEB,
|
|
||||||
0xFB, 0x41, 0xB4, 0xE4, 0x2D, 0x56, 0x1F, 0xE6, 0x95, 0x2D, 0x9C, 0x0A, 0x9B, 0xF6, 0xD4, 0x9D,
|
|
||||||
0x87, 0x64, 0x37, 0x8F, 0x53, 0x9F, 0xA4, 0x13, 0xD3, 0xE1, 0x1F, 0xDA, 0x59, 0xE2, 0x7A, 0x30,
|
|
||||||
0x10, 0x1A, 0xD6, 0xEE, 0x7D, 0xFB, 0x2E, 0xF0, 0xE9, 0x8A, 0x29, 0x65, 0xDF, 0x61, 0xE3, 0xDB,
|
|
||||||
0x7C, 0x18, 0xF1, 0x77, 0x45, 0x97, 0x20, 0x9D, 0x58, 0xC9, 0xBD, 0x96, 0xC5, 0x61, 0xE0, 0x6B,
|
|
||||||
0xDF, 0xF8, 0xBE, 0x2F, 0xA5, 0x9A, 0xC7, 0x94, 0xC6, 0xEB, 0x89, 0x8D, 0x9A, 0xA4, 0x40, 0xB6,
|
|
||||||
0x0A, 0x28, 0x61, 0xB3, 0x90, 0x49, 0x14, 0xDF, 0xA5, 0x6E, 0x22, 0x65, 0x9B, 0xD8, 0xEB, 0xF5,
|
|
||||||
0x9E, 0xAE, 0x76, 0x6C, 0x4F, 0xDC, 0x30, 0x58, 0x46, 0x13, 0x94, 0x5F, 0x4C, 0x3C, 0xA3, 0xB8,
|
|
||||||
0x0D, 0x33, 0x9A, 0xCE, 0xA8, 0x6F, 0x1C, 0x34, 0xAD, 0xF2, 0x26, 0x66, 0x1B, 0xE5, 0x51, 0x79,
|
|
||||||
0xD3, 0x6A, 0x27, 0xA7, 0x1A, 0x1D, 0xDF, 0x8A, 0x5B, 0x92, 0xE2, 0x4E, 0x86, 0x42, 0x04, 0x1A,
|
|
||||||
0x27, 0x52, 0x35, 0xF0, 0xB1, 0xB2, 0xC6, 0xAA, 0x52, 0x6A, 0x84, 0xAC, 0xEB, 0x5B, 0x1D, 0xF6,
|
|
||||||
0x1D, 0x88, 0x5D, 0xD7, 0xB7, 0xDA, 0xD5, 0x6A, 0xFA, 0x50, 0x8A, 0x47, 0x71, 0x13, 0x3B, 0x24,
|
|
||||||
0xF6, 0xDA, 0x86, 0x6D, 0x12, 0x34, 0x19, 0x4D, 0x83, 0x44, 0x11, 0x7C, 0x12, 0xD1, 0x55, 0x3B,
|
|
||||||
0x5E, 0xB4, 0xE9, 0x36, 0x21, 0xCD, 0xD8, 0xF7, 0x5B, 0xBB, 0x1A, 0x5B, 0x1D, 0xE3, 0x6B, 0xFF,
|
|
||||||
0x8F, 0x35, 0xF1, 0x03, 0x57, 0x6B, 0xAE, 0xC1, 0x00, 0x38, 0xDF, 0xE1, 0x00, 0x74, 0xDE, 0xDA,
|
|
||||||
0x29, 0x76, 0x2C, 0xDA, 0xFB, 0x68, 0x18, 0x35, 0x04, 0xE3, 0xB1, 0x5D, 0x4B, 0x30, 0x1E, 0x1E,
|
|
||||||
0x21, 0xB0, 0x6C, 0xD3, 0xAC, 0xA5, 0xB0, 0x2C, 0x4E, 0xD2, 0x89, 0xDC, 0x5B, 0xD5, 0x6C, 0x85,
|
|
||||||
0xC8, 0x9E, 0xE7, 0x55, 0x1C, 0xC6, 0xAC, 0xBA, 0x8B, 0x09, 0xC6, 0x92, 0x81, 0x1B, 0x23, 0xE2,
|
|
||||||
0x80, 0xD5, 0x46, 0xA4, 0xC6, 0x4B, 0x99, 0xEF, 0x72, 0x85, 0xA6, 0xAE, 0x1F, 0x6C, 0xB2, 0xC9,
|
|
||||||
0x00, 0x8C, 0xAC, 0xC6, 0x09, 0xDC, 0x5D, 0x12, 0x67, 0x01, 0x0D, 0xE2, 0x68, 0x92, 0x92, 0xD0,
|
|
||||||
0xA5, 0xC1, 0x2D, 0x71, 0xFC, 0x20, 0x4B, 0x42, 0x77, 0x3B, 0x99, 0x87, 0xB1, 0xF7, 0x25, 0x77,
|
|
||||||
0x08, 0x44, 0x1F, 0x8D, 0xB9, 0x2F, 0xF3, 0x09, 0x9F, 0x78, 0x71, 0xEA, 0x32, 0x42, 0x26, 0x43,
|
|
||||||
0x21, 0xFF, 0xBE, 0xE3, 0x7A, 0xC8, 0x67, 0x57, 0x20, 0x46, 0x8D, 0x84, 0xA6, 0x69, 0xCA, 0x81,
|
|
||||||
0x9A, 0x6B, 0xB8, 0x93, 0x45, 0xEC, 0x6D, 0x32, 0x78, 0xAE, 0x62, 0xB0, 0xF9, 0x9D, 0x0A, 0x36,
|
|
||||||
0x89, 0x1B, 0x91, 0x70, 0x77, 0x28, 0x7B, 0x3D, 0x38, 0x1D, 0xF1, 0xFF, 0xB2, 0x32, 0x10, 0xFC,
|
|
||||||
0x24, 0xEA, 0xCE, 0xE3, 0xFB, 0x76, 0xB6, 0x72, 0xFD, 0xF8, 0x6E, 0x62, 0x6A, 0x48, 0x85, 0x7F,
|
|
||||||
0xE9, 0x72, 0xEE, 0x36, 0x4D, 0x03, 0x5F, 0x1D, 0xB3, 0xDF, 0x72, 0xCE, 0x19, 0x24, 0x24, 0x6D,
|
|
||||||
0x33, 0x84, 0xCE, 0xB5, 0x86, 0xE0, 0x26, 0x3A, 0xD0, 0xD8, 0xA1, 0x6D, 0x77, 0xA8, 0xD1, 0xD3,
|
|
||||||
0x88, 0xDB, 0xC7, 0x97, 0x5C, 0x81, 0x68, 0x54, 0xD6, 0x04, 0x48, 0xC0, 0x4D, 0x43, 0xAE, 0xAE,
|
|
||||||
0x8B, 0xBA, 0x29, 0xFA, 0xD0, 0x8C, 0x6A, 0xBA, 0x84, 0x26, 0x2B, 0xDE, 0x1B, 0xBA, 0x73, 0x50,
|
|
||||||
0xB6, 0xB4, 0x80, 0x20, 0x62, 0xB8, 0xC4, 0x0D, 0xA1, 0x0C, 0xC1, 0x15, 0x63, 0xC2, 0x55, 0xB0,
|
|
||||||
0xE8, 0x72, 0xC7, 0x31, 0x6C, 0x88, 0xDB, 0xCB, 0x0C, 0x25, 0x88, 0x16, 0xB1, 0xDC, 0xCF, 0x2E,
|
|
||||||
0x18, 0xFF, 0x08, 0xB6, 0x74, 0x11, 0xA7, 0xEB, 0x36, 0x7A, 0x46, 0x1A, 0x17, 0x93, 0xF1, 0x59,
|
|
||||||
0xF8, 0x0C, 0x2C, 0x70, 0x08, 0x38, 0xEC, 0xF6, 0x8A, 0x90, 0x81, 0x66, 0xAC, 0x59, 0xB6, 0x9C,
|
|
||||||
0xEC, 0xDC, 0x50, 0xD6, 0xEF, 0xF7, 0x8F, 0x59, 0x4B, 0xD1, 0x1A, 0xAC, 0xDD, 0xA5, 0x74, 0xA8,
|
|
||||||
0x03, 0x1B, 0x42, 0xBF, 0x3C, 0xCB, 0x86, 0x82, 0x28, 0x23, 0x54, 0x3B, 0x62, 0x24, 0xC3, 0xB2,
|
|
||||||
0x29, 0x3D, 0x38, 0xB6, 0x1D, 0xB7, 0x69, 0x0A, 0xE1, 0x9B, 0x3B, 0xA8, 0x6A, 0x01, 0x1A, 0x71,
|
|
||||||
0x33, 0x02, 0xBA, 0x6D, 0xC7, 0x1B, 0xAA, 0x75, 0xAC, 0x7E, 0x66, 0x14, 0x7C, 0x0F, 0xFA, 0xCA,
|
|
||||||
0x0A, 0xE7, 0xAE, 0xB6, 0x2B, 0xDB, 0xD3, 0x60, 0xE0, 0x2E, 0xC8, 0xD8, 0x01, 0x0A, 0xD4, 0x24,
|
|
||||||
0x04, 0xDC, 0x27, 0x2C, 0xCD, 0x30, 0xA1, 0x73, 0x24, 0x3B, 0x2C, 0xD3, 0x36, 0xAC, 0x61, 0xDF,
|
|
||||||
0xB0, 0xBB, 0x5D, 0xA3, 0x33, 0x68, 0x09, 0x19, 0x50, 0xD7, 0x49, 0xC5, 0x99, 0xB9, 0x8F, 0xCC,
|
|
||||||
0x69, 0x74, 0xCC, 0xEE, 0xD4, 0xC1, 0x66, 0xC9, 0xCC, 0x7A, 0xA6, 0xE9, 0x28, 0x21, 0xDA, 0x23,
|
|
||||||
0x11, 0x25, 0x69, 0x35, 0x6A, 0xAE, 0x03, 0xDF, 0x0F, 0x09, 0x4F, 0xC0, 0xE2, 0x8D, 0xB7, 0x6A,
|
|
||||||
0x23, 0xEC, 0x80, 0x3E, 0xD7, 0x6E, 0x14, 0x24, 0x9B, 0x90, 0x81, 0x98, 0x73, 0xBC, 0xC7, 0xDB,
|
|
||||||
0xA4, 0x19, 0xA8, 0x28, 0x89, 0x03, 0xC6, 0xFC, 0x4C, 0x8B, 0x61, 0xFB, 0x96, 0xB8, 0x29, 0x48,
|
|
||||||
0xE4, 0x9C, 0x48, 0x33, 0x1E, 0x69, 0xCF, 0x35, 0x26, 0xB8, 0x8E, 0xBF, 0xB6, 0x37, 0x19, 0x26,
|
|
||||||
0x4B, 0x24, 0x24, 0x1E, 0xE5, 0xE2, 0xE0, 0x5A, 0x0F, 0x1A, 0xAB, 0x0D, 0x4C, 0xE7, 0xED, 0x24,
|
|
||||||
0x85, 0x65, 0xA4, 0xDB, 0xD3, 0x68, 0xDD, 0xED, 0x0E, 0xDD, 0xF9, 0xB0, 0x82, 0x41, 0x36, 0x19,
|
|
||||||
0xF8, 0x6E, 0xAF, 0xC4, 0x45, 0x20, 0xBA, 0x51, 0x6A, 0xE3, 0xD0, 0x5E, 0x6A, 0x62, 0x28, 0x5F,
|
|
||||||
0x6A, 0x9A, 0xD4, 0x50, 0x4E, 0x0E, 0x29, 0x0F, 0xE2, 0x43, 0x8D, 0xB0, 0xF6, 0x68, 0x60, 0x8E,
|
|
||||||
0xCD, 0x8A, 0xB0, 0x96, 0x6D, 0xCF, 0x7B, 0xE6, 0xDE, 0x73, 0x13, 0xDC, 0x54, 0x89, 0xC1, 0x2C,
|
|
||||||
0x8D, 0x1A, 0x29, 0x29, 0xA9, 0xB0, 0xB2, 0x51, 0x01, 0xCA, 0xC3, 0xE1, 0xD0, 0x39, 0xC8, 0x02,
|
|
||||||
0xDD, 0x10, 0x4C, 0xAC, 0x04, 0xF2, 0x35, 0xC1, 0xF5, 0xB4, 0x51, 0x1C, 0x6C, 0xA5, 0xE0, 0xDA,
|
|
||||||
0xCE, 0x36, 0x9E, 0x47, 0xB2, 0xAC, 0x26, 0x9F, 0xF1, 0x17, 0x0B, 0xD3, 0x1F, 0x55, 0x23, 0xC1,
|
|
||||||
0x80, 0x8C, 0xBD, 0x41, 0x1E, 0x42, 0xBC, 0xE1, 0xA0, 0xEB, 0x4B, 0x56, 0xBE, 0x1B, 0x2D, 0x41,
|
|
||||||
0x5B, 0x35, 0xD0, 0x67, 0xFB, 0xC4, 0x27, 0x15, 0x4E, 0x64, 0xEE, 0x79, 0xBE, 0x25, 0x39, 0xB9,
|
|
||||||
0xE3, 0x5E, 0xAF, 0x67, 0xEF, 0x3B, 0x2B, 0x37, 0x6B, 0x93, 0x34, 0x05, 0xC8, 0x29, 0xC3, 0x76,
|
|
||||||
0x99, 0x96, 0x8F, 0xFE, 0xB3, 0x01, 0xF1, 0xA8, 0x34, 0xB5, 0x98, 0x36, 0xEA, 0x75, 0xFB, 0xDD,
|
|
||||||
0xDE, 0x93, 0x91, 0x0C, 0x5D, 0xF3, 0x1B, 0x8F, 0x8C, 0x7A, 0xA3, 0xEE, 0x63, 0x64, 0xAC, 0xD2,
|
|
||||||
0x96, 0x64, 0x16, 0xE2, 0xB6, 0x79, 0x98, 0xAD, 0xD1, 0xB4, 0xD8, 0xFC, 0x93, 0xBA, 0xE6, 0x7B,
|
|
||||||
0xFC, 0xAF, 0xD1, 0x75, 0xAD, 0x3C, 0xB5, 0xDA, 0xB6, 0xE7, 0xFD, 0x9E, 0xED, 0xFD, 0x3E, 0x6D,
|
|
||||||
0x0F, 0x86, 0x73, 0x6B, 0x30, 0x7A, 0x9A, 0xB6, 0x39, 0x6D, 0x45, 0xEA, 0x5A, 0x7D, 0x4B, 0x1F,
|
|
||||||
0x41, 0x58, 0x11, 0x1E, 0x72, 0x12, 0x4F, 0xFC, 0x31, 0x98, 0xD1, 0xA2, 0xEA, 0x76, 0xBD, 0xEE,
|
|
||||||
0xA2, 0xEB, 0xAA, 0x4C, 0x4A, 0xD8, 0x27, 0x9A, 0x14, 0x00, 0x13, 0x2D, 0x0A, 0xF2, 0xF1, 0x96,
|
|
||||||
0xC9, 0x21, 0xD9, 0xE4, 0x80, 0xEC, 0x1C, 0xD8, 0xF3, 0xC6, 0x5D, 0xD3, 0xF6, 0x2A, 0x62, 0x0E,
|
|
||||||
0x07, 0x96, 0x67, 0x8D, 0x99, 0x98, 0xC1, 0x7A, 0xB9, 0x13, 0xB1, 0x6C, 0xE5, 0x46, 0xD5, 0x94,
|
|
||||||
0x78, 0x50, 0x87, 0x57, 0x3C, 0x01, 0xE7, 0xB4, 0x42, 0x84, 0x1A, 0x2C, 0x31, 0xF1, 0x55, 0x99,
|
|
||||||
0xD7, 0x04, 0x11, 0xFF, 0x72, 0xC7, 0x03, 0xC1, 0x99, 0xA4, 0xA7, 0x57, 0xDE, 0x35, 0x45, 0xFA,
|
|
||||||
0x21, 0xC7, 0x3E, 0xB4, 0xD2, 0xBF, 0x7E, 0x5D, 0x21, 0x88, 0x06, 0x19, 0xC2, 0x17, 0x69, 0x10,
|
|
||||||
0xEC, 0x30, 0x95, 0xB7, 0x4E, 0x84, 0x8D, 0x2D, 0x82, 0x90, 0xB0, 0xEF, 0xDC, 0x5D, 0xF3, 0xB1,
|
|
||||||
0xE3, 0x1E, 0xEC, 0x6A, 0x10, 0x25, 0x1B, 0xFA, 0x0B, 0x9E, 0x9E, 0xA7, 0x38, 0xEE, 0xD7, 0xC9,
|
|
||||||
0x44, 0x2E, 0x0B, 0xBF, 0xB6, 0x37, 0x49, 0x18, 0xBB, 0x7E, 0x7B, 0xBE, 0x81, 0x68, 0xF6, 0x77,
|
|
||||||
0x5E, 0xF6, 0xAF, 0xCD, 0xCB, 0x9C, 0x93, 0x6E, 0xDE, 0x9F, 0x7B, 0xE6, 0x41, 0xE8, 0xEE, 0x0D,
|
|
||||||
0xE6, 0x23, 0xDF, 0x7D, 0xD4, 0xA6, 0x0A, 0xAB, 0xF8, 0x7B, 0x6B, 0xFF, 0x7D, 0xB6, 0xB6, 0x6B,
|
|
||||||
0xCD, 0x4D, 0xBF, 0x7A, 0xD2, 0xB7, 0xE6, 0x03, 0x7F, 0xD4, 0x7F, 0xDC, 0xD6, 0x72, 0x00, 0xFB,
|
|
||||||
0x7B, 0x6B, 0xFF, 0xCD, 0xB7, 0xD6, 0x1E, 0x8C, 0xDD, 0xB9, 0xB7, 0xCF, 0x81, 0xBA, 0x04, 0xE7,
|
|
||||||
0x65, 0xF4, 0x56, 0xD0, 0xBC, 0x94, 0x0A, 0x08, 0x34, 0x17, 0x15, 0xA6, 0x45, 0x1C, 0x83, 0x52,
|
|
||||||
0x4F, 0x14, 0x98, 0x58, 0xFD, 0xE5, 0x69, 0x35, 0xA6, 0x83, 0x3A, 0x2F, 0x1A, 0x1C, 0x86, 0x49,
|
|
||||||
0xBE, 0x57, 0x3D, 0x25, 0x69, 0xE8, 0xE2, 0x4B, 0x25, 0x55, 0x3A, 0xBB, 0xBD, 0xF1, 0xC8, 0x9F,
|
|
||||||
0x57, 0x54, 0xDF, 0x37, 0x9F, 0x3B, 0xB2, 0x6E, 0x0A, 0xD2, 0xCA, 0x9D, 0xC2, 0xCF, 0x60, 0x3B,
|
|
||||||
0x6B, 0x5E, 0x66, 0xCC, 0x92, 0x20, 0xD2, 0xEC, 0x4C, 0xC3, 0xCD, 0x74, 0x53, 0x2D, 0x88, 0x16,
|
|
||||||
0x41, 0x04, 0x96, 0xB0, 0xFF, 0xC7, 0x17, 0xB2, 0x5D, 0xA4, 0xEE, 0x9A, 0x64, 0x1A, 0x0E, 0xD9,
|
|
||||||
0x99, 0xCF, 0x77, 0xCC, 0x5C, 0x30, 0x63, 0x9D, 0xA4, 0x31, 0x75, 0x29, 0x69, 0x9A, 0xAD, 0x3D,
|
|
||||||
0x16, 0xAD, 0x0E, 0x3B, 0xBA, 0x03, 0x00, 0xD3, 0x65, 0x6B, 0xFF, 0x97, 0x68, 0x70, 0x1D, 0xFB,
|
|
||||||
0x6E, 0x51, 0xFF, 0x62, 0x46, 0x94, 0x57, 0x63, 0x17, 0xC1, 0x3D, 0xF1, 0x9D, 0xAF, 0xED, 0x20,
|
|
||||||
0xF2, 0xC9, 0x3D, 0x56, 0xDC, 0xCC, 0xA2, 0x10, 0xCC, 0x78, 0x61, 0x7D, 0xD9, 0x61, 0x25, 0x62,
|
|
||||||
0x70, 0x5A, 0x68, 0x30, 0x1D, 0xA5, 0x38, 0x27, 0x35, 0x88, 0x9F, 0xD1, 0x5C, 0x16, 0x21, 0x24,
|
|
||||||
0x1A, 0xAC, 0xA8, 0x56, 0x5B, 0x89, 0x3D, 0x6C, 0x55, 0x93, 0x90, 0x5E, 0x4B, 0x88, 0xCA, 0xF2,
|
|
||||||
0x7F, 0x70, 0xC1, 0x5D, 0xB1, 0xA6, 0x52, 0x75, 0xD1, 0x32, 0xCB, 0x95, 0xC7, 0x52, 0x55, 0x52,
|
|
||||||
0xED, 0x14, 0x45, 0xFE, 0x63, 0xB4, 0xA2, 0xFB, 0x18, 0x39, 0x5E, 0x0B, 0xE4, 0xE6, 0x24, 0x0B,
|
|
||||||
0x13, 0x4A, 0x7D, 0x16, 0x4B, 0x50, 0x16, 0x42, 0x81, 0x59, 0xCA, 0xA5, 0xEC, 0x96, 0x73, 0x58,
|
|
||||||
0xEB, 0xE6, 0x70, 0x58, 0xBA, 0xA8, 0x9A, 0xD4, 0xA8, 0xE3, 0x9B, 0x05, 0xC1, 0x97, 0xD4, 0x03,
|
|
||||||
0x56, 0x72, 0x15, 0x2B, 0xB1, 0xC5, 0x84, 0x4E, 0x9E, 0xFC, 0xE2, 0xAB, 0x8E, 0x8B, 0x8D, 0xAF,
|
|
||||||
0x63, 0xC5, 0xD9, 0x47, 0xAA, 0xAF, 0x54, 0x9E, 0x5C, 0xE0, 0x4B, 0x8A, 0x57, 0xAE, 0x40, 0x9B,
|
|
||||||
0x42, 0x3A, 0xD9, 0x5B, 0x35, 0xF1, 0x81, 0x94, 0x5E, 0x18, 0x4D, 0xAF, 0xD3, 0x27, 0xEB, 0xC7,
|
|
||||||
0x2F, 0xE5, 0x50, 0x9C, 0xDF, 0xB9, 0xDB, 0x27, 0xEE, 0x6D, 0xCA, 0xD6, 0xC8, 0xFB, 0xFA, 0x23,
|
|
||||||
0xF5, 0x2A, 0x26, 0xF3, 0x52, 0x42, 0x22, 0x0D, 0xB2, 0x7D, 0xA0, 0xCF, 0x0B, 0xD7, 0xC3, 0xC1,
|
|
||||||
0xF0, 0x28, 0x3D, 0xBB, 0x57, 0xDC, 0x5F, 0x5D, 0xF2, 0x9B, 0xDC, 0xAB, 0x4B, 0x7E, 0xAF, 0xCB,
|
|
||||||
0x6E, 0x9B, 0xAE, 0xFC, 0xE0, 0x56, 0x63, 0xED, 0x53, 0x3D, 0x37, 0x21, 0x77, 0x0E, 0x8B, 0xDD,
|
|
||||||
0x50, 0x22, 0x9C, 0x8F, 0x5F, 0xCE, 0x98, 0xFA, 0xEC, 0xBF, 0xAD, 0x8E, 0xA5, 0xBD, 0x88, 0xE6,
|
|
||||||
0x59, 0xE2, 0xF0, 0xF7, 0xAB, 0x4B, 0x20, 0x9F, 0x5D, 0xF1, 0x68, 0x3A, 0xBB, 0x5A, 0xD9, 0xB3,
|
|
||||||
0x37, 0x54, 0xCB, 0x08, 0x59, 0x67, 0xDA, 0x36, 0xDE, 0x68, 0x7E, 0xAC, 0x45, 0x31, 0xD5, 0x56,
|
|
||||||
0x2E, 0x5E, 0x84, 0x44, 0x5B, 0x8D, 0x39, 0x7C, 0x07, 0x6F, 0x92, 0xB5, 0x88, 0x04, 0x74, 0x45,
|
|
||||||
0x52, 0xA5, 0xA9, 0xB3, 0xFC, 0x6A, 0x68, 0x49, 0x88, 0x05, 0x5E, 0x8D, 0x87, 0x7C, 0x2D, 0xA0,
|
|
||||||
0x5A, 0x9C, 0xC2, 0x17, 0x1F, 0xE0, 0x0C, 0x19, 0xA6, 0xDA, 0x22, 0x48, 0xD7, 0x77, 0x10, 0x2B,
|
|
||||||
0xB5, 0x60, 0x01, 0x2C, 0xF0, 0x20, 0x8C, 0x25, 0x37, 0x58, 0x91, 0x0D, 0xCB, 0x92, 0x62, 0xE0,
|
|
||||||
0x92, 0xBC, 0xD0, 0xCD, 0x32, 0x58, 0x12, 0x22, 0x9F, 0xAE, 0x05, 0xFE, 0x54, 0xBF, 0x7E, 0xFF,
|
|
||||||
0xE6, 0xF5, 0xEB, 0x6B, 0xFD, 0xB0, 0x5B, 0x5E, 0x5E, 0xE8, 0xB3, 0xD7, 0xD0, 0xBA, 0xD2, 0x5E,
|
|
||||||
0x43, 0x34, 0xCA, 0xB6, 0x19, 0x25, 0x6B, 0xB1, 0xBC, 0x03, 0x02, 0xD4, 0x1C, 0x30, 0x62, 0x79,
|
|
||||||
0x8B, 0xC6, 0xF2, 0x16, 0x1D, 0x43, 0x18, 0x9F, 0x87, 0xE5, 0x2C, 0x3C, 0x78, 0xEA, 0x5A, 0x04,
|
|
||||||
0xD8, 0x3D, 0xD5, 0xD7, 0x5B, 0x6C, 0xCC, 0x7E, 0xF9, 0x55, 0xD7, 0xD6, 0x9B, 0x90, 0x06, 0x09,
|
|
||||||
0x6A, 0x5B, 0x7E, 0xD2, 0x67, 0x9A, 0xE0, 0x24, 0xE6, 0x80, 0xE3, 0x9A, 0xA6, 0x94, 0x05, 0x75,
|
|
||||||
0x31, 0x03, 0xCF, 0x7F, 0xF8, 0x1C, 0xA5, 0x94, 0x48, 0xD7, 0xE2, 0xC8, 0x0B, 0x03, 0xEF, 0x0B,
|
|
||||||
0xAC, 0x91, 0x44, 0x3E, 0x4E, 0xD5, 0x6C, 0x39, 0xBA, 0x76, 0xEB, 0x86, 0x1B, 0xA0, 0xFB, 0xC8,
|
|
||||||
0xC6, 0xEA, 0xB3, 0xD2, 0xBE, 0x25, 0x69, 0xBC, 0x4C, 0xB1, 0x8C, 0x20, 0xB6, 0xFE, 0x36, 0xC8,
|
|
||||||
0x82, 0x79, 0x10, 0x06, 0x74, 0x3B, 0x59, 0x41, 0x12, 0x44, 0x22, 0x29, 0x7A, 0x92, 0x2E, 0xF9,
|
|
||||||
0x94, 0xEC, 0x03, 0x98, 0xDB, 0x54, 0x07, 0x6B, 0x82, 0xC5, 0x5F, 0x4A, 0x16, 0x60, 0x48, 0x29,
|
|
||||||
0xFF, 0x3B, 0xD0, 0xFB, 0x71, 0xD5, 0xF1, 0x1B, 0xE3, 0x2B, 0x0A, 0x54, 0xD4, 0xD7, 0x98, 0x95,
|
|
||||||
0x4E, 0x75, 0xF3, 0x79, 0xAE, 0xD4, 0xF3, 0x54, 0x51, 0x5A, 0xF7, 0xF7, 0xF1, 0x1A, 0xB2, 0x31,
|
|
||||||
0xBF, 0xD9, 0xC0, 0x2B, 0xC4, 0x86, 0xD1, 0x70, 0xC3, 0xB0, 0xA1, 0xA8, 0xE1, 0x03, 0x59, 0x80,
|
|
||||||
0xB4, 0x2B, 0x94, 0x9C, 0xFA, 0x07, 0xB3, 0xA2, 0x9C, 0x39, 0xB7, 0xEF, 0x53, 0x02, 0x06, 0xE7,
|
|
||||||
0x07, 0x69, 0xB3, 0xA5, 0x2B, 0x92, 0xC0, 0xF1, 0x19, 0x46, 0x66, 0xB7, 0x4B, 0x49, 0xD9, 0x33,
|
|
||||||
0x75, 0x8D, 0x03, 0x0B, 0xFF, 0x7C, 0x1B, 0x90, 0xBB, 0xEF, 0x62, 0xD0, 0x10, 0x9E, 0x6A, 0x7B,
|
|
||||||
0xF8, 0x0F, 0xC6, 0xA7, 0x60, 0x07, 0x1A, 0xB4, 0xF5, 0x75, 0x6D, 0x8B, 0xBA, 0xD3, 0x25, 0x75,
|
|
||||||
0x57, 0xA1, 0xB6, 0xE1, 0x73, 0x0A, 0x83, 0x6C, 0x78, 0x6C, 0xD9, 0x03, 0x76, 0x31, 0x9C, 0xEA,
|
|
||||||
0x22, 0xB7, 0xD2, 0x2F, 0x0B, 0x3E, 0x38, 0x74, 0xCB, 0xD8, 0x09, 0x3E, 0x56, 0xBF, 0xE0, 0x83,
|
|
||||||
0x9F, 0x1F, 0xE0, 0x83, 0x49, 0x30, 0xF2, 0xB1, 0xB8, 0x40, 0x36, 0x3C, 0xF2, 0x8C, 0x12, 0x5A,
|
|
||||||
0x47, 0xE2, 0xEB, 0x9D, 0xE0, 0x38, 0x82, 0xCD, 0x16, 0x4C, 0x58, 0x72, 0xAA, 0xCF, 0x2E, 0x40,
|
|
||||||
0x81, 0xC0, 0x03, 0xF4, 0x08, 0xAA, 0x98, 0x09, 0x17, 0x11, 0x3A, 0xE5, 0x8A, 0x44, 0x73, 0xE1,
|
|
||||||
0x19, 0x54, 0xAE, 0x3E, 0xF1, 0xB5, 0x32, 0x3C, 0x5F, 0x82, 0x99, 0x6F, 0x02, 0x33, 0x35, 0x97,
|
|
||||||
0xAE, 0x72, 0x4A, 0xBC, 0x63, 0x93, 0xC6, 0xAB, 0x52, 0x5F, 0xA2, 0xED, 0x5C, 0x4A, 0x3B, 0xC2,
|
|
||||||
0x87, 0xA4, 0xE0, 0x5F, 0x4A, 0x57, 0xEB, 0xBA, 0xB4, 0xF3, 0x22, 0xFB, 0x46, 0x23, 0xE4, 0x38,
|
|
||||||
0xC8, 0x8C, 0x70, 0xA5, 0x9A, 0xC3, 0x0D, 0x58, 0x19, 0xF0, 0x5E, 0x61, 0xFB, 0xEC, 0x67, 0xF0,
|
|
||||||
0x83, 0xFC, 0xCB, 0x35, 0x68, 0x49, 0x7E, 0x29, 0x19, 0x50, 0xA5, 0x4D, 0xAC, 0x88, 0xB5, 0x0A,
|
|
||||||
0x49, 0xC5, 0x64, 0xE8, 0x00, 0x39, 0x4E, 0x7C, 0x46, 0x5B, 0x65, 0xE3, 0x38, 0x18, 0xCB, 0xF5,
|
|
||||||
0x1C, 0xC1, 0x1D, 0x1E, 0xDE, 0xB8, 0x3F, 0x66, 0x90, 0xE3, 0x6D, 0xB2, 0x42, 0xA3, 0x07, 0xEF,
|
|
||||||
0xE7, 0x78, 0x63, 0x81, 0x7C, 0x12, 0x57, 0x3F, 0x32, 0xB0, 0x7D, 0x00, 0xF8, 0x4A, 0xDE, 0x7B,
|
|
||||||
0x14, 0x07, 0xEF, 0x8E, 0xA2, 0xA0, 0x62, 0x2F, 0x4F, 0x43, 0x3E, 0xE0, 0x7D, 0x80, 0x01, 0x1C,
|
|
||||||
0xE7, 0x0E, 0xD1, 0x0F, 0xD7, 0xA3, 0xCE, 0xF8, 0x18, 0xE8, 0x5B, 0xDC, 0xE5, 0xE0, 0x87, 0x1F,
|
|
||||||
0xEB, 0xE1, 0x2F, 0xE7, 0x0C, 0xE7, 0xB6, 0x88, 0x0D, 0x5F, 0x67, 0x4B, 0xFD, 0x38, 0xFB, 0xD9,
|
|
||||||
0x07, 0x02, 0x9B, 0x07, 0x07, 0xCF, 0x68, 0x99, 0x07, 0xBC, 0x3B, 0x37, 0xA0, 0x1D, 0xF8, 0x0F,
|
|
||||||
0x9C, 0x0A, 0x98, 0x28, 0xAC, 0x3C, 0x48, 0x4C, 0x28, 0xF7, 0x1C, 0xDE, 0x73, 0x68, 0xFC, 0xD5,
|
|
||||||
0x4D, 0xE7, 0xEE, 0x07, 0xA9, 0x5F, 0x02, 0x87, 0xCE, 0xDC, 0x8F, 0x58, 0x5E, 0x50, 0xB6, 0x81,
|
|
||||||
0x52, 0xAA, 0x50, 0xD7, 0xC5, 0x73, 0x41, 0xE8, 0x59, 0x75, 0x67, 0x6F, 0x40, 0x74, 0x1A, 0x2C,
|
|
||||||
0xE0, 0xB4, 0x8C, 0x29, 0x02, 0x44, 0xDC, 0x6E, 0x8D, 0xA1, 0x15, 0x39, 0x9A, 0xCE, 0xD7, 0x20,
|
|
||||||
0x56, 0x52, 0xEA, 0x46, 0xF4, 0xD0, 0xF9, 0xB1, 0x17, 0x32, 0x55, 0x32, 0xFB, 0x08, 0xA7, 0xCD,
|
|
||||||
0x89, 0x58, 0x5E, 0x25, 0x14, 0xAA, 0x95, 0x79, 0x69, 0x0D, 0x9C, 0x3C, 0x5F, 0xE4, 0x67, 0x3C,
|
|
||||||
0xAC, 0x7E, 0xE6, 0x8D, 0x42, 0xE5, 0xC5, 0x3D, 0x7B, 0xA1, 0xB6, 0x55, 0x7A, 0xBE, 0x40, 0xEF,
|
|
||||||
0xA1, 0xEF, 0x0E, 0x80, 0xE2, 0x11, 0x42, 0x25, 0x82, 0x44, 0x15, 0x4C, 0xB6, 0x3D, 0x2C, 0x1C,
|
|
||||||
0x06, 0xCF, 0x23, 0xBA, 0x14, 0x2E, 0x5F, 0x76, 0x32, 0x69, 0xFB, 0xC7, 0xDC, 0xA6, 0x88, 0x8B,
|
|
||||||
0x9B, 0xF9, 0x3A, 0xA0, 0x1F, 0xC8, 0xFF, 0x6D, 0xC0, 0xE4, 0x30, 0x9A, 0x09, 0xAF, 0xE0, 0xED,
|
|
||||||
0xB5, 0xE0, 0x01, 0xD9, 0x65, 0x90, 0xD0, 0xD9, 0x62, 0x13, 0xB1, 0x0A, 0x07, 0xF8, 0xC2, 0xED,
|
|
||||||
0xDC, 0x85, 0x48, 0xB8, 0xBB, 0x85, 0x83, 0x29, 0x90, 0x2A, 0xCE, 0xAF, 0x1B, 0x74, 0xEA, 0x6D,
|
|
||||||
0x52, 0xAC, 0x5C, 0x20, 0x64, 0x77, 0xE0, 0xAC, 0x17, 0xD0, 0xA6, 0x7E, 0xA9, 0xB7, 0x8C, 0x68,
|
|
||||||
0x0A, 0x0F, 0x23, 0x98, 0x5A, 0x0E, 0x68, 0xAB, 0x49, 0x2E, 0x90, 0xCE, 0x17, 0xF2, 0x36, 0x78,
|
|
||||||
0x2C, 0x6D, 0x68, 0xB9, 0x9C, 0x9F, 0x74, 0x85, 0xCD, 0xB4, 0x71, 0xD9, 0x70, 0xB4, 0xE3, 0x11,
|
|
||||||
0xFD, 0x93, 0x3E, 0xBB, 0x64, 0x5E, 0xA0, 0x3B, 0xC1, 0x15, 0xED, 0x84, 0x24, 0x5A, 0xD2, 0x55,
|
|
||||||
0xDB, 0x72, 0x5A, 0xD1, 0xC5, 0x94, 0xFE, 0x12, 0xFC, 0x7A, 0x81, 0x33, 0x1F, 0x99, 0xF1, 0xC8,
|
|
||||||
0x84, 0xFA, 0x45, 0x74, 0xA1, 0x3F, 0x34, 0xA9, 0x7E, 0xC1, 0xB9, 0xE7, 0xFE, 0x2E, 0xA4, 0x30,
|
|
||||||
0x82, 0x8B, 0x0B, 0x27, 0x25, 0x74, 0x93, 0x46, 0x1A, 0x9B, 0x56, 0x75, 0x4E, 0x7D, 0x9F, 0x2B,
|
|
||||||
0x12, 0xEC, 0x2B, 0x5B, 0x7D, 0x0E, 0xC0, 0x70, 0x14, 0x65, 0x16, 0xD9, 0x44, 0xC3, 0xEE, 0x35,
|
|
||||||
0x64, 0x1C, 0x67, 0x9F, 0x65, 0x36, 0xD1, 0xC0, 0x6C, 0xC2, 0xB2, 0x47, 0xF8, 0xD7, 0x80, 0x45,
|
|
||||||
0xAB, 0x53, 0x89, 0xA4, 0xA0, 0xD1, 0xB7, 0x1B, 0x10, 0xCC, 0x1B, 0x16, 0x3C, 0x20, 0xFC, 0x37,
|
|
||||||
0x06, 0x0D, 0x0C, 0xFF, 0xF8, 0x90, 0xBC, 0xFB, 0x05, 0xEF, 0x61, 0x43, 0x98, 0x62, 0x03, 0xC3,
|
|
||||||
0x3A, 0x1C, 0x17, 0x7D, 0xA7, 0xA1, 0x5D, 0xCE, 0x84, 0xCE, 0xAA, 0x1C, 0xEB, 0x79, 0xD8, 0x65,
|
|
||||||
0x1E, 0x2C, 0x33, 0xA8, 0xE3, 0xD2, 0x35, 0x39, 0x97, 0xD1, 0x11, 0xB9, 0x06, 0xC3, 0x82, 0x27,
|
|
||||||
0xE0, 0xEA, 0x59, 0x92, 0xD9, 0x65, 0x9E, 0x96, 0xC9, 0x99, 0xE2, 0x53, 0x70, 0x1D, 0xA9, 0x5C,
|
|
||||||
0x7B, 0x8F, 0x61, 0x6A, 0x8F, 0x6B, 0x99, 0x74, 0xCF, 0x5C, 0x6E, 0x8F, 0x73, 0xE9, 0x75, 0xB9,
|
|
||||||
0x68, 0x43, 0x2E, 0xD9, 0x30, 0xE7, 0xA9, 0xB0, 0x1C, 0x9C, 0xCB, 0x73, 0xF0, 0x27, 0xF0, 0x1C,
|
|
||||||
0xFD, 0x11, 0x3C, 0x79, 0xFE, 0xA7, 0x18, 0x38, 0x1E, 0xA4, 0xA5, 0x7D, 0x73, 0x23, 0x3D, 0xDF,
|
|
||||||
0xBE, 0xED, 0x1E, 0xFC, 0x6B, 0x40, 0x70, 0x06, 0x7F, 0xD4, 0xFC, 0x69, 0xE3, 0xA7, 0xA1, 0xD1,
|
|
||||||
0xD5, 0xDE, 0xDA, 0xC6, 0x48, 0x7B, 0x3B, 0x34, 0xAC, 0x2E, 0x7B, 0x37, 0xB5, 0xB7, 0x96, 0x78,
|
|
||||||
0x8C, 0x0C, 0xCB, 0xE2, 0x8F, 0x3E, 0x6F, 0x1C, 0xC0, 0xC3, 0x64, 0x8F, 0xB1, 0x61, 0x0D, 0xD9,
|
|
||||||
0xFB, 0x98, 0x35, 0xD9, 0x30, 0xDC, 0x16, 0x0F, 0xDB, 0xB0, 0x46, 0xEC, 0x31, 0x62, 0x6D, 0x03,
|
|
||||||
0xE4, 0x3A, 0xD0, 0xBE, 0xE2, 0x02, 0xD3, 0xF8, 0x0B, 0xAC, 0x90, 0x5D, 0x33, 0x35, 0x78, 0xBA,
|
|
||||||
0xDB, 0x60, 0x2B, 0xAD, 0x5D, 0x28, 0x4F, 0x6B, 0x3E, 0xE3, 0x01, 0x81, 0xB4, 0x76, 0x0A, 0x92,
|
|
||||||
0x5C, 0x4C, 0x09, 0x43, 0x1F, 0x15, 0x47, 0x74, 0x96, 0xE2, 0x19, 0x3A, 0xE0, 0x88, 0xDE, 0x2A,
|
|
||||||
0x78, 0x78, 0xF1, 0x1A, 0x6B, 0xBE, 0xD7, 0x90, 0x9F, 0x46, 0xCB, 0xAC, 0x49, 0x0C, 0x2A, 0x95,
|
|
||||||
0x06, 0xB8, 0x40, 0x3A, 0x34, 0x7E, 0x1B, 0xDF, 0x91, 0xF4, 0x7B, 0xC8, 0x0D, 0x9A, 0x2D, 0x80,
|
|
||||||
0x59, 0x5A, 0x69, 0x21, 0x57, 0xF4, 0x65, 0xDB, 0x9A, 0x90, 0x19, 0x7D, 0x69, 0x4D, 0xCC, 0x82,
|
|
||||||
0x2D, 0x16, 0xDC, 0x5C, 0xEA, 0xAD, 0x58, 0xA6, 0xC5, 0x32, 0x44, 0x14, 0x11, 0xD1, 0x06, 0x72,
|
|
||||||
0x79, 0x00, 0xCC, 0x45, 0x13, 0x9E, 0xEA, 0x49, 0xF0, 0x9A, 0x0D, 0x9A, 0x68, 0xFA, 0x05, 0xE9,
|
|
||||||
0x70, 0x02, 0x83, 0x5E, 0x94, 0x87, 0xFC, 0xA6, 0x7E, 0xB9, 0x89, 0xA9, 0x1B, 0x6A, 0xBC, 0x42,
|
|
||||||
0xCD, 0x88, 0x28, 0x36, 0x9C, 0xA6, 0x81, 0x00, 0xEF, 0xAB, 0x24, 0x10, 0xB1, 0xFD, 0xD3, 0x14,
|
|
||||||
0xEF, 0x3C, 0x6F, 0x93, 0xF0, 0xD2, 0xA8, 0xA6, 0xB3, 0xA1, 0x57, 0x6B, 0x02, 0x71, 0x50, 0x5B,
|
|
||||||
0x07, 0x11, 0x18, 0x4C, 0x83, 0x65, 0x62, 0x1C, 0x31, 0x56, 0x60, 0x51, 0xD3, 0xC6, 0x18, 0x3E,
|
|
||||||
0xF1, 0xD8, 0xD6, 0xC0, 0x19, 0xE2, 0x9C, 0x1E, 0x70, 0x1D, 0x36, 0x90, 0x11, 0x8B, 0x43, 0x44,
|
|
||||||
0xB5, 0xFF, 0xB9, 0x6E, 0xF8, 0xB1, 0xB7, 0x59, 0xC3, 0x1E, 0x76, 0x96, 0x84, 0xFE, 0x10, 0x12,
|
|
||||||
0xFC, 0xF8, 0xDD, 0xF6, 0x0D, 0xEC, 0x9D, 0x48, 0xB2, 0x5B, 0x9D, 0x20, 0x8A, 0x48, 0xFA, 0xE3,
|
|
||||||
0xCD, 0x4F, 0x6F, 0xA7, 0xD4, 0x40, 0x4D, 0x1A, 0xB0, 0xCD, 0xCF, 0xD4, 0xE0, 0xC7, 0x95, 0x1C,
|
|
||||||
0x95, 0xE2, 0x21, 0xC4, 0x1E, 0xFA, 0x06, 0xEB, 0x1B, 0xEF, 0x16, 0x18, 0x15, 0x8D, 0x52, 0x1F,
|
|
||||||
0x0F, 0x5B, 0x76, 0xCB, 0x61, 0xAB, 0xA3, 0xA9, 0xF4, 0x32, 0xF5, 0x32, 0xF7, 0x44, 0xC0, 0x2A,
|
|
||||||
0xC5, 0x5D, 0x18, 0x42, 0x9A, 0xA6, 0x11, 0x5D, 0x58, 0xAD, 0x87, 0xE3, 0x18, 0x86, 0x45, 0x08,
|
|
||||||
0x66, 0x8A, 0xB7, 0x16, 0x31, 0x0D, 0xCC, 0x32, 0xC4, 0x94, 0x04, 0xB0, 0xA1, 0x31, 0x83, 0xB3,
|
|
||||||
0x00, 0x26, 0xA4, 0x32, 0xDF, 0xD4, 0xF7, 0x84, 0x15, 0xEA, 0xB3, 0x0E, 0xC8, 0x47, 0x9B, 0xD2,
|
|
||||||
0xE4, 0x4A, 0xA6, 0x5B, 0xB5, 0xEA, 0x0E, 0x66, 0xD2, 0x06, 0x65, 0x8F, 0xD6, 0xBE, 0xC5, 0x92,
|
|
||||||
0x01, 0xD4, 0x53, 0x30, 0x35, 0x21, 0x78, 0x4B, 0x7E, 0x5C, 0x17, 0x0E, 0xC4, 0xD1, 0x96, 0xDE,
|
|
||||||
0xB6, 0x40, 0xAF, 0x9C, 0xBE, 0x29, 0xFA, 0x21, 0xEA, 0x76, 0xF0, 0x74, 0xDA, 0x7A, 0xF1, 0xA2,
|
|
||||||
0xC9, 0x94, 0x75, 0xF3, 0x61, 0x26, 0x8C, 0x82, 0x65, 0xDD, 0x00, 0x31, 0x2A, 0xAE, 0x28, 0x70,
|
|
||||||
0x53, 0x03, 0x31, 0xDA, 0xEC, 0x13, 0x2D, 0x50, 0xC6, 0x32, 0x6C, 0x40, 0x09, 0xC3, 0xB6, 0x10,
|
|
||||||
0x6B, 0x6C, 0xFC, 0x3C, 0xE0, 0x8F, 0x21, 0x6B, 0xB3, 0x10, 0x1F, 0xDE, 0x5A, 0xB6, 0x78, 0xB7,
|
|
||||||
0x34, 0x1C, 0x66, 0x9D, 0x81, 0x18, 0x58, 0xC7, 0xD7, 0xEE, 0x2D, 0x1E, 0x91, 0xB7, 0xF8, 0x6C,
|
|
||||||
0x68, 0xF7, 0x36, 0x3C, 0x00, 0x59, 0xB7, 0x36, 0x8B, 0x80, 0x15, 0x0E, 0xFC, 0x6B, 0x5B, 0x08,
|
|
||||||
0x6F, 0x35, 0x2E, 0xE5, 0x12, 0x73, 0x56, 0x7D, 0xC1, 0xC9, 0x14, 0xAC, 0xBA, 0x9C, 0x95, 0x65,
|
|
||||||
0x9E, 0xC1, 0x0B, 0xD6, 0x7C, 0xC0, 0xA7, 0x57, 0xE1, 0xD3, 0x7B, 0x22, 0x9F, 0x51, 0x85, 0xCF,
|
|
||||||
0xE8, 0x0C, 0x3E, 0xB2, 0x76, 0xC0, 0xF2, 0x27, 0x58, 0x66, 0xE3, 0xEA, 0xE6, 0x95, 0xC8, 0xD5,
|
|
||||||
0x3E, 0x89, 0x64, 0xED, 0x53, 0x23, 0x2F, 0x4B, 0xCA, 0xDA, 0x75, 0x72, 0xEF, 0x80, 0xF9, 0xBA,
|
|
||||||
0xDA, 0x2A, 0x25, 0x8B, 0xA9, 0xDE, 0x00, 0x3F, 0x66, 0xA0, 0xAB, 0x98, 0x09, 0xDA, 0xD9, 0x45,
|
|
||||||
0x03, 0x92, 0x72, 0x37, 0x05, 0x57, 0x9E, 0x7E, 0x06, 0x01, 0xA2, 0x2F, 0xA5, 0xAC, 0x3A, 0xFF,
|
|
||||||
0x25, 0x81, 0x3E, 0x6B, 0xE0, 0xCC, 0x15, 0x62, 0xAE, 0x73, 0x91, 0x0F, 0xBB, 0xF0, 0x77, 0xF3,
|
|
||||||
0x6A, 0x06, 0xB2, 0x71, 0x29, 0x2B, 0xF6, 0x28, 0xC6, 0xF2, 0x11, 0xD2, 0xEC, 0xCC, 0xE7, 0x0D,
|
|
||||||
0x75, 0xBE, 0x4F, 0xA2, 0x70, 0xF4, 0x49, 0x57, 0x5C, 0xF9, 0x15, 0xC4, 0x0F, 0x4A, 0x9A, 0x0C,
|
|
||||||
0xA9, 0xCA, 0xA2, 0xEB, 0x8D, 0x16, 0x66, 0x9A, 0xC8, 0x59, 0x4D, 0x17, 0x4B, 0x52, 0xE1, 0x7C,
|
|
||||||
0xDC, 0x27, 0xF1, 0x0D, 0x7D, 0xA1, 0xF0, 0xAB, 0x10, 0xFC, 0x2A, 0xAC, 0xFA, 0x55, 0x28, 0xFC,
|
|
||||||
0x6A, 0x5A, 0xF5, 0xAB, 0xF0, 0x0F, 0xF5, 0x2B, 0xC5, 0xAB, 0xC6, 0x3C, 0x3C, 0x8F, 0x31, 0xD0,
|
|
||||||
0x42, 0x90, 0x86, 0x78, 0x2C, 0xDE, 0xFA, 0x18, 0x72, 0x7B, 0xE8, 0x45, 0x3D, 0xF4, 0xBB, 0x3E,
|
|
||||||
0x73, 0x3E, 0x9B, 0x0D, 0xC5, 0x07, 0x06, 0x6A, 0x74, 0xC5, 0x2E, 0xA3, 0xEF, 0xB3, 0x77, 0x9B,
|
|
||||||
0x7B, 0x22, 0xF4, 0x9F, 0x17, 0xA7, 0x0B, 0xA3, 0xD2, 0x71, 0x5B, 0xCA, 0x27, 0x00, 0x2D, 0xDF,
|
|
||||||
0xFE, 0x3C, 0xAB, 0x39, 0xBC, 0x0E, 0x53, 0x51, 0x57, 0x09, 0xF5, 0xCA, 0x76, 0x85, 0xC5, 0x76,
|
|
||||||
0x39, 0x72, 0xBF, 0x2A, 0x7D, 0x25, 0xE3, 0x90, 0xF2, 0x3C, 0xD9, 0x56, 0x8E, 0xCF, 0xFF, 0x24,
|
|
||||||
0x73, 0x39, 0x1A, 0xEF, 0x8A, 0x9A, 0x54, 0x39, 0xE4, 0x1D, 0x25, 0x60, 0xA5, 0x3A, 0x75, 0xAC,
|
|
||||||
0x3C, 0x2E, 0x16, 0x29, 0x89, 0xB0, 0x76, 0xCC, 0x94, 0xE2, 0x08, 0xEB, 0xF7, 0x4D, 0xFD, 0x7B,
|
|
||||||
0xFE, 0x41, 0xF3, 0xB1, 0x0B, 0xC7, 0xC4, 0x0B, 0xDC, 0x4C, 0x9E, 0x1E, 0x80, 0x39, 0x96, 0xF2,
|
|
||||||
0x27, 0x36, 0x88, 0x40, 0x06, 0x7B, 0xC0, 0x53, 0x26, 0x60, 0xA7, 0xD8, 0xC2, 0x18, 0xD8, 0xC0,
|
|
||||||
0x38, 0xDD, 0x9E, 0xE0, 0x0D, 0x63, 0xCA, 0xEC, 0x95, 0x02, 0xB0, 0x38, 0xA9, 0x25, 0x29, 0x44,
|
|
||||||
0x36, 0x38, 0xDB, 0xBE, 0xE7, 0xE5, 0x1A, 0x76, 0xD1, 0x50, 0xF0, 0x66, 0x05, 0x23, 0xC8, 0x09,
|
|
||||||
0x40, 0xB5, 0xD1, 0x26, 0x0C, 0x9F, 0x4D, 0x49, 0x65, 0x1E, 0x4F, 0x32, 0x84, 0x79, 0x3A, 0xE0,
|
|
||||||
0x84, 0xEB, 0x66, 0x4B, 0x99, 0x4E, 0x1D, 0xCA, 0xA2, 0x29, 0x4F, 0x25, 0x22, 0x72, 0xA7, 0xFD,
|
|
||||||
0xEF, 0x4F, 0x6F, 0x7F, 0xA4, 0x34, 0x11, 0x27, 0x78, 0x38, 0x50, 0xEB, 0x97, 0xCC, 0x04, 0x5E,
|
|
||||||
0xF2, 0xDF, 0x1F, 0x4C, 0x61, 0x4D, 0x10, 0x37, 0x21, 0x93, 0xC2, 0x56, 0x5E, 0xB6, 0xBA, 0x20,
|
|
||||||
0x91, 0x17, 0xFB, 0xE4, 0xE3, 0x87, 0x37, 0x4D, 0xDA, 0x32, 0x58, 0x27, 0x4B, 0x1A, 0xD4, 0x0E,
|
|
||||||
0x35, 0x71, 0x39, 0xBE, 0xB9, 0xA2, 0x68, 0xDB, 0xEA, 0x30, 0x57, 0xE9, 0x14, 0x95, 0x2C, 0x51,
|
|
||||||
0xD5, 0x0A, 0x61, 0xCD, 0x51, 0x27, 0x8E, 0x60, 0x71, 0xFE, 0x16, 0x53, 0x25, 0xE2, 0xAD, 0xF0,
|
|
||||||
0x27, 0x7D, 0xD3, 0x3C, 0x37, 0x68, 0xED, 0x20, 0xE3, 0xEC, 0x4D, 0xA7, 0x51, 0x87, 0x8D, 0xC1,
|
|
||||||
0x64, 0x93, 0xB4, 0xA0, 0xC9, 0x36, 0x4D, 0x6C, 0xE4, 0xE9, 0x95, 0xD4, 0xF1, 0x7F, 0x5D, 0xBF,
|
|
||||||
0xFB, 0x19, 0x10, 0x3D, 0x85, 0x04, 0x17, 0xC7, 0x67, 0x49, 0x1C, 0x65, 0xE4, 0x86, 0xDC, 0xD3,
|
|
||||||
0x13, 0x06, 0x7B, 0x42, 0x44, 0x51, 0x6D, 0x33, 0x6A, 0x53, 0xE2, 0x3D, 0x09, 0x61, 0x1B, 0x2B,
|
|
||||||
0xE5, 0x91, 0x3D, 0xAE, 0x26, 0x21, 0x51, 0x53, 0xFF, 0xCF, 0x1F, 0x6E, 0xE0, 0x5C, 0x6F, 0x3C,
|
|
||||||
0x33, 0x5B, 0xD0, 0x94, 0xC1, 0xF6, 0x34, 0x2B, 0xDB, 0xC5, 0xCB, 0x8C, 0xBB, 0xBC, 0x8D, 0xD9,
|
|
||||||
0x37, 0x2C, 0x8C, 0x08, 0xD0, 0x85, 0xED, 0x4C, 0x36, 0xAC, 0x04, 0x20, 0xB3, 0x6F, 0xC2, 0x7F,
|
|
||||||
0x54, 0xE0, 0x5F, 0x8A, 0x94, 0xF9, 0x3F, 0x20, 0x7B, 0x3D, 0xBE, 0x2E, 0xBC, 0x6D, 0x69, 0x75,
|
|
||||||
0x78, 0x46, 0x7B, 0xC2, 0xFD, 0xCA, 0xF7, 0x40, 0x92, 0x40, 0x94, 0x42, 0x01, 0xD5, 0xB4, 0x4E,
|
|
||||||
0xA7, 0xA3, 0x5F, 0xE0, 0xE1, 0xE1, 0x35, 0xDE, 0xB9, 0x37, 0xCD, 0x16, 0xE6, 0xBB, 0xFB, 0x3D,
|
|
||||||
0x17, 0xE9, 0x24, 0x0C, 0xC8, 0xE2, 0x6D, 0x8B, 0x63, 0x0E, 0x1E, 0x1D, 0xCC, 0x67, 0x53, 0x59,
|
|
||||||
0x6F, 0x69, 0xED, 0x9E, 0x2C, 0x13, 0x8A, 0x74, 0x02, 0x50, 0xD8, 0xC2, 0x8F, 0x1B, 0x9C, 0x53,
|
|
||||||
0xF8, 0xC6, 0xEB, 0x38, 0x5D, 0xBF, 0x72, 0xA9, 0xEB, 0x44, 0x1D, 0x37, 0x49, 0x70, 0x93, 0x38,
|
|
||||||
0x1C, 0xA9, 0x79, 0x76, 0x35, 0xE5, 0xA4, 0x6A, 0xB2, 0xB9, 0xE3, 0x21, 0x13, 0xCB, 0x3A, 0x0A,
|
|
||||||
0x8F, 0xA2, 0x4C, 0x6D, 0x84, 0x2A, 0xAB, 0x8B, 0x50, 0xA4, 0xB1, 0x48, 0xE5, 0xD7, 0x78, 0xA7,
|
|
||||||
0xE3, 0x0B, 0xEB, 0x79, 0xFF, 0xEE, 0xFA, 0x06, 0x4F, 0x08, 0x8C, 0x8F, 0xCE, 0xAC, 0xC8, 0xEF,
|
|
||||||
0x70, 0xB5, 0x74, 0x20, 0xDA, 0xFC, 0x70, 0x0B, 0x1C, 0xDF, 0x02, 0xC8, 0x12, 0x00, 0x4D, 0x5C,
|
|
||||||
0x31, 0x2F, 0x24, 0x03, 0x34, 0x18, 0xCF, 0x2C, 0x1C, 0x1A, 0x47, 0x38, 0xB4, 0xE2, 0x45, 0xCC,
|
|
||||||
0x65, 0xA6, 0x7E, 0xEE, 0x33, 0x4F, 0xD3, 0xFF, 0x13, 0x34, 0x9F, 0xFB, 0xD1, 0x79, 0xD6, 0x22,
|
|
||||||
0xA6, 0xD3, 0x9D, 0x1A, 0xBF, 0x53, 0x3C, 0xDC, 0x2F, 0x7B, 0xB8, 0x70, 0x48, 0xF6, 0xD3, 0xFE,
|
|
||||||
0xA6, 0xFE, 0x2D, 0x38, 0x14, 0xFB, 0x51, 0x39, 0x9E, 0xD3, 0x60, 0x03, 0xFC, 0x67, 0x70, 0x74,
|
|
||||||
0x06, 0xC5, 0x30, 0x4F, 0x8C, 0x5A, 0xFB, 0xC2, 0x17, 0xD5, 0xA2, 0xFF, 0x9F, 0xEA, 0x8D, 0x8B,
|
|
||||||
0xBB, 0x73, 0xFC, 0x11, 0x0B, 0xFF, 0x6A, 0x34, 0x7C, 0xD8, 0x13, 0x41, 0xCA, 0x83, 0xF8, 0x55,
|
|
||||||
0xB9, 0x8C, 0xD1, 0x5E, 0xEA, 0x2D, 0x29, 0xF7, 0xF1, 0x4D, 0xB8, 0xFB, 0x9D, 0x0E, 0x5B, 0x5C,
|
|
||||||
0xA9, 0x3C, 0xCD, 0x08, 0x94, 0xF9, 0x9F, 0x40, 0xCE, 0x15, 0x77, 0x22, 0xCE, 0x9C, 0xAF, 0xF2,
|
|
||||||
0x13, 0x63, 0xC5, 0x4F, 0x00, 0xE4, 0x44, 0xE2, 0xD7, 0x49, 0x53, 0x1D, 0x7F, 0x9E, 0x74, 0xDA,
|
|
||||||
0x33, 0xD8, 0xF6, 0x9F, 0x40, 0x25, 0x89, 0x32, 0x65, 0x64, 0x32, 0x1E, 0x09, 0x3A, 0x1C, 0x73,
|
|
||||||
0xF4, 0x4B, 0xFD, 0xF1, 0x58, 0xC3, 0x7F, 0x24, 0x01, 0x62, 0xFE, 0x35, 0x70, 0xA3, 0x5A, 0xCF,
|
|
||||||
0xB9, 0x80, 0x73, 0xB0, 0x73, 0x27, 0xEE, 0xC5, 0x4E, 0xB0, 0x91, 0x37, 0x64, 0x4F, 0x33, 0x9F,
|
|
||||||
0x3F, 0xC4, 0xF8, 0x8F, 0x31, 0x91, 0x17, 0xC4, 0xC9, 0xFD, 0x99, 0x9E, 0x23, 0xC1, 0xF3, 0x4F,
|
|
||||||
0xF3, 0xB3, 0x43, 0x72, 0x45, 0x46, 0xE7, 0x20, 0x0F, 0xAB, 0xA0, 0x34, 0x62, 0x8A, 0x8E, 0x05,
|
|
||||||
0x1A, 0x59, 0x2B, 0x7C, 0xF1, 0x42, 0xEF, 0x95, 0xBF, 0xAA, 0xBD, 0xBF, 0xFD, 0x26, 0xF0, 0x5C,
|
|
||||||
0xE0, 0xD8, 0xC2, 0x05, 0x1B, 0xF7, 0xF5, 0x96, 0xA1, 0xDB, 0x70, 0x18, 0x95, 0xA3, 0x5A, 0xE5,
|
|
||||||
0x41, 0x9E, 0x1B, 0x79, 0x20, 0x21, 0x42, 0xBE, 0xC3, 0x62, 0x02, 0xCE, 0xD9, 0x55, 0xC7, 0x73,
|
|
||||||
0x28, 0x34, 0xA2, 0xA9, 0x09, 0xFE, 0xF5, 0x90, 0xD3, 0x3A, 0x41, 0x07, 0x6B, 0x85, 0x3D, 0xD3,
|
|
||||||
0xA0, 0xD3, 0x8C, 0xD0, 0x37, 0x68, 0x2A, 0xA0, 0xE5, 0xA6, 0x62, 0xED, 0xD1, 0xC5, 0xD4, 0x7A,
|
|
||||||
0xD8, 0xF9, 0xF9, 0xD6, 0x44, 0xE7, 0xD8, 0x61, 0x61, 0xD2, 0x3D, 0xAB, 0x1D, 0x19, 0xD1, 0xAC,
|
|
||||||
0x67, 0xC2, 0x11, 0xDB, 0x03, 0x8B, 0x4E, 0xF3, 0xF9, 0x21, 0x35, 0x0F, 0x63, 0x7E, 0x97, 0x0A,
|
|
||||||
0x3A, 0x46, 0xF3, 0xC1, 0x23, 0x81, 0x61, 0x91, 0x6E, 0x39, 0x14, 0x96, 0x54, 0x87, 0x61, 0xF0,
|
|
||||||
0x51, 0x71, 0xB2, 0x08, 0x94, 0x02, 0x37, 0xDE, 0xE2, 0xCD, 0x64, 0xF3, 0x84, 0x3B, 0x9F, 0x93,
|
|
||||||
0x50, 0x1F, 0xA7, 0x95, 0x97, 0xCE, 0x07, 0x08, 0xCB, 0x7E, 0xA0, 0xAD, 0x94, 0xD0, 0x2B, 0x99,
|
|
||||||
0xF7, 0x29, 0x79, 0x8E, 0xF2, 0x64, 0xA8, 0x2D, 0x6C, 0xF6, 0x34, 0xBD, 0x72, 0x47, 0x2C, 0x36,
|
|
||||||
0x52, 0x1C, 0xC2, 0x8C, 0x13, 0x11, 0xB5, 0xEE, 0x12, 0xB7, 0x42, 0x8D, 0xB7, 0x9C, 0x6C, 0xD8,
|
|
||||||
0xCB, 0x8F, 0xD7, 0x3F, 0x7C, 0x50, 0x4F, 0x58, 0x98, 0x71, 0x80, 0x78, 0x11, 0x85, 0x4C, 0xE4,
|
|
||||||
0x42, 0x7F, 0xF1, 0xFE, 0xDB, 0xEB, 0xEB, 0xFF, 0x79, 0xF7, 0xE1, 0x55, 0xFD, 0x10, 0x8A, 0x43,
|
|
||||||
0xAE, 0x3F, 0x7E, 0xF7, 0xD3, 0x9B, 0x9B, 0xE9, 0x16, 0x33, 0xC6, 0xA0, 0x0E, 0xF1, 0x83, 0x07,
|
|
||||||
0x4E, 0x5A, 0x70, 0xCC, 0x0A, 0x94, 0x63, 0xD6, 0x8B, 0x17, 0x00, 0xE1, 0xCF, 0xA0, 0x49, 0xBA,
|
|
||||||
0x66, 0xD9, 0x02, 0xF6, 0x46, 0xA0, 0x9E, 0x75, 0x22, 0x16, 0x36, 0x02, 0x79, 0xD6, 0x41, 0xA5,
|
|
||||||
0xAA, 0x05, 0x67, 0x08, 0x49, 0xCE, 0x5D, 0x10, 0xF9, 0xF1, 0x5D, 0x4D, 0xB4, 0x38, 0x7E, 0xDB,
|
|
||||||
0xE1, 0x5C, 0x5D, 0x8A, 0xEB, 0xE4, 0xAB, 0x4B, 0xF1, 0x03, 0x17, 0xF6, 0x3F, 0x96, 0xF9, 0x7F,
|
|
||||||
0x4B, 0x13, 0x97, 0xBB, 0x5F, 0x46, 0x00, 0x00
|
|
||||||
};
|
|
@ -1,139 +0,0 @@
|
|||||||
/*
|
|
||||||
storestrings.cpp - rolling storage class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#include "storestrings.h"
|
|
||||||
//Constructor
|
|
||||||
STORESTRINGS_CLASS::STORESTRINGS_CLASS (int maxsize, int maxstringlength)
|
|
||||||
{
|
|
||||||
//for rolling buffer
|
|
||||||
//if max size is reached then remove oldest one and add the new one
|
|
||||||
_maxsize=maxsize;
|
|
||||||
//to limit the storage space
|
|
||||||
_maxstringlength=maxstringlength;
|
|
||||||
//need space for the "..."
|
|
||||||
if (_maxstringlength<4 && _maxstringlength!=-1) {
|
|
||||||
_maxstringlength=4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Destructor
|
|
||||||
STORESTRINGS_CLASS::~STORESTRINGS_CLASS ()
|
|
||||||
{
|
|
||||||
// clear list and content
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool STORESTRINGS_CLASS::setsize(int size)
|
|
||||||
{
|
|
||||||
_maxsize=size;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool STORESTRINGS_CLASS::setlength(int len)
|
|
||||||
{
|
|
||||||
if (len < 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_maxstringlength = len;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Clear list and content
|
|
||||||
void STORESTRINGS_CLASS::clear()
|
|
||||||
{
|
|
||||||
//while list is not empty
|
|
||||||
while(_charlist.size()) {
|
|
||||||
//remove element
|
|
||||||
char * str = _charlist.pop();
|
|
||||||
//destroy it
|
|
||||||
delete str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool STORESTRINGS_CLASS::add (const __FlashStringHelper *str)
|
|
||||||
{
|
|
||||||
String stmp;
|
|
||||||
stmp=str;
|
|
||||||
return add(stmp.c_str());
|
|
||||||
}
|
|
||||||
//Add element in storage
|
|
||||||
bool STORESTRINGS_CLASS::add (const char * string)
|
|
||||||
{
|
|
||||||
//if we reach max size
|
|
||||||
if (_maxsize==_charlist.size()) {
|
|
||||||
//remove oldest one
|
|
||||||
char * str = _charlist.shift();
|
|
||||||
delete str;
|
|
||||||
}
|
|
||||||
//add new one
|
|
||||||
//get size including \0 at the end
|
|
||||||
size_t size = strlen(string)+1;
|
|
||||||
bool need_resize=false;
|
|
||||||
if ( (_maxstringlength!=-1) && (size >_maxstringlength+1 )) {
|
|
||||||
need_resize = true;
|
|
||||||
size=_maxstringlength+1;
|
|
||||||
}
|
|
||||||
//reserve memory
|
|
||||||
char * ptr = new char[size*sizeof(char)];
|
|
||||||
//copy string to storage
|
|
||||||
if (need_resize) {
|
|
||||||
//copy maximum length minus 3
|
|
||||||
strncpy(ptr,string,_maxstringlength-3);
|
|
||||||
strcpy(ptr+_maxstringlength-3,"...");
|
|
||||||
} else {
|
|
||||||
//copy as it is
|
|
||||||
strcpy(ptr,string);
|
|
||||||
}
|
|
||||||
//add storage to list
|
|
||||||
_charlist.add(ptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//Remove element at pos position
|
|
||||||
bool STORESTRINGS_CLASS::remove(int pos)
|
|
||||||
{
|
|
||||||
//be sure index is in range
|
|
||||||
if (pos<0 && pos>(_charlist.size()-1)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//remove item from list
|
|
||||||
char * str = _charlist.remove(pos);
|
|
||||||
//destroy item
|
|
||||||
delete str;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//Get element at pos position
|
|
||||||
const char * STORESTRINGS_CLASS::get(int pos)
|
|
||||||
{
|
|
||||||
//be sure index is in range
|
|
||||||
if (pos<0 && pos>(_charlist.size()-1)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return (const char *) _charlist.get(pos);
|
|
||||||
}
|
|
||||||
//Get index for defined string
|
|
||||||
int STORESTRINGS_CLASS::get_index(const char * string)
|
|
||||||
{
|
|
||||||
//parse the list until it is found
|
|
||||||
for (int p=0; p<_charlist.size(); p++) {
|
|
||||||
if (strcmp ( _charlist.get(p), string)==0) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//if not found return -1
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
storestrings.h - rolling storage class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef STORESTRINGS_h
|
|
||||||
#define STORESTRINGS_h
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include "GenLinkedList.h"
|
|
||||||
class STORESTRINGS_CLASS
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
STORESTRINGS_CLASS (int maxsize = -1, int maxstringlength=-1);
|
|
||||||
~STORESTRINGS_CLASS ();
|
|
||||||
bool add (const char * string);
|
|
||||||
inline bool add (String & string)
|
|
||||||
{
|
|
||||||
return add(string.c_str());
|
|
||||||
};
|
|
||||||
bool add (const __FlashStringHelper *str);
|
|
||||||
bool remove(int pos);
|
|
||||||
const char * get(int pos);
|
|
||||||
int get_index(const char * string);
|
|
||||||
void clear();
|
|
||||||
inline int size()
|
|
||||||
{
|
|
||||||
return _charlist.size();
|
|
||||||
};
|
|
||||||
bool setsize(int size);
|
|
||||||
bool setlength(int len);
|
|
||||||
inline int getsize()
|
|
||||||
{
|
|
||||||
return _maxsize;
|
|
||||||
};
|
|
||||||
inline int getlength()
|
|
||||||
{
|
|
||||||
return _maxstringlength;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
int _maxsize;
|
|
||||||
int _maxstringlength;
|
|
||||||
GenLinkedList<char *> _charlist;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
webinterface.h - ESP3D configuration class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WEBINTERFACE_h
|
|
||||||
#define WEBINTERFACE_h
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <WiFiClient.h>
|
|
||||||
#include <WiFiServer.h>
|
|
||||||
#ifndef FS_NO_GLOBALS
|
|
||||||
#define FS_NO_GLOBALS
|
|
||||||
#endif
|
|
||||||
#include <FS.h>
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include <ESP8266WebServer.h>
|
|
||||||
#else
|
|
||||||
#include <WebServer.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include "storestrings.h"
|
|
||||||
|
|
||||||
#define MAX_EXTRUDERS 4
|
|
||||||
|
|
||||||
struct auth_ip {
|
|
||||||
IPAddress ip;
|
|
||||||
level_authenticate_type level;
|
|
||||||
char userID[17];
|
|
||||||
char sessionID[17];
|
|
||||||
uint32_t last_time;
|
|
||||||
auth_ip * _next;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WEBINTERFACE_CLASS
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
WEBINTERFACE_CLASS (int port = 80);
|
|
||||||
~WEBINTERFACE_CLASS();
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
ESP8266WebServer web_server;
|
|
||||||
#else
|
|
||||||
WebServer web_server;
|
|
||||||
#endif
|
|
||||||
FS_FILE fsUploadFile;
|
|
||||||
#ifdef ERROR_MSG_FEATURE
|
|
||||||
STORESTRINGS_CLASS error_msg;
|
|
||||||
#endif
|
|
||||||
#ifdef INFO_MSG_FEATURE
|
|
||||||
STORESTRINGS_CLASS info_msg;
|
|
||||||
#endif
|
|
||||||
#ifdef STATUS_MSG_FEATURE
|
|
||||||
STORESTRINGS_CLASS status_msg;
|
|
||||||
#endif
|
|
||||||
bool restartmodule;
|
|
||||||
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;
|
|
||||||
|
|
||||||
private:
|
|
||||||
auth_ip * _head;
|
|
||||||
uint8_t _nb_ip;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern WEBINTERFACE_CLASS * web_interface;
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,505 +0,0 @@
|
|||||||
/*
|
|
||||||
wificonf.cpp - ESP3D configuration class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#include "config.h"
|
|
||||||
#include "wificonf.h"
|
|
||||||
#include "bridge.h"
|
|
||||||
#include "webinterface.h"
|
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include "ESP8266WiFi.h"
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
#include <ESP8266mDNS.h>
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#include <WiFi.h>
|
|
||||||
#include "esp_wifi.h"
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
#include <ESPmDNS.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#include "IPAddress.h"
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
#include <DNSServer.h>
|
|
||||||
DNSServer dnsServer;
|
|
||||||
const byte DNS_PORT = 53;
|
|
||||||
#endif
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include <ESP8266WebServer.h>
|
|
||||||
#else
|
|
||||||
#include <WebServer.h>
|
|
||||||
#endif
|
|
||||||
#ifdef SSDP_FEATURE
|
|
||||||
#include <ESP8266SSDP.h>
|
|
||||||
#endif
|
|
||||||
#ifdef NETBIOS_FEATURE
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
#include <ESP8266NetBIOS.h>
|
|
||||||
#else
|
|
||||||
#include <ESPNetBIOS.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
extern "C" {
|
|
||||||
#include "user_interface.h"
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef TIMESTAMP_FEATURE
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WIFI_CONFIG::WIFI_CONFIG()
|
|
||||||
{
|
|
||||||
iweb_port=DEFAULT_WEB_PORT;
|
|
||||||
idata_port=DEFAULT_DATA_PORT;
|
|
||||||
baud_rate=DEFAULT_BAUD_RATE;
|
|
||||||
sleep_mode=DEFAULT_SLEEP_MODE;
|
|
||||||
_hostname[0]=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t WIFI_CONFIG::getSignal(int32_t RSSI)
|
|
||||||
{
|
|
||||||
if (RSSI <= -100) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (RSSI >= -50) {
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
return (2* (RSSI+100));
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * WIFI_CONFIG::get_hostname()
|
|
||||||
{
|
|
||||||
String hname;
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
hname = WiFi.hostname();
|
|
||||||
#else
|
|
||||||
hname = WiFi.getHostname();
|
|
||||||
#endif
|
|
||||||
if (hname.length()==0) {
|
|
||||||
if (!CONFIG::read_string(EP_HOSTNAME, _hostname, MAX_HOSTNAME_LENGTH)) {
|
|
||||||
strcpy(_hostname,get_default_hostname());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
strcpy(_hostname,hname.c_str());
|
|
||||||
}
|
|
||||||
return _hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * WIFI_CONFIG::get_default_hostname()
|
|
||||||
{
|
|
||||||
static char hostname[13];
|
|
||||||
uint8_t mac [WL_MAC_ADDR_LENGTH];
|
|
||||||
WiFi.macAddress(mac);
|
|
||||||
if (0>sprintf(hostname,"ESP_%02X%02X%02X",mac[3],mac[4],mac[5])) {
|
|
||||||
strcpy (hostname, "ESP8266");
|
|
||||||
}
|
|
||||||
return hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
//safe setup if no connection
|
|
||||||
void WIFI_CONFIG::Safe_Setup()
|
|
||||||
{
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
dnsServer.stop();
|
|
||||||
delay(100);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WiFi.disconnect();
|
|
||||||
//setup Soft AP
|
|
||||||
WiFi.mode(WIFI_AP);
|
|
||||||
IPAddress local_ip (DEFAULT_IP_VALUE[0],DEFAULT_IP_VALUE[1],DEFAULT_IP_VALUE[2],DEFAULT_IP_VALUE[3]);
|
|
||||||
IPAddress gateway (DEFAULT_GATEWAY_VALUE[0],DEFAULT_GATEWAY_VALUE[1],DEFAULT_GATEWAY_VALUE[2],DEFAULT_GATEWAY_VALUE[3]);
|
|
||||||
IPAddress subnet (DEFAULT_MASK_VALUE[0],DEFAULT_MASK_VALUE[1],DEFAULT_MASK_VALUE[2],DEFAULT_MASK_VALUE[3]);
|
|
||||||
String ssid = FPSTR(DEFAULT_AP_SSID);
|
|
||||||
String pwd = FPSTR(DEFAULT_AP_PASSWORD);
|
|
||||||
WiFi.softAP(ssid.c_str(),pwd.c_str());
|
|
||||||
delay(500);
|
|
||||||
WiFi.softAPConfig( local_ip, gateway, subnet);
|
|
||||||
delay(1000);
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Safe mode started"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Read configuration settings and apply them
|
|
||||||
bool WIFI_CONFIG::Setup(bool force_ap)
|
|
||||||
{
|
|
||||||
char pwd[MAX_PASSWORD_LENGTH+1];
|
|
||||||
char sbuf[MAX_SSID_LENGTH+1];
|
|
||||||
char hostname [MAX_HOSTNAME_LENGTH+1];
|
|
||||||
//int wstatus;
|
|
||||||
IPAddress currentIP;
|
|
||||||
byte bflag=0;
|
|
||||||
byte bmode=0;
|
|
||||||
//system_update_cpu_freq(SYS_CPU_160MHZ);
|
|
||||||
//set the sleep mode
|
|
||||||
if (!CONFIG::read_byte(EP_SLEEP_MODE, &bflag )) {
|
|
||||||
LOG("Error read Sleep mode\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
WiFi.setSleepMode ((WiFiSleepType_t)bflag);
|
|
||||||
#else
|
|
||||||
esp_wifi_set_ps((wifi_ps_type_t)bflag);
|
|
||||||
#endif
|
|
||||||
sleep_mode=bflag;
|
|
||||||
if (force_ap) {
|
|
||||||
bmode = AP_MODE;
|
|
||||||
} else {
|
|
||||||
//AP or client ?
|
|
||||||
if (!CONFIG::read_byte(EP_WIFI_MODE, &bmode ) ) {
|
|
||||||
LOG("Error read wifi mode\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!CONFIG::read_string(EP_HOSTNAME, hostname, MAX_HOSTNAME_LENGTH)) {
|
|
||||||
strcpy(hostname,get_default_hostname());
|
|
||||||
}
|
|
||||||
//this is AP mode
|
|
||||||
if (bmode==AP_MODE) {
|
|
||||||
LOG("Set AP mode\r\n")
|
|
||||||
if(!CONFIG::read_string(EP_AP_SSID, sbuf, MAX_SSID_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!CONFIG::read_string(EP_AP_PASSWORD, pwd, MAX_PASSWORD_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.print(F("SSID "));
|
|
||||||
ESP_SERIAL_OUT.println(sbuf);
|
|
||||||
LOG("SSID ")
|
|
||||||
LOG(sbuf)
|
|
||||||
LOG("\r\n")
|
|
||||||
//DHCP or Static IP ?
|
|
||||||
if (!CONFIG::read_byte(EP_AP_IP_MODE, &bflag )) {
|
|
||||||
LOG("Error IP mode\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
LOG("IP Mode: ")
|
|
||||||
LOG(CONFIG::intTostr(bflag))
|
|
||||||
LOG("\r\n")
|
|
||||||
if (bflag==STATIC_IP_MODE) {
|
|
||||||
byte ip_buf[4];
|
|
||||||
LOG("Static mode\r\n")
|
|
||||||
//get the IP
|
|
||||||
LOG("IP value:")
|
|
||||||
if (!CONFIG::read_buffer(EP_AP_IP_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
LOG("Error\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress local_ip (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
LOG(local_ip.toString())
|
|
||||||
LOG("\r\nGW value:")
|
|
||||||
//get the gateway
|
|
||||||
if (!CONFIG::read_buffer(EP_AP_GATEWAY_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
LOG("Error\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress gateway (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
LOG(gateway.toString())
|
|
||||||
LOG("\r\nMask value:")
|
|
||||||
//get the mask
|
|
||||||
if (!CONFIG::read_buffer(EP_AP_MASK_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
LOG("Error Mask value\r\n")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress subnet (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
LOG(subnet.toString())
|
|
||||||
LOG("\r\n")
|
|
||||||
//apply according active wifi mode
|
|
||||||
LOG("Set IP\r\n")
|
|
||||||
WiFi.softAPConfig( local_ip, gateway, subnet);
|
|
||||||
delay(100);
|
|
||||||
}
|
|
||||||
LOG("Disable STA\r\n")
|
|
||||||
WiFi.enableSTA(false);
|
|
||||||
delay(100);
|
|
||||||
LOG("Set phy mode\r\n")
|
|
||||||
//setup PHY_MODE
|
|
||||||
if (!CONFIG::read_byte(EP_AP_PHY_MODE, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
esp_wifi_set_protocol(ESP_IF_WIFI_AP, bflag);
|
|
||||||
#endif
|
|
||||||
LOG("Set AP\r\n")
|
|
||||||
//setup Soft AP
|
|
||||||
WiFi.mode(WIFI_AP);
|
|
||||||
delay(50);
|
|
||||||
WiFi.softAP(sbuf, pwd);
|
|
||||||
delay(100);
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
WiFi.setPhyMode((WiFiPhyMode_t)bflag);
|
|
||||||
#endif
|
|
||||||
delay(100);
|
|
||||||
LOG("Get current config\r\n")
|
|
||||||
//get current config
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
wifi_config_t conf;
|
|
||||||
esp_wifi_get_config(ESP_IF_WIFI_AP, &conf);
|
|
||||||
#else
|
|
||||||
struct softap_config apconfig;
|
|
||||||
wifi_softap_get_config(&apconfig);
|
|
||||||
#endif
|
|
||||||
//set the chanel
|
|
||||||
if (!CONFIG::read_byte(EP_CHANNEL, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
conf.ap.channel=bflag;
|
|
||||||
#else
|
|
||||||
apconfig.channel=bflag;
|
|
||||||
#endif
|
|
||||||
//set Authentification type
|
|
||||||
if (!CONFIG::read_byte(EP_AUTH_TYPE, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
conf.ap.authmode=(wifi_auth_mode_t)bflag;
|
|
||||||
#else
|
|
||||||
apconfig.authmode=(AUTH_MODE)bflag;
|
|
||||||
#endif
|
|
||||||
//set the visibility of SSID
|
|
||||||
if (!CONFIG::read_byte(EP_SSID_VISIBLE, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
conf.ap.ssid_hidden=!bflag;
|
|
||||||
#else
|
|
||||||
apconfig.ssid_hidden=!bflag;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//no need to add these settings to configuration just use default ones
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
conf.ap.max_connection=DEFAULT_MAX_CONNECTIONS;
|
|
||||||
conf.ap.beacon_interval=DEFAULT_BEACON_INTERVAL;
|
|
||||||
if (esp_wifi_set_config(ESP_IF_WIFI_AP, &conf)!=ESP_OK){
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Error Wifi AP!"));
|
|
||||||
delay(1000);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
apconfig.max_connection=DEFAULT_MAX_CONNECTIONS;
|
|
||||||
apconfig.beacon_interval=DEFAULT_BEACON_INTERVAL;
|
|
||||||
//apply settings to current and to default
|
|
||||||
if (!wifi_softap_set_config(&apconfig) || !wifi_softap_set_config_current(&apconfig)) {
|
|
||||||
ESP_SERIAL_OUT.println(F("M117 Error Wifi AP!"));
|
|
||||||
delay(1000);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
LOG("Set STA mode\r\n")
|
|
||||||
if(!CONFIG::read_string(EP_STA_SSID, sbuf, MAX_SSID_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!CONFIG::read_string(EP_STA_PASSWORD, pwd, MAX_PASSWORD_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.print(F("SSID "));
|
|
||||||
ESP_SERIAL_OUT.println(sbuf);
|
|
||||||
LOG("SSID ")
|
|
||||||
LOG(sbuf)
|
|
||||||
LOG("\r\n")
|
|
||||||
if (!CONFIG::read_byte(EP_STA_IP_MODE, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bflag==STATIC_IP_MODE) {
|
|
||||||
byte ip_buf[4];
|
|
||||||
//get the IP
|
|
||||||
if (!CONFIG::read_buffer(EP_STA_IP_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress local_ip (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
//get the gateway
|
|
||||||
if (!CONFIG::read_buffer(EP_STA_GATEWAY_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress gateway (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
//get the mask
|
|
||||||
if (!CONFIG::read_buffer(EP_STA_MASK_VALUE,ip_buf, IP_LENGTH)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPAddress subnet (ip_buf[0],ip_buf[1],ip_buf[2],ip_buf[3]);
|
|
||||||
//apply according active wifi mode
|
|
||||||
WiFi.config( local_ip, gateway, subnet);
|
|
||||||
}
|
|
||||||
WiFi.enableAP(false);
|
|
||||||
delay(100);
|
|
||||||
//setup PHY_MODE
|
|
||||||
if (!CONFIG::read_byte(EP_STA_PHY_MODE, &bflag )) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
esp_wifi_set_protocol(ESP_IF_WIFI_STA, bflag);
|
|
||||||
#endif
|
|
||||||
//setup station mode
|
|
||||||
WiFi.mode(WIFI_STA);
|
|
||||||
delay(100);
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
WiFi.setPhyMode((WiFiPhyMode_t)bflag);
|
|
||||||
#endif
|
|
||||||
WiFi.begin(sbuf, pwd);
|
|
||||||
delay(100);
|
|
||||||
byte i=0;
|
|
||||||
//try to connect
|
|
||||||
byte dot = 0;
|
|
||||||
String msg;
|
|
||||||
while (WiFi.status() != WL_CONNECTED && i<40) {
|
|
||||||
switch(WiFi.status()) {
|
|
||||||
case 1:
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.println(F("No SSID found!"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.println(F("No Connection!"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
if (dot == 0)msg = F("Connecting");
|
|
||||||
dot++;
|
|
||||||
msg.trim();
|
|
||||||
msg +=F(".");
|
|
||||||
//for smoothieware to keep position
|
|
||||||
for (byte i= 0;i< 4-dot; i++)msg +=F(" ");
|
|
||||||
if (dot == 4)dot=0;
|
|
||||||
ESP_SERIAL_OUT.println(msg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
delay(500);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.println(F("Not Connectied!"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
|
||||||
WiFi.hostname(hostname);
|
|
||||||
#else
|
|
||||||
WiFi.setHostname(hostname);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get IP
|
|
||||||
if (WiFi.getMode()==WIFI_STA) {
|
|
||||||
currentIP=WiFi.localIP();
|
|
||||||
} else {
|
|
||||||
currentIP=WiFi.softAPIP();
|
|
||||||
}
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.println(currentIP);
|
|
||||||
ESP_SERIAL_OUT.flush();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WIFI_CONFIG::Enable_servers()
|
|
||||||
{
|
|
||||||
//start web interface
|
|
||||||
web_interface = new WEBINTERFACE_CLASS(wifi_config.iweb_port);
|
|
||||||
//here the list of headers to be recorded
|
|
||||||
const char * headerkeys[] = {"Cookie"} ;
|
|
||||||
size_t headerkeyssize = sizeof(headerkeys)/sizeof(char*);
|
|
||||||
//ask server to track these headers
|
|
||||||
web_interface->web_server.collectHeaders(headerkeys, headerkeyssize );
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
if (WiFi.getMode()!=WIFI_STA ) {
|
|
||||||
// if DNSServer is started with "*" for domain name, it will reply with
|
|
||||||
// provided IP to all DNS request
|
|
||||||
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
|
|
||||||
dnsServer.start(DNS_PORT, "*", WiFi.softAPIP());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
web_interface->web_server.begin();
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
//start TCP/IP interface
|
|
||||||
data_server = new WiFiServer (wifi_config.idata_port);
|
|
||||||
data_server->begin();
|
|
||||||
data_server->setNoDelay(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
// Set up mDNS responder:
|
|
||||||
//useless in AP mode and service consuming
|
|
||||||
if (WiFi.getMode()!=WIFI_AP ){
|
|
||||||
char hostname [MAX_HOSTNAME_LENGTH+1];
|
|
||||||
if (!CONFIG::read_string(EP_HOSTNAME, hostname, MAX_HOSTNAME_LENGTH)) {
|
|
||||||
strcpy(hostname,get_default_hostname());
|
|
||||||
}
|
|
||||||
if (!mdns.begin(hostname)) {
|
|
||||||
ESP_SERIAL_OUT.print(FPSTR(M117_));
|
|
||||||
ESP_SERIAL_OUT.println(F("Error with mDNS!"));
|
|
||||||
delay(1000);
|
|
||||||
} else {
|
|
||||||
// Check for any mDNS queries and send responses
|
|
||||||
delay(100);
|
|
||||||
wifi_config.mdns.addService("http", "tcp", wifi_config.iweb_port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(SSDP_FEATURE) || defined(NETBIOS_FEATURE)
|
|
||||||
String shost;
|
|
||||||
if (!CONFIG::read_string(EP_HOSTNAME, shost, MAX_HOSTNAME_LENGTH)) {
|
|
||||||
shost=wifi_config.get_default_hostname();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef SSDP_FEATURE
|
|
||||||
String stmp;
|
|
||||||
SSDP.setSchemaURL("description.xml");
|
|
||||||
SSDP.setHTTPPort( wifi_config.iweb_port);
|
|
||||||
SSDP.setName(shost.c_str());
|
|
||||||
stmp=String(ESP.getChipId());
|
|
||||||
SSDP.setSerialNumber(stmp.c_str());
|
|
||||||
SSDP.setURL("/");
|
|
||||||
SSDP.setModelName("ESP8266 01");
|
|
||||||
SSDP.setModelNumber("01");
|
|
||||||
SSDP.setModelURL("http://espressif.com/en/products/esp8266/");
|
|
||||||
SSDP.setManufacturer("Espressif Systems");
|
|
||||||
SSDP.setManufacturerURL("http://espressif.com");
|
|
||||||
SSDP.setDeviceType("upnp:rootdevice");
|
|
||||||
if (WiFi.getMode()!=WIFI_AP )SSDP.begin();
|
|
||||||
#endif
|
|
||||||
#ifdef NETBIOS_FEATURE
|
|
||||||
//useless in AP mode and service consuming
|
|
||||||
if (WiFi.getMode()!=WIFI_AP )NBNS.begin(shost.c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WIFI_CONFIG::Disable_servers()
|
|
||||||
{
|
|
||||||
#ifdef TCP_IP_DATA_FEATURE
|
|
||||||
data_server->stop();
|
|
||||||
#endif
|
|
||||||
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
||||||
if (WiFi.getMode()!=WIFI_STA ) {
|
|
||||||
dnsServer.stop();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef NETBIOS_FEATURE
|
|
||||||
//useless in AP mode and service consuming
|
|
||||||
if (WiFi.getMode()!=WIFI_AP )NBNS.end();
|
|
||||||
#endif
|
|
||||||
web_interface->web_server.stop();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
WIFI_CONFIG wifi_config;
|
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
wificonf.h - ESP3D configuration class
|
|
||||||
|
|
||||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WIFICONF_H
|
|
||||||
#define WIFICONF_H
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "IPAddress.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
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// multicast DNS responder feature
|
|
||||||
#ifdef MDNS_FEATURE
|
|
||||||
MDNSResponder mdns;
|
|
||||||
#endif
|
|
||||||
WIFI_CONFIG();
|
|
||||||
int iweb_port;
|
|
||||||
int idata_port;
|
|
||||||
long baud_rate;
|
|
||||||
int sleep_mode;
|
|
||||||
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:
|
|
||||||
char _hostname[33];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern WIFI_CONFIG wifi_config;
|
|
||||||
#endif
|
|
32
libraries/WebServer/.gitignore
vendored
32
libraries/WebServer/.gitignore
vendored
@ -1,32 +0,0 @@
|
|||||||
# 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
|
|
@ -1,99 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,504 +0,0 @@
|
|||||||
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!
|
|
@ -1,9 +0,0 @@
|
|||||||
# 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
|
|
@ -1,160 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
@ -1,345 +0,0 @@
|
|||||||
/*
|
|
||||||
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();
|
|
||||||
}
|
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
@ -1,97 +0,0 @@
|
|||||||
<!--
|
|
||||||
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>
|
|
@ -1,91 +0,0 @@
|
|||||||
#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();
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
#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();
|
|
||||||
}
|
|
@ -1,290 +0,0 @@
|
|||||||
/*
|
|
||||||
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();
|
|
||||||
}
|
|
@ -1,674 +0,0 @@
|
|||||||
<!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>
|
|
@ -1,22 +0,0 @@
|
|||||||
<!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>
|
|
Binary file not shown.
Before Width: | Height: | Size: 174 KiB |
@ -1,137 +0,0 @@
|
|||||||
#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();
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
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);
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
#######################################
|
|
||||||
# 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
|
|
@ -1,9 +0,0 @@
|
|||||||
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
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
@ -1,610 +0,0 @@
|
|||||||
/*
|
|
||||||
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;
|
|
||||||
}
|
|
@ -1,530 +0,0 @@
|
|||||||
/*
|
|
||||||
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 "";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,236 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
@ -1,19 +0,0 @@
|
|||||||
#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
|
|
@ -1,191 +0,0 @@
|
|||||||
#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
|
|
Loading…
x
Reference in New Issue
Block a user