前回、前々回に続き、3回目の電子工作です。玄関の鍵が面倒だと感じたことは誰しも一度はありますよね。鍵をかばんやポケットから取り出すのが地味にめんどくさかったり、鍵をなくしてしまって困ってしまったというような経験をしたことがある人も多いでしょう。ということで今回は、鍵を持ち歩かなくてもスマホで(もしくは手ぶらで)簡単に鍵の開閉をできるように玄関の鍵をスマートロック化していきたいと思います。
目次
搭載した機能
- スイッチで鍵の開閉
- 外部サービス(Google Assistant, Alexa)と連携して外部から鍵の開閉
- 開閉記録をgoogleスプレッドシートに記述
- AmazonDushボタンで鍵の開閉
- ICカードで開閉
- スプレッドシートをICカードのデータベースとして使用する
- LINEから操作する
概要
今回搭載したメインの機能はスマホで鍵を開閉できるようにすることです。この機能はスマートリモコンを作成したときと同様にbeebotteとIFTTTというサービスを利用して実現します。鍵はモーターで開閉するため手動では開けにくくなってしまうため、家の中からはスイッチを押すことで鍵を開閉できるようにします。
また、まだ実装はしていませんが、圧力センサーや磁力センサーを利用してドアの開閉を感知し、ドアが閉まったらオートロックしたり、振動センサーを利用してあらかじめ設定したリズムでドアを叩くと鍵を開ける(ただしセキュリティ面を考えて自分のスマホが近くにある場合のみにする)という機能も今後搭載していきます。
実行環境
- RasberryPi3 Model B+ (Raspberrypi zero wh などでも動作します)
- Python3
購入したもの
- RasberryPi3 Model B+
- サーボモーター(SG92)
- ジャンパーワイヤー
- ボタンスイッチ

Raspberry Pi4 ModelB 4GB ラズベリーパイ4 技適対応品
スマートロック本体の作成
サーボモーターの玄関への取り付けは、石膏粘土を使用して作成しました!
石膏粘土は乾燥するとプラスチックのようにカッチカチに固まります。
値段もお手頃価格なので、3Dプリンターなどを持っていない方におすすめです!
ガムボトルを型にし、サーボモーターが入るように調整し成型しました。

ドライヤーで乾燥させたためひび割れができてしまいましたが、2~3日ほどでしっかりと固まりました。
サーボモーターに取り付ける、鍵を開ける部分は家にあったスプーンを変形させて即席で作成しましたw
スプーンを二つに折り、そのうちの持つ部分の方を使用して鍵にフィットするように調整して折り曲げたものをサーボモーターに取り付けました。
そして、100均で購入したカモフラージュ用のテープを乾燥した粘土に貼り付けて完成です。

セットアップ
・ラズベリーパイの基本設定
ラズベリーパイへのOSのインストールや初期設定がまだの方はこちらの記事をご覧ください。
・インストール、ダウンロードするもの
- paho-mqtt(pythonパッケージ)
- mqtt.beebotte.com.pem( beebotteの証明書)
- sudo pip3 install paho-mqtt
- curl -O https://beebotte.com/certs/mqtt.beebotte.com.pem
・外部サービスとの連携
ここでは、記事が長くなってしまうので一部省略して説明します。もし、うまく設定できない場合はこちらの記事(Alexa, Google HomeをRasberryPiと連携する)で詳しく解説しているので見てみてください。
・ beebotte の設定
beebotteにアカウントを作成し、ログインしたら、”create new” をクリックします。

すると以下のような画面が表示されるので、Channel名とResource名、それからそれらの説明の合計4つを入力したら、”create channel” をクリックします。
(Channel名、Resource名は何でも構いません。例えばChannel名をRaspberryPi、Resource名をSmartLockなどに設定してください。 )

以上でChannelの作成は完了です。作成したChannelにアクセスするためにはChannel Tokenが必要なので、以下のように作成したChannel名をクリックして、Channel Tokenをメモしておいてください。

・IFTTTの設定
アカウントを作成しログインしたら、右上の自分のアカウント名をクリックし、”New Applet”をクリックします。

