diff --git a/homeassistant/components/mqtt/cover.py b/homeassistant/components/mqtt/cover.py index e1ad21564b5..17385e77ec3 100644 --- a/homeassistant/components/mqtt/cover.py +++ b/homeassistant/components/mqtt/cover.py @@ -30,6 +30,7 @@ CONF_SET_POSITION_TEMPLATE = 'set_position_template' CONF_SET_POSITION_TOPIC = 'set_position_topic' CONF_TILT_COMMAND_TOPIC = 'tilt_command_topic' CONF_TILT_STATUS_TOPIC = 'tilt_status_topic' +CONF_TILT_STATUS_TEMPLATE = 'tilt_status_template' CONF_PAYLOAD_CLOSE = 'payload_close' CONF_PAYLOAD_OPEN = 'payload_open' @@ -110,6 +111,7 @@ PLATFORM_SCHEMA = vol.All(mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({ vol.Optional(CONF_TILT_STATE_OPTIMISTIC, default=DEFAULT_TILT_OPTIMISTIC): cv.boolean, vol.Optional(CONF_TILT_STATUS_TOPIC): mqtt.valid_subscribe_topic, + vol.Optional(CONF_TILT_STATUS_TEMPLATE): cv.template, vol.Optional(CONF_UNIQUE_ID): cv.string, vol.Optional(CONF_VALUE_TEMPLATE): cv.template, }).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema).extend( @@ -203,17 +205,26 @@ class MqttCover(MqttAttributes, MqttAvailability, MqttDiscoveryUpdate, set_position_template = self._config.get(CONF_SET_POSITION_TEMPLATE) if set_position_template is not None: set_position_template.hass = self.hass + tilt_status_template = self._config.get(CONF_TILT_STATUS_TEMPLATE) + if tilt_status_template is not None: + tilt_status_template.hass = self.hass topics = {} @callback def tilt_updated(msg): """Handle tilt updates.""" - if (msg.payload.isnumeric() and - (self._config[CONF_TILT_MIN] <= int(msg.payload) <= + payload = msg.payload + if tilt_status_template is not None: + payload = \ + tilt_status_template.async_render_with_possible_json_value( + payload) + + if (payload.isnumeric() and + (self._config[CONF_TILT_MIN] <= int(payload) <= self._config[CONF_TILT_MAX])): - level = self.find_percentage_in_range(float(msg.payload)) + level = self.find_percentage_in_range(float(payload)) self._tilt_value = level self.async_write_ha_state() diff --git a/tests/components/mqtt/test_cover.py b/tests/components/mqtt/test_cover.py index 8bf136c6f0f..91b0355ad22 100644 --- a/tests/components/mqtt/test_cover.py +++ b/tests/components/mqtt/test_cover.py @@ -603,6 +603,39 @@ async def test_tilt_via_topic(hass, mqtt_mock): assert current_cover_tilt_position == 50 +async def test_tilt_via_topic_template(hass, mqtt_mock): + """Test tilt by updating status via MQTT and template.""" + assert await async_setup_component(hass, cover.DOMAIN, { + cover.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'qos': 0, + 'payload_open': 'OPEN', + 'payload_close': 'CLOSE', + 'payload_stop': 'STOP', + 'tilt_command_topic': 'tilt-command-topic', + 'tilt_status_topic': 'tilt-status-topic', + 'tilt_status_template': '{{ (value | multiply(0.01)) | int }}', + 'tilt_opened_value': 400, + 'tilt_closed_value': 125 + } + }) + + async_fire_mqtt_message(hass, 'tilt-status-topic', '99') + + current_cover_tilt_position = hass.states.get( + 'cover.test').attributes['current_tilt_position'] + assert current_cover_tilt_position == 0 + + async_fire_mqtt_message(hass, 'tilt-status-topic', '5000') + + current_cover_tilt_position = hass.states.get( + 'cover.test').attributes['current_tilt_position'] + assert current_cover_tilt_position == 50 + + async def test_tilt_via_topic_altered_range(hass, mqtt_mock): """Test tilt status via MQTT with altered tilt range.""" assert await async_setup_component(hass, cover.DOMAIN, { @@ -643,6 +676,47 @@ async def test_tilt_via_topic_altered_range(hass, mqtt_mock): assert current_cover_tilt_position == 50 +async def test_tilt_via_topic_template_altered_range(hass, mqtt_mock): + """Test tilt status via MQTT and template with altered tilt range.""" + assert await async_setup_component(hass, cover.DOMAIN, { + cover.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'qos': 0, + 'payload_open': 'OPEN', + 'payload_close': 'CLOSE', + 'payload_stop': 'STOP', + 'tilt_command_topic': 'tilt-command-topic', + 'tilt_status_topic': 'tilt-status-topic', + 'tilt_status_template': '{{ (value | multiply(0.01)) | int }}', + 'tilt_opened_value': 400, + 'tilt_closed_value': 125, + 'tilt_min': 0, + 'tilt_max': 50 + } + }) + + async_fire_mqtt_message(hass, 'tilt-status-topic', '99') + + current_cover_tilt_position = hass.states.get( + 'cover.test').attributes['current_tilt_position'] + assert current_cover_tilt_position == 0 + + async_fire_mqtt_message(hass, 'tilt-status-topic', '5000') + + current_cover_tilt_position = hass.states.get( + 'cover.test').attributes['current_tilt_position'] + assert current_cover_tilt_position == 100 + + async_fire_mqtt_message(hass, 'tilt-status-topic', '2500') + + current_cover_tilt_position = hass.states.get( + 'cover.test').attributes['current_tilt_position'] + assert current_cover_tilt_position == 50 + + async def test_tilt_position(hass, mqtt_mock): """Test tilt via method invocation.""" assert await async_setup_component(hass, cover.DOMAIN, {