ラズパイでスマートロック作ってみた② - 扉の開閉状況をGoogleスプレッドシートに記録 |じょるブログ

じょるブログ

電子工作やプログラミング関連の情報を発信している技術系ブログ

電子工作 ラズベリーパイ

ラズパイでスマートロック作ってみた② - 扉の開閉状況をGoogleスプレッドシートに記録

投稿日:2019年3月23日 更新日:

以前作成したスマートロックに、扉の開閉状況をGoogleスプレッドシートに記録する、という機能をつけたので、そのやり方について紹介します。

 

搭載した機能

  

概要

外出するときによく鍵を閉めたかどうか忘れてしまうことはありませんか?僕は心配性なので、そのようなことがしょっちゅうあります。そんなとき、扉の開閉記録が記録されていて、それをスマホで手軽に見れるとしたら便利ですよね。(スマートロックがあれば開閉状況に関わらず、遠隔で閉めればいいだけですが…)

そこで、今回は扉を開閉する度に自動でGoogleスプレッドシートに以下の画像のように開閉日時、開閉方法(デバイス)、開閉状況を記録するプログラムを作成したのでそれについて紹介します。

ちなみにエクセルなどではなく、Googleスプレッドシートに記録する理由は、オンライン上に情報が記録され、どこからでも確認できるからです!

  

 

実行環境

  • RasberryPi3 Model B+ (Raspberrypi zero wh などでも動作します)
  • Python3

    

手順

  1. GoogleスプレッドシートのAPI設定
  2. Googleスプレッドシートに記録するプログラムを作成
  3. 作成したプログラムをスマートロックのプログラムに組み込む

     

① 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スプレッドシートのプログラムと同じフォルダーに保存すれば完了です。

    

続きはこちら↓

   

google ads




google ads




-電子工作, ラズベリーパイ

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


関連記事

ラズベリーパイをディスプレイに接続せずSSH設定する方法

    一般的にラズベリーパイをパソコンからSSHで操作しようとした場合は、ラズパイにマウス、キーボード、ディスプレイを接続して、一度ラズパイ上でwi-fiの設定を行う必要があります。 しかし、実家に …

Raspberry Pi のSDカードが壊れ、起動しなくなってしまった場合の修復方法

スマートリモコンとして使用していたラズベリーパイ(zero WH)の調子が最近悪く、ちょっと動作が遅くなってきたなと思っていたら突然反応しなくなってしまいました。半年以上問題なく稼働していましたが、起 …

物理ボタンをIoT化 – ESP32で Swich bot を自作し、スマホからスイッチをON,OFFできるようにしてみた

   この記事ではESP32をIoTデバイスとして使用し、家の電気のボタンや電子レンジのボタンなどの、あらゆる物理ボタンを押すことのできるスイッチボットを作成する方法について解説します。 市販されてい …

大学生の電子工作 ラズパイでスマートロックを自作してみた

前回、前々回に続き、3回目の電子工作です。玄関の鍵が面倒だと感じたことは誰しも一度はありますよね。鍵をかばんやポケットから取り出すのが地味にめんどくさかったり、鍵をなくしてしまって困ってしまったという …

電子工作 ラズパイで玄関モニター(兼防犯カメラ)作ってみた

今回は前回のスマートリモコンに続き、2回目のIoTデバイス制作です。玄関モニター兼防犯カメラを作ってみました。作成難易度はスマートリモコンよりも簡単ですので皆さんも是非作ってみてください! 玄関モニタ …




関連記事