blob: d7a7d298fc80d8443c14ffea109260d6f956e50a [file] [log] [blame]
Shad Ansari5e8d0692021-12-08 19:09:34 +00001import paho.mqtt.client as mqtt
2import time
3import os
4import sys
5import threading
6import logging as log
7from multiprocessing import Process, Queue, Value, Array, Lock
8
9import roc
Shad Ansari30a23732021-09-29 23:07:21 -070010
11
12class BaseCamera(object):
Shad Ansari26682be2021-10-26 03:52:35 +000013 process = {} # background process that reads frames from camera
Shad Ansaric9f48d32021-10-25 19:03:34 +000014 frame = {} # frame queue
Shad Ansari5e8d0692021-12-08 19:09:34 +000015 activity_counter = Value('i', 0)
16 cameras = Array('i', [0, 0, 0, 0])
17 lock = Lock()
Shad Ansari30a23732021-09-29 23:07:21 -070018
Shad Ansari5e8d0692021-12-08 19:09:34 +000019 def __init__(self, device, key, mbrlow, mbrhigh, devicegroup):
20 self.mqttBroker = "localhost"
Shad Ansaric0726e62021-10-04 22:38:53 +000021 self.device = device
Shad Ansari5e8d0692021-12-08 19:09:34 +000022 self.key = key
23 self.mbrlow = mbrlow
24 self.mbrhigh = mbrhigh
25 self.devicegroup = devicegroup
Shad Ansaric9f48d32021-10-25 19:03:34 +000026
Shad Ansari5e8d0692021-12-08 19:09:34 +000027 """Start the background camera process if it isn't running yet."""
28 if BaseCamera.cameras[int(self.device)] == 0:
29 BaseCamera.cameras[int(self.device)] = 1
30 self.last_detected = None
31 self.timer = None
32 self.detected = False
33 BaseCamera.frame[self.device] = Queue(100)
Shad Ansari26682be2021-10-26 03:52:35 +000034 # start background frame process
35 BaseCamera.process[self.device] = Process(target=self._process, args=(self.device))
36 BaseCamera.process[self.device].start()
Shad Ansari30a23732021-09-29 23:07:21 -070037 # wait until frames are available
Shad Ansari60ca8cc2021-11-02 18:46:44 +000038 _ = self.get_frame()
Shad Ansari30a23732021-09-29 23:07:21 -070039
40 def get_frame(self):
41 """Return the current camera frame."""
Shad Ansari30a23732021-09-29 23:07:21 -070042
Shad Ansari60ca8cc2021-11-02 18:46:44 +000043 # blocks
44 return BaseCamera.frame[self.device].get(block=True)
Shad Ansari30a23732021-09-29 23:07:21 -070045
Shad Ansari341ca3a2021-09-30 12:10:00 -070046 def frames(self):
Shad Ansari30a23732021-09-29 23:07:21 -070047 """"Generator that returns frames from the camera."""
Shad Ansari341ca3a2021-09-30 12:10:00 -070048 raise NotImplementedError('Must be implemented by subclasses.')
Shad Ansari30a23732021-09-29 23:07:21 -070049
Shad Ansari26682be2021-10-26 03:52:35 +000050 def _process(self, device):
51 """Camera background process."""
Shad Ansari30a23732021-09-29 23:07:21 -070052 frames_iterator = self.frames()
53 for frame in frames_iterator:
Shad Ansaric9f48d32021-10-25 19:03:34 +000054 BaseCamera.frame[device].put(frame, block=True)
Shad Ansari4ae11682021-10-22 18:51:53 +000055
Shad Ansari26682be2021-10-26 03:52:35 +000056 BaseCamera.process[device] = None
Shad Ansari5e8d0692021-12-08 19:09:34 +000057
58 def person_detected(self, num):
59 self.last_detected = time.time()
60 if not self.detected:
61 BaseCamera.lock.acquire()
62 BaseCamera.activity_counter.value += 1
63 BaseCamera.lock.release()
64 self.set_resolution_high()
65 roc.set_mbr(self.key, self.devicegroup, self.mbrhigh)
66 self.detected = True
67 self.start_timer()
68
69 def no_person_detected(self):
70 self.detected = False
71 self.timer = None
72 BaseCamera.lock.acquire()
73 BaseCamera.activity_counter.value -=1
74 if BaseCamera.activity_counter.value <= 0:
75 BaseCamera.activity_counter.value = 0
76 self.set_resolution_low()
77 roc.set_mbr(self.key, self.devicegroup, self.mbrlow)
78 BaseCamera.lock.release()
79
80
81 def start_timer(self):
82 # log.info("Start timer for device {}".format(device))
83 self.timer = threading.Timer(10.0, self.timer_expiry)
84 self.timer.start()
85
86
87 def set_resolution_high(self):
88 for device in range(0, 4):
89 self.set_resolution(str(device), "high")
90
91
92 def set_resolution_low(self):
93 for device in range(0, 4):
94 self.set_resolution(str(device), "low")
95
96
97 def set_resolution(self, device, level):
98 log.info("Setting camera {} resolution to {}".format(device, level))
99 client = mqtt.Client()
100 client.connect(self.mqttBroker)
101 client.publish("camera/" + str(5000 + int(device)), level)
102
103
104 def timer_expiry(self):
105 now = time.time()
106 diff = now - self.last_detected
107 log.info("timer_expiry() - now:{}, last_detected:{}".format(now, self.last_detected))
108 if diff > 5.0:
109 self.no_person_detected()
110 else:
111 # Restart timer since person detected not too long back
112 self.start_timer()