ArduinoでWebサーバーを実行する方法

このチュートリアルでは、私のようなWiFiを使用してArduinoデバイスでWebサーバーを起動する方法を紹介します。Arduino MKR WiFi 1010

既存のWiFiネットワークに接続し、ブラウザからArduinoを介して対話できるようになりますHTTP

これは、さまざまなアプリケーションにとって非常に興味深いものです。センサーデータの簡単なチェックから、に基づいたアクションの実行までHTTPリクエスト実行されます。

で定義されているこのプログラムから始めますArduinoを使用してWiFiネットワークに接続するチュートリアル:

#include <SPI.h>
#include <WiFiNINA.h>

void setup() {
  char ssid[] = SECRET_SSID;
  char pass[] = SECRET_PASS;

Serial.begin(9600); while (!Serial);

int status = WL_IDLE_STATUS; while (status != WL_CONNECTED) { Serial.print("Connecting to "); Serial.println(ssid); status = WiFi.begin(ssid, pass); delay(5000); }

Serial.print("IP address: "); Serial.println(WiFi.localIP()); }

void loop() {

}

setup()の前に、次の行を追加します。

WiFiServer server(80);

初期化するにはTCPポート80のサーバーとsetup()コール

server.begin();

サーバーを起動します。

これはTCPサーバーであり、HTTPサーバーではありません。しかし、HTTP(TCP / IPアプリケーションプロトコル)はTCP(トランスポート層)の上に構築されているため、HTTPサーバーを独自に非常に簡単に構築できます。

まず、クライアント接続をリッスンする必要があります。私たちはでそうしますloop()

void loop() {
  WiFiClient client = server.available();
  if (client) {

} }

のavailable()メソッドserver着信クライアントをリッスンします。

内部if (client) {}チェックしてください。HTTPクライアントが接続されています。私たちがする必要があるのは:

  • コールclient.connected()データが接続されているかどうか、および読み取るデータがあるかどうかを確認します
  • コールclient.available()読み取りに使用できるバイト数を取得します(これにより、読み取るデータがあることが確認されます)
  • コールclient.read()着信データ(クライアントから送信されたHTTP要求)から1バイトを読み取る
  • コールclient.println()またはclient.print()クライアントにデータを送信し、適切なHTTP応答を構築する
  • コールclient.stop()接続を終了します

クライアントから送信された各文字のシリアルインターフェイスへの印刷を開始し、最後に接続を閉じます。

void loop() {
  WiFiClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
      }
    }
client.stop();

} }

このプログラムをArduinoにアップロードしてみてください。ブラウザでIPアドレスを指定します。このようなものがシリアルインターフェースに印刷されているのがわかります。これはブラウザによって送信されるものです:

GET / HTTP/1.1
Host: 192.168.1.40
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: keep-alive

Note the ending empty line. This is the end of the HTTP request.

We need to intercept this empty line.

Each line in the HTTP request is terminated by a CR carriage return character (\r), and a LF line feed character (\n).

So the end of the request can be determined by 2 sets of those sequences: \r\n\r\n.

This simple algorithm will work, we just memorize 2 characters prior to the current one, and we check if we identify the sequence \n\r\n (the last 3 characters in that sequence are enough to determine the last line):

void loop() {
  WiFiClient client = server.available();
  if (client) {
<span style="color:#66d9ef">char</span> prevprev;
<span style="color:#66d9ef">char</span> prev;

<span style="color:#66d9ef">while</span> (client.connected()) {
  <span style="color:#66d9ef">if</span> (client.available()) {
    <span style="color:#66d9ef">char</span> c <span style="color:#f92672">=</span> client.read();
    Serial.write(c);

    <span style="color:#66d9ef">if</span> (prevprev <span style="color:#f92672">==</span> <span style="color:#e6db74">'\n'</span> <span style="color:#f92672">&amp;&amp;</span> prev <span style="color:#f92672">==</span> <span style="color:#e6db74">'\r'</span> <span style="color:#f92672">&amp;&amp;</span> c <span style="color:#f92672">==</span> <span style="color:#e6db74">'\n'</span>) {
      <span style="color:#75715e">//we can send the response!

}

    prevprev <span style="color:#f92672">=</span> prev;
    prev <span style="color:#f92672">=</span> c;
  }
}

client.stop();

} }

