2016-04-22 51 views
3

我最近一直在学习如何在Arduino中编程以在Adafruit HUZZAH ESP8266突破上托管HTML/CSS/Javascript网页,所以请原谅我,如果我的方法完全关闭。如何防止Ajax溢出/服务器崩溃? (Arduino/ESP8266环境)

我正在使用Ajax更新页面上的一些压力表值,它可以工作一段时间,但最终我只能得到ERR_CONNECTION_TIMED_OUT

我总是这样做,尤其是当我刚启动服务器时。如果我最终重新设置了无线网卡足够多的时间,它似乎加载得很好,但是它有问题并且非常不稳定。

我也注意到,似乎ESP8266一次只能处理一个用户,一旦我尝试从另一台计算机/电话连接它崩溃的服务器,我不得不击中重置按钮以让它在新主机上工作。

有人可以帮助我理解,如果我只是以非常低效的方式使用Ajax或为什么会发生这种情况?

(旧代码删除,以适应新的代码)

编辑: 所以我相信我已经提高了我的代码在两个方面:

  • 我已经修改了上百的client.println()语句,而是将html/css/js内容存储到四个单独的char数组中,然后仅用四个client.println()语句打印出来。

  • 我还通过在一个以逗号分隔的字符串中一次发送所有变量,将ajax调用的数量从五个减少到一个(不包括对应于仍然必要的LED灯)然后我会逐个过滤相应的变量内容。

不过,我仍然经常遇到,但随机ERR_CONNECTION_TIMED_OUT错误,我说随便,因为我最近才得以继续连续成功的Ajax调用了近两个小时成功运行的服务器之前错误消息开始此起彼伏,然后在重新启动服务器后立即在30秒内出现更多错误消息。

在这一点上,我不明白我是否仍然无效地使用ajax,或者这仅仅是由于ESP8266的限制?

#include <ESP8266WiFi.h> 
#include <WiFiClient.h> 
#include <Wire.h> 

WiFiServer server(80); 
WiFiClient client; 
String HTTP_req; 
String req; 
double test = 42; 
String LEDstatus = "off"; 

(Some variable initializations removed for space) 

char webpagePartOne[2500]; 
char webpagePartTwo[2500]; 
char webpagePartThree[2500]; 
char webpagePartFour[2500]; 


void switchLEDon() { 

//Serial.println("TEST LED ON"); 

int ledStatusLength = 1; 

subsys = 0x13; 

//Account for the end of message 
messageLength = ledStatusLength + 2; 

messageContent = 1; 

Serial.write(som); 
Serial.write(messageLength); 
Serial.write(subsys); 
Serial.write(messageContent); 
Serial.write(eom); 
//Serial.println(""); 
//Serial.println("TURN LED ON|"); 
LEDstatus = "on"; 
} //end switchLEDon 

void switchLEDoff() { 
    (almost the same as switchLEDon(), removed to lower char count here) 
} //end switchLEDoff 

void setStatus(WiFiClient cl) { 

currFluid += 22; 

if(currFluid > 100) 
{ 
    currFluid -= 100; 
} 

cl.print(currNumRefresh); 
cl.print(","); 
cl.print(currPressureC); 
cl.print(","); 
cl.print(currPressureD); 
cl.print(","); 
cl.print(currPressureE); 
cl.print(","); 
cl.print(currFluid); 
} 

void setup() { 
    Serial.begin(115200); 

    pinMode(LED_PIN, OUTPUT); 
WiFi.begin(SSID, pass); 
while (WiFi.status() != WL_CONNECTED) 
{ 
delay(500); 
Serial.print("."); 
} 
Serial.println(""); 
Serial.println("WiFi connected"); 

// Start the server 
server.begin(); 
Serial.println("Server started"); 

Serial.println(WiFi.localIP()); 
} 

