ESP8266(Arduino)でJSONを取得して、パースする
TOP > てきとうにこらむ > ゲーム作りとプログラミング日記 > ESP8266(Arduino)でJSONを取得して、パースする
ArduinoでJSONをパースをするのに、いくらかライブラリがあって、そのうちArduinoJsonを使った。
また、HTTPでJSONを取得したくても、Arduinoではインターネットに繋ぐのが日本では結構難しいので、ESP8266を使った。
天気予報を取得できるhttp://weather.livedoor.com/weather_hacks/webserviceを使ったけども、これ今年の7月末で終了してしまうのか…
コード
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFiMulti.h>
#define ARDUINOJSON_DECODE_UNICODE 1
#include <ArduinoJson.h>
char ssid[] = "SSID"; // SSID
char password[] = "password"; // パスワード
ESP8266WiFiMulti WiFiMulti;
void setup() {
Serial.begin(115200);
for (uint8_t t = 4; t > 0; t--) {
Serial.printf("[SETUP] WAIT %d...\n", t);
Serial.flush();
delay(1000);
}
WiFi.mode(WIFI_STA);
WiFiMulti.addAP(ssid, password);
while (WiFiMulti.run() != WL_CONNECTED) {
delay(1000);
}
WiFiClient client;
HTTPClient http;
Serial.print("[HTTP] begin...\n");
if (http.begin(client, "http://weather.livedoor.com/forecast/webservice/json/v1?city=110010")) {
Serial.printf("[HTTP] GET...\n");
int httpCode = http.GET();
if (httpCode > 0) {
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(38) + 44 * JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 3 * JSON_OBJECT_SIZE(4) + 3 * JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(8) + 3850; //
DynamicJsonDocument doc(capacity);
StaticJsonDocument<64> filter;
filter["forecasts"][0]["date"] = true;
filter["forecasts"][0]["telop"] = true;
DeserializationError error = deserializeJson(doc, payload, DeserializationOption::Filter(filter));
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
const char *date = doc["forecasts"][0]["date"];
const char *telop = doc["forecasts"][0]["telop"];
Serial.printf(
"%sの天気: %s\n",
date,
telop
);
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
} else {
Serial.printf("[HTTP] Unable to connect\n");
}
}
void loop() {
Serial.println("loop");
delay(1000);
}
なにか気をつけるべき事があるかというと、次の2点だろうか。
- DeserializationOption::Filterを使ってパースする要素を限定する。これしないと再起動かかる
- doc["forecasts"][0]["date"]
- doc["forecasts"][0]["telop"]
- Unicodeのパースをするには #define ARDUINOJSON_DECODE_UNICODE 1が必要
- capacityは https://arduinojson.org/v6/assistant/ で求めた