Advertisement
TolentinoCotesta

SmartOven

Apr 25th, 2017
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.90 KB | None | 0 0
  1. #include <Arduino.h>
  2. #include "CountUpDownTimer.h"
  3. #include <PID_v1.h>
  4. #include <ESP8266WiFi.h>
  5. #include <ESP8266WiFiMulti.h>
  6. #include <WebSocketsServer.h>
  7. #include <ESP8266WebServer.h>
  8. #include <ESP8266mDNS.h>
  9. #include <Hash.h>
  10. #include <FS.h>
  11. #include "max6675.h"
  12. #include <SPI.h>
  13.  
  14. #define OUT_PIN1 5
  15. #define OUT_PIN2 16        
  16. #define OUT_ENABLE 15    
  17. int dataSendTime = 5;   // Refresh client data every x seconds (websocket)
  18. int WindowSize = 5000;
  19. unsigned long windowStartTime;
  20.  
  21. ESP8266WiFiMulti WiFiMulti;
  22. ESP8266WebServer server = ESP8266WebServer(80);
  23. WebSocketsServer webSocket = WebSocketsServer(81);
  24. File fsUploadFile;
  25.  
  26. const char* ssid = "mySSID";
  27. const char* password = "mypassword";
  28. const char* host = "smartOven";
  29.  
  30. CountUpDownTimer Timer(UP, LOW); // Default precision is HIGH, but you can change it to also be LOW
  31. CountUpDownTimer dataTimer(UP, LOW);
  32.  
  33. uint16_t iTimerSetpoint = 60;
  34. uint16_t iTemp1Setpoint = 25;
  35. uint16_t iTemp2Setpoint = 25;
  36. String stTimeActual = "60";
  37. double dTempActual1 = 75.0;
  38. double dTempActual2 = 75.0;
  39. bool bStart = false;
  40. int outState1 = 0;         // current state of the OUT
  41. int lastOutState1 = 0;     // previous state of the OUT
  42. int outState2 = 0;         // current state of the OUT
  43. int lastOutState2 = 0;     // previous state of the OUT
  44.  
  45. // SPI hardware
  46. int thermoCS1 = 13;
  47. int thermoSO1 = 12;
  48. int thermoSCK1 = 14;
  49.  
  50. // SPI Software
  51. int thermoCS2 = 0;
  52. int thermoSO2 = 4;
  53. int thermoSCK2 = 2;
  54.  
  55. MAX6675 thermocouple1;
  56. MAX6675 thermocouple2;
  57.  
  58. //Specify the links and initial tuning parameters
  59. double Kp1 ; double Ki1 ; double Kd1 ;
  60. double Setpoint1, Input1, OutputPID1;
  61. PID myPID1(&Input1, &OutputPID1, &Setpoint1, Kp1, Ki1, Kd1, DIRECT);
  62.  
  63. //Specify the links and initial tuning parameters
  64. double Kp2 ; double Ki2 ; double Kd2 ;
  65. double Setpoint2, Input2, OutputPID2;
  66. PID myPID2(&Input2, &OutputPID2, &Setpoint2, Kp2, Ki2, Kd2, DIRECT);
  67.  
  68. // *********************************** //
  69. //      FUNCTIONS     Prototype        //
  70. // *********************************** //
  71.  
  72. String getContentType(String filename);
  73. bool handleFileRead(String path);
  74. void handleFileUpload(void);
  75. void handleFileDelete(void);
  76. void handleFileCreate(void);
  77. void handleFileList(void);
  78. void loadPIDConfig(void);
  79. void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght) ;
  80.  
  81.  
  82. // Setup nodeMCU
  83. void setup() {
  84.     pinMode(OUT_PIN1, OUTPUT);
  85.     pinMode(OUT_PIN2, OUTPUT);
  86.     pinMode(OUT_ENABLE, OUTPUT);
  87.     digitalWrite(OUT_PIN1, LOW);
  88.     digitalWrite(OUT_PIN2, LOW);
  89.     digitalWrite(OUT_ENABLE, LOW);
  90.    
  91.     Serial.flush();
  92.     Serial.begin(115200);  
  93.    
  94.     delay(10);  
  95.     SPIFFS.begin();  
  96.        
  97.     for(uint8_t t = 4; t > 0; t--) {
  98.         Serial.printf("[SETUP] BOOT WAIT %d...\n", t);
  99.         Serial.flush();
  100.         delay(1000);
  101.     }  
  102.  
  103.     WiFiMulti.addAP(ssid, password);
  104.     Serial.print("Connecting WiFi ");
  105.     Serial.println(ssid);
  106.     while(WiFiMulti.run() != WL_CONNECTED) {
  107.         delay(100);
  108.         Serial.print(".");
  109.     }
  110.     Serial.println();
  111.     Serial.print("WiFi connected. IP address: ");
  112.     Serial.println(WiFi.localIP());    
  113.  
  114.     // start webSocket server
  115.     webSocket.begin();
  116.     webSocket.onEvent(webSocketEvent);  
  117.  
  118.     //WEBSERVER INIT
  119.     //list directory
  120.     server.on("/list", HTTP_GET, handleFileList);
  121.     //load editor
  122.     server.on("/edit", HTTP_GET, [](){  if(!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound");   });
  123.     //create file
  124.     server.on("/edit", HTTP_PUT, handleFileCreate);
  125.     //delete file
  126.     server.on("/edit", HTTP_DELETE, handleFileDelete);
  127.     //first callback is called after the request has ended with all parsed arguments
  128.     //second callback handles file uploads at that location
  129.     server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload);      
  130.     //called when the url is not defined here -> index.html (use it to load content from SPIFFS)
  131.     server.onNotFound([](){    if(!handleFileRead(server.uri()))     server.send(404, "text/plain", "FileNotFound");    });        
  132.     server.begin();  
  133.     Serial.println("HTTP server started");
  134.    
  135.      // Add service to MDNS
  136.     MDNS.begin(host);  
  137.     MDNS.addService("http", "tcp", 80);
  138.     MDNS.addService("ws", "tcp", 81);
  139.     Serial.println("MDNSP services started");
  140.  
  141.     dataTimer.SetStopTime(0, 0, dataSendTime );
  142.     dataTimer.StartTimer();
  143.    
  144.     windowStartTime = millis();
  145.     //tell the PID to range between 0 and the full window size
  146.     myPID1.SetOutputLimits(0, WindowSize);
  147.     myPID1.SetMode(AUTOMATIC);
  148.     myPID2.SetOutputLimits(0, WindowSize);
  149.     myPID2.SetMode(AUTOMATIC);
  150.    
  151.     Serial.println("Reading PID constant...");    
  152.     loadPIDConfig();    
  153.     myPID1.SetTunings(Kp1, Ki1, Kd1);
  154.     myPID2.SetTunings(Kp2, Ki2, Kd2);
  155.    
  156.     Serial.print("PID 1 parameter(Kp, Ki, Kd): ");                            
  157.     Serial.println(String(myPID1.GetKp(), 1) + " " + String(myPID1.GetKi(), 1) + " " + String(myPID1.GetKd(), 1));
  158.     Serial.print("PID 2 parameter(Kp, Ki, Kd): ");                            
  159.     Serial.println(String(myPID2.GetKp(), 1) + " " + String(myPID2.GetKi(), 1) + " " + String(myPID2.GetKd(), 1));
  160.    
  161.     //SPI.begin();
  162.     thermocouple1.begin(thermoSCK1, thermoCS1, thermoSO1);
  163.     Serial.print("Temperatura 1 attuale: ");
  164.     Serial.println(String(thermocouple1.readCelsius(), 2)+ (char)176 + "C");
  165.    
  166.     thermocouple2.begin(thermoSCK2, thermoCS2, thermoSO2);
  167.     Serial.print("Temperatura 2 attuale: ");
  168.     Serial.println(String(thermocouple2.readCelsius(), 2)+ (char)176 + "C");
  169.    
  170. }
  171.  
  172. void loop() {
  173.     webSocket.loop();
  174.     server.handleClient();    
  175.  
  176.     myPID1.Compute();
  177.     myPID2.Compute();
  178.    
  179.     // run the timer  
  180.     Timer.Timer();
  181.     dataTimer.Timer();
  182.    
  183.     if (dataTimer.TimeCheck(0, 0, dataSendTime) ) {
  184.        if (dataTimer.TimeHasChanged() ) {
  185.           dTempActual1 = thermocouple1.readCelsius();
  186.           dTempActual2 = thermocouple2.readCelsius();
  187.           // update client data evry x seconds (via webSocket)
  188.           stTimeActual = String(Timer.ShowMinutes(), DEC) + "':" + String(Timer.ShowSeconds(), DEC)  + "\"";
  189.           webSocket.broadcastTXT( "##" + String(iTemp2Setpoint, DEC) +';'+ String(iTemp1Setpoint, DEC) +';'+ String(iTimerSetpoint, DEC) +';'+
  190.                                          String(dTempActual2, 2) + ';' + String(dTempActual1, 2) + ';' + stTimeActual);
  191.        }
  192.        dataTimer.StartTimer();      
  193.     }
  194.  
  195.     // Check if cooking timer has gone
  196.     if (Timer.TimeCheck(0, iTimerSetpoint, 0) ) {
  197.        bStart = false;
  198.        if (Timer.TimeHasChanged() ) {
  199.           Serial.print("Cooking time: ");
  200.           Serial.print(Timer.ShowHours());
  201.           Serial.print(":");
  202.           Serial.print(Timer.ShowMinutes());
  203.           Serial.print(":");
  204.           Serial.println(Timer.ShowSeconds());  
  205.        }    
  206.     }
  207.  
  208.    Input1 = dTempActual1;
  209.    Setpoint1 = iTemp1Setpoint;    
  210.    Input2 = dTempActual2;
  211.    Setpoint2 = iTemp2Setpoint;    
  212.    /*
  213.    Serial.print(OutputPID1);
  214.    Serial.print("; ");
  215.    Serial.println(OutputPID2);
  216.  
  217.    /************************************************
  218.    * turn the output pin on/off based on pid output
  219.    ************************************************/
  220.   if (bStart==true) {
  221.      unsigned long now = millis();
  222.      if (now - windowStartTime > WindowSize) {
  223.         //time to shift the Relay Window
  224.          windowStartTime += WindowSize;
  225.      }
  226.      if (OutputPID1 > now - windowStartTime){
  227.         digitalWrite(OUT_PIN1, HIGH);  
  228.        // Serial.println("High " + String(OutputPID1));    
  229.         }
  230.      else {  digitalWrite(OUT_PIN1, LOW); }
  231.          
  232.      if (OutputPID2 > now - windowStartTime)  { digitalWrite(OUT_PIN2, HIGH);  }
  233.      else {  digitalWrite(OUT_PIN2, LOW);    }
  234.      
  235.   } else {
  236.         digitalWrite(OUT_PIN1, LOW);
  237.         digitalWrite(OUT_PIN2, LOW);
  238.         }
  239.  
  240.   // compare the OUT to its previous state
  241.   outState1 = digitalRead(OUT_PIN1);  
  242.   if (outState1 != lastOutState1) {          
  243.       webSocket.broadcastTXT( "@@" + String(outState1*30)+ ';' + String(outState2*30));
  244.       lastOutState1 = outState1;
  245.   }
  246.   outState2 = digitalRead(OUT_PIN2);  
  247.   if (outState2 != lastOutState2) {    
  248.       webSocket.broadcastTXT( "@@" + String(outState1*30)+ ';' + String(outState2*30));
  249.       lastOutState2 = outState2;
  250.   }
  251. }
  252.  
  253.  
  254.  
  255. // *********************************** //
  256. //            FUNCTIONS                //
  257. // *********************************** //
  258.  
  259.  
  260. String getValue(String data, char separator, int index){
  261.   int found = 0;
  262.   int strIndex[] = {0, -1};
  263.   int maxIndex = data.length()-1;
  264.  
  265.   for(int i=0; i<=maxIndex && found<=index; i++){
  266.     if(data.charAt(i)==separator || i==maxIndex){
  267.         found++;
  268.         strIndex[0] = strIndex[1]+1;
  269.         strIndex[1] = (i == maxIndex) ? i+1 : i;
  270.     }
  271.   }
  272.   return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
  273. }
  274.  
  275. // Websocket messages
  276. void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght) {        
  277.     switch(type) {
  278.         case WStype_DISCONNECTED:{
  279.             Serial.printf("[%u] Disconnected!\n", num);
  280.             break;
  281.         }                
  282.         case WStype_CONNECTED:{
  283.             IPAddress ip = webSocket.remoteIP(num);
  284.             Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
  285.             webSocket.sendTXT(num, "Connected");
  286.             delay(20);            
  287.             // if heating tell to the client we are busy
  288.             if (bStart)
  289.                webSocket.sendTXT( num, "State: RUN");
  290.                webSocket.sendTXT( num, "Clients: " + String(num));
  291.                dTempActual1 = thermocouple1.readCelsius();
  292.                dTempActual2 = thermocouple2.readCelsius();
  293.                // update client data evry x seconds (via webSocket)
  294.                stTimeActual = String(Timer.ShowMinutes(), DEC) + "':" + String(Timer.ShowSeconds(), DEC)  + "\"";
  295.                webSocket.sendTXT( num, "##" + String(iTemp2Setpoint, DEC) +';'+ String(iTemp1Setpoint, DEC) +';'+ String(iTimerSetpoint, DEC) +';'+
  296.                                               String(dTempActual2, 2) + ';' + String(dTempActual1, 2) + ';' + stTimeActual);                  
  297.                webSocket.sendTXT( num, "!!" +  String(myPID1.GetKp(), 1) + ";" + String(myPID1.GetKi(), 1) + ";" + String(myPID1.GetKd(), 1) + ';' +
  298.                                                String(myPID2.GetKp(), 1) + ";" + String(myPID2.GetKi(), 1) + ";" + String(myPID2.GetKd(), 1) + ';' + String(WindowSize));          
  299.             break;
  300.         }            
  301.         case WStype_TEXT:{
  302.             Serial.printf("[%u] get Text: %s\n", num, payload);
  303.             if(payload[0] == '#') {
  304.                 String stData = (const char*) payload + 3;
  305.                 if(payload[1]=='1'){                  
  306.                   iTemp1Setpoint =  stData.toInt();    
  307.                   Serial.printf("Set Temperature 1: %d\n", iTemp1Setpoint);  
  308.                   webSocket.sendTXT(num, "Setpoint T1: " + String(iTemp1Setpoint, DEC));
  309.                 }
  310.                 if(payload[1]=='2'){                  
  311.                   iTemp2Setpoint =  stData.toInt();    
  312.                   Serial.printf("Set Temperature 2: %d\n", iTemp2Setpoint);  
  313.                   webSocket.sendTXT(num, "Setpoint T2: " + String(iTemp2Setpoint, DEC));
  314.                 }
  315.             }
  316.            
  317.             if(payload[0] == '%') {
  318.                 String stData = (const char*) payload + 1;
  319.                 iTimerSetpoint = stData.toInt();;  
  320.                 Serial.printf("Set Timer: %d\n", iTimerSetpoint);
  321.                 Timer.SetStopTime(0, (uint32_t) iTimerSetpoint,0);
  322.                 webSocket.sendTXT(num, "Setpoint Time: " + String(iTimerSetpoint, DEC));
  323.             }
  324.             if(payload[2]== 'A') {
  325.                 Timer.SetStopTime(0, (uint32_t) iTimerSetpoint,0);
  326.                 Timer.StartTimer();
  327.                 Serial.printf("Start heating at %d\xB0C / %d\xB0C. Timer: %d min\n", iTemp1Setpoint, iTemp2Setpoint, iTimerSetpoint);
  328.                 bStart = true;
  329.             }
  330.             if(payload[2] == 'O') {
  331.                 Timer.StopTimer();
  332.                 Serial.println("Stop heating");
  333.                 bStart = false;
  334.             }
  335.             if(payload[0] == '!') {
  336.                 String str;
  337.                 String stData = (const char*) payload + 2;
  338.                
  339.                 Kp1 = getValue(stData, ';', 0).toFloat();
  340.                 Ki1 = getValue(stData, ';', 1).toFloat();
  341.                 Kd1 = getValue(stData, ';', 2).toFloat();            
  342.                 myPID1.SetTunings(Kp1, Ki1, Kd1);          
  343.                 str = String(myPID1.GetKp(), 1) + " " + String(myPID1.GetKi(), 1) + " " + String(myPID1.GetKd(), 1);                                      
  344.                 Serial.print("Update PID 1 parameter(Kp, Ki, Kd). New values: ");                                                    
  345.                 Serial.println(str);
  346.                 webSocket.sendTXT(num, "PID 1 parameter updated: " + str );
  347.                
  348.                 Kp2 = getValue(stData, ';', 3).toFloat();
  349.                 Ki2 = getValue(stData, ';', 4).toFloat();
  350.                 Kd2 = getValue(stData, ';', 5).toFloat();                
  351.                 myPID2.SetTunings(Kp2, Ki2, Kd2);          
  352.                 str = String(myPID2.GetKp(), 1) + " " + String(myPID2.GetKi(), 1) + " " + String(myPID2.GetKd(), 1);                                      
  353.                 Serial.print("Update PID 2 parameter(Kp, Ki, Kd). New values: ");                                                    
  354.                 Serial.println(str);
  355.                 webSocket.sendTXT(num, "PID 2 parameter updated: " + str );
  356.                 // Store new values in FS
  357.                 savePIDConfig();
  358.                 WindowSize = getValue(stData, ';', 6).toInt();
  359.                 Serial.print("Update windows output size. New values: ");                                                    
  360.                 Serial.println(getValue(stData, ';', 6));
  361.             }          
  362.             break;        
  363.        }
  364.     }
  365. }
  366.  
  367.  
  368. void loadPIDConfig(void) {
  369.   File configFile = SPIFFS.open("/PID.ini", "r");
  370.   if (!configFile) {
  371.       Serial.println("File doesn't exist yet. Creating it");  
  372.       // open the file in write mode
  373.       File f = SPIFFS.open("/PID.ini", "w");
  374.       if (!f) {  Serial.println(" file creation failed");    }
  375.       // no cinfigFile: set default values
  376.       Kp1 = 1.0;      Ki1 = 2.0;      Kd1 = 0.3;
  377.       Kp2 = 1.0;      Ki2 = 2.0;      Kd2 = 0.3;
  378.       // now write two lines in key/value style with  end-of-line characters
  379.       f.println(String(Kp1, 1));      f.println(String(Ki1, 1));      f.println(String(Kd1, 1));
  380.       f.println(String(Kp2, 1));      f.println(String(Ki2, 1));      f.println(String(Kd2, 1));
  381.   } else {
  382.           // we could open the file
  383.            Serial.println("File opened. Reading...");  
  384.           for (int i=1; i<=6; i++){
  385.              //Lets read line by line from the file
  386.              String line = configFile.readStringUntil('\n');
  387.              switch (i) {
  388.               case 1: Kp1 = line.toFloat();
  389.               case 2: Ki1 = line.toFloat();
  390.               case 3: Kd1 = line.toFloat();    
  391.               case 4: Kp2 = line.toFloat();
  392.               case 5: Ki2 = line.toFloat();
  393.               case 6: Kd2 = line.toFloat();          
  394.              }
  395.          }
  396.   }
  397.   configFile.close();  
  398. }
  399.  
  400. void savePIDConfig(void) {
  401.   File configFile = SPIFFS.open("/PID.ini", "w");
  402.   if (!configFile) {
  403.       Serial.println("File doesn't exist yet. Creating it");  
  404.       // open the file in write mode
  405.   } else {
  406.           // now write two lines in key/value style with  end-of-line characters
  407.           configFile.println(String(Kp1, 1));
  408.           configFile.println(String(Ki1, 1));
  409.           configFile.println(String(Kd1, 1));
  410.           configFile.println(String(Kp2, 1));
  411.           configFile.println(String(Ki2, 1));
  412.           configFile.println(String(Kd2, 1));
  413.         }
  414.   configFile.close();  
  415. }
  416.  
  417. // Web server file handler
  418. String getContentType(String filename){
  419.   if(server.hasArg("download")) return "application/octet-stream";
  420.   else if(filename.endsWith(".htm")) return "text/html";
  421.   else if(filename.endsWith(".html")) return "text/html";
  422.   else if(filename.endsWith(".ini")) return "text/html";
  423.   else if(filename.endsWith(".css")) return "text/css";
  424.   else if(filename.endsWith(".js")) return "application/javascript";
  425.   else if(filename.endsWith(".png")) return "image/png";
  426.   else if(filename.endsWith(".gif")) return "image/gif";
  427.   else if(filename.endsWith(".jpg")) return "image/jpeg";
  428.   else if(filename.endsWith(".ico")) return "image/x-icon";
  429.   else if(filename.endsWith(".xml")) return "text/xml";
  430.   else if(filename.endsWith(".pdf")) return "application/x-pdf";
  431.   else if(filename.endsWith(".zip")) return "application/x-zip";
  432.   else if(filename.endsWith(".gz")) return "application/x-gzip";
  433.   return "text/plain";
  434. }
  435.  
  436. bool handleFileRead(String path){
  437.   Serial.println("handleFileRead: " + path);
  438.   if(path.endsWith("/")) path += "index.htm";
  439.   String contentType = getContentType(path);
  440.   String pathWithGz = path + ".gz";
  441.   if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){
  442.     if(SPIFFS.exists(pathWithGz))
  443.       path += ".gz";
  444.     File file = SPIFFS.open(path, "r");
  445.     size_t sent = server.streamFile(file, contentType);
  446.     file.close();
  447.     return true;
  448.   }
  449.   return false;
  450. }
  451.  
  452. void handleFileUpload(){
  453.   if(server.uri() != "/edit") return;
  454.   HTTPUpload& upload = server.upload();
  455.   if(upload.status == UPLOAD_FILE_START){
  456.     String filename = upload.filename;
  457.     if(!filename.startsWith("/")) filename = "/"+filename;
  458.     Serial.print("handleFileUpload Name: "); Serial.println(filename);
  459.     fsUploadFile = SPIFFS.open(filename, "w");
  460.     filename = String();
  461.   } else if(upload.status == UPLOAD_FILE_WRITE){
  462.     //Serial.print("handleFileUpload Data: "); Serial.println(upload.currentSize);
  463.     if(fsUploadFile)
  464.       fsUploadFile.write(upload.buf, upload.currentSize);
  465.   } else if(upload.status == UPLOAD_FILE_END){
  466.     if(fsUploadFile)
  467.       fsUploadFile.close();
  468.     Serial.print("handleFileUpload Size: "); Serial.println(upload.totalSize);
  469.   }
  470. }
  471.  
  472. void handleFileDelete(){
  473.   if(server.args() == 0) return server.send(500, "text/plain", "BAD ARGS");
  474.   String path = server.arg(0);
  475.   Serial.println("handleFileDelete: " + path);
  476.   if(path == "/")
  477.     return server.send(500, "text/plain", "BAD PATH");
  478.   if(!SPIFFS.exists(path))
  479.     return server.send(404, "text/plain", "FileNotFound");
  480.   SPIFFS.remove(path);
  481.   server.send(200, "text/plain", "");
  482.   path = String();
  483. }
  484.  
  485. void handleFileCreate(){
  486.   if(server.args() == 0)
  487.     return server.send(500, "text/plain", "BAD ARGS");
  488.   String path = server.arg(0);
  489.   Serial.println("handleFileCreate: " + path);
  490.   if(path == "/")
  491.     return server.send(500, "text/plain", "BAD PATH");
  492.   if(SPIFFS.exists(path))
  493.     return server.send(500, "text/plain", "FILE EXISTS");
  494.   File file = SPIFFS.open(path, "w");
  495.   if(file)
  496.     file.close();
  497.   else
  498.     return server.send(500, "text/plain", "CREATE FAILED");
  499.   server.send(200, "text/plain", "");
  500.   path = String();
  501. }
  502.  
  503. void handleFileList() {
  504.   if(!server.hasArg("dir")) {server.send(500, "text/plain", "BAD ARGS"); return;}  
  505.   String path = server.arg("dir");
  506.   Serial.println("handleFileList: " + path);
  507.   Dir dir = SPIFFS.openDir(path);
  508.   path = String();
  509.   String output = "[";
  510.   while(dir.next()){
  511.     File entry = dir.openFile("r");
  512.     if (output != "[") output += ',';
  513.     bool isDir = false;
  514.     output += "{\"type\":\"";
  515.     output += (isDir)?"dir":"file";
  516.     output += "\",\"name\":\"";
  517.     output += String(entry.name()).substring(1);
  518.     output += "\"}";
  519.     entry.close();
  520.   }
  521.   output += "]";
  522.   server.send(200, "text/json", output);
  523. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement