配信に連動するON AIRランプを作った
MaBeee + Raspberry Pi 5 + Firebotを使った配信に連動するON AIRランプを作った話
配信してるかどうか分かりづらい問題
今は住民一人だけなこともあり、以前と変わらずTwitch配信を続けています。そん中、住民から「デスクトップPCの前にいるときに配信しているのかしていないのかわからないから、用があっても声を掛けづらいことがある」との声が挙がりました。声をかけられると困る配信(というのもあまりないだろうけど)のときは事前に伝えるつもりなので、基本的にいつでも声をかけてもらってもいいというスタイルなのだけど、確かに分かりづらいし、なんとなく話しかけたいけど配信中だったら後でいいみたいな微妙な塩梅のときもありそうです。
というわけで、配信中か否かがわかる仕組みを導入することにしました。
ON AIRランプをMaBeee + Raspberry Piで操作する
こういうとき真っ先に思い浮かぶのは、テレビとかラジオとかにありそうなON AIRランプですね。調べるとAmazonで数千円で入手できるっぽい。
今回購入したのはALFOTOというところのやつで、ポイントは電源がUSBと乾電池(単3×3本)に両対応しているところ。特にスマート化しなくても乾電池動作なら配線とかを考えなくて済むのでこれだけで結構便利そう。
オンエアランプを何らか制御しようと思ったときに1番に思いつくのは電源にスマートプラグを用いるものですが、色々調べるうちに下の記事を見つけました。
この記事で乾電池動作できるランプとBluetooth制御できるMaBeeeというIoT乾電池を知りました。乾電池を制御できるとなると色々応用ができそうなので、今回ぜひ試してみたくなりました。
このMaBeeeは元々プログラミング教育用の教材として展開されているようなのですが、公式が提供しているSDKがiOSとAndroidのみで、さらに開発者が趣味で開発したMacAppがあるのみという状況です。Linuxで動作すれば手持ちのRaspberry Pi 5でとりあえず試せるので非常に助かるんだけどなーと思いながらググったら先人のコードが見つかりました。
実際に試したらうまく動作しました。ありがたい。
他のプログラムから制御できるようにしたいのでHTTPサーバーでリクエストを受けるようにしました。このあたりは今はChatGPTがサクっと書いてくれるので非常に助かります。
工夫しどころとして、http://pi5のローカルアドレス:5000/control
にMaBeeeのMacアドレスとPWMの値をペイロードにしてPOSTリクエストをして任意のMaBeeを操作できるように少し汎用性を持たせてあります。あとはBluetooth通信が不安定なときのために何回かリトライもさせるようにしました。
import time
from flask import Flask, request, jsonify
from bluepy import btle
app = Flask(__name__)
def connect(mac_addr, retries=3, delay=5):
for attempt in range(retries):
try:
peripheral = btle.Peripheral()
peripheral.connect(mac_addr, btle.ADDR_TYPE_RANDOM)
return peripheral
except Exception as e:
if attempt < retries - 1:
time.sleep(delay)
else:
raise e
def write_pwm(peripheral, value):
PWM_HANDLE = 17
PWM_INDEX = 1
data = bytearray(peripheral.readCharacteristic(PWM_HANDLE))
data[PWM_INDEX] = value
peripheral.writeCharacteristic(17, bytes(data), True)
@app.route('/control', methods=['POST'])
def control_device():
data = request.json
if 'mac_addr' not in data or 'pwm_value' not in data:
return jsonify({'error': 'Invalid input'}), 400
mac_addr = data['mac_addr']
pwm_value = int(data['pwm_value'])
if not (0 <= pwm_value <= 100):
return jsonify({'error': 'PWM value must be between 0 and 100'}), 400
try:
peripheral = connect(mac_addr)
write_pwm(peripheral, pwm_value)
peripheral.disconnect()
return jsonify({'status': 'success'}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
FirebotからPi5経由でオンオフさせる
さて、今回の全体構成は以下のような感じです。
さて、Pi5から直接Twitchの配信状況を取得するという方法もありますが、結局のところ僕は配信中にはFirebotを使用しているので、Firebotで配信開始/終了のイベントをサブスクライブする構成にしました。Firebotは他の有名どころのTwitch Chatbotと比べると明らかにノーコードツール寄りで基本何でもできて便利です。
今回の目的はPC前にいるときの配信状況の可視化なのでこれでいいですが、例えば出先で配信しているときも光らせたいみたいな状況であれば、Pi5で制御したほうがいいと思います。(Firebotを常時起動しているような環境を除く)
Firebotの方でも使いまわししやすいようにPreset Effect ListでMaBeee操作のEffectを作っておきます。引数にMacアドレスとPWMをもたせるようにすることでFirebotからも呼び出しやすくなります。pi5のIPアドレスは固定化しておきましょう。(加えて僕はルーターの静的DNSでローカルドメインを割り振りました。便利〜。)
あとは好きなタイミングでMaBeeeの操作を呼び出します。今回は配信開始時に点灯、配信終了時に消灯という設定です。
こんな感じで配信に連動したON AIRランプが出来上がりました。1番難しいプログラム部分もChatGPTに書かせてるのでかなりハードル低くなってるように感じます。
気づき
- MaBeeeは単3の中に単4電池を入れて動作するが、規格の違う電池を直列で使用すると液漏れのリスクが高まるらしいのでスペーサーを導入して単4で統一させた。
- Pi5内蔵のBluetoothおよびMaBeeeのBluetoothも相当弱く、機器の影響をモロに受ける。壁を挟んだり、MaBeeeとPi5の間にWifiアクセスポイントがあるだけでほぼ繋がらなくなった。
- これを改善するためにLinux動作したというレビューのある外付けBluetoothアダプタを試してみたが、これもかなり不安定。どうやら最新カーネルでPi5のときにだけ非常に不安定になるバグがあるらしい。今回は面倒なので内蔵BTでやることにした。
- 上記のような状況なので、MaBeeを使う場合は現実的には近距離にMaBeee操作の母艦マシンを置くことになる。今回は稼働中のPi5でやったが、Raspberry Pi Zero 2 Wだったり安価なマイコンとかでいい気がする。
- 配線に問題がなければスマートプラグのほうが安定かつ安価にできるはず。
今回使ったもの