インターネットに接続して天気予報から取り込みタイミングをお知らせ!
第1回:洗濯物の取り込みを教えてくれるスマートな洗濯バサミを作ろう!
第2回:M5Stickに水分センサを付けて洗濯物乾き具合をチェック
こんにちは、ヨシケンです!
今回の連載では小型のM5Stick-Cシリーズを使って、最先端洗濯バサミを作っています。第3回の今回は、M5Stickに付いているWi-Fiでインターネットに接続して、天気予報の情報を取得し、洗濯バサミが天気の急変などをチェックして、洗濯物の取り込みをお知らせしてくれるようにしてみたいと思います。


今回の記事で必要な物一覧
今回のM5Stick-Cを使ったもの作りに必要な部品はこちらになっています。
M5Stick-C
ESP32に小型ディスプレイを搭載したArduino互換機。ボタン、BLE、Wi-Fiおよびモーションセンサなども始めから入っている。

水分センサ
赤外線により接触物の水分量を計測

DHT11 温湿度センサ
温度と湿度を同時に計測できる安価なデジタルセンサ

今回の記事の流れ
1. Wi-Fiとインターネットへの接続
最先端洗濯バサミを作っていますが、M5Stickには始めからWi-Fi接続の機能があるので、インターネットに接続して、天気情報などを取得できるようにしましょう。天気の急変や天候の変化を定期的に取得して、メッセージなどでお知らせしてくれる機能も便利だと思います。
まずはM5StickでWi-Fiに接続できるようにします。便利なWiFi.hというライブラリがあるので、これを使って以下のような簡単なスケッチを作って試してみます。いつも繋いでいるWi-Fi接続先の情報を入れて、結果をM5Stickに表示させます。
[M5Stick_Wifi.ino]
#include <M5StickC.h>
#include <WiFi.h>
const char* ssid = "XXX”;
const char* password = "YYY”;
void setup() {
Serial.begin (9600);
M5.begin();
M5.Lcd.setRotation(3);
M5.Lcd.setCursor(0, 0, 2);
Serial.printf(ssid);
M5.Lcd.printf("Connecting to %s\n", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print(".");
}
M5.Lcd.printf("\nWiFi connected\n");
}
void loop() {
}
こちらのssidのXXXの部分に自分のWifiのID、YYYのpasswordにWifiのパスワードを入れて、M5Stickに書き込みます。これできちんとWi-Fiに接続できた時には、自分のWi-FiのIDと共に”WiFi connected”の表示が出るはずです。

2. M5Stickで天気情報を取得
M5StickからWi-Fiでインターネットに接続できたら、天気予報を取得したいと思います。天気情報は、世界中の天気をAPIで提供してくれているOpenWeatherMapを使います。OpenWeatherMapのAPIサイトはこちらです。
http://api.openweathermap.org/

このサイト右上のSign Inメニューからアカウントを取って、サインインします。
そうするとメニュー上のAPI Keysというところに行くと、API Key情報があるので、それをコピーしておきます。StatusをActiveにしておくのも忘れないで下さいね。

試しにこのAPIをウェブ上から以下のコマンドで呼び出してみてください。ZZZは先ほどコピーしたKeyになります。
http://api.openweathermap.org/data/2.5/weather?q=tokyo,jp&mode=html&APPID=ZZZ
そうするとこのように東京の天気と気温、天候の情報を簡単に取得することができました。

