我正在制作一个小项目,它向网络服务器发出一些 POST 请求,并根据服务器响应执行一些任务。服务器始终使用 JSON 或数组进行响应
来自服务器的 clasic 响应如下所示:
POST /app_dev.php/api/?XDEBUG_SESSION_START=vagrant HTTP/1.1
Host: XXXXXX.vagrant:8080
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: 37fddefd-e120
id=594cdf2c962d740c2b1dac22&identifier=594cdf2c962d740c2b1dac22
问题是,经过 4 个小时的完美运行,我的 arduino mega 运行得非常非常慢。第一次,检索命令并执行任务(打开 LED 电源(只需 10-20 毫秒。现在,4 小时后,为同一 LED 供电大约需要 5 秒。我看到以太网指示灯缓慢闪烁。我猜是因为我使用了一些常量字符*来存储服务器响应。 我的问题是,在循环函数结束时,像 const char* 这样的变量被删除了? 几个小时后,我的 arduino 运行得这么慢是什么?谢谢
循环运行的代码函数:
void loop () {
dataReceived = 0;
apiResponseReceived = 1;
apiCommandsResponseReceived = 1;
sendConfirmationCommand = 0;
checkForConfirmationResponse = 0;;
payloadData dataPacket,dataBuffer;
tmElements_t tm;
RTC.read(tm);
Serial.print("some things ");
Serial.println(queueEncrypted.count());
Serial.print("some things");
Serial.println(queueDecrypted.count());
printf_P(PSTR("Free ram: %d"),freeRam());
if(apiCommandsResponseReceived == 1) {
Serial.print("flag message");
byte check = stash.create();
stash.print("identifier=");
stash.print("8234nsda987123");
stash.save();
int stash_size = stash.size();
Stash::prepare(PSTR("POST http://$F/$F HTTP/1.0" "rn"
"Host: $F" "rn"
"Connection: close" "rn"
"Content-Type: application/x-www-form-urlencoded" "rn"
"Content-Length: $D" "rn"
"rn"
"$H"),
website,readCommands,website, stash_size, check);
// send the packet - this also releases all stash buffers once done
sessionDoi = ether.tcpSend();
int freeCount = stash.freeCount();
if (freeCount <= 3) {
Stash::initMap(56);
}
apiCommandsResponseReceived = 0;
}
long timeCommand = millis();
while(millis()- timeCommand < 5000) {
word len = ether.packetReceive(); // go receive new packets
word pos = ether.packetLoop(len); // respond to incoming pings
const char* reply2 = ether.tcpReply(sessionDoi);
StaticJsonBuffer<200> jsonBuffer;
Serial.print("flag message");
if (reply2 != 0) {
Serial.println(F(" >>>REPLY recieved...."));
Serial.println(reply2);
reply2 = removeHTTPHeader(reply2);
Serial.println("------HEADER REMOVED-----");
Serial.println(reply2);
JsonObject& root = jsonBuffer.parseObject(reply2);
if (root.success()) {
const char* id = root["id"];
strcpy(global_ID_command,id);
const char* command = root["command"];
const char* value = root["value"];
Serial.print("id: ");
Serial.println(id);
Serial.print("id glabal: ");
Serial.println(global_ID_command);
Serial.print("comanda: ");
Serial.println(command);
Serial.print("flag message");
Serial.print(value);
int comanda = atoi(value);
if(comanda == 1){
Serial.print("e 1");
digitalWrite(error_ETH,HIGH);
}
if(comanda == 0 ){
Serial.print("e 0");
digitalWrite(error_ETH,LOW);
}
sendConfirmationCommand = 1;
}
else {
Serial.println("flag message");
}
if (strstr(reply2,success)) {
Serial.println("flag message");
}
apiCommandsResponseReceived = 1;
jsonBuffer.clear();
break;
}
}
pingSite(ether.hisip, 1, 500);
if(sendConfirmationCommand == 1) {
Serial.print("flag message");
byte response = stash.create();
stash.print("response%5Bcommand%5D=");
stash.print(global_ID_command);
stash.print("&response%5Bcurrent_state%5D=");
stash.print("ON");
stash.print("&response%5Bsuccess%5D=");
stash.print("true");
stash.save();
int stash_size = stash.size();
Stash::prepare(PSTR("POST http://$F/$F HTTP/1.0" "rn"
"Host: $F" "rn"
"Connection: close" "rn"
"Content-Type: application/x-www-form-urlencoded" "rn"
"Content-Length: $D" "rn"
"rn"
"$H"),
website,executeCommands,website, stash_size, response);
// send the packet - this also releases all stash buffers once done
sessionTrei = ether.tcpSend();
int freeCount = stash.freeCount();
if (freeCount <= 3) {
Stash::initMap(56);
}
sendConfirmationCommand = 0;
checkForConfirmationResponse = 1;
}
if(checkForConfirmationResponse == 1){
long timeExecute = millis();
while(millis()- timeExecute < 5000) {
word len = ether.packetReceive(); // go receive new packets
word pos = ether.packetLoop(len); // respond to incoming pings
const char* reply3 = ether.tcpReply(sessionTrei);
Serial.print("flag message");
if (reply3 != 0) {
Serial.println(F(" >>>REPLY recieved...."));
Serial.println(reply3);
reply3 = removeHTTPHeader(reply3);
Serial.println("------HEADER REMOVED-----");
Serial.println(reply3);
if (strstr(reply3,success)) {
Serial.println("flag message");
}
checkForConfirmationResponse = 0;
break;
}
}
}
从 tcp 响应中删除标头的函数
char *removeHTTPHeader(char *buffer) {
char *t = strstr(buffer, "rnrn");
t = t + 4;
return t;
}
这闻起来像经典的动态内存抖动问题。 你没有说你正在使用什么以太网库,所以我不会冒险猜测他们是否正在使用malloc
等。
我可以说 JSON 库不使用动态内存,所以我怀疑速度减慢与解析响应有任何关系。
如果没有完整的代码集,我建议尽可能多地释放RAM,以减轻malloc
对内存的"搜索"。 最大的罪魁祸首是您使用双引号字符串常量。 用F
宏包装print
的所有字符串文本:
Serial.print( F("comanda: ") );
你为一些人做了这件事,但不是全部。 此外,JSON 库似乎支持使用 FLASH 字符串,因此请将所有引用更改为:
const char* command = root[ F("command") ];
这不会在 JSON 对象本身中节省任何内存,但会保存该标识符的 RAM。
这可能只会延长您可以运行的时间。
之后,您可能需要查看以太网/存储代码中的功能,以确定是否可以限制对堆分段的调用的使用。 如果没有明显的问题,您可能需要使用看门狗计时器在预定时间后强制重置。
嵌入式系统中的动态内存是的。 -_-