Blame view

src/monitoring/tasks.py 9.46 KB
5b5566ab   haribo   added celery
1
from __future__ import absolute_import
a190892c   haribo   Date: 05/07/2016
2
from django.conf import settings
ddf59dd4   haribo   Remaniement :
3
from common.models import *
81408f10   Etienne Pallier   Added some useful...
4
5

# (EP) OLD task base class
ac74403f   Etienne Pallier   bugfixed my wrong...
6
7
8
from celery.task import Task
# NEW task base class, but DOES NOT WORK (because celery3 and not 4 ?) !!!
#from celery import Task
81408f10   Etienne Pallier   Added some useful...
9

ddf59dd4   haribo   Remaniement :
10
from devices.PLC import PLCController
4cb0ff36   Jeremy   Update
11
from utils.JDManipulator import *
6c2793c2   jeremy   Update
12
import json
bca9a283   Jeremy   Reworked the sche...
13
import utils.Logger as L
c72eb17a   Jeremy   Update celery task
14
15
16
import majordome.tasks
import alert_manager.tasks

4cb0ff36   Jeremy   Update
17
log = L.setupLogger("MonitoringTaskLogger", "Monitoring")
c5a3b4a0   haribo   Date: 05/07/2016
18

1a2dc19f   Etienne Pallier   nombreux bugfixes...
19
20
21
# EP
#DEBUG_FILE = False
DEBUG_FILE = True
ce470283   Jeremy   Plc simulator fin...
22
23


65149de7   Jeremy   Update
24
25
'''
    Infinite task created at the program's start.
4cb0ff36   Jeremy   Update
26
    Checks the plc status, parse it, analyse it, store it in db
65149de7   Jeremy   Update
27
'''
257abe9b   Jeremy   Added comments
28
29


ef60c3ec   Jeremy   Majordome and mon...
30
31
32
class Monitoring(Task):
    timers = {}
    functions = {}
5b5566ab   haribo   added celery
33
34

    def run(self):
1a2dc19f   Etienne Pallier   nombreux bugfixes...
35
        print ("AGENT Monitoring: startup...")
c72eb17a   Jeremy   Update celery task
36
        self.createTask()
1a2dc19f   Etienne Pallier   nombreux bugfixes...
37
38
39

        # (TRY TO) Connect to PLC
        # (non blocking if could not connect)
65149de7   Jeremy   Update
40
        self.setContext()
1a2dc19f   Etienne Pallier   nombreux bugfixes...
41
42
43
44
45
46
        print ("AGENT Monitoring: config PLC is (ip={}, port={})".format(self.plcController.ip, self.plcController.port))
        
        # (EP) self.setTime()
        self.setTimers()
        print("AGENT Monitoring: my timers (check env status every {}s, check other agents every {}s)".format(self.timer_status, self.timer_tasks))
        
c72eb17a   Jeremy   Update celery task
47
        self.setTasks()
1a2dc19f   Etienne Pallier   nombreux bugfixes...
48
49
        print("AGENT Monitoring: Other Agents id read from DB (majordome={}, alert={})".format(self.majordome_task, self.alert_task))
        
4cb0ff36   Jeremy   Update
50
        self.loop()
a190892c   haribo   Date: 05/07/2016
51

1a2dc19f   Etienne Pallier   nombreux bugfixes...
52

c72eb17a   Jeremy   Update celery task
53
54
    def createTask(self):
        try:
1a2dc19f   Etienne Pallier   nombreux bugfixes...
55
56
57
            # (EP) NO find() method available from Django ORM, c'est du n'importe quoi ce code (lastminute.com ?) !!!! 
            #TaskId.objects.find(task="monitoring").delete()
            TaskId.objects.filter(task="monitoring").delete()
c72eb17a   Jeremy   Update celery task
58
59
        except Exception as e:
            log.info(str(e))
1a2dc19f   Etienne Pallier   nombreux bugfixes...
60
61
            # (EP) return always if no monitoring task to delete, and so monitoring task id is never saved !!!
            #return 1
c72eb17a   Jeremy   Update celery task
62
63
64
65
66
67
68
69
70
71
72
73
        TaskId.objects.create(task_id=self.request.id, task="monitoring")
        return 0

    def setTasks(self):
        try:
            self.majordome_task = TaskId.objects.get(task="majordome")
            self.alert_task = TaskId.objects.get(task="alert_manager")
        except Exception as e:
            self.majordome_task = None
            self.alert_task = None
        return 0

65149de7   Jeremy   Update
74
    def setContext(self):
1a2dc19f   Etienne Pallier   nombreux bugfixes...
75
        self.plcController = PLCController()
4cb0ff36   Jeremy   Update
76
        self.state = "RUNNING"
65149de7   Jeremy   Update
77
        return (0)
c5a3b4a0   haribo   Date: 05/07/2016
78

1a2dc19f   Etienne Pallier   nombreux bugfixes...
79
    def setTimers(self):
ef60c3ec   Jeremy   Majordome and mon...
80
        self.timer_status = 2
c72eb17a   Jeremy   Update celery task
81
82
        self.timer_tasks = 5
        self.timers = {"timer_status": self.timer_status,
1a2dc19f   Etienne Pallier   nombreux bugfixes...
83
84
85
86
87
                       "timer_tasks": self.timer_tasks}
        # (EP)         "tasks": self.timer_tasks}
        # (EP) self.functions = {"timer_status": self.handleTimerStatus,
        self.functions = {"timer_status": self.handleStatus,
                          "timer_tasks": self.handleTasks}
4cb0ff36   Jeremy   Update
88
        return (0)
21598bc6   haribo   Date: 01/08/2016
89

bca9a283   Jeremy   Reworked the sche...
90
91
92
    def logDB(self, message: str):
        Log.objects.create(agent='Monitoring', message=message)

257abe9b   Jeremy   Added comments
93
94
95
    '''
        Function called by the main loop to check if the majordome and alert_manager are running
    '''
c72eb17a   Jeremy   Update celery task
96
    def handleTasks(self):
1a2dc19f   Etienne Pallier   nombreux bugfixes...
97
98
99
        # Reset timer total duration
        # (EP) self.timers["tasks"] = self.timer_tasks
        self.timers["timer_tasks"] = self.timer_tasks
c72eb17a   Jeremy   Update celery task
100
101
102
        # TODO check majordome and alert_manager status
        if self.majordome_task is None:
            try:
ed1bf194   Etienne Pallier   bugfix task major...
103
104
105
                # (EP) bugfix !!!
                #self.monitoring_task = TaskId.objects.get(task="majordome")
                self.majordome_task = TaskId.objects.get(task="majordome")
c72eb17a   Jeremy   Update celery task
106
107
108
109
            except Exception as e:
                majordome.tasks.Majordome.apply_async()
                if settings.DEBUG and DEBUG_FILE:
                    log.info(str(e))
1a2dc19f   Etienne Pallier   nombreux bugfixes...
110
                    
c72eb17a   Jeremy   Update celery task
111
112
113
114
115
116
117
        if self.alert_task is None:
            try:
                self.alert_task = TaskId.objects.get(task="alert_manager")
            except Exception as e:
                alert_manager.tasks.AlertListener.apply_async()
                if settings.DEBUG and DEBUG_FILE:
                    log.info(str(e))
15e15006   Etienne Pallier   Nouvelles modifs ...
118
119
120
        # EP non car 0 = false
        #return 0
        return True
c72eb17a   Jeremy   Update celery task
121

257abe9b   Jeremy   Added comments
122
    '''
6c2793c2   jeremy   Update
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
        Check if all devices info are consitants
    '''
    def isStatusValid(self):
        return True

    '''
        Extract content from the status dictionary
    '''
    def extractFromDict(self, status):
        synthesis = {}
        devices = status["device"]
        for device in devices:
            for value in device["values"]:
                synthesis[value["name"]] = value["value"]
                synthesis[value["name"] + "_unit"] = value["unit"]
        return synthesis

