Преглед на файлове

Inital check_z_actor added + refactoring

master
Dirk Alders преди 5 месеца
родител
ревизия
5a9b7a1847
променени са 6 файла, в които са добавени 114 реда и са изтрити 86 реда
  1. 1
    0
      check_z_actor
  2. 12
    16
      check_z_heartbeat
  3. 1
    1
      check_z_linkquality
  4. 87
    63
      z_server/devices/__init__.py
  5. 1
    1
      z_server/mqtt
  6. 12
    5
      z_server/z_protocol.py

+ 1
- 0
check_z_actor Целия файл

@@ -0,0 +1 @@
1
+check_z_heartbeat

+ 12
- 16
check_z_heartbeat Целия файл

@@ -3,11 +3,12 @@
3 3
 
4 4
 import argparse
5 5
 import nagios
6
+import os
6 7
 import time
7 8
 from z_server import config
8 9
 from z_server import tcp_socket
9 10
 from z_server.z_protocol import server as client_prot
10
-from z_server.z_protocol import DID_FOLLOWS_SETPOINT, DID_BATTERY_LEVEL, DID_HEARTBEAT, DID_LINKQUALITY
11
+from z_server.z_protocol import DIDS
11 12
 from z_server import socket_protocol
12 13
 import sys
13 14
 
@@ -32,19 +33,14 @@ if __name__ == '__main__':
32 33
         "fun": args.fun
33 34
     }
34 35
     #
35
-    if sys.argv[0].endswith('check_z_heartbeat'):
36
-        sp.send(socket_protocol.SID_READ_REQUEST, DID_HEARTBEAT, data)
37
-        sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_HEARTBEAT).get_data()
38
-    elif sys.argv[0].endswith('check_z_battery'):
39
-        sp.send(socket_protocol.SID_READ_REQUEST, DID_BATTERY_LEVEL, data)
40
-        sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_BATTERY_LEVEL).get_data()
41
-    elif sys.argv[0].endswith('check_z_linkquality'):
42
-        sp.send(socket_protocol.SID_READ_REQUEST, DID_LINKQUALITY, data)
43
-        sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_LINKQUALITY).get_data()
44
-    elif sys.argv[0].endswith('check_z_follow'):
45
-        sp.send(socket_protocol.SID_READ_REQUEST, DID_FOLLOWS_SETPOINT, data)
46
-        sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_FOLLOWS_SETPOINT).get_data()
47
-    else:
48
-        sys.stderr.write('No action for command called "%s"\n' % sys.argv[0])
36
+
37
+    did = os.path.basename(sys.argv[0])[8:]
38
+    #
39
+    if did not in DIDS:
40
+        print("Unknown data id %s. You might add it in z_server.z_protocol." % did)
49 41
         sys.exit(100)
50
-    nagios.Nagios().exit(**sp_data)
42
+    else:
43
+        sp.send(socket_protocol.SID_READ_REQUEST, did, data)
44
+        sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, did).get_data() or {
45
+            "status": 101, "msg": "No answer from device for \"%s\". You might want to add it in z_server.devices" % did}
46
+        nagios.Nagios().exit(**sp_data)

+ 1
- 1
check_z_linkquality Целия файл

@@ -1 +1 @@
1
-check_z_follow
1
+check_z_heartbeat

+ 87
- 63
z_server/devices/__init__.py Целия файл

@@ -3,6 +3,7 @@ import logging
3 3
 import mqtt
4 4
 import nagios
5 5
 import time
6
+from z_protocol import DID_ACTOR, DID_BATTERY_LEVEL, DID_FOLLOWS_SETPOINT, DID_HEARTBEAT, DID_LINKQUALITY
6 7
 
7 8
 try:
8 9
     from config import APP_NAME as ROOT_LOGGER_NAME
@@ -12,14 +13,13 @@ logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
12 13
 
13 14
 
14 15
 class base(object):
15
-    MONITORING_HEARTBEAT = "heartbeat"
16
-    MONITORING_BATTERY = "battery"
17
-    MONITORING_FOLLOW_SETPOINT = "follow_setpoint"
18
-    MONITORING_LINKQUALITY = "linkquality"
16
+    KEY_BATTERY = 'battery'
17
+    KEY_CURRENT_VALUE = None
18
+    KEY_LINKQUALITY = 'linkquality'
19
+    KEY_SETPOINT = None
19 20
     #
20 21
     FOLLOW_REQUEST_WARNING = 5      # Seconds, till warning comes up, if device does not follow the command
21 22
     FOLLOW_REQUEST_ERROR = 60       # Seconds, till error comes up, if device does not follow the command
