119 lines
4.6 KiB
Python
Raw Normal View History

2023-10-29 15:10:06 +01:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
from base import mqtt_base
from base import videv_base
import json
2023-10-29 15:45:14 +01:00
import time
2023-10-29 15:10:06 +01:00
def is_json(data):
try:
json.loads(data)
except json.decoder.JSONDecodeError:
return False
else:
return True
class base(mqtt_base):
TX_TOPIC = "set"
TX_VALUE = 0
TX_DICT = 1
TX_TYPE = -1
TX_FILTER_DATA_KEYS = []
#
RX_KEYS = []
RX_IGNORE_TOPICS = []
RX_IGNORE_KEYS = []
RX_FILTER_DATA_KEYS = []
#
CFG_DATA = {}
2023-10-29 15:10:06 +01:00
def __init__(self, mqtt_client, topic):
2023-12-24 08:40:46 +01:00
super().__init__(mqtt_client, topic, default_values=dict.fromkeys(self.RX_KEYS))
2023-10-29 15:10:06 +01:00
# data storage
2024-05-27 11:40:35 +02:00
self.__cfg_by_mid__ = None
2023-10-29 15:10:06 +01:00
# initialisations
mqtt_client.add_callback(topic=self.topic, callback=self.receive_callback)
mqtt_client.add_callback(topic=self.topic+"/#", callback=self.receive_callback)
#
self.add_callback(None, None, self.__state_logging__, on_change_only=True)
2023-10-29 15:10:06 +01:00
2024-05-27 11:40:35 +02:00
def __cfg_callback__(self, key, value, mid):
if self.CFG_DATA.get(key) != value and self.__cfg_by_mid__ != mid and mid is not None:
self.__cfg_by_mid__ = mid
self.logger.warning("Differing configuration identified: Sending default configuration to defice: %s", repr(self.CFG_DATA))
if self.TX_TYPE == self.TX_DICT:
self.mqtt_client.send(self.topic + '/' + self.TX_TOPIC, json.dumps(self.CFG_DATA))
else:
for key in self.CFG_DATA:
self.send_command(key, self.CFG_DATA.get(key))
2024-05-27 11:40:35 +02:00
def set(self, key, data, mid=None, block_callback=[]):
if key in self.CFG_DATA:
2024-05-27 11:40:35 +02:00
self.__cfg_callback__(key, data, mid)
2023-10-29 15:10:06 +01:00
if key in self.RX_IGNORE_KEYS:
pass # ignore these keys
2023-12-24 08:40:46 +01:00
elif key in self.RX_KEYS:
2023-10-29 15:10:06 +01:00
return super().set(key, data, block_callback)
else:
self.logger.warning("Unexpected key %s", key)
def receive_callback(self, client, userdata, message):
if message.topic != self.topic + '/' + videv_base.KEY_INFO:
content_key = message.topic[len(self.topic) + 1:]
if content_key not in self.RX_IGNORE_TOPICS and (not message.topic.endswith(self.TX_TOPIC) or len(self.TX_TOPIC) == 0):
self.logger.debug("Unpacking content_key \"%s\" from message.", content_key)
if is_json(message.payload):
data = json.loads(message.payload)
if type(data) is dict:
for key in data:
2024-05-27 11:40:35 +02:00
self.set(key, self.__device_to_instance_filter__(key, data[key]), message.mid)
2023-10-29 15:10:06 +01:00
else:
2024-05-27 11:40:35 +02:00
self.set(content_key, self.__device_to_instance_filter__(content_key, data), message.mid)
2023-10-29 15:10:06 +01:00
# String
else:
2024-05-27 11:40:35 +02:00
self.set(content_key, self.__device_to_instance_filter__(content_key, message.payload.decode('utf-8')), message.mid)
2023-10-29 15:10:06 +01:00
else:
self.logger.debug("Ignoring topic %s", content_key)
def __device_to_instance_filter__(self, key, data):
if key in self.RX_FILTER_DATA_KEYS:
if data in [1, 'on', 'ON']:
return True
elif data in [0, 'off', 'OFF']:
return False
return data
def __instance_to_device_filter__(self, key, data):
if key in self.TX_FILTER_DATA_KEYS:
if data is True:
return "on"
elif data is False:
return "off"
return data
def send_command(self, key, data):
data = self.__instance_to_device_filter__(key, data)
if self.TX_TOPIC is not None:
if self.TX_TYPE < 0:
self.logger.error("Unknown tx type. Set TX_TYPE of class to a known value")
else:
self.logger.debug("Sending data for %s - %s", key, str(data))
if self.TX_TYPE == self.TX_DICT:
try:
self.mqtt_client.send('/'.join([self.topic, self.TX_TOPIC]), json.dumps({key: data}))
except TypeError:
print(self.topic)
print(key.__dict__)
print(key)
print(data)
raise TypeError
else:
if type(data) not in [str, bytes]:
data = json.dumps(data)
self.mqtt_client.send('/'.join([self.topic, key, self.TX_TOPIC] if len(self.TX_TOPIC) > 0 else [self.topic, key]), data)
else:
self.logger.error("Unknown tx toptic. Set TX_TOPIC of class to a known value")