Raspberry PiとGoogle HomeとSwitch Botと

Switch Botに興味があったので買ってしまった。2個で7000円なので一つあたり3500円。これぐらいの値段なら買ってもいいかなと思える。

Google Homeを持っておりGoogle HomeからSwitch Botを動かすのが本命。Google Homeと連携しようと思うとSwitch Linkが必要になるがこれはいい値段するので買うのを躊躇してしいた。色々調べてみるとRaspberry Piから操作できるようなのでRaspberry Piで操作する(汎用性も高いしね)。エンジニアなのに恥ずかしながらRaspberry Piを触ったことがないのでいい機会だ。個人的なRasPiの設定も後日書く予定


Raspberry PiGoogle Homeの連携について参考にしたのは以下
IFTTTとBeebotteを使ってGoogleHomeからRaspberryPiを操作する - Qiita

おかげさまでGoogle Homeに話しかけて何かしらのレスポンスを受け取れるようになった(Beebottle便利ですね)。ここまでくればこっちのものであとはSwitch Bot にかぎらずpythonでなんでもできる。今後も何かやっていこう。
Switch Botpythonで動かすコードはこちら。このSwitch Botを動かす処理をon_messageの中に書けば終わり。これでGoogle HomeからSwitchLinkを使わずにSwitch Botを動かせるようになった。

ただ困ったところが2つある。
一つ目は反応が少し遅い。p = Peripheral("ff:ff:ff:ff:ff:ff", "random")で接続した時に失敗することがある(失敗しても1回ぐらい)。これはfor文tryすることでなんとかなる。
二つ目の問題は重大でセキュリティに関して。SwitchBotは専用アプリがあって一つ一つのSwitch Botにパスワードを設定できる。パスワードを設定することで他人がSwitch Bot動かせないようになっており安心。なのだがパスワードを設定すると上記pythonスクリプトが動かない。つまり現状Google HomeからセキュアにSwitch Botを動かすにはSwitchLinkしか選択肢がない。うーむ、どうしたもんか。
なおソースコードはこちら。まあ殆ど上記の記事のまんまである。

import json
import logging
import time

import paho.mqtt.client as mqtt
import binascii
from bluepy.btle import Peripheral


TOKEN = "token_***********"  # beebottleのチャンネルトークン
HOSTNAME = "mqtt.beebotte.com"
PORT = 8883
TOPIC = "channel_name/resource_name"
CACERT = "mqtt.beebotte.com.pem" # 証明書 https://beebotte.com/certs/mqtt.beebotte.com.pem

SWITCH_MAC = "ff:ff:ff:ff:ff:ff"
SWITCH_NAME = "switch_name"

_LOGGER = logging.getLogger(__name__)

class SwitchBot:
    def __init__(self, name, mac):
        self._mac = mac
        self._name = name

    def turn_on(self):
        for connection in range(1,6):
            try:
                p = Peripheral(self._mac, "random")
            except:
                _LOGGER.error(f'Connection attempt failed after {connection} tries')
                time.sleep(1)
                continue
            break
        else:
            _LOGGER.error('Connection to Switchbot failed')

        try:
            hand_service = p.getServiceByUUID("cba20d00-224d-11e6-9fb8-0002a5d5c51b")
            hand = hand_service.getCharacteristics("cba20002-224d-11e6-9fb8-0002a5d5c51b")[0]
            hand.write(binascii.a2b_hex("570100"))
            p.disconnect()
        except:
            _LOGGER.error("Cannot connect to switchbot.")

switch_bot = SwitchBot(SWITCH_NAME, SWITCH_MAC)


def on_connect(client, userdata, flags, respons_code):
    print('status {0}'.format(respons_code))
    client.subscribe(TOPIC)

def on_message(client, userdata, msg):
    data = json.loads(msg.payload.decode("utf-8"))["data"][0]
    data = {key:value.strip() for key, value in data.items()}
    #  この辺で条件分岐してスイッチを動かす
    swich_bot.turn_on()

client = mqtt.Client()
client.username_pw_set(f"token:{TOKEN}")
client.on_connect = on_connect
client.on_message = on_message
client.tls_set(CACERT)
client.connect(HOSTNAME, port=PORT, keepalive=60)
client.loop_forever()

パスワードを設定すると動かないのは私だけなのか?でもSwitch Botを動かすスクリプトを見た感じパスワードを送信するようなところはないのでMacアドレスさえわかれば近くのSwitch Botを動かせることになる。多分公開してないパスワード関連のAPIがあるのだろう。早く公開してほしいものである。もしもパスワード設定してもpythonから動かせたよという人がいたらぜひ教えて頂きたい。