diff --git a/homeassistant/components/cover/mqtt.py b/homeassistant/components/cover/mqtt.py index 94e2b948c48..55df204f275 100644 --- a/homeassistant/components/cover/mqtt.py +++ b/homeassistant/components/cover/mqtt.py @@ -145,8 +145,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): async_discover) -async def _async_setup_entity(config, async_add_entities, - discovery_hash=None): +async def _async_setup_entity(config, async_add_entities, discovery_hash=None): """Set up the MQTT Cover.""" async_add_entities([MqttCover(config, discovery_hash)]) @@ -157,37 +156,14 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, def __init__(self, config, discovery_hash): """Initialize the cover.""" + self._unique_id = config.get(CONF_UNIQUE_ID) self._position = None self._state = None self._sub_state = None - self._name = None - self._state_topic = None - self._get_position_topic = None - self._command_topic = None - self._tilt_command_topic = None - self._tilt_status_topic = None - self._qos = None - self._payload_open = None - self._payload_close = None - self._payload_stop = None - self._state_open = None - self._state_closed = None - self._position_open = None - self._position_closed = None - self._retain = None - self._tilt_open_position = None - self._tilt_closed_position = None self._optimistic = None - self._template = None self._tilt_value = None - self._tilt_min = None - self._tilt_max = None self._tilt_optimistic = None - self._tilt_invert = None - self._set_position_topic = None - self._set_position_template = None - self._unique_id = None # Load config self._setup_from_config(config) @@ -195,9 +171,10 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, availability_topic = config.get(CONF_AVAILABILITY_TOPIC) payload_available = config.get(CONF_PAYLOAD_AVAILABLE) payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE) + qos = config.get(CONF_QOS) device_config = config.get(CONF_DEVICE) - MqttAvailability.__init__(self, availability_topic, self._qos, + MqttAvailability.__init__(self, availability_topic, qos, payload_available, payload_not_available) MqttDiscoveryUpdate.__init__(self, discovery_hash, self.discovery_update) @@ -217,42 +194,20 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, self.async_schedule_update_ha_state() def _setup_from_config(self, config): - self._name = config.get(CONF_NAME) - self._state_topic = config.get(CONF_STATE_TOPIC) - self._get_position_topic = config.get(CONF_GET_POSITION_TOPIC) - self._command_topic = config.get(CONF_COMMAND_TOPIC) - self._tilt_command_topic = config.get(CONF_TILT_COMMAND_TOPIC) - self._tilt_status_topic = config.get(CONF_TILT_STATUS_TOPIC) - self._qos = config.get(CONF_QOS) - self._retain = config.get(CONF_RETAIN) - self._state_open = config.get(CONF_STATE_OPEN) - self._state_closed = config.get(CONF_STATE_CLOSED) - self._position_open = config.get(CONF_POSITION_OPEN) - self._position_closed = config.get(CONF_POSITION_CLOSED) - self._payload_open = config.get(CONF_PAYLOAD_OPEN) - self._payload_close = config.get(CONF_PAYLOAD_CLOSE) - self._payload_stop = config.get(CONF_PAYLOAD_STOP) + self._config = config self._optimistic = (config.get(CONF_OPTIMISTIC) or - (self._state_topic is None and - self._get_position_topic is None)) - self._template = config.get(CONF_VALUE_TEMPLATE) - self._tilt_open_position = config.get(CONF_TILT_OPEN_POSITION) - self._tilt_closed_position = config.get(CONF_TILT_CLOSED_POSITION) - self._tilt_min = config.get(CONF_TILT_MIN) - self._tilt_max = config.get(CONF_TILT_MAX) + (config.get(CONF_STATE_TOPIC) is None and + config.get(CONF_GET_POSITION_TOPIC) is None)) self._tilt_optimistic = config.get(CONF_TILT_STATE_OPTIMISTIC) - self._tilt_invert = config.get(CONF_TILT_INVERT_STATE) - self._set_position_topic = config.get(CONF_SET_POSITION_TOPIC) - self._set_position_template = config.get(CONF_SET_POSITION_TEMPLATE) - - self._unique_id = config.get(CONF_UNIQUE_ID) async def _subscribe_topics(self): """(Re)Subscribe to topics.""" - if self._template is not None: - self._template.hass = self.hass - if self._set_position_template is not None: - self._set_position_template.hass = self.hass + template = self._config.get(CONF_VALUE_TEMPLATE) + if template is not None: + template.hass = self.hass + set_position_template = self._config.get(CONF_SET_POSITION_TEMPLATE) + if set_position_template is not None: + set_position_template.hass = self.hass topics = {} @@ -260,7 +215,8 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, def tilt_updated(topic, payload, qos): """Handle tilt updates.""" if (payload.isnumeric() and - self._tilt_min <= int(payload) <= self._tilt_max): + (self._config.get(CONF_TILT_MIN) <= int(payload) <= + self._config.get(CONF_TILT_MAX))): level = self.find_percentage_in_range(float(payload)) self._tilt_value = level @@ -269,13 +225,13 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, @callback def state_message_received(topic, payload, qos): """Handle new MQTT state messages.""" - if self._template is not None: - payload = self._template.async_render_with_possible_json_value( + if template is not None: + payload = template.async_render_with_possible_json_value( payload) - if payload == self._state_open: + if payload == self._config.get(CONF_STATE_OPEN): self._state = False - elif payload == self._state_closed: + elif payload == self._config.get(CONF_STATE_CLOSED): self._state = True else: _LOGGER.warning("Payload is not True or False: %s", payload) @@ -285,8 +241,8 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, @callback def position_message_received(topic, payload, qos): """Handle new MQTT state messages.""" - if self._template is not None: - payload = self._template.async_render_with_possible_json_value( + if template is not None: + payload = template.async_render_with_possible_json_value( payload) if payload.isnumeric(): @@ -301,29 +257,29 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, return self.async_schedule_update_ha_state() - if self._get_position_topic: + if self._config.get(CONF_GET_POSITION_TOPIC): topics['get_position_topic'] = { - 'topic': self._get_position_topic, + 'topic': self._config.get(CONF_GET_POSITION_TOPIC), 'msg_callback': position_message_received, - 'qos': self._qos} - elif self._state_topic: + 'qos': self._config.get(CONF_QOS)} + elif self._config.get(CONF_STATE_TOPIC): topics['state_topic'] = { - 'topic': self._state_topic, + 'topic': self._config.get(CONF_STATE_TOPIC), 'msg_callback': state_message_received, - 'qos': self._qos} + 'qos': self._config.get(CONF_QOS)} else: # Force into optimistic mode. self._optimistic = True - if self._tilt_status_topic is None: + if self._config.get(CONF_TILT_STATUS_TOPIC) is None: self._tilt_optimistic = True else: self._tilt_optimistic = False self._tilt_value = STATE_UNKNOWN topics['tilt_status_topic'] = { - 'topic': self._tilt_status_topic, + 'topic': self._config.get(CONF_TILT_STATUS_TOPIC), 'msg_callback': tilt_updated, - 'qos': self._qos} + 'qos': self._config.get(CONF_QOS)} self._sub_state = await subscription.async_subscribe_topics( self.hass, self._sub_state, @@ -347,7 +303,7 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, @property def name(self): """Return the name of the cover.""" - return self._name + return self._config.get(CONF_NAME) @property def is_closed(self): @@ -371,13 +327,13 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, def supported_features(self): """Flag supported features.""" supported_features = 0 - if self._command_topic is not None: + if self._config.get(CONF_COMMAND_TOPIC) is not None: supported_features = OPEN_CLOSE_FEATURES - if self._set_position_topic is not None: + if self._config.get(CONF_SET_POSITION_TOPIC) is not None: supported_features |= SUPPORT_SET_POSITION - if self._tilt_command_topic is not None: + if self._config.get(CONF_TILT_COMMAND_TOPIC) is not None: supported_features |= TILT_FEATURES return supported_features @@ -388,14 +344,15 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, This method is a coroutine. """ mqtt.async_publish( - self.hass, self._command_topic, self._payload_open, self._qos, - self._retain) + self.hass, self._config.get(CONF_COMMAND_TOPIC), + self._config.get(CONF_PAYLOAD_OPEN), self._config.get(CONF_QOS), + self._config.get(CONF_RETAIN)) if self._optimistic: # Optimistically assume that cover has changed state. self._state = False - if self._get_position_topic: + if self._config.get(CONF_GET_POSITION_TOPIC): self._position = self.find_percentage_in_range( - self._position_open, COVER_PAYLOAD) + self._config.get(CONF_POSITION_OPEN), COVER_PAYLOAD) self.async_schedule_update_ha_state() async def async_close_cover(self, **kwargs): @@ -404,14 +361,15 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, This method is a coroutine. """ mqtt.async_publish( - self.hass, self._command_topic, self._payload_close, self._qos, - self._retain) + self.hass, self._config.get(CONF_COMMAND_TOPIC), + self._config.get(CONF_PAYLOAD_CLOSE), self._config.get(CONF_QOS), + self._config.get(CONF_RETAIN)) if self._optimistic: # Optimistically assume that cover has changed state. self._state = True - if self._get_position_topic: + if self._config.get(CONF_GET_POSITION_TOPIC): self._position = self.find_percentage_in_range( - self._position_closed, COVER_PAYLOAD) + self._config.get(CONF_POSITION_CLOSED), COVER_PAYLOAD) self.async_schedule_update_ha_state() async def async_stop_cover(self, **kwargs): @@ -420,25 +378,30 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, This method is a coroutine. """ mqtt.async_publish( - self.hass, self._command_topic, self._payload_stop, self._qos, - self._retain) + self.hass, self._config.get(CONF_COMMAND_TOPIC), + self._config.get(CONF_PAYLOAD_STOP), self._config.get(CONF_QOS), + self._config.get(CONF_RETAIN)) async def async_open_cover_tilt(self, **kwargs): """Tilt the cover open.""" - mqtt.async_publish(self.hass, self._tilt_command_topic, - self._tilt_open_position, self._qos, - self._retain) + mqtt.async_publish(self.hass, + self._config.get(CONF_TILT_COMMAND_TOPIC), + self._config.get(CONF_TILT_OPEN_POSITION), + self._config.get(CONF_QOS), + self._config.get(CONF_RETAIN)) if self._tilt_optimistic: - self._tilt_value = self._tilt_open_position + self._tilt_value = self._config.get(CONF_TILT_OPEN_POSITION) self.async_schedule_update_ha_state() async def async_close_cover_tilt(self, **kwargs): """Tilt the cover closed.""" - mqtt.async_publish(self.hass, self._tilt_command_topic, - self._tilt_closed_position, self._qos, - self._retain) + mqtt.async_publish(self.hass, + self._config.get(CONF_TILT_COMMAND_TOPIC), + self._config.get(CONF_TILT_CLOSED_POSITION), + self._config.get(CONF_QOS), + self._config.get(CONF_RETAIN)) if self._tilt_optimistic: - self._tilt_value = self._tilt_closed_position + self._tilt_value = self._config.get(CONF_TILT_CLOSED_POSITION) self.async_schedule_update_ha_state() async def async_set_cover_tilt_position(self, **kwargs): @@ -451,29 +414,38 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, # The position needs to be between min and max level = self.find_in_range_from_percent(position) - mqtt.async_publish(self.hass, self._tilt_command_topic, - level, self._qos, self._retain) + mqtt.async_publish(self.hass, + self._config.get(CONF_TILT_COMMAND_TOPIC), + level, + self._config.get(CONF_QOS), + self._config.get(CONF_RETAIN)) async def async_set_cover_position(self, **kwargs): """Move the cover to a specific position.""" + set_position_template = self._config.get(CONF_SET_POSITION_TEMPLATE) if ATTR_POSITION in kwargs: position = kwargs[ATTR_POSITION] percentage_position = position - if self._set_position_template is not None: + if set_position_template is not None: try: - position = self._set_position_template.async_render( + position = set_position_template.async_render( **kwargs) except TemplateError as ex: _LOGGER.error(ex) self._state = None - elif self._position_open != 100 and self._position_closed != 0: + elif (self._config.get(CONF_POSITION_OPEN) != 100 and + self._config.get(CONF_POSITION_CLOSED) != 0): position = self.find_in_range_from_percent( position, COVER_PAYLOAD) - mqtt.async_publish(self.hass, self._set_position_topic, - position, self._qos, self._retain) + mqtt.async_publish(self.hass, + self._config.get(CONF_SET_POSITION_TOPIC), + position, + self._config.get(CONF_QOS), + self._config.get(CONF_RETAIN)) if self._optimistic: - self._state = percentage_position == self._position_closed + self._state = percentage_position == \ + self._config.get(CONF_POSITION_CLOSED) self._position = percentage_position self.async_schedule_update_ha_state() @@ -481,11 +453,11 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, """Find the 0-100% value within the specified range.""" # the range of motion as defined by the min max values if range_type == COVER_PAYLOAD: - max_range = self._position_open - min_range = self._position_closed + max_range = self._config.get(CONF_POSITION_OPEN) + min_range = self._config.get(CONF_POSITION_CLOSED) else: - max_range = self._tilt_max - min_range = self._tilt_min + max_range = self._config.get(CONF_TILT_MAX) + min_range = self._config.get(CONF_TILT_MIN) current_range = max_range - min_range # offset to be zero based offset_position = position - min_range @@ -496,7 +468,8 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, min_percent = 0 position_percentage = min(max(position_percentage, min_percent), max_percent) - if range_type == TILT_PAYLOAD and self._tilt_invert: + if range_type == TILT_PAYLOAD and \ + self._config.get(CONF_TILT_INVERT_STATE): return 100 - position_percentage return position_percentage @@ -510,17 +483,18 @@ class MqttCover(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo, returning the offset """ if range_type == COVER_PAYLOAD: - max_range = self._position_open - min_range = self._position_closed + max_range = self._config.get(CONF_POSITION_OPEN) + min_range = self._config.get(CONF_POSITION_CLOSED) else: - max_range = self._tilt_max - min_range = self._tilt_min + max_range = self._config.get(CONF_TILT_MAX) + min_range = self._config.get(CONF_TILT_MIN) offset = min_range current_range = max_range - min_range position = round(current_range * (percentage / 100.0)) position += offset - if range_type == TILT_PAYLOAD and self._tilt_invert: + if range_type == TILT_PAYLOAD and \ + self._config.get(CONF_TILT_INVERT_STATE): position = max_range - position + offset return position