Arduino +ESP8266 发送 POST 一次但每隔一次就失败
Arduino +ESP8266 sending POST once but fails every other time
我将 esp8266 与我的 arduino Mega 一起使用,并使用 AT 命令通过串行控制它(我知道这不是使用 ESP 的最佳方式,但我不知道如何使用其他方式)。 ..所以我的问题是我制定了我的 POST 请求并发送到我的网页....第一次尝试时它工作正常,但之后,在每次循环尝试中,它都失败了......请可以有人检查我的代码,看看您是否能找到可能导致此问题的错误?
这是我发送数据的函数:
void SendData(){
cmd = "AT+CIPSTART=\"TCP\",\"";
cmd+= server;
cmd+="\",80";
Serial1.println(cmd);
Serial.println(cmd);
delay(1000);
if(Serial1.find("OK"))
{
Serial.println("\r\nReady to send data!");
}
String retazec="cz="+cas_zaznamu; ////DATA from sensors etc.
retazec=retazec+"&tep="+t;
retazec=retazec+"&vlhv="+vv;
retazec=retazec+"&vlhp="+vp;
retazec=retazec+"&zav="+za;
retazec=retazec+"&kur="+ku;
retazec=retazec+"&vet="+ve;
retazec=retazec+"&pz="+datum_zavlaha;
int retazec_len=retazec.length();
retazec.toCharArray(retaz,70);
cmd = "POST /arduino.php"; ////POST request
cmd+=" HTTP/1.1\r\n";
cmd+="Host: myhost.com\r\n";
cmd+="Content-Type: application/x-www-form-urlencoded\r\n";
cmd+="Connection:Close\r\n";
cmd+="Content-Length: ";
cmd+=retazec_len;
cmd+="\r\n\r\n";
int size=cmd.length()+retazec_len+2;
Serial1.print("AT+CIPSEND=");
Serial1.println(size);
Serial.print("AT+CIPSEND=");
Serial.println(size);
delay(2000);
if (Serial1.find(">")){
Serial.println("Sending data...");
} else {
Serial1.println("AT+CIPCLOSE");
Serial.println("COnnection closed");
return;
}
Serial.print(cmd);
Serial1.print(cmd);
for(int i=0;i<=retazec_len;i++){
Serial.print(retaz[i]);
Serial1.print(retaz[i]);
}
Serial1.print("\r\n");
if(Serial1.find("OK"))
{
Serial.println("Succesfuly send!");
}
ReadString(); /// emptying the buffer by reading serial1
delay(5000);
Serial.println("-----end");
}
此外,我对 GET 请求有不同的功能,与上面的非常相似,并且连续多次工作(不想说每次 bcs 它只 运行 几分钟) .
如有任何建议,我们将不胜感激。 :)
我受过教育的 guess:The String class 结合 at 命令
尝试在基于 web 的场景中摆脱 String class。原因:您想长期拥有一个稳定的环境运行。 String class 使用堆内存来动态构建和销毁它所需的底层结构,例如追加字符串(... = .. + .. + ..)。由于没有所谓的垃圾收集(并且无论如何都没有足够的内存),相对较小的内存被切成小单元,其中(在一定长度上)字符串不再适合 -> 崩溃,重置 => 丢失 POST 或 GET 请求。
使用固定的全局字符数组来构建您的消息,这些消息被编译到闪存中并停止 "memory bleeding"。
附上示例 (虽然我不明白 - 从你的语言 - 变量的名称或内容并且没有给出我不得不猜测的类型)
char retazec[256] = {'[=10=]'}; /* Defined globally - Used for retazec functions max 255 chars */
char cmd[512] = {'[=10=]'}; /* Defined globally - Used for POST/GET functions max 511 chars */
char numBuffer[16] = {'[=10=]'}; /* Defined globally - Used for uint32_t or smaller number conversions to char */
unsigned long timeStamp = 0;
unsigned long delayTime = 2000;
setup(){...}
//The parts you gave "translated"into char manuipulation
const char* cmdStart[] = "POST /arduino.php HTTP/1.1\r\n Host: myhost.com\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection:Close\r\nContent-Length: ";
const char* cmdEnd[] = "\r\n\r\n";
strcpy (retazec, "cz=");
itoa(cas_zaznamu, numBuffer, 10); // convert int DATA from sensors etc.
// If its a float use this command
// dtostrf(floatvar, StringLengthIncDecimalPoint, numVarsAfterDecimal, charbuf);
// dtostrf(cas_zaznamu, 3, 2, numBuffer); // -> xx.xx
strcat(retazec, numBuffer);
strcat(retazec, "&tep=");
itoa(t, numBuffer, 10);
// or dtostrf(t, 4, 2, numBuffer); // -> xxx.xx
strcat(retazec, numBuffer);
strcat(retazec, "&vlhv=");
....
// ... till datum_zavlaha;
int retazec_len=strlen(retazec); // gives you the length
// not needed we have a char array allready retazec.toCharArray(retaz,70);
strcpy(cmd, cmdStart);
iota (retazec_len, numBuffer);
strcat(cmd, numBuffer);
strcat(cmd, cmdEnd);
int size=strlen(cmd)+retazec_len+2;
if (millis() - timeStamp > delayTime) {
Serial1.print("AT+CIPSEND=");
Serial1.println(size);
Serial.print("AT+CIPSEND=");
Serial.println(size);
timeStamp = millis();
}
// NO NEVER delay(2000);
if (Serial1.find(">")){
Serial.println("Sending data...");
} else {
Serial1.println("AT+CIPCLOSE");
Serial.println("COnnection closed");
return;
}
第二个问题是延迟(它停止处理死在它的轨道上)所以 cpu 在你的情况下等待 2 秒然后重新启动 - 在使用通信协议时不是一个聪明的主意。我实现了一个非阻塞延迟——如果你在其他地方需要它,正如我所说,你只提供了代码片段
编辑 OP 反馈后
在动态通信场景中应避免将字符串 class 作为一个整体,因此在程序的所有部分。
我是否应该使用一个大字符串(小 s = char 数组)来应对原始代码的作用但不是带有 char 数组的 String。
所以恕我直言,结构只需要适应 char 数组而无需大的更改(除了明确地将数字转换为 char)顺便说一句,当您将变量添加到 String
uint8_t aNumber = 12;
String myBigString = "A number is " + aNumber;
在字符串库内部与
相同
uint8_t aNumber = 12;
char numBuffer [16] = {'[=12=]'} ;
char myBigString [32] = {'[=12=]'} ;
strcpy (myBigString, "A number is ");
iota (aNumber, numBuffer, 10);
strcat (myBigString, numBuffer);
不同之处在于 - 您编写代码行而不是懒洋洋地使用错误的库,但可以完全控制内存以及将其编译为闪存的优势,从而节省内存。 Const char 实际上是通过指针调用的——所以稍后有一些函数可以只获取数组的某些部分,以便从一个大数组中创建变量消息。
在对 github 进行代码分析后,有另一个大问题:阻塞延迟()的使用:
loop() {
delay(1000);
// lot of code
delay(3000);
}
替换为非阻塞延迟
无符号长时间戳 = 0;
setup(){}
loop() {
if (millis() - timeStamp > 4000) {
// lot of code
timeStamp = millis(); // reset the timer
}
}
并如前所述删除所有字符串(例如)
///////////PREMENNE PRIJIMANÝCH ÚDAJOV///////
String mode;
String inzavlaha;
String inkurenie;
String invetranie;
String invlhkost_p;
String invlhkost_v;
String incas;
String intrvanie;
String inopakovanie;
String inteplota;
最后 tio.If 如果您需要全球范围的帮助,请开始用英语编写您的所有程序(变量和注释),这样更容易获得帮助。
我将 esp8266 与我的 arduino Mega 一起使用,并使用 AT 命令通过串行控制它(我知道这不是使用 ESP 的最佳方式,但我不知道如何使用其他方式)。 ..所以我的问题是我制定了我的 POST 请求并发送到我的网页....第一次尝试时它工作正常,但之后,在每次循环尝试中,它都失败了......请可以有人检查我的代码,看看您是否能找到可能导致此问题的错误?
这是我发送数据的函数:
void SendData(){
cmd = "AT+CIPSTART=\"TCP\",\"";
cmd+= server;
cmd+="\",80";
Serial1.println(cmd);
Serial.println(cmd);
delay(1000);
if(Serial1.find("OK"))
{
Serial.println("\r\nReady to send data!");
}
String retazec="cz="+cas_zaznamu; ////DATA from sensors etc.
retazec=retazec+"&tep="+t;
retazec=retazec+"&vlhv="+vv;
retazec=retazec+"&vlhp="+vp;
retazec=retazec+"&zav="+za;
retazec=retazec+"&kur="+ku;
retazec=retazec+"&vet="+ve;
retazec=retazec+"&pz="+datum_zavlaha;
int retazec_len=retazec.length();
retazec.toCharArray(retaz,70);
cmd = "POST /arduino.php"; ////POST request
cmd+=" HTTP/1.1\r\n";
cmd+="Host: myhost.com\r\n";
cmd+="Content-Type: application/x-www-form-urlencoded\r\n";
cmd+="Connection:Close\r\n";
cmd+="Content-Length: ";
cmd+=retazec_len;
cmd+="\r\n\r\n";
int size=cmd.length()+retazec_len+2;
Serial1.print("AT+CIPSEND=");
Serial1.println(size);
Serial.print("AT+CIPSEND=");
Serial.println(size);
delay(2000);
if (Serial1.find(">")){
Serial.println("Sending data...");
} else {
Serial1.println("AT+CIPCLOSE");
Serial.println("COnnection closed");
return;
}
Serial.print(cmd);
Serial1.print(cmd);
for(int i=0;i<=retazec_len;i++){
Serial.print(retaz[i]);
Serial1.print(retaz[i]);
}
Serial1.print("\r\n");
if(Serial1.find("OK"))
{
Serial.println("Succesfuly send!");
}
ReadString(); /// emptying the buffer by reading serial1
delay(5000);
Serial.println("-----end");
}
此外,我对 GET 请求有不同的功能,与上面的非常相似,并且连续多次工作(不想说每次 bcs 它只 运行 几分钟) .
如有任何建议,我们将不胜感激。 :)
我受过教育的 guess:The String class 结合 at 命令
尝试在基于 web 的场景中摆脱 String class。原因:您想长期拥有一个稳定的环境运行。 String class 使用堆内存来动态构建和销毁它所需的底层结构,例如追加字符串(... = .. + .. + ..)。由于没有所谓的垃圾收集(并且无论如何都没有足够的内存),相对较小的内存被切成小单元,其中(在一定长度上)字符串不再适合 -> 崩溃,重置 => 丢失 POST 或 GET 请求。
使用固定的全局字符数组来构建您的消息,这些消息被编译到闪存中并停止 "memory bleeding"。
附上示例 (虽然我不明白 - 从你的语言 - 变量的名称或内容并且没有给出我不得不猜测的类型)
char retazec[256] = {'[=10=]'}; /* Defined globally - Used for retazec functions max 255 chars */
char cmd[512] = {'[=10=]'}; /* Defined globally - Used for POST/GET functions max 511 chars */
char numBuffer[16] = {'[=10=]'}; /* Defined globally - Used for uint32_t or smaller number conversions to char */
unsigned long timeStamp = 0;
unsigned long delayTime = 2000;
setup(){...}
//The parts you gave "translated"into char manuipulation
const char* cmdStart[] = "POST /arduino.php HTTP/1.1\r\n Host: myhost.com\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection:Close\r\nContent-Length: ";
const char* cmdEnd[] = "\r\n\r\n";
strcpy (retazec, "cz=");
itoa(cas_zaznamu, numBuffer, 10); // convert int DATA from sensors etc.
// If its a float use this command
// dtostrf(floatvar, StringLengthIncDecimalPoint, numVarsAfterDecimal, charbuf);
// dtostrf(cas_zaznamu, 3, 2, numBuffer); // -> xx.xx
strcat(retazec, numBuffer);
strcat(retazec, "&tep=");
itoa(t, numBuffer, 10);
// or dtostrf(t, 4, 2, numBuffer); // -> xxx.xx
strcat(retazec, numBuffer);
strcat(retazec, "&vlhv=");
....
// ... till datum_zavlaha;
int retazec_len=strlen(retazec); // gives you the length
// not needed we have a char array allready retazec.toCharArray(retaz,70);
strcpy(cmd, cmdStart);
iota (retazec_len, numBuffer);
strcat(cmd, numBuffer);
strcat(cmd, cmdEnd);
int size=strlen(cmd)+retazec_len+2;
if (millis() - timeStamp > delayTime) {
Serial1.print("AT+CIPSEND=");
Serial1.println(size);
Serial.print("AT+CIPSEND=");
Serial.println(size);
timeStamp = millis();
}
// NO NEVER delay(2000);
if (Serial1.find(">")){
Serial.println("Sending data...");
} else {
Serial1.println("AT+CIPCLOSE");
Serial.println("COnnection closed");
return;
}
第二个问题是延迟(它停止处理死在它的轨道上)所以 cpu 在你的情况下等待 2 秒然后重新启动 - 在使用通信协议时不是一个聪明的主意。我实现了一个非阻塞延迟——如果你在其他地方需要它,正如我所说,你只提供了代码片段
编辑 OP 反馈后
在动态通信场景中应避免将字符串 class 作为一个整体,因此在程序的所有部分。
我是否应该使用一个大字符串(小 s = char 数组)来应对原始代码的作用但不是带有 char 数组的 String。
所以恕我直言,结构只需要适应 char 数组而无需大的更改(除了明确地将数字转换为 char)顺便说一句,当您将变量添加到 String
uint8_t aNumber = 12;
String myBigString = "A number is " + aNumber;
在字符串库内部与
相同uint8_t aNumber = 12;
char numBuffer [16] = {'[=12=]'} ;
char myBigString [32] = {'[=12=]'} ;
strcpy (myBigString, "A number is ");
iota (aNumber, numBuffer, 10);
strcat (myBigString, numBuffer);
不同之处在于 - 您编写代码行而不是懒洋洋地使用错误的库,但可以完全控制内存以及将其编译为闪存的优势,从而节省内存。 Const char 实际上是通过指针调用的——所以稍后有一些函数可以只获取数组的某些部分,以便从一个大数组中创建变量消息。
在对 github 进行代码分析后,有另一个大问题:阻塞延迟()的使用:
loop() {
delay(1000);
// lot of code
delay(3000);
}
替换为非阻塞延迟 无符号长时间戳 = 0;
setup(){}
loop() {
if (millis() - timeStamp > 4000) {
// lot of code
timeStamp = millis(); // reset the timer
}
}
并如前所述删除所有字符串(例如)
///////////PREMENNE PRIJIMANÝCH ÚDAJOV///////
String mode;
String inzavlaha;
String inkurenie;
String invetranie;
String invlhkost_p;
String invlhkost_v;
String incas;
String intrvanie;
String inopakovanie;
String inteplota;
最后 tio.If 如果您需要全球范围的帮助,请开始用英语编写您的所有程序(变量和注释),这样更容易获得帮助。