So now we can send the response inside the if, we can use client.println() for this, and we add a simple response like this:

HTTP/1.1 200 OK
Content-Type: text/html
Connection: close

<!DOCTYPE HTML> <html> test </html>

In this way:

client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("test");
client.println("</html>");
break;

The break; statement ends the while (client.connected()) {} block.

Here is the full program:

#include <SPI.h>
#include <WiFiNINA.h>

WiFiServer server(80);

void setup() { char ssid[] = SECRET_SSID; char pass[] = SECRET_PASS;

Serial.begin(9600); while (!Serial);

int status = WL_IDLE_STATUS; while (status != WL_CONNECTED) { Serial.print("Connecting to "); Serial.println(ssid); status = WiFi.begin(ssid, pass); delay(5000); }

Serial.print("IP address: "); Serial.println(WiFi.localIP());

server.begin(); }

void loop() { WiFiClient client = server.available(); if (client) {

<span style="color:#66d9ef">char</span> prevprev;
<span style="color:#66d9ef">char</span> prev;
<span style="color:#66d9ef">while</span> (client.connected()) {
  <span style="color:#66d9ef">if</span> (client.available()) {
    <span style="color:#66d9ef">char</span> c <span style="color:#f92672">=</span> client.read();
    Serial.write(c);

    <span style="color:#66d9ef">if</span> (prevprev <span style="color:#f92672">==</span> <span style="color:#e6db74">'\n'</span> <span style="color:#f92672">&amp;&amp;</span> prev <span style="color:#f92672">==</span> <span style="color:#e6db74">'\r'</span> <span style="color:#f92672">&amp;&amp;</span> c <span style="color:#f92672">==</span> <span style="color:#e6db74">'\n'</span>) {
      client.println(<span style="color:#e6db74">"HTTP/1.1 200 OK"</span>);
      client.println(<span style="color:#e6db74">"Content-Type: text/html"</span>);
      client.println(<span style="color:#e6db74">"Connection: close"</span>);
      client.println();
      client.println(<span style="color:#e6db74">"&lt;!DOCTYPE HTML&gt;"</span>);
      client.println(<span style="color:#e6db74">"&lt;html&gt;"</span>);
      client.println(<span style="color:#e6db74">"test"</span>);
      client.println(<span style="color:#e6db74">"&lt;/html&gt;"</span>);
      <span style="color:#66d9ef">break</span>;
    }

    prevprev <span style="color:#f92672">=</span> prev;
    prev <span style="color:#f92672">=</span> c;
  }
}

client.stop();

} }

Try it, you should see test showing up in the browser:

The approach works until you need to figure out how what the client asked us.

In that case you want to read each line, so this alternative approach works better:

void loop() {
  WiFiClient client = server.available();
  if (client) {
    String line = "";
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
    <span style="color:#66d9ef">if</span> (c <span style="color:#f92672">!=</span> <span style="color:#e6db74">'\n'</span> <span style="color:#f92672">&amp;&amp;</span> c <span style="color:#f92672">!=</span> <span style="color:#e6db74">'\r'</span>) {
      line <span style="color:#f92672">+=</span> c;
    }

    <span style="color:#66d9ef">if</span> (c <span style="color:#f92672">==</span> <span style="color:#e6db74">'\n'</span>) {
      <span style="color:#66d9ef">if</span> (line.length() <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) {
        client.println(<span style="color:#e6db74">"HTTP/1.1 200 OK"</span>);
        client.println(<span style="color:#e6db74">"Content-Type: text/html"</span>);
        client.println(<span style="color:#e6db74">"Connection: close"</span>);
        client.println();
        client.println(<span style="color:#e6db74">"&lt;!DOCTYPE HTML&gt;"</span>);
        client.println(<span style="color:#e6db74">"&lt;html&gt;"</span>);
        client.println(<span style="color:#e6db74">"test"</span>);
        client.println(<span style="color:#e6db74">"&lt;/html&gt;"</span>);
        <span style="color:#66d9ef">break</span>;
      } <span style="color:#66d9ef">else</span> {
        line <span style="color:#f92672">=</span> <span style="color:#e6db74">""</span>;
      }
    }
  }
}

client.stop();

} }

In the last else we can inspect the line because the line is terminated, and act accordingly to our needs.


More electronics tutorials: