【问题标题】:Global variable assigned inside while loop not available outside the loop在while循环内分配的全局变量在循环外不可用
【发布时间】:2017-01-03 05:37:04
【问题描述】:

我正在使用 ESP8266 WiFi 芯片调用 api。我声明了一个全局变量来分配服务器发送的令牌给它。变量赋值是在一个while循环内进行的。在这个循环中,我正在读取回复“令牌”的内容并将其保存在全局变量中。 但是当我在while循环之外打印出结果到变量时是空的。但在循环内部却不是。

String deviceToken;

WiFiClient client;

  if (!client.connect(hostIp, 80)){
    Serial.println("Connection to server failed.");
    Serial.print(client.connect(hostIp, 80));
    return;
  }

    String authURL = "/api/";
      authURL += "startauth/";
      authURL += serialValue;
      Serial.print("Requesting URL: ");
      Serial.println(authURL);

      // This will send auth request to the server
      client.print(String("GET ") + authURL + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" + 
                   "Connection: close\r\n\r\n");
     unsigned long timeout = millis();
     while (client.available() == 0) {
        if (millis() - timeout > 5000) {
          Serial.println(">>> Client Timeout !");
          client.stop();
          return;
        }
     }
    // Read Auth reply from server and print them to Serial
      while(client.available()){
        String token = client.readStringUntil('\r');
        deviceToken = token;
        writeDeviceToken(token.c_str());  //Function to write data in eeprom
        Serial.print(deviceToken); //NOT EMPTY
      }

      Serial.print("Device Token:" + deviceToken);  //EMPTY VARIABLE

【问题讨论】:

  • 确定 deviceToken 在最后一次迭代中不是空的吗?您能否在最后有效地调用Serial.print("") 一次或多次,从而导致此问题?
  • @Phylogenesis 是的,这似乎是我删除令牌打印后删除了“0”的问题。

标签: while-loop scope arduino esp8266


【解决方案1】:

在您的 while 循环中,您将逐行遍历 HTTP 标头和数据,并且每次都覆盖 deviceToken。这没关系,除了每一行都以\r\n 结尾,而不仅仅是\r - (另外,您可能只想将令牌写入eeprom,而不是每个标题)。

所以最后被读取的令牌是单个\n,然后将其放入deviceToken。您需要在每一行之后读取额外的字节。

另一种方法是读取直到到达\r\n\r\n(标题块的末尾),然后读取大小(28 hex - 这是chunked transfer),然后您可以读取并存储您想要的令牌.否则,您的令牌将是最后一个 0,或者它后面的换行符。

另外请记住,不能保证回复总是被分块(在这种情况下实际上很奇怪),您也应该为“正常”回复做好准备。

解决此问题的一种简单方法是发送HTTP/1.0 请求而不是HTTP/1.1(只要该服务器支持)。由于HTTP/1.0 不支持/不允许分块传输,您将始终在回复中使用“干净”deviceToken

【讨论】:

  • 这就是我一直在等待的答案。谢谢。我现在尝试做的是使用'\ n'。并删除了循环外的 writingToEEPROM。我认为它是这样工作的。令牌被添加到下一个 url 字符串中以进行新的 api 调用。但不幸的是,我收到了 400 个错误请求。我在邮递员的序列号上测试了打印的网址,它工作正常。
  • @KeghamK。您的令牌现在可能有一个尾随 \r,这可能会导致错误的请求。
  • @KeghamK。改用HTTP/1.0 可能会更好/更容易 - 请参阅更新的答案。
  • 感谢 HTTP/1.0 部分,我将与服务器开发人员核实,看看他的服务器是否支持 1.0
  • @KeghamK。您可以通过将代码中的 HTTP/1.1 更改为 HTTP/1.0 来快速检查。几乎所有的服务器都应该支持。
【解决方案2】:

感谢 Danny_ds 的说明,我能够解决我的问题并考虑在此处分享工作代码作为参考。

// Read Auth reply from server and print them to Serial
  while(client.available()){

      char c = client.read(); 
      response += c;
  }
   String testStatus = response;
   if((strstr(testStatus.c_str(),"HTTP/1.1 500")) != NULL) {
    Serial.println("Found reponse 500");
    return;

   } else if ((strstr(testStatus.c_str(),"HTTP/1.1 200")) != NULL) {
      Serial.println("Found reponse 200");
      //Grabing the token after the header
      String token = response.substring(response.indexOf("\r\n\r\n") + 8 );
      //Removing the \r in end of token
      token.remove(40);
      deviceToken = token;
      writeDeviceToken(deviceToken.c_str());
      delay(500);
      Serial.print("Device Token:" + deviceToken);
      return;
   }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 2019-11-07
    相关资源
    最近更新 更多