Browse Source

Warning collector implemented

tags/v1.1.0^0
Dirk Alders 1 year ago
parent
commit
7b3c7198be
4 changed files with 76 additions and 9 deletions
  1. 42
    7
      devices/__init__.py
  2. 5
    2
      function/__init__.py
  3. 15
    0
      function/rooms.py
  4. 14
    0
      function/videv.py

+ 42
- 7
devices/__init__.py View File

30
 from function.videv import base as videv_base
30
 from function.videv import base as videv_base
31
 import json
31
 import json
32
 import logging
32
 import logging
33
+import math
33
 import task
34
 import task
35
+import time
34
 
36
 
35
 try:
37
 try:
36
     from config import APP_NAME as ROOT_LOGGER_NAME
38
     from config import APP_NAME as ROOT_LOGGER_NAME
40
 BATTERY_WARN_LEVEL = 5
42
 BATTERY_WARN_LEVEL = 5
41
 
43
 
42
 
44
 
45
+class warning(dict):
46
+    TYPE_BATTERY_LOW = 1
47
+    TYPE_OVERTEMPERATURE = 2
48
+    #
49
+    KEY_ID = 'id'
50
+    KEY_TYPE = 'type'
51
+    KEY_TEXT = 'text'
52
+    KEY_TM = 'tm'
53
+
54
+    def __init__(self, identification, type, text, args):
55
+        super().__init__({
56
+            self.KEY_ID: identification,
57
+            self.KEY_TYPE: type,
58
+            self.KEY_TEXT: text % args,
59
+            self.KEY_TM: time.localtime(),
60
+        })
61
+
62
+    def __str__(self):
63
+        return time.asctime(self.get(self.KEY_TM)) + ": " + self[self.KEY_TEXT] + " - " + self[self.KEY_ID]
64
+
65
+
43
 def is_json(data):
66
 def is_json(data):
44
     try:
67
     try:
45
         json.loads(data)
68
         json.loads(data)
110
     KEY_WARNING = '__WARNING__'
133
     KEY_WARNING = '__WARNING__'
111
 
134
 
112
     def __init__(self, mqtt_client, topic):
135
     def __init__(self, mqtt_client, topic):
113
-        super().__init__(mqtt_client, topic, default_values=dict.fromkeys(self.RX_KEYS))
136
+        super().__init__(mqtt_client, topic, default_values=dict.fromkeys(self.RX_KEYS + [self.KEY_WARNING]))
114
         # data storage
137
         # data storage
115
         # initialisations
138
         # initialisations
116
         mqtt_client.add_callback(topic=self.topic, callback=self.receive_callback)
139
         mqtt_client.add_callback(topic=self.topic, callback=self.receive_callback)
119
     def set(self, key, data, block_callback=[]):
142
     def set(self, key, data, block_callback=[]):
120
         if key in self.RX_IGNORE_KEYS:
143
         if key in self.RX_IGNORE_KEYS:
121
             pass    # ignore these keys
144
             pass    # ignore these keys
122
-        elif key in self.RX_KEYS:
145
+        elif key in self.RX_KEYS or key == self.KEY_WARNING:
123
             return super().set(key, data, block_callback)
146
             return super().set(key, data, block_callback)
124
         else:
147
         else:
125
             self.logger.warning("Unexpected key %s", key)
148
             self.logger.warning("Unexpected key %s", key)
230
     # WARNING CALL
253
     # WARNING CALL
231
     #
254
     #
232
     def __warning__(self, client, key, data):
255
     def __warning__(self, client, key, data):
233
-        pass    # TODO: implement warning feedback (key: KEY_OVERTEMPERATURE - info: KEY_TEMPERATURE)
256
+        w = warning(self.topic, warning.TYPE_OVERTEMPERATURE, "Temperature to high (%.1f°C)", self.get(self.KEY_TEMPERATURE, math.nan))
257
+        self.logger.warning(w)
258
+        self.set(self.KEY_WARNING, w)
234
 
259
 
235
     #
260
     #
236
     # RX
261
     # RX
382
     # WARNING CALL
407
     # WARNING CALL
383
     #
408
     #
384
     def __warning__(self, client, key, data):
409
     def __warning__(self, client, key, data):
385
-        pass    # TODO: implement warning feedback (key: KEY_BATTERY_LOW - info: KEY_BATTERY)
410
+        w = warning(self.topic, warning.TYPE_BATTERY_LOW, "Battery low (%.1f%%)", self.get(self.KEY_BATTERY, math.nan))
411
+        self.logger.warning(w)
412
+        self.set(self.KEY_WARNING, w)
386
 
413
 
387
     #
414
     #
388
     # RX
415
     # RX
392
         """rv: numeric value"""
419
         """rv: numeric value"""
393
         return self.get(self.KEY_LINKQUALITY)
420
         return self.get(self.KEY_LINKQUALITY)
394
 
421
 
422
+    @property
423
+    def battery(self):
424
+        """rv: numeric value"""
425
+        return self.get(self.KEY_BATTERY)
426
+
395
 
