0

我正在做一个小项目,向网络服务器发出一些 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 运行非常缓慢。第一次,只需 10-20 毫秒即可检索命令并执行任务(打开 LED 电源)。现在,4 小时后,为同一个 LED 供电大约需要 5 秒。我看到以太网指示灯正在缓慢闪烁。我猜是因为我使用了一些 const char* 来存储服务器响应。我的问题是,在循环函数的末尾,像 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" "\r\n"
      "Host: $F" "\r\n"
      "Connection: close" "\r\n"
      "Content-Type: application/x-www-form-urlencoded" "\r\n"
      "Content-Length: $D" "\r\n"
      "\r\n"
      "$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" "\r\n"
      "Host: $F" "\r\n"
      "Connection: close" "\r\n"
      "Content-Type: application/x-www-form-urlencoded" "\r\n"
      "Content-Length: $D" "\r\n"
      "\r\n"
      "$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, "\r\n\r\n");
    t = t + 4;
    return t;
}
4

1 回答 1

0

这闻起来像经典的动态内存抖动问题。你没有说你正在使用什么以太网库,所以我不会冒险猜测他们是否正在使用malloc等。

我可以说 JSON 库不使用动态内存,所以我怀疑减速与解析响应有什么关系。

如果没有完整的代码集,我建议尽可能多地释放 RAM,以减轻malloc. 最大的罪魁祸首是您使用双引号字符串常量。printF宏包装所有字符串文字:

Serial.print( F("comanda: ") );

你这样做是为了一些,但不是全部。此外,JSON 库似乎支持使用 FLASH 字符串,因此将所有引用更改为:

const char* command = root[ F("command") ];

这不会在 JSON 对象本身中保存任何内存,但会为该标识符保存 RAM。

这可能只会延长您可以运行的时间。

之后,您可能想查看以太网/存储代码中的哪些功能,以确定您是否可以限制使用对堆进行分段的调用。如果没有明显的问题,您可能需要使用看门狗定时器在预定时间后强制重置。

是的,嵌入式系统中的动态内存。-_-

于 2017-07-04T00:06:30.380 回答