はじめに
最近突然の雨で、外に干していた洗濯物が濡れてしまうことが続いていたので、
M5Stackを使って、雨の降り始めを通知するアプリを作ってみようと思います。
困ってたこと
- 自分が住んでいる場所の天気が必ずしも天気予報と同じ天気ではなかったため、よく雨で洗濯物が濡れてしまっていた
- 雨が降っていないか確認するのがめんどくさかった
今回作るもの
- すぐに洗濯物を取り込めるように、雨の降り始めのタイミングでSlackで通知してくれる
- 手元にあったM5Stack, 水分センサー(本来は土中の水分量を計測するもの), M5Stack 3G拡張ボードを使って試してみる
- Wifi利用、3G回線利用のそれぞれで試してみる
開発環境、使用したもの
- Mac
- M5Stack Gray
手順
手順1: M5StackをMacで開発するための準備
今回は、最近PCを新しくしたこともあり、Arduino IDEのインストールから必要でしたので、以下の手順で進めました。
-
MacにArduino IDEをインストールする
- https://www.arduino.cc/en/Main/Software を開き、Mac用をダウンロード&インストールする
-
ESP32用のボードマネージャを追加する
- Arduino > Preferences > 追加のボードマネージャのURLに以下のURLを追加します
https://dl.espressif.com/dl/package_esp32_index.json
- Arduino > Preferences > 追加のボードマネージャのURLに以下のURLを追加します
-
M5Stack用のライブラリをインストールする
-
MacとM5Stackを接続した後、ボード、シリアルポート等の設定値を以下のように設定します
-
サンプルスケッチを書き込み、動作確認をします
手順2: 水分量をM5Stackで測定する
手元にあった水分量センサーをM5Stackとつなげ、以下のサンプルコードを書き込み、センサーが濡れている時は1, それ以外は0が取得できることを確認します。
- サンプルコード
#include <M5Stack.h>
#define WATER_SENSOR 36
void setup() {
M5.begin();
pinMode(WATER_SENSOR, INPUT);
}
void loop() {
Serial.println(digitalRead(WATER_SENSOR));
M5.Lcd.println(digitalRead(WATER_SENSOR));
delay(1000);
}
手順3: 水分が検出できた時にSlackに通知する
Slack通知には、Incoming WebHooksを利用します。
下記のサンプルコードで、Slack通知することができるはずです。
この例では、Wifi通信を利用しています。
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <M5Stack.h>
#define WIFI_SSID "{SSID}"
#define WIFI_PASS "{PASSWORD}"
#define WATER_SENSOR 36
const char *server = "hooks.slack.com";
const char *json = "{'channel': '{チャンネル名}', 'username': 'てるてる坊主', 'text': '雨が降り始めたよ!', 'icon_emoji': ':rain_cloud:'}";
const char* slack_root_ca= "証明書" ;
WiFiMulti wifi;
HTTPClient http;
int isDetected = false;
void setup() {
Serial.begin(115200);
M5.begin();
wifi.addAP(WIFI_SSID, WIFI_PASS);
while (wifi.run() != WL_CONNECTED) { delay(500); }
pinMode(WATER_SENSOR, INPUT);
M5.Lcd.clear(BLACK);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(20);
M5.Lcd.println();
M5.Lcd.print(" Sunny!");
}
void loop() {
if (digitalRead(WATER_SENSOR) == 1 && isDetected == false) {
postSlack();
isDetected = true;
M5.Lcd.clear(BLACK);
M5.Lcd.setCursor(0, 0);
M5.Lcd.println();
M5.Lcd.print(" Rainy!");
}
delay(1000 * 10);
}
void postSlack() {
http.begin(server, 443, "/services/XXX/YYY/ZZZ", slack_root_ca);
http.addHeader("Content-Type", "application/json" );
http.POST((uint8_t*)json, strlen(json));
}
(オプション)手順4: M5Stack3G拡張モジュールを利用したSlack通知を試してみる
M5Stackには元々WiFiモジュールが組み込まれているため、3G拡張モジュールを利用する必要はありませんが、
Wifiでの通信を3G通信に置き換えたSlack通知も試してみたので、そちらについてもメモをしておきます。
デバイス側の負荷軽減という観点では、こちらの方が好ましいかもしれません。
必要なものは、M5Stack3G拡張モジュールとSIMカードです。
今回は、Soracom Beamを経由して、Slackに通知する構成で実現してみました。
セットアップ
- M5Stack 3G拡張モジュールのセットアップやライブラリのインストールは、こちらを参考にしました。
HTTPアクセスの動作確認
- まずは3GでのHTTPアクセスの動作確認をしたかったので、
ステップ 2: M5Stack で開発してみる (HTTP アクセス)
のスケッチをそのまま利用することにしました。
このスケッチでは、TinyGsmClientを利用しているので、M5Stack用のライブラリをインストールした時と同様の手順で、TinyGsmClientについてもインストールが必要になります。 - HTTPアクセスに成功すると、M5Stackのディスプレイ上に、HTTPアクセス時の各種情報が表示されます。
デバイス側サンプルコード
動作確認ができたら、Slack通知にとりかかります。
M5Stack側からSoracom Beamに連携するコードは下記のコードが参考になると思います。
(※このサンプルでは水分センサーの処理は入れていません。)
#include <M5Stack.h>
#define TINY_GSM_MODEM_UBLOX
#include <TinyGsmClient.h>
TinyGsm modem(Serial2); /* 3G board modem */
TinyGsmClient ctx(modem);
void setup() {
Serial.begin(115200);
M5.begin();
M5.Lcd.clear(BLACK);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.println(F("M5Stack + 3G Module"));
M5.Lcd.print(F("modem.restart()"));
Serial2.begin(115200, SERIAL_8N1, 16, 17);
modem.restart();
M5.Lcd.println(F("done"));
M5.Lcd.print(F("getModemInfo:"));
String modemInfo = modem.getModemInfo();
M5.Lcd.println(modemInfo);
M5.Lcd.print(F("waitForNetwork()"));
while (!modem.waitForNetwork()) M5.Lcd.print(".");
M5.Lcd.println(F("Ok"));
M5.Lcd.print(F("gprsConnect(soracom.io)"));
modem.gprsConnect("soracom.io", "sora", "sora");
M5.Lcd.println(F("done"));
M5.Lcd.print(F("isNetworkConnected()"));
while (!modem.isNetworkConnected()) M5.Lcd.print(".");
M5.Lcd.println(F("Ok"));
M5.Lcd.print(F("My IP addr: "));
IPAddress ipaddr = modem.localIP();
M5.Lcd.print(ipaddr);
delay(2000);
}
void loop() {
M5.update();
M5.Lcd.clear(BLACK);
M5.Lcd.setCursor(0, 0);
M5.Lcd.println(F("Post to SORACOM BEAM"));
if (!ctx.connect("uni.soracom.io", 80)) {
Serial.println(F("Connect failed."));
return;
}
Serial.println(F("connected."));
/* build payload */
const char *json = "{'channel': '{チャンネル名}', 'username': 'てるてる坊主', 'text': '雨が降り始めたよ!', 'icon_emoji': ':rain_cloud:'}";
char payload[1024];
sprintf(payload, "%s", json);
/* send request */
ctx.println("POST / HTTP/1.1");
ctx.println("Host: uni.soracom.io");
ctx.println("Content-Type: application/json");
char content_length_hdr[32];
sprintf(content_length_hdr, "Content-Length: %lu", strlen(payload));
ctx.println(content_length_hdr);
ctx.println();
ctx.println(payload);
Serial.println("sent data below;");
Serial.println(payload);
/* receive response */
while (ctx.connected()) {
String line = ctx.readStringUntil('\n');
Serial.println(line);
if (line == "\r") {
Serial.println("headers received.");
break;
}
}
char buf[1 * 1024] = {0};
ctx.readBytes(buf, sizeof(buf)); /* body */
ctx.stop();
M5.Lcd.println(buf);
Serial.println("received data below;");
Serial.println(buf);
Serial.println("### Wait.");
delay(1000 * 10);
}
Soracom Beam設定
Soracom BeamからSlackのWebhookAPIを実行するには、Soracomコンソール側で設定するだけで実現できます。
よくあるAWS Lambda等のサーバーレスファンクションを構築する必要はありません。
設定に関しては、SORACOMのドキュメントが参考になりますので、参考にしてみてください。
デモ
映っていないですが、水分センサーに水滴をたらしたときの、M5Stackの表示とSlack通知結果を貼っておきます。
M5Stackディスプレイ | Slack通知 |
---|---|
終わりに
今回は手元にあるデバイス、センサーを使って作ってみました。
まだ、実践では試せていないので、次回洗濯物を干す際に試してみようと思います。
FutureWorkとして、時間があれば以下の対応をしてみたいと思っています。