ROC integration

Change-Id: Ica1d8b10e9c0318d89361ff85206aabfa5f58e7f
diff --git a/Makefile b/Makefile
index af0e2bf..08e84a3 100644
--- a/Makefile
+++ b/Makefile
@@ -78,7 +78,7 @@
 		--network host \
 		--name $(CONTAINER_NAME) \
 		--rm \
-		$(DOCKER_IMAGENAME)
+		$(DOCKER_IMAGENAME) --key "eyJhbGciOiJSUzI1NiIsImtpZCI6IjUwNDJmNjcxYTQ1YWMxNGM1MzA0ZTA3MWY3MWM2N2FkNGE4N2RhZDYifQ.eyJpc3MiOiJodHRwczovL2RleC5hZXRoZXJwcm9qZWN0Lm9yZy9kZXgiLCJzdWIiOiJDaXN4TmpNNE5ERTZPRGMxWlRNeU5qY3RZakkwT1MwME9XTXdMV0V5TW1ZdE1qUmlaalUyWXprNVpEazFFZ1ZqY205M1pBIiwiYXVkIjoiYWV0aGVyLXJvYy1ndWkiLCJleHAiOjE2Mzg5OTU0MTAsImlhdCI6MTYzODkwOTAxMCwibm9uY2UiOiJNSGRTV25CWFpGRkxRVmxNWlROWk9IbzViWE55ZDJOV2VFWnlTV2RuUlRSUE4xaDNTMnBSTVV4NGRUSmoiLCJhdF9oYXNoIjoiWGtGNW5WM3UwcUZxYml3RC03c2NNdyIsImNfaGFzaCI6ImUzdXdRVkZpOW5ieGJlbHNmNW9MS0EiLCJlbWFpbCI6InNoYWRAb3Blbm5ldHdvcmtpbmcub3JnIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImdyb3VwcyI6WyJBZXRoZXJST0NBZG1pbiIsIk9ORlN0YWZmIl0sIm5hbWUiOiJzaGFkIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2hhZCJ9.uIaSeuJGviVSiQeOT8EBPBoLBDy5G8lSwXz48XoAyNIyj3jontKNKfOf8pnQR7Cvrutqk56WOS78V8HPQgr01uTezaSHMZzPNnHtsyyCreMChAwKV-ZKS40b0q56yNihScHHVB0wlSO6Yr9K45M2tX1AActL10Ky3td9myvObPXEPgYsiG-KTWQVNAC_dnrmArKuUiqVlWAJhJckdRBOGHVhceenaDCrMPB8u-Z3_-S89gq4mper1fXNFmDCxXbRceJJPfWeWJNhJEQ0y1LC1c8JLxKFpynjfetXCA9qAaPJ0vzn-NYQnVpTqiDm7BsW4Ry1-62Nlgm3km2wT-Le_A"
 
 run-native-file: $(VENV)
 	. ./bin/person_detection.sh -i ./resources/run.mp4
