#今回作るもの
こんな感じで鍵が開きます。
こんな感じ pic.twitter.com/gBETpm7GiU
— dai💸 (@dainbe1231) 2018年10月26日
#はじめに
######大まかな仕組み
既存のサービスをいろいろつないで形にしています。
######なぜスマートロックを作ろうかと思ったか?
- 市販のものは値段が高い
- レスポンスが悪い
- 自由度が低い
- 調べてみたら簡単にできそう
- せっかくAlexa買ったのに使ってない気がする
説明とかどうでもいい人はここに鍵本体のソースが乗ってます。
#使用したもの
#####ハードウェア
- windows10 PC
- raspberry pi zero WH (長いので以下raspi)
- サーボモーター(SG92R)
- タミヤ 楽しい工作シリーズ ユニバーサルアームセット
- OTGケーブル Micro-B
- 100均で買えるリードスイッチ付きのライト
- 基板、LED、抵抗、etc.
#####ソフトウェア
- TeraTerm
- Blynk
- node-red
#1.raspiの設定
今回使用するraspiはOTGケーブルでパソコンとつなぐだけでヘッドレス運用ができるのでとても便利です。
こちらのリンク を参考にしてセットアップしましょう。
セットアップ出来たらPythonの設定です。
なぜかPythonに標準搭載されているパッケージ管理ツールのpipがないので
~$ sudo apt install python3-dev
~$ sudo apt install python3-pip
と入力してpipを入れます。
~$ pip3 -V
pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.5)
と出てれば成功です。
もし、アップグレードしてください。と言われたら
~$ python -m pip3 install --upgrade pip3
でアップグレードすることができます。
次に今回使うモジュールをインストールしていきます。
インストールが必要なモジュールは
- slackbot
- slacker
- RPi.GPIO
- datetme
です。
順番にインストールしていきましょう。
~$ pip3 install slackbot
~$ pip3 install slacker
~$ pip3 install RPi.GPIO
~$ pip3 install datetime
#2.サーボを制御する
それではサーボを制御していきます。
主に使うのは、サーボモーターとRPi.GPIOです。
サーボモーターはPWMで制御するのでraspiのPWM出力ができるpinに信号線を接続しなければなりません。
また、今回使うサーボは4.8V以上で駆動するのでraspiの5Vのpinにつなぎましょう。
コードです。
import RPi.GPIO as GPIO
import time
# BOARDでpinで指定
GPIO.setmode(GPIO.BOARD)
#pin33を出力に設定
gp_out = 33
GPIO.setup(gp_out, GPIO.OUT)
#PMWを50Hzにセット
servo = GPIO.PWM(gp_out, 50)
servo.start(0)
GPIO.setup(gp_out, GPIO.OUT)
time.sleep(0.5)
#初期値
servo.ChangeDutyCycle(7.25)
time.sleep(0.5)
servo.ChangeDutyCycle(12)
time.sleep(0.5)
#位置の初期化
servo.ChangeDutyCycle(7.25)
time.sleep(0.5)
#サーボの出力ピンの設定をリセット
GPIO.cleanup(gp_out)
90度動いて元に戻るようにしてあります。動いたでしょうか?
GitHubのコードでは開けるための動きと閉めるときの動きを関数にしてlock.txtに状態を書き込んであります。
ついでにLEDも光らせてます。
#3.botをつくる。
今回はPythonで簡単にbotを実装できるslackbotを使っていきます。
slackbotに関してはこちらの方の記事がとても分かりやすく参考になります。
GitHubから一部ですがコードを載せておきます。
@listen_to(u'(鍵|カギ|かぎ)+.*(開け|あけ|空け)+')
@respond_to(u'(鍵|カギ|かぎ)+.*(開け|あけ|空け)+')
@respond_to(u'(解錠)+')
@respond_to('(open)+.*(door)+')
@respond_to(u'(扉|トビラ|とびら)+.*(開け|あけ|空け)+')
def openKeyOrder(message, *something):
userID = message.channel._client.users[message.body['user']][u'id']
userName = message.channel._client.users[message.body['user']][u'name']
# message.reply(userName)
with open('/home/pi/slackbot/lock.txt', mode='r') as f:
for row in f:
key = int(row.strip())
global lock
lock = key
if lock == 1:
message.reply(u'わかりました。解錠します。')
open_key()
print(userName + "さんの命令でカギを開けます。")
else:
message.reply(u'鍵が開いているようです。')
lock.txtを読み込むことで鍵が開いているか閉まっているかを判断して条件分岐してます。
userIDはコマンドラインからメンション、DMをするために必要になるものです。
また、userNameは登録した名前になります。
これらを組み合わせてuserの制限をしていきます。
def openKeyOrder(message, *something):
userID = message.channel._client.users[message.body['user']][u'id']
userName =message.channel._client.users[message.body['user']][u'name']
#message.reply(userName)
my_attachments = {"fallback": "test", \
"actions": [{\
"type": "button", \
"text": "はい", \
"url": "https://slack.com/api/chat.postMessage?token="+commander_token+"&channel="+smart_lock_ID+"&text=add%20%3C%40"+userID+"%3E%20instant&as_user=Ture&pretty=1"\
},\
{\
"type": "button", \
"text": "いいえ", \
"url": "https://slack.com/api/chat.postMessage?token="+commander_token+"&channel="+smart_lock_ID+"&text=rm%20%3C%40"+userID+"%3E%20instant&as_user=Ture&pretty=1"}]}
attachment = [my_attachments]
if userID in root_user or userID in instant_user:
message.reply("権限があります。")
else:
message.reply("権限がありません。")
slacker.chat.post_message(master_ID,'<@'+userID+'>さんが鍵を開けようとしました。\n許可しますか?', as_user=True, attachments=attachment)
またまたGitHubから抜粋ですが、root_user,instant_userのリストにuserIDがないと鍵が開けられないようにしています。
また、権限がないuserが鍵を開けようとすると自分宛に下のようなメッセージが送られてきます。
再起動するとinstant_userのリストは初期化されるので定期的に再起動させるようにすると勝手に利用制限がかかって楽です。
#4.ボタンで鍵を開ける。
さすがに室内にいるときにslackで「鍵開けて」というのは不便なので本体にボタンをつけて開け閉めできるようにしましょう。
ということで、pinを入力に設定して信号を受け取りましょう。
このように接続するとボタンを押すと8pinに入力信号が入ります。
入力信号を受け取ったときにサーボを動かす関数を発火させられれば鍵が開きます。
slackbotのbot.pyに細工をして同時に起動させましょう。
GitHubからですが載せておきます。
また、今回は入力を11pinにしています。
def check_button():
while True:
with open('/home/pi/slackbot/lock.txt', mode='r') as f:
for row in f:
key = int(row.strip())
lock = key
if GPIO.input(sw1_in) == 1 and lock == 1:
open_key()
elif GPIO.input(sw1_in) == 1 and lock == 0:
close_key()
servo.stop()
GPIO.cleanup()
def main():
bot = Bot()
# ボタン監視用のスレッドを起動する
th_me = threading.Thread(target=check_button, name="th_check_button")
th_me.setDaemon(True)
th_me.start()
try:
slacker.chat.post_message(c_name, '起動しました。', as_user=True)
# botを起動する
bot.run()
except Exception as e:
print(e)
if __name__ == "__main__":
print('start slackbot')
main()
これでslackbotとボタン監視用のスレッドが同時に立ち上がってボタンでもslackからでも開けられるようになりました。
#5.Alexaに鍵を開けてもらう。
仕組みは単純でAlexaに「鍵開けて」と言うとSlack上に「鍵開けて」と送信することができればよいわけです。
そのためにNode-redとAlexa Home Skill Bridgeを使います。
Node-redの導入はこちらを参考にセットアップしていきます。
Alexa Home Skill Bridgeの導入はこちらの方のものがわかりやすく参考になりました。
今回追加で使うノードは3つです。
alexa用のノード
slack用のノード
タイムスタンプ用のノード(なくてもいい)
Alexa Home Skill Bridgeは次のように設定します。
これでAlexa上でON/OFFをいじれるのでそれに応じてslackに送るメッセージを分岐させます。
AlexaアプリからNode-redスキルを有効化するここを忘れずに!!
一応フローをここに置いておきます。
これをraspi上で起動させておけばいい感じになりますね。
また、Alexaアプリの定型アクションをこんな感じにしておくと自然に開けることができます。
#6.再起動時に自動起動する.
raspiのOSであるRaspbianはLinux系のOSなのでcrontabでいろいろいじれます。
ついでにみんなに再起動することを知らせるためにbotにしゃべらせましょう!
# coding: utf-8
import subprocess
from slacker import Slacker
from slackbot_settings import API_TOKEN
# API token
token = API_TOKEN
# 投稿するチャンネル名
c_name = '自分のチャンネル'
#投稿
slacker = Slacker(token)
slacker.chat.post_message(c_name, '1分後に再起動します。', as_user=True)
subprocess.run(('/sbin/shutdown','-r','1'))
そしてbye.pyをcrontabで定期実行しましょう!
crontab -e
と入力してから選択肢がでると思うので"nano"を選択して下記のように書いてみてください。
@reboot sudo python3 hoge/bot.py
59 3 * * * sudo python3 hoge/bye.py
終了するときは'Ctrl + x'→'y'です。
これで再起動時にbotが起動して3:59にメッセージが送信、1分後に再起動します。
再起動するとinstant_userが初期化されるのでinstantらしくてちょうどいいですね。
#7.最後に
一番最初の動画でお気づきかもしれませんが、うちの鍵が固くSG92Rではトルクがたりず、RaspberryPi Zero Wでは電流が足りないという事態となり泣く泣くいろいろ買い換えました...
それに伴いこんなこともありましたね…
やる気あんのかこいつ pic.twitter.com/cH4ySwGmYn
— dai💸 (@dainbe1231) 2018年10月12日
slackに特定のメッセージを送信すれば鍵を開けることができるので100均一で売ってるbluetoothボタンを使って
こんなものやこんなん pic.twitter.com/VFaecuQ0f5
— dai💸 (@dainbe1231) 2018年10月8日
こんなものを組み合わせると応用が利きますね。
またAPIを叩いてslackにメッセージを送信すれば鍵が開くのでこんな感じでスマホからも簡単にできますね。
ショートカット機能万歳!!
##追記(2020/01/23)
RaspberryPiやめてM5Stack(ESP32)で作り直しました。
M5Stackでスマートロックを作った
#####参考にした記事
Raspberry Piでスマートロックをつくった