22
-    FOLLOW_KEY = None
23 23
     #
24 24
     BATTERY_LVL_WARNING = 15
25 25
     BATTERY_LVL_ERROR = 5
@@ -42,9 +42,6 @@ class base(object):
42 42
         #
43 43
         self.__target_storage__ = {}
44 44
         self.__state_storage__ = {}
45
-        #
46
-        self.battery = None
47
-        self.linkquality = None
48 45
 
49 46
     def __rx__(self, client, userdata, message):
50 47
         try:
@@ -54,28 +51,22 @@ class base(object):
54 51
         else:
55 52
             if type(payload) is dict:
56 53
                 #
57
-                # heartbeat
54
+                # Device values
58 55
                 #
59 56
                 if message.topic == self.topic:
60
-                    self.last_device_msg = time.time()
61
-                #
62
-                # follow setpoint
63
-                #
64
-                if self.FOLLOW_KEY is not None and self.FOLLOW_KEY in payload:
65
-                    if message.topic == self.topic + '/set':
66
-                        self.target(self.FOLLOW_KEY, payload[self.FOLLOW_KEY])
67
-                    if message.topic == self.topic:
68
-                        self.state(self.FOLLOW_KEY, payload[self.FOLLOW_KEY])
57
+                    for key in [self.KEY_BATTERY, self.KEY_CURRENT_VALUE, self.KEY_LINKQUALITY, self.KEY_SETPOINT]:
58
+                        if key in payload:
59
+                            self.state(key, payload[key])
69 60
                 #
70
-                # battery level
61
+                # Device setpoint
71 62
                 #
72
-                if self.MONITORING_BATTERY in payload and message.topic == self.topic:
73
-                    self.battery = payload[self.MONITORING_BATTERY]
63
+                if message.topic == self.topic + '/set' and self.KEY_SETPOINT in payload:
64
+                    self.target(self.KEY_SETPOINT, payload[self.KEY_SETPOINT])
74 65
                 #
75
-                # linkquality
66
+                # heartbeat
76 67
                 #
77
-                if self.MONITORING_LINKQUALITY in payload and message.topic == self.topic:
78
-                    self.linkquality = payload[self.MONITORING_LINKQUALITY]
68
+                if message.topic == self.topic:
69
+                    self.last_device_msg = time.time()
79 70
 
80 71
     def target(self, key, value):
81 72
         tm_t, value_t = self.__target_storage__.get(key, (0, None))
@@ -89,74 +80,81 @@ class base(object):
89 80
 
90 81
     def status(self, key):
91 82
         #
83
+        # ACTOR
84
+        #
85
+        if key == DID_ACTOR:
86
+            return self.__nagios_return__(DID_ACTOR, nagios.Nagios.WARNING, "Not available for this device")
87
+        #
92 88
         # HEARTBEAT
93 89
         #
94
-        if key == self.MONITORING_HEARTBEAT:
90
+        elif key == DID_HEARTBEAT:
95 91
             if self.last_device_msg is None:
96
-                return self.__nagios_return__(self.MONITORING_HEARTBEAT, nagios.Nagios.UNKNOWN, "Device exists, but no data received")
92
+                return self.__nagios_return__(DID_HEARTBEAT, nagios.Nagios.UNKNOWN, "Device exists, but no data received")
97 93
             else:
98 94
                 dt = time.time() - self.last_device_msg
99 95
                 dt_disp = dt / 60 / 60
100 96
                 if dt > self.LAST_MSG_ERROR:
101
-                    return self.__nagios_return__(self.MONITORING_HEARTBEAT, nagios.Nagios.ERROR, "Last message %.1fh ago" % dt_disp)
97
+                    return self.__nagios_return__(DID_HEARTBEAT, nagios.Nagios.ERROR, "Last message %.1fh ago" % dt_disp)
102 98
                 elif dt > self.LAST_MSG_WARNING:
103
-                    return self.__nagios_return__(self.MONITORING_HEARTBEAT, nagios.Nagios.WARNING, "Last message %.1fh ago" % dt_disp)
99
+                    return self.__nagios_return__(DID_HEARTBEAT, nagios.Nagios.WARNING, "Last message %.1fh ago" % dt_disp)
104 100
                 else:
105
-                    return self.__nagios_return__(self.MONITORING_HEARTBEAT, nagios.Nagios.OK, "Last message %.1fh ago" % dt_disp)
101
+                    return self.__nagios_return__(DID_HEARTBEAT, nagios.Nagios.OK, "Last message %.1fh ago" % dt_disp)
106 102
         #
