From 149cf7cdeb4c90340ffb04ef2e5995dcce3d02b0 Mon Sep 17 00:00:00 2001 From: Dirk Alders Date: Wed, 20 Dec 2023 07:26:39 +0100 Subject: [PATCH] zigbee stuff restructured --- check_z_battery | 1 + check_z_follow | 1 + check_z_heat_vlv_follow => check_z_heartbeat | 15 +-- check_z_heat_vlv_battery | 1 - check_z_heat_vlv_heartbeat | 1 - check_z_motion_battery | 1 - check_z_motion_heartbeat | 43 -------- check_z_tr_inp_battery | 1 - check_z_tr_inp_heartbeat | 43 -------- z_server/devices/__init__.py | 105 +++++++------------ z_server/z_protocol.py | 9 +- 11 files changed, 51 insertions(+), 170 deletions(-) create mode 120000 check_z_battery create mode 120000 check_z_follow rename check_z_heat_vlv_follow => check_z_heartbeat (74%) delete mode 120000 check_z_heat_vlv_battery delete mode 120000 check_z_heat_vlv_heartbeat delete mode 120000 check_z_motion_battery delete mode 100755 check_z_motion_heartbeat delete mode 120000 check_z_tr_inp_battery delete mode 100755 check_z_tr_inp_heartbeat diff --git a/check_z_battery b/check_z_battery new file mode 120000 index 0000000..e32a613 --- /dev/null +++ b/check_z_battery @@ -0,0 +1 @@ +check_z_heartbeat \ No newline at end of file diff --git a/check_z_follow b/check_z_follow new file mode 120000 index 0000000..e32a613 --- /dev/null +++ b/check_z_follow @@ -0,0 +1 @@ +check_z_heartbeat \ No newline at end of file diff --git a/check_z_heat_vlv_follow b/check_z_heartbeat similarity index 74% rename from check_z_heat_vlv_follow rename to check_z_heartbeat index d23f49b..f2d97c1 100755 --- a/check_z_heat_vlv_follow +++ b/check_z_heartbeat @@ -7,7 +7,7 @@ import time from z_server import config from z_server import tcp_socket from z_server.z_protocol import server as client_prot -from z_server.z_protocol import DID_FOLLOWS_HEATING_SETPOINT, DID_BATTERY_LEVEL, DID_HEARTBEAT +from z_server.z_protocol import DID_FOLLOWS_SETPOINT, DID_BATTERY_LEVEL, DID_HEARTBEAT from z_server import socket_protocol import sys @@ -19,6 +19,7 @@ if __name__ == '__main__': parser.add_argument('-s', '--stg', required=True) parser.add_argument('-l', '--loc', required=True) parser.add_argument('-r', '--roo', required=True) + parser.add_argument('-f', '--fun', required=True) args = parser.parse_args() # c = tcp_socket.tcp_client_stp('127.0.0.1', config.SOCK_PROT_PORT) @@ -28,18 +29,18 @@ if __name__ == '__main__': "stg": args.stg, "loc": args.loc, "roo": args.roo, - "fun": "FUN_HEA" # <-- Const, because script is for heat_vlv only + "fun": args.fun } # - if sys.argv[0].endswith('check_z_heat_vlv_heartbeat'): + if sys.argv[0].endswith('check_z_heartbeat'): sp.send(socket_protocol.SID_READ_REQUEST, DID_HEARTBEAT, data) sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_HEARTBEAT).get_data() - elif sys.argv[0].endswith('check_z_heat_vlv_follow'): - sp.send(socket_protocol.SID_READ_REQUEST, DID_FOLLOWS_HEATING_SETPOINT, data) - sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_FOLLOWS_HEATING_SETPOINT).get_data() - elif sys.argv[0].endswith('check_z_heat_vlv_battery'): + elif sys.argv[0].endswith('check_z_battery'): sp.send(socket_protocol.SID_READ_REQUEST, DID_BATTERY_LEVEL, data) sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_BATTERY_LEVEL).get_data() + elif sys.argv[0].endswith('check_z_follow'): + sp.send(socket_protocol.SID_READ_REQUEST, DID_FOLLOWS_SETPOINT, data) + sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_FOLLOWS_SETPOINT).get_data() else: sys.stderr.write('No action for command called "%s"\n' % sys.argv[0]) sys.exit(100) diff --git a/check_z_heat_vlv_battery b/check_z_heat_vlv_battery deleted file mode 120000 index 06aac91..0000000 --- a/check_z_heat_vlv_battery +++ /dev/null @@ -1 +0,0 @@ -check_z_heat_vlv_follow \ No newline at end of file diff --git a/check_z_heat_vlv_heartbeat b/check_z_heat_vlv_heartbeat deleted file mode 120000 index 06aac91..0000000 --- a/check_z_heat_vlv_heartbeat +++ /dev/null @@ -1 +0,0 @@ -check_z_heat_vlv_follow \ No newline at end of file diff --git a/check_z_motion_battery b/check_z_motion_battery deleted file mode 120000 index f846099..0000000 --- a/check_z_motion_battery +++ /dev/null @@ -1 +0,0 @@ -check_z_motion_heartbeat \ No newline at end of file diff --git a/check_z_motion_heartbeat b/check_z_motion_heartbeat deleted file mode 100755 index fc883c1..0000000 --- a/check_z_motion_heartbeat +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/python3 -# - -import argparse -import nagios -import time -from z_server import config -from z_server import tcp_socket -from z_server.z_protocol import server as client_prot -from z_server.z_protocol import DID_FOLLOWS_HEATING_SETPOINT, DID_BATTERY_LEVEL, DID_HEARTBEAT -from z_server import socket_protocol -import sys - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - prog='ProgramName', - description='What the program does', - epilog='Text at the bottom of help') - parser.add_argument('-s', '--stg', required=True) - parser.add_argument('-l', '--loc', required=True) - parser.add_argument('-r', '--roo', required=True) - args = parser.parse_args() - # - c = tcp_socket.tcp_client_stp('127.0.0.1', config.SOCK_PROT_PORT) - sp = client_prot(c, channel_name='example_client') - # - data = { - "stg": args.stg, - "loc": args.loc, - "roo": args.roo, - "fun": "FUN_MSE" # <-- Const, because script is for input_device - } - # - if sys.argv[0].endswith('check_z_motion_heartbeat'): - sp.send(socket_protocol.SID_READ_REQUEST, DID_HEARTBEAT, data) - sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_HEARTBEAT).get_data() - elif sys.argv[0].endswith('check_z_motion_battery'): - sp.send(socket_protocol.SID_READ_REQUEST, DID_BATTERY_LEVEL, data) - sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_BATTERY_LEVEL).get_data() - else: - sys.stderr.write('No action for command called "%s"\n' % sys.argv[0]) - sys.exit(100) - nagios.Nagios().exit(**sp_data) diff --git a/check_z_tr_inp_battery b/check_z_tr_inp_battery deleted file mode 120000 index 7bc679d..0000000 --- a/check_z_tr_inp_battery +++ /dev/null @@ -1 +0,0 @@ -check_z_tr_inp_heartbeat \ No newline at end of file diff --git a/check_z_tr_inp_heartbeat b/check_z_tr_inp_heartbeat deleted file mode 100755 index e0b64d2..0000000 --- a/check_z_tr_inp_heartbeat +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/python3 -# - -import argparse -import nagios -import time -from z_server import config -from z_server import tcp_socket -from z_server.z_protocol import server as client_prot -from z_server.z_protocol import DID_FOLLOWS_HEATING_SETPOINT, DID_BATTERY_LEVEL, DID_HEARTBEAT -from z_server import socket_protocol -import sys - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - prog='ProgramName', - description='What the program does', - epilog='Text at the bottom of help') - parser.add_argument('-s', '--stg', required=True) - parser.add_argument('-l', '--loc', required=True) - parser.add_argument('-r', '--roo', required=True) - args = parser.parse_args() - # - c = tcp_socket.tcp_client_stp('127.0.0.1', config.SOCK_PROT_PORT) - sp = client_prot(c, channel_name='example_client') - # - data = { - "stg": args.stg, - "loc": args.loc, - "roo": args.roo, - "fun": "FUN_INP" # <-- Const, because script is for input_device - } - # - if sys.argv[0].endswith('check_z_tr_inp_heartbeat'): - sp.send(socket_protocol.SID_READ_REQUEST, DID_HEARTBEAT, data) - sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_HEARTBEAT).get_data() - elif sys.argv[0].endswith('check_z_tr_inp_battery'): - sp.send(socket_protocol.SID_READ_REQUEST, DID_BATTERY_LEVEL, data) - sp_data = sp.receive(socket_protocol.SID_READ_RESPONSE, DID_BATTERY_LEVEL).get_data() - else: - sys.stderr.write('No action for command called "%s"\n' % sys.argv[0]) - sys.exit(100) - nagios.Nagios().exit(**sp_data) diff --git a/z_server/devices/__init__.py b/z_server/devices/__init__.py index 44189ae..0b99e8d 100644 --- a/z_server/devices/__init__.py +++ b/z_server/devices/__init__.py @@ -14,7 +14,7 @@ logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__) class base(object): FOLLOW_REQUEST_WARNING = 5 # Seconds, till warning comes up, if device does not follow the command FOLLOW_REQUEST_ERROR = 60 # Seconds, till error comes up, if device does not follow the command - FOLLOW_KEYS = ["current_heating_setpoint", ] + FOLLOW_KEY = None # BATTERY_LVL_WARNING = 15 BATTERY_LVL_ERROR = 5 @@ -36,7 +36,30 @@ class base(object): self.battery = None def __rx__(self, client, userdata, message): - pass + try: + payload = json.loads(message.payload) + except json.decoder.JSONDecodeError: + pass + else: + if type(payload) is dict: + # + # heartbeat + # + if message.topic == self.topic: + self.last_device_msg = time.time() + # + # follow setpoint + # + if self.FOLLOW_KEY is not None and self.FOLLOW_KEY in payload: + if message.topic == self.topic + '/set': + self.target(self.FOLLOW_KEY, payload[self.FOLLOW_KEY]) + if message.topic == self.topic: + self.state(self.FOLLOW_KEY, payload[self.FOLLOW_KEY]) + # + # battery level + # + if "battery" in payload and message.topic == self.topic: + self.battery = payload["battery"] def target(self, key, value): tm_t, value_t = self.__target_storage__.get(key, (0, None)) @@ -67,22 +90,24 @@ class base(object): # # FOLLOW SETPOINT # - elif key in self.FOLLOW_KEYS: - tm_s, value_s = self.__state_storage__.get(key, (0, None)) + elif key == 'follow_setpoint': + if self.FOLLOW_KEY is None: + return {"status": nagios.Nagios.UNKNOWN, "msg": "Device exist, but does not follow any setpoint."} + tm_s, value_s = self.__state_storage__.get(self.FOLLOW_KEY, (0, None)) try: - tm_t, value_t = self.__target_storage__[key] + tm_t, value_t = self.__target_storage__[self.FOLLOW_KEY] except KeyError: if value_s is not None: - return {"status": nagios.Nagios.WARNING, "msg": "Current temperature setpoint %.1f°C (age=%.1fs), but never received a setpoint" % (value_s, time.time()-tm_s)} - return {"status": nagios.Nagios.UNKNOWN, "msg": "Device exists, but no data received or unknown monitoring"} + return {"status": nagios.Nagios.WARNING, "msg": "Current temperature setpoint %.1f°C (age=%.1fmin), but never received a setpoint" % (value_s, (time.time()-tm_s)/60)} + return {"status": nagios.Nagios.UNKNOWN, "msg": "Device exists, but no data received"} else: tm = time.time() dt = tm - tm_t if value_t != value_s and dt > self.FOLLOW_REQUEST_ERROR: - return {"status": nagios.Nagios.ERROR, "msg": "Requested setpoint unequal valve setpoint since %.1f°C (age=%.1fs)" % (value_s, time.time()-tm_s)} + return {"status": nagios.Nagios.ERROR, "msg": "Requested setpoint unequal valve setpoint %.1f°C since %.1fmin" % (value_s, (time.time()-tm_s)/60)} elif value_t != value_s and dt > self.FOLLOW_REQUEST_WARNING: - return {"status": nagios.Nagios.WARNING, "msg": "Requested setpoint unequal valve setpoint since %.1f°C (age=%.1fs)" % (value_s, time.time()-tm_s)} - return {"status": nagios.Nagios.OK, "msg": "Requested setpoint equal valve setpoint %.1f°C (age=%.1fs)" % (value_s, time.time()-tm_s)} + return {"status": nagios.Nagios.WARNING, "msg": "Requested setpoint unequal valve setpoint %.1f°C since %.1fmin" % (value_s, (time.time()-tm_s))} + return {"status": nagios.Nagios.OK, "msg": "Requested setpoint equal valve setpoint %.1f°C" % value_s} # # BATTERY # @@ -119,22 +144,7 @@ class tradfri_sw_br_ct(base): class tradfri_button(base): - def __rx__(self, client, userdata, message): - try: - payload = json.loads(message.payload) - except json.decoder.JSONDecodeError: - logger.warning("JSON decode error %s", self.topic) - else: - # - # heartbeat - # - if message.topic == self.topic: - self.last_device_msg = time.time() - # - # battery level - # - if "battery" in payload and message.topic == self.topic: - self.battery = payload["battery"] + pass class livarno_sw_br_ct(base): @@ -144,31 +154,7 @@ class livarno_sw_br_ct(base): class brennenstuhl_heatingvalve(base): BATTERY_LVL_WARNING = 4 BATTERY_LVL_ERROR = 3 - - def __rx__(self, client, userdata, message): - try: - payload = json.loads(message.payload) - except json.decoder.JSONDecodeError: - logger.warning("JSON decode error %s", self.topic) - else: - # - # heartbeat - # - if message.topic == self.topic: - self.last_device_msg = time.time() - # - # follow setpoint - # - if "current_heating_setpoint" in payload: - if message.topic == self.topic + '/set': - self.target("current_heating_setpoint", payload["current_heating_setpoint"]) - if message.topic == self.topic: - self.state("current_heating_setpoint", payload["current_heating_setpoint"]) - # - # battery level - # - if "battery" in payload and message.topic == self.topic: - self.battery = payload["battery"] + FOLLOW_KEY = "current_heating_setpoint" class silvercrest_powerplug(base): @@ -176,22 +162,7 @@ class silvercrest_powerplug(base): class silvercrest_motion_sensor(base): - def __rx__(self, client, userdata, message): - try: - payload = json.loads(message.payload) - except json.decoder.JSONDecodeError: - logger.warning("JSON decode error %s", self.topic) - else: - # - # heartbeat - # - if message.topic == self.topic: - self.last_device_msg = time.time() - # - # battery level - # - if "battery" in payload and message.topic == self.topic: - self.battery = payload["battery"] + pass class my_powerplug(base): diff --git a/z_server/z_protocol.py b/z_server/z_protocol.py index a2d9328..940193b 100644 --- a/z_server/z_protocol.py +++ b/z_server/z_protocol.py @@ -2,7 +2,7 @@ import nagios import socket_protocol # from devdi.topic import topic_by_props -DID_FOLLOWS_HEATING_SETPOINT = 'current_heating_setpoint' +DID_FOLLOWS_SETPOINT = 'follow_setpoint' DID_BATTERY_LEVEL = 'battery' DID_HEARTBEAT = 'heartbeat' @@ -13,11 +13,8 @@ class server(socket_protocol.pure_json_protocol): self.__devices__ = kwargs.pop('devices') socket_protocol.pure_json_protocol.__init__(self, *args, **kwargs) # - # self.add_data((socket_protocol.SID_READ_REQUEST, socket_protocol.SID_READ_RESPONSE), - # DID_FOLLOWS_HEATING_SETPOINT, 'current_heating_setpoint') - # if not self.__comm_inst__.IS_CLIENT: - self.register_callback(socket_protocol.SID_READ_REQUEST, DID_FOLLOWS_HEATING_SETPOINT, self.device_status) + self.register_callback(socket_protocol.SID_READ_REQUEST, DID_FOLLOWS_SETPOINT, self.device_status) self.register_callback(socket_protocol.SID_READ_REQUEST, DID_BATTERY_LEVEL, self.device_status) self.register_callback(socket_protocol.SID_READ_REQUEST, DID_HEARTBEAT, self.device_status) @@ -26,7 +23,7 @@ class server(socket_protocol.pure_json_protocol): try: dev = self.__devices__.get_str(**msg.get_data()) except: - return socket_protocol.STATUS_CALLBACK_ERROR, {"status": nagios.Nagios.UNKNOWN, "msg": "Exception while getting device."} + return socket_protocol.STATUS_CALLBACK_ERROR, {"status": nagios.Nagios.UNKNOWN, "msg": "Device does not exist."} if dev is None: return socket_protocol.STATUS_SERVICE_OR_DATA_UNKNOWN, {"status": nagios.Nagios.UNKNOWN, "msg": "Device does not exist."} else: