Прошло несколько месяцев с момента начала эксплуатации решения Rasp + Gdrive. Появилась идея добавить небольшой функционал. В итоге я перенес скрипт на Python, полностью его переписал и собрал из него демон для системы.
Итак задача:
1. Как и первой версии скрипта, пишем на Google Disk склеенные с 2-х камер снимки с заданным интервалом(раз в 5 минут).
2. Если в нерабочее время на снимках замечено движение- отправлять оповещение через telegram.
Посколько нет смысла сравнивать снимки сделанные с интервалом в 5 или 10 минут. За это время вор может остаться незамеченным. Поэтому я полностью переписал логику работы скрипта.
Скрипт запускается как сервис. В рабочее время(то есть когда нет необходимости в оповещении о проникновении) снимки создаются раз в 5 минут.
В нерабочее интервал создания снимков- 15 секунд. Сравнение 2-х последних снимков, на предмет наличия изменений и оповещение через telegram, если изменения будут обнаружены(с отправкой снимка).
Итак:
1. Оповещения отправляются через бота телеграм. Что это и как создать хорошо описано на просторах сети. Создать можно на сайте "папаши"
2. Скрипт запускается как демон с помощью supervisor
3. Чтобы не насиловать SD карту малины, все файлы я пишу на подключенную USB флешку.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from PIL import Image, ImageChops
import numpy as np
import datetime, time, os, shutil, telepot
#-----------------------------------------------------------
INTPHOTO = 5 # Интервал сохранения снимков на гуглодиск
now = datetime.datetime.now()
ROOTDIRECTORY = "/mnt/USB/PragaVoices/"
TMPDIRECTORY = "/mnt/USB/tmp"
FAILSCOUNT = 0
ALERTSTATUS = 0
CONTROLFILE = TMPDIRECTORY + '/control.jpeg'
WORKTIMEST = datetime.time(10,00)
WORKTIMEEN = datetime.time(20,00)
ALERTTIMEST = datetime.time(21,30)
ALERTTIMEEN = datetime.time(8,00)
#-----------------------------------------------------------
def motion_detect(image1, image2):
im1 = Image.open(image1)
im2 = Image.open(image2)
img = ImageChops.difference(im2, im1)
w,h = img.size
a = np.array(img.convert('RGB')).reshape((w*h,3))
h,e = np.histogramdd(a, bins=(16,)*3, range=((0,256),)*3)
prob = h/np.sum(h) # normalize
prob = prob[prob>0] # remove zeros
image_ent = -np.sum(prob*np.log2(prob))
im1.close()
im2.close()
if image_ent >= 1:
return True
else:
return False
#-----------------------------------------------------------
def newest_file_in_tree(rootfolder, extension=".jpeg"):
return max(
(os.path.join(dirname, filename)
for dirname, dirnames, filenames in os.walk(rootfolder)
for filename in filenames
if filename.endswith(extension)),
key=lambda fn: os.stat(fn).st_mtime)
#-----------------------------------------------------------
def get_photo_from_cam(DATE, TIME):
for i in range(1, 3):
response = os.system("ping -c 2 192.168.1.25" + str(i))
if response == 0:
cmd = 'avconv -rtsp_transport tcp -i "rtsp://192.168.1.25' + str(i) + '/user=user&password=password&channel=1&stream=0.sdp" -f image2 -vframes 1 -pix_fmt yuvj420p ' + TMPDIRECTORY + '/' + TIME + '-CAM' + str(i) + '.jpg'
os.system(cmd)
if os.path.isfile(FILE1) and os.path.isfile(FILE2):
cmd = 'convert +append -strip -interlace Plane -quality 60 ' + FILE1 + ' ' + FILE2 + ' ' + TMPDIRECTORY + '/' + TIME + '.jpeg'
os.system(cmd)
os.remove(FILE1)
os.remove(FILE2)
return True
else:
return False
#-----------------------------------------------------------
newest = newest_file_in_tree(ROOTDIRECTORY)
if not os.path.isfile(CONTROLFILE):
shutil.copy(newest, CONTROLFILE)
while True:
now = datetime.datetime.now()
now_time = datetime.datetime.now().time()
if now_time >= ALERTTIMEEN and now_time <= ALERTTIMEST:
SLEEPINTERVAL = INTPHOTO * 60
else:
SLEEPINTERVAL = 15
DATE = now.strftime("%d-%m")
TIME = now.strftime("%H-%M")
DIRECTORY = ROOTDIRECTORY + DATE
if not os.path.exists(DIRECTORY):
os.makedirs(DIRECTORY)
if not os.path.exists(TMPDIRECTORY):
os.makedirs(TMPDIRECTORY)
FILE1 = TMPDIRECTORY + '/' + TIME + '-CAM1.jpg'
FILE2 = TMPDIRECTORY + '/' + TIME + '-CAM2.jpg'
#-----------------------------------------------------------
newest = newest_file_in_tree(ROOTDIRECTORY)
PHOTOPREVTIME = os.stat(newest).st_mtime
PHOTOPREVTIMECONTROL = os.stat(CONTROLFILE).st_mtime
if get_photo_from_cam(DATE, TIME):
PHOTOLASTTIME = os.stat(TMPDIRECTORY + '/' + TIME + '.jpeg').st_mtime
INTERV = (PHOTOLASTTIME - PHOTOPREVTIME) / 60
INTERVCONTROL = (PHOTOLASTTIME - PHOTOPREVTIMECONTROL) / 60
#-----------Если кто-то пришел- ТРЕВОГА------------
if now_time >= ALERTTIMEST or now_time <= ALERTTIMEEN:
if motion_detect(TMPDIRECTORY + '/' + TIME + '.jpeg', CONTROLFILE):
# shutil.copy(TMPDIRECTORY + '/' + TIME + '.jpeg', DIRECTORY)
TelegramBot.sendMessage(GROUPID, 'Замечено движение в салоне')
photo = open(TMPDIRECTORY + '/' + TIME + '.jpeg', 'rb')
TelegramBot.sendPhoto(GROUPID, photo)
photo.close()
#-----------------------------------------------------------
if INTERVCONTROL >= INTPHOTO:
if os.path.isfile(CONTROLFILE):
os.remove(CONTROLFILE)
shutil.copy(TMPDIRECTORY + '/' + TIME + '.jpeg', CONTROLFILE)
if INTERV >= INTPHOTO:
if now_time >= WORKTIMEST and now_time <= WORKTIMEEN:
shutil.copy(TMPDIRECTORY + '/' + TIME + '.jpeg', DIRECTORY)
#-----------Если кто-то пришел положить на диск-----------
if (now_time >= ALERTTIMEEN and now_time <= WORKTIMEST) or (now_time >= WORKTIMEEN and now_time <= ALERTTIMEST):
if motion_detect(TMPDIRECTORY + '/' + TIME + '.jpeg', CONTROLFILE):
shutil.copy(TMPDIRECTORY + '/' + TIME + '.jpeg', DIRECTORY)
os.remove(TMPDIRECTORY + '/' + TIME + '.jpeg')
else:
for i in range(1, 3):
if os.path.isfile("FILE" + str(i)):
PHOTOLASTTIME = os.stat("FILE" + str(i)).st_mtime
INTERV = (PHOTOLASTTIME - PHOTOPREVTIME) / 60
if INTERV >= INTPHOTO and now >= WORKTIMEST and now <= WORKTIMEEN:
shutil.move("FILE" + str(i), DIRECTORY)
else:
os.remove("FILE" + str(i))
FAILSCOUNT += 1
if FAILSCOUNT >= 5 and ALERTSTATUS == 0:
TelegramBot.sendMessage(GROUPID, 'Нет изображения с одной из камер. Детектор движения отключен')
FAILSCOUNT = 0
ALERTSTATUS = 1
time.sleep(SLEEPINTERVAL)
Комментариев нет:
Отправить комментарий