使用Arduino Wifi客户端发送可靠的HTTP请求

时间:2017-06-19 21:19:12

标签: arduino client

当触发我的Arduino MKR1000上的传感器时,我会发送一封电子邮件:

//....
WiFiClient client;
char server[] = "www.myserver.com";
//....

void setup() {
//... Connect to wifi ....
}

void loop() {
    // when sensor triggered => 
    if (client.connect(server, 80)) {
        Serial.println("Sending email");
        client.print("GET /WaterOff/sendGridCall.php");
        client.print("?valve=");
        client.print(valve);
        client.print("&position=");
        client.print(position);
        client.println(" HTTP/1.1");
        client.print("Host: ");
        client.println(server);
        client.println("User-Agent: Arduino");
        client.println("Connection: close");
        client.println();
    }

    delay(6000);
}

但是,它仅在前几次有效(打印“发送电子邮件”),之后不执行请求(不打印“发送电子邮件”)。我是否应该采取一些额外措施使其可靠。

1 个答案:

答案 0 :(得分:3)

您永远不会关闭连接。但阻止等待电子邮件确认可能需要永远。您应该考虑使用一个小型状态机来使您的网络连接正常工作。

void loop() 
{
    // when sensor triggered => 
    if (client.connect(server, 80)) {      // You connect to client, but it's already 
                                           // connected the second time around
        // send ...
        // client() should wait for response, and client.disconnect()
    }

    // ...
    delay(6000);      // tip: avoid blocking the main loop, this blocks your ability to 
                      // read your sensor while sending emails.
}

您的应用的状态机可能如下所示:

enum EmailState {
    emIdle, emSendMail, emCheckMailSent, emEmailOK, emEmailError,
};

EmailState email_state;
unsigned long long mail_timer;      // can be shared between states.

// small state handlers that do a bit at a time, 
// check for an event, wait on some delay (use millis())
// avoid blocking the instruction flow as much as possible.

static void on_emIdle()
{
  // read sensor, check timer?
  email_state = (triggered) ? emSendMail : emIdle;
}

static void on_sendMail()
{
    if (client.connect())
    {
        // ... prints
        email_state = emCheckMailSent;
        return;
    }
    email_state = emEmailError;
}

static void on_emCheckMailSent()
{
   // receive HTTP response...  can have a long timeout without blocking.
   email_state = emCheckMailSent; 
     // or emEmailOK or emEmailError or retry emSendMail
}

static void on_emEmailOK() 
{
   if (/*client is connected?*/)
       client.disconnect();

   if (!mail_timer) 
       mail_timer = millis();

   if (millis() - mail_timer < 6000)  // stay in this state for 6 seconds...
   {
       email_state = emEmailOK;
       return;
    }

    mail_timer = 0;        // always reset the timer so it can be used by other states
    email_state = emIdle;
}

static void on_emEmailError() 
{
   if (/*client is connected?*/)
       client.disconnect();
   // keep a log ?
   email_state = emIdle; // or another timer
}

//...
void loop() 
{
   // update readings, manage other things...
   // ...
   switch(email_state)
   {
   default:
   case emIdle:           on_emIdle();          break; 
   case emSendMail:       on_emSendMail();      break;
   case emCheckMailSent:  on_emCheckMailSent(); break;
   case emEmailOK:        on_emEmailOK();       break;
   case emEmailError:     on_emEmailError();    break;
   }
}