123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- #
- from base import mqtt_base
- from base import videv_base
- import json
- import time
-
- BATTERY_WARN_LEVEL = 10
-
-
- 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 = []
- #
- KEY_WARNING = '__WARNING__'
-
- def __init__(self, mqtt_client, topic):
- super().__init__(mqtt_client, topic, default_values=dict.fromkeys(self.RX_KEYS + [self.KEY_WARNING]))
- # data storage
- # initialisations
- mqtt_client.add_callback(topic=self.topic, callback=self.receive_callback)
- mqtt_client.add_callback(topic=self.topic+"/#", callback=self.receive_callback)
-
- def set(self, key, data, block_callback=[]):
- if key in self.RX_IGNORE_KEYS:
- pass # ignore these keys
- elif key in self.RX_KEYS or key == self.KEY_WARNING:
- 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:
- self.set(key, self.__device_to_instance_filter__(key, data[key]))
- else:
- self.set(content_key, self.__device_to_instance_filter__(content_key, data))
- # String
- else:
- self.set(content_key, self.__device_to_instance_filter__(content_key, message.payload.decode('utf-8')))
- 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")
-
-
- class warning(dict):
- TYPE_BATTERY_LOW = 1
- TYPE_OVERTEMPERATURE = 2
- #
- KEY_ID = 'id'
- KEY_TYPE = 'type'
- KEY_TEXT = 'text'
- KEY_TM = 'tm'
-
- def __init__(self, identification, type, text, args):
- super().__init__({
- self.KEY_ID: identification,
- self.KEY_TYPE: type,
- self.KEY_TEXT: text % args,
- self.KEY_TM: time.localtime(),
- })
-
- def __str__(self):
- return time.asctime(self.get(self.KEY_TM)) + ": " + self[self.KEY_TEXT] + " - " + self[self.KEY_ID]
|