Merge pull request #661 from bachp/mqtt-retain

Allow setting the retain flag for mqtt switch.
This commit is contained in:
Paulus Schoutsen 2015-11-26 12:19:52 -08:00
commit 4c3d6981a6
5 changed files with 24 additions and 14 deletions

View File

@ -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. """

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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)