diff --git a/person_detection/action.py b/person_detection/action.py
deleted file mode 100644
index 5cd241f..0000000
--- a/person_detection/action.py
+++ /dev/null
@@ -1,62 +0,0 @@
-import paho.mqtt.client as mqtt
-import time
-import os
-import sys
-import threading
-import logging as log
-
-import roc
-
-mqttBroker ="localhost"
-
-resolution = {}
-timer = {}
-timestamp = {}
-
-
-def person_detected(device, num):
-    timestamp[device] = time.time()
-    if device in resolution and resolution[device] == "high":
-        return
-    set_resolution_high(device)
-
-
-def start_timer(device):
-    # log.info("Start timer for device {}".format(device))
-    timer[device] = threading.Timer(10.0, timer_expiry, device)
-    timer[device].start()
-
-
-def remove_timer(device):
-    del timer[device]
-
-
-def set_resolution_high(device):
-    set_resolution(device, "high")
-    roc.set_uplink_mbr_high()
-
-
-def set_resolution_low(device):
-    set_resolution(device, "low")
-    roc.set_uplink_mbr_low()
-
-
-def set_resolution(device, level):
-    log.info("Setting camera {} resolution to {}".format(device, level))
-    resolution[device] = level
-    if level == "high" and device not in timer:
-        start_timer(device)
-    client = mqtt.Client()
-    client.connect(mqttBroker)
-    client.publish("camera/" + str(5000 + int(device)), level)
-
-
-def timer_expiry(device):
-    now = time.time()
-    diff = now - timestamp[device]
-    # log.info("timer_expiry() - now:{}, timestamp:{}".format(now, timestamp[device]))
-    if diff > 5.0:
-        set_resolution_low(device)
-        remove_timer(device)
-    else:
-        start_timer(device)
diff --git a/person_detection/app.py b/person_detection/app.py
index 87a2cd9..fc0b9c7 100644
--- a/person_detection/app.py
+++ b/person_detection/app.py
@@ -41,15 +41,41 @@
 def build_argparser():
     parser = ArgumentParser(add_help=False)
     args = parser.add_argument_group('Options')
-    args.add_argument('-h', '--help', action='help', default=SUPPRESS, help='Show this help message and exit.')
-    args.add_argument("-m", "--model", help="Required. Path to an .xml file with a trained model.",
-                      required=True, type=str)
+    args.add_argument('-h', '--help',
+            action = 'help',
+            default = SUPPRESS,
+            help = 'Show this help message and exit.')
+    args.add_argument("-m", "--model",
+            help = "Required. Path to an .xml file with a trained model.",
+            required = True,
+            type = str)
     args.add_argument("-i", "--input",
-                      help="Path to video file or image. 'cam' for capturing video stream from camera",
-                      default = "gstreamer", type=str)
-    args.add_argument("-pt", "--prob_threshold", help="Optional. Probability threshold for detections filtering",
-                      default=0.0, type=float)
-    args.add_argument("--idle", action='store_true', help="Idle if no clients connected")
+            help = "Path to video file or image. 'cam' for capturing video stream from camera",
+            default = "gstreamer",
+            type = str)
+    args.add_argument("-pt", "--prob_threshold",
+            help = "Optional. Probability threshold for detections filtering",
+            default = 0.75,
+            type = float)
+    args.add_argument("--idle",
+            action = 'store_true',
+            help = "Idle if no clients connected")
+    args.add_argument("--key",
+            help = "ROC api key",
+            required = True,
+            type = str)
+    args.add_argument("--mbrlow",
+            help = "Low range of MBR",
+            default = 5000000,
+            type = int)
+    args.add_argument("--mbrhigh",
+            help = "High range of MBR",
+            default = 10000000,
+            type = int)
+    args.add_argument("--devicegroup",
+            help = "Camera device group",
+            default = "menlo-4g-cameras",
+            type = str)
 
     return parser
 
diff --git a/person_detection/base_camera.py b/person_detection/base_camera.py
index 28ee57d..d7a7d29 100644
--- a/person_detection/base_camera.py
+++ b/person_detection/base_camera.py
@@ -1,23 +1,39 @@
-from multiprocessing import Process, Queue
+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
 
 
 class BaseCamera(object):
     process = {} # background process that reads frames from camera
     frame = {} # frame queue
+    activity_counter = Value('i', 0)
+    cameras = Array('i', [0, 0, 0, 0])
+    lock = Lock()
 
-    def __init__(self, device=None, idle=False):
-        """Start the background camera process if it isn't running yet."""
+    def __init__(self, device, key, mbrlow, mbrhigh, devicegroup):
+        self.mqttBroker = "localhost"
         self.device = device
