如何防止Ajaxoverflow/server崩溃? (Arduino/ESP8266 环境)
How to prevent Ajax overflow/server crash? (Arduino/ESP8266 Environment)
我最近一直在学习如何在 Arduino 中编程以在 Adafruit HUZZAH ESP8266 breakout 上托管一个 HTML/CSS/Javascript 网页,所以如果我的方法完全不正确,请原谅我。
我正在使用 Ajax 更新页面上的一些压力表值,它工作了一段时间,但最终我只得到 ERR_CONNECTION_TIMED_OUT
。
我一直都遇到这个问题,尤其是在我刚刚启动服务器时。如果我最终重置 wifi 卡足够多次,它似乎加载得很好但是
这是有问题的,而且非常不稳定。
我还注意到,似乎 ESP8266 一次只能处理一个用户,一旦我尝试从另一个 computer/phone 连接,服务器就会崩溃,我必须点击重置按钮以使其在该新主机上运行。
有人可以帮助我了解我是否只是以非常低效的方式使用 Ajax 或者为什么会这样?
(删除旧代码以适应新代码)
编辑:
所以我相信我已经通过两种方式改进了我的代码:
我修改了数百个 client.println() 语句,而是将 html/css/js 内容存储到四个单独的字符数组中,然后仅在四个 client.println() 语句。
我还通过将所有立即在逗号分隔的字符串中添加变量,然后我分别过滤掉相应的变量内容。
但是,我仍然遇到频繁但随机的 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();
}
}
I've also noticed that it seems that the ESP8266 can only handle one user on it at a time
我的建议是尽量不要使用 Keep-Alive
header,这可能会导致问题。
client.println("Connection: keep-alive");
当您设置 Keep-alive
时,它会一直保持连接打开,这可能会导致错误。
例如,如果您的服务器有 session 超时,这应该使 session 始终保持活动状态。
keep alive也有超时和最大请求数
由于您每隔一段时间就会收到此错误,我认为这是您的超时问题 + 服务器允许在保持活动连接上接受的最大请求。
删除并在没有它的情况下进行测试。
尝试使用数据包嗅探器Wireshark并对结果进行截图
来自:
https://mcuoneclipse.com/2014/11/30/tutorial-web-server-with-the-esp8266-wifi-module/
发送回复后尝试关闭连接:
正在关闭连接:CIPCLOSE
所以事情 正在 工作:-)。诀窍是我必须在发送数据后关闭连接。我可以使用一个 CIPCLOSE 命令:
AT+CIPCLOSE=
我可以用它来关闭频道。所以我关闭了
的连接
AT+CIPCLOSE=0
所以经过大量测试后,我得出的结论是 ESP8266 无法处理持续的 ajax 更新并最终使用 websockets 来完成我的任务(到目前为止,它似乎比ajax 曾经是)。
这是我基于以下结果得出的示例:https://gist.github.com/bbx10/667e3d4f5f2c0831d00b
我最近一直在学习如何在 Arduino 中编程以在 Adafruit HUZZAH ESP8266 breakout 上托管一个 HTML/CSS/Javascript 网页,所以如果我的方法完全不正确,请原谅我。
我正在使用 Ajax 更新页面上的一些压力表值,它工作了一段时间,但最终我只得到 ERR_CONNECTION_TIMED_OUT
。
我一直都遇到这个问题,尤其是在我刚刚启动服务器时。如果我最终重置 wifi 卡足够多次,它似乎加载得很好但是 这是有问题的,而且非常不稳定。
我还注意到,似乎 ESP8266 一次只能处理一个用户,一旦我尝试从另一个 computer/phone 连接,服务器就会崩溃,我必须点击重置按钮以使其在该新主机上运行。
有人可以帮助我了解我是否只是以非常低效的方式使用 Ajax 或者为什么会这样?
(删除旧代码以适应新代码)
编辑: 所以我相信我已经通过两种方式改进了我的代码:
我修改了数百个 client.println() 语句,而是将 html/css/js 内容存储到四个单独的字符数组中,然后仅在四个 client.println() 语句。
我还通过将所有立即在逗号分隔的字符串中添加变量,然后我分别过滤掉相应的变量内容。
但是,我仍然遇到频繁但随机的 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();
}
}
I've also noticed that it seems that the ESP8266 can only handle one user on it at a time
我的建议是尽量不要使用 Keep-Alive
header,这可能会导致问题。
client.println("Connection: keep-alive");
当您设置 Keep-alive
时,它会一直保持连接打开,这可能会导致错误。
例如,如果您的服务器有 session 超时,这应该使 session 始终保持活动状态。
keep alive也有超时和最大请求数
由于您每隔一段时间就会收到此错误,我认为这是您的超时问题 + 服务器允许在保持活动连接上接受的最大请求。
删除并在没有它的情况下进行测试。
尝试使用数据包嗅探器Wireshark并对结果进行截图
来自: https://mcuoneclipse.com/2014/11/30/tutorial-web-server-with-the-esp8266-wifi-module/
发送回复后尝试关闭连接:
正在关闭连接:CIPCLOSE
所以事情 正在 工作:-)。诀窍是我必须在发送数据后关闭连接。我可以使用一个 CIPCLOSE 命令:
AT+CIPCLOSE= 我可以用它来关闭频道。所以我关闭了
的连接AT+CIPCLOSE=0
所以经过大量测试后,我得出的结论是 ESP8266 无法处理持续的 ajax 更新并最终使用 websockets 来完成我的任务(到目前为止,它似乎比ajax 曾经是)。
这是我基于以下结果得出的示例:https://gist.github.com/bbx10/667e3d4f5f2c0831d00b