Zigbee heating valve follow check improved, battery check added

This commit is contained in:
Dirk Alders 2023-12-16 07:12:29 +01:00
parent 4fb01e2f93
commit 33042e3f3c
4 changed files with 54 additions and 20 deletions

1
check_z_heat_vlv_battery Symbolic link
View File

@ -0,0 +1 @@
check_z_heat_vlv_follow

View File

@ -7,7 +7,7 @@ import time
from z_server import config from z_server import config
from z_server import tcp_socket from z_server import tcp_socket
from z_server.z_protocol import server as client_prot from z_server.z_protocol import server as client_prot
from z_server.z_protocol import DID_FOLLOWS_HEATING_SETPOINT from z_server.z_protocol import DID_FOLLOWS_HEATING_SETPOINT, DID_BATTERY_LEVEL
from z_server import socket_protocol from z_server import socket_protocol
import sys import sys
@ -30,7 +30,14 @@ if __name__ == '__main__':
"roo": args.roo, "roo": args.roo,
"fun": "FUN_HEA" # <-- Const, because script is for heat_vlv only "fun": "FUN_HEA" # <-- Const, because script is for heat_vlv only
} }
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() if 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'):
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) nagios.Nagios().exit(**sp_data)

View File

@ -14,6 +14,10 @@ logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
class base(object): class base(object):
FOLLOW_REQUEST_WARNING = 5 # Seconds, till warning comes up, if device does not follow the command 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_REQUEST_ERROR = 60 # Seconds, till error comes up, if device does not follow the command
FOLLOW_KEYS = ["current_heating_setpoint", ]
#
BATTERY_LVL_WARNING = 10
BATTERY_LVL_ERROR = 5
def __init__(self, mqtt_client: mqtt.mqtt_client, topic): def __init__(self, mqtt_client: mqtt.mqtt_client, topic):
self.topic = topic self.topic = topic
@ -23,6 +27,8 @@ class base(object):
# #
self.__target_storage__ = {} self.__target_storage__ = {}
self.__state_storage__ = {} self.__state_storage__ = {}
#
self.battery = None
def __rx__(self, client, userdata, message): def __rx__(self, client, userdata, message):
pass pass
@ -38,21 +44,37 @@ class base(object):
logger.debug("Device state identified: %s: %s", key, repr(value)) logger.debug("Device state identified: %s: %s", key, repr(value))
def status(self, key): def status(self, key):
tm_s, value_s = self.__state_storage__.get(key, (0, None)) #
try: # FOLLOW SETPOINT
tm_t, value_t = self.__target_storage__[key] #
except KeyError: if key in self.FOLLOW_KEYS:
if value_s is not None: tm_s, value_s = self.__state_storage__.get(key, (0, 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)} try:
return {"status": nagios.Nagios.UNKNOWN, "msg": "Device exists, but no data received or unknown monitoring"} tm_t, value_t = self.__target_storage__[key]
else: except KeyError:
tm = time.time() if value_s is not None:
dt = tm - tm_t return {"status": nagios.Nagios.WARNING, "msg": "Current temperature setpoint %.1f°C (age=%.1fs), but never received a setpoint" % (value_s, time.time()-tm_s)}
if value_t != value_s and dt > self.FOLLOW_REQUEST_ERROR: return {"status": nagios.Nagios.UNKNOWN, "msg": "Device exists, but no data received or unknown monitoring"}
return {"status": nagios.Nagios.ERROR, "msg": "Requested setpoint unequal valve setpoint since %.1fs" % dt} else:
elif value_t != value_s and dt > self.FOLLOW_REQUEST_WARNING: tm = time.time()
return {"status": nagios.Nagios.WARNING, "msg": "Requested setpoint unequal valve setpoint since %.1fs" % dt} dt = tm - tm_t
return {"status": nagios.Nagios.OK, "msg": "Requested setpoint equal valve setpoint"} 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)}
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)}
#
# BATTERY
#
elif key == "battery":
if self.battery is None:
return {"status": nagios.Nagios.UNKNOWN, "msg": "Device exists, but no data received or unknown monitoring"}
elif self.battery < self.BATTERY_LVL_ERROR:
return {"status": nagios.Nagios.ERROR, "msg": "Battery level critical low (%.1f%%)" % self.battery}
elif self.battery < self.BATTERY_LVL_WARNING:
return {"status": nagios.Nagios.WARNING, "msg": "Battery level low (%.1f%%)" % self.battery}
else:
return {"status": nagios.Nagios.OK, "msg": "Battery okay (%.1f%%)" % self.battery}
class group(object): class group(object):
@ -95,6 +117,8 @@ class brennenstuhl_heatingvalve(base):
self.target("current_heating_setpoint", payload["current_heating_setpoint"]) self.target("current_heating_setpoint", payload["current_heating_setpoint"])
if message.topic == self.topic: if message.topic == self.topic:
self.state("current_heating_setpoint", payload["current_heating_setpoint"]) self.state("current_heating_setpoint", payload["current_heating_setpoint"])
if "battery" in payload and message.topic == self.topic:
self.battery = payload["battery"]
class silvercrest_powerplug(base): class silvercrest_powerplug(base):

View File

@ -3,6 +3,7 @@ import socket_protocol
# from devdi.topic import topic_by_props # from devdi.topic import topic_by_props
DID_FOLLOWS_HEATING_SETPOINT = 'current_heating_setpoint' DID_FOLLOWS_HEATING_SETPOINT = 'current_heating_setpoint'
DID_BATTERY_LEVEL = 'battery'
class server(socket_protocol.pure_json_protocol): class server(socket_protocol.pure_json_protocol):
@ -15,9 +16,10 @@ class server(socket_protocol.pure_json_protocol):
# DID_FOLLOWS_HEATING_SETPOINT, 'current_heating_setpoint') # DID_FOLLOWS_HEATING_SETPOINT, 'current_heating_setpoint')
# #
if not self.__comm_inst__.IS_CLIENT: if not self.__comm_inst__.IS_CLIENT:
self.register_callback(socket_protocol.SID_READ_REQUEST, DID_FOLLOWS_HEATING_SETPOINT, self.follow_heating_setpoint) self.register_callback(socket_protocol.SID_READ_REQUEST, DID_FOLLOWS_HEATING_SETPOINT, self.device_status)
self.register_callback(socket_protocol.SID_READ_REQUEST, DID_BATTERY_LEVEL, self.device_status)
def follow_heating_setpoint(self, msg): def device_status(self, msg):
if msg.get_status() == socket_protocol.STATUS_OKAY: if msg.get_status() == socket_protocol.STATUS_OKAY:
try: try:
dev = self.__devices__.get_str(**msg.get_data()) dev = self.__devices__.get_str(**msg.get_data())