#!/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 videv_base from function.rooms import room, room_collection import time try: from config import APP_NAME as ROOT_LOGGER_NAME except ImportError: ROOT_LOGGER_NAME = 'root' class videv_switching(videv_base): KEY_STATE = 'state' def __init__(self, mqtt_client, topic, sw_device, sw_key): super().__init__(mqtt_client, topic) self.add_routing(self.KEY_STATE, sw_device, sw_key) # self.__tx_capabilities__() class videv_switching_timer(videv_base): KEY_STATE = 'state' KEY_TIMER = 'timer' def __init__(self, mqtt_client, topic, sw_device, sw_key, tm_device, tm_key): super().__init__(mqtt_client, topic) self.add_routing(self.KEY_STATE, sw_device, sw_key) self.add_display(self.KEY_TIMER, tm_device, tm_key) # self.__tx_capabilities__() class videv_switching_motion(videv_base): KEY_STATE = 'state' # KEY_TIMER = 'timer' KEY_MOTION_SENSOR = 'motion_%d' def __init__(self, mqtt_client, topic, sw_device, sw_key, motion_function): self.motion_sensors = motion_function.motion_sensors # super().__init__(mqtt_client, topic) self.add_routing(self.KEY_STATE, sw_device, sw_key) self.add_display(self.KEY_TIMER, motion_function, motion_function.KEY_TIMER) # motion sensor state for index, motion_sensor in enumerate(self.motion_sensors): self.add_display(self.KEY_MOTION_SENSOR % index, motion_sensor, motion_sensor.KEY_OCCUPANCY) # self.__tx_capabilities__() class videv_switch_brightness(videv_base): KEY_STATE = 'state' KEY_BRIGHTNESS = 'brightness' def __init__(self, mqtt_client, topic, sw_device, sw_key, br_device, br_key): super().__init__(mqtt_client, topic) self.add_routing(self.KEY_STATE, sw_device, sw_key) self.add_routing(self.KEY_BRIGHTNESS, br_device, br_key) # self.__tx_capabilities__() class videv_switch_brightness_color_temp(videv_base): KEY_STATE = 'state' KEY_BRIGHTNESS = 'brightness' KEY_COLOR_TEMP = 'color_temp' def __init__(self, mqtt_client, topic, sw_device, sw_key, br_device, br_key, ct_device, ct_key): super().__init__(mqtt_client, topic) self.add_routing(self.KEY_STATE, sw_device, sw_key) self.add_routing(self.KEY_BRIGHTNESS, br_device, br_key) self.add_routing(self.KEY_COLOR_TEMP, ct_device, ct_key) # self.__tx_capabilities__() class videv_heating(videv_base): KEY_USER_TEMPERATURE_SETPOINT = 'user_temperature_setpoint' KEY_VALVE_TEMPERATURE_SETPOINT = 'valve_temperature_setpoint' KEY_AWAY_MODE = 'away_mode' KEY_SUMMER_MODE = 'summer_mode' KEY_START_BOOST = 'start_boost' KEY_SET_DEFAULT_TEMPERATURE = 'set_default_temperature' KEY_BOOST_TIMER = 'boost_timer' # KEY_TEMPERATURE = 'temperature' def __init__(self, mqtt_client, topic, heating_function): super().__init__(mqtt_client, topic) # self.add_routing(self.KEY_USER_TEMPERATURE_SETPOINT, heating_function, heating_function.KEY_USER_TEMPERATURE_SETPOINT) self.add_routing(self.KEY_AWAY_MODE, heating_function, heating_function.KEY_AWAY_MODE) self.add_routing(self.KEY_SUMMER_MODE, heating_function, heating_function.KEY_SUMMER_MODE) # self.add_control(self.KEY_START_BOOST, heating_function, heating_function.KEY_START_BOOST, False) self.add_control(self.KEY_SET_DEFAULT_TEMPERATURE, heating_function, heating_function.KEY_SET_DEFAULT_TEMPERATURE, False) # self.add_display(self.KEY_VALVE_TEMPERATURE_SETPOINT, heating_function, heating_function.KEY_TEMPERATURE_SETPOINT) self.add_display(self.KEY_BOOST_TIMER, heating_function, heating_function.KEY_BOOST_TIMER) self.add_display(self.KEY_TEMPERATURE, heating_function, heating_function.KEY_TEMPERATURE_CURRENT, False) # self.__tx_capabilities__() class videv_multistate(videv_base): KEY_STATE = 'state_%d' def __init__(self, mqtt_client, topic, key_for_device, device, num_states, default_values=None): super().__init__(mqtt_client, topic) self.num_states = num_states # send default values for i in range(0, num_states): self.__tx__(self.KEY_STATE % i, False) # device.add_callback(key_for_device, None, self.__index_rx__, True) # self.__tx_capabilities__() def __index_rx__(self, device, key, data): for i in range(0, self.num_states): self.__tx__(self.KEY_STATE % i, i == data) # self.__tx_capabilities__() class videv_audio_player(videv_base): KEY_ACTIVE_PLAYER = 'player_%d' KEY_TITLE = 'title' NO_TITLE = '---' def __init__(self, mqtt_client, topic, *args): super().__init__(mqtt_client, topic) for i, device in enumerate(args): self.add_display(self.KEY_ACTIVE_PLAYER % i, device, device.KEY_STATE) # for audio_device in args: audio_device.add_callback(audio_device.KEY_TITLE, None, self.__title_rx__, True) # self.__tx_capabilities__() def __title_rx__(self, device, key, data): self.__tx__(self.KEY_TITLE, data or self.NO_TITLE) @property def capabilities(self): super().capabilities self.__capabilities__[self.KEY_TITLE] = {'display': True} return self.__capabilities__ class videv_warnings(videv_base): MAX_WARNINGS = 10 KEY_WARNING = 'html_short' def __init__(self, mqtt_client, topic, default_values=None): super().__init__(mqtt_client, topic, default_values) self.__warnings__ = [] def warningcollector(self, client, key, data): self.__warnings__.append(data) self.__warnings__ = self.__warnings__[-self.MAX_WARNINGS:] txt = "

