ソースを参照

Warning collector implemented

tags/v1.1.0^0
Dirk Alders 1年前
コミット
7b3c7198be
4個のファイルの変更76行の追加9行の削除
  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 ファイルの表示

@@ -30,7 +30,9 @@ from base import mqtt_base
30 30
 from function.videv import base as videv_base
31 31
 import json
32 32
 import logging
33
+import math
33 34
 import task
35
+import time
34 36
 
35 37
 try:
36 38
     from config import APP_NAME as ROOT_LOGGER_NAME
@@ -40,6 +42,27 @@ except ImportError:
40 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 66
 def is_json(data):
44 67
     try:
45 68
         json.loads(data)
@@ -110,7 +133,7 @@ class base(mqtt_base):
110 133
     KEY_WARNING = '__WARNING__'
111 134
 
112 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 137
         # data storage
115 138
         # initialisations
116 139
         mqtt_client.add_callback(topic=self.topic, callback=self.receive_callback)
@@ -119,7 +142,7 @@ class base(mqtt_base):
119 142
     def set(self, key, data, block_callback=[]):
120 143
         if key in self.RX_IGNORE_KEYS:
121 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 146
             return super().set(key, data, block_callback)
124 147
         else:
125 148
             self.logger.warning("Unexpected key %s", key)
@@ -230,7 +253,9 @@ class shelly(base):
230 253
     # WARNING CALL
231 254
     #
232 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 261
     # RX
@@ -382,7 +407,9 @@ class silvercrest_motion_sensor(base):
382 407
     # WARNING CALL
383 408
     #
384 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 415
     # RX
@@ -392,6 +419,11 @@ class silvercrest_motion_sensor(base):
392 419
         """rv: numeric value"""
393 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 428
 class my_powerplug(base):
397 429
     KEY_OUTPUT_0 = "output/1"
@@ -637,8 +669,9 @@ class tradfri_button(base):
637 669
     def __warning__(self, client, key, data):
638 670
         if data <= BATTERY_WARN_LEVEL:
639 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 675
         else:
643 676
             self.__battery_warning__ = False
644 677
 
@@ -684,7 +717,9 @@ class brennenstuhl_heatingvalve(base):
684 717
         if data <= BATTERY_WARN_LEVEL:
685 718
             if not self.__battery_warning__:
686 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 723
         else:
689 724
             self.__battery_warning__ = False
690 725
 

+ 5
- 2
function/__init__.py ファイルの表示

@@ -8,8 +8,7 @@ from function.ground_floor_west import ground_floor_west
8 8
 from function.first_floor_west import first_floor_west
9 9
 from function.first_floor_east import first_floor_east
10 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 12
 import logging
14 13
 
15 14
 try:
@@ -40,6 +39,10 @@ class all_functions(room_collection):
40 39
         self.init_cross_room_interactions()
41 40
         # Off Buttons
42 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 47
     def init_cross_room_interactions(self):
45 48
         # shelly dirk input 1

+ 15
- 0
function/rooms.py ファイルの表示

@@ -40,3 +40,18 @@ class room_collection(object):
40 40
                 sub = getattr(self, sub_name)
41 41
                 if sub.__class__.__bases__[0].__name__ in self.ALLOWED_CLASSES:
42 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 ファイルの表示

@@ -260,6 +260,20 @@ class videv_audio_player(base):
260 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 277
 class all_off(base):
264 278
     ALLOWED_CLASSES = (room, room_collection, )
265 279
 

読み込み中…
キャンセル
保存