我将使用ESP8266(连接到STM32L0)上传数据到Grovestreams有问题(使用ThingSpeak它可以很好地工作,但在GS上没有)。我没有使用Arduino HW或SW(而且永远不会),但是我自己的库(但这可能不是问题)。
在网络浏览器中,此命令有效
http://grovestreams.com/api/feed?api_key=secretKEY&compId=bath&data=29&data=66&asPut
&asPut
存在,因为Web浏览器使用GET作为默认值。
但是当我和ESP8266这样做时
ESP8266_SendCmd("AT+CIPSTART="TCP","grovestreams.com",80");
ESP8266_SendData("PUT /api/feed?api_key=secretKEY&compId=bath&data=29&data=66 HTTP/1.1");
ESP将数据发送到grovestreams
AT+CIPSTART="TCP","grovestreams.com",80
CONNECT
OK
AT+CIPSEND=95
OK
>
busy s...
Recv 95 bytes
SEND OK
但没有任何反应(值不会显示在服务器上)。 我也试过这个
ESP8266_SendCmd("AT+CIPSTART="TCP","grovestreams.com",80");
ESP8266_SendData("PUT /api/feed?api_key=secretKEY&compId=bath&data=29&data=66 HTTP/1.1\r\nHost: \r\nConnection: close\r\nContent-Type: application/json");
然后我从服务器
得到答案+IPD,487:HTTP/1.1 408 Request Time-out
Date: Sat, 05 May 2018 00:48:23 GMT
Server: Apache
Vary: Accept-Encoding
Content-Length: 293
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>408
Request Time-out</title></head><body><h1>Request Time-out</h1><p>Server
timeout waiting for the HTTP request from the client.</p><hr><address>Apache
Server at www.grovestreams.com Port 80</address></body></html>CLOSED
发送数据和命令的功能类似于
void ESP8266_SendData(char* data)
{
char str[50] = "";
sprintf(str, "AT+CIPSEND=%d", strlen(data));
ESP8266_SendCmd(str);
HAL_Delay(100);
char str2[2048] = "";
sprintf(str2, "%s\r\n", data);
HAL_UART_Transmit(&ESPUartHandle, str2,(uint16_t) strlen(str2), 20);
HAL_Delay(200);
}
void ESP8266_SendCmd(char* cmd)
{
char str[50] = "";
sprintf(str, "%s\r\n", cmd);
HAL_UART_Transmit(&ESPUartHandle, str,(uint16_t) strlen(str), 20);
HAL_Delay(100);
}
正如我之前所写,使用Thingspeak,它完美地工作(GET方法)
ESP8266_SendCmd("AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",80");
HAL_Delay(2000);
ESP8266_SendData("GET /update?api_key=secretKEY&field1=36");
请问,ESP8266上的PUT方法我做错了什么?
编辑6.5.2018:在详细检查arduino grovestreams库之后,这个命令格式有效:
ESP8266_SendData("PUT /api/feed?api_key=secretKEY&compId=bath&data=20.7&data=66.8 HTTP/1.1\nHost: grovestreams.com\nConnection: close\nContent-Type: application/json\n\n");
最后两个\n\n
非常重要,没有它就不会上传数据。
答案 0 :(得分:0)
Grovestreams和ThingSpeak之间的差异可能与解析HTTP请求的方式不同(ThingSpeak使用更强大的实现)。
RFC2616 - Section 4. HTTP Message说以下内容:
请求(第5节)和响应(第6节)消息使用通用 用于传输实体的RFC 822 [9]的消息格式(有效载荷 的消息)。两种类型的消息都包含一个起始行,即零 或更多标题字段(也称为&#34;标题&#34;),空行(即, CRLF之前没有任何内容的行)表示结束 标题字段,可能还有消息正文。
因此,您不发送标题的结尾&#34;标记\r\n\r\n
可能导致服务器继续等待更多标头,这些标头可能在单独的TCP帧(或TLS PDU)中发送。您得到的答复进一步证实了这一点:
<html><head><title>408
Request Time-out</title></head><body><h1>Request Time-out</h1><p>Server
timeout waiting for the HTTP request from the client.</p><hr><address>Apache
Server at www.grovestreams.com Port 80</address></body></html>
因此总的来说,您的代码似乎存在两个问题:
\r\n
)而不仅仅是LF \n
来符合RFC2616。它在Section 19.3 Tolerant Applications中提到了以下内容:消息头字段的行终止符是序列CRLF。 但是,我们建议应用程序在解析此类标头时, 将单个LF识别为行终止符并忽略前导CR。
您发送\n
而不是\r\n
来分隔标题只是因为给定的实现容忍它,而不是因为这样做遵循RFC。
应用这些修补程序后,正确的请求应如下所示:
ESP8266_SendData("PUT /api/feed?api_key=secretKEY&compId=bath&data=20.7&data=66.8 HTTP/1.1\r\nHost: grovestreams.com\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n");