2017-02-07 17:13:24 +00:00
|
|
|
"""
|
|
|
|
Support for MQTT discovery.
|
|
|
|
|
|
|
|
For more details about this component, please refer to the documentation at
|
|
|
|
https://home-assistant.io/components/mqtt/#discovery
|
|
|
|
"""
|
|
|
|
import json
|
|
|
|
import logging
|
|
|
|
import re
|
|
|
|
|
2018-07-18 09:54:27 +00:00
|
|
|
from homeassistant.components import mqtt
|
2017-02-07 17:13:24 +00:00
|
|
|
from homeassistant.helpers.discovery import async_load_platform
|
|
|
|
from homeassistant.const import CONF_PLATFORM
|
|
|
|
from homeassistant.components.mqtt import CONF_STATE_TOPIC
|
|
|
|
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
TOPIC_MATCHER = re.compile(
|
2017-06-24 07:46:41 +00:00
|
|
|
r'(?P<prefix_topic>\w+)/(?P<component>\w+)/'
|
|
|
|
r'(?:(?P<node_id>[a-zA-Z0-9_-]+)/)?(?P<object_id>[a-zA-Z0-9_-]+)/config')
|
2017-02-14 07:54:13 +00:00
|
|
|
|
2017-11-15 04:19:15 +00:00
|
|
|
SUPPORTED_COMPONENTS = [
|
2018-04-06 04:11:38 +00:00
|
|
|
'binary_sensor', 'camera', 'cover', 'fan',
|
2018-06-25 13:13:19 +00:00
|
|
|
'light', 'sensor', 'switch', 'lock', 'climate']
|
2017-03-08 07:01:36 +00:00
|
|
|
|
|
|
|
ALLOWED_PLATFORMS = {
|
|
|
|
'binary_sensor': ['mqtt'],
|
2018-04-06 04:11:38 +00:00
|
|
|
'camera': ['mqtt'],
|
2017-11-15 04:19:15 +00:00
|
|
|
'cover': ['mqtt'],
|
2017-09-17 09:32:22 +00:00
|
|
|
'fan': ['mqtt'],
|
2017-03-08 07:01:36 +00:00
|
|
|
'light': ['mqtt', 'mqtt_json', 'mqtt_template'],
|
2018-03-18 16:26:07 +00:00
|
|
|
'lock': ['mqtt'],
|
2017-03-26 13:48:28 +00:00
|
|
|
'sensor': ['mqtt'],
|
|
|
|
'switch': ['mqtt'],
|
2018-06-25 13:13:19 +00:00
|
|
|
'climate': ['mqtt'],
|
2017-03-08 07:01:36 +00:00
|
|
|
}
|
2017-02-07 17:13:24 +00:00
|
|
|
|
2017-05-23 18:08:12 +00:00
|
|
|
ALREADY_DISCOVERED = 'mqtt_discovered_components'
|
|
|
|
|
2017-02-07 17:13:24 +00:00
|
|
|
|
2018-03-17 03:27:05 +00:00
|
|
|
async def async_start(hass, discovery_topic, hass_config):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Initialize of MQTT Discovery."""
|
2018-03-17 03:27:05 +00:00
|
|
|
async def async_device_message_received(topic, payload, qos):
|
2017-02-07 17:13:24 +00:00
|
|
|
"""Process the received message."""
|
|
|
|
match = TOPIC_MATCHER.match(topic)
|
|
|
|
|
|
|
|
if not match:
|
|
|
|
return
|
|
|
|
|
2018-03-17 03:27:05 +00:00
|
|
|
_prefix_topic, component, node_id, object_id = match.groups()
|
2017-02-07 17:13:24 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
payload = json.loads(payload)
|
|
|
|
except ValueError:
|
2017-02-14 07:54:13 +00:00
|
|
|
_LOGGER.warning("Unable to parse JSON %s: %s", object_id, payload)
|
2017-02-07 17:13:24 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
if component not in SUPPORTED_COMPONENTS:
|
|
|
|
_LOGGER.warning("Component %s is not supported", component)
|
|
|
|
return
|
|
|
|
|
|
|
|
payload = dict(payload)
|
2017-03-08 07:01:36 +00:00
|
|
|
platform = payload.get(CONF_PLATFORM, 'mqtt')
|
|
|
|
if platform not in ALLOWED_PLATFORMS.get(component, []):
|
|
|
|
_LOGGER.warning("Platform %s (component %s) is not allowed",
|
|
|
|
platform, component)
|
|
|
|
return
|
|
|
|
|
|
|
|
payload[CONF_PLATFORM] = platform
|
2017-02-07 17:13:24 +00:00
|
|
|
if CONF_STATE_TOPIC not in payload:
|
2017-06-24 07:46:41 +00:00
|
|
|
payload[CONF_STATE_TOPIC] = '{}/{}/{}{}/state'.format(
|
|
|
|
discovery_topic, component, '%s/' % node_id if node_id else '',
|
|
|
|
object_id)
|
2017-02-07 17:13:24 +00:00
|
|
|
|
2017-05-23 18:08:12 +00:00
|
|
|
if ALREADY_DISCOVERED not in hass.data:
|
|
|
|
hass.data[ALREADY_DISCOVERED] = set()
|
|
|
|
|
2017-06-24 07:46:41 +00:00
|
|
|
# If present, the node_id will be included in the discovered object id
|
|
|
|
discovery_id = '_'.join((node_id, object_id)) if node_id else object_id
|
|
|
|
|
|
|
|
discovery_hash = (component, discovery_id)
|
2017-05-23 18:08:12 +00:00
|
|
|
if discovery_hash in hass.data[ALREADY_DISCOVERED]:
|
|
|
|
_LOGGER.info("Component has already been discovered: %s %s",
|
2017-06-24 07:46:41 +00:00
|
|
|
component, discovery_id)
|
2017-05-23 18:08:12 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
hass.data[ALREADY_DISCOVERED].add(discovery_hash)
|
|
|
|
|
2017-06-24 07:46:41 +00:00
|
|
|
_LOGGER.info("Found new component: %s %s", component, discovery_id)
|
2017-05-23 18:08:12 +00:00
|
|
|
|
2018-03-17 03:27:05 +00:00
|
|
|
await async_load_platform(
|
2017-03-09 07:53:17 +00:00
|
|
|
hass, component, platform, payload, hass_config)
|
2017-02-07 17:13:24 +00:00
|
|
|
|
2018-03-17 03:27:05 +00:00
|
|
|
await mqtt.async_subscribe(
|
2017-02-18 22:17:18 +00:00
|
|
|
hass, discovery_topic + '/#', async_device_message_received, 0)
|
2017-02-07 17:13:24 +00:00
|
|
|
|
|
|
|
return True
|