diff --git a/homeassistant/components/switch/mqtt.py b/homeassistant/components/switch/mqtt.py new file mode 100644 index 00000000000..ee38c5fbb43 --- /dev/null +++ b/homeassistant/components/switch/mqtt.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +""" +homeassistant.components.switch.mqtt +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Allows to configure a MQTT switch. + +In an ideal scenario, the MQTT device will have a state topic to publish state changes. +If these messages are published with RETAIN flag, the MQTT switch will receive +an instant state update after subscription and will start with correct state. Otherwise, +the initial state of the switch will be false/off. + +When a state topic is not available, the switch will work in an optimistic mode. +In this mode, the MQTT switch will immediately change state after every command. +Otherwise, the switch will wait for state confirmation from device (message from state_topic). + +Optimistic mode can be forced, even if state topic is available. +Try to enable it, if experiencing incorrect switch operation. + + +Configuration: + +switch: + platform: mqtt + name: "Bedroom Switch" + state_topic: "home/bedroom/switch1" + command_topic: "home/bedroom/switch1/set" + payload_on: "ON" + payload_off: "OFF" + optimistic: false + +Variables: + +name +*Optional +The name of the switch. Default is 'MQTT Switch'. + +state_topic +*Optional +The MQTT topic subscribed to receive state updates. +If not specified, optimistic mode will be forced. + +command_topic +*Required +The MQTT topic to publish commands to change the switch state. + +payload_on +*Optional +The payload that represents enabled state. Default is "ON". + +payload_off +*Optional +The payload that represents disabled state. Default is "OFF". + +optimistic +*Optional +Flag that defines if switch works in optimistic mode. Default is false. + +""" + +import logging +import homeassistant.components.mqtt as mqtt +from homeassistant.components.switch import SwitchDevice + +_LOGGER = logging.getLogger(__name__) + +DEFAULT_NAME = "MQTT Switch" +DEFAULT_PAYLOAD_ON = "ON" +DEFAULT_PAYLOAD_OFF = "OFF" +DEFAULT_OPTIMISTIC = False + +DEPENDENCIES = ['mqtt'] + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices_callback, discovery_info=None): + """ Add MQTT Switch """ + + if config.get('command_topic') is None: + _LOGGER.error("Missing required variable: command_topic") + return False + + add_devices_callback([MqttSwitch( + hass, + config.get('name', DEFAULT_NAME), + config.get('state_topic'), + config.get('command_topic'), + config.get('payload_on', DEFAULT_PAYLOAD_ON), + config.get('payload_off', DEFAULT_PAYLOAD_OFF), + config.get('optimistic', DEFAULT_OPTIMISTIC))]) + +class MqttSwitch(SwitchDevice): + """ Represents a switch that can be togggled using MQTT """ + def __init__(self, hass, name, state_topic, command_topic, payload_on, payload_off, optimistic): + self._state = False + self._hass = hass + self._name = name + self._state_topic = state_topic + self._command_topic = command_topic + self._payload_on = payload_on + self._payload_off = payload_off + self._optimistic = optimistic + + def message_received(topic, payload, qos): + if (payload == self._payload_on): + self._state = True + self.update_ha_state() + elif (payload == self._payload_off): + self._state = False + self.update_ha_state() + + if self._state_topic is None: + """ force optimistic mode """ + self._optimistic = True + else: + """ subscribe the state_topic """ + mqtt.subscribe(hass, self._state_topic, message_received) + + @property + def should_poll(self): + """ No polling needed """ + return False + + @property + def name(self): + """ The name of the switch """ + return self._name + + @property + def is_on(self): + """ True if device is on. """ + return self._state + + def turn_on(self, **kwargs): + """ Turn the device on. """ + mqtt.publish(self.hass, self._command_topic, self._payload_on) + if self._optimistic: + """ optimistically assume that switch has changed state """ + self._state = True + self.update_ha_state() + + def turn_off(self, **kwargs): + """ Turn the device off. """ + mqtt.publish(self.hass, self._command_topic, self._payload_off) + if self._optimistic: + """ optimistically assume that switch has changed state """ + self._state = False + self.update_ha_state()