概要
VolumioをREST APIから操作するダッシュボタン(リモコン)を作って動作を確認した。
背景と目的
先日構築したラズパイオーディオは、スマホやPCのブラウザから操作しているのだが、ボリュームやトラック送りといった基本的で簡単な操作のためにいちいち画面を開くのが面倒だったりする。何か簡単にする手段はないかと考えたが、やはりハードボタンに勝るものはないなと思った。そこで、ハードボタンをつけようと思う。
詳細
1.構想
Volumioを操作する手段は、いくつかあると思われるが、すぐに試せるものとしてはREST APIがある。Webブラウザで簡単に試したところ、レスポンスも悪くなく、やりたい操作はちゃんとAPIが用意されているので問題なさそう。なので、これを活用する。
REST APIをたたくためのハードは、以前作成したESP-WROOM-32によるダッシュボタンが手元にあるので、これを活用してAPIをたたくソフトをのせればよさそうだ。
ダッシュボタンは、3つしかボタンがないが、だいたいよくやる操作は、再生/停止、VOL上下、トラック送り/戻しなので、これが割り当てられれば良い。
2.ソフト実装
ソフトは、Arduinoで開発。
2.1 簡単な仕様
- 赤ボタン = 再生/停止
- 緑ボタン = トラック戻し
- 青ボタン = トラック送り
- 赤を押しながら、緑ボタン = VOL DOWN
- 赤を押しながら、青ボタン = VOL UP
2.2 実装
2.21 APIをたたく
REST APIをたたく処理をまとめた関数を用意。引数に応じてたたくAPIを選択。
String send(String url) { String response = ""; WiFiClient client; if (!client.connect(HOST, 80)) { Serial.println("connection failed"); return response; } // This will send the request to the server client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + HOST + "\r\n" + "Connection: close\r\n\r\n"); unsigned long timeout = millis(); while (client.available() == 0) { if (millis() - timeout > HTTP_TIMEOUT * 1000) { Serial.println(">>> Client Timeout !"); client.stop(); return response; } } // Read all the lines of the reply from server and print them to Serial while(client.available()) { response = client.readStringUntil('\r'); } return response; }
2.22 ボリュームの操作
Volumio REST APIの仕様上、ボリュームは、変化量ではなく設定したい値を送信する必要がある。なので、VOL DOWN、UPは一筋縄ではいかない。/api/v1/getstateというリソースパスをたたき、現在のボリューム値を取得してから変化分を足して再度APIに送信しなければならない。その操作をまとめたのが、get_current_volという関数。
// 現在のVOLを取得 int get_current_vol(){ String line = send("/api/v1/getstate"); int i1 = line.indexOf("\"volume\":"); int i2 = line.indexOf(",", i1); String str_vol = line.substring(i1 + 9, i2); int current_vol = str_vol.toInt(); return current_vol; }
2.23 押されたボタンによって動作を切り替える
ダッシュボタンの基本的動作は、押されたときに起動してWi-Fi接続し何らかの処理をしてスリープという流れ。押されたボタンがwakeup_pinという変数で判断できるようにしてあるので、何が押されたかを判断して、URLを組み立て送信する。
String url = "/api/v1/commands/"; if (wakeup_pin & GPIO_RED) { bool volup = false; bool voldown = false; while (digitalRead(GPIO_RED_PIN) == HIGH) { if(digitalRead(GPIO_GRN_PIN) == HIGH) { voldown = true; break; } if(digitalRead(GPIO_BLU_PIN) == HIGH) { volup = true; break; } delay(100); } if (volup) { url += "?cmd=volume&volume=" + String(get_current_vol() + 5); Serial.println("VOLUP button has been pushed."); } else if (voldown) { url += "?cmd=volume&volume=" + String(get_current_vol() - 5); Serial.println("VOLDOWN button has been pushed."); } else { url += "?cmd=toggle"; Serial.println("Red button has been pushed."); } } else if (wakeup_pin & GPIO_GRN) { url += "?cmd=prev"; Serial.println("Green button has been pushed."); } else if (wakeup_pin & GPIO_BLU) { url += "?cmd=next"; Serial.println("Blue button has been pushed."); } // 送信 send(url);
3.動作確認
上記のプログラムを書き込み、ボタン動作を確認したところ、正しく動作した。というわけで、スマホなしで簡単に操作できる!!!
まとめ
Volumio用のダッシュボタンを作成できた。Volumio環境が快適になった。