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

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

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

開発環境

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

項目
ArduinoESP32-DevKitC
IDEPlatform IO
ファームウェアarduino-esp32#2.0.2
HTTPClientver 2.0.0

ダミーサーバーの用意

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

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

.
├── dummy_root
│   └── status.json
└── dummy_server.py
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 の内容は次のとおりです。
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リクエストを送信するプログラム例です。

cpp
#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リクエストを送信するプログラム例です。

cpp
#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}

関連記事

最後までご覧いただきありがとうございます!

▼ 記事に関するご質問やお仕事のご相談は以下よりお願いいたします。
お問い合わせフォーム

ESP32搭載ボード
ESP32の書籍
Arduinoで人気の周辺パーツ
M5Stackのオススメ参考書
M5Stack製品
M5StickCで使えるHat
ESP32ボード
関連記事