2016-09-02 3 views
0

Я работаю на небольшой метеостанции, основанной на Arduino Uno. Фактически я уже создаю прототип, который измеряет влажность, температуру, давление и уровень CO2 и отправляет данные через запрос POST на сервер. В течение всей недели он отлично работает, отправляя данные на сервер на почасовой основе. Но вчера я узнал, что новых данных не поступало. Моя первая мысль заключалась в том, что что-то не так с WiFi, я перезапускаю маршрутизатор, проверяю подключение, все работает отлично. Я думаю, что если что-то не так с Arduino и перезапустить его, это сработает. Так что я проверить, что я получаю после подключения и ответ был:Arduino с WiFi Shield сделать странный запрос на отправку

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 я нахожу что-то интересное:

Работа после запроса, пришедшего из Почтальон выглядеть следующим образом:

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, но LIKE «ПРИВЕТ 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; 
} 

ответ

0

Я выяснить корень проблемы, по умолчанию WiFiShield v.1.0 сказать «HELLO» при открытии TCP-соединения. Фактически это написано глубоко в руководстве.

Мое соединение было не так быстро, так что удается сказать «ПРИВЕТ» перед подключением, но я обновить прошивку маршрутизатора и начать работать быстрее, поэтому «ПРИВЕТ» подключен к следующему запросу, который был POST в этом случае. Решение просто добавьте:

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

и эта команда отключает приветственное сообщение на WiFiShield. Надеюсь, это поможет кому-то.