void loop() { 


//Communication Protocol 
if(Serial.available() > 0) 
{ 
    //Serial.print("SERIAL.AVAILABLE: "); 
    //Serial.println(Serial.available()); 

    //delay(1000); 

    if(initialCounter == 0) 
    { 
     rx_byte = Serial.read(); 
    /* 
     //Print Start of Message 
     Serial.print("0x"); 
     if(rx_byte<0x10) 
     { 
      Serial.print("0"); 
     } 
     Serial.println(rx_byte, HEX); 
    */ 
     //Serial.println(rx_byte, BIN); 
     //Serial.println(rx_byte); 

     initialCounter++; 
    } 


    if((!messageBegun) && (rx_byte == som)) 
    { 
     messageBegun = true; 

     //Serial.println("MESSAGE BEGUN TRUE"); 
    } //end if (messageInProgress && rx_byte) 

    if((messageBegun) && (!messageInProgress)) 
    { 
     serialCurrent = Serial.available(); 

     if(serialCurrent > 0) 
     {  
      receivedMessageLength = (uint8_t)Serial.read(); 
     /* 
      Serial.print("MESSAGE LENGTH: "); 
      Serial.println(receivedMessageLength); 
     */ 
      messageBegun = false; 

      messageInProgress = true; 

      //Serial.println("MESSAGE IN PROGRESS TRUE"); 

     } //end if (serialCurrent) 
    } //end if (messageBegun && messageInProgress) 

    if(messageInProgress) 
    { 
     serialCurrent = Serial.available(); 

     if(serialCurrent >= receivedMessageLength) 
     { 

      Serial.readBytes(rxBuff, receivedMessageLength); 

      if((byte)rxBuff[receivedMessageLength-1] != eom) 
      { 
       //Serial.println("ERROR"); 
       //Serial.write(Serial.read()); 
      } //end if (rxBuff != eom) 

      else 
      { 
       messageInProgress = false; 

       for(int i=0; i<receivedMessageLength; i++) 
       { 
        if(rxBuff[i] == eom) 
        { 
        /* 
         //Print End of Message 
         Serial.print("0x"); 
         if(rx_byte<0x10) 
         { 
          Serial.print("0"); 
         } 
         Serial.println(rxBuff[i], HEX); 
        */ 
         initialCounter = 0; 

         receivedMessageLength = 0; 

        } //end if 

        else if(i == 0) 
        { 
         receivedSubsys = rxBuff[i]; 
        /* 
         //Print Subsystem 
         Serial.print("0x"); 
         if(rx_byte<0x10) 
         { 
          Serial.print("0"); 
         } 
         Serial.println(rxBuff[i], HEX); 
        */ 
        } //end if 
        else 
        { 
         if(receivedSubsys == 0x14) 
         { 
          currNumRefresh = rxBuff[i]; 
         } //end if 

         else if(receivedSubsys == 0x15) 
         { 
          currPressureC = rxBuff[i]; 
         } //end else if 

         else if(receivedSubsys == 0x16) 
         { 
          currPressureD = rxBuff[i]; 
         } //end else if 

         else if(receivedSubsys == 0x17) 
         { 
          currPressureE = rxBuff[i]; 
         } //end else if 

        } //end else 
       } //end for 

      } //end else 

     } //end if (serialCurrent) 

    } //end if (messageInProgress) 
} //end if (Serial.available) 

WiFiClient client = server.available(); 
if (client) { 
    boolean currentLineIsBlank = true; 
    String currentLine = ""; 
    /* 
    if(digitalRead(LED_PIN)) 
    { 
     LEDstatus = "on"; 
    } 
    else if(!digitalRead(LED_PIN)) 
    { 
     LEDstatus = "off"; 
    } 
    */ 
    while (client.connected()) { 
     if (client.available()) { 
      char c = client.read(); 
      HTTP_req += c; 

      if (c == '\n' && currentLineIsBlank) 
      { 
       client.println("HTTP/1.1 200 OK"); 
       client.println("Content-Type: text/html"); 
       client.println("Connection: keep-alive"); 
       client.println(); 

       //LED Functions 
       if (HTTP_req.indexOf("ajax_LED_switch_on") > -1) { 
        switchLEDon(); 
       } 
       else if(HTTP_req.indexOf("ajax_LED_switch_off") > -1) { 
        switchLEDoff(); 
       } 
       else if(HTTP_req.indexOf("ajax_set_status") > -1) { 
        setStatus(client); 
       } 
       else { 

       //Part One 

        strcpy(webpagePartOne,"<!DOCTYPE html>\n"); 
        strcat(webpagePartOne,"<html>\n"); 
         strcat(webpagePartOne,"<head>\n"); 
         strcat(webpagePartOne,"<title>Adafruit HUZZAH ESP8266</title>\n"); 
         strcat(webpagePartOne,"<style type='text/css'>\n"); 

          (css here removed for space) 

         //Part Two 

          (Some more css here removed for space) 

         strcat(webpagePartTwo,"</style>\n"); 
         strcat(webpagePartTwo,"<script>\n"); 

          strcat(webpagePartTwo,"var currPressureTest = 0;\n"); 
          strcat(webpagePartTwo,"var currFluidTest = 0;\n"); 

          //Set Status function 
          strcat(webpagePartTwo,"function setStatus(){\n"); 

           strcat(webpagePartTwo,"nocache = \"&nocache=\"+ Math.random() * 1000000;\n"); 
           strcat(webpagePartTwo,"var request = new XMLHttpRequest();\n"); 
           strcat(webpagePartTwo,"request.onreadystatechange = function() {\n"); 
            strcat(webpagePartTwo,"if (this.readyState == 4) {\n"); 
             strcat(webpagePartTwo,"if (this.status == 200) {\n"); 
              strcat(webpagePartTwo,"if (this.responseText != null) {\n"); 

               strcat(webpagePartTwo,"var totalStatus = this.responseText;\n"); 

               strcat(webpagePartTwo,"var splitStatus = totalStatus.split(',');\n"); 

               //strcat(webpagePartThree,"alert('Pressure C: ' + splitStatus[0] + ', Pressure D: ' + splitStatus[1] + ', Pressure E: ' + splitStatus[2]);\n"); 

               //Num Refresh 
               strcat(webpagePartTwo,"document.getElementById(\"demo\").innerHTML = splitStatus[0];\n"); 

               //PRESSURE C 
               strcat(webpagePartTwo,"var pressureValue = document.querySelector('.gauge-c');\n"); 
               strcat(webpagePartTwo,"pressureValue.style.transform = 'rotate('+ splitStatus[1] +'deg)';\n"); 

               strcat(webpagePartTwo,"var pressureText = (((splitStatus[1])/180)*100).toFixed(0);\n"); 
               strcat(webpagePartTwo,"document.getElementById(\"pressurePercentC\").innerHTML = pressureText + '%';\n"); 

               strcat(webpagePartTwo,"if(pressureText > 75){\n"); 
                strcat(webpagePartTwo,"pressureValue.style.background = 'red';\n"); 
               strcat(webpagePartTwo,"}\n"); 

               strcat(webpagePartTwo,"else if(pressureText > 25 && pressureText < 75){\n"); 
                strcat(webpagePartTwo,"pressureValue.style.background = 'yellow';\n"); 
               strcat(webpagePartTwo,"}\n"); 

               strcat(webpagePartTwo,"else if(pressureText < 25){\n"); 
                strcat(webpagePartTwo,"pressureValue.style.background = 'green';\n"); 
               strcat(webpagePartTwo,"}\n");        

               //PRESSURE D 
               strcat(webpagePartTwo,"var pressureValue = document.querySelector('.gauge-d');\n"); 
               strcat(webpagePartTwo,"pressureValue.style.transform = 'rotate('+ splitStatus[2] +'deg)';\n"); 

               strcat(webpagePartTwo,"var pressureText = (((splitStatus[2])/180)*100).toFixed(0);\n"); 
               strcat(webpagePartTwo,"document.getElementById(\"pressurePercentD\").innerHTML = pressureText + '%';\n"); 

               strcat(webpagePartTwo,"if(pressureText > 75){\n"); 
                strcat(webpagePartTwo,"pressureValue.style.background = 'red';\n"); 
               strcat(webpagePartTwo,"}\n"); 

               strcat(webpagePartTwo,"else if(pressureText > 25 && pressureText < 75){\n"); 
                strcat(webpagePartTwo,"pressureValue.style.background = 'yellow';\n"); 
               strcat(webpagePartTwo,"}\n"); 

               strcat(webpagePartTwo,"else if(pressureText < 25){\n"); 
                strcat(webpagePartTwo,"pressureValue.style.background = 'green';\n"); 
               strcat(webpagePartTwo,"}\n"); 


               //PRESSURE E 
               strcat(webpagePartTwo,"var pressureValue = document.querySelector('.gauge-e');\n"); 
               strcat(webpagePartTwo,"pressureValue.style.transform = 'rotate('+ splitStatus[3] +'deg)';\n"); 

               strcat(webpagePartTwo,"var pressureText = (((splitStatus[3])/180)*100).toFixed(0);\n"); 
               strcat(webpagePartTwo,"document.getElementById(\"pressurePercentE\").innerHTML = pressureText + '%';\n"); 

              //Part Three 

               strcpy(webpagePartThree,"if(pressureText > 75){\n"); 
                strcat(webpagePartThree,"pressureValue.style.background = 'red';\n"); 
               strcat(webpagePartThree,"}\n"); 

               strcat(webpagePartThree,"else if(pressureText > 25 && pressureText < 75){\n"); 
                strcat(webpagePartThree,"pressureValue.style.background = 'yellow';\n"); 
               strcat(webpagePartThree,"}\n"); 

               strcat(webpagePartThree,"else if(pressureText < 25){\n"); 
                strcat(webpagePartThree,"pressureValue.style.background = 'green';\n"); 
               strcat(webpagePartThree,"}\n"); 


               //FLUID LEVEL 
               strcat(webpagePartThree,"var fluidValue = document.querySelector('.fluidMeter');\n"); 
               strcat(webpagePartThree,"fluidValue.value = splitStatus[4];\n"); 

               strcat(webpagePartThree,"var fluidText = splitStatus[4];\n"); 
               strcat(webpagePartThree,"document.getElementById(\"fluidPercent\").innerHTML = fluidText + '%';\n"); 

           strcat(webpagePartThree,"}}}}\n"); 
           strcat(webpagePartThree,"request.open(\"GET\", \"ajax_set_status\" + nocache, true);\n"); 
           strcat(webpagePartThree,"request.send(null);\n"); 

           strcat(webpagePartThree,"setTimeout('setStatus()', 5000);\n"); 

          strcat(webpagePartThree,"}\n"); 

          strcat(webpagePartThree,"function LEDswitch(){\n"); 
           strcat(webpagePartThree,"var LEDswitchCheck = document.getElementById('myonoffswitch').checked;\n"); 

           strcat(webpagePartThree,"if(LEDswitchCheck){\n"); 
            strcat(webpagePartThree,"nocache = \"&nocache=\"+ Math.random() * 1000000;\n"); 
            strcat(webpagePartThree,"var request = new XMLHttpRequest();\n"); 
            strcat(webpagePartThree,"request.onreadystatechange = function() {\n"); 
             strcat(webpagePartThree,"if (this.readyState == 4) {\n"); 
              strcat(webpagePartThree,"if (this.status == 200) {\n"); 
               strcat(webpagePartThree,"if (this.responseText != null) {\n"); 
                //strcat(webpagePartThree,"document.getElementById(\"LEDbtn\").innerHTML = this.responseText;\n"); 
            strcat(webpagePartThree,"}}}}\n"); 
            strcat(webpagePartThree,"request.open(\"GET\", \"ajax_LED_switch_on\" + nocache, true);\n"); 
            strcat(webpagePartThree,"request.send(null);\n"); 
           strcat(webpagePartThree,"}\n"); 
           strcat(webpagePartThree,"else if(!LEDswitchCheck) {\n"); 
            strcat(webpagePartThree,"nocache = \"&nocache=\"+ Math.random() * 1000000;\n"); 
            strcat(webpagePartThree,"var request = new XMLHttpRequest();\n"); 
            strcat(webpagePartThree,"request.onreadystatechange = function() {\n"); 
             strcat(webpagePartThree,"if (this.readyState == 4) {\n"); 
              strcat(webpagePartThree,"if (this.status == 200) {\n"); 
               strcat(webpagePartThree,"if (this.responseText != null) {\n"); 
                //strcat(webpagePartThree,"document.getElementById(\"LEDbtn\").innerHTML = this.responseText;\n"); 
            strcat(webpagePartThree,"}}}}\n"); 
            strcat(webpagePartThree,"request.open(\"GET\", \"ajax_LED_switch_off\" + nocache, true);\n"); 
            strcat(webpagePartThree,"request.send(null);\n"); 
           strcat(webpagePartThree,"}\n"); 
          strcat(webpagePartThree,"}\n"); 
         strcat(webpagePartThree,"</script>\n"); 

        strcat(webpagePartThree,"</head>\n"); 
        strcat(webpagePartThree,"<body style='background-color:#558C89;' onload=\"setStatus();\">\n"); 
         strcat(webpagePartThree,"<div style='background-color:#74AFAD;'>\n"); 
          strcat(webpagePartThree,"<h1 style='text-decoration: underline;'>Adafruit HUZZAH ESP8266</h1>\n"); 
         strcat(webpagePartThree,"</div>\n"); 
         strcat(webpagePartThree,"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n</div>\n<div style=\"clear:both;\"></div><p>\n");      strcat(webpagePartThree,"<div style='background-color:#74AFAD;'>\n"); 
          strcat(webpagePartThree,"<h2 style='color: red;'>LED Controls</h2>\n"); 

          strcat(webpagePartThree,"<div id='LEDbtn' class='onoffswitch'>\n"); 

           /* 
           if (LEDstatus == "on") 
           { 
            strcat(webpagePartThree,"<input type='checkbox' name='onoffswitch' class='onoffswitch-checkbox' id='myonoffswitch' checked='checked' onclick='LEDswitch()'>\n"); 

           } //end if 
           */ 
           /* 
           else if(LEDstatus == "off") 
           {*/ 
            strcat(webpagePartThree,"<input type='checkbox' name='onoffswitch' class='onoffswitch-checkbox' id='myonoffswitch' onclick='LEDswitch()'>\n"); 
           //} //end else 

           strcat(webpagePartThree,"<label class='onoffswitch-label' for='myonoffswitch'>\n"); 
            strcat(webpagePartThree,"<span class='onoffswitch-inner'></span>\n"); 
            strcat(webpagePartThree,"<span class='onoffswitch-switch'></span>\n"); 
           strcat(webpagePartThree,"</label>\n"); 
          strcat(webpagePartThree,"</div>\n"); 
         strcat(webpagePartThree,"</div>\n"); 

         //Part Four 

         strcpy(webpagePartFour,"<div style='background-color:#74AFAD;'>\n"); 
          strcat(webpagePartFour,"<h2 style='color: green;'>Num Refresh Test</h2>\n"); 
          strcat(webpagePartFour,"<div id=\"demo\"><h2>Let AJAX change this text</h2></div>\n"); 
         strcat(webpagePartFour,"</div>\n"); 
        strcat(webpagePartFour,"</div>\n"); 
        //strcat(webpagePartFour,"<div id='gaugeCounter'></div>\n"); 
        strcat(webpagePartFour,"<div class='pressureRow'>\n"); 
         strcat(webpagePartFour,"<div class='pressureContainer'>\n"); 
          strcat(webpagePartFour,"<div class='gauge-a'></div>\n"); 
          strcat(webpagePartFour,"<div class='gauge-b'></div>\n"); 
          strcat(webpagePartFour,"<div class='gauge-c'></div>\n"); 
          strcat(webpagePartFour,"<div class='gauge-data'><h1 id='pressurePercentC'>0%</h1></div>\n"); 
         strcat(webpagePartFour,"</div>\n"); 
         strcat(webpagePartFour,"<div class='pressureContainer'>\n"); 
          strcat(webpagePartFour,"<div class='gauge-a'></div>\n"); 
          strcat(webpagePartFour,"<div class='gauge-b'></div>\n"); 
          strcat(webpagePartFour,"<div class='gauge-d'></div>\n"); 
          strcat(webpagePartFour,"<div class='gauge-data'><h1 id='pressurePercentD'>0%</h1></div>\n"); 
         strcat(webpagePartFour,"</div>\n"); 
         strcat(webpagePartFour,"<div class='pressureContainer'>\n"); 
          strcat(webpagePartFour,"<div class='gauge-a'></div>\n"); 
          strcat(webpagePartFour,"<div class='gauge-b'></div>\n"); 
          strcat(webpagePartFour,"<div class='gauge-e'></div>\n"); 
          strcat(webpagePartFour,"<div class='gauge-data'><h1 id='pressurePercentE'>0%</h1></div>\n"); 
         strcat(webpagePartFour,"</div>\n"); 
        strcat(webpagePartFour,"</div>\n"); 

        strcat(webpagePartFour,"<div class='fluidContainer'>\n"); 
         strcat(webpagePartFour,"<meter class='fluidMeter' max='100' value='50' low='25' high='75' optimum='100'></meter>\n"); 
         strcat(webpagePartFour,"<div class='fluid-data'><h1 id='fluidPercent'>0%</h1></div>\n"); 
        strcat(webpagePartFour,"</div>\n"); 
        strcat(webpagePartFour,"</body>\n"); 
        strcat(webpagePartFour,"</html>"); 

        client.print(webpagePartOne); 
        client.print(webpagePartTwo); 
        client.print(webpagePartThree); 
        client.print(webpagePartFour); 
       } 

      req = HTTP_req;  

      // Serial.print(HTTP_req); 
       HTTP_req = ""; 
       break; 
      } //end if 



     } 
    } 
    delay(100); 
    client.stop(); 
} 
} 
+0

