2

我正在尝试为 Arduino Uno WiFi Rev2 板编写一些代码。具体来说,我想使用 POST HTTP 请求将一些数据发送到我编写的 API 端点。我已经用 Postman 测试了这个端点,它工作正常。但是,当我尝试使用 WiFiNina 库 ( https://www.arduino.cc/en/Reference/WiFiNINA ) 发布我的数据时,请求永远不会到达我的端点。

我的 Arduino 草图包含两个文件。第一个是我的“主”文件,它充当我的代码的入口点并处理我的代码的大部分功能。在这个文件中,我按照 Arduino 文档中的说明设置了 WiFiClient:

#define URL "myappdomain.azurewebsites.net"
...
WiFiClient client;
int status = WL_IDLE_STATUS;
...
void setup(){
...
status = WiFi.begin(WifiSSID, WifiPassword);

  while (WiFi.status() != WL_CONNECTED) {  //Wait for the WiFI connection completion
    delay(500);
    Serial.println("Waiting for connection");
  }
...
}
...

void loop(){
...
String requestBody = 
    "{\n    \"clientReadings\": {\n        \"sensorA\": [],\n        \"sensorB\": []\n    },\n    \"deviceId\": 1,\n    \"millilitersConsumed\" : 999\n}";

//send the request
postData(requestBody);
...
}

在我的第二个文件中,这是处理此 API 请求的代码部分:

void postData(String body){
  if(WiFi.status()== WL_CONNECTED){   //Check WiFi connection status

     if (client.connect(URL, 80)){
        client.println("POST /api/PGWC HTTP/1.1"); 
        client.print("Host: ");
        client.println(URL);
        client.println("Content-type: application/json");
        client.println("Accept: */*");
        client.println("Cache-Control: no-cache");
        client.print("Host: ");
        client.println(URL);
        client.println("Accept-Encoding: gzip, deflate");
        client.print("Content-Length: ");
        client.println(body.length());
        client.println("Connection: close");
        client.println();
        client.println(body);
     }else{
      Serial.println("Error connecting to server");
     }
  }
}

我根据我在网上找到的 WiFiNina 库的示例和文档构建了这个请求。(这里有一个例子:https ://www.arduino.cc/en/Reference/WiFiNINAClient )。标头信息和正文基于我通过 Postman 发送的请求,因此我相信我的请求内容是准确的。我相信我能够通过“client.connect”行连接到服务器,因为我从未看到错误消息打印到串行监视器,但我看到串行监视器显示“Serial.println”语句的内容我放在我的“client.println”语句之前。但是,托管 API 终结点的 Azure Function App 没有显示 API 终结点被命中的迹象。当我用 Postman 发送相同的数据时,

当我尝试从 postData 函数中将正文、URL 和 body.length() 的内容打印到串行监视器时,一切都按预期显示。此外,我在“连接:关闭”行尝试了不同的选项,但无济于事。

作为参考,这是 Postman 在成功访问 API 端点时告诉我它正在发送的内容。我也尝试过端口 443。它在 Postman 中运行良好,但在 Arduino 中又不行。

Host: myappdomain.azurewebsites.net:80
Content-Type: application/json
User-Agent: PostmanRuntime/7.17.1
Accept: */*
Cache-Control: no-cache
Postman-Token: [some UUID, some other UUID]
Host: myappdomain.azurewebsites.net:80
Accept-Encoding: gzip, deflate
Content-Length: 130
Connection: keep-alive
cache-control: no-cache

{
    "clientReadings": {
        "sensorA": [],
        "sensorB": []
    },
    "deviceId": 1,
    "millilitersConsumed" : 123
}```

(I've changed the domain for this post, so this request won't work if you try to plug it into Postman because myappdomain.azurewebsites.net is not my real domain)

4

1 回答 1

0

编辑:想通了。

原来wifi.println("Content-Length: " + body.length());

不一样wifi.println("Content-Length: " + String(body.length()));

正文长度 var 需要包装为字符串,然后它可以正常工作

让我感到困惑的是看到 OP 把它写成

wifi.print("Content-Length: ");
wifi.println(body.length());

我不认为它需要被包装为一个字符串,但我猜当连接字符串时它是不同的。

也很奇怪我需要这个标题开始(REST应用程序不需要它工作)并具有正确的主体值,使用类似 200 导致连接挂起(但在 REST 应用程序上将其设置为像200这样的通用也可以正常工作)

END EDIT ...留下原始内容以供参考

我也想弄清楚这一点,所以这是一个扩展评论而不是答案。

当我使用像邮递员(休息)这样的应用程序时,它可以工作我得到 200 个响应,但是从 arduino uno wifi rev2 它失败了HTTP/1.1 422 Unprocessable Entity {"reason":"Unprocessable Entity","error":true}

我的json只是String body = "{\n \"value\": 500\n}";

和里面if (wifi.connect(serverAddress, port)) {

我打电话

void postData(String body) {
// send HTTP request header
wifi.println("POST /gardener/Douglas/George/water HTTP/1.1");
wifi.println("Host: " + String(serverAddress));
wifi.println("Content-Type: application/json");
wifi.println("Accept: */*");
wifi.println("Cache-Control: no-cache");
wifi.println("Accept-Encoding: gzip, deflate");
wifi.println("Accept-Language: en-us");
wifi.println("Content-Length: " + body.length()); //ANSWER: body.length() needs to be wrapped as a string, see above
wifi.println("Connection: close");
wifi.println(); // end HTTP request header
wifi.println(body);
}

fwiw 获取请求工作正常

void getHello() {
wifi.println("GET /hello HTTP/1.1");
wifi.println("Host: " + String(serverAddress));
wifi.println("Connection: close");
wifi.println(); // end HTTP request header
}
于 2021-04-30T02:00:16.677 回答