From 08d29d3630f498932a00fde2187a1cfe40c3a6d0 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 20 Nov 2015 23:43:59 +0100 Subject: [PATCH 1/2] Add MQTT binary sensor --- .../components/binary_sensor/mqtt.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 homeassistant/components/binary_sensor/mqtt.py diff --git a/homeassistant/components/binary_sensor/mqtt.py b/homeassistant/components/binary_sensor/mqtt.py new file mode 100644 index 00000000000..cac991d4eb2 --- /dev/null +++ b/homeassistant/components/binary_sensor/mqtt.py @@ -0,0 +1,76 @@ +""" +homeassistant.components.binary_sensor.mqtt +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Allows to configure a MQTT binary sensor. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/binary_sensor.mqtt/ +""" +import logging +from homeassistant.components.binary_sensor import BinarySensorDevice +import homeassistant.components.mqtt as mqtt + +_LOGGER = logging.getLogger(__name__) + +DEFAULT_NAME = 'MQTT Binary sensor' +DEFAULT_QOS = 0 +DEFAULT_PAYLOAD_ON = 'ON' +DEFAULT_PAYLOAD_OFF = 'OFF' + +DEPENDENCIES = ['mqtt'] + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """ Add MQTT binary sensor. """ + + if config.get('state_topic') is None: + _LOGGER.error('Missing required variable: state_topic') + return False + + add_devices([MqttBinarySensor( + hass, + config.get('name', DEFAULT_NAME), + config.get('state_topic', None), + config.get('qos', DEFAULT_QOS), + config.get('payload_on', DEFAULT_PAYLOAD_ON), + config.get('payload_off', DEFAULT_PAYLOAD_OFF))]) + + +# pylint: disable=too-many-arguments, too-many-instance-attributes +class MqttBinarySensor(BinarySensorDevice): + """ Represents a binary sensor that is updated by MQTT. """ + def __init__(self, hass, name, state_topic, qos, payload_on, payload_off): + self._hass = hass + self._name = name + self._state = False + self._state_topic = state_topic + self._payload_on = payload_on + self._payload_off = payload_off + self._qos = qos + + def message_received(topic, payload, qos): + """ A new MQTT message has been received. """ + if payload == self._payload_on: + self._state = True + self.update_ha_state() + elif payload == self._payload_off: + self._state = False + self.update_ha_state() + + mqtt.subscribe(hass, self._state_topic, message_received, self._qos) + + @property + def should_poll(self): + """ No polling needed. """ + return False + + @property + def name(self): + """ The name of the binary sensor. """ + return self._name + + @property + def is_on(self): + """ True if the binary sensor is on. """ + return self._state From 422a93e73599f661b9c6be2f2b6a7bdc6b28bdeb Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 20 Nov 2015 23:48:59 +0100 Subject: [PATCH 2/2] Add tests for MQTT binary sensor --- tests/components/binary_sensor/__init__.py | 0 tests/components/binary_sensor/test_mqtt.py | 48 +++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/components/binary_sensor/__init__.py create mode 100644 tests/components/binary_sensor/test_mqtt.py diff --git a/tests/components/binary_sensor/__init__.py b/tests/components/binary_sensor/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/components/binary_sensor/test_mqtt.py b/tests/components/binary_sensor/test_mqtt.py new file mode 100644 index 00000000000..83fa532d051 --- /dev/null +++ b/tests/components/binary_sensor/test_mqtt.py @@ -0,0 +1,48 @@ +""" +tests.components.binary_sensor.test_mqtt +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Tests MQTT binary sensor. +""" +import unittest + +import homeassistant.core as ha +import homeassistant.components.binary_sensor as binary_sensor +from tests.common import mock_mqtt_component, fire_mqtt_message +from homeassistant.const import (STATE_OFF, STATE_ON) + + +class TestSensorMQTT(unittest.TestCase): + """ Test the MQTT sensor. """ + + def setUp(self): # pylint: disable=invalid-name + self.hass = ha.HomeAssistant() + mock_mqtt_component(self.hass) + + def tearDown(self): # pylint: disable=invalid-name + """ Stop down stuff we started. """ + self.hass.stop() + + def test_setting_sensor_value_via_mqtt_message(self): + self.assertTrue(binary_sensor.setup(self.hass, { + 'binary_sensor': { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'test-topic', + 'payload_on': 'ON', + 'payload_off': 'OFF', + } + })) + + state = self.hass.states.get('binary_sensor.test') + self.assertEqual(STATE_OFF, state.state) + + fire_mqtt_message(self.hass, 'test-topic', 'ON') + self.hass.pool.block_till_done() + state = self.hass.states.get('binary_sensor.test') + self.assertEqual(STATE_ON, state.state) + + fire_mqtt_message(self.hass, 'test-topic', 'OFF') + self.hass.pool.block_till_done() + state = self.hass.states.get('binary_sensor.test') + self.assertEqual(STATE_OFF, state.state)