Blame view

src/core/pyros_django/monitoring/AgentM.py 8.97 KB
1cffbf1c   Etienne Pallier   moved pyros_djang...
1
2
3
4
5
6
7
8
9
10
11
#!/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

sys.path.append("..")
57a9ffac   Etienne Pallier   bugfixing agentM
12
sys.path.append("../../../..")
12451fde   Etienne Pallier   Amélioration logging
13
from src.core.pyros_django.agent.Agent import Agent, build_agent, log
1cffbf1c   Etienne Pallier   moved pyros_djang...
14
15

# PM 20190416 recycle code
ad6d274a   Etienne Pallier   Restructuration d...
16
17
from src.core.pyros_django.devices.PLC import PLCController
from src.core.pyros_django.monitoring.plc_checker import PlcChecker
1cffbf1c   Etienne Pallier   moved pyros_djang...
18
from common.models import *
e5f122b6   Alexis Koralewski   Adding env monito...
19
20
21
from config.pyros.config_pyros import ConfigPyros


1cffbf1c   Etienne Pallier   moved pyros_djang...
22
23
24
25
26
27
28
29
30
31

##log = L.setupLogger("AgentXTaskLogger", "AgentX")



class AgentM(Agent):


    # FOR TEST ONLY
    # Run this agent in simulator mode
71b8533d   Etienne Pallier   update agentA, ag...
32
    TEST_MODE = False
1cffbf1c   Etienne Pallier   moved pyros_djang...
33
    # Run the assertion tests at the end
71b8533d   Etienne Pallier   update agentA, ag...
34
35
36
    TEST_WITH_FINAL_TEST = True
    TEST_MAX_DURATION_SEC = None
    #TEST_MAX_DURATION_SEC = 120
1cffbf1c   Etienne Pallier   moved pyros_djang...
37
38

    # PM 20190416 fucking config path starting: /home/patrick/Dev/PYROS/start_agent.py agentM
a9d06e6f   Etienne Pallier   new PYROS_DOCKER_...
39
40
    ##_path_data = 'config'
    _path_data = 'config/old_config'
1cffbf1c   Etienne Pallier   moved pyros_djang...
41
42
43
44
45
    # PM 20190416 recycle code
    plcController = PLCController()
    print ("AGENT ENV: config PLC is (ip={}, port={})".format(plcController.ip, plcController.port))
    plc_checker = PlcChecker()

12451fde   Etienne Pallier   Amélioration logging
46
    log.debug("PLC instanciated")
e5f122b6   Alexis Koralewski   Adding env monito...
47
    time_history_minutes = 4
12451fde   Etienne Pallier   Amélioration logging
48

1cffbf1c   Etienne Pallier   moved pyros_djang...
49
50
51

    '''
    # Who should I send commands to ?
71b8533d   Etienne Pallier   update agentA, ag...
52
53
    #TEST_COMMANDS_DEST = "myself"
    TEST_COMMANDS_DEST = "AgentA"
1cffbf1c   Etienne Pallier   moved pyros_djang...
54
    # Scenario to be executed
71b8533d   Etienne Pallier   update agentA, ag...
55
    TEST_COMMANDS_LIST = [
1cffbf1c   Etienne Pallier   moved pyros_djang...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
        "go_active",
        "go_idle",
        "go_active",
        "go_idle",
        "go_active",
        "go_idle",
        "exit",
    ]
    '''

    """
    =================================================================
        FUNCTIONS RUN INSIDE MAIN THREAD
    =================================================================
    """
7f61826d   Alexis Koralewski   Fixing Agent.py i...
71
    # old config
1cffbf1c   Etienne Pallier   moved pyros_djang...
72
    # @override
71b8533d   Etienne Pallier   update agentA, ag...
73
    #def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True):
7f61826d   Alexis Koralewski   Fixing Agent.py i...
74
75
76
77
78
    # 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)
dd27c2bc   Alexis Koralewski   Updating agent co...
79
    def __init__(self, name:str=None):
7f61826d   Alexis Koralewski   Fixing Agent.py i...
80
81
        if name is None:
            name = self.__class__.__name__
dd27c2bc   Alexis Koralewski   Updating agent co...
82
        super().__init__()
e5f122b6   Alexis Koralewski   Adding env monito...
83
84
85
86
87
        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)}")
1cffbf1c   Etienne Pallier   moved pyros_djang...
88
    # @override
0bcd6dd5   Etienne Pallier   renamed Agent met...
89
90
    def _init(self):
        super()._init()
e5f122b6   Alexis Koralewski   Adding env monito...
91
       
12451fde   Etienne Pallier   Amélioration logging
92
        log.debug("end init()")
1cffbf1c   Etienne Pallier   moved pyros_djang...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
        # --- 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()



    """
    =================================================================
        FUNCTIONS RUN INSIDE A SUB-THREAD (OR A PROCESS) (thread_*())
    =================================================================
    """

    # Define your own command step(s) here
    def cmd_step1(self, step:int):
        cmd = self._current_specific_cmd
        cmd.result = f"in step #{step}/{self._thread_total_steps_number}"
        cmd.save()
        """
        if self.RUN_IN_THREAD:
            print("(save from thread)")
            cmd.save()
        else:
            #@transaction.atomic
            print("(save from process)")
            with transaction.atomic():
                cmd.save()
                #Command.objects.select_for_update()
        """

    def cmd_step2(self, step:int):
        self.cmd_step1(step)
    def cmd_step3(self, step:int):
        self.cmd_step1(step)
    def cmd_step4(self, step:int):
        self.cmd_step1(step)

    """
    # @override
    def thread_exec_specific_cmd_step(self, step:int, sleep_time:float=1.0):
        self.thread_stop_if_asked()
        cmd = self._current_specific_cmd
        print(f">>>>> Thread (cmd {cmd.name}): step #{step}/5")
        self.sleep(sleep_time)
    """

    '''
    # @override
    def exec_specific_cmd_start(self, cmd:Command, from_thread=True):
        super().exec_specific_cmd_start(cmd, from_thread)
    '''

    # @override
74a196a1   Alexis Koralewski   fixing weather pa...
167
168
169
170
    # 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_body(self):
12451fde   Etienne Pallier   Amélioration logging
171
        log.debug("in routine_process_body()")
1cffbf1c   Etienne Pallier   moved pyros_djang...
172
173
174
175
        print("TODO: we recycle code")
        status_plc = self.plcController.getStatus()
        if self.parseNewStatus(status_plc):
            self.saveWeather()
7f61826d   Alexis Koralewski   Fixing Agent.py i...
176
            #self.saveInternalMonitoring()
1cffbf1c   Etienne Pallier   moved pyros_djang...
177

61df368d   Etienne Pallier   Mis à jour Enviro...
178
    def parseNewStatus(self,status_plc):
1cffbf1c   Etienne Pallier   moved pyros_djang...
179
        # """ PM 20181009 parse new status for config
7f61826d   Alexis Koralewski   Fixing Agent.py i...
180
        # Find return string "plc_status" positin within status_plc
1cffbf1c   Etienne Pallier   moved pyros_djang...
181
182
183
        if status_plc.find('PLC_STATUS') >= 0:
            self.plc_checker.chk_config(status_plc)
            return True
61df368d   Etienne Pallier   Mis à jour Enviro...
184
        return False
1cffbf1c   Etienne Pallier   moved pyros_djang...
185
186
187

    def saveWeather(self):
        outside = WeatherWatch()
7f61826d   Alexis Koralewski   Fixing Agent.py i...
188
        inside = SiteWatch()
b9068dc6   Alexis Koralewski   Adding WeatherWat...
189
        datetimenow = datetime.now(timezone.utc)
e5f122b6   Alexis Koralewski   Adding env monito...
190
        latest_entry_of_history = WeatherWatchHistory.objects.all().order_by("-datetime").first()
b9068dc6   Alexis Koralewski   Adding WeatherWat...
191
192
193
        if latest_entry_of_history != None:
            # Get last entry of WeatherWatchHistory as WeatherWatch
            latest_entry_of_history_as_weather = WeatherWatch.objects.get(id=latest_entry_of_history.weather.id)
e5f122b6   Alexis Koralewski   Adding env monito...
194
        outside_attributes_values = {}
a78619ca   Patrick Maeght   weather config up...
195
        for sensor in self.plc_checker.monitoring_names.keys():
b9068dc6   Alexis Koralewski   Adding WeatherWat...
196
            if sensor in self.plc_checker.inside_sensors:
7f61826d   Alexis Koralewski   Fixing Agent.py i...
197
198
199
200
                value = self.plc_checker.get_sensor(sensor)
                inside.setAttribute(sensor,value)
            else:
                value = self.plc_checker.get_sensor(sensor)
7f61826d   Alexis Koralewski   Fixing Agent.py i...
201
                outside.setAttribute(sensor, value)
e5f122b6   Alexis Koralewski   Adding env monito...
202
                outside_attributes_values[sensor] = value
1cffbf1c   Etienne Pallier   moved pyros_djang...
203
204
        outside.setGlobalStatus()
        outside.save()
b9068dc6   Alexis Koralewski   Adding WeatherWat...
205
206
207
208
209
        #inside.save()
        # We don't have an history for weatherwatch
        if latest_entry_of_history == None:
            weather_history = WeatherWatchHistory()
            weather_history.weather = outside
e5f122b6   Alexis Koralewski   Adding env monito...
210
211
            for sensor in outside_attributes_values.keys():
                weather_history.setAttribute(sensor,outside_attributes_values.get(sensor))
b9068dc6   Alexis Koralewski   Adding WeatherWat...
212
213
214
215
216
217
            # save also sensors 
            weather_history.save()
        else:
            time_between_history_and_latest_entry = datetimenow - latest_entry_of_history_as_weather.updated  
            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
e5f122b6   Alexis Koralewski   Adding env monito...
218
            if int(sec_diff) > self.time_history_minutes:
b9068dc6   Alexis Koralewski   Adding WeatherWat...
219
220
                weather_history = WeatherWatchHistory()
                weather_history.weather = outside
e5f122b6   Alexis Koralewski   Adding env monito...
221
222
                for sensor in outside_attributes_values.keys():
                    weather_history.setAttribute(sensor,outside_attributes_values.get(sensor))
b9068dc6   Alexis Koralewski   Adding WeatherWat...
223
                weather_history.save()
12451fde   Etienne Pallier   Amélioration logging
224
225
        log.debug("saved weather")

7f61826d   Alexis Koralewski   Fixing Agent.py i...
226
227
228
229
230
231
    def isInsideMonitoring(self,key):
        print(key)
        if key in ("Power_input","Roof_state"):
            return True
        else:
            return False
1cffbf1c   Etienne Pallier   moved pyros_djang...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    # @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

dd27c2bc   Alexis Koralewski   Updating agent co...
269
    agent = build_agent(AgentM)
71b8533d   Etienne Pallier   update agentA, ag...
270
    '''
1cffbf1c   Etienne Pallier   moved pyros_djang...
271
272
273
    TEST_MODE, configfile = extract_parameters()
    agent = AgentM("AgentM", configfile, RUN_IN_THREAD)
    agent.setSimulatorMode(TEST_MODE)
71b8533d   Etienne Pallier   update agentA, ag...
274
    '''
1cffbf1c   Etienne Pallier   moved pyros_djang...
275
276
    print(agent)
    agent.run()