107 103
         # FOLLOW SETPOINT
108 104
         #
109
-        elif key == self.MONITORING_FOLLOW_SETPOINT:
110
-            if self.FOLLOW_KEY is None:
111
-                return self.__nagios_return__(self.MONITORING_FOLLOW_SETPOINT, nagios.Nagios.UNKNOWN, "Device exist, but does not follow any setpoint.", force=True)
112
-            tm_s, value_s = self.__state_storage__.get(self.FOLLOW_KEY, (0, None))
105
+        elif key == DID_FOLLOWS_SETPOINT:
106
+            if self.KEY_SETPOINT is None:
107
+                return self.__nagios_return__(DID_FOLLOWS_SETPOINT, nagios.Nagios.UNKNOWN, "Device exist, but does not follow any setpoint.", force=True)
108
+            tm_s, value_s = self.__state_storage__.get(self.KEY_SETPOINT, (0, None))
113 109
             try:
114
-                tm_t, value_t = self.__target_storage__[self.FOLLOW_KEY]
110
+                tm_t, value_t = self.__target_storage__[self.KEY_SETPOINT]
115 111
             except KeyError:
116 112
                 if value_s is not None:
117
-                    return self.__nagios_return__(self.MONITORING_FOLLOW_SETPOINT, nagios.Nagios.OK, "Current temperature setpoint %.1f°C, but never received a setpoint. That might be okay." % value_s)
118
-                return self.__nagios_return__(self.MONITORING_FOLLOW_SETPOINT, nagios.Nagios.UNKNOWN, "Device exists, but no data received")
113
+                    return self.__nagios_return__(DID_FOLLOWS_SETPOINT, nagios.Nagios.OK, "Current temperature setpoint %.1f°C, but never received a setpoint. That might be okay." % value_s)
114
+                return self.__nagios_return__(DID_FOLLOWS_SETPOINT, nagios.Nagios.UNKNOWN, "Device exists, but no data received")
119 115
             else:
120 116
                 tm = time.time()
121 117
                 dt = tm - tm_t
122 118
                 if value_t != value_s and dt > self.FOLLOW_REQUEST_ERROR:
123
-                    return self.__nagios_return__(self.MONITORING_FOLLOW_SETPOINT, nagios.Nagios.ERROR, "Requested setpoint %.1f°C unequal valve setpoint %.1f°C since %.1fmin" % (value_t, value_s, (time.time()-tm_s)/60))
119
+                    return self.__nagios_return__(DID_FOLLOWS_SETPOINT, nagios.Nagios.ERROR, "Requested setpoint %.1f°C unequal valve setpoint %.1f°C since %.1fmin" % (value_t, value_s, (time.time()-tm_s)/60))
124 120
                 elif value_t != value_s and dt > self.FOLLOW_REQUEST_WARNING:
125
-                    return self.__nagios_return__(self.MONITORING_FOLLOW_SETPOINT, nagios.Nagios.WARNING, "Requested setpoint %.1f°C unequal valve setpoint %.1f°C since %.1fmin" % (value_t, value_s, (time.time()-tm_s)))
126
-                return self.__nagios_return__(self.MONITORING_FOLLOW_SETPOINT, nagios.Nagios.OK, "Requested setpoint equal valve setpoint %.1f°C" % value_s)
121
+                    return self.__nagios_return__(DID_FOLLOWS_SETPOINT, nagios.Nagios.WARNING, "Requested setpoint %.1f°C unequal valve setpoint %.1f°C since %.1fmin" % (value_t, value_s, (time.time()-tm_s)))
122
+                return self.__nagios_return__(DID_FOLLOWS_SETPOINT, nagios.Nagios.OK, "Requested setpoint equal valve setpoint %.1f°C" % value_s)
127 123
         #
128 124
         # BATTERY
129 125
         #
