diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index b8dc8909887..65db49f8636 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -28,6 +28,7 @@ MQTT_CLIENT = None DEFAULT_PORT = 1883 DEFAULT_KEEPALIVE = 60 DEFAULT_QOS = 0 +DEFAULT_RETAIN = False SERVICE_PUBLISH = 'publish' EVENT_MQTT_MESSAGE_RECEIVED = 'MQTT_MESSAGE_RECEIVED' @@ -46,11 +47,12 @@ CONF_CERTIFICATE = 'certificate' ATTR_TOPIC = 'topic' ATTR_PAYLOAD = 'payload' ATTR_QOS = 'qos' +ATTR_RETAIN = 'retain' MAX_RECONNECT_WAIT = 300 # seconds -def publish(hass, topic, payload, qos=None): +def publish(hass, topic, payload, qos=None, retain=None): """ Send an MQTT message. """ data = { ATTR_TOPIC: topic, @@ -58,6 +60,10 @@ def publish(hass, topic, payload, qos=None): } if qos is not None: data[ATTR_QOS] = qos + + if retain is not None: + data[ATTR_RETAIN] = retain + hass.services.call(DOMAIN, SERVICE_PUBLISH, data) @@ -119,9 +125,10 @@ def setup(hass, config): msg_topic = call.data.get(ATTR_TOPIC) payload = call.data.get(ATTR_PAYLOAD) qos = call.data.get(ATTR_QOS, DEFAULT_QOS) + retain = call.data.get(ATTR_RETAIN, DEFAULT_RETAIN) if msg_topic is None or payload is None: return - MQTT_CLIENT.publish(msg_topic, payload, qos) + MQTT_CLIENT.publish(msg_topic, payload, qos, retain) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_mqtt) @@ -190,9 +197,9 @@ class MQTT(object): self._mqttc.connect(broker, port, keepalive) - def publish(self, topic, payload, qos): + def publish(self, topic, payload, qos, retain): """ Publish a MQTT message. """ - self._mqttc.publish(topic, payload, qos) + self._mqttc.publish(topic, payload, qos, retain) def start(self): """ Run the MQTT client. """ diff --git a/homeassistant/components/switch/mqtt.py b/homeassistant/components/switch/mqtt.py index 43bceab69a5..7b973799eed 100644 --- a/homeassistant/components/switch/mqtt.py +++ b/homeassistant/components/switch/mqtt.py @@ -17,6 +17,7 @@ DEFAULT_QOS = 0 DEFAULT_PAYLOAD_ON = "ON" DEFAULT_PAYLOAD_OFF = "OFF" DEFAULT_OPTIMISTIC = False +DEFAULT_RETAIN = False DEPENDENCIES = ['mqtt'] @@ -35,6 +36,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): config.get('state_topic'), config.get('command_topic'), config.get('qos', DEFAULT_QOS), + config.get('retain', DEFAULT_RETAIN), config.get('payload_on', DEFAULT_PAYLOAD_ON), config.get('payload_off', DEFAULT_PAYLOAD_OFF), config.get('optimistic', DEFAULT_OPTIMISTIC), @@ -44,7 +46,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): # pylint: disable=too-many-arguments, too-many-instance-attributes class MqttSwitch(SwitchDevice): """ Represents a switch that can be toggled using MQTT. """ - def __init__(self, hass, name, state_topic, command_topic, qos, + def __init__(self, hass, name, state_topic, command_topic, qos, retain, payload_on, payload_off, optimistic, state_format): self._state = False self._hass = hass @@ -52,6 +54,7 @@ class MqttSwitch(SwitchDevice): self._state_topic = state_topic self._command_topic = command_topic self._qos = qos + self._retain = retain self._payload_on = payload_on self._payload_off = payload_off self._optimistic = optimistic @@ -93,7 +96,7 @@ class MqttSwitch(SwitchDevice): def turn_on(self, **kwargs): """ Turn the device on. """ mqtt.publish(self.hass, self._command_topic, self._payload_on, - self._qos) + self._qos, self._retain) if self._optimistic: # optimistically assume that switch has changed state self._state = True @@ -102,7 +105,7 @@ class MqttSwitch(SwitchDevice): def turn_off(self, **kwargs): """ Turn the device off. """ mqtt.publish(self.hass, self._command_topic, self._payload_off, - self._qos) + self._qos, self._retain) if self._optimistic: # optimistically assume that switch has changed state self._state = False diff --git a/tests/components/alarm_control_panel/test_mqtt.py b/tests/components/alarm_control_panel/test_mqtt.py index 6cba26c15a6..58c55350cd2 100644 --- a/tests/components/alarm_control_panel/test_mqtt.py +++ b/tests/components/alarm_control_panel/test_mqtt.py @@ -101,7 +101,7 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): alarm_control_panel.alarm_arm_home(self.hass) self.hass.pool.block_till_done() - self.assertEqual(('alarm/command', 'ARM_HOME', 0), + self.assertEqual(('alarm/command', 'ARM_HOME', 0, False), self.mock_publish.mock_calls[-1][1]) def test_arm_home_not_publishes_mqtt_with_invalid_code(self): @@ -130,7 +130,7 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): alarm_control_panel.alarm_arm_away(self.hass) self.hass.pool.block_till_done() - self.assertEqual(('alarm/command', 'ARM_AWAY', 0), + self.assertEqual(('alarm/command', 'ARM_AWAY', 0, False), self.mock_publish.mock_calls[-1][1]) def test_arm_away_not_publishes_mqtt_with_invalid_code(self): @@ -159,7 +159,7 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): alarm_control_panel.alarm_disarm(self.hass) self.hass.pool.block_till_done() - self.assertEqual(('alarm/command', 'DISARM', 0), + self.assertEqual(('alarm/command', 'DISARM', 0, False), self.mock_publish.mock_calls[-1][1]) def test_disarm_not_publishes_mqtt_with_invalid_code(self): diff --git a/tests/components/light/test_mqtt.py b/tests/components/light/test_mqtt.py index 39c81ee0a04..fdebb0c1ef5 100644 --- a/tests/components/light/test_mqtt.py +++ b/tests/components/light/test_mqtt.py @@ -139,7 +139,7 @@ class TestLightMQTT(unittest.TestCase): light.turn_on(self.hass, 'light.test') self.hass.pool.block_till_done() - self.assertEqual(('test_light_rgb/set', 'on', 2), + self.assertEqual(('test_light_rgb/set', 'on', 2, False), self.mock_publish.mock_calls[-1][1]) state = self.hass.states.get('light.test') self.assertEqual(STATE_ON, state.state) @@ -147,7 +147,7 @@ class TestLightMQTT(unittest.TestCase): light.turn_off(self.hass, 'light.test') self.hass.pool.block_till_done() - self.assertEqual(('test_light_rgb/set', 'off', 2), + self.assertEqual(('test_light_rgb/set', 'off', 2, False), self.mock_publish.mock_calls[-1][1]) state = self.hass.states.get('light.test') self.assertEqual(STATE_OFF, state.state) diff --git a/tests/components/switch/test_mqtt.py b/tests/components/switch/test_mqtt.py index 4754e64e575..2cfe29c2910 100644 --- a/tests/components/switch/test_mqtt.py +++ b/tests/components/switch/test_mqtt.py @@ -68,7 +68,7 @@ class TestSensorMQTT(unittest.TestCase): switch.turn_on(self.hass, 'switch.test') self.hass.pool.block_till_done() - self.assertEqual(('command-topic', 'beer on', 2), + self.assertEqual(('command-topic', 'beer on', 2, False), self.mock_publish.mock_calls[-1][1]) state = self.hass.states.get('switch.test') self.assertEqual(STATE_ON, state.state) @@ -76,7 +76,7 @@ class TestSensorMQTT(unittest.TestCase): switch.turn_off(self.hass, 'switch.test') self.hass.pool.block_till_done() - self.assertEqual(('command-topic', 'beer off', 2), + self.assertEqual(('command-topic', 'beer off', 2, False), self.mock_publish.mock_calls[-1][1]) state = self.hass.states.get('switch.test') self.assertEqual(STATE_OFF, state.state)