Advertisement
FlyFar

esp8266_wifi_duck.ino

Jul 17th, 2023
1,065
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 12.60 KB | Cybersecurity | 0 0
  1. #include <ESP8266WiFi.h>
  2. #include <FS.h>
  3. #include <ESP8266mDNS.h>
  4. #include <ESPAsyncTCP.h>
  5. #include <ESPAsyncWebServer.h>
  6. #include <SPIFFSEditor.h>
  7. #include <EEPROM.h>
  8. #include "data.h"
  9.  
  10. #include "Settings.h"
  11.  
  12. #define BAUD_RATE 57200
  13. #define bufferSize 600
  14. #define debug false
  15.  
  16. /* ============= CHANGE WIFI CREDENTIALS ============= */
  17. const char *ssid = "WiFi Duck";
  18. const char *password = "quackquack"; //min 8 chars
  19. /* ============= ======================= ============= */
  20.  
  21. AsyncWebServer server(80);
  22. FSInfo fs_info;
  23.  
  24. Settings settings;
  25.  
  26. bool shouldReboot = false;
  27.  
  28. //Web stuff
  29. extern const uint8_t data_indexHTML[] PROGMEM;
  30. extern const uint8_t data_updateHTML[] PROGMEM;
  31. extern const uint8_t data_error404[] PROGMEM;
  32. extern const uint8_t data_styleCSS[] PROGMEM;
  33. extern const uint8_t data_functionsJS[] PROGMEM;
  34. extern const uint8_t data_liveHTML[] PROGMEM;
  35. extern const uint8_t data_infoHTML[] PROGMEM;
  36. extern const uint8_t data_nomalizeCSS[] PROGMEM;
  37. extern const uint8_t data_skeletonCSS[] PROGMEM;
  38. extern const uint8_t data_license[] PROGMEM;
  39. extern const uint8_t data_settingsHTML[] PROGMEM;
  40. extern const uint8_t data_viewHTML[] PROGMEM;
  41.  
  42. extern String formatBytes(size_t bytes);
  43.  
  44. //Script stuff
  45. bool runLine = false;
  46. bool runScript = false;
  47. File script;
  48.  
  49. uint8_t scriptBuffer[bufferSize];
  50. uint8_t scriptLineBuffer[bufferSize];
  51. int bc = 0; //buffer counter
  52. int lc = 0; //line buffer counter
  53.  
  54.  
  55. void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
  56.   File f;
  57.  
  58.   if(!filename.startsWith("/")) filename = "/" + filename;
  59.  
  60.   if(!index) f = SPIFFS.open(filename, "w"); //create or trunicate file
  61.   else f = SPIFFS.open(filename, "a"); //append to file (for chunked upload)
  62.  
  63.   if(debug) Serial.write(data, len);
  64.   f.write(data, len);
  65.  
  66.   if(final){ //upload finished
  67.       if(debug) Serial.printf("UploadEnd: %s, %u B\n", filename.c_str(), index+len);
  68.       f.close();
  69.   }
  70. }
  71.  
  72. void send404(AsyncWebServerRequest *request){
  73.   AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", data_error404, sizeof(data_error404));
  74.   request->send(response);
  75. }
  76.  
  77. void sendToIndex(AsyncWebServerRequest *request){
  78.   AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "");
  79.   response->addHeader("Location","/");
  80.   request->send(response);
  81. }
  82.  
  83. void sendSettings(AsyncWebServerRequest *request) {
  84.     AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", data_settingsHTML, sizeof(data_settingsHTML));
  85.     request->send(response);
  86. }
  87.  
  88. void setup() {
  89.  
  90.   Serial.begin(BAUD_RATE);
  91.   delay(2000);
  92.   if(debug) Serial.println("\nstarting...\nSSID: "+ (String)ssid +"\nPassword: "+ (String)password);
  93.  
  94.   EEPROM.begin(4096);
  95.   SPIFFS.begin();
  96.  
  97.   settings.load();
  98.   if(debug) settings.print();
  99.  
  100.   if(settings.autoExec) {
  101.       String _name = (String)settings.autostart;
  102.       script = SPIFFS.open("/" + _name, "r");
  103.       runScript = true;
  104.       runLine = true;
  105.   }
  106.  
  107.   WiFi.mode(WIFI_STA);
  108.   WiFi.softAP(settings.ssid, settings.password, settings.channel, settings.hidden);
  109.  
  110.   // ===== WebServer ==== //
  111.   MDNS.addService("http","tcp",80);
  112.  
  113.   server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
  114.       AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", data_indexHTML, sizeof(data_indexHTML));
  115.       request->send(response);
  116.   });
  117.   server.on("/index.html", HTTP_GET, sendToIndex);
  118.  
  119.   server.on("/live.html", HTTP_GET, [](AsyncWebServerRequest *request) {
  120.       AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", data_liveHTML, sizeof(data_liveHTML));
  121.       request->send(response);
  122.   });
  123.  
  124.   server.on("/view.html", HTTP_GET, [](AsyncWebServerRequest *request) {
  125.       AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", data_viewHTML, sizeof(data_viewHTML));
  126.       request->send(response);
  127.   });
  128.  
  129.   server.on("license", HTTP_GET, [](AsyncWebServerRequest *request) {
  130.       AsyncWebServerResponse *response = request->beginResponse_P(200, "text/plain", data_license, sizeof(data_license));
  131.       request->send(response);
  132.   });
  133.  
  134.   server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request) {
  135.       AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", data_styleCSS, sizeof(data_styleCSS));
  136.       request->send(response);
  137.   });
  138.  
  139.   server.on("/normalize.css", HTTP_GET, [](AsyncWebServerRequest *request) {
  140.       AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", data_nomalizeCSS, sizeof(data_nomalizeCSS));
  141.       request->send(response);
  142.   });
  143.  
  144.   server.on("/skeleton.css", HTTP_GET, [](AsyncWebServerRequest *request) {
  145.       AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", data_skeletonCSS, sizeof(data_skeletonCSS));
  146.       request->send(response);
  147.   });
  148.  
  149.   server.on("/functions.js", HTTP_GET, [](AsyncWebServerRequest *request) {
  150.       AsyncWebServerResponse *response = request->beginResponse_P(200, "text/javascript", data_functionsJS, sizeof(data_functionsJS));
  151.       request->send(response);
  152.   });
  153.  
  154.   server.on("/info.html", HTTP_GET, [](AsyncWebServerRequest *request) {
  155.       AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", data_infoHTML, sizeof(data_infoHTML));
  156.       request->send(response);
  157.   });
  158.  
  159.   server.on("/settings.html", HTTP_GET, [](AsyncWebServerRequest *request) {
  160.       sendSettings(request);
  161.   });
  162.  
  163.   server.on("/settings.html", HTTP_POST, [](AsyncWebServerRequest *request) {
  164.  
  165.       if(request->hasArg("ssid")) {
  166.           String _ssid = request->arg("ssid");
  167.           settings.ssidLen = _ssid.length();
  168.           _ssid.toCharArray(settings.ssid, 32);
  169.           if(debug) Serial.println("new SSID = '"+_ssid+"'");
  170.       }
  171.       if(request->hasArg("pswd")) {
  172.           String _pswd = request->arg("pswd");
  173.           settings.passwordLen = _pswd.length();
  174.           _pswd.toCharArray(settings.password, 32);
  175.           if(debug) Serial.println("new password = '" + _pswd + "'");
  176.       }
  177.       if(request->hasArg("autostart")) {
  178.           String _autostart = request->arg("autostart");
  179.           settings.autostartLen = _autostart.length();
  180.           _autostart.toCharArray(settings.autostart, 32);
  181.           if(debug) Serial.println("new autostart = '" + _autostart + "'");
  182.       }
  183.       if(request->hasArg("ch")) settings.channel = request->arg("ch").toInt();
  184.       if(request->hasArg("hidden")) settings.hidden = true;
  185.       else settings.hidden = false;
  186.       if(request->hasArg("autoExec")) settings.autoExec = true;
  187.       else settings.autoExec = false;
  188.      
  189.       settings.save();
  190.       if(debug) settings.print();
  191.  
  192.       sendSettings(request);
  193.   });
  194.  
  195.   server.on("/settings.json", HTTP_GET, [](AsyncWebServerRequest *request) {
  196.       String output = "{";
  197.       output += "\"ssid\":\"" + (String)settings.ssid + "\",";
  198.       output += "\"password\":\"" + (String)settings.password + "\",";
  199.       output += "\"channel\":" + String((int)settings.channel) + ",";
  200.       output += "\"hidden\":" + String((int)settings.hidden) + ",";
  201.       output += "\"autoExec\":" + String((int)settings.autoExec) + ",";
  202.       output += "\"autostart\":\"" + (String)settings.autostart + "\"";
  203.       output += "}";
  204.       request->send(200, "text/json", output);
  205.   });
  206.  
  207.   server.on("/list.json", HTTP_GET, [](AsyncWebServerRequest *request) {
  208.       SPIFFS.info(fs_info);
  209.       Dir dir = SPIFFS.openDir("");
  210.       String output;
  211.       output += "{";
  212.       output += "\"totalBytes\":" + (String)fs_info.totalBytes + ",";
  213.       output += "\"usedBytes\":" + (String)fs_info.usedBytes + ",";
  214.       output += "\"list\":[ ";
  215.       while(dir.next()) {
  216.           File entry = dir.openFile("r");
  217.           String filename = String(entry.name()).substring(1);
  218.           output += '{';
  219.           output += "\"n\":\"" + filename + "\",";//name
  220.           output += "\"s\":\"" + formatBytes(entry.size()) + "\"";//size
  221.           output += "},";
  222.           entry.close();
  223.       }
  224.       output = output.substring(0, output.length() - 1);
  225.       output += "]}";
  226.       request->send(200, "text/json", output);
  227.   });
  228.  
  229.   server.on("/script", HTTP_GET, [](AsyncWebServerRequest *request){
  230.     if(request->hasArg("name")){
  231.       String _name = request->arg("name");
  232.       request->send(SPIFFS, "/"+_name, "text/plain");
  233.     }else send404(request);
  234.   });
  235.  
  236.   server.on("/run", HTTP_POST, [](AsyncWebServerRequest *request) {
  237.       if(request->hasArg("name")) {
  238.           String _name = request->arg("name");
  239.           script = SPIFFS.open("/" + _name, "r");
  240.           runScript = true;
  241.           runLine = true;
  242.           request->send(200, "text/plain", "true");
  243.       }
  244.       else if(request->hasArg("script")) {
  245.           Serial.println(request->arg("script"));
  246.           request->send(200, "text/plain", "true");
  247.       }
  248.       else send404(request);
  249.   });
  250.  
  251.   server.on("/save", HTTP_POST, [](AsyncWebServerRequest *request) {
  252.       if(request->hasArg("name") && request->hasArg("script")) {
  253.           String _name = request->arg("name");
  254.           String _script = request->arg("script");
  255.           File f = SPIFFS.open("/" + _name, "w");
  256.           if(f) {
  257.               f.print(_script);
  258.               request->send(200, "text/plain", "true");
  259.           }
  260.           else request->send(200, "text/plain", "false");
  261.       }
  262.       else send404(request);
  263.   });
  264.  
  265.  
  266.   server.on("/delete", HTTP_GET, [](AsyncWebServerRequest *request){
  267.     if(request->hasArg("name")){
  268.       String _name = request->arg("name");
  269.       SPIFFS.remove("/"+_name);
  270.       request->send(200, "text/plain", "true");
  271.     }else send404(request);
  272.   });
  273.  
  274.   server.on("/rename", HTTP_GET, [](AsyncWebServerRequest *request) {
  275.       if(request->hasArg("name") && request->hasArg("newName")) {
  276.           String _name = request->arg("name");
  277.           String _newName = request->arg("newName");
  278.           SPIFFS.rename("/" + _name, "/" + _newName);
  279.           request->send(200, "text/plain", "true");
  280.       }
  281.       else send404(request);
  282.   });
  283.  
  284.   server.on("/format", HTTP_GET, [](AsyncWebServerRequest *request){
  285.     SPIFFS.format();
  286.     request->send(200, "text/plain", "true");
  287.     sendToIndex(request);
  288.   });
  289.  
  290.   server.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request){
  291.     sendToIndex(request);
  292.   }, handleUpload);
  293.  
  294.   server.onNotFound([](AsyncWebServerRequest *request){
  295.     send404(request);
  296.   });
  297.  
  298.   server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request) {
  299.       AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "");
  300.       response->addHeader("Location", "/info.html");
  301.       request->send(response);
  302.   });
  303.  
  304.   server.on("/restart", HTTP_GET, [](AsyncWebServerRequest *request) {
  305.       shouldReboot = true;
  306.   });
  307.  
  308.   server.on("/reset", HTTP_GET, [](AsyncWebServerRequest *request) {
  309.       settings.reset();
  310.       request->send(200, "text/plain", "true");
  311.       sendToIndex(request);
  312.   });
  313.  
  314.   //update
  315.   server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){
  316.     shouldReboot = !Update.hasError();
  317.     AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", shouldReboot?"OK":"FAIL");
  318.     response->addHeader("Connection", "close");
  319.     request->send(response);
  320.   },[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
  321.     if(!index){
  322.       if(debug) Serial.printf("Update Start: %s\n", filename.c_str());
  323.       Update.runAsync(true);
  324.       if(!Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000)){
  325.           if(debug) Update.printError(Serial);
  326.       }
  327.     }
  328.     if(!Update.hasError()){
  329.       if(Update.write(data, len) != len){
  330.         Update.printError(Serial);
  331.       }
  332.     }
  333.     if(final){
  334.       if(Update.end(true)){
  335.         if(debug) Serial.printf("Update Success: %uB\n", index+len);
  336.       } else {
  337.         if(debug) Update.printError(Serial);
  338.       }
  339.     }
  340.   });
  341.  
  342.   server.begin();
  343.  
  344.   if(debug) Serial.println("started");
  345. }
  346.  
  347. void sendBuffer(){
  348.   for(int i=0;i<bc;i++) Serial.write((char)scriptBuffer[i]);
  349.   runLine = false;
  350.   bc = 0;
  351. }
  352.  
  353. void addToBuffer(){
  354.   if(bc + lc > bufferSize) sendBuffer();
  355.   for(int i=0;i<lc;i++){
  356.     scriptBuffer[bc] = scriptLineBuffer[i];
  357.     bc++;
  358.   }
  359.   lc = 0;
  360. }
  361.  
  362. void loop() {
  363.   if(shouldReboot) ESP.restart();
  364.  
  365.   if(Serial.available()) {
  366.     uint8_t answer = Serial.read();
  367.     if(answer == 0x99) {
  368.       if(debug) Serial.println("done");
  369.       runLine = true;
  370.     }
  371.     else {
  372.         String command = (char)answer + Serial.readStringUntil('\n');
  373.         command.replace("\r", "");
  374.         if(command == "reset") {
  375.             settings.reset();
  376.             shouldReboot = true;
  377.         }
  378.     }
  379.   }
  380.  
  381.   if(runScript && runLine){
  382.     if(script.available()){
  383.       uint8_t nextChar = script.read();
  384.       if(debug) Serial.write(nextChar);
  385.       scriptLineBuffer[lc] = nextChar;
  386.       lc++;
  387.       if(nextChar == 0x0D || lc == bufferSize) addToBuffer();
  388.     }else{
  389.       addToBuffer();
  390.       if(bc > 0) sendBuffer();
  391.       runScript = false;
  392.       script.close();
  393.     }
  394.   }
  395.  
  396. }
Tags: Arduino
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement