この投稿は Electric Imp Advent Calendar 2015 の8日目の記事です。
まだLEDねた
前回はLEDをWebUIから制御してみました。
今回は、携帯電話のSMSを使ってLEDを制御してみたいと思います。
Twilio
さて、ブログラムから電話が絡む操作をするにはTwilioというサービスが便利です。Twilioは専用の電話番号を発行してもらって、電話を受ける、かける、SMSを受信する、SMSを送信するといったことをAPIから行えるサービスです。
アメリカ発のサービスですが、KDDIが日本の代理店となっているようです。
今回はこのサービスをつかって、SMSを送るとLEDをON/OFFしてくれるものをElectric Impで作ってみたいと思います。
電話番号を取得する
まずはTwilioのアカウントが必要です。トライアルのアカウントは無料で作ることができるので、さくっと登録してしまいます。
アカウントができたら、SMSが使える電話番号を取得します。
"利用可能な機能"のSMSにマークがあるものを選びます。日本の電話番号はSMSが使えないみたいなのでアメリカ合衆国の番号にしました。
エージェントのコードを書く
Twilioで取得した番号にSMSを送る -> TwilioがSMS受信のコールバックURLを呼び出す -> Impエージェントが処理 -> Impデバイスに通知 -> LED制御 -> Twilioにレスポンス -> 結果をSMS送信元に返信
ということをやります。
TwilioからSMS受信したときにImpエージェントの特定のURLを呼び出してもらうようにTwilioを設定するので、まずはエージェント側を実装してしまいます。
#require "rocky.class.nut:1.2.3" app <- Rocky(); app.post("/state", function(context) { try { if (!("state" in context.req.body)) throw "Missing param: state"; } catch (e) { context.send(400, e); return; } try { if (!(context.req.body.state == "1" || context.req.body.state == "0")) throw "Invalid value: state"; } catch (e) { context.send(400, e); } local ledState = context.req.body.state.tointeger(); device.send("set.led", ledState); context.send({state = ledState}); }); app.post("/sms/receive", function(context) { local body = context.req.body; // for debug if ("MessageSid" in body) { server.log("MessageSid: " + body.MessageSid); } if ("SmsSid" in body) { server.log("SmsSid: " + body.SmsSid); } if ("AccountSid" in body) { server.log("AccountSid: " + body.AccountSid); } if ("MessagingServiceSid" in body) { server.log("MessagingServiceSid: " + body.MessagingServiceSid); } if ("From" in body) { server.log("From: " + body.From); } if ("To" in body) { server.log("To: " + body.To); } if ("Body" in body) { server.log("Body: " + body.Body); } if ("NumMedia" in body) { server.log("NumMedia: " + body.NumMedia); } context.setHeader("Content-Type", "text/plain; charset=UTF-8"); if (body.Body.find("ON") != null) { device.send("set.led", 1); context.send(200, "ONにしました"); } else if (body.Body.find("OFF") != null) { device.send("set.led", 0); context.send(200, "OFFにしました"); } else { context.send(200, "'ON'または'OFF'のキーワードでLEDを制御します"); } });
前回のコードに "/sms/receive" のリクエストに応答するハンドラを追加しました。SMSを受信すると送信元、送信先、本文などがTwilioから通知されます。どのようなパラメータが通知されるかは、https://jp.twilio.com/docs/api/twiml/sms/twilio_request で解説されています。
ここでは、受信したメッセージの中に ON
または OFF
のキーワードが含まれていたらデバイスのLEDを操作するようにしています。
また、レスポンスとしてテキストを返すことで、メッセージの送信元にテキストを返信しています。
SMSを受信したときに呼び出されるURLを設定する
エージェントのURLをTwilioの設定画面から設定します。
Twilioにログインして、製品一覧 -> プログラマブルSMS -> 電話番号とたどり、取得済みの電話番号を表示させます。電話番号をクリックするとメッセージの設定画面が開くので、 Configure with
を URL
、 Request URL
にエージェントのURL + "/sms/receive" を入力し、 HTTP POST
を選択します。
これで、SMSを受信すると設定したURLが呼び出されるようになりました。
Impをデプロイし、動作を確認してみます。
SMSを送信してみる
iPhoneから実際にSMSを送信してみました。
その時のImpのログはこんな感じです。
2015-12-09 00:46:11 UTC+9 [Agent] MessageSid: xxxx 2015-12-09 00:46:11 UTC+9 [Agent] SmsSid: xxxx 2015-12-09 00:46:11 UTC+9 [Agent] AccountSid: xxxx 2015-12-09 00:46:11 UTC+9 [Agent] From: +81xxxxxxxxxx 2015-12-09 00:46:11 UTC+9 [Agent] To: +1234567xxxx 2015-12-09 00:46:11 UTC+9 [Agent] Body: ONにしてちょ 2015-12-09 00:46:11 UTC+9 [Agent] NumMedia: 0 2015-12-09 00:46:11 UTC+9 [Device] Set LED to state: 1 2015-12-09 00:47:00 UTC+9 [Agent] MessageSid: xxxx 2015-12-09 00:47:00 UTC+9 [Agent] SmsSid: xxxx 2015-12-09 00:47:00 UTC+9 [Agent] AccountSid: xxxx 2015-12-09 00:47:00 UTC+9 [Agent] From: +81xxxxxxxx 2015-12-09 00:47:00 UTC+9 [Agent] To: +1234567xxxx 2015-12-09 00:47:00 UTC+9 [Agent] Body: OFFってください! 2015-12-09 00:47:00 UTC+9 [Agent] NumMedia: 0 2015-12-09 00:47:00 UTC+9 [Device] Set LED to state: 0
まとめ
というわけで今回はSMS経由でLED制御ってことにしてみましたが、正直ElectricImpあまり関係ないかもしれません。今回のケースではTwilioからのリクエストに応答する形でしたが、ElectricImpのエージェント等からTwilioのAPIを叩くこともできます。ElectricImpが提供するライブラリにTwilioのAPIを扱えるものがあるのでそれを使うとなにかイベントが起きた時に、SMSで通知とかできると思います。
ちなみに今回は海外の番号を取得したので、送るSMSも海外宛になり、送受信料は普通に1通50円から100円くらいかかるはずですのでもし試す場合はご注意ください。