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
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)
{
"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() 内で HttpClient に WiFiClient をつっこみ、GETでHTTPリクエストします。 responseCode には、HTTPリクエストのレスポンスコードが格納されてます。200 や 404 エラーなどです。 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}