您可以启用串行调试输出?您可以使用'Serial.setDebugOutput(true);'启用基本调试,然后通过Arduino ESP构建选项启用更详细的日志记录 - Core + WiFi可能会这样做。我有客户每周都会从我的基于ESP的设备中抓取大型动态JSON blob,而且没有问题,我记得看到了这些与此相关的_exact_相同的问题。通常情况下,它要达到最大客户端限制,或者没有及时服务缓冲区,或者同样愚蠢的事情。如果是这种情况,你应该看到'LmacRxBlk:1'。或类似的东西 –

+0

谢谢,但我最终找到了另一种解决方案。 –

回答

0

大量的测试所以之后我来到了ESP8266不能处理不断AJAX更新的结论,并最终使用的WebSockets来完成我的任务(其中,迄今为止,似乎是比ajax更稳定的FAR)。

下面是我根据我的结果掉的例子:https://gist.github.com/bbx10/667e3d4f5f2c0831d00b

0

我也注意到,似乎ESP8266只能在一个时间

我的建议去做去尝试,而不是使用Keep-Alive处理上一个用户这可能会导致问题。

client.println("Connection: keep-alive"); 

当您设置Keep-alive其保持连接打开所有的时间,这可能会导致错误。

如果您的服务器例如有一个会话超时这应该保持会话一直活着。

保持活动也有超时和最大请求​​

既然你在一段时间得到这个错误每一次,我认为这是你的超时+最大的问题请求服务器允许接受的保持活跃的连接。

删除并测试它没有它。

+0

我试过了,但不幸的是错误仍然出现:( –

0

尝试使用数据包嗅探器Wireshark和截图结果

+0

谢谢,但我最终找到了另一种解决方案。 –