130
-        elif key == self.MONITORING_BATTERY:
131
-            if self.battery is None:
132
-                return self.__nagios_return__(self.MONITORING_BATTERY, nagios.Nagios.UNKNOWN, "Device exists, but no data received or unknown monitoring")
133
-            elif self.battery <= self.BATTERY_LVL_ERROR:
134
-                return self.__nagios_return__(self.MONITORING_BATTERY, nagios.Nagios.ERROR, "Battery level critical low (%.1f%%)" % self.battery)
135
-            elif self.battery <= self.BATTERY_LVL_WARNING:
136
-                return self.__nagios_return__(self.MONITORING_BATTERY, nagios.Nagios.WARNING, "Battery level low (%.1f%%)" % self.battery)
126
+        elif key == DID_BATTERY_LEVEL:
127
+            battery_lvl = self.__state_storage__.get(self.KEY_BATTERY, (0, None))[1]
128
+            if battery_lvl is None:
129
+                return self.__nagios_return__(DID_BATTERY_LEVEL, nagios.Nagios.UNKNOWN, "Device exists, but no data received or unknown monitoring")
130
+            elif battery_lvl <= self.BATTERY_LVL_ERROR:
131
+                return self.__nagios_return__(DID_BATTERY_LEVEL, nagios.Nagios.ERROR, "Battery level critical low (%.1f%%)" % battery_lvl)
132
+            elif battery_lvl <= self.BATTERY_LVL_WARNING:
133
+                return self.__nagios_return__(DID_BATTERY_LEVEL, nagios.Nagios.WARNING, "Battery level low (%.1f%%)" % battery_lvl)
137 134
             else:
138
-                return self.__nagios_return__(self.MONITORING_BATTERY, nagios.Nagios.OK, "Battery okay (%.1f%%)" % self.battery)
135
+                return self.__nagios_return__(DID_BATTERY_LEVEL, nagios.Nagios.OK, "Battery okay (%.1f%%)" % battery_lvl)
139 136
         #
140 137
         # LINKQUALITY
141 138
         #
142
-        elif key == self.MONITORING_LINKQUALITY:
143
-            if self.linkquality is None:
144
-                return self.__nagios_return__(self.MONITORING_LINKQUALITY, nagios.Nagios.UNKNOWN, "Device exists, but no data received or unknown monitoring")
145
-            elif self.linkquality <= self.LINKQUALITY_ERROR:
146
-                return self.__nagios_return__(self.MONITORING_LINKQUALITY, nagios.Nagios.ERROR, "Linkquality critical low (%d)" % self.linkquality)
147
-            elif self.linkquality <= self.LINKQUALITY_WARNING:
148
-                return self.__nagios_return__(self.MONITORING_LINKQUALITY, nagios.Nagios.WARNING, "Linkquality level low (%d)" % self.linkquality)
139
+        elif key == DID_LINKQUALITY:
140
+            linkquality = self.__state_storage__.get(self.KEY_LINKQUALITY, (0, None))[1]
141
+            if linkquality is None:
142
+                return self.__nagios_return__(DID_LINKQUALITY, nagios.Nagios.UNKNOWN, "Device exists, but no data received or unknown monitoring")
143
+            elif linkquality <= self.LINKQUALITY_ERROR:
144
+                return self.__nagios_return__(DID_LINKQUALITY, nagios.Nagios.ERROR, "Linkquality critical low (%d)" % linkquality)
145
+            elif linkquality <= self.LINKQUALITY_WARNING:
146
+                return self.__nagios_return__(DID_LINKQUALITY, nagios.Nagios.WARNING, "Linkquality level low (%d)" % linkquality)
149 147
             else:
150
-                return self.__nagios_return__(self.MONITORING_LINKQUALITY, nagios.Nagios.OK, "Linkquality okay (%d)" % self.linkquality)
148
+                return self.__nagios_return__(DID_LINKQUALITY, nagios.Nagios.OK, "Linkquality okay (%d)" % linkquality)
151 149
 
152
-    def __nagios_return__(self, monitoring_name, status, msg, force=False):
150
+    def __nagios_return__(self, did, status, msg, force=False):
153 151
         tm = time.time()
154
-        if monitoring_name not in self.__unknown_tm__:
155
-            self.__unknown_tm__[monitoring_name] = None
152
+        if did not in self.__unknown_tm__:
153
+            self.__unknown_tm__[did] = None
156 154
         if status == nagios.Nagios.UNKNOWN and not force:
157
-            if self.__unknown_tm__[monitoring_name] is None:
158
-                self.__unknown_tm__[monitoring_name] = tm
159
-            dt = tm - self.__unknown_tm__[monitoring_name]
155
+            if self.__unknown_tm__[did] is None:
156
+                self.__unknown_tm__[did] = tm
157
+            dt = tm - self.__unknown_tm__[did]
160 158
             if dt >= self.LAST_MSG_ERROR:
161 159
                 status = nagios.Nagios.UNKNOWN
162 160
             elif dt >= self.LAST_MSG_WARNING:
@@ -165,7 +163,7 @@ class base(object):
165 163
                 status = nagios.Nagios.OK
166 164
             msg += " - since %.1fh" % (dt / 3600)
167 165
         else:
168
-            self.__unknown_tm__[monitoring_name] = None
166
+            self.__unknown_tm__[did] = None
169 167
         return {"status": status, "msg": msg}