ではこのAPIを使って、M5Stickで天気情報を取得するスケッチを作ります。
[M5Stick_Weather.ino]
#include <M5StickC.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
const char* ssid = "XXX”;
const char* password = "YYY”;
const String endpoint = "http://api.openweathermap.org/data/2.5/weather?q=tokyo,jp&APPID=";
const String key = "ZZZ";
String getWeather(){
HTTPClient http;
http.begin(endpoint + key);
int httpCode = http.GET();
String weather="Error";
if (httpCode > 0) {
String payload = http.getString(); // JSON形式の結果を取得
Serial.println(httpCode);
Serial.println(payload);
DynamicJsonBuffer jsonBuffer;
String json = payload;
JsonObject& weatherdata = jsonBuffer.parseObject(json);
if(!weatherdata.success()){
Serial.println("parseObject() failed");
}
weather = weatherdata["weather"][0]["main"].as<char*>();
}
return weather;
}
void setup() {
Serial.begin (9600);
M5.begin();
M5.Lcd.setRotation(3);
M5.Lcd.setCursor(0, 0, 2);
Serial.printf(ssid);
M5.Lcd.printf("Connecting to %s\n", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print(".");
}
M5.Lcd.printf("\nWiFi connected\n");
}
void loop(){
M5.Lcd.fillScreen(BLACK);
String weather = getWeather();
Serial.println(weather);
M5.Lcd.setCursor(0,10);
M5.Lcd.print(weather);
delay(1000*600);//10分待機
}
この中でkeyのZZZ部分に先ほどコピーしたAPI Keyを貼り付けます。そしてOpenWeatherMapのAPIから以下のようにJSONで天気情報を取得します。
weather = weatherdata["weather"][0]["main"].as<char*>();
この時、APIの結果をJSON形式で受け取るため、ArduinoJsonというライブラリを追加しておく必要があります。この天気予報情報を10分おきに取得して、M5Stickの画面を更新しています。これで写真のようにM5Stickに天気情報が表示できました。

3. 雨予報ならメッセージを送信
天気情報が取得できたら、この予報が雨の時に、洗濯物を取り込むようM5Stickからメッセージを送りたいと思います。M5StickをLINEに接続できるようにして、LINEのAPIからメッセージを送るようにします。
まずM5StickとLINEを連携するに当たって、LINE NotifyというAPIのアカウントを取得します。こちらのリンクからLINE Notifyに登録をおこないます。
https://notify-bot.line.me/ja/
右上のメニューからLINEアカウントでログインします。その後、下の方にあるアクセストークンの発行画面から「トークンを発行する」をクリックします。

ここでは、洗濯物の情報を共有するためのM5RoomというLINEグループを作っておいて、ここにメッセージを送ります。このグループに洗濯物情報を共有する家族と共に、このLINE Notifyも招待しておきます。トークンを発行すると、一度だけそのアクセストークンが出てくるので、これをコピーしておきます。

