176 lines
5.7 KiB
Python
Raw Normal View History

import json
import logging
import mqtt
import nagios
import time
try:
from config import APP_NAME as ROOT_LOGGER_NAME
except ImportError:
ROOT_LOGGER_NAME = 'root'
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", ]
#
BATTERY_LVL_WARNING = 20
BATTERY_LVL_ERROR = 10
#
LAST_MSG_WARNING = 6 * 24 * 60 * 60
LAST_MSG_ERROR = 24 * 24 * 60 * 60
def __init__(self, mqtt_client: mqtt.mqtt_client, topic):
self.topic = topic
#
mqtt_client.add_callback(topic, self.__rx__)
mqtt_client.add_callback(topic + '/#', self.__rx__)
#
self.last_device_msg = None
#
self.__target_storage__ = {}
self.__state_storage__ = {}
#
self.battery = None
def __rx__(self, client, userdata, message):
pass
def target(self, key, value):
tm_t, value_t = self.__target_storage__.get(key, (0, None))
if value != value_t:
self.__target_storage__[key] = time.time(), value
logger.debug("Target value for device identified: %s: %s", key, repr(value))
def state(self, key, value):
2023-12-14 18:16:15 +01:00
self.__state_storage__[key] = time.time(), value
logger.debug("Device state identified: %s: %s", key, repr(value))
def status(self, key):
#
# HEARTBEAT
#
if key == "heartbeat":
if self.last_device_msg is None:
return {"status": nagios.Nagios.UNKNOWN, "msg": "Device exists, but no data received or unknown monitoring"}
else:
dt = time.time() - self.last_device_msg
dt_disp = dt / 60 / 60
if dt > self.LAST_MSG_ERROR:
return {"status": nagios.Nagios.ERROR, "msg": "Last message %.1fh ago" % dt_disp}
elif dt > self.LAST_MSG_WARNING:
return {"status": nagios.Nagios.WARNING, "msg": "Last message %.1fh ago" % dt_disp}
else:
return {"status": nagios.Nagios.OK, "msg": "Last message %.1fh ago" % dt_disp}
#
# FOLLOW SETPOINT
#
elif key in self.FOLLOW_KEYS:
tm_s, value_s = self.__state_storage__.get(key, (0, None))
try:
tm_t, value_t = self.__target_storage__[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"}
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)}
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):
def __init__(self, *args, **kwargs):
pass
class shelly_sw1(base):
pass
class tradfri_sw(base):
pass
class tradfri_sw_br(base):
pass
class tradfri_sw_br_ct(base):
pass
class tradfri_button(base):
pass
class livarno_sw_br_ct(base):
pass
class brennenstuhl_heatingvalve(base):
BATTERY_LVL_WARNING = 10
BATTERY_LVL_ERROR = 5
def __init__(self, mqtt_client: mqtt.mqtt_client, topic):
base.__init__(self, mqtt_client, topic)
def __rx__(self, client, userdata, message):
payload = json.loads(message.payload)
#
# heartbeat
2023-12-16 08:22:38 +01:00
#
if message.topic == self.topic:
self.last_device_msg = time.time()
#
# follow setpoint
#
2023-12-15 19:58:54 +01:00
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"]
class silvercrest_powerplug(base):
pass
class silvercrest_motion_sensor(base):
pass
class my_powerplug(base):
pass
class audio_status(base):
pass
class remote(base):
pass