Commit 514e3287b5a145ca753bb7761fc0dfd5b458eb87

Authored by Alexis Koralewski
1 parent 43d8ca44
Exists in dev

Update AgentM (protected attributes/functions)

CHANGELOG
  1 +05-12-2022 (AKo): v0.6.15.1
  2 + - Update AgentM (protected attributes/functions)
  3 +
1 4 02-12-2022 (AKo): v0.6.15.1
2 5 - Fix initial_fixture with new path of models
3 6 - Fix routine_manager tests
... ...
privatedev/plugin/agent/AgentM.py 0 → 100755
... ... @@ -0,0 +1,279 @@
  1 +#!/usr/bin/env python3
  2 +
  3 +import sys
  4 +##import utils.Logger as L
  5 +#import threading #, multiprocessing, os
  6 +#import time
  7 +
  8 +#from django.db import transaction
  9 +#from common.models import Command
  10 +
  11 +import os
  12 +pwd = os.environ['PROJECT_ROOT_PATH']
  13 +if pwd not in sys.path:
  14 + sys.path.append(pwd)
  15 +
  16 +from src.core.pyros_django.agent.Agent import Agent, build_agent, log
  17 +
  18 +# PM 20190416 recycle code
  19 +from src.core.pyros_django.devices.PLC import PLCController
  20 +from src.core.pyros_django.monitoring.plc_checker import PlcChecker
  21 +from common.models import *
  22 +from config.pyros.config_pyros import ConfigPyros
  23 +
  24 +
  25 +
  26 +##log = L.setupLogger("AgentXTaskLogger", "AgentX")
  27 +
  28 +
  29 +
  30 +class AgentM(Agent):
  31 +
  32 +
  33 + # FOR TEST ONLY
  34 + # Run this agent in simulator mode
  35 + TEST_MODE = False
  36 + # Run the assertion tests at the end
  37 + TEST_WITH_FINAL_TEST = True
  38 + TEST_MAX_DURATION_SEC = None
  39 + #TEST_MAX_DURATION_SEC = 120
  40 +
  41 + # PM 20190416 fucking config path starting: /home/patrick/Dev/PYROS/start_agent.py agentM
  42 + ##_path_data = 'config'
  43 + _path_data = 'config/old_config'
  44 + # PM 20190416 recycle code
  45 + plcController = PLCController()
  46 + print ("AGENT ENV: config PLC is (ip={}, port={})".format(plcController.ip, plcController.port))
  47 + plc_checker = PlcChecker()
  48 +
  49 + log.debug("PLC instanciated")
  50 + time_history_minutes = 4
  51 +
  52 +
  53 + '''
  54 + # Who should I send commands to ?
  55 + #TEST_COMMANDS_DEST = "myself"
  56 + TEST_COMMANDS_DEST = "AgentA"
  57 + # Scenario to be executed
  58 + TEST_COMMANDS_LIST = [
  59 + "go_active",
  60 + "go_idle",
  61 + "go_active",
  62 + "go_idle",
  63 + "go_active",
  64 + "go_idle",
  65 + "exit",
  66 + ]
  67 + '''
  68 +
  69 + """
  70 + =================================================================
  71 + FUNCTIONS RUN INSIDE MAIN THREAD
  72 + =================================================================
  73 + """
  74 + # old config
  75 + # @override
  76 + #def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True):
  77 + # def __init__(self, config_filename=None, RUN_IN_THREAD=True):
  78 + # ##if name is None: name = self.__class__.__name__
  79 + # super().__init__(config_filename, RUN_IN_THREAD)
  80 +
  81 + # new config (obsconfig)
  82 + def __init__(self, name:str=None):
  83 + if name is None:
  84 + name = self.__class__.__name__
  85 + super().__init__()
  86 + PYROS_CONFIG_FILE = os.environ.get("pyros_config_file")
  87 + if PYROS_CONFIG_FILE:
  88 + CONFIG_PYROS = ConfigPyros(PYROS_CONFIG_FILE).pyros_config
  89 + self.time_history_minutes = int(CONFIG_PYROS.get("ENV").get("time_history"))
  90 + log.info(f"time_history_minutes set to {int(self.time_history_minutes)}")
  91 + # @override
  92 + def _init(self):
  93 + super()._init()
  94 +
  95 + log.debug("end init()")
  96 + # --- Set the mode according the startmode value
  97 + ##agent_alias = self.__class__.__name__
  98 + ##self.set_mode_from_config(agent_alias)
  99 +
  100 + '''
  101 + # @override
  102 + def load_config(self):
  103 + super().load_config()
  104 + '''
  105 +
  106 + '''
  107 + # @override
  108 + def update_survey(self):
  109 + super().update_survey()
  110 + '''
  111 +
  112 + '''
  113 + # @override
  114 + def get_next_command(self):
  115 + return super().get_next_command()
  116 + '''
  117 +
  118 + # @override
  119 + def do_log(self):
  120 + super().do_log()
  121 +
  122 +
  123 +
  124 + """
  125 + =================================================================
  126 + FUNCTIONS RUN INSIDE A SUB-THREAD (OR A PROCESS) (thread_*())
  127 + =================================================================
  128 + """
  129 +
  130 + # Define your own command step(s) here
  131 + def cmd_step1(self, step:int):
  132 + cmd = self._current_specific_cmd
  133 + cmd.result = f"in step #{step}/{self._thread_total_steps_number}"
  134 + cmd.save()
  135 + """
  136 + if self.RUN_IN_THREAD:
  137 + print("(save from thread)")
  138 + cmd.save()
  139 + else:
  140 + #@transaction.atomic
  141 + print("(save from process)")
  142 + with transaction.atomic():
  143 + cmd.save()
  144 + #Command.objects.select_for_update()
  145 + """
  146 +
  147 + def cmd_step2(self, step:int):
  148 + self.cmd_step1(step)
  149 + def cmd_step3(self, step:int):
  150 + self.cmd_step1(step)
  151 + def cmd_step4(self, step:int):
  152 + self.cmd_step1(step)
  153 +
  154 + """
  155 + # @override
  156 + def thread_exec_specific_cmd_step(self, step:int, sleep_time:float=1.0):
  157 + self.thread_stop_if_asked()
  158 + cmd = self._current_specific_cmd
  159 + print(f">>>>> Thread (cmd {cmd.name}): step #{step}/5")
  160 + self.sleep(sleep_time)
  161 + """
  162 +
  163 + '''
  164 + # @override
  165 + def exec_specific_cmd_start(self, cmd:Command, from_thread=True):
  166 + super().exec_specific_cmd_start(cmd, from_thread)
  167 + '''
  168 +
  169 + # @override
  170 + # previous name of function : routine_process
  171 + # Note : in Agent.py, routine_process_body seems to be the main function of routine of the agent
  172 + # We need to override routine_process_body and not routine_process
  173 + def _routine_process_iter_end_body(self):
  174 + log.debug("in routine_process_body()")
  175 + print("TODO: we recycle code")
  176 + status_plc = self.plcController.getStatus()
  177 + if self.parseNewStatus(status_plc):
  178 + self.saveWeather()
  179 + #self.saveInternalMonitoring()
  180 +
  181 + def parseNewStatus(self,status_plc):
  182 + # """ PM 20181009 parse new status for config
  183 + # Find return string "plc_status" positin within status_plc
  184 + if status_plc.find('PLC_STATUS') >= 0:
  185 + self.plc_checker.chk_config(status_plc)
  186 + return True
  187 + return False
  188 +
  189 + def saveWeather(self):
  190 + outside = WeatherWatch()
  191 + inside = SiteWatch()
  192 + datetimenow = datetime.now(timezone.utc)
  193 + latest_entry_of_history = WeatherWatchHistory.objects.all().order_by("-datetime").first()
  194 + if latest_entry_of_history != None:
  195 + # Get last entry of WeatherWatchHistory as WeatherWatch
  196 + latest_entry_of_history_as_weather = WeatherWatch.objects.get(id=latest_entry_of_history.weather.id)
  197 + outside_attributes_values = {}
  198 + for sensor in self.plc_checker.monitoring_names.keys():
  199 + if sensor in self.plc_checker.inside_sensors:
  200 + value = self.plc_checker.get_sensor(sensor)
  201 + inside.setAttribute(sensor,value)
  202 + else:
  203 + value = self.plc_checker.get_sensor(sensor)
  204 + outside.setAttribute(sensor, value)
  205 + outside_attributes_values[sensor] = value
  206 + outside.setGlobalStatus()
  207 + outside.save()
  208 + #inside.save()
  209 + # We don't have an history for weatherwatch
  210 + if latest_entry_of_history == None:
  211 + weather_history = WeatherWatchHistory()
  212 + weather_history.weather = outside
  213 + for sensor in outside_attributes_values.keys():
  214 + weather_history.setAttribute(sensor,outside_attributes_values.get(sensor))
  215 + # save also sensors
  216 + weather_history.save()
  217 + else:
  218 + time_between_history_and_latest_entry = datetimenow - latest_entry_of_history_as_weather.updated
  219 + sec_diff = time_between_history_and_latest_entry.total_seconds() / 60
  220 + # if diff between last entry of history and current time if greather than x then we save a new entry in history
  221 + if int(sec_diff) > self.time_history_minutes:
  222 + weather_history = WeatherWatchHistory()
  223 + weather_history.weather = outside
  224 + for sensor in outside_attributes_values.keys():
  225 + weather_history.setAttribute(sensor,outside_attributes_values.get(sensor))
  226 + weather_history.save()
  227 + log.debug("saved weather")
  228 +
  229 + def isInsideMonitoring(self,key):
  230 + print(key)
  231 + if key in ("Power_input","Roof_state"):
  232 + return True
  233 + else:
  234 + return False
  235 + # @override
  236 + def thread_exec_specific_cmd_main(self):
  237 + # This is optional
  238 + self.thread_set_total_steps_number(5)
  239 +
  240 + # HERE, write your own scenario
  241 +
  242 + # scenario OK
  243 + self.thread_exec_specific_cmd_step(1, self.cmd_step1, 1)
  244 + self.thread_exec_specific_cmd_step(2, self.cmd_step2, 3)
  245 + self.thread_exec_specific_cmd_step(3, self.cmd_step1, 5)
  246 + self.thread_exec_specific_cmd_step(4, self.cmd_step3, 10)
  247 + self.thread_exec_specific_cmd_step(5, self.cmd_step1, 4)
  248 + # ... as many as you need
  249 +
  250 + """ autre scenario
  251 + self.thread_exec_specific_cmd_step(1, self.cmd_step1, 1)
  252 + self.thread_exec_specific_cmd_step(2, self.cmd_step2, 2)
  253 + self.thread_exec_specific_cmd_step(3, self.cmd_step1, 2)
  254 + self.thread_exec_specific_cmd_step(4, self.cmd_step3, 2)
  255 + self.thread_exec_specific_cmd_step(5, self.cmd_step1, 3)
  256 + """
  257 +
  258 + '''
  259 + # @override
  260 + def exec_specific_cmd_end(self, cmd:Command, from_thread=True):
  261 + super().exec_specific_cmd_end(cmd, from_thread)
  262 + '''
  263 +
  264 +
  265 +if __name__ == "__main__":
  266 +
  267 + # with thread
  268 + RUN_IN_THREAD=True
  269 + # with process
  270 + #RUN_IN_THREAD=False
  271 +
  272 + agent = build_agent(AgentM)
  273 + '''
  274 + TEST_MODE, configfile = extract_parameters()
  275 + agent = AgentM("AgentM", configfile, RUN_IN_THREAD)
  276 + agent.setSimulatorMode(TEST_MODE)
  277 + '''
  278 + print(agent)
  279 + agent.run()
... ...
src/core/pyros_django/monitoring/AgentM.py
... ... @@ -8,8 +8,11 @@ import sys
8 8 #from django.db import transaction
9 9 #from common.models import Command
10 10  
11   -sys.path.append("..")
12   -sys.path.append("../../../..")
  11 +import os
  12 +pwd = os.environ['PROJECT_ROOT_PATH']
  13 +if pwd not in sys.path:
  14 + sys.path.append(pwd)
  15 +
13 16 from src.core.pyros_django.agent.Agent import Agent, build_agent, log
14 17  
15 18 # PM 20190416 recycle code
... ... @@ -167,7 +170,7 @@ class AgentM(Agent):
167 170 # previous name of function : routine_process
168 171 # Note : in Agent.py, routine_process_body seems to be the main function of routine of the agent
169 172 # We need to override routine_process_body and not routine_process
170   - def routine_process_body(self):
  173 + def _routine_process_iter_end_body(self):
171 174 log.debug("in routine_process_body()")
172 175 print("TODO: we recycle code")
173 176 status_plc = self.plcController.getStatus()
... ...