#!/usr/bin/env python3 import sys ##import utils.Logger as L #import threading #, multiprocessing, os #import time #from django.db import transaction #from common.models import Command import os pwd = os.environ['PROJECT_ROOT_PATH'] if pwd not in sys.path: sys.path.append(pwd) from src.core.pyros_django.majordome.agent.Agent import Agent, build_agent, log, parse_args # PM 20190416 recycle code from src.core.pyros_django.devices.PLC import PLCController from src.core.pyros_django.env_monitor.plc_checker import PlcChecker from common.models import * from env_monitor.models import * from config.pyros.config_pyros import ConfigPyros ##log = L.setupLogger("AgentXTaskLogger", "AgentX") class AgentM(Agent): # FOR TEST ONLY # Run this agent in simulator mode TEST_MODE = False # Run the assertion tests at the end TEST_WITH_FINAL_TEST = True TEST_MAX_DURATION_SEC = None #TEST_MAX_DURATION_SEC = 120 ##_path_data = 'config' _path_data = 'config/old_config' # PM 20190416 recycle code plcController = PLCController() print ("AGENT ENV: config PLC is (ip={}, port={})".format(plcController.ip, plcController.port)) plc_checker = PlcChecker() log.debug("PLC instanciated") time_history_minutes = 4 ''' # Who should I send commands to ? #TEST_COMMANDS_DEST = "myself" TEST_COMMANDS_DEST = "AgentA" # Scenario to be executed TEST_COMMANDS_LIST = [ "go_active", "go_idle", "go_active", "go_idle", "go_active", "go_idle", "exit", ] ''' """ ================================================================= FUNCTIONS RUN INSIDE MAIN THREAD ================================================================= """ # old config # @override #def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True): # def __init__(self, config_filename=None, RUN_IN_THREAD=True): # ##if name is None: name = self.__class__.__name__ # super().__init__(config_filename, RUN_IN_THREAD) # new config (obsconfig) def __init__(self, name:str=None, simulated_computer=None): if name is None: name = self.__class__.__name__ super().__init__(simulated_computer=simulated_computer) PYROS_CONFIG_FILE = os.environ.get("pyros_config_file") if PYROS_CONFIG_FILE: CONFIG_PYROS = ConfigPyros(PYROS_CONFIG_FILE).pyros_config self.time_history_minutes = int(CONFIG_PYROS.get("ENV").get("time_history")) log.info(f"time_history_minutes set to {int(self.time_history_minutes)}") # Read device config to get all monitoring_names and their info (qualities) # make function to read it # @override def _init(self): super()._init() log.debug("end init()") # --- Set the mode according the startmode value ##agent_alias = self.__class__.__name__ ##self.set_mode_from_config(agent_alias) ''' # @override def load_config(self): super().load_config() ''' ''' # @override def update_survey(self): super().update_survey() ''' ''' # @override def get_next_command(self): return super().get_next_command() ''' # @override def do_log(self): super().do_log() # @override # previous name of function : routine_process # Note : in Agent.py, routine_process_body seems to be the main function of routine of the agent # We need to override routine_process_body and not routine_process def _routine_process_iter_end_body(self): log.info("in routine process iter end body") log.debug("in routine_process_body()") #status_plc = self.plcController.getStatus() print("Save weather") self.saveWeather() def parseNewStatus(self,status_plc): # """ PM 20181009 parse new status for config # Find return string "plc_status" positin within status_plc if status_plc.find('PLC_STATUS') >= 0: self.plc_checker.chk_config(status_plc) return True return False def saveWeather(self): print("saving weather") datetimenow = datetime.now(timezone.utc) # get sensor config to read quality and take the device with the best quality value monitoring_devices = self.get_config().get_monitoring_devices() devices = self.get_config().get_devices() sensors_data_with_qualities = {} #for sensor_data in Sensors_data_last_value.objects.all(): for device in monitoring_devices: output_data = self.get_config().get_output_data_device(device) for sensor in output_data.keys(): for key in output_data[sensor]: try: sensor_data = Sensors_data_last_value.objects.get(key=key) except Sensors_data_last_value.DoesNotExist: # No value found pass quality = output_data[sensor][key].get("quality") monitoring_name = output_data[sensor][key].get("monitoring_name") label = output_data[sensor][key].get("label") if sensors_data_with_qualities.get(monitoring_name) is None: sensors_data_with_qualities[monitoring_name] = { key:{ "quality":float(quality), "label":label } } else: sensors_data_with_qualities[monitoring_name][key] = { "quality":float(quality), "label":label } for monitoring_name in sensors_data_with_qualities.keys(): max_quality = 0 associated_key = "" for sensor_data in sensors_data_with_qualities[monitoring_name].keys(): # make sorted list by quality & device valid -> device_valid = error_code key = sensor_data quality = sensors_data_with_qualities[monitoring_name][sensor_data]["quality"] # Also use error_code if quality >= max_quality: if Sensors_data_last_value.objects.filter(key=key).exists(): max_quality = quality associated_key = key label = sensors_data_with_qualities[monitoring_name][sensor_data]["label"] # Data doesn't exist in database ? if associated_key != "": do_update = True try: env_data = Env_data.objects.get(monitoring_name=monitoring_name) except Env_data.DoesNotExist: # it's a creation do_update = False env_data = Env_data.objects.create( monitoring_name=monitoring_name, value = Sensors_data_last_value.objects.get(key=associated_key).value, label=label ) if do_update: # it's an update env_data.value = Sensors_data_last_value.objects.get(key=associated_key).value env_data.monitoring_name = monitoring_name env_data.label = label env_data.save() self.setGlobalStatus() latest_entry_of_history = Env_data_hist.objects.all().order_by("-created").first() if latest_entry_of_history == None: for env_data in Env_data.objects.all(): env_data_hist = Env_data_hist.objects.create( monitoring_name=env_data.monitoring_name, value=env_data.value, label=env_data.label ) else: time_between_history_and_latest_entry = datetimenow - latest_entry_of_history.created sec_diff = time_between_history_and_latest_entry.total_seconds() / 60 # if diff between last entry of history and current time if greather than x then we save a new entry in history if int(sec_diff) > self.time_history_minutes: for env_data in Env_data.objects.all(): env_data_hist = Env_data_hist.objects.create( monitoring_name=env_data.monitoring_name, value=env_data.value, label=env_data.label ) log.info("End of agentM saving weather") def setGlobalStatus(self): global_status = "" # Old monitoring # if self.doors and self.doors.find("open") != -1: # self.global_status += "DOOR_OPEN " # if self.lights and self.lights == "on": # self.global_status += "LIGHTS_ON " # if self.humidity and float(self.humidity) > 80: # self.global_status += "HUMIDITY_TOO_HIGH " # New monitoring if Env_data.objects.filter(monitoring_name="Temp_ext").exists(): if float(Env_data.objects.get(monitoring_name="Temp_ext").value) > 40: global_status += "TOO_HOT " if Env_data.objects.filter(monitoring_name="Rain").exists(): if float(Env_data.objects.get(monitoring_name="Rain").value) > 0: global_status += "RAINING " if Env_data.objects.filter(monitoring_name="Wind_speed").exists(): if float(Env_data.objects.get(monitoring_name="Wind_speed").value) > 5: global_status += "WINDY " if Env_data.objects.filter(monitoring_name="Humidity_ext").exists(): if float(Env_data.objects.get(monitoring_name="Humidity_ext").value) > 80: global_status += "HUMIDITY_TOO_HIGH " if global_status == "": global_status = "OK" do_update = True try: global_status_db = Env_data.objects.get(monitoring_name="global_status") except Env_data.DoesNotExist: do_update = False global_status_db = Env_data.objects.create(monitoring_name="global_status",value=global_status,label="Global status") if do_update: global_status_db.monitoring_name = "global_status" global_status_db.label = "Global status" global_status_db.value = global_status global_status_db.save() def isInsideMonitoring(self,key): if key in ("Power_input","Roof_state"): return True else: return False # @override def thread_exec_specific_cmd_main(self): # This is optional self.thread_set_total_steps_number(5) # HERE, write your own scenario # scenario OK self.thread_exec_specific_cmd_step(1, self.cmd_step1, 1) self.thread_exec_specific_cmd_step(2, self.cmd_step2, 3) self.thread_exec_specific_cmd_step(3, self.cmd_step1, 5) self.thread_exec_specific_cmd_step(4, self.cmd_step3, 10) self.thread_exec_specific_cmd_step(5, self.cmd_step1, 4) # ... as many as you need """ autre scenario self.thread_exec_specific_cmd_step(1, self.cmd_step1, 1) self.thread_exec_specific_cmd_step(2, self.cmd_step2, 2) self.thread_exec_specific_cmd_step(3, self.cmd_step1, 2) self.thread_exec_specific_cmd_step(4, self.cmd_step3, 2) self.thread_exec_specific_cmd_step(5, self.cmd_step1, 3) """ ''' # @override def exec_specific_cmd_end(self, cmd:Command, from_thread=True): super().exec_specific_cmd_end(cmd, from_thread) ''' if __name__ == "__main__": # with thread RUN_IN_THREAD=True # with process #RUN_IN_THREAD=False args = parse_args(sys.argv[1:]) agent = build_agent(AgentM,param_constr=args) ''' TEST_MODE, configfile = extract_parameters() agent = AgentM("AgentM", configfile, RUN_IN_THREAD) agent.setSimulatorMode(TEST_MODE) ''' print(agent) agent.run()