mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
support for last will and birth message for mqtt (#4381)
This commit is contained in:
parent
7aaf3a46db
commit
0e0ba28249
@ -17,8 +17,9 @@ from homeassistant.config import load_yaml_config_file
|
|||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import template, config_validation as cv
|
from homeassistant.helpers import template, config_validation as cv
|
||||||
from homeassistant.helpers.event import threaded_listener_factory
|
from homeassistant.helpers.event import threaded_listener_factory
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (EVENT_HOMEASSISTANT_START,
|
||||||
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, CONF_VALUE_TEMPLATE)
|
EVENT_HOMEASSISTANT_STOP, CONF_VALUE_TEMPLATE,
|
||||||
|
CONF_USERNAME, CONF_PASSWORD, CONF_PORT)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -33,17 +34,17 @@ REQUIREMENTS = ['paho-mqtt==1.2']
|
|||||||
|
|
||||||
CONF_EMBEDDED = 'embedded'
|
CONF_EMBEDDED = 'embedded'
|
||||||
CONF_BROKER = 'broker'
|
CONF_BROKER = 'broker'
|
||||||
CONF_PORT = 'port'
|
|
||||||
CONF_CLIENT_ID = 'client_id'
|
CONF_CLIENT_ID = 'client_id'
|
||||||
CONF_KEEPALIVE = 'keepalive'
|
CONF_KEEPALIVE = 'keepalive'
|
||||||
CONF_USERNAME = 'username'
|
|
||||||
CONF_PASSWORD = 'password'
|
|
||||||
CONF_CERTIFICATE = 'certificate'
|
CONF_CERTIFICATE = 'certificate'
|
||||||
CONF_CLIENT_KEY = 'client_key'
|
CONF_CLIENT_KEY = 'client_key'
|
||||||
CONF_CLIENT_CERT = 'client_cert'
|
CONF_CLIENT_CERT = 'client_cert'
|
||||||
CONF_TLS_INSECURE = 'tls_insecure'
|
CONF_TLS_INSECURE = 'tls_insecure'
|
||||||
CONF_PROTOCOL = 'protocol'
|
CONF_PROTOCOL = 'protocol'
|
||||||
|
|
||||||
|
CONF_BIRTH_MESSAGE = 'birth_message'
|
||||||
|
CONF_WILL_MESSAGE = 'will_message'
|
||||||
|
|
||||||
CONF_STATE_TOPIC = 'state_topic'
|
CONF_STATE_TOPIC = 'state_topic'
|
||||||
CONF_COMMAND_TOPIC = 'command_topic'
|
CONF_COMMAND_TOPIC = 'command_topic'
|
||||||
CONF_QOS = 'qos'
|
CONF_QOS = 'qos'
|
||||||
@ -84,14 +85,20 @@ _HBMQTT_CONFIG_SCHEMA = vol.Schema(dict)
|
|||||||
CLIENT_KEY_AUTH_MSG = 'client_key and client_cert must both be present in ' \
|
CLIENT_KEY_AUTH_MSG = 'client_key and client_cert must both be present in ' \
|
||||||
'the mqtt broker config'
|
'the mqtt broker config'
|
||||||
|
|
||||||
|
MQTT_PUBLISH_SCHEMA = vol.Schema({
|
||||||
|
vol.Required(ATTR_TOPIC): valid_publish_topic,
|
||||||
|
vol.Required(ATTR_PAYLOAD, 'payload'): cv.string,
|
||||||
|
vol.Required(ATTR_QOS, default=DEFAULT_QOS): _VALID_QOS_SCHEMA,
|
||||||
|
vol.Required(ATTR_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
|
||||||
|
}, required=True)
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: vol.Schema({
|
DOMAIN: vol.Schema({
|
||||||
vol.Optional(CONF_CLIENT_ID): cv.string,
|
vol.Optional(CONF_CLIENT_ID): cv.string,
|
||||||
vol.Optional(CONF_KEEPALIVE, default=DEFAULT_KEEPALIVE):
|
vol.Optional(CONF_KEEPALIVE, default=DEFAULT_KEEPALIVE):
|
||||||
vol.All(vol.Coerce(int), vol.Range(min=15)),
|
vol.All(vol.Coerce(int), vol.Range(min=15)),
|
||||||
vol.Optional(CONF_BROKER): cv.string,
|
vol.Optional(CONF_BROKER): cv.string,
|
||||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT):
|
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
||||||
vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)),
|
|
||||||
vol.Optional(CONF_USERNAME): cv.string,
|
vol.Optional(CONF_USERNAME): cv.string,
|
||||||
vol.Optional(CONF_PASSWORD): cv.string,
|
vol.Optional(CONF_PASSWORD): cv.string,
|
||||||
vol.Optional(CONF_CERTIFICATE): cv.isfile,
|
vol.Optional(CONF_CERTIFICATE): cv.isfile,
|
||||||
@ -103,6 +110,8 @@ CONFIG_SCHEMA = vol.Schema({
|
|||||||
vol.Optional(CONF_PROTOCOL, default=DEFAULT_PROTOCOL):
|
vol.Optional(CONF_PROTOCOL, default=DEFAULT_PROTOCOL):
|
||||||
vol.All(cv.string, vol.In([PROTOCOL_31, PROTOCOL_311])),
|
vol.All(cv.string, vol.In([PROTOCOL_31, PROTOCOL_311])),
|
||||||
vol.Optional(CONF_EMBEDDED): _HBMQTT_CONFIG_SCHEMA,
|
vol.Optional(CONF_EMBEDDED): _HBMQTT_CONFIG_SCHEMA,
|
||||||
|
vol.Optional(CONF_WILL_MESSAGE): MQTT_PUBLISH_SCHEMA,
|
||||||
|
vol.Optional(CONF_BIRTH_MESSAGE): MQTT_PUBLISH_SCHEMA
|
||||||
}),
|
}),
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
@ -241,11 +250,15 @@ def setup(hass, config):
|
|||||||
certificate = os.path.join(os.path.dirname(__file__),
|
certificate = os.path.join(os.path.dirname(__file__),
|
||||||
'addtrustexternalcaroot.crt')
|
'addtrustexternalcaroot.crt')
|
||||||
|
|
||||||
|
will_message = conf.get(CONF_WILL_MESSAGE)
|
||||||
|
birth_message = conf.get(CONF_BIRTH_MESSAGE)
|
||||||
|
|
||||||
global MQTT_CLIENT
|
global MQTT_CLIENT
|
||||||
try:
|
try:
|
||||||
MQTT_CLIENT = MQTT(hass, broker, port, client_id, keepalive,
|
MQTT_CLIENT = MQTT(hass, broker, port, client_id, keepalive,
|
||||||
username, password, certificate, client_key,
|
username, password, certificate, client_key,
|
||||||
client_cert, tls_insecure, protocol)
|
client_cert, tls_insecure, protocol, will_message,
|
||||||
|
birth_message)
|
||||||
except socket.error:
|
except socket.error:
|
||||||
_LOGGER.exception("Can't connect to the broker. "
|
_LOGGER.exception("Can't connect to the broker. "
|
||||||
"Please check your settings and the broker "
|
"Please check your settings and the broker "
|
||||||
@ -296,13 +309,14 @@ class MQTT(object):
|
|||||||
|
|
||||||
def __init__(self, hass, broker, port, client_id, keepalive, username,
|
def __init__(self, hass, broker, port, client_id, keepalive, username,
|
||||||
password, certificate, client_key, client_cert,
|
password, certificate, client_key, client_cert,
|
||||||
tls_insecure, protocol):
|
tls_insecure, protocol, will_message, birth_message):
|
||||||
"""Initialize Home Assistant MQTT client."""
|
"""Initialize Home Assistant MQTT client."""
|
||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
|
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.topics = {}
|
self.topics = {}
|
||||||
self.progress = {}
|
self.progress = {}
|
||||||
|
self.birth_message = birth_message
|
||||||
|
|
||||||
if protocol == PROTOCOL_31:
|
if protocol == PROTOCOL_31:
|
||||||
proto = mqtt.MQTTv31
|
proto = mqtt.MQTTv31
|
||||||
@ -329,7 +343,11 @@ class MQTT(object):
|
|||||||
self._mqttc.on_connect = self._mqtt_on_connect
|
self._mqttc.on_connect = self._mqtt_on_connect
|
||||||
self._mqttc.on_disconnect = self._mqtt_on_disconnect
|
self._mqttc.on_disconnect = self._mqtt_on_disconnect
|
||||||
self._mqttc.on_message = self._mqtt_on_message
|
self._mqttc.on_message = self._mqtt_on_message
|
||||||
|
if will_message:
|
||||||
|
self._mqttc.will_set(will_message.get(ATTR_TOPIC),
|
||||||
|
will_message.get(ATTR_PAYLOAD),
|
||||||
|
will_message.get(ATTR_QOS),
|
||||||
|
will_message.get(ATTR_RETAIN))
|
||||||
self._mqttc.connect(broker, port, keepalive)
|
self._mqttc.connect(broker, port, keepalive)
|
||||||
|
|
||||||
def publish(self, topic, payload, qos, retain):
|
def publish(self, topic, payload, qos, retain):
|
||||||
@ -365,7 +383,8 @@ class MQTT(object):
|
|||||||
def _mqtt_on_connect(self, _mqttc, _userdata, _flags, result_code):
|
def _mqtt_on_connect(self, _mqttc, _userdata, _flags, result_code):
|
||||||
"""On connect callback.
|
"""On connect callback.
|
||||||
|
|
||||||
Resubscribe to all topics we were subscribed to.
|
Resubscribe to all topics we were subscribed to and publish birth
|
||||||
|
message.
|
||||||
"""
|
"""
|
||||||
if result_code != 0:
|
if result_code != 0:
|
||||||
_LOGGER.error('Unable to connect to the MQTT broker: %s', {
|
_LOGGER.error('Unable to connect to the MQTT broker: %s', {
|
||||||
@ -387,6 +406,11 @@ class MQTT(object):
|
|||||||
# qos is None if we were in process of subscribing
|
# qos is None if we were in process of subscribing
|
||||||
if qos is not None:
|
if qos is not None:
|
||||||
self.subscribe(topic, qos)
|
self.subscribe(topic, qos)
|
||||||
|
if self.birth_message:
|
||||||
|
self.publish(self.birth_message.get(ATTR_TOPIC),
|
||||||
|
self.birth_message.get(ATTR_PAYLOAD),
|
||||||
|
self.birth_message.get(ATTR_QOS),
|
||||||
|
self.birth_message.get(ATTR_RETAIN))
|
||||||
|
|
||||||
def _mqtt_on_subscribe(self, _mqttc, _userdata, mid, granted_qos):
|
def _mqtt_on_subscribe(self, _mqttc, _userdata, mid, granted_qos):
|
||||||
"""Subscribe successful callback."""
|
"""Subscribe successful callback."""
|
||||||
|
@ -227,6 +227,8 @@ class TestMQTTCallbacks(unittest.TestCase):
|
|||||||
assert setup_component(self.hass, mqtt.DOMAIN, {
|
assert setup_component(self.hass, mqtt.DOMAIN, {
|
||||||
mqtt.DOMAIN: {
|
mqtt.DOMAIN: {
|
||||||
mqtt.CONF_BROKER: 'mock-broker',
|
mqtt.CONF_BROKER: 'mock-broker',
|
||||||
|
mqtt.CONF_BIRTH_MESSAGE: {mqtt.ATTR_TOPIC: 'birth',
|
||||||
|
mqtt.ATTR_PAYLOAD: 'birth'}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -291,6 +293,12 @@ class TestMQTTCallbacks(unittest.TestCase):
|
|||||||
3: 'home/sensor',
|
3: 'home/sensor',
|
||||||
}, mqtt.MQTT_CLIENT.progress)
|
}, mqtt.MQTT_CLIENT.progress)
|
||||||
|
|
||||||
|
def test_mqtt_birth_message_on_connect(self):
|
||||||
|
"""Test birth message on connect."""
|
||||||
|
mqtt.MQTT_CLIENT._mqtt_on_connect(None, None, 0, 0)
|
||||||
|
mqtt.MQTT_CLIENT._mqttc.publish.assert_called_with('birth', 'birth', 0,
|
||||||
|
False)
|
||||||
|
|
||||||
def test_mqtt_disconnect_tries_no_reconnect_on_stop(self):
|
def test_mqtt_disconnect_tries_no_reconnect_on_stop(self):
|
||||||
"""Test the disconnect tries."""
|
"""Test the disconnect tries."""
|
||||||
mqtt.MQTT_CLIENT._mqtt_on_disconnect(None, None, 0)
|
mqtt.MQTT_CLIENT._mqtt_on_disconnect(None, None, 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user