def setup_method(self, method_id): """ Initialize method variables to start running a method """ self.setpoint_tracking_id = '' method = load_method_handler(method_id, self.logger) this_controller = db_retrieve_table_daemon(PID, unique_id=self.unique_id) self.method_type = method.method_type if parse_db_time(this_controller.method_start_time) is None: self.method_start_time = datetime.datetime.now() self.method_end_time = method.determine_end_time( self.method_start_time) self.logger.info("Starting method {} {}".format( self.method_start_time, self.method_end_time)) with session_scope(MYCODO_DB_PATH) as db_session: this_controller = db_session.query(PID) this_controller = this_controller.filter( PID.unique_id == self.unique_id).first() this_controller.method_start_time = self.method_start_time this_controller.method_end_time = self.method_end_time db_session.commit() else: # already running, potentially the daemon has been restarted self.method_start_time = this_controller.method_start_time self.method_end_time = this_controller.method_end_time self.setpoint_tracking_id = method_id self.logger.debug( "Method enabled: {id}".format(id=self.setpoint_tracking_id))
def start_method(self, method_id): """Instruct a method to start running.""" if method_id: this_controller = db_retrieve_table_daemon( Trigger, unique_id=self.unique_id) method = load_method_handler(method_id, self.logger) if parse_db_time(this_controller.method_start_time) is None: self.method_start_time = datetime.datetime.now() self.method_end_time = method.determine_end_time( self.method_start_time) self.logger.info( f"Starting method {self.method_start_time} {self.method_end_time}" ) with session_scope(MYCODO_DB_PATH) as db_session: this_controller = db_session.query(Trigger) this_controller = this_controller.filter( Trigger.unique_id == self.unique_id).first() this_controller.method_start_time = self.method_start_time this_controller.method_end_time = self.method_end_time db_session.commit() else: # already running, potentially the daemon has been restarted self.method_start_time = this_controller.method_start_time self.method_end_time = this_controller.method_end_time
def get_method_output(self, method_id): """ Get output variable from method """ this_controller = db_retrieve_table_daemon( Trigger, unique_id=self.unique_id) if this_controller.method_start_time is None: return now = datetime.datetime.now() method = load_method_handler(method_id, self.logger) setpoint, ended = method.calculate_setpoint(now, this_controller.method_start_time) if setpoint is not None: if setpoint > 100: setpoint = 100 elif setpoint < 0: setpoint = 0 return setpoint, ended
def check_pid(self): """ Get measurement and apply to PID controller """ # If PID is active, retrieve measurement and update # the control variable. # A PID on hold will sustain the current output and # not update the control variable. if self.is_activated and (not self.is_paused or not self.is_held): self.get_last_measurement_pid() if self.last_measurement_success: if self.setpoint_tracking_type == 'method' and self.setpoint_tracking_id != '': # Update setpoint using a method this_pid = db_retrieve_table_daemon( PID, unique_id=self.unique_id) now = datetime.datetime.now() method = load_method_handler(self.setpoint_tracking_id, self.logger) new_setpoint, ended = method.calculate_setpoint( now, this_pid.method_start_time) self.logger.debug("Method {} {} {} {}".format( self.setpoint_tracking_id, method, now, this_pid.method_start_time)) if ended: # point in time is out of method range with session_scope(MYCODO_DB_PATH) as db_session: # Overwrite this_controller with committable connection this_pid = db_session.query(PID).filter( PID.unique_id == self.unique_id).first() self.logger.debug("Ended") # Duration method has ended, reset method_start_time locally and in DB this_pid.method_start_time = None this_pid.method_end_time = None this_pid.is_activated = False db_session.commit() self.is_activated = False self.stop_controller() db_session.commit() if new_setpoint is not None: self.logger.debug("New setpoint = {} {}".format( new_setpoint, ended)) self.PID_Controller.setpoint = new_setpoint else: self.logger.debug( "New setpoint = default {} {}".format( self.setpoint, ended)) self.PID_Controller.setpoint = self.setpoint if self.setpoint_tracking_type == 'input-math' and self.setpoint_tracking_id != '': # Update setpoint using an Input or Math device_id = self.setpoint_tracking_id.split(',')[0] measurement_id = self.setpoint_tracking_id.split(',')[1] measurement = get_measurement(measurement_id) if not measurement: return False, None conversion = db_retrieve_table_daemon( Conversion, unique_id=measurement.conversion_id) channel, unit, measurement = return_measurement_info( measurement, conversion) last_measurement = read_last_influxdb( device_id, unit, channel, measure=measurement, duration_sec=self.setpoint_tracking_max_age) if last_measurement[1] is not None: self.PID_Controller.setpoint = last_measurement[1] else: self.logger.debug( "Could not find measurement for Setpoint " "Tracking. Max Age of {} exceeded for measuring " "device ID {} (measurement {})".format( self.setpoint_tracking_max_age, device_id, measurement_id)) self.PID_Controller.setpoint = None # Calculate new control variable (output) from PID Controller self.PID_Controller.update_pid_output(self.last_measurement) self.write_pid_values() # Write variables to database # Is PID in a state that allows manipulation of outputs if (self.is_activated and self.PID_Controller.setpoint is not None and (not self.is_paused or self.is_held)): self.manipulate_output()