fe5613f5   jeremy   Update plc protocol
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
    # TODO ATTENTION SI DEUX DEVICES ONT LE MEME NOM
    def saveContent(self, content):
        devices = content["device"]
        for device in devices:
            status = PlcDeviceStatus()
            try:
                database_device = PlcDevice.objects.get(name=device["name"])
            except Exception as e:
                plc = Plc.objects.first()
                database_device = PlcDevice.objects.create(device=plc, name=device["name"])
            status.device = database_device
            for value in device["values"]:
                status.setValue(value["name"], value["value"], value["unit"])
            status.save()

6c2793c2   jeremy   Update
155
    '''
257abe9b   Jeremy   Added comments
156
157
        Parse status returned by plc
    '''
ce470283   Jeremy   Plc simulator fin...
158
159
160
    def parseStatus(self, status_plc):
        try:
            status = {}
fe5613f5   jeremy   Update plc protocol
161
162
163
164
165
166
167
168
            dict = json.loads(status_plc)[0]
            if dict["name"] == "STATUS":
                if self.isStatusValid():
                    status = self.extractFromDict(dict)
                    self.saveContent(dict)
                else:
                    # TODO HANDLE ERROR HERE
                    pass
ce470283   Jeremy   Plc simulator fin...
169
170
171
172
173
174
175
176
        except Exception as e:
            if DEBUG_FILE and settings.DEBUG:
                log.info(str(e))
            self.status_plc = {}
            return 1
        self.status_plc = status
        return 0

257abe9b   Jeremy   Added comments
177
    '''
fe5613f5   jeremy   Update plc protocol
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
        Check if string is ouside
    '''
    def isOutside(self, key):
        if key.find('Outside') != -1 or key.find('Rain') != -1\
                or key.find("Wind") != -1 or key.find("Sky") != -1:
            return True
        elif key == "Pressure":
            return True
        elif key == "DewPoint":
            return True
        return False

    def isInside(self, key):
        if key.find('Inside') != -1 or key.find('Door') != -1:
            return True
        elif key == "status":
            return True
        elif key == "current":
            return True
        return False

    '''
257abe9b   Jeremy   Added comments
200
201
        Save status returned by plc
    '''
ce470283   Jeremy   Plc simulator fin...
202
203
204
205
    def saveStatus(self):
        outside = WeatherWatch()
        inside = SiteWatch()
        for key, value in self.status_plc.items():
fe5613f5   jeremy   Update plc protocol
206
            if self.isOutside(key):
ce470283   Jeremy   Plc simulator fin...
207
                outside.setAttribute(key, value)
fe5613f5   jeremy   Update plc protocol
208
            elif self.isInside(key):
ce470283   Jeremy   Plc simulator fin...
209
210
211
212
213
                inside.setAttribute(key, value)
        outside.setGlobalStatus()
        inside.setGlobalStatus()
        outside.save()
        inside.save()
15e15006   Etienne Pallier   Nouvelles modifs ...
214
        #return 0
ce470283   Jeremy   Plc simulator fin...
215

257abe9b   Jeremy   Added comments
216
217
218
    '''
        Function called by the main loop to handle the plc status
    '''
1a2dc19f   Etienne Pallier   nombreux bugfixes...
219
220
    def handleStatus(self):
        # Reset timer total duration
4cb0ff36   Jeremy   Update
221
        self.timers["timer_status"] = self.timer_status
1a2dc19f   Etienne Pallier   nombreux bugfixes...
222
223
224
225
        status_plc = self.plcController.getStatus()
        
        # Error while READING status ?
        if (self.plcController.isError(status_plc)):
ce470283   Jeremy   Plc simulator fin...
226
            if (settings.DEBUG and DEBUG_FILE):
1a2dc19f   Etienne Pallier   nombreux bugfixes...
227
                log.info("Invalid PLC status returned (while reading) : " + str(status_plc))