".join([time.asctime(w[w.KEY_TM]) + "
" + w[w.KEY_TEXT] + "
" + w[w.KEY_ID] for w in self.__warnings__]) self.__tx__(self.KEY_WARNING, txt) class all_off(videv_base): ALLOWED_CLASSES = (room, room_collection, ) def __init__(self, mqtt_client, topic, room_collection): super().__init__(mqtt_client, topic) self.__room_collection__ = room_collection # init __inst_dict__ self.__inst_dict__ = {} self.__add_instances__("all", self.__room_collection__) # register mqtt callbacks for all my keys for key in self.__inst_dict__: mqtt_client.add_callback(topic + "/" + key, self.all_off) # self.__tx_capabilities__() def __check_inst_capabilities__(self, name, inst): # fits to specified classes if isinstance(inst, self.ALLOWED_CLASSES): try: # all_off method is callable return callable(inst.all_off) except AttributeError: # all_off method does not exist return False return False def __add_instances__(self, name, inst, level=0): if self.__check_inst_capabilities__(name, inst): # add given instance to my __inst_dict__ self.__inst_dict__[name] = inst # iterate over all attribute names of instance for sub_name in dir(inst): # attribute name is not private if not sub_name.startswith("__"): sub = getattr(inst, sub_name) # recurse with this object if level == 0: self.__add_instances__(sub_name, sub, level=level+1) else: self.__add_instances__(name + "/" + sub_name, sub, level=level+1) def all_off(self, client, userdata, message): key = message.topic[len(self.topic) + 1:] self.__inst_dict__[key].all_off() self.__tx_capabilities__() @property def capabilities(self): if self.__capabilities__ is None: self.__capabilities__ = {} self.__capabilities__['__type__'] = self.__class__.__name__ for key in self.__inst_dict__: self.__capabilities__[key] = {} self.__capabilities__[key]['control'] = True return self.__capabilities__