Sentinel Watch
目次
- 概要
- アイデアの詳細
- 特徴
- 使用部品
- ソースコード
- 現状・今後
- 参考文献
概要
ラズベリーパイ4と開閉スイッチを使用してドアの開閉の検知、ドアが開いた場合には録画の開始、一定期間ドアが開いていればブザーでの警告とスマホへの送信をすることによって注意を促すことができる。これにより遠隔監視、侵入検知が可能になります。
アイデアの詳細
・監視機能:開閉スイッチを使用してドアの開閉の検知
・アラート機能:45秒以上ドアが開いているのを検知するとブザーでの警告とLEDを点滅させる
・記録機能:監視機能が反応するとカメラを使って録画を開始、ドアが閉まるまで録画を続ける
・通知機能:ドアが開いた際にスマホに通知、一定以上開いていたら閉まっていないことの通知
・削除機能:録画した動画が多すぎると重くなるので一定期間経過した動画を削除する
ラズパイと接続した磁気センサーの入った開閉スイッチをドアと壁に設置します。ドアが開いた場合にスマホにLINE Notifyを使い開いたことの通知を行い、ラズパイで録画をはじめドアが閉まるまで撮影を続けます。
追記
LINE Notifyでは録画した動画の送信はできなかったため代案としてスマホアプリでVNCを入れWifi機能を利用することによって直接確認をするか、Google Driveに保存することによって確認をすることが可能
特徴
このシステムはドアが開いたとき限定で反応するシステムなので常に監視できるわけではありませんが、反応した際にはスマホに通知を行い動画の確認もすることが可能です。そのため、何かあった場合にはすぐに確認や対応することを可能となります。
使用部品
・ラズベリーパイ4
・磁気センサー(ドア開閉スイッチ)
・ラズパイカメラ
・ブザー
・LED
ソースコード
Sentinel Watchのソースコードになります。今回は、GPIO18ピンとグランドに接続してドア開閉スイッチを使用しました。削除機能の時間は今回は一時間に設定しています。
Sentinel
import threading
import RPi.GPIO as GPIO
import sys
import os
import cv2
from picamera2 import MappedArray, Picamera2
import datetime
import shutil
import time
from picamera2.encoders import H264Encoder
import subprocess
import requests # LINE Notify送信のために追加
from datetime import datetime, timedelta # ファイル削除用に追加
# GPIOの設定
GPIO.setmode(GPIO.BCM)
# ピン番号の設定
LED1 = 27 # GPIO 27
DOOR_PIN = 18 # ドア開閉スイッチ
BUZZER_PIN = 23 # ブザー
# GPIOピンの設定
GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(DOOR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(BUZZER_PIN, GPIO.OUT)
# 録画回数(リビジョン)を管理
revision_counter = 0
# Line Notify設定
LINE_NOTIFY_TOKEN = "YOUR_LINE_NOTIFY_TOKEN"
LINE_NOTIFY_API = 'https://notify-api.line.me/api/notify'
# Line Notify送信関数
def send_line_notify(message):
headers = {
'Authorization': f'Bearer {LINE_NOTIFY_TOKEN}'
}
payload = {'message': message}
response = requests.post(LINE_NOTIFY_API, headers=headers, params=payload)
print(f"LINE Notify Response: {response.status_code}, {response.text}")
# 録画ファイルの削除関数 (1時間経過した .mp4 ファイルを削除)
def delete_old_videos(directory, max_age_minutes=60):
now = time.time()
max_age_seconds = max_age_minutes * 60
for filename in os.listdir(directory):
file_path = os.path.join(directory, filename)
# 拡張子が .mp4 のファイルのみを対象とする
if os.path.isfile(file_path) and file_path.endswith('.mp4'):
file_age_seconds = now - os.path.getmtime(file_path)
if file_age_seconds > max_age_seconds:
print(f"削除対象: {file_path} (経過時間: {file_age_seconds}秒)")
os.remove(file_path)
# 録画ファイルの監視スレッド(1分おきに60分以上経過したファイルを削除)
def video_cleanup_watcher():
while True:
delete_old_videos("/home/pi/sentinel", max_age_minutes=15)
time.sleep(60)
# カメラ録画関数
def camera01():
global DOOR_PIN, revision_counter
print("CAMERA START")
try:
camera = Picamera2()
camera.configure(camera.create_video_configuration())
camera.configure(camera.create_preview_configuration(main={"format": 'XRGB8888', "size": (640, 480)}))
# タイムスタンプを追加
colour = (0, 255, 0)
origin = (0, 30)
font = cv2.FONT_HERSHEY_SIMPLEX
scale = 1
thickness = 2
def apply_timestamp(request):
timestamp = time.strftime("%Y-%m-%d %X")
with MappedArray(request, "main") as m:
cv2.putText(m.array, timestamp, origin, font, scale, colour, thickness)
camera.pre_callback = apply_timestamp
encoder = H264Encoder(10000000)
# 保存先ディレクトリを確認・作成
os.makedirs("/home/pi/sentinel", exist_ok=True)
# 録画ファイル名にタイムスタンプとリビジョンを追加
timestamp = time.strftime("%Y%m%d_%H%M%S")
revision_counter += 1 # リビジョンをインクリメント
h264_file_path = f"/home/pi/sentinel/DoorIsOpen_{timestamp}_rev{revision_counter}.h264"
mp4_file_path = f"/home/pi/sentinel/DoorIsOpen_{timestamp}_rev{revision_counter}.mp4"
camera.start_recording(encoder, h264_file_path)
# ドアが開いている間録画を続ける
while GPIO.input(DOOR_PIN) == 0:
GPIO.output(LED1, True) # LED点灯
camera.stop_recording()
camera.close()
print("録画を終了しました")
# H264をMP4に変換 (subprocess.runでエラーチェックを追加)
result = subprocess.run(['/usr/bin/MP4Box', '-add', h264_file_path, mp4_file_path], capture_output=True, text=True)
# MP4Boxのエラーを確認
if result.returncode != 0:
print(f"MP4Boxエラー: {result.stderr}")
raise RuntimeError(f"MP4Boxによる変換に失敗しました。")
# MP4ファイルが存在するか確認
if not os.path.exists(mp4_file_path):
raise FileNotFoundError(f"{mp4_file_path} が見つかりません。変換に失敗しました。")
# 元の.h264ファイルを削除
os.remove(h264_file_path)
GPIO.output(LED1, False) # LED消灯
print(f"録画ファイルが保存されました: {mp4_file_path}")
return mp4_file_path
except Exception as e:
print(f"Error in camera recording: {e}")
return None
# LED点灯スレッド 録画時に点灯する
def ledmain():
global stopstr1
stopstr1 = " "
last_buzzer_time = 0
door_open_start_time = None
door_was_open = False
notified_open = False
notified_open_long = False
while True:
if stopstr1 != " ":
GPIO.cleanup()
print("ドア監視終了")
sys.exit()
current_time = time.time()
# ドアが開いているかチェック
door_open = GPIO.input(DOOR_PIN) == 0
if door_open:
if door_open_start_time is None:
door_open_start_time = current_time
if not door_was_open:
print("ドアが開いています")
door_was_open = True
notified_open = False
notified_open_long = False
GPIO.output(LED1, True)
# ドアが開いたことを通知(まだ通知していない場合)
if not notified_open:
send_line_notify("ドアが開いています")
notified_open = True
# 45秒以上開いている場合に「ドアが開いたままです」を通知(まだ通知していない場合)
if current_time - door_open_start_time > 45 and not notified_open_long:
send_line_notify("ドアが開いたままです")
notified_open_long = True
if current_time - last_buzzer_time > 45 and current_time - door_open_start_time > 10:
GPIO.output(BUZZER_PIN, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(BUZZER_PIN, GPIO.LOW)
last_buzzer_time = current_time
# 録画処理
video_file = camera01()
if video_file:
print(f"録画ファイルが作成されました: {video_file}")
else:
if door_was_open:
print("ドアが閉まりました")
GPIO.output(LED1, False)
door_open_start_time = None
door_was_open = False
notified_open = False
notified_open_long = False
time.sleep(1)
# プログラム終了時の割り込み入力処理
def stopinput():
global stopstr1
stopstr1 = input()
# スレッドの開始
stop_thread = threading.Thread(target=stopinput)
stop_thread.start()
led_thread = threading.Thread(target=ledmain)
led_thread.start()
# 録画ファイルの監視スレッドの開始
cleanup_thread = threading.Thread(target=video_cleanup_watcher)
cleanup_thread.start()
# スレッドの終了を待つ
stop_thread.join()
led_thread.join()
cleanup_thread.join()
# GPIOのクリーンアップ
GPIO.cleanup()
プログラムの動きとしては、ドアを開閉した際に磁気センサーが反応して信号を送ることによって開閉の検知、その際にLINE Notifyに「ドアが開きました」と送信。もし、45秒以上ドアが開いているなら続いて「ドアが開いたままです」と送信するのに加えてLEDの点滅やブザーでの警告も行っています。
録画の部分は動画の順番がわかりやすいように番号を付けています。削除は一分ごとにファイルの監視を行い一時間以上経過した動画は削除するようにしています。
現状・今後
現状ドアの開閉の検知や監視機能・録画機能・削除機能ともに動作できていますが、LINE Notifyでの録画した動画の送信についてはできないため、Google Driveを使用した動画の保存を試そうと考えています。そのため現状は代案の一つ目のVNCアプリとWifi機能を使用しての動作の確認になります。
参考文献
https://monomonotech.jp/kurage/raspberrypi/daiso_sensorlight.html
-
3mannennhosii2
さんが
2024/09/30
に
編集
をしました。
(メッセージ: 初版)
-
3mannennhosii2
さんが
2024/09/30
に
編集
をしました。
-
3mannennhosii2
さんが
2024/10/24
に
編集
をしました。
-
3mannennhosii2
さんが
2024/10/24
に
編集
をしました。
-
3mannennhosii2
さんが
2024/10/28
に
編集
をしました。
-
3mannennhosii2
さんが
2024/10/28
に
編集
をしました。
-
3mannennhosii2
さんが
2024/10/28
に
編集
をしました。
-
3mannennhosii2
さんが
2024/10/28
に
編集
をしました。
-
3mannennhosii2
さんが
2024/10/28
に
編集
をしました。
-
3mannennhosii2
さんが
2024/10/29
に
編集
をしました。
-
3mannennhosii2
さんが
2024/10/29
に
編集
をしました。
-
3mannennhosii2
さんが
2024/10/30
に
編集
をしました。
ログインしてコメントを投稿する