21 #ifdef ARDUINO_ARCH_ESP32
26 #if ENABLED(ESP3D_WIFISUPPORT)
30 #if defined (ENABLE_HTTP)
31 #include MARLIN_PATH(gcode/queue.h)
32 #include MARLIN_PATH(inc/Version.h)
38 #include <WebSocketsServer.h>
42 #if ENABLED(SDSUPPORT)
45 #include <Preferences.h>
46 #include <WebServer.h>
47 #include <ESP32SSDP.h>
48 #include <StreamString.h>
51 #include <esp_wifi_types.h>
56 #include <ESP32SSDP.h>
58 #ifdef ENABLE_CAPTIVE_PORTAL
59 #include <DNSServer.h>
60 const byte DNS_PORT = 53;
69 UPLOAD_STATUS_NONE = 0,
70 UPLOAD_STATUS_FAILED = 1,
71 UPLOAD_STATUS_CANCELLED = 2,
72 UPLOAD_STATUS_SUCCESSFUL = 3,
73 UPLOAD_STATUS_ONGOING = 4
76 #ifdef ENABLE_AUTHENTICATION
77 #define DEFAULT_ADMIN_PWD "admin"
78 #define DEFAULT_USER_PWD "user";
79 #define DEFAULT_ADMIN_LOGIN "admin"
80 #define DEFAULT_USER_LOGIN "user"
81 #define ADMIN_PWD_ENTRY "ADMIN_PWD"
82 #define USER_PWD_ENTRY "USER_PWD"
83 #define AUTH_ENTRY_NB 20
84 #define MAX_LOCAL_PASSWORD_LENGTH 16
85 #define MIN_LOCAL_PASSWORD_LENGTH 1
89 const char PAGE_404 [] =
"<HTML>\n<HEAD>\n<title>Redirecting...</title> \n</HEAD>\n<BODY>\n<CENTER>Unknown page : $QUERY$- you will be redirected...\n<BR><BR>\nif not redirected, <a href='http://$WEB_ADDRESS$'>click here</a>\n<BR><BR>\n<PROGRESS name='prg' id='prg'></PROGRESS>\n\n<script>\nvar i = 0; \nvar x = document.getElementById(\"prg\"); \nx.max=5; \nvar interval=setInterval(function(){\ni=i+1; \nvar x = document.getElementById(\"prg\"); \nx.value=i; \nif (i>5) \n{\nclearInterval(interval);\nwindow.location.href='/';\n}\n},1000);\n</script>\n</CENTER>\n</BODY>\n</HTML>\n\n";
90 const char PAGE_CAPTIVE [] =
"<HTML>\n<HEAD>\n<title>Captive Portal</title> \n</HEAD>\n<BODY>\n<CENTER>Captive Portal page : $QUERY$- you will be redirected...\n<BR><BR>\nif not redirected, <a href='http://$WEB_ADDRESS$'>click here</a>\n<BR><BR>\n<PROGRESS name='prg' id='prg'></PROGRESS>\n\n<script>\nvar i = 0; \nvar x = document.getElementById(\"prg\"); \nx.max=5; \nvar interval=setInterval(function(){\ni=i+1; \nvar x = document.getElementById(\"prg\"); \nx.value=i; \nif (i>5) \n{\nclearInterval(interval);\nwindow.location.href='/';\n}\n},1000);\n</script>\n</CENTER>\n</BODY>\n</HTML>\n\n";
94 bool Web_Server::_setupdone =
false;
95 uint16_t Web_Server::_port = 0;
96 String Web_Server::_hostname =
"";
97 uint16_t Web_Server::_data_port = 0;
98 long Web_Server::_id_connection = 0;
99 uint8_t Web_Server::_upload_status = UPLOAD_STATUS_NONE;
100 WebServer * Web_Server::_webserver = NULL;
101 WebSocketsServer * Web_Server::_socket_server = NULL;
102 #ifdef ENABLE_AUTHENTICATION
103 auth_ip * Web_Server::_head = NULL;
104 uint8_t Web_Server::_nb_ip = 0;
105 #define MAX_AUTH_IP 10
115 return _id_connection;
120 bool no_error =
true;
131 if (penabled == 0)
return false;
133 _webserver=
new WebServer(_port);
134 #ifdef ENABLE_AUTHENTICATION
136 const char * headerkeys[] = {
"Cookie"} ;
137 size_t headerkeyssize =
sizeof (headerkeys) /
sizeof (
char*);
139 _webserver->collectHeaders (headerkeys, headerkeyssize );
141 _socket_server =
new WebSocketsServer(_port + 1);
142 _socket_server->begin();
143 _socket_server->onEvent(handle_Websocket_Event);
151 _webserver->on(
"/",HTTP_ANY, handle_root);
154 _webserver->onNotFound (handle_not_found);
157 _webserver->on(
"/login", HTTP_ANY, handle_login);
160 _webserver->on (
"/command", HTTP_ANY, handle_web_command);
161 _webserver->on (
"/command_silent", HTTP_ANY, handle_web_command_silent);
164 _webserver->on (
"/files", HTTP_ANY, handleFileList, SPIFFSFileupload);
167 _webserver->on (
"/updatefw", HTTP_ANY, handleUpdate, WebUpdateUpload);
169 #if ENABLED(SDSUPPORT)
171 _webserver->on(
"/upload", HTTP_ANY, handle_direct_SDFileList,SDFile_direct_upload);
174 #ifdef ENABLE_CAPTIVE_PORTAL
175 if(WiFi.getMode() == WIFI_AP){
178 dnsServer.start(DNS_PORT,
"*", WiFi.softAPIP());
179 _webserver->on (
"/generate_204", HTTP_ANY, handle_root);
180 _webserver->on (
"/gconnectivitycheck.gstatic.com", HTTP_ANY, handle_root);
182 _webserver->on (
"/fwlink/", HTTP_ANY, handle_root);
188 if(WiFi.getMode() == WIFI_STA){
189 _webserver->on (
"/description.xml", HTTP_GET, handle_SSDP);
191 SSDP.setSchemaURL (
"description.xml");
192 SSDP.setHTTPPort (_port);
193 SSDP.setName (_hostname);
195 SSDP.setDeviceType (
"upnp:rootdevice");
214 if(WiFi.getMode() == WIFI_STA){
215 MDNS.addService(
"http",
"tcp",_port);
229 mdns_service_remove(
"_http",
"_tcp");
231 if (_socket_server) {
232 delete _socket_server;
233 _socket_server = NULL;
239 #ifdef ENABLE_AUTHENTICATION
241 auth_ip * current = _head;
242 _head = _head->_next;
251 void Web_Server::handle_root()
253 String path =
"/index.html";
254 String contentType = getContentType(path);
255 String pathWithGz = path +
".gz";
257 if((SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) && !_webserver->hasArg(
"forcefallback") && _webserver->arg(
"forcefallback")!=
"yes") {
258 if(SPIFFS.exists(pathWithGz)) {
261 File file = SPIFFS.open(path, FILE_READ);
262 _webserver->streamFile(file, contentType);
267 _webserver->sendHeader(
"Content-Encoding",
"gzip");
272 void Web_Server:: handle_not_found()
275 _webserver->sendContent_P(
"HTTP/1.1 301 OK\r\nLocation: /\r\nCache-Control: no-cache\r\n\r\n");
279 bool page_not_found =
false;
280 String path = _webserver->urlDecode(_webserver->uri());
281 String contentType = getContentType(path);
282 String pathWithGz = path +
".gz";
284 #if ENABLED(SDSUPPORT)
285 if ((path.substring(0,4) ==
"/SD/")) {
287 path = path.substring(3);
290 if (SD_card.
exists(pathWithGz.c_str()) || SD_card.
exists(path.c_str())) {
291 if (!SD_card.
exists(path.c_str())) path = pathWithGz;
292 if(SD_card.
open(path.c_str())) {
294 _webserver->setContentLength(SD_card.
size());
295 _webserver->sendHeader(
"Cache-Control",
"no-cache");
296 _webserver->send(200,
"application/octet-stream",
"");
298 WiFiClient c = _webserver->client();
299 int16_t len = SD_card.
read( buf, 1200);
302 len = SD_card.
read( buf, 1200);
312 String content =
"cannot find ";
314 _webserver->send(404,
"text/plain",content.c_str());
318 if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) {
319 if(SPIFFS.exists(pathWithGz)) {
322 File file = SPIFFS.open(path, FILE_READ);
323 _webserver->streamFile(file, contentType);
327 page_not_found =
true;
330 if (page_not_found ) {
331 #ifdef ENABLE_CAPTIVE_PORTAL
332 if (WiFi.getMode()!=WIFI_STA ) {
333 String content=PAGE_CAPTIVE;
334 String stmp = WiFi.softAPIP().toString();
336 String KEY_IP =
"$WEB_ADDRESS$";
337 String KEY_QUERY =
"$QUERY$";
342 content.replace(KEY_IP,stmp);
343 content.replace(KEY_IP,stmp);
344 content.replace(KEY_QUERY,_webserver->uri());
345 _webserver->send(200,
"text/html",content);
350 contentType = getContentType(path);
351 pathWithGz = path +
".gz";
352 if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) {
353 if(SPIFFS.exists(pathWithGz)) {
356 File file = SPIFFS.open(path, FILE_READ);
357 _webserver->streamFile(file, contentType);
362 contentType = PAGE_404;
364 if (WiFi.getMode()==WIFI_STA ) {
365 stmp=WiFi.localIP().toString();
367 stmp=WiFi.softAPIP().toString();
370 String KEY_IP =
"$WEB_ADDRESS$";
371 String KEY_QUERY =
"$QUERY$";
376 contentType.replace(KEY_IP,stmp);
377 contentType.replace(KEY_QUERY,_webserver->uri());
378 _webserver->send(200,
"text/html",contentType);
384 void Web_Server::handle_SSDP ()
386 StreamString sschema ;
387 if (sschema.reserve (1024) ) {
388 String templ =
"<?xml version=\"1.0\"?>"
389 "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
394 "<URLBase>http://%s:%u/</URLBase>"
396 "<deviceType>upnp:rootdevice</deviceType>"
397 "<friendlyName>%s</friendlyName>"
398 "<presentationURL>/</presentationURL>"
399 "<serialNumber>%s</serialNumber>"
400 "<modelName>ESP32</modelName>"
401 "<modelNumber>Marlin</modelNumber>"
402 "<modelURL>http://espressif.com/en/products/hardware/esp-wroom-32/overview</modelURL>"
403 "<manufacturer>Espressif Systems</manufacturer>"
404 "<manufacturerURL>http://espressif.com</manufacturerURL>"
410 String sip = WiFi.localIP().toString();
411 uint32_t chipId = (uint16_t) (ESP.getEfuseMac() >> 32);
412 sprintf (uuid,
"38323636-4558-4dda-9188-cda0e6%02x%02x%02x",
413 (uint16_t) ( (chipId >> 16) & 0xff),
414 (uint16_t) ( (chipId >> 8) & 0xff),
415 (uint16_t) chipId & 0xff );
416 String serialNumber = String (chipId);
417 sschema.printf (templ.c_str(),
421 serialNumber.c_str(),
423 _webserver->send (200,
"text/xml", (String) sschema);
425 _webserver->send (500);
432 void Web_Server::handle_web_command ()
445 if (_webserver->hasArg (
"plain") || _webserver->hasArg (
"commandText") ) {
446 if (_webserver->hasArg (
"plain") ) {
447 cmd = _webserver->arg (
"plain");
449 cmd = _webserver->arg (
"commandText");
452 _webserver->send (200,
"text/plain",
"Invalid command");
457 int ESPpos = cmd.indexOf (
"[ESP");
460 int ESPpos2 = cmd.indexOf (
"]", ESPpos);
463 String cmd_part1 = cmd.substring (ESPpos + 4, ESPpos2);
464 String cmd_part2 =
"";
466 if ( (auth_level ==
LEVEL_GUEST) && (cmd_part1.toInt() != 800) ) {
467 _webserver->send (401,
"text/plain",
"Authentication failed!\n");
471 if (ESPpos2 < cmd.length() ) {
472 cmd_part2 = cmd.substring (ESPpos2 + 1);
475 if (cmd_part1.toInt() != 0) {
478 execute_internal_command (cmd_part1.toInt(), cmd_part2, auth_level, &espresponse);
486 _webserver->send (401,
"text/plain",
"Authentication failed!\n");
493 scmd = get_Splited_Value(cmd,
'\n', sindex);
494 while ( scmd !=
"" ){
499 scmd = get_Splited_Value(cmd,
'\n', sindex);
501 _webserver->send (200,
"text/plain", res.c_str());
505 void Web_Server::handle_web_command_silent ()
518 if (_webserver->hasArg (
"plain") || _webserver->hasArg (
"commandText") ) {
519 if (_webserver->hasArg (
"plain") ) {
520 cmd = _webserver->arg (
"plain");
522 cmd = _webserver->arg (
"commandText");
525 _webserver->send (200,
"text/plain",
"Invalid command");
530 int ESPpos = cmd.indexOf (
"[ESP");
533 int ESPpos2 = cmd.indexOf (
"]", ESPpos);
536 String cmd_part1 = cmd.substring (ESPpos + 4, ESPpos2);
537 String cmd_part2 =
"";
539 if ( (auth_level ==
LEVEL_GUEST) && (cmd_part1.toInt() != 800) ) {
540 _webserver->send (401,
"text/plain",
"Authentication failed!\n");
544 if (ESPpos2 < cmd.length() ) {
545 cmd_part2 = cmd.substring (ESPpos2 + 1);
548 if (cmd_part1.toInt() != 0) {
550 if(execute_internal_command (cmd_part1.toInt(), cmd_part2, auth_level, NULL)) _webserver->send (200,
"text/plain",
"ok");
551 else _webserver->send (200,
"text/plain",
"error");
557 _webserver->send (401,
"text/plain",
"Authentication failed!\n");
563 scmd = get_Splited_Value(cmd,
'\n', sindex);
570 scmd = get_Splited_Value(cmd,
'\n', sindex);
572 _webserver->send (200,
"text/plain", res.c_str());
579 bool response =
true;
589 if (!espresponse)
return false;
590 String resp =
"No SD card";
591 #if ENABLED(SDSUPPORT)
594 if (state == -1)resp=
"Busy";
595 else if (state == 1)resp=
"SD card detected";
596 else resp=
"No SD card";
598 espresponse->
println (resp.c_str());
608 if (!espresponse)
return false;
609 #ifdef ENABLE_AUTHENTICATION
613 espresponse->
print(
"{\"EEPROM\":[");
616 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
618 espresponse->
print (
"\",\"T\":\"S\",\"V\":\"");
619 espresponse->
print (_hostname.c_str());
620 espresponse->
print (
"\",\"H\":\"Hostname\" ,\"S\":\"");
622 espresponse->
print (
"\", \"M\":\"");
624 espresponse->
print (
"\"}");
625 espresponse->
print (
",");
628 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
630 espresponse->
print (
"\",\"T\":\"B\",\"V\":\"");
632 espresponse->
print (String(vi).c_str());
633 espresponse->
print (
"\",\"H\":\"HTTP protocol\",\"O\":[{\"Enabled\":\"1\"},{\"Disabled\":\"0\"}]}");
634 espresponse->
print (
",");
637 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
639 espresponse->
print (
"\",\"T\":\"I\",\"V\":\"");
640 espresponse->
print (String(_port).c_str());
641 espresponse->
print (
"\",\"H\":\"HTTP Port\",\"S\":\"");
643 espresponse->
print (
"\",\"M\":\"");
645 espresponse->
print (
"\"}");
646 espresponse->
print (
",");
671 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
673 espresponse->
print (
"\",\"T\":\"B\",\"V\":\"");
675 espresponse->
print (String(vi).c_str());
676 espresponse->
print (
"\",\"H\":\"Wifi mode\",\"O\":[{\"STA\":\"1\"},{\"AP\":\"2\"},{\"None\":\"0\"}]}");
677 espresponse->
print (
",");
680 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
682 espresponse->
print (
"\",\"T\":\"S\",\"V\":\"");
685 espresponse->
print (
"\",\"S\":\"");
687 espresponse->
print (
"\",\"H\":\"Station SSID\",\"M\":\"");
689 espresponse->
print (
"\"}");
690 espresponse->
print (
",");
693 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
695 espresponse->
print (
"\",\"T\":\"S\",\"V\":\"");
697 espresponse->
print (
"\",\"S\":\"");
699 espresponse->
print (
"\",\"H\":\"Station Password\",\"M\":\"");
701 espresponse->
print (
"\"}");
702 espresponse->
print (
",");
705 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
707 espresponse->
print (
"\",\"T\":\"B\",\"V\":\"");
709 espresponse->
print (
"\",\"H\":\"Station IP Mode\",\"O\":[{\"DHCP\":\"0\"},{\"Static\":\"1\"}]}");
710 espresponse->
print (
",");
713 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
715 espresponse->
print (
"\",\"T\":\"A\",\"V\":\"");
717 espresponse->
print (
"\",\"H\":\"Station Static IP\"}");
718 espresponse->
print (
",");
721 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
723 espresponse->
print (
"\",\"T\":\"A\",\"V\":\"");
725 espresponse->
print (
"\",\"H\":\"Station Static Gateway\"}");
726 espresponse->
print (
",");
729 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
731 espresponse->
print (
"\",\"T\":\"A\",\"V\":\"");
733 espresponse->
print (
"\",\"H\":\"Station Static Mask\"}");
734 espresponse->
print (
",");
737 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
739 espresponse->
print (
"\",\"T\":\"S\",\"V\":\"");
742 espresponse->
print (
"\",\"S\":\"");
744 espresponse->
print (
"\",\"H\":\"AP SSID\",\"M\":\"");
746 espresponse->
print (
"\"}");
747 espresponse->
print (
",");
750 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
752 espresponse->
print (
"\",\"T\":\"S\",\"V\":\"");
754 espresponse->
print (
"\",\"S\":\"");
756 espresponse->
print (
"\",\"H\":\"AP Password\",\"M\":\"");
758 espresponse->
print (
"\"}");
759 espresponse->
print (
",");
762 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
764 espresponse->
print (
"\",\"T\":\"A\",\"V\":\"");
767 espresponse->
print (
"\",\"H\":\"AP Static IP\"}");
768 espresponse->
print (
",");
771 espresponse->
print (
"{\"F\":\"network\",\"P\":\"");
773 espresponse->
print (
"\",\"T\":\"B\",\"V\":\"");
775 espresponse->
print (
"\",\"H\":\"AP Channel\",\"O\":[");
777 espresponse->
print (
"{\"");
778 espresponse->
print (String(i).c_str());
779 espresponse->
print (
"\":\"");
780 espresponse->
print (String(i).c_str());
781 espresponse->
print (
"\"}");
783 espresponse->
print (
",");
786 espresponse->
print (
"]}");
788 espresponse->
print (
"]}");
796 #ifdef ENABLE_AUTHENTICATION
800 String spos = get_param (cmd_params,
"P=",
false);
801 String styp = get_param (cmd_params,
"T=",
false);
802 String sval = get_param (cmd_params,
"V=",
true);
805 if (spos.length() == 0) {
808 if (! (styp ==
"B" || styp ==
"S" || styp ==
"A" || styp ==
"I" || styp ==
"F") ) {
819 if ((styp ==
"B") || (styp ==
"F")){
820 int8_t bbuf = sval.toInt();
821 if (prefs.putChar(spos.c_str(), bbuf) ==0 ) {
841 int16_t ibuf = sval.toInt();
842 if (prefs.putUShort(spos.c_str(), ibuf) == 0) {
857 if (prefs.putString(spos.c_str(), sval) == 0) {
900 if (espresponse) espresponse->
println (
"Error: Incorrect Command");
902 if (espresponse) espresponse->
println (
"ok");
911 if (!espresponse)
return false;
912 #ifdef ENABLE_AUTHENTICATION
915 espresponse->
print(
"{\"AP_LIST\":[");
916 int n = WiFi.scanNetworks();
918 for (
int i = 0; i < n; ++i) {
920 espresponse->
print (
",");
922 espresponse->
print (
"{\"SSID\":\"");
923 espresponse->
print (WiFi.SSID (i).c_str());
924 espresponse->
print (
"\",\"SIGNAL\":\"");
926 espresponse->
print (
"\",\"IS_PROTECTED\":\"");
928 if (WiFi.encryptionType (i) == WIFI_AUTH_OPEN) {
929 espresponse->
print (
"0");
931 espresponse->
print (
"1");
933 espresponse->
print (
"\"}");
938 espresponse->
print (
"]}");
940 if (WiFi.getMode() == WIFI_AP_STA) {
941 WiFi.enableSTA (
false);
948 #ifdef ENABLE_AUTHENTICATION
951 if (!espresponse)
return false;
952 espresponse->
print (
"Chip ID: ");
953 espresponse->
print (String ( (uint16_t) (ESP.getEfuseMac() >> 32) ).c_str());
954 espresponse->
print (
"\n");
955 espresponse->
print (
"CPU Frequency: ");
956 espresponse->
print (String (ESP.getCpuFreqMHz() ).c_str());
957 espresponse->
print (
"Mhz");
958 espresponse->
print (
"\n");
959 espresponse->
print (
"CPU Temperature: ");
960 espresponse->
print (String (temperatureRead(), 1).c_str());
961 espresponse->
print (
"°C");
962 espresponse->
print (
"\n");
963 espresponse->
print (
"Free memory: ");
964 espresponse->
print (formatBytes (ESP.getFreeHeap()).c_str());
965 espresponse->
print (
"\n");
966 espresponse->
print (
"SDK: ");
967 espresponse->
print (ESP.getSdkVersion());
968 espresponse->
print (
"\n");
969 espresponse->
print (
"Flash Size: ");
970 espresponse->
print (formatBytes (ESP.getFlashChipSize()).c_str());
971 espresponse->
print (
"\n");
972 espresponse->
print (
"Available Size for update: ");
974 if (ESP.getFlashChipSize() > 0x20000) {
975 espresponse->
print (formatBytes (0x140000).c_str());
977 espresponse->
print (formatBytes (0x0).c_str());
979 espresponse->
print (
"\n");
980 espresponse->
print (
"Available Size for SPIFFS: ");
981 espresponse->
print (formatBytes (SPIFFS.totalBytes()).c_str());
982 espresponse->
print (
"\n");
983 espresponse->
print (
"Baud rate: ");
984 long br = Serial.baudRate();
992 espresponse->
print (String(br).c_str());
993 espresponse->
print (
"\n");
994 espresponse->
print (
"Sleep mode: ");
995 if (WiFi.getSleep())espresponse->
print (
"Modem");
996 else espresponse->
print (
"None");
997 espresponse->
print (
"\n");
998 espresponse->
print (
"Web port: ");
999 espresponse->
print (String(_port).c_str());
1000 espresponse->
print (
"\n");
1001 espresponse->
print (
"Data port: ");
1002 if (_data_port!=0)espresponse->
print (String(_data_port).c_str());
1003 else espresponse->
print (
"Disabled");
1004 espresponse->
print (
"\n");
1005 espresponse->
print (
"Hostname: ");
1006 espresponse->
print ( _hostname.c_str());
1007 espresponse->
print (
"\n");
1008 espresponse->
print (
"Active Mode: ");
1009 if (WiFi.getMode() == WIFI_STA) {
1010 espresponse->
print (
"STA (");
1011 espresponse->
print ( WiFi.macAddress().c_str());
1012 espresponse->
print (
")");
1013 espresponse->
print (
"\n");
1014 espresponse->
print (
"Connected to: ");
1015 if (WiFi.isConnected()){
1016 espresponse->
print (WiFi.SSID().c_str());
1017 espresponse->
print (
"\n");
1018 espresponse->
print (
"Signal: ");
1020 espresponse->
print (
"%");
1021 espresponse->
print (
"\n");
1023 esp_wifi_get_protocol (ESP_IF_WIFI_STA, &PhyMode);
1024 espresponse->
print (
"Phy Mode: ");
1025 if (PhyMode == (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)) espresponse->
print (
"11n");
1026 else if (PhyMode == (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G)) espresponse->
print (
"11g");
1027 else if (PhyMode == (WIFI_PROTOCOL_11B )) espresponse->
print (
"11b");
1028 else espresponse->
print (
"???");
1029 espresponse->
print (
"\n");
1030 espresponse->
print (
"Channel: ");
1031 espresponse->
print (String (WiFi.channel()).c_str());
1032 espresponse->
print (
"\n");
1033 espresponse->
print (
"IP Mode: ");
1034 tcpip_adapter_dhcp_status_t dhcp_status;
1035 tcpip_adapter_dhcpc_get_status (TCPIP_ADAPTER_IF_STA, &dhcp_status);
1036 if (dhcp_status == TCPIP_ADAPTER_DHCP_STARTED)espresponse->
print (
"DHCP");
1037 else espresponse->
print (
"Static");
1038 espresponse->
print (
"\n");
1039 espresponse->
print (
"IP: ");
1040 espresponse->
print (WiFi.localIP().toString().c_str());
1041 espresponse->
print (
"\n");
1042 espresponse->
print (
"Gateway: ");
1043 espresponse->
print (WiFi.gatewayIP().toString().c_str());
1044 espresponse->
print (
"\n");
1045 espresponse->
print (
"Mask: ");
1046 espresponse->
print (WiFi.subnetMask().toString().c_str());
1047 espresponse->
print (
"\n");
1048 espresponse->
print (
"DNS: ");
1049 espresponse->
print (WiFi.dnsIP().toString().c_str());
1050 espresponse->
print (
"\n");
1052 espresponse->
print (
"Disabled Mode: ");
1053 espresponse->
print (
"AP (");
1054 espresponse->
print (WiFi.softAPmacAddress().c_str());
1055 espresponse->
print (
")");
1056 espresponse->
print (
"\n");
1057 }
else if (WiFi.getMode() == WIFI_AP) {
1058 espresponse->
print (
"AP (");
1059 espresponse->
print (WiFi.softAPmacAddress().c_str());
1060 espresponse->
print (
")");
1061 espresponse->
print (
"\n");
1063 esp_wifi_get_config (ESP_IF_WIFI_AP, &conf);
1064 espresponse->
print (
"SSID: ");
1065 espresponse->
print ((
const char*) conf.ap.ssid);
1066 espresponse->
print (
"\n");
1067 espresponse->
print (
"Visible: ");
1068 espresponse->
print ( (conf.ap.ssid_hidden == 0) ?
"Yes" :
"No");
1069 espresponse->
print (
"\n");
1070 espresponse->
print (
"Authentication: ");
1071 if (conf.ap.authmode == WIFI_AUTH_OPEN) {
1072 espresponse->
print (
"None");
1073 }
else if (conf.ap.authmode == WIFI_AUTH_WEP) {
1074 espresponse->
print (
"WEP");
1075 }
else if (conf.ap.authmode == WIFI_AUTH_WPA_PSK) {
1076 espresponse->
print (
"WPA");
1077 }
else if (conf.ap.authmode == WIFI_AUTH_WPA2_PSK) {
1078 espresponse->
print (
"WPA2");
1080 espresponse->
print (
"WPA/WPA2");
1082 espresponse->
print (
"\n");
1083 espresponse->
print (
"Max Connections: ");
1084 espresponse->
print (String(conf.ap.max_connection).c_str());
1085 espresponse->
print (
"\n");
1086 espresponse->
print (
"DHCP Server: ");
1087 tcpip_adapter_dhcp_status_t dhcp_status;
1088 tcpip_adapter_dhcps_get_status (TCPIP_ADAPTER_IF_AP, &dhcp_status);
1089 if (dhcp_status == TCPIP_ADAPTER_DHCP_STARTED)espresponse->
print (
"Started");
1090 else espresponse->
print (
"Stopped");
1091 espresponse->
print (
"\n");
1092 espresponse->
print (
"IP: ");
1093 espresponse->
print (WiFi.softAPIP().toString().c_str());
1094 espresponse->
print (
"\n");
1095 tcpip_adapter_ip_info_t ip_AP;
1096 tcpip_adapter_get_ip_info (TCPIP_ADAPTER_IF_AP, &ip_AP);
1097 espresponse->
print (
"Gateway: ");
1098 espresponse->
print (IPAddress (ip_AP.gw.addr).toString().c_str());
1099 espresponse->
print (
"\n");
1100 espresponse->
print (
"Mask: ");
1101 espresponse->
print (IPAddress (ip_AP.netmask.addr).toString().c_str());
1102 espresponse->
print (
"\n");
1103 espresponse->
print (
"Connected clients: ");
1104 wifi_sta_list_t station;
1105 tcpip_adapter_sta_list_t tcpip_sta_list;
1106 esp_wifi_ap_get_sta_list (&station);
1107 tcpip_adapter_get_sta_list (&station, &tcpip_sta_list);
1108 espresponse->
print (String(station.num).c_str());
1109 espresponse->
print (
"\n");
1110 for (
int i = 0; i < station.num; i++) {
1111 espresponse->
print (mac2str(tcpip_sta_list.sta[i].mac));
1112 espresponse->
print (
" ");
1113 espresponse->
print ( IPAddress (tcpip_sta_list.sta[i].ip.addr).toString().c_str());
1114 espresponse->
print (
"\n");
1116 espresponse->
print (
"Disabled Mode: ");
1117 espresponse->
print (
"STA (");
1118 espresponse->
print (WiFi.macAddress().c_str());
1119 espresponse->
print (
")");
1120 espresponse->
print (
"\n");
1121 }
else if (WiFi.getMode() == WIFI_AP_STA)
1123 espresponse->
print (
"Mixed");
1124 espresponse->
print (
"\n");
1125 espresponse->
print (
"STA (");
1126 espresponse->
print (WiFi.macAddress().c_str());
1127 espresponse->
print (
")");
1128 espresponse->
print (
"\n");
1129 espresponse->
print (
"AP (");
1130 espresponse->
print (WiFi.softAPmacAddress().c_str());
1131 espresponse->
print (
")");
1132 espresponse->
print (
"\n");
1135 espresponse->
print (
"Wifi Off");
1136 espresponse->
print (
"\n");
1139 espresponse->
print (
"FW version: Marlin ");
1140 espresponse->
print (SHORT_BUILD_VERSION);
1141 espresponse->
print (
" (ESP32)");
1148 parameter = get_param(cmd_params,
"",
true);
1149 #ifdef ENABLE_AUTHENTICATION
1155 if (parameter==
"RESTART") {
1158 MYSERIAL1.println(
"Restart ongoing");
1161 }
else response =
false;
1164 if (espresponse)espresponse->
println (
"Error: Incorrect Command");
1166 if (espresponse)espresponse->
println (
"ok");
1169 #ifdef ENABLE_AUTHENTICATION
1174 parameter = get_param (cmd_params,
"",
true);
1175 if (parameter.length() == 0) {
1177 parameter = DEFAULT_USER_PWD;
1179 if (prefs.putString(USER_PWD_ENTRY, parameter) != parameter.length()){
1181 espresponse->
println (
"error");
1182 }
else espresponse->
println (
"ok");
1186 if (isLocalPasswordValid (parameter.c_str() ) ) {
1189 if (prefs.putString(USER_PWD_ENTRY, parameter) != parameter.length()) {
1191 espresponse->
println (
"error");
1192 }
else espresponse->
println (
"ok");
1195 espresponse->
println (
"error");
1200 espresponse->
println (
"error");
1208 #ifdef ENABLE_AUTHENTICATION
1212 if ( (cmd_params.length() > 0) && (cmd_params[0] !=
'/') ) {
1213 cmd_params =
"/" + cmd_params;
1215 File currentfile = SPIFFS.open (cmd_params, FILE_READ);
1218 while (currentfile.available()) {
1219 String currentline = currentfile.readStringUntil(
'\n');
1220 currentline.replace(
"\n",
"");
1221 currentline.replace(
"\r",
"");
1222 if (currentline.length() > 0) {
1223 int ESPpos = currentline.indexOf (
"[ESP");
1226 int ESPpos2 = currentline.indexOf (
"]", ESPpos);
1229 String cmd_part1 = currentline.substring (ESPpos + 4, ESPpos2);
1230 String cmd_part2 =
"";
1232 if (ESPpos2 < currentline.length() ) {
1233 cmd_part2 = currentline.substring (ESPpos2 + 1);
1236 if(cmd_part1.toInt()!=0) {
1237 if (!execute_internal_command(cmd_part1.toInt(),cmd_part2, auth_type, espresponse)) response =
false;
1242 if (currentline.length() > 0){
1252 currentfile.close();
1253 if (espresponse)espresponse->
println (
"ok");
1255 if (espresponse)espresponse->
println (
"error");
1263 #ifdef ENABLE_AUTHENTICATION
1266 parameter = get_param (cmd_params,
"",
true);
1267 #ifdef ENABLE_AUTHENTICATION
1269 espresponse->
println (
"error");
1275 if (parameter ==
"FORMAT") {
1276 if (espresponse)espresponse->
print (
"Formating");
1278 if (espresponse)espresponse->
println (
"...Done");
1280 if (espresponse)espresponse->
println (
"error");
1289 if (!espresponse)
return false;
1291 resp =
"FW version:";
1292 resp += SHORT_BUILD_VERSION;
1293 resp +=
" # FW target:marlin-embedded # FW HW:";
1294 #if ENABLED(SDSUPPORT)
1295 resp +=
"Direct SD";
1299 resp +=
" # primary sd:/sd # secondary sd:none # authentication:";
1300 #ifdef ENABLE_AUTHENTICATION
1305 resp +=
" # webcommunication: Sync: ";
1306 resp += String(_port + 1);
1307 resp +=
"# hostname:";
1309 if (WiFi.getMode() == WIFI_AP)resp +=
"(AP mode)";
1310 if (espresponse)espresponse->
println (resp.c_str());
1314 if (espresponse)espresponse->
println (
"Error: Incorrect Command");
1322 void Web_Server::handle_login()
1324 #ifdef ENABLE_AUTHENTICATION
1326 String sUser,sPassword;
1329 bool msg_alert_error=
false;
1331 if (_webserver->hasArg(
"DISCONNECT")) {
1332 String cookie = _webserver->header(
"Cookie");
1333 int pos = cookie.indexOf(
"ESPSESSIONID=");
1336 int pos2 = cookie.indexOf(
";",pos);
1337 sessionID = cookie.substring(pos+strlen(
"ESPSESSIONID="),pos2);
1339 ClearAuthIP(_webserver->client().remoteIP(), sessionID.c_str());
1340 _webserver->sendHeader(
"Set-Cookie",
"ESPSESSIONID=0");
1341 _webserver->sendHeader(
"Cache-Control",
"no-cache");
1342 String buffer2send =
"{\"status\":\"Ok\",\"authentication_lvl\":\"guest\"}";
1343 _webserver->send(code,
"application/json", buffer2send);
1350 else if (auth_level ==
LEVEL_USER) auths =
"user";
1351 else if (auth_level ==
LEVEL_ADMIN) auths =
"admin";
1355 if (_webserver->hasArg(
"SUBMIT")) {
1357 if ( _webserver->hasArg(
"PASSWORD") && _webserver->hasArg(
"USER")) {
1359 sUser = _webserver->arg(
"USER");
1360 if ( !((sUser == DEFAULT_ADMIN_LOGIN) || (sUser == DEFAULT_USER_LOGIN))) {
1361 msg_alert_error=
true;
1362 smsg =
"Error : Incorrect User";
1365 if (msg_alert_error ==
false) {
1367 sPassword = _webserver->arg(
"PASSWORD");
1368 String sadminPassword;
1372 String defV = DEFAULT_ADMIN_PWD;
1373 sadminPassword = prefs.getString(ADMIN_PWD_ENTRY, defV);
1374 String suserPassword;
1375 defV = DEFAULT_USER_PWD;
1376 suserPassword = prefs.getString(USER_PWD_ENTRY, defV);
1379 if(!(((sUser == DEFAULT_ADMIN_LOGIN) && (strcmp(sPassword.c_str(),sadminPassword.c_str()) == 0)) ||
1380 ((sUser == DEFAULT_USER_LOGIN) && (strcmp(sPassword.c_str(),suserPassword.c_str()) == 0)))) {
1381 msg_alert_error=
true;
1382 smsg =
"Error: Incorrect password";
1387 msg_alert_error=
true;
1388 smsg =
"Error: Missing data";
1392 if (_webserver->hasArg(
"PASSWORD") && _webserver->hasArg(
"USER") && _webserver->hasArg(
"NEWPASSWORD") && (msg_alert_error==
false) ) {
1393 String newpassword = _webserver->arg(
"NEWPASSWORD");
1394 if (isLocalPasswordValid(newpassword.c_str())) {
1396 if(sUser == DEFAULT_ADMIN_LOGIN) spos = ADMIN_PWD_ENTRY;
1397 else spos = USER_PWD_ENTRY;
1401 if (prefs.putString(spos.c_str(), newpassword) != newpassword.length()) {
1402 msg_alert_error =
true;
1403 smsg =
"Error: Cannot apply changes";
1408 msg_alert_error=
true;
1409 smsg =
"Error: Incorrect password";
1413 if ((code == 200) || (code == 500)) {
1415 if(sUser == DEFAULT_ADMIN_LOGIN) {
1417 }
else if(sUser == DEFAULT_USER_LOGIN){
1423 if ((current_auth_level != auth_level) || (auth_level==
LEVEL_GUEST)) {
1424 auth_ip * current_auth =
new auth_ip;
1425 current_auth->level = current_auth_level;
1426 current_auth->ip=_webserver->client().remoteIP();
1427 strcpy(current_auth->sessionID,create_session_ID());
1428 strcpy(current_auth->userID,sUser.c_str());
1429 current_auth->last_time=millis();
1430 if (AddAuthIP(current_auth)) {
1431 String tmps =
"ESPSESSIONID=";
1432 tmps+=current_auth->sessionID;
1433 _webserver->sendHeader(
"Set-Cookie",tmps);
1434 _webserver->sendHeader(
"Cache-Control",
"no-cache");
1435 switch(current_auth->level) {
1447 delete current_auth;
1448 msg_alert_error=
true;
1450 smsg =
"Error: Too many connections";
1454 if (code == 200) smsg =
"Ok";
1457 String buffer2send =
"{\"status\":\"" + smsg +
"\",\"authentication_lvl\":\"";
1458 buffer2send += auths;
1459 buffer2send +=
"\"}";
1460 _webserver->send(code,
"application/json", buffer2send);
1463 String cookie = _webserver->header(
"Cookie");
1464 int pos = cookie.indexOf(
"ESPSESSIONID=");
1467 int pos2 = cookie.indexOf(
";",pos);
1468 sessionID = cookie.substring(pos+strlen(
"ESPSESSIONID="),pos2);
1469 auth_ip * current_auth_info = GetAuth(_webserver->client().remoteIP(), sessionID.c_str());
1470 if (current_auth_info != NULL){
1471 sUser = current_auth_info->userID;
1475 String buffer2send =
"{\"status\":\"200\",\"authentication_lvl\":\"";
1476 buffer2send += auths;
1477 buffer2send +=
"\",\"user\":\"";
1478 buffer2send += sUser;
1479 buffer2send +=
"\"}";
1480 _webserver->send(code,
"application/json", buffer2send);
1483 _webserver->sendHeader(
"Cache-Control",
"no-cache");
1484 _webserver->send(200,
"application/json",
"{\"status\":\"Ok\",\"authentication_lvl\":\"admin\"}");
1489 void Web_Server::handleFileList ()
1493 _upload_status = UPLOAD_STATUS_NONE;
1494 _webserver->send (401,
"text/plain",
"Authentication failed!\n");
1498 String status =
"Ok";
1499 if ( (_upload_status == UPLOAD_STATUS_FAILED) || (_upload_status == UPLOAD_STATUS_CANCELLED) ) {
1500 status =
"Upload failed";
1509 if (_webserver->hasArg (
"path") ) {
1510 path += _webserver->arg (
"path") ;
1514 path.replace (
"//",
"/");
1515 if (path[path.length() - 1] !=
'/') {
1519 if (_webserver->hasArg (
"action") ) {
1521 if (_webserver->arg (
"action") ==
"delete" && _webserver->hasArg (
"filename") ) {
1523 String shortname = _webserver->arg (
"filename");
1524 shortname.replace (
"/",
"");
1525 filename = path + _webserver->arg (
"filename");
1526 filename.replace (
"//",
"/");
1527 if (!SPIFFS.exists (filename) ) {
1528 status = shortname +
" does not exists!";
1530 if (SPIFFS.remove (filename) ) {
1531 status = shortname +
" deleted";
1534 if ( (path !=
"/") && (path[path.length() - 1] =
'/') ) {
1535 ptmp = path.substring (0, path.length() - 1);
1537 File dir = SPIFFS.open (ptmp);
1538 File dircontent = dir.openNextFile();
1541 File r = SPIFFS.open (path +
"/.", FILE_WRITE);
1547 status =
"Cannot deleted " ;
1548 status += shortname ;
1553 if (_webserver->arg (
"action") ==
"deletedir" && _webserver->hasArg (
"filename") ) {
1555 String shortname = _webserver->arg (
"filename");
1556 shortname.replace (
"/",
"");
1557 filename = path + _webserver->arg (
"filename");
1559 filename.replace (
"//",
"/");
1560 if (filename !=
"/") {
1561 bool delete_error =
false;
1562 File dir = SPIFFS.open (path + shortname);
1564 File file2deleted = dir.openNextFile();
1565 while (file2deleted) {
1566 String fullpath = file2deleted.name();
1567 if (!SPIFFS.remove (fullpath) ) {
1568 delete_error =
true;
1569 status =
"Cannot deleted " ;
1572 file2deleted = dir.openNextFile();
1575 if (!delete_error) {
1576 status = shortname ;
1577 status +=
" deleted";
1582 if (_webserver->arg (
"action") ==
"createdir" && _webserver->hasArg (
"filename") ) {
1584 filename = path + _webserver->arg (
"filename") +
"/.";
1585 String shortname = _webserver->arg (
"filename");
1586 shortname.replace (
"/",
"");
1587 filename.replace (
"//",
"/");
1588 if (SPIFFS.exists (filename) ) {
1589 status = shortname +
" already exists!";
1591 File r = SPIFFS.open (filename, FILE_WRITE);
1593 status =
"Cannot create ";
1594 status += shortname ;
1597 status = shortname +
" created";
1602 String jsonfile =
"{";
1604 if ( (path !=
"/") && (path[path.length() - 1] =
'/') ) {
1605 ptmp = path.substring (0, path.length() - 1);
1607 File dir = SPIFFS.open (ptmp);
1608 jsonfile +=
"\"files\":[";
1609 bool firstentry =
true;
1610 String subdirlist =
"";
1611 File fileparsed = dir.openNextFile();
1612 while (fileparsed) {
1613 String filename = fileparsed.name();
1615 bool addtolist =
true;
1617 filename = filename.substring (path.length(), filename.length() );
1619 if (filename.indexOf (
"/") > -1) {
1623 filename = filename.substring (0, filename.indexOf (
"/") );
1625 tag += filename +
"*";
1626 if (subdirlist.indexOf (tag) > -1 || filename.length() == 0) {
1630 if (subdirlist.length() == 0) {
1633 subdirlist += filename +
"*";
1637 if (! ( (filename ==
".") || (filename ==
"") ) ) {
1638 size = formatBytes (fileparsed.size() );
1650 jsonfile +=
"\"name\":\"";
1651 jsonfile += filename;
1652 jsonfile +=
"\",\"size\":\"";
1657 fileparsed = dir.openNextFile();
1660 jsonfile +=
"\"path\":\"" + path +
"\",";
1661 jsonfile +=
"\"status\":\"" + status +
"\",";
1664 totalBytes = SPIFFS.totalBytes();
1665 usedBytes = SPIFFS.usedBytes();
1666 jsonfile +=
"\"total\":\"" + formatBytes (totalBytes) +
"\",";
1667 jsonfile +=
"\"used\":\"" + formatBytes (usedBytes) +
"\",";
1668 jsonfile.concat (F (
"\"occupation\":\"") );
1669 jsonfile += String (100 * usedBytes / totalBytes);
1673 _webserver->sendHeader(
"Cache-Control",
"no-cache");
1674 _webserver->send(200,
"application/json", jsonfile);
1675 _upload_status = UPLOAD_STATUS_NONE;
1679 void Web_Server::SPIFFSFileupload ()
1685 _upload_status = UPLOAD_STATUS_CANCELLED;
1688 MYSERIAL1.println(
"Upload rejected");
1690 _webserver->client().stop();
1693 static String filename;
1694 static File fsUploadFile = (File)0;
1696 HTTPUpload& upload = _webserver->upload();
1699 if(upload.status == UPLOAD_FILE_START) {
1700 String upload_filename = upload.filename;
1701 if (upload_filename[0] !=
'/') filename =
"/" + upload_filename;
1702 else filename = upload.filename;
1705 upload_filename = filename;
1706 filename =
"/user" + upload_filename;
1709 if (SPIFFS.exists (filename) ) {
1710 SPIFFS.remove (filename);
1712 if (fsUploadFile ) {
1713 fsUploadFile.close();
1716 fsUploadFile = SPIFFS.open(filename, FILE_WRITE);
1720 _upload_status= UPLOAD_STATUS_ONGOING;
1723 _upload_status=UPLOAD_STATUS_CANCELLED;
1726 MYSERIAL1.println(
"Upload error");
1728 _webserver->client().stop();
1732 }
else if(upload.status == UPLOAD_FILE_WRITE) {
1734 if(fsUploadFile && _upload_status == UPLOAD_STATUS_ONGOING) {
1736 fsUploadFile.write(upload.buf, upload.currentSize);
1739 _upload_status=UPLOAD_STATUS_CANCELLED;
1740 fsUploadFile.close();
1741 if (SPIFFS.exists (filename) ) {
1742 SPIFFS.remove (filename);
1744 _webserver->client().stop();
1747 MYSERIAL1.println(
"Upload error");
1752 }
else if(upload.status == UPLOAD_FILE_END) {
1756 fsUploadFile.close();
1758 String sizeargname = upload.filename +
"S";
1759 fsUploadFile = SPIFFS.open (filename, FILE_READ);
1760 uint32_t filesize = fsUploadFile.size();
1761 fsUploadFile.close();
1762 if (_webserver->hasArg (sizeargname.c_str()) ) {
1763 if (_webserver->arg (sizeargname.c_str()) != String(filesize)) {
1764 _upload_status = UPLOAD_STATUS_FAILED;
1765 SPIFFS.remove (filename);
1768 if (_upload_status == UPLOAD_STATUS_ONGOING) {
1769 _upload_status = UPLOAD_STATUS_SUCCESSFUL;
1773 MYSERIAL1.println(
"Upload error");
1778 _upload_status=UPLOAD_STATUS_CANCELLED;
1779 _webserver->client().stop();
1780 if (SPIFFS.exists (filename) ) {
1781 SPIFFS.remove (filename);
1785 MYSERIAL1.println(
"Upload error");
1791 if (_upload_status == UPLOAD_STATUS_ONGOING) {
1792 _upload_status = UPLOAD_STATUS_CANCELLED;
1794 if(fsUploadFile)fsUploadFile.close();
1795 if (SPIFFS.exists (filename) ) {
1796 SPIFFS.remove (filename);
1800 MYSERIAL1.println(
"Upload error");
1807 void Web_Server::handleUpdate ()
1811 _upload_status = UPLOAD_STATUS_NONE;
1812 _webserver->send (403,
"text/plain",
"Not allowed, log in first!\n");
1815 String jsonfile =
"{\"status\":\"" ;
1816 jsonfile += String(_upload_status);
1819 _webserver->sendHeader(
"Cache-Control",
"no-cache");
1820 _webserver->send(200,
"application/json", jsonfile);
1822 if (_upload_status == UPLOAD_STATUS_SUCCESSFUL) {
1826 _upload_status = UPLOAD_STATUS_NONE;
1831 void Web_Server::WebUpdateUpload ()
1833 static size_t last_upload_update;
1834 static uint32_t maxSketchSpace ;
1837 _upload_status = UPLOAD_STATUS_CANCELLED;
1838 _webserver->client().stop();
1841 MYSERIAL1.println(
"Upload rejected");
1847 HTTPUpload& upload = _webserver->upload();
1850 if(upload.status == UPLOAD_FILE_START) {
1853 MYSERIAL1.println(
"Update Firmware");
1855 _upload_status= UPLOAD_STATUS_ONGOING;
1858 maxSketchSpace = (ESP.getFlashChipSize() > 0x20000) ? 0x140000 : 0x140000 / 2;
1859 last_upload_update = 0;
1860 if(!Update.begin(maxSketchSpace)) {
1861 _upload_status=UPLOAD_STATUS_CANCELLED;
1864 MYSERIAL1.println(
"Update cancelled");
1866 _webserver->client().stop();
1871 MYSERIAL1.println(
"Update 0%");
1876 }
else if(upload.status == UPLOAD_FILE_WRITE) {
1878 if (_upload_status == UPLOAD_STATUS_ONGOING) {
1880 if ( ((100 * upload.totalSize) / maxSketchSpace) !=last_upload_update) {
1881 last_upload_update = (100 * upload.totalSize) / maxSketchSpace;
1882 String s =
"Update ";
1883 s+= String(last_upload_update);
1887 MYSERIAL1.println(s.c_str());
1890 if(Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
1891 _upload_status=UPLOAD_STATUS_CANCELLED;
1896 }
else if(upload.status == UPLOAD_FILE_END) {
1897 if(Update.end(
true)) {
1901 MYSERIAL1.println(
"Update 100%");
1903 _upload_status=UPLOAD_STATUS_SUCCESSFUL;
1905 }
else if(upload.status == UPLOAD_FILE_ABORTED) {
1908 MYSERIAL1.println(
"Update failed");
1911 _upload_status=UPLOAD_STATUS_CANCELLED;
1917 #if ENABLED(SDSUPPORT)
1920 void Web_Server::handle_direct_SDFileList()
1924 _upload_status=UPLOAD_STATUS_NONE;
1925 _webserver->send(401,
"application/json",
"{\"status\":\"Authentication failed!\"}");
1931 String sstatus=
"Ok";
1932 if ((_upload_status == UPLOAD_STATUS_FAILED) || (_upload_status == UPLOAD_STATUS_CANCELLED)) {
1933 sstatus =
"Upload failed";
1934 _upload_status = UPLOAD_STATUS_NONE;
1936 bool list_files =
true;
1940 _webserver->sendHeader(
"Cache-Control",
"no-cache");
1941 _webserver->send(200,
"application/json",
"{\"status\":\"No SD Card\"}");
1946 if(_webserver->hasArg(
"path")) {
1947 path += _webserver->arg(
"path") ;
1951 path.replace(
"//",
"/");
1954 if(_webserver->hasArg(
"action")) {
1956 if(_webserver->arg(
"action") ==
"delete" && _webserver->hasArg(
"filename")) {
1958 String shortname = _webserver->arg(
"filename");
1959 filename = path + shortname;
1960 shortname.replace(
"/",
"");
1961 filename.replace(
"//",
"/");
1963 if(!card.
exists(filename.c_str())) {
1964 sstatus = shortname +
" does not exist!";
1966 if (card.
remove(filename.c_str())) {
1967 sstatus = shortname +
" deleted";
1969 sstatus =
"Cannot deleted ";
1970 sstatus+=shortname ;
1975 if( _webserver->arg(
"action") ==
"deletedir" && _webserver->hasArg(
"filename")) {
1977 String shortname = _webserver->arg(
"filename");
1978 shortname.replace(
"/",
"");
1979 filename = path +
"/" + shortname;
1980 filename.replace(
"//",
"/");
1981 if (filename !=
"/") {
1983 sstatus = shortname +
" does not exist!";
1985 if (!card.
rmdir(filename.c_str())) {
1986 sstatus =
"Error deleting: ";
1987 sstatus += shortname ;
1989 sstatus = shortname ;
1990 sstatus+=
" deleted";
1994 sstatus =
"Cannot delete root";
1998 if( _webserver->arg(
"action")==
"createdir" && _webserver->hasArg(
"filename")) {
2000 String shortname = _webserver->arg(
"filename");
2001 filename = path + shortname;
2002 shortname.replace(
"/",
"");
2003 filename.replace(
"//",
"/");
2004 if(card.
exists(filename.c_str())) {
2005 sstatus = shortname +
" already exists!";
2007 if (!card.
mkdir(filename.c_str())) {
2008 sstatus =
"Cannot create ";
2009 sstatus += shortname ;
2011 sstatus = shortname +
" created";
2018 if( _webserver->hasArg(
"dontlist")) {
2019 if( _webserver->arg(
"dontlist") ==
"yes") {
2023 String jsonfile =
"{" ;
2024 jsonfile+=
"\"files\":[";
2026 String s =
"{\"status\":\" ";
2028 s+=
" does not exist on SD Card\"}";
2029 _webserver->sendHeader(
"Cache-Control",
"no-cache");
2030 _webserver->send(200,
"application/json", s.c_str());
2038 while (card.
readDir(name,&size ,&isFile)) {
2042 jsonfile+=
"{\"name\":\"";
2044 jsonfile+=
"\",\"shortname\":\"";
2046 jsonfile+=
"\",\"size\":\"";
2047 if (isFile)jsonfile+=formatBytes(size);
2048 else jsonfile+=
"-1";
2049 jsonfile+=
"\",\"datetime\":\"";
2055 jsonfile+=
"],\"path\":\"";
2056 jsonfile+=path +
"\",";
2062 uint32_t occupedspace = (volUsed/volTotal)*100;
2063 jsonfile+=
"\"total\":\"";
2064 if ( (occupedspace <= 1) && (volTotal!=volUsed)) {
2067 jsonfile+= formatBytes(volTotal); ;
2069 jsonfile+=
"\",\"used\":\"";
2070 jsonfile+= formatBytes(volUsed); ;
2071 jsonfile+=
"\",\"occupation\":\"";
2072 jsonfile+=String(occupedspace);
2075 jsonfile+=
"\"mode\":\"direct\",";
2076 jsonfile+=
"\"status\":\"";
2077 jsonfile+=sstatus +
"\"";
2080 _webserver->sendHeader(
"Cache-Control",
"no-cache");
2081 _webserver->send (200,
"application/json", jsonfile.c_str());
2082 _upload_status=UPLOAD_STATUS_NONE;
2086 void Web_Server::SDFile_direct_upload()
2089 static String upload_filename;
2092 _upload_status=UPLOAD_STATUS_NONE;
2093 _webserver->send(401,
"application/json",
"{\"status\":\"Authentication failed!\"}");
2097 HTTPUpload& upload = _webserver->upload();
2101 if(upload.status == UPLOAD_FILE_START) {
2102 upload_filename = upload.filename;
2103 if (upload_filename[0] !=
'/') {
2104 upload_filename =
"/" + upload.filename;
2106 upload_filename= sdfile.
makepath83(upload_filename);
2108 _upload_status=UPLOAD_STATUS_CANCELLED;
2111 MYSERIAL1.println(
"Upload cancelled");
2113 _webserver->client().stop();
2116 if (sdfile.
exists (upload_filename.c_str()) ) {
2117 sdfile.
remove (upload_filename.c_str());
2121 if (!sdfile.
open (upload_filename.c_str(),
false)) {
2124 MYSERIAL1.println(
"Upload cancelled");
2126 _webserver->client().stop();
2127 _upload_status = UPLOAD_STATUS_FAILED;
2130 _upload_status = UPLOAD_STATUS_ONGOING;
2134 }
else if(upload.status == UPLOAD_FILE_WRITE) {
2140 MYSERIAL1.println(
"Upload failed");
2142 if (sdfile.
exists (upload_filename.c_str()) ) {
2143 sdfile.
remove (upload_filename.c_str());
2145 _webserver->client().stop();
2149 if ( (_upload_status = UPLOAD_STATUS_ONGOING) && (upload.currentSize > 0)) {
2150 sdfile.
write (upload.buf, upload.currentSize);
2155 }
else if(upload.status == UPLOAD_FILE_END) {
2157 uint32_t filesize = sdfile.
size();
2158 String sizeargname = upload.filename +
"S";
2159 if (_webserver->hasArg (sizeargname.c_str()) ) {
2160 if (_webserver->arg (sizeargname.c_str()) != String(filesize)) {
2163 MYSERIAL1.println(
"Upload failed");
2165 _upload_status = UPLOAD_STATUS_FAILED;
2168 if (_upload_status == UPLOAD_STATUS_ONGOING) {
2169 _upload_status = UPLOAD_STATUS_SUCCESSFUL;
2172 _upload_status=UPLOAD_STATUS_FAILED;
2176 MYSERIAL1.println(
"Upload failed");
2178 _webserver->client().stop();
2180 if (sdfile.
exists (upload_filename.c_str()) ) {
2181 sdfile.
remove (upload_filename.c_str());
2189 static uint32_t timeout = millis();
2190 #ifdef ENABLE_CAPTIVE_PORTAL
2191 if(WiFi.getMode() == WIFI_AP){
2192 dnsServer.processNextRequest();
2195 if (_webserver)_webserver->handleClient();
2196 if (_socket_server && _setupdone) {
2198 _socket_server->loop();
2200 if ((millis() - timeout) > 10000) {
2201 if (_socket_server){
2203 s+=String(_id_connection);
2204 _socket_server->broadcastTXT(s);
2211 void Web_Server::handle_Websocket_Event(uint8_t num, uint8_t type, uint8_t * payload,
size_t length) {
2214 case WStype_DISCONNECTED:
2217 case WStype_CONNECTED:
2219 IPAddress ip = _socket_server->remoteIP(num);
2221 String s =
"CURRENT_ID:" + String(num);
2223 _id_connection = num;
2224 _socket_server->sendTXT(_id_connection, s);
2225 s =
"ACTIVE_ID:" + String(_id_connection);
2226 _socket_server->broadcastTXT(s);
2252 char * Web_Server::mac2str (uint8_t mac [8])
2254 static char macstr [18];
2255 if (0 > sprintf (macstr,
"%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) ) {
2256 strcpy (macstr,
"00:00:00:00:00:00");
2261 String Web_Server::get_Splited_Value(String data,
char separator,
int index)
2264 int strIndex[] = {0, -1};
2265 int maxIndex = data.length()-1;
2267 for(
int i=0; i<=maxIndex && found<=index; i++){
2268 if(data.charAt(i)==separator || i==maxIndex){
2270 strIndex[0] = strIndex[1]+1;
2271 strIndex[1] = (i == maxIndex) ? i+1 : i;
2275 return found>index ? data.substring(strIndex[0], strIndex[1]) :
"";
2280 String Web_Server::formatBytes (uint32_t bytes)
2283 return String (bytes) +
" B";
2284 }
else if (bytes < (1024 * 1024) ) {
2285 return String (bytes / 1024.0) +
" KB";
2286 }
else if (bytes < (1024 * 1024 * 1024) ) {
2287 return String (bytes / 1024.0 / 1024.0) +
" MB";
2289 return String (bytes / 1024.0 / 1024.0 / 1024.0) +
" GB";
2295 String Web_Server::getContentType (String filename)
2297 String file_name = filename;
2298 file_name.toLowerCase();
2299 if (filename.endsWith (
".htm") ) {
2301 }
else if (file_name.endsWith (
".html") ) {
2303 }
else if (file_name.endsWith (
".css") ) {
2305 }
else if (file_name.endsWith (
".js") ) {
2306 return "application/javascript";
2307 }
else if (file_name.endsWith (
".png") ) {
2309 }
else if (file_name.endsWith (
".gif") ) {
2311 }
else if (file_name.endsWith (
".jpeg") ) {
2312 return "image/jpeg";
2313 }
else if (file_name.endsWith (
".jpg") ) {
2314 return "image/jpeg";
2315 }
else if (file_name.endsWith (
".ico") ) {
2316 return "image/x-icon";
2317 }
else if (file_name.endsWith (
".xml") ) {
2319 }
else if (file_name.endsWith (
".pdf") ) {
2320 return "application/x-pdf";
2321 }
else if (file_name.endsWith (
".zip") ) {
2322 return "application/x-zip";
2323 }
else if (file_name.endsWith (
".gz") ) {
2324 return "application/x-gzip";
2325 }
else if (file_name.endsWith (
".txt") ) {
2326 return "text/plain";
2328 return "application/octet-stream";
2334 #ifdef ENABLE_AUTHENTICATION
2335 if (_webserver->hasHeader (
"Cookie") ) {
2336 String cookie = _webserver->header (
"Cookie");
2337 int pos = cookie.indexOf (
"ESPSESSIONID=");
2339 int pos2 = cookie.indexOf (
";", pos);
2340 String sessionID = cookie.substring (pos + strlen (
"ESPSESSIONID="), pos2);
2341 IPAddress ip = _webserver->client().remoteIP();
2343 return ResetAuthIP (ip, sessionID.c_str() );
2352 #ifdef ENABLE_AUTHENTICATION
2354 bool Web_Server::isLocalPasswordValid (
const char * password)
2358 if ( (strlen (password) > MAX_LOCAL_PASSWORD_LENGTH) || (strlen (password) < MIN_LOCAL_PASSWORD_LENGTH) ) {
2362 for (
int i = 0; i < strlen (password); i++) {
2372 bool Web_Server::AddAuthIP (auth_ip * item)
2374 if (_nb_ip > MAX_AUTH_IP) {
2377 item->_next = _head;
2384 char * Web_Server::create_session_ID()
2386 static char sessionID[17];
2388 for (
int i = 0; i < 17; i++) {
2389 sessionID[i] =
'\0';
2392 uint32_t now = millis();
2394 IPAddress remoteIP = _webserver->client().remoteIP();
2396 if (0 > sprintf (sessionID,
"%02X%02X%02X%02X%02X%02X%02X%02X", remoteIP[0], remoteIP[1], remoteIP[2], remoteIP[3], (uint8_t) ( (now >> 0) & 0xff), (uint8_t) ( (now >> 8) & 0xff), (uint8_t) ( (now >> 16) & 0xff), (uint8_t) ( (now >> 24) & 0xff) ) ) {
2397 strcpy (sessionID,
"NONE");
2403 bool Web_Server::ClearAuthIP (IPAddress ip,
const char * sessionID)
2405 auth_ip * current = _head;
2406 auth_ip * previous = NULL;
2409 if ( (ip == current->ip) && (strcmp (sessionID, current->sessionID) == 0) ) {
2412 if (current == _head) {
2413 _head = current->_next;
2418 previous->_next = current->_next;
2421 current = previous->_next;
2425 current = current->_next;
2432 auth_ip * Web_Server::GetAuth (IPAddress ip,
const char * sessionID)
2434 auth_ip * current = _head;
2439 if (ip == current->ip) {
2440 if (strcmp (sessionID, current->sessionID) == 0) {
2446 current = current->_next;
2454 auth_ip * current = _head;
2455 auth_ip * previous = NULL;
2459 if ( (millis() - current->last_time) > 360000) {
2461 if (current == _head) {
2462 _head = current->_next;
2467 previous->_next = current->_next;
2470 current = previous->_next;
2473 if (ip == current->ip) {
2474 if (strcmp (sessionID, current->sessionID) == 0) {
2476 current->last_time = millis();
2481 current = current->_next;
2488 String Web_Server::get_param (String & cmd_params,
const char *
id,
bool withspace)
2490 static String parameter;
2496 if (strlen (
id) == 0) {
2501 start = cmd_params.indexOf (
id);
2510 end = cmd_params.indexOf (
" ", start);
2514 end = cmd_params.length();
2517 parameter = cmd_params.substring (start + strlen (
id),
end);
2525 _webserver = webserver;
2534 if (!_header_sent) {
2535 _webserver->setContentLength(CONTENT_LENGTH_UNKNOWN);
2536 _webserver->sendHeader(
"Content-Type",
"text/html");
2537 _webserver->sendHeader(
"Cache-Control",
"no-cache");
2538 _webserver->send(200);
2539 _header_sent =
true;
2542 if (_buffer.length() > 1200) {
2544 _webserver->sendContent(_buffer);
2554 if(_buffer.length() > 0)_webserver->sendContent(_buffer);
2556 _webserver->sendContent(
"");
2558 _header_sent =
false;
2563 #endif // Enable HTTP
2565 #endif // ENABLE_WIFI
2567 #endif // ARDUINO_ARCH_ESP32