SonoSwitchをつくるお!
前回までのあらすじ
SonosはIFTTTから制御できそうというところまでわかりました。
今回は、IFTTTのSonos Actionsを使うべく、WebhooksをTriggerとして、M5StackからIFTTT経由でSonosのスピーカーの制御をしてみようと思います。
M5Stackって?
詳しい説明は省きますが、ディスプレイやWi-Fi/BTなどがもろもろついた小さなマイコンボードです。
プログラミング方法も色々ありますが、ブラウザ上でノンコーディングでプログラミングできるUI Flowを使って実装してみようと思います。
やりたいことは以下の通り。
- Sonosのスピーカーを制御(Prev/Next/Pause)できる
SonoSwitch
- おしゃれなUIを表示
- ボタンを押すと制御(Prev/Next/Pause)が行えるようにする
- 裏ではIFTTTのWebhooksへHTTP-GETを行う
IFTTT側の設定
先述の通り、TriggerをWebhooks、ActionをSonosとなるようにレシピを設定します。
レシピは別々のWebhooksイベントで3つ作成します。今回は、それぞれのイベント名をこのようにしました。
- sonoswitch1:Skip to previous
- sonoswitch2:Pause
- sonoswitch3:Skip to next
To trigger an Event Make a POST or GET web request to: https://maker.ifttt.com/trigger/{event}/with/key/{key}
それぞれのイベントごとにURLが決まり、ここにHTTP-GETをするとSonosのActionが発火するようになりました。今度は、M5StackからこれらのURLをHTTP-GETできるようにしていきます。
つぎにM5Stack側の実装
とはいえ、まずは(本質的ではないですが)UIを作ってみます。
macOSのKeynoteでこんな感じのUIを作ってJPGで保存し、UI Flow経由でM5Stackに流し込みます。SonosのロゴのフォントはGIll Sans
が一番近かったです(笑)
UI Flowでは、こんな感じに実装していきます。
MicroPythonのコードは、この記事の後ろの方で晒します。やっていることはざっくりこんな感じで、
- 起動時にWi-Fi接続
- ボタン押下時にそれぞれのレシピへのWebhooksへHTTP-GETを送るようにする
- HTTP-GET成功/失敗時に効果音を出す
これをUI Flowで組んでいきます。
つかってみますー
これが、ふつーに使えます(笑)
Sonosのスピーカーに直接コマンドを送っているわけではないので、1〜2秒のタイムラグはあるものの、Sonosのスピーカーの制御がちゃんとできています!
逆に言えば、インターネット回線さえあれば、理論上は地球の裏側からもSonosのスピーカーを制御できるということですねー。すごいー。
コードはこんな感じです
from m5stack import * from m5ui import * from uiflow import * import wifiCfg import urequests setScreenColor(0x222222) image0 = M5Img(0, 0, "res/SonoSwitch.jpg", True) statusCode = None def buttonB_wasReleased(): global statusCode if not (wifiCfg.wlan_sta.isconnected()): wifiCfg.reconnect() while not (wifiCfg.wlan_sta.isconnected()): pass try: req = urequests.request(method='GET', url='http://maker.ifttt.com/trigger/sonoswitch2/with/key/xxxxxxx', headers={}) except: pass statusCode = req.status_code pass btnB.wasReleased(buttonB_wasReleased) def buttonA_wasReleased(): global statusCode if not (wifiCfg.wlan_sta.isconnected()): wifiCfg.reconnect() while not (wifiCfg.wlan_sta.isconnected()): pass try: req = urequests.request(method='GET', url='http://maker.ifttt.com/trigger/sonoswitch1/with/key/xxxxxxx', headers={}) except: pass statusCode = req.status_code pass btnA.wasReleased(buttonA_wasReleased) def buttonC_wasReleased(): global statusCode if not (wifiCfg.wlan_sta.isconnected()): wifiCfg.reconnect() while not (wifiCfg.wlan_sta.isconnected()): pass try: req = urequests.request(method='GET', url='http://maker.ifttt.com/trigger/sonoswitch3/with/key/xxxxxxx', headers={}) except: pass statusCode = req.status_code pass btnC.wasReleased(buttonC_wasReleased) statusCode = -1 wifiCfg.autoConnect(lcdShow = False) while not (wifiCfg.wlan_sta.isconnected()): pass speaker.tone(1800, 100) while True: if statusCode > 0: if statusCode == 200: speaker.tone(1800, 100) speaker.tone(2400, 100) else: speaker.tone(1800, 300) statusCode = -1 wait_ms(2)