def checkConditionals(self, cond_id): """ Check if any sensor conditional statements are activated and execute their actions if the conditional is true. For example, if measured temperature is above 30C, notify [email protected] :rtype: None :param each_cond: Object of SQL table entries for a specific column :type each_cond: sqlalchemy object """ attachment_file = False attachment_type = False last_measurement = self.getLastMeasurement( self.cond_measurement_type[cond_id]) if (last_measurement and ((self.cond_direction[cond_id] == 'above' and last_measurement > self.cond_setpoint[cond_id]) or (self.cond_direction[cond_id] == 'below' and last_measurement < self.cond_setpoint[cond_id]))): now = time.time() timestamp = datetime.datetime.fromtimestamp(now).strftime( '%Y-%m-%d %H-%M-%S') message = "{}\n[Sensor Conditional {}] {}\n{} {} ".format( timestamp, cond_id, self.cond_name[cond_id], self.cond_measurement_type[cond_id], last_measurement) if self.cond_direction[cond_id] == 'above': message += ">" elif self.cond_direction[cond_id] == 'below': message += "<" message += " {} setpoint.".format(self.cond_setpoint[cond_id]) if (self.cond_relay_id[cond_id] and self.cond_relay_state[cond_id] in ['on', 'off']): message += "\nTurning relay {} {}".format( self.cond_relay_id[cond_id], self.cond_relay_state[cond_id]) if (self.cond_relay_state[cond_id] == 'on' and self.cond_relay_on_duration[cond_id]): message += " for {} seconds".format( self.cond_relay_on_duration[cond_id]) message += ". " relay_on_off = threading.Thread( target=self.control.relay_on_off, args=( self.cond_relay_id[cond_id], self.cond_relay_state[cond_id], self.cond_relay_on_duration[cond_id], )) relay_on_off.start() # Execute command in shell if self.cond_execute_command[cond_id]: message += "\nExecute '{}'. ".format( self.cond_execute_command[cond_id]) cmd_out, cmd_err, cmd_status = cmd_output( self.cond_execute_command[cond_id]) message += "Status: {}. ".format(cmd_status) if self.cond_camera_record[cond_id] in ['photo', 'photoemail']: attachment_file = camera_record(INSTALL_DIRECTORY, 'photo') elif self.cond_camera_record[cond_id] in ['video', 'videoemail']: attachment_file = camera_record(INSTALL_DIRECTORY, 'video', duration_sec=5) if self.cond_email_notify[cond_id]: if (self.email_count >= self.smtp_max_count and time.time() < self.smtp_wait_timer[cond_id]): self.allowed_to_send_notice = False else: if time.time() > self.smtp_wait_timer[cond_id]: self.email_count = 0 self.smtp_wait_timer[cond_id] = time.time() + 3600 self.allowed_to_send_notice = True self.email_count += 1 # If the emails per hour limit has not been exceeded if self.allowed_to_send_notice: message += "\nNotify {}.".format( self.cond_email_notify[cond_id]) # attachment_type != False indicates to # attach a photo or video if self.cond_camera_record[cond_id] == 'photoemail': message += "\nPhoto attached." attachment_type = 'still' elif self.cond_camera_record[cond_id] == 'videoemail': message += "\nVideo attached." attachment_type = 'video' with session_scope(MYCODO_DB_PATH) as new_session: smtp = new_session.query(SMTP).first() send_email(self.logger, smtp.host, smtp.ssl, smtp.port, smtp.user, smtp.passw, smtp.email_from, self.cond_email_notify[cond_id], message, attachment_file, attachment_type) else: self.logger.debug( "[Sensor Conditional {}] " "{:.0f} seconds left to be " "allowed to email again.".format( cond_id, (self.smtp_wait_timer[cond_id] - time.time()))) if self.cond_flash_lcd[cond_id]: start_flashing = threading.Thread( target=self.control.flash_lcd, args=( self.cond_flash_lcd[cond_id], 1, )) start_flashing.start() self.logger.debug(message) else: self.logger.debug("[Sensor Conditional {}] Last measurement " "not found".format(cond_id))
def checkConditionals(self, relay_id, on_duration): with session_scope(MYCODO_DB_PATH) as new_session: conditionals = new_session.query(RelayConditional) new_session.expunge_all() new_session.close() conditionals = conditionals.filter(RelayConditional.if_relay_id == relay_id) conditionals = conditionals.filter(RelayConditional.activated == True) if self.is_on(relay_id): conditionals = conditionals.filter(RelayConditional.if_action == 'on') conditionals = conditionals.filter(RelayConditional.if_duration == on_duration) else: conditionals = conditionals.filter(RelayConditional.if_action == 'off') for each_conditional in conditionals.all(): message = None if (each_conditional.do_relay_id or each_conditional.execute_command or each_conditional.email_notify): now = time.time() timestamp = datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H-%M-%S') message = "{}\n[Relay Conditional {}] {}\n".format( timestamp, each_conditional.id, each_conditional.name) message += "If relay {} ({}) turns {}, Then:\n".format( each_conditional.if_relay_id, self.relay_name[each_conditional.if_relay_id], each_conditional.if_action) if each_conditional.do_relay_id: message += "Turn relay {} ({}) {}".format( each_conditional.do_relay_id, self.relay_name[each_conditional.do_relay_id], each_conditional.do_action) if each_conditional.do_duration == 0: self.relay_on_off(each_conditional.do_relay_id, each_conditional.do_action) else: message += " for {} seconds".format(each_conditional.do_duration) self.relay_on_off(each_conditional.do_relay_id, each_conditional.do_action, each_conditional.do_duration) message += ".\n" if each_conditional.execute_command: # Execute command as user mycodo message += "Execute: '{}'. ".format( each_conditional.execute_command) cmd_out, cmd_err, cmd_status = cmd_output( self.cond_execute_command[cond_id]) message += "Status: {}. ".format(cmd_status) if each_conditional.email_notify: if (self.email_count >= self.smtp_max_count and time.time() < self.smtp_wait_time): self.allowed_to_send_notice = False else: if time.time() > self.smtp_wait_time: self.email_count = 0 self.smtp_wait_time = time.time() + 3600 self.allowed_to_send_notice = True self.email_count += 1 if self.allowed_to_send_notice: message += "Notify {}.".format( each_conditional.email_notify) with session_scope(MYCODO_DB_PATH) as new_session: smtp = new_session.query(SMTP).first() send_email(self.logger, smtp.host, smtp.ssl, smtp.port, smtp.user, smtp.passw, smtp.email_from, each_conditional.email_notify, message) else: self.logger.debug("[Relay Conditional {}] True: " "{:.0f} seconds left to be " "allowed to email again.".format( each_cond.id, (self.smtp_wait_time-time.time()))) if each_conditional.flash_lcd: start_flashing = threading.Thread( target=self.control.flash_lcd, args=(each_conditional.flash_lcd, 1,)) start_flashing.start() if (each_conditional.do_relay_id or each_conditional.execute_command or each_conditional.email_notify): self.logger.debug("{}".format(message))
def check_conditionals(self, output_id, state=None, on_duration=None, duty_cycle=None): conditionals = db_retrieve_table_daemon(Conditional) conditionals = conditionals.filter( Conditional.if_relay_id == output_id) conditionals = conditionals.filter( Conditional.is_activated == True) if self.is_on(output_id): conditionals = conditionals.filter( or_(Conditional.if_relay_state == 'on', Conditional.if_relay_state == 'on_any')) on_with_duration = and_( Conditional.if_relay_state == 'on', Conditional.if_relay_duration == on_duration) conditionals = conditionals.filter( or_(Conditional.if_relay_state == 'on_any', on_with_duration)) else: conditionals = conditionals.filter( Conditional.if_relay_state == 'off') for each_conditional in conditionals.all(): conditional_actions = db_retrieve_table_daemon(ConditionalActions) conditional_actions = conditional_actions.filter( ConditionalActions.conditional_id == each_conditional.id).all() for each_cond_action in conditional_actions: now = time.time() timestamp = datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H-%M-%S') message = u"{ts}\n[Output Conditional {id}] {name}\n".format( ts=timestamp, id=each_cond_action.id, name=each_conditional.name) if each_cond_action.do_action == 'relay': if each_cond_action.do_relay_id not in self.output_name: message += u"Error: Invalid output ID {id}.".format( id=each_cond_action.do_relay_id) else: message += u"If output {id} ({name}) turns {state}, Then ".format( id=each_conditional.if_relay_id, name=self.output_name[each_conditional.if_relay_id], state=each_conditional.if_relay_state) message += u"turn output {id} ({name}) {state}".format( id=each_cond_action.do_relay_id, name=self.output_name[each_cond_action.do_relay_id], state=each_cond_action.do_relay_state) if each_cond_action.do_relay_duration == 0: self.output_on_off(each_cond_action.do_relay_id, each_cond_action.do_relay_state) else: message += u" for {dur} seconds".format( dur=each_cond_action.do_relay_duration) self.output_on_off(each_cond_action.do_relay_id, each_cond_action.do_relay_state, duration=each_cond_action.do_relay_duration) message += ".\n" elif each_cond_action.do_action == 'command': # Execute command as user mycodo message += u"Execute: '{}'. ".format( each_cond_action.do_action_string) # Check command for variables to replace with values command_str = each_cond_action.do_action_string command_str = command_str.replace( "((output_pin))", str(self.output_pin[output_id])) command_str = command_str.replace( "((output_action))", str(state)) command_str = command_str.replace( "((output_duration))", str(on_duration)) command_str = command_str.replace( "((output_pwm))", str(duty_cycle)) _, _, cmd_status = cmd_output(command_str) message += u"Status: {}. ".format(cmd_status) elif each_cond_action.do_action == 'email': if (self.email_count >= self.smtp_max_count and time.time() < self.smtp_wait_time): self.allowed_to_send_notice = False else: if time.time() > self.smtp_wait_time: self.email_count = 0 self.smtp_wait_time = time.time() + 3600 self.allowed_to_send_notice = True self.email_count += 1 if self.allowed_to_send_notice: message += u"Notify {}.".format( each_cond_action.email_notify) smtp = db_retrieve_table_daemon(SMTP, entry='first') send_email( smtp.host, smtp.ssl, smtp.port, smtp.user, smtp.passw, smtp.email_from, each_cond_action.do_action_string, message) else: self.logger.debug( "[Output Conditional {}] True: {:.0f} seconds " "left to be allowed to email again.".format( each_conditional.id, self.smtp_wait_time-time.time())) elif each_cond_action.do_action == 'flash_lcd': start_flashing = threading.Thread( target=self.control.flash_lcd, args=(each_cond_action.do_lcd_id, 1,)) start_flashing.start() # TODO: Implement photo/video actions for output conditionals elif each_cond_action.do_action == 'photo': self.logger.error("Photo action not currently implemented") elif each_cond_action.do_action == 'video': self.logger.error("Video action not currently implemented") self.logger.debug(u"{}".format(message))
def check_conditionals(self, relay_id, on_duration): conditionals = db_retrieve_table_daemon(Conditional) conditionals = conditionals.filter( Conditional.if_relay_id == relay_id) conditionals = conditionals.filter( Conditional.is_activated == True) if self.is_on(relay_id): conditionals = conditionals.filter( Conditional.if_relay_state == 'on') conditionals = conditionals.filter( Conditional.if_relay_duration == on_duration) else: conditionals = conditionals.filter( Conditional.if_relay_state == 'off') for each_conditional in conditionals.all(): conditional_actions = db_retrieve_table_daemon(ConditionalActions) conditional_actions = conditional_actions.filter( ConditionalActions.conditional_id == each_conditional.id).all() for each_cond_action in conditional_actions: now = time.time() timestamp = datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H-%M-%S') message = u"{ts}\n[Relay Conditional {id}] {name}\n".format( ts=timestamp, id=each_cond_action.id, name=each_conditional.name) if each_cond_action.do_action == 'relay': if each_cond_action.do_relay_id not in self.relay_name: message += u"Error: Invalid relay ID {id}.".format( id=each_cond_action.do_relay_id) else: message += u"If relay {id} ({name}) turns {state}, Then ".format( id=each_conditional.if_relay_id, name=self.relay_name[each_conditional.if_relay_id], state=each_conditional.if_relay_state) message += u"turn relay {id} ({name}) {state}".format( id=each_cond_action.do_relay_id, name=self.relay_name[each_cond_action.do_relay_id], state=each_cond_action.do_relay_state) if each_cond_action.do_relay_duration == 0: self.relay_on_off(each_cond_action.do_relay_id, each_cond_action.do_relay_state) else: message += u" for {dur} seconds".format( dur=each_cond_action.do_relay_duration) self.relay_on_off(each_cond_action.do_relay_id, each_cond_action.do_relay_state, duration=each_cond_action.do_relay_duration) message += ".\n" elif each_cond_action.do_action == 'command': # Execute command as user mycodo message += u"Execute: '{}'. ".format( each_cond_action.do_action_string) _, _, cmd_status = cmd_output( each_cond_action.do_action_string) message += u"Status: {}. ".format(cmd_status) elif each_cond_action.do_action == 'email': if (self.email_count >= self.smtp_max_count and time.time() < self.smtp_wait_time): self.allowed_to_send_notice = False else: if time.time() > self.smtp_wait_time: self.email_count = 0 self.smtp_wait_time = time.time() + 3600 self.allowed_to_send_notice = True self.email_count += 1 if self.allowed_to_send_notice: message += u"Notify {}.".format( each_cond_action.email_notify) smtp = db_retrieve_table_daemon(SMTP, entry='first') send_email( smtp.host, smtp.ssl, smtp.port, smtp.user, smtp.passw, smtp.email_from, each_cond_action.do_action_string, message) else: self.logger.debug( "[Relay Conditional {}] True: {:.0f} seconds " "left to be allowed to email again.".format( each_conditional.id, self.smtp_wait_time-time.time())) elif each_cond_action.do_action == 'flash_lcd': start_flashing = threading.Thread( target=self.control.flash_lcd, args=(each_cond_action.do_lcd_id, 1,)) start_flashing.start() # TODO: Implement photo/video actions for relay conditionals elif each_cond_action.do_action == 'photo': pass elif each_cond_action.do_action == 'video': pass self.logger.debug(u"{}".format(message))
def check_conditionals(self, cond_id): """ Check if any sensor conditional statements are activated and execute their actions if the conditional is true. For example, if measured temperature is above 30C, notify [email protected] :rtype: None :param cond_id: ID of conditional to check :type cond_id: str """ logger_cond = logging.getLogger( "mycodo.SensorCond-{id}".format(id=cond_id)) attachment_file = False attachment_type = False message = "" conditional = False if self.cond_edge_detected[cond_id]: conditional = 'edge' elif self.cond_direction[cond_id]: conditional = 'measurement' now = time.time() timestamp = datetime.datetime.fromtimestamp(now).strftime( '%Y-%m-%d %H-%M-%S') if conditional == 'measurement': last_measurement = self.get_last_measurement( self.cond_measurement_type[cond_id]) if (last_measurement and ((self.cond_direction[cond_id] == 'above' and last_measurement > self.cond_setpoint[cond_id]) or (self.cond_direction[cond_id] == 'below' and last_measurement < self.cond_setpoint[cond_id]))): message = "{}\n[Sensor Conditional {}] {}\n{} {} ".format( timestamp, cond_id, self.cond_name[cond_id], self.cond_measurement_type[cond_id], last_measurement) if self.cond_direction[cond_id] == 'above': message += ">" elif self.cond_direction[cond_id] == 'below': message += "<" message += " {} setpoint.".format(self.cond_setpoint[cond_id]) else: logger_cond.debug("Last measurement not found") return 1 elif conditional == 'edge': if self.cond_edge_select[cond_id] == 'edge': message = "{}\n[Sensor Conditional {}] {}. {} Edge Detected.".format( timestamp, cond_id, self.cond_name[cond_id], self.cond_edge_detected) elif self.cond_edge_select[cond_id] == 'state': if GPIO.input(int( self.location)) == self.cond_gpio_state[cond_id]: message = "{}\n[Sensor Conditional {}] {}. {} GPIO State Detected.".format( timestamp, cond_id, self.cond_name[cond_id], self.cond_gpio_state[cond_id]) else: return 0 if (self.cond_relay_id[cond_id] and self.cond_relay_state[cond_id] in ['on', 'off']): message += "\nTurning relay {} {}".format( self.cond_relay_id[cond_id], self.cond_relay_state[cond_id]) if (self.cond_relay_state[cond_id] == 'on' and self.cond_relay_on_duration[cond_id]): message += " for {} seconds".format( self.cond_relay_on_duration[cond_id]) message += ". " relay_on_off = threading.Thread( target=self.control.relay_on_off, args=( self.cond_relay_id[cond_id], self.cond_relay_state[cond_id], self.cond_relay_on_duration[cond_id], )) relay_on_off.start() # Execute command in shell if self.cond_execute_command[cond_id]: message += "\nExecute '{}'. ".format( self.cond_execute_command[cond_id]) _, _, cmd_status = cmd_output(self.cond_execute_command[cond_id]) message += "Status: {}. ".format(cmd_status) if self.cond_camera_record[cond_id] in ['photo', 'photoemail']: camera_still = db_retrieve_table(MYCODO_DB_PATH, CameraStill, entry='first') attachment_file = camera_record('photo', camera_still) elif self.cond_camera_record[cond_id] in ['video', 'videoemail']: camera_stream = db_retrieve_table(MYCODO_DB_PATH, CameraStream, entry='first') attachment_file = camera_record('video', camera_stream, duration_sec=5) if self.cond_email_notify[cond_id]: if (self.email_count >= self.smtp_max_count and time.time() < self.smtp_wait_timer[cond_id]): self.allowed_to_send_notice = False else: if time.time() > self.smtp_wait_timer[cond_id]: self.email_count = 0 self.smtp_wait_timer[cond_id] = time.time() + 3600 self.allowed_to_send_notice = True self.email_count += 1 # If the emails per hour limit has not been exceeded if self.allowed_to_send_notice: message += "\nNotify {}.".format( self.cond_email_notify[cond_id]) # attachment_type != False indicates to # attach a photo or video if self.cond_camera_record[cond_id] == 'photoemail': message += "\nPhoto attached." attachment_type = 'still' elif self.cond_camera_record[cond_id] == 'videoemail': message += "\nVideo attached." attachment_type = 'video' smtp = db_retrieve_table(MYCODO_DB_PATH, SMTP, entry='first') send_email(smtp.host, smtp.ssl, smtp.port, smtp.user, smtp.passw, smtp.email_from, self.cond_email_notify[cond_id], message, attachment_file, attachment_type) else: logger_cond.debug( "{:.0f} seconds left to be allowed to email " "again.".format(self.smtp_wait_timer[cond_id] - time.time())) if self.cond_flash_lcd[cond_id]: start_flashing = threading.Thread(target=self.control.flash_lcd, args=( self.cond_flash_lcd[cond_id], 1, )) start_flashing.start() logger_cond.debug(message)
def check_conditionals(self, cond_id): """ Check if any sensor conditional statements are activated and execute their actions if the conditional is true. For example, if measured temperature is above 30C, notify [email protected] :rtype: None :param cond_id: ID of conditional to check :type cond_id: str """ logger_cond = logging.getLogger( "mycodo.sensor_cond_{id}".format(id=cond_id)) attachment_file = False attachment_type = False cond = db_retrieve_table_daemon(Conditional, device_id=cond_id, entry='first') message = u"[Sensor Conditional: {name} ({id})]".format(name=cond.name, id=cond_id) if cond.if_sensor_direction: last_measurement = self.get_last_measurement( cond.if_sensor_measurement) if (last_measurement and ((cond.if_sensor_direction == 'above' and last_measurement > cond.if_sensor_setpoint) or (cond.if_sensor_direction == 'below' and last_measurement < cond.if_sensor_setpoint))): message += u" {meas}: {value} ".format( meas=cond.if_sensor_measurement, value=last_measurement) if cond.if_sensor_direction == 'above': message += "(>" elif cond.if_sensor_direction == 'below': message += "(<" message += u" {sp} set value).".format( sp=cond.if_sensor_setpoint) else: logger_cond.debug("Last measurement not found") return 1 elif cond.if_sensor_edge_detected: if cond.if_sensor_edge_select == 'edge': message += u" {edge} Edge Detected.".format( edge=cond.if_sensor_edge_detected) elif cond.if_sensor_edge_select == 'state': if GPIO.input(int(self.location)) == cond.if_sensor_gpio_state: message += u" {state} GPIO State Detected.".format( state=cond.if_sensor_gpio_state) else: return 0 cond_actions = db_retrieve_table_daemon(ConditionalActions) cond_actions = cond_actions.filter( ConditionalActions.conditional_id == cond_id).all() for cond_action in cond_actions: message += u" Conditional Action ({id}): {do_action}.".format( id=cond_action.id, do_action=cond_action.do_action) # Actuate relay if (cond_action.do_relay_id and cond_action.do_relay_state in ['on', 'off']): message += u" Turn relay {id} {state}".format( id=cond_action.do_relay_id, state=cond_action.do_relay_state) if (cond_action.do_relay_state == 'on' and cond_action.do_relay_duration): message += u" for {sec} seconds".format( sec=cond_action.do_relay_duration) message += "." relay_on_off = threading.Thread( target=self.control.relay_on_off, args=( cond_action.do_relay_id, cond_action.do_relay_state, cond_action.do_relay_duration, )) relay_on_off.start() # Execute command in shell elif cond_action.do_action == 'command': message += u" Execute '{com}' ".format( com=cond_action.do_action_string) _, _, cmd_status = cmd_output(cond_action.do_action_string) message += u"(Status: {stat}).".format(stat=cmd_status) # Capture photo elif cond_action.do_action in ['photo', 'photo_email']: message += u" Capturing photo with camera ({id}).".format( id=cond_action.do_camera_id) camera_still = db_retrieve_table_daemon( Camera, device_id=cond_action.do_camera_id) attachment_file = camera_record('photo', camera_still) # Capture video elif cond_action.do_action in ['video', 'video_email']: message += u" Capturing video with camera ({id}).".format( id=cond_action.do_camera_id) camera_stream = db_retrieve_table_daemon( Camera, device_id=cond_action.do_camera_id) attachment_file = camera_record( 'video', camera_stream, duration_sec=cond_action.do_camera_duration) # Activate PID controller elif cond_action.do_action == 'activate_pid': message += u" Activate PID ({id}).".format( id=cond_action.do_pid_id) pid = db_retrieve_table_daemon(PID, device_id=cond_action.do_pid_id, entry='first') if pid.is_activated: message += u" Notice: PID is already active!" else: activate_pid = threading.Thread( target=self.control.controller_activate, args=( 'PID', cond_action.do_pid_id, )) activate_pid.start() # Deactivate PID controller elif cond_action.do_action == 'deactivate_pid': message += u" Deactivate PID ({id}).".format( id=cond_action.do_pid_id) pid = db_retrieve_table_daemon(PID, device_id=cond_action.do_pid_id, entry='first') if not pid.is_activated: message += u" Notice: PID is already inactive!" else: deactivate_pid = threading.Thread( target=self.control.controller_deactivate, args=( 'PID', cond_action.do_pid_id, )) deactivate_pid.start() elif cond_action.do_action in [ 'email', 'photo_email', 'video_email' ]: if (self.email_count >= self.smtp_max_count and time.time() < self.smtp_wait_timer[cond_id]): self.allowed_to_send_notice = False else: if time.time() > self.smtp_wait_timer[cond_id]: self.email_count = 0 self.smtp_wait_timer[cond_id] = time.time() + 3600 self.allowed_to_send_notice = True self.email_count += 1 # If the emails per hour limit has not been exceeded if self.allowed_to_send_notice: message += u" Notify {email}.".format( email=cond_action.do_action_string) # attachment_type != False indicates to # attach a photo or video if cond_action.do_action == 'photo_email': message += u" Photo attached to email." attachment_type = 'still' elif cond_action.do_action == 'video_email': message += u" Video attached to email." attachment_type = 'video' smtp = db_retrieve_table_daemon(SMTP, entry='first') send_email(smtp.host, smtp.ssl, smtp.port, smtp.user, smtp.passw, smtp.email_from, cond_action.do_action_string, message, attachment_file, attachment_type) else: logger_cond.debug( "Wait {sec:.0f} seconds to email again.".format( sec=self.smtp_wait_timer[cond_id] - time.time())) elif cond_action.do_action == 'flash_lcd': message += u" Flashing LCD ({id}).".format( id=cond_action.do_lcd_id) start_flashing = threading.Thread( target=self.control.flash_lcd, args=( cond_action.do_lcd_id, 1, )) start_flashing.start() logger_cond.debug(message)
def checkConditionals(self, relay_id, on_duration): with session_scope(MYCODO_DB_PATH) as new_session: conditionals = new_session.query(RelayConditional) new_session.expunge_all() new_session.close() conditionals = conditionals.filter( RelayConditional.if_relay_id == relay_id) conditionals = conditionals.filter(RelayConditional.activated == True) if self.is_on(relay_id): conditionals = conditionals.filter( RelayConditional.if_action == 'on') conditionals = conditionals.filter( RelayConditional.if_duration == on_duration) else: conditionals = conditionals.filter( RelayConditional.if_action == 'off') for each_conditional in conditionals.all(): message = None if (each_conditional.do_relay_id or each_conditional.execute_command or each_conditional.email_notify): now = time.time() timestamp = datetime.datetime.fromtimestamp(now).strftime( '%Y-%m-%d %H-%M-%S') message = "{}\n[Relay Conditional {}] {}\n".format( timestamp, each_conditional.id, each_conditional.name) message += "If relay {} ({}) turns {}, Then:\n".format( each_conditional.if_relay_id, self.relay_name[each_conditional.if_relay_id], each_conditional.if_action) if each_conditional.do_relay_id: message += "Turn relay {} ({}) {}".format( each_conditional.do_relay_id, self.relay_name[each_conditional.do_relay_id], each_conditional.do_action) if each_conditional.do_duration == 0: self.relay_on_off(each_conditional.do_relay_id, each_conditional.do_action) else: message += " for {} seconds".format( each_conditional.do_duration) self.relay_on_off(each_conditional.do_relay_id, each_conditional.do_action, each_conditional.do_duration) message += ".\n" if each_conditional.execute_command: # Execute command as user mycodo message += "Execute: '{}'. ".format( each_conditional.execute_command) cmd_out, cmd_err, cmd_status = cmd_output( self.cond_execute_command[cond_id]) message += "Status: {}. ".format(cmd_status) if each_conditional.email_notify: if (self.email_count >= self.smtp_max_count and time.time() < self.smtp_wait_time): self.allowed_to_send_notice = False else: if time.time() > self.smtp_wait_time: self.email_count = 0 self.smtp_wait_time = time.time() + 3600 self.allowed_to_send_notice = True self.email_count += 1 if self.allowed_to_send_notice: message += "Notify {}.".format( each_conditional.email_notify) with session_scope(MYCODO_DB_PATH) as new_session: smtp = new_session.query(SMTP).first() send_email(self.logger, smtp.host, smtp.ssl, smtp.port, smtp.user, smtp.passw, smtp.email_from, each_conditional.email_notify, message) else: self.logger.debug("[Relay Conditional {}] True: " "{:.0f} seconds left to be " "allowed to email again.".format( each_cond.id, (self.smtp_wait_time - time.time()))) if each_conditional.flash_lcd: start_flashing = threading.Thread( target=self.control.flash_lcd, args=( each_conditional.flash_lcd, 1, )) start_flashing.start() if (each_conditional.do_relay_id or each_conditional.execute_command or each_conditional.email_notify): self.logger.debug("{}".format(message))
def checkConditionals(self, cond_id): """ Check if any sensor conditional statements are activated and execute their actions if the conditional is true. For example, if measured temperature is above 30C, notify [email protected] :rtype: None :param each_cond: Object of SQL table entries for a specific column :type each_cond: sqlalchemy object """ attachment_file = False attachment_type = False message = "" conditional = False if self.cond_edge_detected[cond_id]: conditional = 'edge' elif self.cond_direction[cond_id]: conditional = 'measurement' now = time.time() timestamp = datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H-%M-%S') if conditional == 'measurement': last_measurement = self.getLastMeasurement(self.cond_measurement_type[cond_id]) if (last_measurement and ((self.cond_direction[cond_id] == 'above' and last_measurement > self.cond_setpoint[cond_id]) or (self.cond_direction[cond_id] == 'below' and last_measurement < self.cond_setpoint[cond_id]))): message = "{}\n[Sensor Conditional {}] {}\n{} {} ".format( timestamp, cond_id, self.cond_name[cond_id], self.cond_measurement_type[cond_id], last_measurement) if self.cond_direction[cond_id] == 'above': message += ">" elif self.cond_direction[cond_id] == 'below': message += "<" message += " {} setpoint.".format(self.cond_setpoint[cond_id]) else: self.logger.debug("[Sensor Conditional {}] Last measurement " "not found".format(cond_id)) return 1 elif conditional == 'edge': if self.cond_edge_select[cond_id] == 'edge': message = "{}\n[Sensor Conditional {}] {}. {} Edge Detected.".format( timestamp, cond_id, self.cond_name[cond_id], self.cond_edge_detected) elif self.cond_edge_select[cond_id] == 'state': if GPIO.input(int(self.location)) == self.cond_gpio_state[cond_id]: message = "{}\n[Sensor Conditional {}] {}. {} GPIO State Detected.".format( timestamp, cond_id, self.cond_name[cond_id], self.cond_gpio_state[cond_id]) else: return 0 if (self.cond_relay_id[cond_id] and self.cond_relay_state[cond_id] in ['on', 'off']): message += "\nTurning relay {} {}".format( self.cond_relay_id[cond_id], self.cond_relay_state[cond_id]) if (self.cond_relay_state[cond_id] == 'on' and self.cond_relay_on_duration[cond_id]): message += " for {} seconds".format(self.cond_relay_on_duration[cond_id]) message += ". " relay_on_off = threading.Thread( target=self.control.relay_on_off, args=(self.cond_relay_id[cond_id], self.cond_relay_state[cond_id], self.cond_relay_on_duration[cond_id],)) relay_on_off.start() # Execute command in shell if self.cond_execute_command[cond_id]: message += "\nExecute '{}'. ".format( self.cond_execute_command[cond_id]) cmd_out, cmd_err, cmd_status = cmd_output(self.cond_execute_command[cond_id]) message += "Status: {}. ".format(cmd_status) if self.cond_camera_record[cond_id] in ['photo', 'photoemail']: attachment_file = camera_record(INSTALL_DIRECTORY, 'photo') elif self.cond_camera_record[cond_id] in ['video', 'videoemail']: attachment_file = camera_record(INSTALL_DIRECTORY, 'video', duration_sec=5) if self.cond_email_notify[cond_id]: if (self.email_count >= self.smtp_max_count and time.time() < self.smtp_wait_timer[cond_id]): self.allowed_to_send_notice = False else: if time.time() > self.smtp_wait_timer[cond_id]: self.email_count = 0 self.smtp_wait_timer[cond_id] = time.time()+3600 self.allowed_to_send_notice = True self.email_count += 1 # If the emails per hour limit has not been exceeded if self.allowed_to_send_notice: message += "\nNotify {}.".format( self.cond_email_notify[cond_id]) # attachment_type != False indicates to # attach a photo or video if self.cond_camera_record[cond_id] == 'photoemail': message += "\nPhoto attached." attachment_type = 'still' elif self.cond_camera_record[cond_id] == 'videoemail': message += "\nVideo attached." attachment_type = 'video' with session_scope(MYCODO_DB_PATH) as new_session: smtp = new_session.query(SMTP).first() send_email(self.logger, smtp.host, smtp.ssl, smtp.port, smtp.user, smtp.passw, smtp.email_from, self.cond_email_notify[cond_id], message, attachment_file, attachment_type) else: self.logger.debug("[Sensor Conditional {}] " "{:.0f} seconds left to be " "allowed to email again.".format( cond_id, (self.smtp_wait_timer[cond_id]-time.time()))) if self.cond_flash_lcd[cond_id]: start_flashing = threading.Thread( target=self.control.flash_lcd, args=(self.cond_flash_lcd[cond_id], 1,)) start_flashing.start() self.logger.debug(message)