#!/usr/bin/env python # -*- coding: utf-8 -*- # import devices import logging import task try: from config import APP_NAME as ROOT_LOGGER_NAME except ImportError: ROOT_LOGGER_NAME = 'root' logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__) class brightness_choose_n_action(object): def __init__(self, mqtt_client, button_tradfri, topic_led): self.gui_led_active_device = devices.nodered_gui_leds(mqtt_client, topic_led) # brightness change button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_DOWN_LONG, self.brightness_action) button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_UP_LONG, self.brightness_action) button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_DOWN_RELEASE, self.brightness_action) button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_UP_RELEASE, self.brightness_action) # device change button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_UP, self.choose_next_device) button_tradfri.add_callback(devices.tradfri_button.KEY_ACTION, devices.tradfri_button.ACTION_BRIGHTNESS_DOWN, self.choose_prev_device) # self.brightness_device_list = [] self.callback_device_list = [] self.device_states = [] self.active_device_state = None self.update_active_device_led() def add(self, brightness_device, callback_device, callback_key): """ brightness_device: A device for brightness function needs to have the following methods: * .default_inc() * .default_dec() * .default_stop() callback_device: A device for installing callback which are executed, when the device is switched on or off. It needs the following method: * .add_callback(key, data or None, callback, on_changes_only) """ if len(self.brightness_device_list) >= len(devices.nodered_gui_leds.RX_KEYS): raise ValueError("Number of devices is limited by number of leds in devices.nodered_gui_leds.") self.brightness_device_list.append(brightness_device) self.callback_device_list.append((callback_device, callback_key)) self.device_states.append(False) callback_device.add_callback(callback_key, True, self.device_state_action, True) callback_device.add_callback(callback_key, False, self.device_state_action, True) def device_state_action(self, device, key, data): self.device_states[self.callback_device_list.index((device, key))] = data if data is True: self.active_device_state = self.callback_device_list.index((device, key)) self.update_active_device_led() else: self.choose_next_device() def update_active_device_led(self): for i in range(0, len(self.brightness_device_list)): self.gui_led_active_device.set_led(devices.nodered_gui_leds.RX_KEYS[i], self.active_device_state == i) def choose_prev_device(self, device=None, key=None, data=None): if self.active_device_state is not None: start_value = self.active_device_state for i in range(0, len(self.brightness_device_list)): target_state = (start_value - i - 1) % (len(self.brightness_device_list)) if self.device_states[target_state]: self.active_device_state = target_state self.update_active_device_led() return self.active_device_state = None self.update_active_device_led() def choose_next_device(self, device=None, key=None, data=None): if self.active_device_state is not None: start_value = self.active_device_state for i in range(0, len(self.brightness_device_list)): target_state = (start_value + i + 1) % (len(self.brightness_device_list)) if self.device_states[target_state]: self.active_device_state = target_state self.update_active_device_led() return self.active_device_state = None self.update_active_device_led() def brightness_action(self, device, key, data): if self.active_device_state is not None: target = self.brightness_device_list[self.active_device_state] if data == devices.tradfri_button.ACTION_BRIGHTNESS_UP_LONG: logger.info("Increasing \"%s\" - %s", type(self).__name__, target.topic) target.default_inc() elif data == devices.tradfri_button.ACTION_BRIGHTNESS_DOWN_LONG: logger.info("Decreasing \"%s\" - %s", type(self).__name__, target.topic) target.default_dec() elif data in [devices.tradfri_button.ACTION_BRIGHTNESS_UP_RELEASE, devices.tradfri_button.ACTION_BRIGHTNESS_DOWN_RELEASE]: target.default_stop() class heating_function_brennenstuhl(object): RETURN_TO_DEFAULT_TIME = 45 * 60 BOOST_TEMP_OFFSET = 5 def __init__(self, mqtt_client, topic_valve, default_temperature, topic_boost, topic_setpoint, topic_led): self.ct = task.periodic(1, self.cyclic_task) # self.topic = topic_valve self.default_temperature = default_temperature # self.heating_valve = devices.brennenstuhl_heatingvalve(mqtt_client, topic_valve) self.heating_valve.set_heating_setpoint(self.default_temperature) self.heating_valve.add_callback( devices.brennenstuhl_heatingvalve.KEY_HEATING_SETPOINT, None, self.heating_setpoint_actions) self.gui_value_temp_setp = devices.nodered_gui_heatvalve(mqtt_client, topic_setpoint) self.gui_value_temp_setp.add_callback( devices.nodered_gui_heatvalve.KEY_HEATING_SETPOINT, None, self.heating_setpoint_actions) self.gui_button_boost = devices.nodered_gui_heatvalve(mqtt_client, topic_boost) self.gui_button_boost.add_callback(None, None, self.boost_actions) self.gui_led_boost = devices.nodered_gui_heatvalve(mqtt_client, topic_led) # self.return_to_default_timer = None self.return_to_default_setpoint = None self.gui_led_boost.set_feedback(False) # self.ct.run() def heating_setpoint_actions(self, device, key, data): if device.topic == self.heating_valve.topic: # valve setpoint action self.gui_value_temp_setp.set_feedback(data) if data > self.default_temperature: if data != self.return_to_default_setpoint: logger.info('Got heating setpoint (%.1f°C) \"%s\" with deviation to the default value (%.1f°C). Starting timer for returning to default.', data, self.topic, self.default_temperature) self.return_to_default_timer = self.RETURN_TO_DEFAULT_TIME self.return_to_default_setpoint = data self.gui_led_boost.set_feedback(True) else: if self.return_to_default_timer is not None: logger.info('Deleting timer \"%s\" for returning to default.', self.topic) self.return_to_default_timer = None self.return_to_default_setpoint = None self.gui_led_boost.set_feedback(False) elif device.topic == self.gui_value_temp_setp.topic: # user setpoint action logger.info('Setpoint change \"%s\" to %.1f°C', self.topic, data) self.default_temperature = data self.heating_valve.set_heating_setpoint(self.default_temperature) self.return_to_default_timer = None self.return_to_default_setpoint = None self.gui_led_boost.set_feedback(False) def boost_actions(self, davice, key, data): logger.info('Starting boost mode \"%s\" with setpoint %.1f°C.', self.topic, self.default_temperature + self.BOOST_TEMP_OFFSET) self.heating_valve.set_heating_setpoint(self.default_temperature + self.BOOST_TEMP_OFFSET) def cyclic_task(self, rt): if self.return_to_default_timer is not None: self.return_to_default_timer -= self.ct.cycle_time if self.return_to_default_timer <= 0: logger.info('Return to default timer expired \"%s\".', self.topic) self.heating_valve.set_heating_setpoint(self.default_temperature) self.return_to_default_timer = None self.return_to_default_setpoint = None self.gui_led_boost.set_feedback(False)