def update_usage(): '''Every UPDATE_INTERVAL, update for how long the backend has been running''' global LICENSE_PARAMS count = 1 t = threading.currentThread() performance.add_thread() print bgcolors.FAIL + 'Update license usage TID: %d\n' % ( get_tid()) + bgcolors.ENDC # Keep running detection thread as long as stop event not occurred while (not t.stopped()): # TODO: Revise this if statement below if count % UPDATE_INTERVAL == 0: print bgcolors.WARNING + '\nUpdate usage' + bgcolors.ENDC try: # Get current usage from database usage_in_hr = LICENSE_DB.retrieve( LICENSE_PARAMS['license_id'])[0][1] usage_in_hr += 1 LICENSE_DB.edit(LICENSE_PARAMS['license_id'], usage_in_hr) print "Usage in hours: %d" % (usage_in_hr) USAGE_LOCK.acquire() LICENSE_PARAMS['used'] = usage_in_hr USAGE_LOCK.release() ret, msg = is_license_valid() # Stop thread after license expires if not ret: print 'From while loop:', msg auto_testcases.update_license_logfile() t.stop() break except Exception as ex: print ex logger.error(ex.message) time.sleep(1) count += 1 # Deinit backend sessions print bgcolors.FAIL + 'Clean up from license thread' + bgcolors.ENDC camera_controller.delete_all_cameras(delete_from_db=False) camera_controller.deinitialize_model()
def monitor_thread(): '''This thread spawns and monitors the notification threads and respawns them if they crash''' t = current_thread() display_tid(t.name, get_tid()) performance.add_thread() logging.info("Starting monitoring thread: %s" % (t.name)) if USE_IMI: call_method = call_imi else: call_method = call_twilio sms_method = sms_textlocal # Add the respective queues for performance performance.add_call_q(call_q) performance.add_sms_q(sms_q) performance.add_email_q(email_q) # Create the three notification threads email_thread = StoppableThread(target=sendEmail, name="Email-Thread") call_thread = StoppableThread(target=call_method, name="Call-Thread") sms_thread = StoppableThread(target=sms_method, name="SMS-Thread") # Add the threads to the monitoring dicitonary monitor_dict = { "Email-Thread": email_thread, "Call-Thread": call_thread, "SMS-Thread": sms_thread } # Start the threads logging.info("Starting notifier threads...") for thread_name, _thread in monitor_dict.iteritems(): _thread.start() # Monitor the thread for activity while (not t.stopped()): time.sleep(1) for thread_name, _thread in monitor_dict.iteritems(): if not _thread.is_alive(): try: if thread_name == "Email-Thread": # Close existing thread _thread.join() # Restart new thread logging.warning("Re-starting Email-Thread") print bg.FAIL + '\nRe-starting Email-Thread' + bg.ENDC email_thread = StoppableThread(target=sendEmail, name='Email-Thread') monitor_dict["Email-Thread"] = email_thread email_thread.start() elif thread_name == "Call-Thread": # Close existing thread _thread.join() # Restart new thread logging.warning("Re-starting Call-Thread") print bg.FAIL + '\nRe-starting Call-Thread' + bg.ENDC call_thread = StoppableThread(target=call_method, name='Call-Thread') monitor_dict["Call-Thread"] = call_thread call_thread.start() elif thread_name == "SMS-Thread": # Close existing thread _thread.join() # Restart new thread logging.warning("Re-starting SMS-Thread") print bg.FAIL + '\nRe-starting SMS-Thread' + bg.ENDC sms_thread = StoppableThread(target=sms_method, name='SMS-Thread') monitor_dict["SMS-Thread"] = sms_thread sms_thread.start() except Exception as ex: print ex logging.error(ex.message) print bg.FAIL + '\nClean up from monitor thread' + bg.ENDC for thread_name, _thread in monitor_dict.iteritems(): _thread.join()
def detect_object(camera_obj, mod_q): '''Detect objects and generate alerts if threshold has crossed''' # Process feed only if detection is enabled if not is_any_detection_enabled(camera_obj.object_detect): logger.info("No Object detection enabled. Not processing feed...") return t = threading.currentThread() display_tid(t.name, get_tid()) performance.add_thread() vcap = camera_obj.get_video_cap() frame_count = 0 last_detection_frame = 0 last_person_detection_frame = 0 # Initialize first two frames with None t0 = None t1 = None ret = False # Error flags ERROR_FLAG = False main_start = time.time() # Keep running detection thread as long as stop event not occurred while (not t.stopped()): # Try to open the video stream if not vcap.isOpened() or ERROR_FLAG: ERROR_FLAG = False ret = False waitTime = 1 while ret == False and not t.stopped(): logger.error( "Could not read video capture for %s. Retrying after %d second..." % (camera_obj.camera_name, waitTime)) time.sleep(waitTime) vcap = camera_obj.get_video_cap() ret, t2 = vcap.read() if waitTime < 5: waitTime = waitTime + 1 try: fps = int(vcap.get(cv2.CAP_PROP_FPS)) # Since analog cameras aren't returning a normal fps value if fps > 30: fps = 30 frame_rate = camera_obj.get_frame_rate() frame_per_window = int(fps / frame_rate) # Read the third image ret2, t2 = vcap.read() if not ret2: logger.error("Could not read the video frames for %s" % (camera_obj.camera_name)) ERROR_FLAG = True time.sleep(0.5) # Avoid high CPU usage continue # Process frames as per the camera's sensitivity settings if frame_count % frame_per_window == 0: height, width, _ = t2.shape if height > MIN_HEIGHT_DIM: factor = MIN_HEIGHT_DIM / float(height) t2 = cv2.resize(t2, None, fx=factor, fy=factor) logger.debug("Camera %s frame num to process:%d" % (camera_obj.camera_name, frame_count)) # Main call to motion predict object_dict = camera_obj.object_detect.copy() del object_dict["intrusion"] # if 1 in object_dict.values() and ((t0!=None) and (t1!=None) and (t2!=None)): # performance.fps_log('Calling Inception for %s'%(t.name)) # image, pred_dict = motion_predict.extract_feature(t0, t1, t2) # if pred_dict is not None: # logger.debug("Camera %s Prediction Dict:%s"%(camera_obj.camera_name, str(pred_dict))) # for obj, detection_status in object_dict.iteritems(): # if detection_status == DETECTION_STATUS_ON and any(obj in key for key in pred_dict): # predict_obj = [key for key in pred_dict if obj in key][0] # prediction_val = pred_dict[predict_obj] # logger.debug("Detected object:%s with confidence=%f and detection threshold=%f"%(obj, # prediction_val, DETECTION_THRESHOLD)) # if prediction_val > DETECTION_THRESHOLD: # if last_detection_frame == 0 or (frame_count - last_detection_frame)/fps > MIN_DETECT_INTERVAL: # notify_detection(image, camera_obj, obj, prediction_val) # last_detection_frame = frame_count # Check if intrusion is enabled and time is satisfied if camera_obj.is_intrusion_enabled(): #mod_q.put((camera_obj.camera_id, camera_obj.camera_name, camera_obj.email_list, camera_obj.sms_list, camera_obj.call_list, frame_count, fps, t2), block=False) im = darknet.array_to_image(t2) darknet.rgbgr_image(im) mod_q.put((camera_obj.camera_id, camera_obj.camera_name, camera_obj.email_list, camera_obj.sms_list, camera_obj.call_list, frame_count, fps, t2, im), block=False) # Pass on the old values t0 = t1 t1 = t2 frame_count += 1 except Queue.Full: logger.error("The detection Queueu is full! Max Size:%d reached" % (MAX_Q_SZ)) except Exception as ex: ERROR_FLAG = True time.sleep(0.5) # Avoid high CPU usage logger.error(ex.message) print bgcolors.FAIL + 'Clean up from %s' % t.name + bgcolors.ENDC vcap.release() cv2.destroyAllWindows()
def call_imi(): ''' This function calls all the numbers in the call_list using IMI services ''' t = current_thread() display_tid(t.name, get_tid()) performance.add_thread() logging.info("Starting Call thread: %s" % (t.name)) caller_dict = {} call_count_dict = {} #call_list, objectType = call_q.get(block=True, timeout=MIN_Q_TIMEOUT) #auto_testcases.calllist_automation(False,1,call_list,len(call_list),MAX_CALL_Q_SZ,call_q.qsize()) start_time = time.time() call_time_gap_flag = True call_time_gap = 1 while (not t.stopped()): try: # If the MAX_CALL_Q_SZ has been reached, we have plenty of buffered items which will take too # long to process. In this scenario, reduce the Queue to include only the latest 'MIN_CALL_Q_PERCENT' # items to be processed if call_q.qsize() == MAX_CALL_Q_SZ: reduce_items = int(MAX_CALL_Q_SZ - (MIN_CALL_Q_PERCENT * MAX_CALL_Q_SZ / float(100))) logger.info( "Max call q size reached:%d removing oldest %d items" % (MAX_CALL_Q_SZ, reduce_items)) for _ in range(reduce_items): _, _ = call_q.get() call_list, objectType = call_q.get(block=True, timeout=MIN_Q_TIMEOUT) if (time.time() > start_time + 40): if (4 in run_testcases.flag): auto_testcases.calllist_automation(call_time_gap_flag, call_time_gap, call_list, len(call_list), MAX_CALL_Q_SZ, call_q.qsize() + 1) start_time = time.time() def timeout_call(call_list, objectType, caller_dict, call_count_dict): apiurl = "http://api-openhouse.imimobile.com/1/obd/thirdpartycall/callSessions" mode = 'Media' new_call_list = [] for callee in call_list: if callee not in caller_dict or ( callee in caller_dict and time.time() - caller_dict[callee] > CALL_GAP_TIME): called_party = '91' + callee logging.debug("Calling: %s for object: %s" % (called_party, objectType)) print bgcolors.OKGREEN + '\nCalling %s, alerting for %s' % ( called_party, objectType) + bgcolors.ENDC #rawdata ="address=%(Mobile)s&medianame=%(medianame)s&mode=%(mode)s" % dict(Mobile=called_party, rawdata = "address=%(Mobile)s&mode=%(mode)s&patternId=0&medianame=%(medianame)s" % dict( Mobile=called_party, mode=mode, medianame=objectType) headers = { 'key': API_KEY, 'Content-type': 'application/x-www-form-urlencoded' } r = requests.post(apiurl, data=json.dumps(rawdata).replace( "\"", ""), headers=headers) #print "Ritwik:", apiurl, json.dumps(rawdata).replace("\"",""), headers print 'IMI call JSON response: %s\n' % (r.text) logging.debug("JSON Response UUID: %s" % (r.text)) caller_dict[callee] = time.time() # A buffered call has been processsed, so reduce the buffered call count if callee in call_count_dict: call_count_dict[ callee] = call_count_dict[callee] - 1 else: # Only store a maximum of 10 elements of a particular caller. # Do not keep storing a caller indefinitely if callee in call_count_dict and call_count_dict[ callee] < MAX_CALL_SAME_NUM_BUFFER: call_count_dict[ callee] = call_count_dict[callee] + 1 elif callee not in call_count_dict: call_count_dict[callee] = 1 if call_count_dict[callee] <= MAX_CALL_SAME_NUM_BUFFER: new_call_list.append(callee) if new_call_list: call_q.put((new_call_list, objectType)) timeout(timeout_call, (call_list, objectType, caller_dict, call_count_dict)) except Queue.Empty as ex: pass except Exception as ex: print ex logging.error(ex) time.sleep(1) print "Stopping Call thread: %s" % (t.name) logging.info("Stopping Call thread: %s" % (t.name))
def sms_imi(): ''' This sents a SMS to the numbers in "toAddressList" using IMI services ''' t = current_thread() display_tid(t.name, get_tid()) performance.add_thread() logging.info("Starting SMS thread: %s" % (t.name)) while (not t.stopped()): try: # If the MAX_SMS_Q_SZ has been reached, we have plenty of buffered items which will take too # long to process. In this scenario, reduce the Queue to include only the latest 'MIN_SMS_Q_PERCENT' # items to be processed if sms_q.qsize() == MAX_SMS_Q_SZ: reduce_items = int(MAX_SMS_Q_SZ - (MIN_SMS_Q_PERCENT * MAX_SMS_Q_SZ / float(100))) logger.info( "Max sms q size reached:%d removing oldest %d items" % (MAX_SMS_Q_SZ, reduce_items)) for _ in range(reduce_items): _, _, _, _, _ = sms_q.get() toAddressList, objectType, detectionTime, camera_name, detectionAcuracy = sms_q.get( block=True, timeout=MIN_Q_TIMEOUT) Subj = "%s Detection Alarm!!!\n\n" % (objectType.title()) Text = "%s detected at %s for camera '%s' with %d%% accuracy." % ( objectType.title(), detectionTime, camera_name, detectionAcuracy) Text += "\n\nFrom Deep Sight AI Labs" Message = Subj + Text apiurl = 'http://api-openhouse.imimobile.com/smsmessaging/1/outbound/tel%3A%2Bopnhse/requests' for toAddress in toAddressList: called_party = '91' + toAddress print '\nSending notification SMS to %s with content:\n------------\n%s\n------------' % ( called_party, Message) #JSON object to be sent in the POST body. rawdata = { 'outboundSMSMessageRequest': { 'address': 'tel:' + called_party, 'senderAddress': 'tel:OPNHSE', 'senderName': 'DSLABS', 'outboundSMSTextMessage': { 'message': Message } } } headers = { 'key': API_KEY, 'Content-type': 'application/json', 'Accept': 'application/json' } r = requests.post(apiurl, data=json.dumps(rawdata), headers=headers) uuid = None try: uuid = r.text[r.text.index( 'urn:uuid:'):][:r.text[r.text.index('urn:uuid:'):]. index('\\')] print 'IMI SMS JSON response:', uuid except: print 'IMI SMS JSON response:', r.text logging.debug("Sending SMS to: %s with content: %s" % (toAddress, Message)) logging.debug("JSON Response UUID: %s" % (uuid)) except Queue.Empty as ex: pass except Exception as ex: print ex logging.error(ex.message) time.sleep(0.5) print "Stopping SMS thread: %s" % (t.name) logging.info("Stopping SMS thread: %s" % (t.name))
def call_twilio(): ''' This function calls all the numbers in the call_list using twilio ''' t = current_thread() display_tid(t.name, get_tid()) performance.add_thread() logging.info("Starting Call thread: %s" % (t.name)) caller_dict = {} call_count_dict = {} while (not t.stopped()): try: new_call_list = [] # If the MAX_CALL_Q_SZ has been reached, we have plenty of buffered items which will take too # long to process. In this scenario, reduce the Queue to include only the latest 'MIN_CALL_Q_PERCENT' # items to be processed if call_q.qsize() == MAX_CALL_Q_SZ: reduce_items = int(MAX_CALL_Q_SZ - (MIN_CALL_Q_PERCENT * MAX_CALL_Q_SZ / float(100))) logger.info( "Max call q size reached:%d removing oldest %d items" % (MAX_CALL_Q_SZ, reduce_items)) for _ in range(reduce_items): _, _ = call_q.get() call_list, objectType = call_q.get(block=True, timeout=MIN_Q_TIMEOUT) def call_timeout(call_list, objectType, caller_dict, call_count_dict): client = Client(account_sid, auth_token) if objectType == "intrusion": objectType = "int" xml_file = default_twilio_url + objectType + ".xml" for callee in call_list: if callee not in caller_dict or ( callee in caller_dict and time.time() - caller_dict[callee] > CALL_GAP_TIME): called_party = str("+91" + callee) logging.debug( "called_party:%s default_twilio_from:%s xml_file:%s" % (called_party, default_twilio_from, xml_file)) call = client.calls.create(to=called_party, from_=default_twilio_from, url=xml_file) caller_dict[callee] = time.time() # A buffered call has been processsed, so reduce the buffered call count if callee in call_count_dict: call_count_dict[ callee] = call_count_dict[callee] - 1 else: # Only store a maximum of 10 elements of a particular caller. # Do not keep storing a caller indefinitely if callee in call_count_dict and call_count_dict[ callee] < MAX_CALL_SAME_NUM_BUFFER: call_count_dict[ callee] = call_count_dict[callee] + 1 elif callee not in call_count_dict: call_count_dict[callee] = 1 if call_count_dict[callee] <= MAX_CALL_SAME_NUM_BUFFER: new_call_list.append(callee) if new_call_list: call_q.put((new_call_list, objectType)) timeout(call_timeout, (call_list, objectType, caller_dict, call_count_dict)) except Queue.Empty as ex: pass except Exception as ex: print ex logging.error(ex) time.sleep(1) logging.info("Stopping Call thread: %s" % (t.name))
def sms_textlocal(): ''' This sents a SMS to the numbers in "toAddressList" using text_local ''' t = current_thread() display_tid(t.name, get_tid()) performance.add_thread() logging.info("Starting SMS thread: %s" % (t.name)) error_flag = True #toAddressList, objectType, detectionTime, camera_name, detectionAcuracy = sms_q.get(block=True, timeout=MIN_Q_TIMEOUT) #auto_testcases.smslist_automation(toAddressList,len(toAddressList),MAX_SMS_Q_SZ,sms_q.qsize()) start_time = time.time() while (not t.stopped()): try: # If the MAX_SMS_Q_SZ has been reached, we have plenty of buffered items which will take too # long to process. In this scenario, reduce the Queue to include only the latest 'MIN_SMS_Q_PERCENT' # items to be processed if sms_q.qsize() == MAX_SMS_Q_SZ: reduce_items = int(MAX_SMS_Q_SZ - (MIN_SMS_Q_PERCENT * MAX_SMS_Q_SZ / float(100))) logger.info( "Max sms q size reached:%d removing oldest %d items" % (MAX_SMS_Q_SZ, reduce_items)) for _ in range(reduce_items): _, _, _, _, _ = sms_q.get() toAddressList, objectType, detectionTime, camera_name, detectionAcuracy = sms_q.get( block=True, timeout=MIN_Q_TIMEOUT) if (time.time() > start_time + 40): if (5 in run_testcases.flag): auto_testcases.smslist_automation(toAddressList, len(toAddressList), MAX_SMS_Q_SZ, sms_q.qsize() + 1) start_time = time.time() def timeout_sms(toAddressList, objectType, detectionTime, camera_name, detectionAcuracy): Subj = "%s Detection Alarm!!!" % (objectType.title()) Text = "%s detected at %s for camera %s with %d%% accuracy." % ( objectType.title(), detectionTime, camera_name, detectionAcuracy) toAddressList = [ str(str(toAddress) + "@sms.textlocal.in") for toAddress in toAddressList ] msg = MIMEMultipart() msg['Subject'] = Subj msg['From'] = TEXTLOCAL_USERNAME msg['To'] = ", ".join(toAddressList) msg.attach(MIMEText(Text)) error_flag = True while error_flag: try: server = smtplib.SMTP('smtp.gmail.com', 587) server.starttls() server.ehlo() server.login(TEXTLOCAL_USERNAME, TEXTLOCAL_PASSWORD) except Exception as ex: logger.error(ex) server.quit() else: error_flag = False server.sendmail(TEXTLOCAL_USERNAME, toAddressList, msg.as_string()) logging.info("Sending SMS to: %s with content: %s" % (toAddressList, Text)) timeout(timeout_sms, (toAddressList, objectType, detectionTime, camera_name, detectionAcuracy)) except Queue.Empty as ex: pass except Exception as ex: print ex logging.error(ex) error_flag = True time.sleep(1) logging.info("Stopping SMS thread: %s" % (t.name))
def sendEmail(): ''' This sents a mail a message to the mail ids in "toAddressList" with the details of intrusion and an image capturing the intruder. ''' t = current_thread() display_tid(t.name, get_tid()) performance.add_thread() logging.info("Starting email thread: %s" % (t.name)) error_flag = True start_time = time.time() print run_testcases.flag #toAddressList, objectType, detectionTime, camera_name, detectionAcuracy, imageName = email_q.get(block=True, timeout=MIN_Q_TIMEOUT) #auto_testcases.emaillist_automation(toAddressList,len(toAddressList),MAX_EMAIL_Q_SZ,email_q.qsize()) while (not t.stopped()): try: # If the MAX_EMAIL_Q_SZ has been reached, we have plenty of buffered items which will take too # long to process. In this scenario, reduce the Queue to include only the latest 'MIN_EMAIL_Q_PERCENT' # items to be processed if email_q.qsize() == MAX_EMAIL_Q_SZ: reduce_items = int(MAX_EMAIL_Q_SZ - (MIN_EMAIL_Q_PERCENT * MAX_EMAIL_Q_SZ / float(100))) logger.info( "Max email q size reached:%d removing oldest %d items" % (MAX_EMAIL_Q_SZ, reduce_items)) for _ in range(reduce_items): _, _, _, _, _, _ = email_q.get() toAddressList, objectType, detectionTime, camera_name, detectionAcuracy, imageName = email_q.get( block=True, timeout=MIN_Q_TIMEOUT) if (time.time() > start_time + 40): print "Send mail testing" if (6 in run_testcases.flag): auto_testcases.emaillist_automation( toAddressList, len(toAddressList), MAX_EMAIL_Q_SZ, email_q.qsize() + 1) start_time = time.time() def timeout_email(toAddressList, objectType, detectionTime, camera_name, detectionAcuracy, imageName): Subj = "%s Detection Alarm!!!" % (objectType.title()) Text = "%s detected at %s for camera %s with %d%% accuracy. Please check attached image for reference." % ( objectType.title(), detectionTime, camera_name, detectionAcuracy) msg = MIMEMultipart() msg['Subject'] = Subj msg['From'] = EMAIL_USERNAME msg['To'] = ", ".join(toAddressList) msg.attach(MIMEText(Text)) with open(imageName, "rb") as fil: part = MIMEApplication(fil.read(), Name=basename(imageName)) part['Content-Disposition'] = 'attachment; filename="%s"' % ( basename(imageName)) msg.attach(part) error_flag = True while error_flag: try: server = smtplib.SMTP('smtp.gmail.com', 587) server.starttls() server.ehlo() server.login(EMAIL_USERNAME, EMAIL_PASSWORD) except Exception as ex: logger.error(ex) server.quit() else: error_flag = False server.sendmail(EMAIL_USERNAME, toAddressList, msg.as_string()) logging.info("Sending email to: %s with content: %s" % (toAddressList, Text)) timeout(timeout_email, (toAddressList, objectType, detectionTime, camera_name, detectionAcuracy, imageName)) except Queue.Empty as ex: pass except Exception as ex: print ex logging.error(ex) error_flag = True time.sleep(1) print "Stopping Email thread: %s" % (t.name) logging.info("Stopping email thread: %s" % (t.name))