ESP32でHTTPClientを使ってウェブサーバーにGET、POSTするやり方

ESP32でHTTPClientを使ってウェブサーバーにGET、POSTするやり方

ESP32でウェブサーバーにHTTPリクエストをするやり方をご紹介します。HTTPClientを使うとカンタンにGET、POSTできますよ。SSLを使ったHTTPSでも可能ですが、ここではもっともカンタンなHTTP通信での方法をご紹介いたします。

開発環境

この記事の執筆時では、次の開発環境でプログラムを実行テストしました。

項目
Arduino ESP32-DevKitC
IDE Platform IO
ファームウェア arduino-esp32#2.0.2
HTTPClient ver 2.0.0

ダミーサーバーの用意

ESP32でHTTPリクエストのテストを行う場合は、ダミーサーバーを用意しておくと便利です。Pythonでカンタンに立ち上げることができます。必要ない場合は読み飛ばしてください。

パソコン内の適当な場所に、次のような構成でファイルを用意しておきます。

.
├── dummy_root
│   └── status.json
└── dummy_server.py

dummy_server.py の内容は次のとおりです。

from http.server import HTTPServer, BaseHTTPRequestHandler
import os
import re
import logging
import socket

host_list = socket.gethostbyname_ex(socket.gethostname())
lan_address = host_list[2][1]

dirname = os.path.dirname(__file__)
server_ip = "0.0.0.0"
server_port = 9998

lan_url = "http://{}:{:d}".format(lan_address, server_port)
url = "http://{}:{:d}".format(server_ip, server_port)


os.chdir(dirname + "/dummy_root/")


def load_file(path):
    with open(path, mode='r') as f:
        s = f.read()
        return s.encode('utf-8')

class S(BaseHTTPRequestHandler):

    def do_GET(self):
        # logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers))

        m = re.match(r'^/status$', self.path)
        if m != None:
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            self.wfile.write(load_file("status.json"))


    def do_POST(self):
        print('======================= POST =======================');
        print(self.path)

        m = re.match(r'^/data$', self.path)
        if m != None:
            # {"device_name": "esp32", "temperature": 21.6}

            content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
            post_data = self.rfile.read(content_length) # <--- Gets the data itself
            print('======================= HTTP Request =======================');
            logging.info("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n",
                    str(self.path), str(self.headers), post_data.decode('utf-8'))

            self.send_response(200)
            self.send_header('Content-Type', 'application/json')
            self.end_headers()
            self.wfile.write('{"status":"ok"}'.encode('utf-8'))
        
def web_server():
    logging.basicConfig(level=logging.INFO)
    
    httpd = HTTPServer(('', server_port), S)

    logging.info('Starting httpd...\n')
    httpd.serve_forever()


if __name__ == "__main__":
    print(lan_url)
    print(url)
    web_server()
    # t = threading.Thread(target = web_server)
    # t.start()

    # cmd = 'open {}'.format(url)
    # print(cmd)
    # os.system(cmd)

status.json の内容は次のとおりです。

{
    "TIMESTAMP": "2022-10-30T04:07:00",
    "STATUS": 1
}

GETでHTTPリクエストしたい

ESP32でGETリクエストを使う用途としましては、サーバー上に何らかのステータス状態を置いておき、ESP32からアクセスして確認させることでESP32の動作をコントロールするといった使い方ができます。AWSのIoT Coreで言うところのシャドウのような使い方ですね。AWSではMQTTプロトコルで通信しますが、ちょっとした用途でしたらHTTPリクエストで十分かと思います。

次はESP32からウェブサーバーにGETのHTTPリクエストを送信するプログラム例です。

#include <HTTPClient.h>
#include <WiFi.h>

#include "Arduino.h"

#ifndef WIFI_SSID
#define WIFI_SSID "xxxxx"  // WiFi SSID (2.4GHz only)
#endif

#ifndef WIFI_PASSWORD
#define WIFI_PASSWORD "xxxxx"  // WiFiパスワード
#endif

String url = "http://192.168.61.5:9998/status";

void setup() {
    Serial.begin(115200);

    WiFi.mode(WIFI_STA);
    delay(500);
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void loop() {
    WiFiClient client;
    HTTPClient http;

    if (!http.begin(client, url)) {
        Serial.println("Failed HTTPClient begin!");
        return;
    }

    Serial.println("HTTPClient begin!");
    http.addHeader("Content-Type", "application/json");
    int responseCode = http.GET();
    String body = http.getString();
    Serial.println(responseCode);
    Serial.println(body);

    http.end();

    delay(5000);
}

カンタンですね! setup() でWiFiクライアントを立ち上げておきます。 loop() 内で HttpClientWiFiClient をつっこみ、GETでHTTPリクエストします。

responseCode には、HTTPリクエストのレスポンスコードが格納されています。200404 エラーなどです。

HTTPリクエストで返された本文の内容は getString() で取得できます。内容がjsonであれば、そのままjsonの文字列が String 型で返されます。

▼ ESP32でJSONをパースすにはjson11を使うと便利です。やり方は次の記事をご覧ください。

POSTでHTTPリクエストしたい

ESP32にセンサを取り付けてそのデータをウェブサーバーに投げて記録したいことは多いですよね。

次はESP32からウェブサーバーにPOSTのHTTPリクエストを送信するプログラム例です。

#include <HTTPClient.h>
#include <WiFi.h>

#include "Arduino.h"

#ifndef WIFI_SSID
#define WIFI_SSID "xxxxx"  // WiFi SSID (2.4GHz only)
#endif

#ifndef WIFI_PASSWORD
#define WIFI_PASSWORD "xxxxx"  // WiFiパスワード
#endif

String url = "http://192.168.61.5:9998/data";

void setup() {
    Serial.begin(115200);

    WiFi.mode(WIFI_STA);
    delay(500);
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void loop() {
    WiFiClient client;
    HTTPClient http;
    String json = R"({"device_name": "esp32", "temperature": 21.6})";

    if (!http.begin(client, url)) {
        Serial.println("Failed HTTPClient begin!");
        return;
    }
    Serial.println(json);
    http.addHeader("Content-Type", "application/json");
    int responseCode = http.POST(json);
    String body = http.getString();

    Serial.println(responseCode);
    Serial.println(body);

    http.end();

    delay(5000);
}

GETとほぼ同じなので説明はいいでしょう。POSTで投げたいデータは http.POST(データ内容) で指定します。

この記事の最初にご紹介したダミーサーバーをお使いになれば、次のようなHTTPリクエストが確認できるはずです。

INFO:root:POST request,
Path: /data
Headers:
Host: 192.168.61.5:9998
User-Agent: ESP32HTTPClient
Connection: keep-alive
Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0
Content-Type: application/json
Content-Length: 44



Body:
{"device_name": "esp32", "temperature": 21.6}
「キッチンノート.fun」という料理サイトを立ち上げました!このサイトで紹介していた料理記事は、そちらへ移動しました。
記事に関するご質問などがあれば、
Twitter または お問い合わせ までご連絡ください。
関連記事