はじめに
こんにちは。電気毛布を自動制御しようと頑張っているエンジニア@tmitsuoka0423です。
以前、obnizを使った電気毛布制御システムを作成しました。
手元に M5StickC があったので、上記の記事で作成したプログラム同等のスケッチを作成し、快適な睡眠生活を送っていました。
また、Ambientというサービスを使い、測定した布団の温度などを可視化して楽しんでいました。
Wi-Fi接続のために、毎回ソースを書き換える?
ある日、フィードバックをもらうため知人に電気毛布システムを貸すことになったのですが、そこで問題が発生しました。
M5StickC に書き込んでいるスケッチに、私の家のネットワーク接続情報がハードコーディングされていたのです。
これでは知人の家のネットワークにつながりません。
String ssid = "hoge";
String password = "hogehoge";
WiFi.begin(ssid, password);
幸い、知人は IoT にとても明るいエンジニアでしたので必要なソースコードを渡し、自分でSSIDとパスワードを書き換えてM5ScickCに書き込んでくれとお願いできました。
このシステムは、実はArduinoスケッチを修正して、M5StickCに書き込める人しか使えない仕組みになってしまっていたのです。
製品化を考える上で、使える人という観点であまり制約を設けたくありません。
そこで本記事では、スマホからネットワーク接続情報を入力できる仕組みとソースコードを紹介します。
ネットワーク接続までの流れ
接続の流れとしては、大まかに2ステップとなります。
- スマホと M5StickC を Wi-Fi 接続し、ネットワーク接続情報を M5StickC に送る
- M5StickC をネットワークに接続する
なお、ソースコードはすべて[m5stickc-wifi-entry-sample-public]にアップしていますので、全量はこちらからご確認ください。
記事では、ソースコードをピックアップして説明します。
⓪起動時はアクセスポイントモード
M5StickC は実はアクセスポイントとして振る舞うことができます。
以下のように書くと、M5StickC がアクセスポイントとなり
- SSID: "M5S_AP"
- Password: "12345678"
で、スマホや PC から Wi-Fi 接続できるようになります。
WiFi.softAP("M5S_AP", "12345678");
(1)スマホからM5StickCにWi-Fi接続する
スマホで Wi-Fi 一覧を見ると、M5S_AP
があるはずです。
パスワードを入力して接続します。
(2)ネットワーク接続情報入力ページを表示する、(3)送信する
M5S_AP
に接続した状態で、http://192.168.4.1/
にアクセスすると以下のような画面が表示されるので、家にあるネットワークの SSID とパスワードを入力します。
表示されている画面は、M5StickC から HTML を返却しています。
接続するボタン
をタップすると、form が GET で送信されます。
WiFiServer server(80);
WiFiClient client = server.available();
String s = "";
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
s += "<!DOCTYPE html>";
s += "<html lang=\"ja\">";
s += " <head>";
~~~~~~~~~~~~~~~~~~~~(略) ~~~~~~~~~~~~~~~~~~~~
s += " <main>";
s += " <form method=\"GET\" action=\"/connect\">";
s += " <input type=\"text\" name=\"ssid\" placeholder=\"SSID\" />";
s += " <input type=\"password\" name=\"password\" placeholder=\"Password\" />";
s += " <button type=\"submit\">接続する</button>";
s += " </form>";
s += " </body>";
s += "</html>";
client.print(s);
client.flush();
client.stop();
(4)M5StickCをネットワークに接続する
スマホで入力したネットワーク接続情報を受け取るには以下のようなコードを書きます。
String req = client.readStringUntil('\r');
int addr_start = req.indexOf(' ');
int addr_end = req.indexOf(' ', addr_start + 1);
String path = req.substring(addr_start + 1, addr_end); // path -> "/connect?ssid=<SSID>&password=<Password>"
String 型の変数path
にSSID
とパスワード
が入ってくるので、正規表現かなにかで抜き出し、以下のコードを書きます。
WiFi.begin(ssid, password);
ネットワーク接続に成功した場合、M5StickC のモニタにConnected!
と表示されます。
シリアルモニタで、ローカル IP アドレスも割り当てられていることが確認できました。
蛇足
- よく思い出したら、スマートコンセントHS105を Wi-Fi に接続するときに似たような手順で接続していた(HS105 はスマホアプリだった)
- なんとなく裏側の実装がわかったと同時に、"誰でも IoT 製品を Wi-Fi に接続する方法"としてある種の答え合わせができた気がする。
- ライブラリとして公開していきたい