Allow MQTT discovery availability shortcut (#57479)

* replace base in availability topic

* add tests for availability shortcuts - fix import

* group constants

* simplified loop

* Moving constants to .const

* rename value to topic

* move CONF_TOPIC to .const

* move CONF_AVAILABILITY to .const

* remove check for string

* Silently ignore if no config topic is found.

* CONF_TOPIC should be required
This commit is contained in:
Jan Bouwhuis 2021-10-11 23:37:31 +02:00 committed by GitHub
parent 13db867c1d
commit a36a765352
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 4 deletions

View File

@ -9,11 +9,13 @@ ATTR_QOS = "qos"
ATTR_RETAIN = "retain"
ATTR_TOPIC = "topic"
CONF_AVAILABILITY = "availability"
CONF_BROKER = "broker"
CONF_BIRTH_MESSAGE = "birth_message"
CONF_QOS = ATTR_QOS
CONF_RETAIN = ATTR_RETAIN
CONF_STATE_TOPIC = "state_topic"
CONF_TOPIC = "topic"
CONF_WILL_MESSAGE = "will_message"
DATA_MQTT_CONFIG = "mqtt_config"

View File

@ -22,6 +22,8 @@ from .const import (
ATTR_DISCOVERY_HASH,
ATTR_DISCOVERY_PAYLOAD,
ATTR_DISCOVERY_TOPIC,
CONF_AVAILABILITY,
CONF_TOPIC,
DOMAIN,
)
@ -138,6 +140,14 @@ async def async_start( # noqa: C901
payload[key] = f"{base}{value[1:]}"
if value[-1] == TOPIC_BASE and key.endswith("topic"):
payload[key] = f"{value[:-1]}{base}"
if payload.get(CONF_AVAILABILITY):
for availability_conf in payload[CONF_AVAILABILITY]:
topic = availability_conf.get(CONF_TOPIC)
if topic:
if topic[0] == TOPIC_BASE:
availability_conf[CONF_TOPIC] = f"{base}{topic[1:]}"
if topic[-1] == TOPIC_BASE:
availability_conf[CONF_TOPIC] = f"{topic[:-1]}{base}"
# 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

View File

@ -18,12 +18,14 @@ from homeassistant.helpers.dispatcher import (
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.typing import ConfigType
from . import CONF_TOPIC, DATA_MQTT, debug_info, publish, subscription
from . import DATA_MQTT, debug_info, publish, subscription
from .const import (
ATTR_DISCOVERY_HASH,
ATTR_DISCOVERY_PAYLOAD,
ATTR_DISCOVERY_TOPIC,
CONF_AVAILABILITY,
CONF_QOS,
CONF_TOPIC,
DEFAULT_PAYLOAD_AVAILABLE,
DEFAULT_PAYLOAD_NOT_AVAILABLE,
DOMAIN,
@ -50,7 +52,6 @@ AVAILABILITY_LATEST = "latest"
AVAILABILITY_MODES = [AVAILABILITY_ALL, AVAILABILITY_ANY, AVAILABILITY_LATEST]
CONF_AVAILABILITY = "availability"
CONF_AVAILABILITY_MODE = "availability_mode"
CONF_AVAILABILITY_TOPIC = "availability_topic"
CONF_ENABLED_BY_DEFAULT = "enabled_by_default"
@ -108,7 +109,7 @@ MQTT_AVAILABILITY_LIST_SCHEMA = vol.Schema(
cv.ensure_list,
[
{
vol.Optional(CONF_TOPIC): valid_subscribe_topic,
vol.Required(CONF_TOPIC): valid_subscribe_topic,
vol.Optional(
CONF_PAYLOAD_AVAILABLE, default=DEFAULT_PAYLOAD_AVAILABLE
): cv.string,

View File

@ -12,7 +12,12 @@ from homeassistant.components.mqtt.abbreviations import (
DEVICE_ABBREVIATIONS,
)
from homeassistant.components.mqtt.discovery import ALREADY_DISCOVERED, async_start
from homeassistant.const import EVENT_STATE_CHANGED, STATE_OFF, STATE_ON
from homeassistant.const import (
EVENT_STATE_CHANGED,
STATE_OFF,
STATE_ON,
STATE_UNAVAILABLE,
)
import homeassistant.core as ha
from tests.common import (
@ -449,6 +454,18 @@ async def test_discovery_expansion(hass, mqtt_mock, caplog):
' "name": "DiscoveryExpansionTest1",'
' "stat_t": "test_topic/~",'
' "cmd_t": "~/test_topic",'
' "availability": ['
" {"
' "topic":"~/avail_item1",'
' "payload_available": "available",'
' "payload_not_available": "not_available"'
" },"
" {"
' "topic":"avail_item2/~",'
' "payload_available": "available",'
' "payload_not_available": "not_available"'
" }"
" ],"
' "dev":{'
' "ids":["5706DF"],'
' "name":"DiscoveryExpansionTest1 Device",'
@ -463,6 +480,12 @@ async def test_discovery_expansion(hass, mqtt_mock, caplog):
async_fire_mqtt_message(hass, "homeassistant/switch/bla/config", data)
await hass.async_block_till_done()
state = hass.states.get("switch.DiscoveryExpansionTest1")
assert state.state == STATE_UNAVAILABLE
async_fire_mqtt_message(hass, "avail_item2/some/base/topic", "available")
await hass.async_block_till_done()
state = hass.states.get("switch.DiscoveryExpansionTest1")
assert state is not None
assert state.name == "DiscoveryExpansionTest1"
@ -474,6 +497,12 @@ async def test_discovery_expansion(hass, mqtt_mock, caplog):
state = hass.states.get("switch.DiscoveryExpansionTest1")
assert state.state == STATE_ON
async_fire_mqtt_message(hass, "some/base/topic/avail_item1", "not_available")
await hass.async_block_till_done()
state = hass.states.get("switch.DiscoveryExpansionTest1")
assert state.state == STATE_UNAVAILABLE
ABBREVIATIONS_WHITE_LIST = [
# MQTT client/server/trigger settings