長年Amazon Echoを使ってきましたが、試しに触ってみたHomebridgeの使い勝手がAlexaとは雲泥の差だったので、Siri+Homekit+Homebridgeに乗り換えることにしました。プラグインで対応デバイスを増やせる上に、プラグイン開発が盛んなのが良いですね。

で、我が家のガレージの電動シャッター(文化シヤッター製)には、USB経由で給電されている間はシャッター開放の信号を送り続け、給電が止まったりシャッターから離れたりして信号が届かなくなるとシャッターが閉まる、という仕組みの「セレクルーズII」というリモコンが付属していたんですが、これを使ってHomebridge経由でシャッターを開閉出来ないかな?と。

まずUSB給電のオンオフですが、どこのご家庭にも一つか二つか三つは転がっているRaspberry PiってUSBバスパワーのオンオフが可能なので、これを使おうと。USBポートひとつひとつを制御するのはちょっと面倒なんですが、ポート全体なら以下のコマンドでオンオフ出来ます。

# オフにする時:
echo -n "1-1" > /sys/bus/usb/drivers/usb/unbind

# オンにする時:
echo -n "1-1" > /sys/bus/usb/drivers/usb/bind

で、せっかくなので同じRasPi上でHomebridgeも動かしちゃいます。HomebridgeにはRasPi用のイメージもあるので楽チンです。あとはHomebridgeがインストールされたマシン上でコマンドを実行できるCMD4というプラグインがあるので、このプラグインの仕様に合わせてバスパワーをオンオフするシェルスクリプトを書いて登録すれば完成です。

今回はCMD4を使用。Homebridgeの設定からJSON Configを開き、GarageDoorOpenerというデバイスを直書きで追加します。

    "platforms": [
        {
            "name": "Config",
            "port": 8581,
            "platform": "config"
        },
        {
            "platform": "Cmd4",
            "name": "Cmd4",
            "debug": true,
            "accessories": [
                {
                    "type": "GarageDoorOpener",
                    "displayName": "Shutter",
                    "currentDoorState": "OPEN",
                    "targetDoorState": "OPEN",
                    "obstructionDetected": "FALSE",
                    "lockCurrentState": "UNSECURED",
                    "lockTargetState": "UNSECURED",
                    "name": "Shutter",
                    "manufacturer": "Bunka Shutter",
                    "model": "Anything",
                    "serialNumber": "12345",
                    "stateChangeResponseTime": 30,
                    "state_cmd": "/home/pi/bin/shopen.sh",
                    "polling": [
                        {
                            "characteristic": "targetDoorState",
                            "interval": 60,
                            "timeout": 8000
                        },
                        {
                            "characteristic": "currentDoorState",
                            "interval": 60,
                            "timeout": 8000
                        }
                    ]
                }
            ]
        }
    ]

そしてCMD4から実行されるシェルスクリプトを作成。こちらはCMD4の Extras/Cmd4Scripts/Examples/ExampleShellScript_template.sh をほぼそのまま使っています。ざっくり説明するとシェルスクリプトは「Get/Set」「デバイス名」「特性」「true/false」の4つの引数付きで実行され、Getは現在の状態を取得、Setは状態を変更する場合(ドアの開閉)に用いられます。

#!/bin/bash

set -e

length=$#
device=""
io=""
characteristic=""
option=""

if [ $length -le 1 ]; then
printf "Usage: $0 Get < AccessoryName > < Characteristic >\n"
printf "Usage: $0 Set < AccessoryName > < Characteristic > < Value >\n"
exit -1
fi


if [ $length -ge 1 ]; then
io=$1
# printf "io=$io\n" # debug
fi
if [ $length -ge 2 ]; then
device=$2
# printf "device = ${device}\n" # debug
fi
if [ $length -ge 3 ]; then
characteristic=$3
# printf "Characteristic = ${characteristic}\n" # debug
fi
if [ $length -ge 4 ]; then
option=$4
# printf "option = ${option}\n" # debug
fi


if [ "${io}" == 'Get' ]; then
case $characteristic in
'CurrentDoorState')
PSTATUS=$(lsusb | wc -l)
if [ $PSTATUS -gt 2 ]; then
printf "0\n"
else
printf "1\n"
fi
exit 0
;;
'TargetDoorState')
printf "0\n"
exit 0
;;
'ObstructionDetected')
printf "0\n"
exit 0
;;
'LockCurrentState')
printf "0\n"
exit 0
*)
printf "UnHandled Get ${device} Characteristic ${characteristic}\n"
exit -1
;;
esac
fi

if [ "${io}" == 'Set' ]; then
case $characteristic in
'CurrentDoorState')
exit 0
;;
'TargetDoorState')
if [ $option -eq 0 ]; then
sudo sh -c "echo -n \"1-1\" > /sys/bus/usb/drivers/usb/bind"
else
sudo sh -c "echo -n \"1-1\" > /sys/bus/usb/drivers/usb/unbind"
fi
exit 0
;;
'ObstructionDetected')
exit 0
;;
'LockCurrentState')
exit 0
;;
*)
printf "UnHandled Set GarageDoorOpenner Characteristic ${characteristic}"
exit -1
;;
esac
fi

printf "Unknown io command ${io}\n"
exit -1

 あとはHomekitにHomebrigeを追加して「Siri、シャッターを開けて」「シャッターを閉めて」みたいな感じで操作します。

使ってみた感想ですが、「開放の電波が途絶えるとシャッターを下ろす」というセレクルーズの仕様上、セレクルーズは「閉」の状態&通常のリモコンで開けた状態で「シャッターを閉めて」と言っても閉まらないのは、動作として正しいのだけど使い勝手としてはイマイチだなあと。やはり指ロボットでリモコンを操作するのが正しいのか……