-        if self.device not in BaseCamera.process:
-            BaseCamera.process[self.device] = None
-        if BaseCamera.process[self.device] is None:
+        self.key = key
+        self.mbrlow = mbrlow
+        self.mbrhigh = mbrhigh
+        self.devicegroup = devicegroup
 
-            self.frame[device] = Queue(100)
-
+        """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)
             # 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()
 
@@ -38,3 +54,59 @@
             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()
+            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()
+            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, 4):
+            self.set_resolution(str(device), "high")
+
+
+    def set_resolution_low(self):
+        for device in range(0, 4):
+            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()
diff --git a/person_detection/person_detection.py b/person_detection/person_detection.py
index 47a3fcf..5d01794 100644
--- a/person_detection/person_detection.py
+++ b/person_detection/person_detection.py
@@ -17,11 +17,9 @@
 
 from base_camera import BaseCamera
 
-import action
-
-Shape = namedtuple('Shape', ['n','c','h','w'])
 
 class Camera(BaseCamera):
+    Shape = namedtuple('Shape', ['n','c','h','w'])
 
     def __init__(self, device, args):
         log.basicConfig(format="[ %(levelname)s ] %(message)s", level=log.INFO, stream=sys.stdout)
@@ -32,7 +30,7 @@
         self.is_async_mode = True
         self.device = device
 
-        super(Camera, self).__init__(device, args.idle)
+        super(Camera, self).__init__(device, args.key, args.mbrlow, args.mbrhigh, args.devicegroup)
 
     def __del__(self):
         # stream.release()
@@ -70,7 +68,7 @@
         log.info("Loading IR to the plugin...")
         exec_net = IECore().load_network(network=net, device_name="CPU", num_requests=2)
         # Read and pre-process input image
-        shape = Shape(*net.inputs[input_blob].shape)
+        shape = Camera.Shape(*net.inputs[input_blob].shape)
 
         del net
 
@@ -142,7 +140,7 @@
                         cv2.FONT_HERSHEY_COMPLEX, 0.6, black, 1)
 
                 if obj_count > 0:
-                    action.person_detected(self.device, obj_count)
+                    self.person_detected(obj_count)
 
             yield cv2.imencode('.jpg', frame)[1].tobytes()
 
diff --git a/person_detection/roc.py b/person_detection/roc.py
index 96d4ac5..a9477f1 100644
--- a/person_detection/roc.py
+++ b/person_detection/roc.py
@@ -8,52 +8,43 @@
 from requests.structures import CaseInsensitiveDict
 
 
-TOKEN = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjU0MzE3MDI4ZWJjNGZjNzFkNGUyZDdlODQwN2M2NTI4MWU5ZmYzYTgifQ.eyJpc3MiOiJodHRwczovL2RleC5hZXRoZXJwcm9qZWN0Lm9yZy9kZXgiLCJzdWIiOiJDaXN4TmpNNE5ERTZPRGMxWlRNeU5qY3RZakkwT1MwME9XTXdMV0V5TW1ZdE1qUmlaalUyWXprNVpEazFFZ1ZqY205M1pBIiwiYXVkIjoiYWV0aGVyLXJvYy1ndWkiLCJleHAiOjE2Mzg2MzkwNTQsImlhdCI6MTYzODU1MjY1NCwibm9uY2UiOiJkemw0TkZGb1RDMDBjVWxyVlRsMmJVTTVRekJvY3pCRVQzZEVWbWxKVlU5UVZXVlBjSFpoTm14NU1ERnIiLCJhdF9oYXNoIjoiWElONGprZzdyeWRzVVRROVBjekVZZyIsImNfaGFzaCI6IlZuSng4cklpSGRYeWFjSi0yaVgyaEEiLCJlbWFpbCI6InNoYWRAb3Blbm5ldHdvcmtpbmcub3JnIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImdyb3VwcyI6WyJBZXRoZXJST0NBZG1pbiIsIk9ORlN0YWZmIl0sIm5hbWUiOiJzaGFkIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2hhZCJ9.F6v3q5RuJVUm-4BPcj02IOoDL5grsmjlYzGJSvuM7R9lCIWXI-Qi6Xb-rgLtCBH3qGhWHuk8abd7ud2ipYDnpLybavJOB8iPr_I-lBy6MFxriTxp6OipeZ5nxAXyt9iyslNcLTTmzapsV5Blzl5xvzwOqCItV9dIRVtDNYPiU5CYEA69Eu8Gy8d_0URmI5re26LaBzJ8EHu1KHuhTh3RoExZUHyCagrTmtUnLkep9jXOTszGoKW2Qw7p2H3d-vHIAVGCx2JBERQC8zAalIaajTZ_gc8lqgzsYauSbHIVdm7o5AesL_dCOJQF1E-FTXDOdVMHVmos7BDchr9jui5_Dg"
-### A VALID TOKEN ###"
-
 URL = "https://roc.menlo.aetherproject.org/aether-roc-api/aether/v4.0.0/connectivity-service-v4/"
 #URL = "https://roc.staging.aether.onlab.us/aether-roc-api/aether/v4.0.0/connectivity-service-v4/"
 
-cameras = "menlo-4g-cameras"
-#cameras = "cameras-4g"
 
-MBR_HIGH = 5000000
-MBR_LOW  = 2000000
+def headers(key):
+    h = CaseInsensitiveDict()
+    h["Content-Type"] = "application/json"
+    h["Authorization"] = "Bearer " + key
+    return h
 
-roc_headers = CaseInsensitiveDict()
-roc_headers["Content-Type"] = "application/json"
-roc_headers["Authorization"] = "Bearer " + TOKEN
-
-def get_mbr(device_group):
+def get_mbr(key, device_group):
     url = URL + "vcs/vcs/vcs-{}/slice/mbr".format(device_group)
-    response = requests.get(url, headers=roc_headers)
+    response = requests.get(url, headers=headers(key))
     if response.status_code != 200:
         print("Failed to get mbr, status_code: {}".format(response.status_code))
         return None
     mbr = json.loads(response.text)
     return mbr
 
-def set_mbr(device_group, mbr):
+def set_mbr(key, device_group, mbr):
+    m = {'uplink' : mbr}
     url = URL + "vcs/vcs/vcs-{}/slice/mbr".format(device_group)
-    response = requests.post(url, headers=roc_headers, json=mbr)
+    response = requests.post(url, headers=headers(key), json=m)
     assert response.status_code == 201, "Failed to set mbr"
     if response.status_code != 201:
         print("Failed to set mbr, device_group:{}, mbr:{}, status_code: {}".format(device_group, mbr, response.status_code))
 
-def set_uplink_mbr_high():
-    mbr = {'uplink' : MBR_HIGH}
-    set_mbr(cameras, mbr)
-
-def set_uplink_mbr_low():
-    mbr = {'uplink' : MBR_LOW}
-    set_mbr(cameras, mbr)
-
 if __name__ == '__main__':
-    mbr = get_mbr(cameras)
+    key = ""
+    cameras = "menlo-4g-cameras"
+    #cameras = "cameras-4g"
+
+    mbr = get_mbr(key, cameras)
     print("uplink mbr:{}, downlink mbr: {}".format(mbr["uplink"], mbr["downlink"]))
-    set_uplink_mbr_low()
-    mbr = get_mbr(cameras)
+    set_mbr(key, cameras, 5000000)
+    mbr = get_mbr(key, cameras)
     print("uplink mbr:{}, downlink mbr: {}".format(mbr["uplink"], mbr["downlink"]))
-    set_uplink_mbr_high()
-    mbr = get_mbr(cameras)
+    set_mbr(key, cameras, 10000000)
+    mbr = get_mbr(key, cameras)
     print("uplink mbr:{}, downlink mbr: {}".format(mbr["uplink"], mbr["downlink"]))