blob: b8fa47c6a412b2f487460214fb5ac4be23739a79 [file] [log] [blame]
import paho.mqtt.client as mqtt
import time
import os
import sys
import threading
import logging as log
from multiprocessing import Process, Queue, Value, Array, Lock
import roc
import config
class BaseCamera(object):
process = {} # background process that reads frames from camera
frame = {} # frame queue
activity_counter = Value('i', 0)
cameras = Array('i', [0]*len(config.cameras))
lock = Lock()
def __init__(self, device, key, mbrlow, mbrhigh, devicegroup, noroc):
self.mqttBroker = "localhost"
self.device = device
self.key = key
self.mbrlow = mbrlow
self.mbrhigh = mbrhigh
self.devicegroup = devicegroup
self.noroc = noroc
"""Start the background camera process if it isn't running yet."""
if BaseCamera.cameras[int(self.device)] == 0:
BaseCamera.cameras[int(self.device)] = 1
self.last_detected = None
self.timer = None
self.detected = False
BaseCamera.frame[self.device] = Queue(100)
self.set_resolution(self.device, "low")
# start background frame process
BaseCamera.process[self.device] = Process(target=self._process, args=(self.device))
BaseCamera.process[self.device].start()
# wait until frames are available
_ = self.get_frame()
log.info("Start camera {} feed to {}".format(self.device, self.client))
def get_frame(self):
"""Return the current camera frame."""
# blocks
return BaseCamera.frame[self.device].get(block=True)
def frames(self):
""""Generator that returns frames from the camera."""
raise NotImplementedError('Must be implemented by subclasses.')
def _process(self, device):
"""Camera background process."""
frames_iterator = self.frames()
for frame in frames_iterator:
BaseCamera.frame[device].put(frame, block=True)
BaseCamera.process[device] = None
def person_detected(self, num):
self.last_detected = time.time()
if not self.detected:
BaseCamera.lock.acquire()
BaseCamera.activity_counter.value += 1
BaseCamera.lock.release()
self.set_resolution_high()
if not self.noroc:
roc.set_mbr(self.key, self.devicegroup, self.mbrhigh)
self.detected = True
self.start_timer()
def no_person_detected(self):
self.detected = False
self.timer = None
BaseCamera.lock.acquire()
BaseCamera.activity_counter.value -=1
if BaseCamera.activity_counter.value <= 0:
BaseCamera.activity_counter.value = 0
self.set_resolution_low()
if not self.noroc:
roc.set_mbr(self.key, self.devicegroup, self.mbrlow)
BaseCamera.lock.release()
def start_timer(self):
# log.info("Start timer for device {}".format(device))
self.timer = threading.Timer(10.0, self.timer_expiry)
self.timer.start()
def set_resolution_high(self):
for device in range(0, len(config.cameras)):
self.set_resolution(str(device), "high")
def set_resolution_low(self):
for device in range(0, len(config.cameras)):
self.set_resolution(str(device), "low")
def set_resolution(self, device, level):
log.info("Setting camera {} resolution to {}".format(device, level))
client = mqtt.Client()
client.connect(self.mqttBroker)
client.publish("camera/" + str(5000 + int(device)), level)
def timer_expiry(self):
now = time.time()
diff = now - self.last_detected
log.info("timer_expiry() - now:{}, last_detected:{}".format(now, self.last_detected))
if diff > 5.0:
self.no_person_detected()
else:
# Restart timer since person detected not too long back
self.start_timer()