2
0

More than 3 years have passed since last update.

【ソース公開】コロナが怖いので冷蔵庫で生存報告するシステム作った

Posted at

備忘録がてら

目次

  1. きっかけ
  2. 構想
  3. 成果物
  4. 買ったもの
    1. そのほか使ったもの
  5. ラズパイのセットアップ
  6. 電子工作
  7. LINE Notifyの登録
  8. 開発
    1. システム構成
    2. プログラム
    3. システムの監視
    4. システムの自動起動
  9. さいごに
  10. 参考サイト様

きっかけ

一人暮らしなので

コロナ

人知れず死ぬ

が怖いので危篤状態の検知+生きていることを逐次報告できるシステムを作ろうと思った。

構想

やりたいことは

  • 自宅にセンサーを取り付けて、24時間検知
  • 日常生活の動作から検知できて、システムを意識したくない
  • 通信相手(両親)が使ってるアプリ→LINEに通知する

冷蔵庫であれば毎日開け閉めをするので、
冷蔵庫の扉に磁気センサーを取り付けたRaspberry Piを設置し、Python×LINE Notifyで実現する。

成果物

実物
IMG_20210815_193846_886.jpg

kansei_2.jpg

冷蔵庫を開けたときLINEの通知画面(頻繁に通知するのでLINEアプリ側で通知OFF)
line_notifity.png

しばらくの間冷蔵庫の開閉がなかった時の通知(別グループ)
line_alert.png

ラズパイの起動画面(システムと監視システム)
kansei_3.PNG

電子工作・Python共に初心者の割にはちゃんと動作するので目的は達成。
開発期間は1~2日程度

買ったもの

総額6000円ぐらい

アマゾンとヨドバシで買った。ジャンパーワイヤ等パーツ類は秋月電子通商で買ったほうがよさそう

・はんだごてセット(845円)
https://www.amazon.co.jp/gp/product/B00J7BNP5U

・microSD 32GB(780円)
https://www.amazon.co.jp/gp/product/B09379M37J

・磁気センサー(1000円)
https://www.amazon.co.jp/gp/product/B0833LJQDV

・ジャンパーワイヤ オス-メス(589円)
https://www.amazon.co.jp/gp/product/B07MR1SVVR

・Raspberry Pi Zero WH(2630円)
 GPIOを使いたかったので最初から取り付けられているZero WHを購入
https://www.yodobashi.com/product/100000001003904466/

・ヒートシンク(125円)
https://www.yodobashi.com/product/100000001003498338/
 

そのほか使ったもの

・MicroB ACアダプタ
 Zero WHの充電用

・HDMI-MiniHDMIケーブル
 Zero WHのモニター接続用。mini-HDMIをmicro-HDMIと間違えないように
 ※Zero WHはmini-HDMIで、4 Model Bはmicro-HDMI

・USB MicroB-A変換アダプタ
 Zero WHにはUSB-TypeAが無いのでキーボードやら接続するのに必要

・マウス/キーボード
 無線でマウス/キーボードセットのものが便利

・ビニールテープ
 はんだづけした箇所に巻いた(熱収縮テープのほうがいいかも)

ラズパイのセットアップ

microSDをクリーンアップし、Raspberry Pi OSを下記リンクからダウンロード→インストール後、取り付け。
https://www.raspberrypi.org/software/
pi_zero_WH_2.jpg

ヒートシンクの取り付け。
pi_zero_WH_3.jpg

モニターと接続、電源を供給しOSの初期セットアップ。※検索すればいっぱい出てくるので省略

電子工作

ぶきっちょにとって一番の鬼門。学生以来のはんだごてでおっかなびっくり。

磁気センサーとジャンパーワイヤ(オス-メス)2本のオス部分とはんだづけする。
1628493866544_1.jpg

はんだづけできたらRaspberry Pi Zero WHのGPIOボードにジャンパーワイヤのメス部分を接続する。
片方をGPIO4、もう片方はGND。
pi_zero_WH_5.jpg
gpio.PNG

LINE Notifyの登録

登録・トークンの取得方法は下記リンク参照。 
https://qiita.com/akeome/items/e1e0fecf2e754436afc8

通常通知用のグループと緊急用グループ2つを連携。
キャプチャ.PNG

開発

Raspberry Pi OSにデフォルトインストールされているThonnyで開発した。
Pythonは普段触っておらずコード量も多くないので、中身はご容赦いただきたい。

システム構成

/home/「User」/Desktop/Fridge_Open_Notification_System/
    ┣ log ━ 「ログファイル」
    ┣ Main.py                ・・・メインプログラム
    ┣ LINENotification.py    ・・・LINE Notify通知用
    ┗ PrintLog.py            ・・・ログファイル生成用

プログラム

プログラムを起動するとコンソールが起動し、while文で磁気センサーのinput情報を取得し続ける。
磁気センサーが開くのを検知したらLINEの通知を飛ばす。
直近の通知から12時間経過したら注意用の通知、24時間経過したら警告用の通知、その後1時間ごとに再通知する。

Main.py
import time
import RPi.GPIO as GPIO
import requests
import datetime

#自作関数------------------
import PrintLog 
import LINENotification

#冷蔵庫開閉通知システム Main関数
Magnet_PIN = 4 #磁気センサーの刺さったGPIOのPIN番号
SW_Status = 1 #磁気センサーON/OFFステータス
IsOpened = False #冷蔵庫開放時フラグ

LastNotified = datetime.datetime.now() #直近の通知時刻
LastNotified_Warning = datetime.datetime(1999,1,1,0,0,0) #直近の警告通知時刻 

AttentionHour = 12 #注意経過時間 ※直近の通知時刻から一定期間応答がなかった場合、注意する
WarningHour = 24 #警告経過時間 ※直近の通知時刻から一定期間応答がなかった場合、警告する
IsNotified_Attention = False #注意フラグ