LINE側で接続する設定ができたので、メッセージを送れるようM5StickからからこのAPIを使ってみましょう。前回作った温湿度、乾き度合いを計測する機能も含めて、Laundry_Weather_Lineスケッチを作りました。19〜50行目と137〜141行目が追加した記述です。
[M5Stick_Laundry_Weather_Line.ino]
#include <M5StickC.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#define WATER_SENSOR 33
#include <DHT.h>
const int PIN_DHT = 0;
DHT dht(PIN_DHT,DHT11);
const char* ssid = "XXXX”;
const char* password = "YYYY”;
const String endpoint = "http://api.openweathermap.org/data/2.5/weather?q=tokyo,jp&APPID=";
const String key = "ZZZZ”;
void send(String message) {
const char* host = "notify-api.line.me";
const char* token = "LLLL";
WiFiClientSecure client;
Serial.println("Try");
client.setInsecure();
if (!client.connect(host, 443)) {
Serial.println("Connection failed");
return;
}
Serial.println("Connected");
String query = String("message=") + message;
String request = String("") +
"POST /api/notify HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Authorization: Bearer " + token + "\r\n" +
"Content-Length: " + String(query.length()) + "\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n\r\n" +
query + "\r\n";
client.print(request);
while (client.connected()) {
String line = client.readStringUntil('\n');
Serial.println(line);
if (line == "\r") {
break;
}
}
String line = client.readStringUntil('\n');
Serial.println(line);
}
String getWeather(){
HTTPClient http;
http.begin(endpoint + key);
int httpCode = http.GET();
String weather="Error";
if (httpCode > 0) {
String payload = http.getString(); // JSON形式の結果を取得
Serial.println(httpCode);
Serial.println(payload);
DynamicJsonBuffer jsonBuffer;
String json = payload;
JsonObject& weatherdata = jsonBuffer.parseObject(json);
if(!weatherdata.success()){
Serial.println("parseObject() failed");
}
weather = weatherdata["weather"][0]["main"].as<char*>();
}
return weather;
}
void setup() {
Serial.begin (9600);
pinMode(WATER_SENSOR, INPUT);
dht.begin();
M5.begin();
M5.Lcd.setRotation(3);
M5.Lcd.setTextSize(2);
Serial.printf(ssid);
M5.Lcd.printf("Connecting to %s\n", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print(".");
}
M5.Lcd.printf("\nWiFi connected\n");
}
void loop(){
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(10, 0); //文字表示の左上位置を設定
M5.Lcd.setTextColor(WHITE); // (WHITE, BLACK, RED, GREEN, BLUE, YELLOW...)
M5.Lcd.printf("W: ");
String weather = getWeather();
Serial.println(weather);
M5.Lcd.print(weather);
M5.Lcd.setCursor(10, 20);
M5.Lcd.setTextColor(BLUE);
M5.Lcd.print(digitalRead(WATER_SENSOR));
if ( digitalRead(WATER_SENSOR) == 0 ) {
M5.Lcd.printf(": Wet");
} else {
M5.Lcd.printf(": Dry!");
}
Serial.println(digitalRead(WATER_SENSOR));
M5.Lcd.setCursor(10, 40);
M5.Lcd.setTextColor(GREEN);
M5.Lcd.print("H:");
M5.Lcd.print(humidity,0);
M5.Lcd.print("%");
M5.Lcd.setTextColor(RED);
M5.Lcd.printf(" T:");
M5.Lcd.print(temperature,0);
M5.Lcd.print("C");
M5.Lcd.setCursor(10, 60);
float laundry_index = ( 0.81*temperature+0.01*humidity*(0.99*temperature-14.3)+46.3 );
M5.Lcd.setTextColor(YELLOW);
M5.Lcd.printf("Laundry: ");
M5.Lcd.print(laundry_index,0);
delay(1000*600);//10分待機
if (weather == "Rain"){
send("気温は"+String(temperature,0)+"C、湿度は"+String(humidity,0)+"%です。");
send("雨が降るので取り込んで!");
}
}
まず、send機能内のLINEメッセージのLLLのところに、先ほどコピーしたトークンをペーストします。取得した天気情報がRain(またはSnowなど)であれば、「取り込んで!」というメッセージと共にLINEに送信します。
それではこのスケッチをM5Stickに流し込んで、結果を見てみます。このように天気情報、外気温、選択指数などがM5Stick上に表示されます。

画像のように天気情報が雨予報(Rain)に変わると、LINEにメッセージが送られて、洗濯物を取り込むように促します。

LINEで送られているメッセージはこのようになりました。ここでは10分おきに天気をチェックしていますが、使用方法などに応じてチェックのタイミングを変えてみてください。

4. まとめ
今回の連載では、M5Stickを使った最先端洗濯バサミを作っています。M5Stickは最初からWi-Fiが備わっていますので、家の無線LANに繋いでインターネットに簡単に接続することができます。天気情報は、その地域の天気予報をOpenWeatheMapというオープンなAPIから取得することができます。
また、M5StickとLINEを接続してメッセージを送れるようにしました。これにより、天気情報が変わったときに、M5StcikからLINEを送信して、洗濯物を取り込むようにアラートを出すことができました。
これ以外にも、強風の情報や天気の急変などをこの天気APIから取得して、様々なメッセージを追加するのも面白いかもしれません。実際測っている外気温や湿度の情報と組み合わせて、最適な取り込みタイミングを流すのもいいと思います。
それでは次回は、この最先端洗濯バサミを完成させて、外で使っていろいろな記録を残せるようにしようと思います。
お楽しみに!
今回の連載の流れ
第1回:洗濯物の取り込みを教えてくれるスマートな洗濯バサミを作ろう!
第2回:M5Stickに水分センサを付けて洗濯物乾き具合をチェック
第3回:インターネットに接続して天気予報から取り込みタイミングをお知らせ!(今回)
第4回:省電力化して最先端スマート洗濯バサミの完成!