427
 
396
 class my_powerplug(base):
428
 class my_powerplug(base):
397
     KEY_OUTPUT_0 = "output/1"
429
     KEY_OUTPUT_0 = "output/1"
637
     def __warning__(self, client, key, data):
669
     def __warning__(self, client, key, data):
638
         if data <= BATTERY_WARN_LEVEL:
670
         if data <= BATTERY_WARN_LEVEL:
639
             if not self.__battery_warning__:
671
             if not self.__battery_warning__:
640
-                self.__battery_warning__ = True
641
-                pass    # TODO: implement warning feedback (key: KEY_BATTERY_LOW - info: KEY_BATTERY)
672
+                w = warning(self.topic, warning.TYPE_BATTERY_LOW, "Battery low (%.1f%%)", data)
673
+                self.logger.warning(w)
674
+                self.set(self.KEY_WARNING, w)
642
         else:
675
         else:
643
             self.__battery_warning__ = False
676
             self.__battery_warning__ = False
644
 
677
 
684
         if data <= BATTERY_WARN_LEVEL:
717
         if data <= BATTERY_WARN_LEVEL:
685
             if not self.__battery_warning__:
718
             if not self.__battery_warning__:
686
                 self.__battery_warning__ = True
719
                 self.__battery_warning__ = True
687
-                pass    # TODO: implement warning feedback (key: KEY_BATTERY_LOW - info: KEY_BATTERY)
720
+                w = warning(self.topic, warning.TYPE_BATTERY_LOW, "Battery low (%.1f%%)", data)
721
+                self.logger.warning(w)
722
+                self.set(self.KEY_WARNING, w)
688
         else:
723
         else:
689
             self.__battery_warning__ = False
724
             self.__battery_warning__ = False
690
 
725
 

+ 5
- 2
function/__init__.py View File

8
 from function.first_floor_west import first_floor_west
8
 from function.first_floor_west import first_floor_west
9
 from function.first_floor_east import first_floor_east
9
 from function.first_floor_east import first_floor_east
10
 from function.rooms import room_collection
10
 from function.rooms import room_collection
11
-from function.videv import all_off
12
-import inspect
11
+from function.videv import all_off, videv_warnings
13
 import logging
12
 import logging
14
 
13
 
15
 try:
14
 try:
40
         self.init_cross_room_interactions()
39
         self.init_cross_room_interactions()
41
         # Off Buttons
40
         # Off Buttons
42
         self.init_off_functionality()
41
         self.init_off_functionality()
42
+        # Warnings
43
+        videv_warning = videv_warnings(self.mqtt_client, config.TOPIC_WARNINGS)
44
+        for device in self.all_devices():
45
+            device.add_callback(devices.base.KEY_WARNING, None, videv_warning.warningcollector)
43
 
46
 
44
     def init_cross_room_interactions(self):
47
     def init_cross_room_interactions(self):
45
         # shelly dirk input 1
48
         # shelly dirk input 1

+ 15
- 0
function/rooms.py View File

40
                 sub = getattr(self, sub_name)
40
                 sub = getattr(self, sub_name)
41
                 if sub.__class__.__bases__[0].__name__ in self.ALLOWED_CLASSES:
41
                 if sub.__class__.__bases__[0].__name__ in self.ALLOWED_CLASSES:
42
                     sub.all_off()
42
                     sub.all_off()
43
+
44
+    def all_devices(self, object_to_analyse=None):
45
+        target = object_to_analyse or self
46
+        #
47
+        devices = []
48
+        for name, obj in inspect.getmembers(target):
49
+            if not callable(obj):                                       # sort out methods
50
+                try:
51
+                    if obj.__module__.startswith('function.'):
52
+                        devices.extend(self.all_devices(obj))           # rekurse in function instances
53
+                    elif obj.__module__ == "devices":
54
+                        devices.append(obj)
55
+                except AttributeError:
56
+                    pass                                                # sort out non modules
57
+        return devices

+ 14
- 0
function/videv.py View File

260
         return self.__capabilities__
260
         return self.__capabilities__
261
 
261
 
262
 
262
 
263
+class videv_warnings(base):
264
+    MAX_WARNINGS = 10
265
+    KEY_WARNING = 'text'
266
+
267
+    def __init__(self, mqtt_client, topic, default_values=None):
268
+        super().__init__(mqtt_client, topic, default_values)
269
+        self.__warnings__ = []
270
+
271
+    def warningcollector(self, client, key, data):
272
+        self.__warnings__.append(data)
273
+        self.__warnings__ = self.__warnings__[-self.MAX_WARNINGS:]
274
+        self.__tx__(self.KEY_WARNING, '\n'.join([str(w) for w in self.__warnings__]))
275
+
276
+
263
 class all_off(base):
277
 class all_off(base):
264
     ALLOWED_CLASSES = (room, room_collection, )
278
     ALLOWED_CLASSES = (room, room_collection, )
265
 
279
 

Loading…
Cancel
Save