123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- #
- """
- Virtual Device(s)
-
- Targets:
- * MQTT-Interface to control joined devices as one virtual device.
- * Primary signal routing
- * No functionality should be implemented here
- """
-
- from base import mqtt_base
- import devices
- import json
- import logging
-
- BASETOPIC = "videv"
-
-
- try:
- from config import APP_NAME as ROOT_LOGGER_NAME
- except ImportError:
- ROOT_LOGGER_NAME = 'root'
-
-
- class base(mqtt_base):
- DEFAULT_VALUES = {}
-
- def __init__(self, mqtt_client, topic, *args):
- super().__init__(mqtt_client, topic)
- self.__device_list__ = {}
- for videv_key, device in [reduced[:2] for reduced in args]:
- self.__device_list__[videv_key] = device
- # send initial state
- for key in self.keys():
- self.__tx__(key, self[key])
- # add receive topics
- mqtt_client.add_callback(self.topic + "/#", self.__rx__)
-
- def __tx__(self, key, data):
- if type(data) not in (str, ):
- data = json.dumps(data)
- if key in self.keys():
- self.mqtt_client.send(self.topic + '/' + key, data)
- else:
- self.logger.warning("Ignoring send request for key %s (not available for this class)", key)
-
- def __rx__(self, client, userdata, message):
- key = message.topic.split('/')[-1]
- if key in self.keys():
- try:
- data = json.loads(message.payload)
- except json.decoder.JSONDecodeError:
- data = message.payload
- if data != self[key]:
- self.__rx_functionality__(key, data)
- self.set(key, data)
- else:
- self.logger.info("Ignoring rx message with topic %s", message.topic)
-
- def __rx_functionality__(self, key, data):
- raise NotImplemented("Method __rx_functionality__ needs to be implemented in child class")
-
- def __device_data__(self, device, key, data):
- raise NotImplemented("Method __device_data__ needs to be implemented in child class")
-
-
- class base_routing(base):
- def __init__(self, mqtt_client, topic, *args):
- super().__init__(mqtt_client, topic, *args)
- #
- self.__device_key__ = {}
- index = 0
- for videv_key, device, device_key in args:
- if self.__device_list__[videv_key] != device:
- raise ReferenceError("Parent class generated a deviating device list")
- self.__device_key__[videv_key] = device_key
- index += 1
- # add callbacks
- for key in self.__device_list__:
- self.__device_list__[key].add_callback(self.__device_key__[key], None, self.__device_data__, True)
-
- def __rx_functionality__(self, key, data):
- try:
- self.__device_list__[key].set(self.__device_key__[key], data)
- except KeyError:
- self.logger.warning("RX passthrough not possible for key %s", key)
-
- def __device_data__(self, device, key, data):
- l1 = [k for k, v in self.__device_list__.items() if v == device]
- l2 = [k for k, v in self.__device_key__.items() if v == key]
- try:
- videv_key = [k for k in l1 if k in l2][0]
- except IndexError:
- self.logger.warning("videv_key not available for %s::%s", device.__class__.__name__, device.topic)
- else:
- self.set(videv_key, data)
- self.__tx__(videv_key, data)
-
-
- class videv_switching(base_routing):
- KEY_STATE = 'state'
- #
- DEFAULT_VALUES = {
- KEY_STATE: False,
- }
-
- def __init__(self, mqtt_client, topic, sw_device, sw_key):
- #
- super().__init__(mqtt_client, topic, (self.KEY_STATE, sw_device, sw_key))
-
-
- class videv_switch_brightness(base_routing):
- KEY_STATE = 'state'
- KEY_BRIGHTNESS = 'brightness'
- #
- DEFAULT_VALUES = {
- KEY_STATE: False,
- KEY_BRIGHTNESS: 0
- }
-
- def __init__(self, mqtt_client, topic, sw_device, sw_key, br_device, br_key):
- #
- super().__init__(mqtt_client, topic, (self.KEY_STATE, sw_device, sw_key), (self.KEY_BRIGHTNESS, br_device, br_key))
-
-
- class videv_switch_brightness_color_temp(base_routing):
- KEY_STATE = 'state'
- KEY_BRIGHTNESS = 'brightness'
- KEY_COLOR_TEMP = 'color_temp'
- #
- DEFAULT_VALUES = {
- KEY_STATE: False,
- KEY_BRIGHTNESS: 0,
- KEY_COLOR_TEMP: 0,
- }
-
- def __init__(self, mqtt_client, topic, sw_device, sw_key, br_device, br_key, ct_device, ct_key):
- #
- super().__init__(
- mqtt_client, topic,
- (self.KEY_STATE, sw_device, sw_key),
- (self.KEY_BRIGHTNESS, br_device, br_key),
- (self.KEY_COLOR_TEMP, ct_device, ct_key)
- )
|