15e15006   Etienne Pallier   Nouvelles modifs ...
228
229
230
            # EP Non car 1 = true
            #return (1)
            return False
1a2dc19f   Etienne Pallier   nombreux bugfixes...
231
        
ed1bf194   Etienne Pallier   bugfix task major...
232
        # (EP) if parseStatus() = THERE WAS AN ERROR !!!
1a2dc19f   Etienne Pallier   nombreux bugfixes...
233
        # Error while PARSING status ?
ce470283   Jeremy   Plc simulator fin...
234
235
        if self.parseStatus(status_plc):
            if (settings.DEBUG and DEBUG_FILE):
1a2dc19f   Etienne Pallier   nombreux bugfixes...
236
                log.info("Invalid PLC status returned (while parsing) : " + str(status_plc))
15e15006   Etienne Pallier   Nouvelles modifs ...
237
238
239
240
            # EP Non car 1 = true
            #return (1)
            return False
        
c7583f6e   Etienne Pallier   Cleaner isolation...
241
242
        print("Status received from PLC (read and parsed ok):")
        print(status_plc)
15e15006   Etienne Pallier   Nouvelles modifs ...
243
244
245
        #return self.saveStatus()
        self.saveStatus()
        return True
21598bc6   haribo   Date: 01/08/2016
246

257abe9b   Jeremy   Added comments
247
248
249
    '''
        Main loop
    '''
4cb0ff36   Jeremy   Update
250
    def loop(self):
c7583f6e   Etienne Pallier   Cleaner isolation...
251
        i=0
4cb0ff36   Jeremy   Update
252
        while (self.state != "SHUTDOWN"):
c7583f6e   Etienne Pallier   Cleaner isolation...
253
254
255
256
            print("-")
            print("-")
            print("-")
            print ("AGENT Monitoring (ENV): iteration "+str(i)+", (my state is " + self.state+") :")
4cb0ff36   Jeremy   Update
257
258
259
260
            minimal_timer = min(self.timers, key=self.timers.get)
            time.sleep(self.timers[minimal_timer])
            self.timers = {key: value - self.timers[minimal_timer] for key, value in self.timers.items()}
            for timer_name, timer_value in self.timers.items():
4cb0ff36   Jeremy   Update
261
                if (timer_value <= 0):
ef60c3ec   Jeremy   Majordome and mon...
262
                    if (timer_name in self.functions):
1a2dc19f   Etienne Pallier   nombreux bugfixes...
263
                        # Handle the timer function
4cb0ff36   Jeremy   Update
264
                        self.functions[timer_name]()
1a2dc19f   Etienne Pallier   nombreux bugfixes...
265
266
                        if (settings.DEBUG and DEBUG_FILE):
                            log.info("Timer : " + str(timer_name) + " executed by monitoring")
4cb0ff36   Jeremy   Update
267
                    else:
ce470283   Jeremy   Plc simulator fin...
268
                        if (settings.DEBUG and DEBUG_FILE):
4cb0ff36   Jeremy   Update
269
                            log.info("Timer : " + str(timer_name) + "is not known by the monitoring")
bca9a283   Jeremy   Reworked the sche...
270
                        self.logDB("Timer " + str(timer_name) + " unknown")
1a2dc19f   Etienne Pallier   nombreux bugfixes...
271
272
273
                # EP : pas au bon endroit !!!
                #if (settings.DEBUG and DEBUG_FILE):
                    #log.info("Timer : " + str(timer_name) + " executed by monitoring")
c7583f6e   Etienne Pallier   Cleaner isolation...
274
            i+=1
ef60c3ec   Jeremy   Majordome and mon...
275
276
        return (0)

1a2dc19f   Etienne Pallier   nombreux bugfixes...
277
278


ef60c3ec   Jeremy   Majordome and mon...
279
280
281
if (__name__ == "__main__"):
    m = Monitoring()
    m.run()