ESP8266数据通过PUT方法上传到Grovestreams

时间:2018-05-05 13:05:15

标签: c http iot esp8266

我将使用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非常重要,没有它就不会上传数据。

1 个答案:

答案 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>

因此总的来说,您的代码似乎存在两个问题:

  1. 使用CRLF(\r\n)而不仅仅是LF \n来符合RFC2616。它在Section 19.3 Tolerant Applications中提到了以下内容:
  2.   

    消息头字段的行终止符是序列CRLF。   但是,我们建议应用程序在解析此类标头时,   将单个LF识别为行终止符并忽略前导CR。

    您发送\n而不是\r\n来分隔标题只是因为给定的实现容忍它,而不是因为这样做遵循RFC。

    1. 通过在最后一个标题内容之后的最后一个CRLF之后立即放置CRLF,发送空标头以表示标题部分的结尾。这告诉服务器它应该不再等待更多的头文件,它现在可以继续接收/解析HTTP主体(如果在给定的情况下有一个)或发送响应。
    2. 应用这些修补程序后,正确的请求应如下所示:

      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");