def capture_timer_image(): time.sleep(5) #Sleep for 5 seconds on startup then take the first picture while True: logger.info("Capturing timer image: %i min" % config.get(constants.CONFIG_TIMER_INTERVAL_MIN)) success = capture.request() if not success: logger.info("Timer image was triggered but the camera was already in use") time.sleep(config.get(constants.CONFIG_TIMER_INTERVAL_MIN) * constants.SECONDS2MIN)
def capture(self): with self.__lock__: logger.info("Capture image") filename = get_filename(config.get(constants.CONFIG_IMAGE_DIR), config.get(constants.CONFIG_IMAGE_PREFIX)) self.stop() self.camera.resolution = (config.get(constants.CONFIG_IMAGE_WIDTH), config.get(constants.CONFIG_IMAGE_HEIGHT)) self.camera.capture(filename, format="jpeg", quality=config.get(constants.CONFIG_IMAGE_QUALITY)) self.start() return filename
def enabled(self): if not config.get(constants.CONFIG_MOTION_ENABLED): return False #motion disabled in configuration if self.last_motion_event is None or self.exceeds_motion_capture_delay(): self.motion_events = 1 self.last_motion_event = datetime.now() return True #doesn't exceed motion capture delay elif self.motion_events + 1 <= config.get(constants.CONFIG_MOTION_CAPTURE_THRESHOLD): self.motion_events += 1 self.last_motion_event = datetime.now() return True #still within motion capture threshold else: logger.warning("Motion capture threshold exceeded") return False #exceeds motion capture threshold
def get(self): try: return jsonify(config.get()) except exceptions.HTTPException: raise except Exception as ex: logger.exception("An error occurred while attempting to send configs") abort(500)
def motion_detected(self): logger.debug("Motion capture requested") if self.working: logger.info("Cannot process motion request. Another request is still in progress") return False self.event = constants.EVENT_MOTION, config.get(constants.CONFIG_MOTION_EVENT_CAPTURE_TYPE) return True
def check_config_updates(*args): logger.info( "Checking for config updates: %s" % args ) try: server_configs = server.get_config() if server_configs is None or server_configs[constants.CONFIG_VERSION] < config.get(constants.CONFIG_VERSION): logger.info("Server config out of date, sending updated cam config") server.send_config() elif server_configs[constants.CONFIG_VERSION] > config.get(constants.CONFIG_VERSION): logger.info("Cam config updating from server") config.update(server_configs) config.set_status(constants.CONFIG_STATUS_UPDATED) server.send_config_status(config.get_status()) #restart capture to load the most recent configs capture.restart() socket.config_updated(config.get_status()) except ValueError: logger.exception("Could not parse response from server") except Exception as ex: logger.exception("Could not update configs from the server")
def start(self): logger.info("Starting capture") sensitivity = config.get(constants.CONFIG_MOTION_SENSITIVITY) threshold = config.get(constants.CONFIG_MOTION_THRESHOLD) percent_change_max = config.get(constants.CONFIG_MOTION_PERCENT_CHANGE_MAX) self.camera.resolution = (config.get(constants.CONFIG_IMAGE_WIDTH),config.get(constants.CONFIG_IMAGE_HEIGHT)) self.camera.framerate = 2 self.camera.vflip = config.get(constants.CONFIG_IMAGE_VFLIP) self.camera.hflip = config.get(constants.CONFIG_IMAGE_HFLIP) self.camera.exposure_mode = config.get(constants.CONFIG_IMAGE_EXPOSURE_MODE) self.camera.awb_mode = config.get(constants.CONFIG_IMAGE_AWB_MODE) self.camera.led = False if self.motion_enabled: analyzer = motion.SimpleGaussMotionDetector(self.camera, self.handler, sensitivity, threshold, percent_change_max = percent_change_max) self.camera.start_recording(self.buffer, format='h264') self.camera.start_recording(analyzer, format='rgb', splitter_port=2, resize=(320,240))
def capture_image(): global capturing capturing = True filename = get_filename(config.get(constants.CONFIG_IMAGE_DIR), config.get(constants.CONFIG_IMAGE_PREFIX)) with camera_lock: with picamera.PiCamera() as camera: camera.resolution = (config.get(constants.CONFIG_IMAGE_WIDTH), config.get(constants.CONFIG_IMAGE_HEIGHT)) camera.vflip = config.get(constants.CONFIG_IMAGE_VFLIP) camera.hflip = config.get(constants.CONFIG_IMAGE_HFLIP) quality = config.get(constants.CONFIG_IMAGE_QUALITY) camera.exposure_mode = 'auto' camera.awb_mode = 'auto' camera.capture(filename, format="jpeg", quality=quality) capturing = False return filename
def record(self, seconds): with self.__lock__: logger.info("Recording event for %s seconds" % seconds) filename = get_filename(config.get(constants.CONFIG_IMAGE_DIR), "recording-", "h264") temp = "%s.temp" % filename #Split the recording into the output file for the after motion data self.camera.split_recording(temp) #Write before motion buffer into file with io.open(filename, 'wb') as output: with self.buffer.lock: for frame in self.buffer.frames: if frame.frame_type == picamera.PiVideoFrameType.sps_header: self.buffer.seek(frame.position) break while True: buf = self.buffer.read1() if not buf: break output.write(buf) self.buffer.seek(0) self.buffer.truncate() #split the recording back into the circular stream self.camera.wait_recording(seconds) self.camera.split_recording(self.buffer) #stitch the 2 streams together and remove the temp file with io.open(filename, 'ab') as output: with io.open(temp, 'rb') as t: output.write(t.read()) os.remove(temp) return filename
def exceeds_motion_capture_delay(self): if self.last_motion_event is not None: delta_date = datetime.now() - timedelta(seconds=config.get(constants.CONFIG_MOTION_DELAY_SEC)) return delta_date > self.last_motion_event else: return True
if detected and motion_events.enabled(): success = capture.motion_detected() else: return if not success: logger.info("Manual image was triggered but the camera was already in use") #Initialize motion_events = motion.MotionEvents() motion_sensors = sensors.Motion(capture_motion_image) capture = camera.CaptureHandler(send) temp = sensors.Temperature() server = service.YetiService(config.get(constants.CONFIG_SERVER)) socket = service.YetiSocket(config.get(constants.CONFIG_SOCKET_HOST), config.get(constants.CONFIG_SOCKET_PORT), config_update_callback=check_config_updates, manual_capture_callback=capture_manual_image) #check for config updates from the server check_config_updates({"version":"current"}) #start all threads and run until a stop signal is detected capture.start() timer_capture_thread = threading.Thread(target=capture_timer_image) timer_capture_thread.daemon = True timer_capture_thread.start() def signal_handler(signal, frame): logger.warning("Stop signal detected...")
def send_config(self): logger.info("Updating server configs") r = requests.put(self.baseUrl + "config", json=config.get()) logger.info("StatusCode: %s, Text: %s" % (r.status_code, r.text))