170 168
 
171 169
 
@@ -202,7 +200,33 @@ class livarno_sw_br_ct(base):
202 200
 class brennenstuhl_heatingvalve(base):
203 201
     BATTERY_LVL_WARNING = 4
204 202
     BATTERY_LVL_ERROR = 3
205
-    FOLLOW_KEY = "current_heating_setpoint"
203
+    #
204
+    ACTOR_WARN_OFFSET = 1.5
205
+    ACTOR_ERR_OFFSET = 2.5
206
+    #
207
+    KEY_SETPOINT = "current_heating_setpoint"
208
+    KEY_CURRENT_VALUE = "local_temperature"
209
+
210
+    def status(self, key):
211
+        #
212
+        # ACTOR
213
+        #
214
+        if key == DID_ACTOR:
215
+            tm_s, value_s = self.__state_storage__.get(self.KEY_SETPOINT, (0, None))
216
+            tm_c, value_c = self.__state_storage__.get(self.KEY_CURRENT_VALUE, (0, None))
217
+            #
218
+            if value_s is None or value_c is None:
219
+                return self.__nagios_return__(DID_ACTOR, nagios.Nagios.UNKNOWN, "Device exists, but no data received")
220
+            elif value_s <= 5:
221
+                return self.__nagios_return__(DID_ACTOR, nagios.Nagios.OK, "No monitoring in Summer Mode")
222
+            elif value_c > value_s + self.ACTOR_ERR_OFFSET:
223
+                return self.__nagios_return__(DID_ACTOR, nagios.Nagios.ERROR, "Current Temperature much to high %.1f°C > %.1f°C" % (value_c, value_s))
224
+            elif value_c > value_s + self.ACTOR_WARN_OFFSET:
225
+                return self.__nagios_return__(DID_ACTOR, nagios.Nagios.WARNING, "Current Temperature to high %.1f°C > %.1f°C" % (value_c, value_s))
226
+            else:
227
+                return self.__nagios_return__(DID_ACTOR, nagios.Nagios.OK, "Current Temperature okay %.1f°C > %.1f°C" % (value_c, value_s))
228
+        else:
229
+            return super().status(key)
206 230
 
207 231
 
208 232
 class silvercrest_powerplug(base):

+ 1
- 1
z_server/mqtt

@@ -1 +1 @@
1
-Subproject commit 328d3471a748472695a61193becdda76c7eefe69
1
+Subproject commit 14e56ccdbf6594f699b4afcfb4acafe9b899e914

+ 12
- 5
z_server/z_protocol.py Целия файл

@@ -2,10 +2,19 @@ import nagios
2 2
 import socket_protocol
3 3
 # from devdi.topic import topic_by_props
4 4
 
5
-DID_FOLLOWS_SETPOINT = 'follow_setpoint'
5
+DID_ACTOR = 'actor'
6 6
 DID_BATTERY_LEVEL = 'battery'
7
+DID_FOLLOWS_SETPOINT = 'follow'
7 8
 DID_HEARTBEAT = 'heartbeat'
8 9
 DID_LINKQUALITY = 'linkquality'
10
+#
11
+DIDS = (
12
+    DID_ACTOR,
13
+    DID_BATTERY_LEVEL,
14
+    DID_FOLLOWS_SETPOINT,
15
+    DID_HEARTBEAT,
16
+    DID_LINKQUALITY
17
+)
9 18
 
10 19
 
11 20
 class server(socket_protocol.pure_json_protocol):
@@ -15,10 +24,8 @@ class server(socket_protocol.pure_json_protocol):
15 24
         socket_protocol.pure_json_protocol.__init__(self, *args, **kwargs)
16 25
         #
17 26
         if not self.__comm_inst__.IS_CLIENT:
18
-            self.register_callback(socket_protocol.SID_READ_REQUEST, DID_FOLLOWS_SETPOINT, self.device_status)
19
-            self.register_callback(socket_protocol.SID_READ_REQUEST, DID_BATTERY_LEVEL, self.device_status)
20
-            self.register_callback(socket_protocol.SID_READ_REQUEST, DID_LINKQUALITY, self.device_status)
21
-            self.register_callback(socket_protocol.SID_READ_REQUEST, DID_HEARTBEAT, self.device_status)
27
+            for did in DIDS:
28
+                self.register_callback(socket_protocol.SID_READ_REQUEST, did, self.device_status)
22 29
 
23 30
     def device_status(self, msg):
24 31
         if msg.get_status() == socket_protocol.STATUS_OKAY:

Loading…
Отказ
Запис