From 25cbc8317f359c9924b561a8588a5934024dc7e8 Mon Sep 17 00:00:00 2001 From: mkfink Date: Thu, 8 Feb 2018 06:28:12 -0500 Subject: [PATCH] Force update support for mqtt binary sensor (#12092) --- .../components/binary_sensor/mqtt.py | 16 ++++- tests/components/binary_sensor/test_mqtt.py | 71 +++++++++++++++++-- 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/binary_sensor/mqtt.py b/homeassistant/components/binary_sensor/mqtt.py index 650179f676b..e033355f655 100644 --- a/homeassistant/components/binary_sensor/mqtt.py +++ b/homeassistant/components/binary_sensor/mqtt.py @@ -14,8 +14,8 @@ import homeassistant.components.mqtt as mqtt from homeassistant.components.binary_sensor import ( BinarySensorDevice, DEVICE_CLASSES_SCHEMA) from homeassistant.const import ( - CONF_NAME, CONF_VALUE_TEMPLATE, CONF_PAYLOAD_ON, CONF_PAYLOAD_OFF, - CONF_DEVICE_CLASS) + CONF_FORCE_UPDATE, CONF_NAME, CONF_VALUE_TEMPLATE, CONF_PAYLOAD_ON, + CONF_PAYLOAD_OFF, CONF_DEVICE_CLASS) from homeassistant.components.mqtt import ( CONF_STATE_TOPIC, CONF_AVAILABILITY_TOPIC, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS, MqttAvailability) @@ -24,8 +24,10 @@ import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) DEFAULT_NAME = 'MQTT Binary sensor' + DEFAULT_PAYLOAD_OFF = 'OFF' DEFAULT_PAYLOAD_ON = 'ON' +DEFAULT_FORCE_UPDATE = False DEPENDENCIES = ['mqtt'] @@ -34,6 +36,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({ vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string, vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string, vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean, }).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema) @@ -53,6 +56,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): config.get(CONF_AVAILABILITY_TOPIC), config.get(CONF_DEVICE_CLASS), config.get(CONF_QOS), + config.get(CONF_FORCE_UPDATE), config.get(CONF_PAYLOAD_ON), config.get(CONF_PAYLOAD_OFF), config.get(CONF_PAYLOAD_AVAILABLE), @@ -65,7 +69,7 @@ class MqttBinarySensor(MqttAvailability, BinarySensorDevice): """Representation a binary sensor that is updated by MQTT.""" def __init__(self, name, state_topic, availability_topic, device_class, - qos, payload_on, payload_off, payload_available, + qos, force_update, payload_on, payload_off, payload_available, payload_not_available, value_template): """Initialize the MQTT binary sensor.""" super().__init__(availability_topic, qos, payload_available, @@ -77,6 +81,7 @@ class MqttBinarySensor(MqttAvailability, BinarySensorDevice): self._payload_on = payload_on self._payload_off = payload_off self._qos = qos + self._force_update = force_update self._template = value_template @asyncio.coroutine @@ -124,3 +129,8 @@ class MqttBinarySensor(MqttAvailability, BinarySensorDevice): def device_class(self): """Return the class of this sensor.""" return self._device_class + + @property + def force_update(self): + """Force update.""" + return self._force_update diff --git a/tests/components/binary_sensor/test_mqtt.py b/tests/components/binary_sensor/test_mqtt.py index 396020561ac..9b5cf7aa736 100644 --- a/tests/components/binary_sensor/test_mqtt.py +++ b/tests/components/binary_sensor/test_mqtt.py @@ -1,13 +1,15 @@ """The tests for the MQTT binary sensor platform.""" import unittest +import homeassistant.core as ha from homeassistant.setup import setup_component import homeassistant.components.binary_sensor as binary_sensor -from homeassistant.const import (STATE_OFF, STATE_ON, - STATE_UNAVAILABLE) -from tests.common import ( - get_test_home_assistant, mock_mqtt_component, fire_mqtt_message) +from homeassistant.const import STATE_OFF, STATE_ON +from homeassistant.const import EVENT_STATE_CHANGED, STATE_UNAVAILABLE + +from tests.common import get_test_home_assistant, fire_mqtt_message +from tests.common import mock_component, mock_mqtt_component class TestSensorMQTT(unittest.TestCase): @@ -141,3 +143,64 @@ class TestSensorMQTT(unittest.TestCase): state = self.hass.states.get('binary_sensor.test') self.assertEqual(STATE_UNAVAILABLE, state.state) + + def test_force_update_disabled(self): + """Test force update option.""" + mock_component(self.hass, 'mqtt') + assert setup_component(self.hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'test-topic', + 'payload_on': 'ON', + 'payload_off': 'OFF' + } + }) + + events = [] + + @ha.callback + def callback(event): + """Verify event got called.""" + events.append(event) + + self.hass.bus.listen(EVENT_STATE_CHANGED, callback) + + fire_mqtt_message(self.hass, 'test-topic', 'ON') + self.hass.block_till_done() + self.assertEqual(1, len(events)) + + fire_mqtt_message(self.hass, 'test-topic', 'ON') + self.hass.block_till_done() + self.assertEqual(1, len(events)) + + def test_force_update_enabled(self): + """Test force update option.""" + mock_component(self.hass, 'mqtt') + assert setup_component(self.hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'test-topic', + 'payload_on': 'ON', + 'payload_off': 'OFF', + 'force_update': True + } + }) + + events = [] + + @ha.callback + def callback(event): + """Verify event got called.""" + events.append(event) + + self.hass.bus.listen(EVENT_STATE_CHANGED, callback) + + fire_mqtt_message(self.hass, 'test-topic', 'ON') + self.hass.block_till_done() + self.assertEqual(1, len(events)) + + fire_mqtt_message(self.hass, 'test-topic', 'ON') + self.hass.block_till_done() + self.assertEqual(2, len(events))