带有WiFi Shield的Arduino发出奇怪的帖子请求

时间:2016-09-02 14:17:51

标签: post arduino

我正在研究基于Arduino Uno的小型气象站。事实上,我已经创建了测量湿度,温度,压力和CO2水平的原型,并通过POST请求将数据发送到服务器。整个星期,它可以完美地按小时向服务器发送数据。但昨天我发现没有新数据出现。我的第一个想法是WiFi出了问题,我重新启动路由器,检查连接,一切都很完美。我认为如果Arduino出现问题并重新启动它,它会起作用。所以我检查连接后我得到了什么,答案是:

   HTTP/1.1 405 METHOD NOT ALLOWED
   Date: Fri, 02 Sep 2016 13:27:02 GMT
   Server: Apache/2.4.10 (Debian)
   Allow: GET, OPTIONS, POST, HEAD
   Content-Length: 178
   Connection: close
   Content-Type: text/html

   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
   <title>405 Method Not Allowed</title>
   <h1>Method Not Allowed</h1>
   <p>The method is not allowed for the requested URL.</p>
   *CLOS*

好的,然后我手动向服务器发送POST请求(通过邮递员),它是有效的。所以我去服务器并开始读取日志,没有错误,但在access.log中我发现了一些有趣的东西:

来自Postman的工作岗位请求如下:

15.15.119.103 - - [02/Sep/2016:13:54:03 +0300] "POST /api/meteo HTTP/1.1" 200 319 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"

但是当它来自Arduino时,它看起来很奇怪

15.15.119.103 - - [02/Sep/2016:13:53:54 +0300] "*HELLO*POST /api/meteo HTTP/1.1" 405 380 "-" "-"

因此,你可以看到服务器不像POST,而是喜欢“ HELLO POST”并且它毁了一切。问题是我在代码中没有任何改变,而且它在一周内以某种方式工作。你可以看到我的Arduino代码的和平:

#include <WiFly.h>
#include "HTTPClient.h"

#define SSID      "bbbbbbb"
#define KEY       "ccccccc"

#define AUTH      WIFLY_AUTH_WPA2_PSK

#define HTTP_POST_URL "15.15.25.67/api/meteo"

SoftwareSerial uart(2, 3);
WiFly wifly(uart);
HTTPClient http;

String PostData;
char PostBuf[90];

        uart.begin(9600);
//      check if WiFly is associated with AP(SSID)
        if (!wifly.isAssociated(SSID)) {
          while (!wifly.join(SSID, KEY, AUTH)) {
            Serial.println("Failed to join " SSID);
            Serial.println("Wait 0.1 second and try again...");
            delay(100);
          }

          wifly.save();    // save configuration, 
        }  
        PostData.toCharArray(PostBuf, 90);
        while (http.post(HTTP_POST_URL, PostBuf, 10000) < 0) {
        }
        while (wifly.receive((uint8_t *)&get, 1, 1000) == 1) {
        Serial.print(get);
        }
        uart.end();

所以它连接到WiFI并发送请求,但请求类型很奇怪。我试图找到任何可以帮助的关键,没有结果可能有人可以给我建议吗?

如果需要,我把这里放在HTTPClient.h:

#ifndef __HTTP_CLIENT_H__
#define __HTTP_CLIENT_H__

#define HTTP_CLIENT_DEFAULT_TIMEOUT         30000  // 3s

#define HTTP_MAX_HOST_LEN                   20
#define HTTP_MAX_PATH_LEN                   64
#define HTTP_MAX_BUF_LEN                    100

#define HTTP_DEFAULT_PORT                   80

#include <Arduino.h>
#include <WiFly.h>

class HTTPClient {
  public:
    HTTPClient();

    int get(const char *url, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT);
    int get(const char *url, const char *header, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT);
    int post(const char *url, const char *data, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT);
    int post(const char *url, const char *headers, const char *data, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT);

  private:
    int parseURL(const char *url, char *host, int max_host_len, uint16_t *port, char *path, int max_path_len);
    int connect(const char *url, const char *method, const char *data, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT);
    int connect(const char *url, const char *method, const char *header, const char *data, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT);

    WiFly* wifly;
};

#endif // __HTTP_CLIENT_H__

对于HTTPClient.cpp,它看起来像这样:

#include <string.h>
#include "HTTPClient.h"
#include "Debug.h"

HTTPClient::HTTPClient()
{
  wifly = WiFly::getInstance();
}

int HTTPClient::get(const char *url, int timeout)
{
  return connect(url, "GET", NULL, NULL, timeout);
}

int HTTPClient::get(const char *url, const char *headers, int timeout)
{
  return connect(url, "GET", headers, NULL, timeout);
}

int HTTPClient::post(const char *url, const char *data, int timeout)
{
  return connect(url, "POST", NULL, data, timeout);
}

int HTTPClient::post(const char *url, const char *headers, const char *data, int timeout)
{
  return connect(url, "POST", headers, data, timeout);
}

int HTTPClient::connect(const char *url, const char *method, const char *data, int timeout)
{
  return connect(url, method, NULL, data, timeout);
}

int HTTPClient::connect(const char *url, const char *method, const char *headers, const char *data, int timeout)
{
  char host[HTTP_MAX_HOST_LEN];
  uint16_t port;
  char path[HTTP_MAX_PATH_LEN];

  if (parseURL(url, host, sizeof(host), &port, path, sizeof(path)) != 0) {
    DBG("Failed to parse URL.\r\n");
    return -1;
  }

  if (!wifly->connect(host, port, timeout)) {
    DBG("Failed to connect.\r\n");
    return -2;
  }

  // Send request
  char buf[HTTP_MAX_BUF_LEN];
  snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", method, path);
  wifly->send(buf);

  // Send all headers
  snprintf(buf, sizeof(buf), "Host: %s\r\nConnection: close\r\n", host);
  wifly->send(buf);

  if (data != NULL) {
    snprintf(buf, sizeof(buf), "Content-Length: %d\r\nContent-Type: text/plain\r\n", strlen(data));
    wifly->send(buf);
  }

  if (headers != NULL) {
    wifly->send(headers);
  }

  // Close headers
  wifly->send("\r\n");

  // Send body
  if (data != NULL) {
    wifly->send(data);
  }

  return 0;
}

int HTTPClient::parseURL(const char *url, char *host, int max_host_len, uint16_t *port, char *path, int max_path_len)
{
  char *scheme_ptr = (char *)url;
  char *host_ptr = (char *)strstr(url, "://");
  if (host_ptr != NULL) {
    if (strncmp(scheme_ptr, "http://", 7)) {
      DBG("Bad scheme\r\n");
      return -1;
    }
    host_ptr += 3;
  } else {
    host_ptr = (char *)url;
  }

  int host_len = 0;
  char *port_ptr = strchr(host_ptr, ':');
  if (port_ptr != NULL) {
    host_len = port_ptr - host_ptr;
    port_ptr++;
    if (sscanf(port_ptr, "%hu", port) != 1) {
      DBG("Could not find port.\r\n");
      return -3;
    }
  } else {
    *port = HTTP_DEFAULT_PORT;
  }

  char *path_ptr = strchr(host_ptr, '/');
  if (host_len == 0) {
    host_len = path_ptr - host_ptr;
  }

  if (max_host_len < (host_len + 1)) {
    DBG("Host buffer is too small.\r\n");
    return -4;
  }
  memcpy(host, host_ptr, host_len);
  host[host_len] = '\0';

  int path_len;
  char *fragment_ptr = strchr(host_ptr, '#');
  if (fragment_ptr != NULL) {
    path_len = fragment_ptr - path_ptr;
  } else {
    path_len = strlen(path_ptr);
  }

  if (max_path_len < (path_len + 1)) {
    DBG("Path buffer is too small.\r\n");
    return -5;
  }
  memcpy(path, path_ptr, path_len);
  path[path_len] = '\0';

  return 0;
}

1 个答案:

答案 0 :(得分:0)

我找到问题的根源,默认情况下,当TCP连接打开时,WiFiShield v.1.0会说“ HELLO ”。事实上,它深入到手册中。

我的连接速度不是很快,因此在连接之前设法说“ HELLO ”,但我升级路由器固件并开始更快地工作,这就是为什么“ HELLO “在这种情况下连接到POST的下一个请求。解决方案很简单,只需添加:

wifly.sendCommand("set comm remote 0\r");

和此命令禁用WiFiShield上的欢迎消息。希望它对某人有所帮助。