以前作成したスマートロックに、扉の開閉状況をGoogleスプレッドシートに記録する、という機能をつけたので、そのやり方について紹介します。
目次
搭載した機能
- スイッチで鍵の開閉
- 外部サービス(Google Assistant, Alexa)と連携して外部から鍵の開閉
- 開閉記録をgoogleスプレッドシートに記述
- AmazonDushボタンで鍵の開閉
- ICカードで開閉
概要
外出するときによく鍵を閉めたかどうか忘れてしまうことはありませんか?僕は心配性なので、そのようなことがしょっちゅうあります。そんなとき、扉の開閉記録が記録されていて、それをスマホで手軽に見れるとしたら便利ですよね。(スマートロックがあれば開閉状況に関わらず、遠隔で閉めればいいだけですが…)
そこで、今回は扉を開閉する度に自動でGoogleスプレッドシートに以下の画像のように開閉日時、開閉方法(デバイス)、開閉状況を記録するプログラムを作成したのでそれについて紹介します。
ちなみにエクセルなどではなく、Googleスプレッドシートに記録する理由は、オンライン上に情報が記録され、どこからでも確認できるからです!
実行環境
- RasberryPi3 Model B+ (Raspberrypi zero wh などでも動作します)
- Python3
手順
- GoogleスプレッドシートのAPI設定
- Googleスプレッドシートに記録するプログラムを作成
- 作成したプログラムをスマートロックのプログラムに組み込む
① GoogleスプレッドシートのAPI設定
GoogleスプレッドシートのAPIの設定方法についてはこちらの記事(ラズパイで取得したIoTデータをグーグルスプレッドシートに自動記録)にまとめたので参照してください。
② Googleスプレッドシートに記録するプログラムを作成
次に、プログラムを作成します。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import datetime
import argparse
#変更してください
key_name = '**************.json'
sheet_key = 'xxxxxxxxxxxxxxxxxxxxx'
#引数の設定
parser = argparse.ArgumentParser()
parser.add_argument("sheet_number", help="input using spreadsheet number", type=int)
parser.add_argument("value1", help="input write value", type=str, nargs='?', default='')
parser.add_argument("value2", help="input write value", type=str, nargs='?', default='')
parser.add_argument("value3", help="input write value", type=str, nargs='?', default='')
parser.add_argument("value4", help="input write value", type=str, nargs='?', default='')
parser.add_argument("value5", help="input write value", type=str, nargs='?', default='')
parser.add_argument("value6", help="input write value", type=str, nargs='?', default='')
parser.add_argument("value7", help="input write value", type=str, nargs='?', default='')
parser.add_argument("value8", help="input write value", type=str, nargs='?', default='')
parser.add_argument("value9", help="input write value", type=str, nargs='?', default='')
parser.add_argument("value10", help="input write value", type=str, nargs='?', default='')
args = parser.parse_args()
sheet_num = args.sheet_number
#APIにログイン
scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']
credentials = ServiceAccountCredentials.from_json_keyfile_name(key_name, scope)
gc = gspread.authorize(credentials)
#bookを開く
workbook = gc.open_by_key(sheet_key)
#sheetを指定
worksheet = workbook.get_worksheet(sheet_num)
#セルに入力
cell_value = [args.value1, args.value2, args.value3, args.value4, args.value5, args.value6, args.value7, args.value8, args.value9, args.value10]
worksheet.append_row(cell_value)
print("written")
プログラム中のkey_nameはGoogleスプレッドシートのAPI設定時にダウンロードしたjsonファイル名に変更してください。
また、sheet_keyにはスプレッドシートのURLの
https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxx/edit?usp=drivesdk
のxxxxxxxxxxxxxxxxxxxxxの部分の英数字を入力してください。
このプログラムは、実行時に引数を入力(最大10個)することで、その引数がGoogleスプレッドシートに記載されます。ただし、一番目の引数にはスプレッドシートのシート番号(0から数える)を入力します。
例 : python gspred.py 0 2019/01/01 12:34:56 alexa 開
③ 作成したプログラムをスマートロックのプログラムに組み込む
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import paho.mqtt.client as mqtt
import subprocess
import datetime
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 #17error
pin_close = 27
pin_autolock = 9
GPIO.setup(pin_open,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.setup(pin_close,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.setup(pin_autolock,GPIO.IN,pull_up_down=GPIO.PUD_UP)
#### グローバル変数(スプレッドシート記入)
Terminal = 'button'
def press_open_button(pin_number):
global Terminal
counter = 0
print("GPIO[%d]のコールバックが発生しました" % pin_number)
while True:
status = GPIO.input(pin_open)
if status == 0:
counter = counter + 1
if counter >= 10:
Terminal = 'button'
print("開錠します")
open()
break
else:
print("開錠を取り消します")
break
time.sleep(0.001)
print(counter)
def press_close_button(pin_number):
global Terminal
counter = 0
print("GPIO[%d]のコールバックが発生しました" % pin_number)
while True:
status = GPIO.input(pin_close)
if status == 0:
counter = counter + 1
if counter >= 10:
Terminal = 'button'
print("閉錠します")
close()
break
else:
print("閉錠を取り消します")
break
time.sleep(0.001)
print(counter)
def press_autolock_button(pin_number):
global Terminal
counter = 0
print("GPIO[%d]のコールバックが発生しました" % pin_number)
while True:
status = GPIO.input(pin_autolock)
if status == 0:
counter = counter + 1
if counter >= 10:
Terminal = 'button'
print("オートロックします")
autolock()
break
else:
print("オートロックを取り消します")
break
time.sleep(0.001)
print(counter)
def open():
global Terminal
now = datetime.datetime.today()
now_date = '{0:%Y-%m-%d}'.format(now)
now_time = '{0:%H:%M:%S}'.format(now)
lock_status ='開'
cmd = ('python3 gsp-homeauto.py 0 {0} {1} {2} {3}'.format(now_date, now_time, Terminal, lock_status))
subprocess.Popen(cmd.split())
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():
global Terminal
now = datetime.datetime.today()
now_date = '{0:%Y-%m-%d}'.format(now)
now_time = '{0:%H:%M:%S}'.format(now)
lock_status ='閉'
cmd = ('python3 gsp-homeauto.py 0 {0} {1} {2} {3}'.format(now_date, now_time, Terminal, lock_status))
subprocess.Popen(cmd.split())
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 autolock():
global Terminal
now = datetime.datetime.today()
now_date = '{0:%Y-%m-%d}'.format(now)
now_time = '{0:%H:%M:%S}'.format(now)
lock_status ='オートロック'
cmd = ('python3 gsp-homeauto.py 0 {0} {1} {2} {3}'.format(now_date, now_time, Terminal, lock_status))
subprocess.Popen(cmd.split())
open()
time.sleep(7)
close()
def on_connect(client, userdata, flags, respons_code):
print('status {0}'.format(respons_code))
#subprocess.call({"python", "ltika1.py"})
def on_disconnect(client, userdata, flags, respons_code):
if respons_code != 0:
print("Unexpected disconnection.")
#subprocess.call(python homeauto.py)
#sys.exit()
#subprocess.call({"python", "ltika1.py"})
else:
print('disconect')
print(respons_code)
client.loop_stop()
print('11')
def on_message(client, userdata, msg):
print(msg.topic + ' ' + str(msg.payload))
data = json.loads(msg.payload.decode("utf-8"))["data"][0]
global Terminal
Terminal = data["terminal"]
# control
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)
GPIO.add_event_detect(pin_autolock, GPIO.FALLING, callback = press_autolock_button, bouncetime = 1000)
client.loop_forever()
except KeyboardInterrupt:
print('finished')
GPIO.cleanup()
上のコードのbeebotteのセッティングのTokenとTopicのところに自分の値を入力し、 先ほど作成したGoogleスプレッドシートのプログラムと同じフォルダーに保存すれば完了です。
続きはこちら↓