StartHour = 6 #通知開始時間
EndHour = 22 #通知終了時間

#Magnet_PINを入力モード、pull_up設定にする
GPIO.setmode(GPIO.BCM)
GPIO.setup(Magnet_PIN,GPIO.IN,pull_up_down=GPIO.PUD_UP)

while True:
    try:
        SW_Status = GPIO.input(Magnet_PIN)
        if SW_Status == 0:
            #扉が閉まっていたら
            nowDate = datetime.datetime.now()
            print("Close")

            #直近の通知時刻から注意経過時刻・警告経過時刻の取得
            AttentionTime = LastNotified + datetime.timedelta(hours=AttentionHour)
            WarningTime = LastNotified + datetime.timedelta(hours=WarningHour)

            if nowDate >= WarningTime:
                #直近の通知時刻から警告経過時間応答がなかった場合

                LastNotified_Warning_add1hour = LastNotified_Warning + datetime.timedelta(hours=1)
                if  nowDate >= LastNotified_Warning_add1hour:
                    #最後に警告した時間から1時間以上経過している場合                    
                    LINENotification.Alert("【警告】最後の冷蔵庫開閉通知から"\
                                   + str(WarningHour) + "時間以上経過しました。\n"\
                                   + "本人に連絡をしてください。\n"\
                                   "直近の通知時刻:" + LastNotified.strftime('%Y年%m月%d日 %H:%M:%S'))
                    LastNotified_Warning = nowDate

            elif nowDate >= AttentionTime:
                #直近の通知時刻から注意経過時間応答がなかった場合
                if IsNotified_Attention == False:
                    LINENotification.Alert("【注意】最後の冷蔵庫開閉通知から"\
                                   + str(AttentionHour) + "時間経過しました。\n"\
                                   + "心配な場合、本人に連絡をしてみてください。\n"\
                                   "直近の通知時刻:" + LastNotified.strftime('%Y年%m月%d日 %H:%M:%S'))
                    IsNotified_Attention = True

            IsOpened = False            
        else:
            #扉が開いていたら
            nowDate = datetime.datetime.now()
            if IsOpened == True:
                continue

            print("Open!")            
            PrintLog.func("冷蔵庫Open")

            if StartHour <= nowDate.hour and nowDate.hour < EndHour:
                #LINEに通知する
                LINENotification.func("冷蔵庫パカッ")
            else:
                #通知時間外だった場合
                PrintLog.func("寝る時間なので通知しないよ")

            #直近の通知時刻にセット
            LastNotified = nowDate
            IsOpened = True
        time.sleep(1)
    except:
        break

GPIO.cleanup()
print("end")


LINENotification.py
import requests
import os
import datetime

#LINEに通知
def func(message='テストメッセージ'):

    #通知用メッセージ
    message_str = message + " "+ datetime.datetime.now().strftime('%Y年%m月%d日 %H:%M:%S')

    line_notify_token = '「グループのトークン」'
    line_notify_api = 'https://notify-api.line.me/api/notify'
    headers = {'Authorization': f'Bearer {line_notify_token}'}
    data = {'message': f' {message_str}'}
    requests.post(line_notify_api, headers = headers, data = data)

#警告用:LINEに通知
def Alert(message='テストメッセージ'):
    line_notify_token = '「グループのトークン」'
    line_notify_api = 'https://notify-api.line.me/api/notify'
    headers = {'Authorization': f'Bearer {line_notify_token}'}
    data = {'message': f' {message}'}
    requests.post(line_notify_api, headers = headers, data = data)


PrintLog.py
import os
import datetime

#ログ生成関数
def func(message='テストメッセージ'):
    print("LogWrite:" + message)

    LogDir = "/home/「User」/Desktop/Fridge_Open_Notification_System/log"
    LogFile = LogDir + "/" + datetime.datetime.now().strftime('%Y%m%d.txt')

    #ディレクトリが存在しない場合、新規作成
    if not os.path.exists(LogDir):        
        os.makedirs(LogDir)

    #ログファイル書き込み    
    f = open(LogFile, 'a', encoding='UTF-8')
    f.writelines(message + " " + datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S\n')) 


システムの監視

システムが停止した時に再起動するシェルスクリプトを作成。

start.sh
#!/bin/bash

#冷蔵庫開閉通知システムの監視
ProcessName=start.sh
echo "冷蔵庫開閉通知システムの監視"

while true
do
    count=`ps -ef | grep /home/「User」/Desktop/Fridge_Open_Notification_System/Main.py | grep -v grep | wc -l`
    if [ $count = 0 ]; then
        #システムが停止していたら起動
        echo "start:Fridge_Open_Notification_System"
        lxterminal -e "python3 /home/「User」/Desktop/Fridge_Open_Notification_System/Main.py"  
    fi
    sleep 1
done

システムの自動起動

ラズパイが停止した際、起動のためだけにいちいちモニターに接続するのも面倒なので、自動起動の設定をした。
「/home/「User」/.config/autostart」ディレクトリにデスクトップエントリを作成。

start.desktop
[Desktop Entry]
Exec=lxterminal -e "sh /home/「User」/Desktop/start.sh"
Type=Application

さいごに

想定していたものが思いのほか簡単にできたので良かった。

現代の素晴らしい物流システムのおかげで着想から1週間程度で実現できたので、今後も何か思いついたら作っていきたい。

参考サイト様

LINE Notify公式

ラズパイで100均ドア開閉センサー検知

ラズパイで冷蔵庫の閉め忘れをLINE通知する

PythonでLINE Notifyへ通知を送る

デスクトップ起動後に、自動的に指定したプログラムを起動させる方法について

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0