次の画面で ”+This” というところをクリックし 、画面が切り替わったら“search service” のところに “Google” と入力してGoogle Assistant を探し、Google Assistantのアイコンをクリックします。
(Alexaの設定を行う場合はAlexaを選択します。)
choose trigerと表示されるので “Say a simple phrase” をクリックします。
次の画面で以下のように、Google Assistant に話しかける(または入力する)フレーズとそのレスポンスを入力し、言語をJapaneseに設定したら “create trigger” をクリックします。 (下の画像ではスマートリモコンの設定をしているので適宜変更してください。例えば ”エアコンつけて” と書いてあるところを ”鍵を開けて” などに変更してください。

次に、Google Assistant と beebotteを連携させるための仲介役となるwebhooksとの連携をしていきます。 ”+That” をクリックし 、画面が切り替わったら“search service” のところに “Webhooks” と入力してWebhooksを探し、Webhooksのアイコンをクリックします。
choose actionと表示されるので “ Make a web request ” をクリックします。
次の画面で以下のように入力してください。
・URL
” https://api.beebotte.com/v1/data/publish/チャンネル名/トピック名?token=[先ほどメモしたBeebotteのトークン] “と入力
・Method
” POST “を選択
・Content Type
” application/json “を選択
・Body
” {“data”:[{“device”:”デバイス名”,”action”:”アクション名”}]} “と入力

URL中のチャンネル名/トピック名にはbeebotteで設定したチャンネル名とトピック名を入力してください。
Bodyのデバイス名とアクション名は、デバイス名をlock、アクション名を鍵を開ける場合はopen、閉める場合はcloseと入力してください。
“Create action” をクリックし、次の画面で “Finish” をクリックすればIFTTTでの設定は完了です。
回路図

右側のスイッチが鍵を開ける用のスイッチで、左側が閉める用のスイッチです。
プログラム
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
-
- import paho.mqtt.client as mqtt
- import subprocess
- import json
- import sys
- import time
- import RPi.GPIO as GPIO
-
-
-
- ##### beebotteのセッティング #####
- HOST = 'mqtt.beebotte.com'
- PORT = 8883
- CA_CERTS = 'mqtt.beebotte.com.pem'
- TOKEN = 'token_xxxxxxxxxxxxxxxxxx' #Beebotteで作成したチャンネルのトークンを入力
- TOPIC = 'チャンネル名/トピック名' #Beebotteで作成したトピック名を入力
-
-
-
- ##### サーボモーターのセッティング #####
- # pinの指定方法をBCMに設定(GPIO.BOARDとすると基盤のピン番号となる)
- GPIO.setmode(GPIO.BCM)
- # pin番号の指定
- pin_servo = 4
- # 指定したpinを出力に設定
- GPIO.setup(pin_servo, GPIO.OUT)
- # PWMサイクルを50Hz(20ms)に設定 (都合により関数内で設定を行う)
- # servo = GPIO.PWM(pin_servo, 50)
- # 回転角を定義
- left = 2.5
- center = 7.25
- right = 12.0
-
-
- ##### プッシュボタンのセッティング #####
- pin_open = 10
- pin_close = 27
-
- GPIO.setup(pin_open,GPIO.IN,pull_up_down=GPIO.PUD_UP)
- GPIO.setup(pin_close,GPIO.IN,pull_up_down=GPIO.PUD_UP)
-
- def press_open_button(pin_number):
- counter = 0
- print("GPIO[%d]のコールバックが発生しました" % pin_number)
- while True:
- status = GPIO.input(pin_open)
- if status == 0:
- counter = counter + 1
- if counter >= 10:
- print("開錠します")
- open()
- break
- else:
- print("開錠を取り消します")
- break
- time.sleep(0.001)
- print(counter)
-
- def press_close_button(pin_number):
- counter = 0
- print("GPIO[%d]のコールバックが発生しました" % pin_number)
- while True:
- status = GPIO.input(pin_close)
- if status == 0:
- counter = counter + 1
- if counter >= 10:
- print("閉錠します")
- close()
- break
- else:
- print("閉錠を取り消します")
- break
- time.sleep(0.001)
- print(counter)
-
-
- def open():
- servo = GPIO.PWM(pin_servo, 50)
- servo.start(center)
- time.sleep(0.3)
- servo.ChangeDutyCycle(left)
- time.sleep(0.3)
- servo.ChangeDutyCycle(center)
- time.sleep(0.3)
- servo.stop()
-
- def close():
- servo = GPIO.PWM(pin_servo, 50)
- servo.start(center)
- time.sleep(0.3)
- servo.ChangeDutyCycle(right)
- time.sleep(0.3)
- servo.ChangeDutyCycle(center)
- time.sleep(0.3)
- servo.stop()
-
-
- def on_connect(client, userdata, flags, respons_code):
- print('status {0}'.format(respons_code))
-
- def on_disconnect(client, userdata, flags, respons_code):
- print('disconect')
- #client.loop_stop()
-
-
- def on_message(client, userdata, msg):
- print(msg.topic + ' ' + str(msg.payload))
- data = json.loads(msg.payload.decode("utf-8"))["data"][0]
- print(msg.payload.decode("utf-8"))
- print(data)
-
- if (data["device"] == 'lock'):
- if (data["action"] == 'open'):
- print('鍵を開けます')
- open()
- print('鍵を開けました')
- elif (data["action"] == 'close'):
- print('鍵を閉めます')
- close()
- print('鍵を閉めました')
- else:
- print('unknown message')
-
- else:
- print('unknown message')
-
- if __name__ == '__main__':
- try:
- client = mqtt.Client()
- client.on_connect = on_connect
- client.on_disconnect = on_disconnect
- client.on_message = on_message
- client.username_pw_set('token:%s' % TOKEN)
- client.tls_set(CA_CERTS)
- client.connect(HOST, PORT)
- client.subscribe(TOPIC)
-
- GPIO.add_event_detect(pin_open, GPIO.FALLING, callback = press_open_button, bouncetime = 1000)
- GPIO.add_event_detect(pin_close, GPIO.FALLING, callback = press_close_button, bouncetime = 1000)
-
-
- client.loop_forever()
- except KeyboardInterrupt:
- print('finished')
- GPIO.cleanup()
上のコードのbeebotteのセッティングのところに先ほどメモした自分のbeebotteのTokenとTopicを入力し、 先ほどダウンロードしたmqtt.beebotte.com.pemがあるディレクトリにこのプログラムを保存してください。
使い方
プログラムを実行して数秒待つと、mqttによる接続が開始され ” status 0 ” と表示されるので、お手持ちのスマホやGoogle HomeからGoogle Assistantを呼び出し、先ほどIFTTTで設定した言葉(エアコンつけてなど)を話してみてください(入力でも可)。先ほどIFTTTで設定した言葉(エアコンをつけますなど)が返ってきて、ターミナルにBeebotteに送られた(publishされた)データ等が表示されたら外部サービスとの連携は成功です。さらに数秒待つと鍵の開け閉めが実行されます。
Alexaから操作する場合は1つ注意する点があり、” アレクサ、エアコンつけて “と話しかけても動作しません。Alexaから IFTTTを使用するには” アレクサ、トリガー、エアコンつけて “といったり、” アレクサ、エアコンつけてをトリガー ” といったように話しかけなければいけません。成功すると ” IFTTTに送信します ” という言葉が返ってきます。