タグ:Beebotte | IFTTT | Raspberry Pi
前々から興味のあったラズパイを使ってIoTしてみたい!
それと自宅にスマートロックを導入したもののマンション自体のオートロックを解錠させるのに結局カギは持ち歩かなきゃならないので
何とか鍵を持たずスマホだけでエントランスから自室までの解錠したい!!という個人的欲求を年末年始で解決してみた。
自宅マンションのオートロックは通常通りにエントランスから鍵を使うか、インターホンで部屋番号を呼び出し、自室から「解錠」ボタンを押さないと開かない。
これをSwitcBotというスイッチガジェットをベースに考案。
別途4000円ほどで専用ハブを購入すればwifi接続して外部からでも操作できるみたいですが、ここをできるだけ自力IoTしてみます。
今回は以前から持っていたもののなかなか触る機会がなかったので改めてセットアップ。
初期セットアップなどはいろんな所で紹介されているのでそちらを参考に。
とりあえず最低限としてOSにはRaspbianを入れてメインPCからSSH接続できるように設定。
今回は安定して外部からの接続ができるようにwifiではなくLANケーブルを直接繋げてます。
今回初めて利用しましたがMQTTってなんぞや?
Message Queue Telemetry Transportの略で、publish/subscribeモデルという仕組みに基づいてつくられた軽量なメッセージプロトコルです。
ネットワークが不安定な場所や、性能が低いデバイスでも動くように軽量化されているのが特徴で、TCP/IP ネットワークをベースに作られています。
今回はこのMQTTを利用できるサービスを利用します。
beebotte
アカウントを作成したら右上メニューから「Channels」を選択して
「Create New」ボタンをクリック。
上記のようなチャンネル名とリソース名を設定して、「Create Channel」ボタンで新規作成します。
リソース項目数などは後から編集はできないのでオートロック解除の仕様上、まずインターホンの応答ボタンを押さないと解錠ボタンのプッシュが効かない様なパターンもあるので、
1アクション=1ボットとして、それぞれの動作に複数の操作(スイッチ)が必要な場合はそれぞれ用にリソース数も設定が必要です。
チャンネルを作成すると専用のチャンネルトークンが作成されます(token_○○○○)
作成したチャンネルは右メニューの「Console」からテスト送信ができます。
Secret Keyが必要ですが、これがどこにあるかわかりにくいんですがここにあります
ラズパイからメイン処理でBeebotteへリクエストをするためのBeebotteの証明書をダウンロードしておきます。
https://beebotte.com/certs/mqtt.beebotte.com.pem続いてスマートスピーカーへのトリガーの設定ですが、こちらは有名なIFTTTを利用します。IFTTT
わかりにくいですが、画像の「+」をクリックして新規アプレットを作成します。
まずは"コレ"から"ソレ"の部分の"コレ"を設定します。
「This」をクリックしたら対応サービス一覧画面に変わるので「google assistant」と入力し、
トリガー項目一覧が出るのでその中から「Say a simple phrase」をクリック。
初回はGoogleアカウントのログインが必要だったと思います
上記の様な発動条件を設定して「Create trigger」をクリック
次は"コレ"から"ソレ"の部分の"ソレ"を設定します。
「That」をクリックしたら対応サービス一覧画面に変わるので「web hooks」と入力し、「Make a web request」をクリック。
URLにはBeebotteで作成したリクエストURLを入力して各項目は上記の様に設定して「Create action」をクリック
Bodyの部分はGoogle Homeアプリで設定してあるデバイス情報がアプレット作成後に自動で入ると思います。
# GoogleHomeで設定済みのbody設定例 {"data":[{"room":"living","device":"release","action":"on"}]}
アプレット名をわかりやすい名前に変更してFinishをクリックするとアプレットが作成されます。
これでIFTTTを経由して"This"(GoogleHomeへの音声命令)から"That"(Beebotteへの外部リクエスト)が開通して、自宅のラズパイにリクエストを送る準備ができました。
いよいよラズパイで動作させるメイン処理です。ラズパイ本体をディスプレイに繋いでターミナルアプリを起動するか、メインPCからSSH接続してファイルを作成します。
※ラズパイ上のpythonはデフォで2系のため、pyenv経由で3系を入れてる前提です。
そしてpython3系でBluetoothを使うのに必要なパッケージを入れます。
# Pyenv関連パッケージのインストール $ sudo apt-get install -y git openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev # pyenv設定 $ git clone https://github.com/yyuu/pyenv.git ~/.pyenv $ vim .bash_profile $ export PYENV_ROOT="$HOME/.pyenv" $ export PATH="$PYENV_ROOT/bin:$PATH" $ eval "$(pyenv init -)" # Python3系のインストールとデフォ設定 $ pyenv install 3.6.6 $ pyenv global 3.6.6 $ python --version --> 3.6.6 # 必要なパッケージをインストール $ pip install pybluez $ apt-get install libboost-python-dev $ apt-get install libboost-thread-dev $ pip install gattlib
gattlibのインストールが色々と手間取ると思いますが、自分の環境は以下のコマンドで成功しました
pip download gattlib tar xvzf ./gattlib-0.20150805.tar.gz cd gattlib-0.20150805/ sed -ie 's/boost_python-py34/boost_python-py36/' setup.py pip install .
上記設定が完了したら実際にSwitchBotのボタンが押されるか確認してみます。
# 操作したいスイッチのMACアドレスで1回プッシュ sudo python switchbot_py3.py -d xx:xx:xx:xx:xx:xx Press
MACアドレスはSwitchBotアプリのスイッチ一覧から歯車マークで各デバイス情報の右上アイコンの情報ページに記されています。
主な変更点はトークン情報とSwitchBot本体のMACアドレス部分です。
各ファイルディレクトリは"/usr/local/lib/switchbot/"
をベースに置いていきます。
事前にダウンロードしたBeebotteの証明書も同ディレクトリ内に置いておきます。
import os import sys import time import json import logging import time import paho.mqtt.client as mqtt import binascii from bluepy.btle import Peripheral TOKEN = "トークン情報" HOSTNAME = "mqtt.beebotte.com" PORT = 8883 TOPIC = "Entrance/release" CACERT = "/usr/local/lib/switchbot/mqtt.beebotte.com.pem" SWITCH_MAC = "SwitchBotのMACアドレス" SWITCH_NAME = "release" if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG,format='%(asctime)s- %(name)s - %(levelname)s - %(message)s') _LOGGER = logging.getLogger(__name__) class SwitchBot: def __init__(self, name, mac): self._mac = mac self._name = name def action(self, act): for connection in range(1,6): try: p = Peripheral(self._mac, "random") except: _LOGGER.error('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] if act == "on": hand.write(binascii.a2b_hex("570101")) elif act == "off": hand.write(binascii.a2b_hex("570102")) elif act == "press": 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()} if "action" in data.keys(): switch_bot.action(data["action"]) def fork(): pid = os.fork() if pid > 0: f = open('/var/run/switchbotd.pid','w') f.write(str(pid)+"\n") f.close() sys.exit() if pid == 0: main() def main(): client = mqtt.Client() client.username_pw_set("token:%s"%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() if __name__=='__main__': fork()
このファイルを実際に動かしてswitchbotが動けば準備はほぼ完了です。
ほぼ完了ではありますが、現状ではファイルをいちいち実行しないと動かないので
一例の処理をサービスとして登録して、ラズパイを起動したらそのままサービスも起動する様に設定します。
# ディレクトリ構造をラズパイにデプロイ $ tree /usr/local/lib/switchbot/
[Unit] Description=SwitchBot [Service] ExecStart=/usr/bin/python /usr/local/lib/switchbot/switchbot.py Restart=always Type=forking PIDFile=/var/run/switchbot.pid [Install] WantedBy=multi-user.target
# サービス再読み込み $ sudo systemctl daemon-reload # switchbotデーモンスタート $ sudo systemctl start switchbot # OS起動時有効設定 $ sudo systemctl enable switchbot # 状態確認 $ systemctl status switchbot # 自動起動 $ systemctl is-enabled switchbot enabled
もしエラーが出る場合はラズパイを再起動したり、サービスファイルのPIDFileパスの権限を変更するなど試してみてください。
自分の場合は一度PIDFileの行をコメントアウトしたらエラーが出なくなったので、その後修正しました。
これでGoogle Homeから音声で操作できるようになりましたが、室内からの操作だったら最初からSwitchBotのアプリでできるよ、正直意味ないよって事でちゃんと外からでもオートロックを施錠できるように
後編では室外からでも操作できるようにします。