def load_sensors(self): """Load the sensors from the db in the thread to avoid session problems""" storage.set(storage.MONITORING_STATE, MONITORING_UPDATING_CONFIG) send_sensors_state(None) # TODO: wait a little bit to see status for debug sleep(3) # !!! delete old sensors before load again self._sensors = [] self._sensors = self._db_session.query(Sensor).filter_by(deleted=False).all() self._logger.debug("Sensors reloaded!") if len(self._sensors) > self._sensorAdapter.channel_count: self._logger.info( "Invalid number of sensors to monitor (Found=%s > Max=%s)", len(self._sensors), self._sensorAdapter.channel_count, ) self._sensors = [] storage.set(storage.MONITORING_STATE, MONITORING_INVALID_CONFIG) elif not self.validate_sensor_config(): self._logger.info("Invalid channel configuration") self._sensors = [] storage.set(storage.MONITORING_STATE, MONITORING_INVALID_CONFIG) elif self.has_uninitialized_sensor(): self._logger.info("Found sensor(s) without reference value") self.calibrate_sensors() storage.set(storage.MONITORING_STATE, MONITORING_READY) else: storage.set(storage.MONITORING_STATE, MONITORING_READY) send_sensors_state(False)
def disarm_monitoring(self, user_id, keypad_id): if self._delay_timer: self._delay_timer.cancel() self._delay_timer = None arm = self._db_session.query(Arm).filter_by(end_time=None).first() if arm: arm.end_time = dt.now() arm.end_user_id = user_id arm.end_keypad_id = keypad_id self._db_session.commit() current_state = storage.get(storage.MONITORING_STATE) current_arm = storage.get(storage.ARM_STATE) if ( current_state in ( MONITORING_ARM_DELAY, MONITORING_ARMED, MONITORING_ALERT_DELAY, MONITORING_ALERT) and current_arm in (ARM_AWAY, ARM_STAY) or current_state == MONITORING_SABOTAGE ): storage.set(storage.ARM_STATE, ARM_DISARM) storage.set(storage.MONITORING_STATE, MONITORING_READY) self._stop_alert.set()
def run(self): self._logger.info("Monitoring started") self._db_session = Session() # wait some seconds to build up socket IO connection before emit messages sleep(5) # remove invalid state items from db before startup self.cleanup_database() # initialize state send_alert_state(None) send_syren_state(None) storage.set(storage.ARM_STATE, ARM_DISARM) self.load_sensors() while True: try: message = self._actions.get(True, 1 / int(environ["SAMPLE_RATE"])) self._logger.debug("Action: %s" % message) if message["action"] == MONITOR_STOP: break elif message["action"] == MONITOR_ARM_AWAY: self.arm_monitoring(ARM_AWAY, message.get("user_id", None), message.get("keypad_id", None)) elif message["action"] == MONITOR_ARM_STAY: self.arm_monitoring(ARM_STAY, message.get("user_id", None), message.get("keypad_id", None)) elif message["action"] in (MONITORING_ALERT, MONITORING_ALERT_DELAY): if self._delay_timer: self._delay_timer.cancel() self._delay_timer = None elif message["action"] == MONITOR_DISARM: self.disarm_monitoring(message.get("user_id", None), message.get("keypad_id", None)) continue elif message["action"] == MONITOR_UPDATE_CONFIG: self.load_sensors() except Empty: pass self.check_power() self.scan_sensors() self.handle_alerts() self._stop_alert.set() self._db_session.close() self._logger.info("Monitoring stopped")
def check_power(self): # load the value once from the adapter new_power_source = self._powerAdapter.source_type if new_power_source == PowerAdapter.SOURCE_BATTERY: storage.set(storage.POWER_STATE, POWER_SOURCE_BATTERY) self._logger.debug("System works from battery") elif new_power_source == PowerAdapter.SOURCE_NETWORK: storage.set(storage.POWER_STATE, POWER_SOURCE_NETWORK) self._logger.debug("System works from network") if new_power_source == PowerAdapter.SOURCE_BATTERY and self._power_source == PowerAdapter.SOURCE_NETWORK: send_power_state(POWER_SOURCE_BATTERY) self._logger.info("Power outage started!") elif new_power_source == PowerAdapter.SOURCE_NETWORK and self._power_source == PowerAdapter.SOURCE_BATTERY: send_power_state(POWER_SOURCE_NETWORK) self._logger.info("Power outage ended!") self._power_source = new_power_source
def __init__(self, broadcaster: Broadcaster): """ Constructor """ super(Monitor, self).__init__(name=THREAD_MONITOR) self._logger = logging.getLogger(LOG_MONITOR) self._sensorAdapter = SensorAdapter() self._powerAdapter = PowerAdapter() self._broadcaster = broadcaster self._sensors = None self._power_source = None self._db_session = None self._alerts = {} self._actions = Queue() self._stop_alert = Event() self._delay_timer = None storage.set(storage.MONITORING_STATE, MONITORING_STARTUP) storage.set(storage.ARM_STATE, ARM_DISARM) self._broadcaster.register_queue(id(self), self._actions) self._logger.info("Monitoring created")
def arm_monitoring(self, arm_type, user_id, keypad_id): self._db_session.add( Arm( arm_type=arm_type, start_time=dt.now(), user_id=user_id, keypad_id=keypad_id, ) ) self._db_session.commit() # get max delay of arm arm_delay = get_arm_delay(self._db_session, arm_type) def stop_arm_delay(): self._logger.debug("End arm delay => armed!!!") storage.set(storage.MONITORING_STATE, MONITORING_ARMED) storage.set(storage.ARM_STATE, arm_type) self._logger.debug("Arm with delay: %s / %s", arm_delay, arm_type) if arm_delay is not None: storage.set(storage.MONITORING_STATE, MONITORING_ARM_DELAY) self._delay_timer = Timer(arm_delay, stop_arm_delay) self._delay_timer.start() else: storage.set(storage.MONITORING_STATE, MONITORING_ARMED) self._stop_alert.clear()
def run(self): self._logger.info( "Alert (%s) started on sensor (id:%s) waiting %s sec before starting syren", self._alert_type, self._sensor_id, self._delay, ) if self._delay > 0: storage.set(storage.MONITORING_STATE, MONITORING_ALERT_DELAY) self._broadcaster.send_message({"action": MONITORING_ALERT_DELAY}) if not self._stop_event.wait(self._delay): self._logger.info( "Start syren because not disarmed (%s) sensor (id:%s) in %s secs", self._alert_type, self._sensor_id, self._delay, ) SyrenAlert.start_syren(self._alert_type, SensorAlert._sensor_queue, self._stop_event) SensorAlert._sensor_queue.put(self._sensor_id) if self._alert_type == ALERT_SABOTAGE: storage.set(storage.MONITORING_STATE, MONITORING_SABOTAGE) self._broadcaster.send_message({"action": MONITORING_SABOTAGE}) else: storage.set(storage.MONITORING_STATE, MONITORING_ALERT) self._broadcaster.send_message({"action": MONITORING_ALERT}) else: self._logger.info("Sensor alert stopped")
def stop_arm_delay(): self._logger.debug("End arm delay => armed!!!") storage.set(storage.MONITORING_STATE, MONITORING_ARMED)