ESP8266を使った様々な通知
いま、ネットに散らばってる様々なセンシング方法をカスタマイズして自作のホームセキュリティをESP8266で作っていたんですけど、作りこんでから、
ESP32のほうが良かったのでは・・・?
と思いつつ後には引けない状態となっていますw。ホームセキュリティを実現するためには異常があった時「アラーム(警報音)を鳴らす」等の自律的な動作のほかに、ご主人様の携帯端末にアラートなど、速やかに情報フィードバックする必要が出てきます。通知をする上で可能性があるのは
- 電話をかける
- SMSを送り付ける
- メールを送る
- SNSで連絡する
この4つぐらいかなと思います。この中でも、LINEは家族の間でも利用率が高く、異常があった時にグループで通知ができるので家族の誰かが速やかに気づくことができるかなと思い4のSNS(LINE)で行おうと思った次第です。
ESP8266からLineNotifyを利用する
上のサイトを読んだ通り、Webサービスから通知を送り付けることができるサービスです。
上のサイトはPHPで行っていますが基本は、HTTPS(443)でnotify-api.line.meに接続し、/api/notifyにリクエストを投げるだけです。HTTPS接続なのでESP8266ではWiFiClientSecureを使うことになります。実際、ESP8266で利用している記事も数件見かけました。
このサイトを見て・・・
さくっとソースを
コピペ参考にササっと自分用のサンプルコードをつくろう
と思ったんですが、いくらやっても、client.connect(host,port)のところでコケルんですよ。ネットにうまく繋がってないのかと思い、WiFiClientに切り替えて別なサイトに80ポートで接続してみたけど問題なく接続できるので、HTTPS(WiFiClientSecure)がらみの問題かなと思い調査開始。
そこで見つけたのが以下のブログ。ESP8266で自サイトにHTTPS接続して取得してみるという記事。コピペで動くとのことなので、問題の切り分けに利用させていただく。
1 2 3 4 |
if (!client.connect(host, httpsPort)) { Serial.println("connection failed"); return; } |
ここでも上の部分でconnection failedになる。さらに調査すると・・・
をみつける。まさにこれなんだけど解決方法は
1 |
client.setInsecure(); |
を入れろ!とのこと。これは何だろうと調べてみると
ようはFingerPrint(指紋)を使わずに接続する方法とのこと。FingerPrintを使った方法だと僕はどうしても動かせなかったのでこちらを使おうと思います。逆を言えばFingerPrintには証明書に有効期限があるので使いたくなかったのでよかったです。
さっきのコピペして検証できるブログのコードのsetup()の先頭にclient.setInsecure();を入れてclient.setFingerprint(fingerprint);をコメントアウトして動かしてみると無事コンテンツがHTTP経由で取得できたのでLINE Notiftyの書き換えを行ってみました。
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
#include <ESP8266WiFi.h> #include <WiFiClientSecure.h> const char* ssid = "ssid"; const char* password = "password"; const char* lineApiToken = "LINE API TOKEN"; // https://devdocs.line.me/files/sticker_list.pdf int stickerPackage = 1; int stickerId = 113; const char* host = "notify-api.line.me"; const String url = "/api/notify"; const int httpsPort = 443; WiFiClientSecure client; void setup() { client.setInsecure(); Serial.begin(115200); // Connect to Wi-Fi WiFi.mode(WIFI_STA); delay(100); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi.."); } Serial.println(WiFi.localIP()); delay(1000); } void loop() { String message = "テストメッセージです"; lineNotify(message, 0, 0); delay(30 * 1000); message = "テストスタンプです"; lineNotify(message, stickerPackage, stickerId); delay(30 * 1000); } // if stkid or stkpkgid is 0, a sticker is not sent. void lineNotify(String message, int stkpkgid, int stkid){ //digitalWrite(ledPin, HIGH); Serial.print("connecting to "); Serial.println(host); if (!client.connect(host, httpsPort)) { Serial.println("connection failed"); return; } /* if (!client.verify(fingerprint, host)) { return; } */ Serial.print("requesting URL: "); Serial.println(url); String lineMessage = "message=" + message; if((stkid != 0) && (stkpkgid != 0)){ lineMessage += "&stickerPackageId="; lineMessage += stkpkgid; lineMessage += "&stickerId="; lineMessage += stkid; } String header = "POST " + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: ESP8266\r\n" + "Authorization: Bearer " + lineApiToken + "\r\n" + "Connection: close\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: " + lineMessage.length() + "\r\n"; client.print(header); client.print("\r\n"); client.print(lineMessage + "\r\n"); Serial.print("request sent:"); Serial.println(lineMessage); String res = client.readString(); Serial.println(res); client.stop(); } |
参考サイトの【土壌センサー + LINE Notify】水やりが必要になったらLINE通知の記事のスケッチからセンサー部のコードなどを除去して単純な投稿スケッチにしました。FingerPrintは利用しないため、setup()にclient.setInsecure();を入れてclient.verify(fingerprint, host);はコメントアウトしています。とりあえず、これで動作するようになりました。
余談ですけど、スタンプのIDの紹介ページが
上のPDFにリンクされていましたが、公式のリファレンスのサイトをみてみると
になっています。上のリンクのPDFのIDをいれても送信できないので注意してください
追記[2020-06-04]
後日またブログに書こうと思いますが、けっこうガチ目なホームセキュリティを組んでいくとメモリが逼迫してくると思います。WiFiClientSecureを使うと結構な実行コストがかかるようで接続エラーになるようです。
EPS8266でWiFiClientSecureを使わない方法として、別サーバーにPHPを設置し、ESP8266HTTPClient等を用いてリクエストをPHPに送り、PHPからLineNotifyに通知を送る形にした方が余計な負担をかけなさそうです。
あと、別サーバーとかPHPがめんどくさい人は、IFTTTを使ってLINEに通知するのがメジャーな方法でしょう。
ESP8266にとってWiFiClientSecurはメモリ大食いで、すぐにコケてしまう子のでなので完全なスタンドアローンにするにはスケッチの大幅な見直しが必要となったり、動作が不安定になることが予想されます。単機能とかなら問題ないと思いますよ。