ラズパイで冷蔵庫のプリンを監視する

皆さんは後で食べようと冷蔵庫に取っておいたプリンが食べられていたことはありますか？
私はあります。
自分へのご褒美にと楽しみにしていたところへその仕打ち、
ショックは計り知れないですよね。

プリンに名前を書いておくような生半可な対策ではなく、
また同じ悲劇が起こることを防ぐシステムを考案しましたので、
その実現までの記録を残したいと思います。

前回のラズパイ記事ではカメラを使ってタイムラプスを作る流れを紹介しましたが、
今度はそれに加えてセンサーを使ってみることにしました。

https://qiita.com/horoyoi3/items/86394408644f03bc252a

# システム構成イメージ
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1139641/6446582f-6426-1a3e-e333-770097f015d6.png)

ドアが開けられたことを検知して写真を撮影、冷蔵庫から何を取り出したかを記録。
その写真をLINEで自分に送ることでリアルタイムで事態を把握できるようにします。

「これではプリンが食べられること自体は防げないのでは？」と思われるかもしれませんが、
監視されているという事実を抑止力にプリンを守ろうと仕組みを描いています。

冷蔵庫の開閉検知には[ドアセンサー](https://akizukidenshi.com/catalog/g/gP-13371/)を使用します。
片方のパーツが磁石になっていて、センサーと近づけることで回路が繋がり、離すと回路が切れる仕組みです。

LINEへの画像送信にはLINE Notifyを利用します。
自分のLINEアカウントでログインするだけで簡単に使い始めることでき、
何か通知を受け取る仕組みを構築するのに便利です。

https://notify-bot.line.me/ja/

プログラミングはPython（今回は3.5.3）にて行います。
では順を追って、ひとつずつ検証していきたいと思います。

# 検証
## 1. ドアの開閉を検知する
ラズパイのGPIOにドアセンサーを接続します。
センサーはそのままだと接続できず、はんだ付けが必要ですが、
今回は検証であるため絶縁テープでジャンパ線と繋ぎました。

ピンは好きなGPIOピンとGNDに接続します。
（写真ではGPIO17とその隣のGNDを使っています）
![image2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1139641/8e40d05a-112a-70a7-2aa2-5f8de30bd6fe.jpeg)

センサーを検証するためのPythonソースコードは以下のようにしました。

```python:test_door_sensor.py
import RPi.GPIO as GPIO
from time import sleep

# GPIOピン番号の指定方法を設定
GPIO.setmode(GPIO.BCM)
# GPIO17を入力モード、プルアップ抵抗を有効化
# 入力がないときにONとなる
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)

status = 1
while True:
    try:
        status = GPIO.input(17)
        if status == 0:
            print("close")
        else:
            print("open")

        sleep(1)
    except:
        break

GPIO.cleanup()
```

コードを実行しセンサーを近づけたり遠ざけたりすると、
出力される判定結果が変わることが確認できました。
これでセンサー部の検証はOKです。
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1139641/7c51161f-cb06-427b-103a-9299f9761d18.png)

## 2. カメラで写真を撮影する
今回はPythonでカメラモジュールを操作し写真を撮影します。
カメラモジュールのPythonインターフェースであるPicameraを使います。

```python:test_camera.py
from picamera import PiCamera

camera = PiCamera()
camera.capture("photo.jpg")
```

ちょっと近いのでボケてますが、撮れていますね！
![image4.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1139641/f8499bcb-d47e-65cf-6b19-716ff6bced40.jpeg)

## 3. LINEに画像を送信しスマホで受け取る
[LINE Notify](https://notify-bot.line.me/ja/)にて、自分のLINEアカウントでログインをします。
初めてログインする場合は認証コードの入力が求められるので、スマホのLINEアプリで入力しましょう。
ログイン後のマイページで「トークンを発行する」からアクセストークンの発行ができます。
![image5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1139641/1f320ac6-b5b2-f58f-0e00-863396c4f2a2.png)
トークン名は通知メッセージに含まれて表示されるので、
それを踏まえて設定しましょう。

取得したアクセストークンを使って、
PythonソースコードからLINE NotifyのAPIをリクエストします。

```python:test_line_notify.py
import requests

# LINE Notifyアクセストークン
token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# LINE Notify通知API
url = "https://notify-api.line.me/api/notify"

headers = {"Authorization": "Bearer " + token}
payload = {"message": "Hello!"}
file_name = "photo.jpg"
files = {"imageFile": open(file_name, "rb")}

requests.post(url, headers=headers, data=payload, files=files)
```

実行すると画像付きでメッセージが送信されました。
![image6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1139641/e01fdba8-621a-4a26-5f92-ee7ceb944451.png)

# システムの動作確認
検証は完了したのでそれぞれの検証ソースコードをひとつにまとめ、動作確認します。
単純なマージ結果ですが以下のようになりました。

```python:monitoring_pudding.py
import RPi.GPIO as GPIO
import requests
from time import sleep
from picamera import PiCamera
from time import sleep

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)

camera = PiCamera()

token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
url = "https://notify-api.line.me/api/notify"
headers = {"Authorization": "Bearer " + token}
payload = {"message": "冷蔵庫が開けられました"}
file_name = "photo.jpg"

status = 1
while True:
    try:
        status = GPIO.input(17)
        if status == 0:
            print("close")
        else:
            print("open")
            camera.capture(file_name)
            files = {"imageFile": open(file_name, "rb")}
            requests.post(url, headers=headers, data=payload, files=files)
            print("sent message")

        sleep(3)
    except:
        break

GPIO.cleanup()
```

監視システムを設置した様子です。
不格好ですが最終的にはこのような形になりました。。
冷蔵庫を漁る手元を含んだ全身を写すにはある程度の高さが必要で、調整に苦労しました。
![image7.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1139641/0ba10a8f-d331-fe40-ec5e-592f8bca57dc.jpeg)

あとはPythonコードを実行、監視状態し準備完了です。
プリンを取り出す様子をシミュレーションしてみました。
![image8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1139641/7cc7f6b9-ab8e-802c-a7b4-e3bfc892210b.png)
バッチリ写ってますね！
これで安心してプリンを置いておけそうです。

#　課題

- 冷蔵庫が空いている間、複数のLINEメッセージが届いてしまうため煩わしい
- 部屋が暗いと真っ黒な画像になる
    - 赤外線LED付きカメラで暗視対応できそう
- カメラの設置場所と手元を撮りたい都合で顔までは入らなかった
    - 魚眼レンズ搭載のカメラを使用すればよさそう

# まとめ
今回は冷蔵庫のプリンを監視すると題しましたが、別に冷蔵庫やプリンのみにとどまらず、
出入り口の監視などの様々な用途に応用できると思います。
初めてラズパイとセンサーを組み合わせてシステムを構築してみたのですが、
触って動作を検証できただけで新しい世界が広がった感覚がありました。
また新しいアイデアが生まれたら、挑戦して記事にしてみたいと思います。