#!/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) )