みなさん、こんにちは。
私は自宅のインターホンにSwitchBot Botを設置して、Alexa経由で「アレクサ、オートロックを開いて」と声で制御できるようにしています。
当初は「声で操作できるなんて未来的!」と満足していたのですが、実際に運用してみると意外な盲点が……。
急な来訪者が来たとき、焦ってAlexaを呼び出すのが意外と面倒だったり、うまく聞き取ってもらえなかったり……。
「やっぱり、手元に物理ボタンが欲しい……!」
そう思い立ち、手元にあった自撮り棒付属のBluetoothボタン(TAWARON製)を使って、SwitchBotを制御するシステムを構築することにしました。
ただ、Bluetoothボタンの宿命で、よくあるのが接続失敗。毎回、「本当に動いたかな?」と不安になるのは嫌ですよね。
そこで今回は、SwitchBotの操作に加えて、Google Home Notifierを使ってスマートスピーカーから「解錠しました」と音声フィードバックを返す仕組みも組み込むことにしました。
今回は、GitHub Copilotという最強の相棒と一緒に、古いRaspberry Pi(Python 3.5環境)向けにシステムを実装した過程をご紹介します!
事前準備
今回のシステムは、過去の記事で紹介したツールを組み合わせています。以下のセットアップが終わっている前提で進めますので、未読の方はチェックしてみてくださいね。
- google-home-notifierの設定(Google Homeに喋らせる用)
- switchbot.pyの設定(SwitchBotをPythonから叩く用)
Bluetoothボタン(TAWARON)のペアリング
まずはRaspberry Piとボタンをペアリングします。bluetoothctlを使いましょう。
# bluetoothctlを起動
sudo bluetoothctl
# スキャン開始
scan on
# 「TAWARON」が見つかったらペアリング!
pair XX:XX:XX:XX:XX:XX
connect XX:XX:XX:XX:XX:XX
trust XX:XX:XX:XX:XX:XX
exit
権限設定
プログラムからBluetoothデバイス(inputデバイス)を叩けるよう、ユーザーをinputグループに追加しておきます。
sudo usermod -a -G input $USER
# 一度ログアウトしてログインし直すと反映されます
以上で、事前準備は完了です!
いざ開発 – こだわり&改修ポイント
開発を始めるにあたって、まずは先人の知恵を借りようとGitHubで見つけた既存のリポジトリ(300yen-iot-button)をベースにしようと考えました。
しかし、実際に手元の環境で動かしてみると課題が山積みで……。
- evdevライブラリの依存関係が古い
- MACアドレスベースの検出がTAWARONでは動かない
- 最新のPython機能が使われており、Raspbian Stretch(Python 3.5)でエラーが出る
「これ、ほぼ作り直した方が早いのでは……?」と思い、GitHub Copilotをフル活用して大幅な書き換えを行いました。
1. evdevを廃止し、低レベルイベント監視へ
古いライブラリへの依存を避けるため、/sys/class/input/event* から直接バイナリデータを読み取る方式に変更しました。Copilotに「Linuxのinput_event構造体をPythonのstructモジュールで解析するコードを書いて」と頼んで、サクッと実装。
# Copilotと一緒に書いた binary unpack ロジック
# Linuxの timeval (32bit) フォーマットに対応
tv_sec, tv_usec, evt_type, code, value = struct.unpack('IIHHi', data)
2. デバイス検出を「名前ベース」に
TAWARONは内部に複数のサブデバイスを持っており、MACアドレスベースの検出が不安定でした。そこで、「”Keyboard” という文字列を含むデバイスパスを探す」というロジックにCopilotと相談しながらリライト。これで確実にキー入力イベントをキャッチできるようになりました。
3. Python 3.5 互換性への執念(f-stringよ、さらば)
今回の環境はPython 3.5.3。モダンなf-stringやsubprocess.runの便利な引数が使えません。Copilotに「このコードをPython 3.5でも動くように書き換えて」と指示し、すべてのf-stringを.format()へ、subprocessをPopenベースのレガシーな書き方へ修正しました。
4. 堅牢な再接続&連打防止
Bluetoothボタンはすぐスリープに入るため、エラーハンドリングが重要です。
- デバイスが外れてもループで再検索し続けるロジック
- 1秒以内のチャタリングを無視するガード
これらを追加し、実用性を高めました。
設定ファイルでメンテナンスしやすく
設定はconfig.pyに外だしして、一箇所で管理できるようにしました。MACアドレスやIPアドレスなど、環境依存の設定を簡単に変更できます。
CONFIG = {
"BUTTON_DEVICE_NAME": "TAWARON",
"SWITCHBOT_MAC_ADDRESS": "**:**:**:**:**:**",
"IP_ADDRESS": "192.168.**.**", # Google HomeのIP
"NOTIFIER_PORT": 8091,
"NOTIFICATION_TEXT": "ドアを解錠しました",
"MULTIPLE_PRESS_THRESHOLD": 1.0, # 連打防止(秒)
"PYTHON_HOST_PATH": "/path/to/switchbot.py",
}
systemdに登録して自動起動を仕込む
24時間365日動いてほしいので、systemdに登録します。bt-button.service というUnitファイルを作成します。
[Service]
ExecStart=/usr/bin/python3 /path/to/bt_button.py
Restart=always
RestartSec=10
これを /etc/systemd/system/ に放り込んで sudo systemctl enable すれば、ラズパイ起動時に自動で立ち上がります。
まとめ
既存コードの課題をGitHub Copilotと一緒に乗り越えることで、以下のメリットが得られました!
- ✅ 環境を選ばない:ライブラリ依存を減らし、古いOSでも動作。
- ✅ 安定した検知:デバイス名ベースの柔軟なフィルタリング。
- ✅ 運用性:音声通知によるフィードバックと、systemdによる常駐化。
今回開発したソースコードはGitHubで公開しています。環境依存が強い部分もありますが、普段Pythonを触っているエンジニアならきっと「いい感じ」に調整して使えるはず。ぜひ試してみてください!
🔗 GitHubリポジトリ:bt_button_for_switchbot
本日も最後までお読みいただきありがとうございました。
それでは、よいIoTライフを!



