parent
eff9b2a1a0
commit
fb93b79b12
11 changed files with 547 additions and 3 deletions
|
@ -45,7 +45,8 @@ from homeassistant.util.async_ import run_callback_threadsafe
|
||||||
from homeassistant.util.logging import catch_log_exception
|
from homeassistant.util.logging import catch_log_exception
|
||||||
|
|
||||||
# Loading the config flow file will register the flow
|
# Loading the config flow file will register the flow
|
||||||
from . import config_flow, discovery, server # noqa: F401 pylint: disable=unused-import
|
from . import config_flow # noqa: F401 pylint: disable=unused-import
|
||||||
|
from . import debug_info, discovery, server
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_DISCOVERY_HASH,
|
ATTR_DISCOVERY_HASH,
|
||||||
ATTR_DISCOVERY_TOPIC,
|
ATTR_DISCOVERY_TOPIC,
|
||||||
|
@ -56,6 +57,7 @@ from .const import (
|
||||||
DEFAULT_QOS,
|
DEFAULT_QOS,
|
||||||
PROTOCOL_311,
|
PROTOCOL_311,
|
||||||
)
|
)
|
||||||
|
from .debug_info import log_messages
|
||||||
from .discovery import MQTT_DISCOVERY_UPDATED, clear_discovery_hash, set_discovery_hash
|
from .discovery import MQTT_DISCOVERY_UPDATED, clear_discovery_hash, set_discovery_hash
|
||||||
from .models import Message, MessageCallbackType, PublishPayloadType
|
from .models import Message, MessageCallbackType, PublishPayloadType
|
||||||
from .subscription import async_subscribe_topics, async_unsubscribe_topics
|
from .subscription import async_subscribe_topics, async_unsubscribe_topics
|
||||||
|
@ -513,6 +515,7 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
|
||||||
|
|
||||||
websocket_api.async_register_command(hass, websocket_subscribe)
|
websocket_api.async_register_command(hass, websocket_subscribe)
|
||||||
websocket_api.async_register_command(hass, websocket_remove_device)
|
websocket_api.async_register_command(hass, websocket_remove_device)
|
||||||
|
websocket_api.async_register_command(hass, websocket_mqtt_info)
|
||||||
|
|
||||||
if conf is None:
|
if conf is None:
|
||||||
# If we have a config entry, setup is done by that config entry.
|
# If we have a config entry, setup is done by that config entry.
|
||||||
|
@ -1058,6 +1061,7 @@ class MqttAttributes(Entity):
|
||||||
attr_tpl.hass = self.hass
|
attr_tpl.hass = self.hass
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@log_messages(self.hass, self.entity_id)
|
||||||
def attributes_message_received(msg: Message) -> None:
|
def attributes_message_received(msg: Message) -> None:
|
||||||
try:
|
try:
|
||||||
payload = msg.payload
|
payload = msg.payload
|
||||||
|
@ -1122,6 +1126,7 @@ class MqttAvailability(Entity):
|
||||||
"""(Re)Subscribe to topics."""
|
"""(Re)Subscribe to topics."""
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@log_messages(self.hass, self.entity_id)
|
||||||
def availability_message_received(msg: Message) -> None:
|
def availability_message_received(msg: Message) -> None:
|
||||||
"""Handle a new received MQTT availability message."""
|
"""Handle a new received MQTT availability message."""
|
||||||
if msg.payload == self._avail_config[CONF_PAYLOAD_AVAILABLE]:
|
if msg.payload == self._avail_config[CONF_PAYLOAD_AVAILABLE]:
|
||||||
|
@ -1207,6 +1212,7 @@ class MqttDiscoveryUpdate(Entity):
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Got update for entity with hash: %s '%s'", discovery_hash, payload,
|
"Got update for entity with hash: %s '%s'", discovery_hash, payload,
|
||||||
)
|
)
|
||||||
|
debug_info.update_entity_discovery_data(self.hass, payload, self.entity_id)
|
||||||
if not payload:
|
if not payload:
|
||||||
# Empty payload: Remove component
|
# Empty payload: Remove component
|
||||||
_LOGGER.info("Removing component: %s", self.entity_id)
|
_LOGGER.info("Removing component: %s", self.entity_id)
|
||||||
|
@ -1219,6 +1225,9 @@ class MqttDiscoveryUpdate(Entity):
|
||||||
await self._discovery_update(payload)
|
await self._discovery_update(payload)
|
||||||
|
|
||||||
if discovery_hash:
|
if discovery_hash:
|
||||||
|
debug_info.add_entity_discovery_data(
|
||||||
|
self.hass, self._discovery_data, self.entity_id
|
||||||
|
)
|
||||||
# Set in case the entity has been removed and is re-added
|
# Set in case the entity has been removed and is re-added
|
||||||
set_discovery_hash(self.hass, discovery_hash)
|
set_discovery_hash(self.hass, discovery_hash)
|
||||||
self._remove_signal = async_dispatcher_connect(
|
self._remove_signal = async_dispatcher_connect(
|
||||||
|
@ -1242,6 +1251,7 @@ class MqttDiscoveryUpdate(Entity):
|
||||||
def _cleanup_on_remove(self) -> None:
|
def _cleanup_on_remove(self) -> None:
|
||||||
"""Stop listening to signal and cleanup discovery data."""
|
"""Stop listening to signal and cleanup discovery data."""
|
||||||
if self._discovery_data and not self._removed_from_hass:
|
if self._discovery_data and not self._removed_from_hass:
|
||||||
|
debug_info.remove_entity_data(self.hass, self.entity_id)
|
||||||
clear_discovery_hash(self.hass, self._discovery_data[ATTR_DISCOVERY_HASH])
|
clear_discovery_hash(self.hass, self._discovery_data[ATTR_DISCOVERY_HASH])
|
||||||
self._removed_from_hass = True
|
self._removed_from_hass = True
|
||||||
|
|
||||||
|
@ -1303,6 +1313,18 @@ class MqttEntityDeviceInfo(Entity):
|
||||||
return device_info_from_config(self._device_config)
|
return device_info_from_config(self._device_config)
|
||||||
|
|
||||||
|
|
||||||
|
@websocket_api.websocket_command(
|
||||||
|
{vol.Required("type"): "mqtt/device/debug_info", vol.Required("device_id"): str}
|
||||||
|
)
|
||||||
|
@websocket_api.async_response
|
||||||
|
async def websocket_mqtt_info(hass, connection, msg):
|
||||||
|
"""Get MQTT debug info for device."""
|
||||||
|
device_id = msg["device_id"]
|
||||||
|
mqtt_info = await debug_info.info_for_device(hass, device_id)
|
||||||
|
|
||||||
|
connection.send_result(msg["id"], mqtt_info)
|
||||||
|
|
||||||
|
|
||||||
@websocket_api.websocket_command(
|
@websocket_api.websocket_command(
|
||||||
{vol.Required("type"): "mqtt/device/remove", vol.Required("device_id"): str}
|
{vol.Required("type"): "mqtt/device/remove", vol.Required("device_id"): str}
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,6 +4,7 @@ CONF_DISCOVERY = "discovery"
|
||||||
DEFAULT_DISCOVERY = False
|
DEFAULT_DISCOVERY = False
|
||||||
|
|
||||||
ATTR_DISCOVERY_HASH = "discovery_hash"
|
ATTR_DISCOVERY_HASH = "discovery_hash"
|
||||||
|
ATTR_DISCOVERY_PAYLOAD = "discovery_payload"
|
||||||
ATTR_DISCOVERY_TOPIC = "discovery_topic"
|
ATTR_DISCOVERY_TOPIC = "discovery_topic"
|
||||||
CONF_STATE_TOPIC = "state_topic"
|
CONF_STATE_TOPIC = "state_topic"
|
||||||
PROTOCOL_311 = "3.1.1"
|
PROTOCOL_311 = "3.1.1"
|
||||||
|
|
146
homeassistant/components/mqtt/debug_info.py
Normal file
146
homeassistant/components/mqtt/debug_info.py
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
"""Helper to handle a set of topics to subscribe to."""
|
||||||
|
from collections import deque
|
||||||
|
from functools import wraps
|
||||||
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
|
||||||
|
from .const import ATTR_DISCOVERY_PAYLOAD, ATTR_DISCOVERY_TOPIC
|
||||||
|
from .models import MessageCallbackType
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
DATA_MQTT_DEBUG_INFO = "mqtt_debug_info"
|
||||||
|
STORED_MESSAGES = 10
|
||||||
|
|
||||||
|
|
||||||
|
def log_messages(hass: HomeAssistantType, entity_id: str) -> MessageCallbackType:
|
||||||
|
"""Wrap an MQTT message callback to support message logging."""
|
||||||
|
|
||||||
|
def _log_message(msg):
|
||||||
|
"""Log message."""
|
||||||
|
debug_info = hass.data[DATA_MQTT_DEBUG_INFO]
|
||||||
|
messages = debug_info["entities"][entity_id]["topics"][msg.topic]
|
||||||
|
messages.append(msg.payload)
|
||||||
|
|
||||||
|
def _decorator(msg_callback: MessageCallbackType):
|
||||||
|
@wraps(msg_callback)
|
||||||
|
def wrapper(msg: Any) -> None:
|
||||||
|
"""Log message."""
|
||||||
|
_log_message(msg)
|
||||||
|
msg_callback(msg)
|
||||||
|
|
||||||
|
setattr(wrapper, "__entity_id", entity_id)
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
return _decorator
|
||||||
|
|
||||||
|
|
||||||
|
def add_topic(hass, message_callback, topic):
|
||||||
|
"""Prepare debug data for topic."""
|
||||||
|
entity_id = getattr(message_callback, "__entity_id", None)
|
||||||
|
if entity_id:
|
||||||
|
debug_info = hass.data.setdefault(
|
||||||
|
DATA_MQTT_DEBUG_INFO, {"entities": {}, "triggers": {}}
|
||||||
|
)
|
||||||
|
entity_info = debug_info["entities"].setdefault(
|
||||||
|
entity_id, {"topics": {}, "discovery_data": {}}
|
||||||
|
)
|
||||||
|
entity_info["topics"][topic] = deque([], STORED_MESSAGES)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_topic(hass, message_callback, topic):
|
||||||
|
"""Remove debug data for topic."""
|
||||||
|
entity_id = getattr(message_callback, "__entity_id", None)
|
||||||
|
if entity_id and entity_id in hass.data[DATA_MQTT_DEBUG_INFO]["entities"]:
|
||||||
|
hass.data[DATA_MQTT_DEBUG_INFO]["entities"][entity_id]["topics"].pop(topic)
|
||||||
|
|
||||||
|
|
||||||
|
def add_entity_discovery_data(hass, discovery_data, entity_id):
|
||||||
|
"""Add discovery data."""
|
||||||
|
debug_info = hass.data.setdefault(
|
||||||
|
DATA_MQTT_DEBUG_INFO, {"entities": {}, "triggers": {}}
|
||||||
|
)
|
||||||
|
entity_info = debug_info["entities"].setdefault(
|
||||||
|
entity_id, {"topics": {}, "discovery_data": {}}
|
||||||
|
)
|
||||||
|
entity_info["discovery_data"] = discovery_data
|
||||||
|
|
||||||
|
|
||||||
|
def update_entity_discovery_data(hass, discovery_payload, entity_id):
|
||||||
|
"""Update discovery data."""
|
||||||
|
entity_info = hass.data[DATA_MQTT_DEBUG_INFO]["entities"][entity_id]
|
||||||
|
entity_info["discovery_data"][ATTR_DISCOVERY_PAYLOAD] = discovery_payload
|
||||||
|
|
||||||
|
|
||||||
|
def remove_entity_data(hass, entity_id):
|
||||||
|
"""Remove discovery data."""
|
||||||
|
hass.data[DATA_MQTT_DEBUG_INFO]["entities"].pop(entity_id)
|
||||||
|
|
||||||
|
|
||||||
|
def add_trigger_discovery_data(hass, discovery_hash, discovery_data, device_id):
|
||||||
|
"""Add discovery data."""
|
||||||
|
debug_info = hass.data.setdefault(
|
||||||
|
DATA_MQTT_DEBUG_INFO, {"entities": {}, "triggers": {}}
|
||||||
|
)
|
||||||
|
debug_info["triggers"][discovery_hash] = {
|
||||||
|
"device_id": device_id,
|
||||||
|
"discovery_data": discovery_data,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def update_trigger_discovery_data(hass, discovery_hash, discovery_payload):
|
||||||
|
"""Update discovery data."""
|
||||||
|
trigger_info = hass.data[DATA_MQTT_DEBUG_INFO]["triggers"][discovery_hash]
|
||||||
|
trigger_info["discovery_data"][ATTR_DISCOVERY_PAYLOAD] = discovery_payload
|
||||||
|
|
||||||
|
|
||||||
|
def remove_trigger_discovery_data(hass, discovery_hash):
|
||||||
|
"""Remove discovery data."""
|
||||||
|
hass.data[DATA_MQTT_DEBUG_INFO]["triggers"][discovery_hash]["discovery_data"] = None
|
||||||
|
|
||||||
|
|
||||||
|
async def info_for_device(hass, device_id):
|
||||||
|
"""Get debug info for a device."""
|
||||||
|
mqtt_info = {"entities": [], "triggers": []}
|
||||||
|
entity_registry = await hass.helpers.entity_registry.async_get_registry()
|
||||||
|
|
||||||
|
entries = hass.helpers.entity_registry.async_entries_for_device(
|
||||||
|
entity_registry, device_id
|
||||||
|
)
|
||||||
|
mqtt_debug_info = hass.data.setdefault(
|
||||||
|
DATA_MQTT_DEBUG_INFO, {"entities": {}, "triggers": {}}
|
||||||
|
)
|
||||||
|
for entry in entries:
|
||||||
|
if entry.entity_id not in mqtt_debug_info["entities"]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
entity_info = mqtt_debug_info["entities"][entry.entity_id]
|
||||||
|
topics = [
|
||||||
|
{"topic": topic, "messages": list(messages)}
|
||||||
|
for topic, messages in entity_info["topics"].items()
|
||||||
|
]
|
||||||
|
discovery_data = {
|
||||||
|
"topic": entity_info["discovery_data"].get(ATTR_DISCOVERY_TOPIC, ""),
|
||||||
|
"payload": entity_info["discovery_data"].get(ATTR_DISCOVERY_PAYLOAD, ""),
|
||||||
|
}
|
||||||
|
mqtt_info["entities"].append(
|
||||||
|
{
|
||||||
|
"entity_id": entry.entity_id,
|
||||||
|
"topics": topics,
|
||||||
|
"discovery_data": discovery_data,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
for trigger in mqtt_debug_info["triggers"].values():
|
||||||
|
if trigger["device_id"] != device_id:
|
||||||
|
continue
|
||||||
|
|
||||||
|
discovery_data = {
|
||||||
|
"topic": trigger["discovery_data"][ATTR_DISCOVERY_TOPIC],
|
||||||
|
"payload": trigger["discovery_data"][ATTR_DISCOVERY_PAYLOAD],
|
||||||
|
}
|
||||||
|
mqtt_info["triggers"].append({"discovery_data": discovery_data})
|
||||||
|
|
||||||
|
return mqtt_info
|
|
@ -26,6 +26,7 @@ from . import (
|
||||||
CONF_QOS,
|
CONF_QOS,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
cleanup_device_registry,
|
cleanup_device_registry,
|
||||||
|
debug_info,
|
||||||
)
|
)
|
||||||
from .discovery import MQTT_DISCOVERY_UPDATED, clear_discovery_hash
|
from .discovery import MQTT_DISCOVERY_UPDATED, clear_discovery_hash
|
||||||
|
|
||||||
|
@ -183,6 +184,7 @@ async def async_setup_trigger(hass, config, config_entry, discovery_data):
|
||||||
if not payload:
|
if not payload:
|
||||||
# Empty payload: Remove trigger
|
# Empty payload: Remove trigger
|
||||||
_LOGGER.info("Removing trigger: %s", discovery_hash)
|
_LOGGER.info("Removing trigger: %s", discovery_hash)
|
||||||
|
debug_info.remove_trigger_discovery_data(hass, discovery_hash)
|
||||||
if discovery_id in hass.data[DEVICE_TRIGGERS]:
|
if discovery_id in hass.data[DEVICE_TRIGGERS]:
|
||||||
device_trigger = hass.data[DEVICE_TRIGGERS][discovery_id]
|
device_trigger = hass.data[DEVICE_TRIGGERS][discovery_id]
|
||||||
device_trigger.detach_trigger()
|
device_trigger.detach_trigger()
|
||||||
|
@ -192,6 +194,7 @@ async def async_setup_trigger(hass, config, config_entry, discovery_data):
|
||||||
else:
|
else:
|
||||||
# Non-empty payload: Update trigger
|
# Non-empty payload: Update trigger
|
||||||
_LOGGER.info("Updating trigger: %s", discovery_hash)
|
_LOGGER.info("Updating trigger: %s", discovery_hash)
|
||||||
|
debug_info.update_trigger_discovery_data(hass, discovery_hash, payload)
|
||||||
config = TRIGGER_DISCOVERY_SCHEMA(payload)
|
config = TRIGGER_DISCOVERY_SCHEMA(payload)
|
||||||
await _update_device(hass, config_entry, config)
|
await _update_device(hass, config_entry, config)
|
||||||
device_trigger = hass.data[DEVICE_TRIGGERS][discovery_id]
|
device_trigger = hass.data[DEVICE_TRIGGERS][discovery_id]
|
||||||
|
@ -230,6 +233,9 @@ async def async_setup_trigger(hass, config, config_entry, discovery_data):
|
||||||
await hass.data[DEVICE_TRIGGERS][discovery_id].update_trigger(
|
await hass.data[DEVICE_TRIGGERS][discovery_id].update_trigger(
|
||||||
config, discovery_hash, remove_signal
|
config, discovery_hash, remove_signal
|
||||||
)
|
)
|
||||||
|
debug_info.add_trigger_discovery_data(
|
||||||
|
hass, discovery_hash, discovery_data, device.id
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_device_removed(hass: HomeAssistant, device_id: str):
|
async def async_device_removed(hass: HomeAssistant, device_id: str):
|
||||||
|
@ -241,6 +247,7 @@ async def async_device_removed(hass: HomeAssistant, device_id: str):
|
||||||
discovery_hash = device_trigger.discovery_data[ATTR_DISCOVERY_HASH]
|
discovery_hash = device_trigger.discovery_data[ATTR_DISCOVERY_HASH]
|
||||||
discovery_topic = device_trigger.discovery_data[ATTR_DISCOVERY_TOPIC]
|
discovery_topic = device_trigger.discovery_data[ATTR_DISCOVERY_TOPIC]
|
||||||
|
|
||||||
|
debug_info.remove_trigger_discovery_data(hass, discovery_hash)
|
||||||
device_trigger.detach_trigger()
|
device_trigger.detach_trigger()
|
||||||
clear_discovery_hash(hass, discovery_hash)
|
clear_discovery_hash(hass, discovery_hash)
|
||||||
device_trigger.remove_signal()
|
device_trigger.remove_signal()
|
||||||
|
|
|
@ -11,7 +11,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
|
||||||
from .abbreviations import ABBREVIATIONS, DEVICE_ABBREVIATIONS
|
from .abbreviations import ABBREVIATIONS, DEVICE_ABBREVIATIONS
|
||||||
from .const import ATTR_DISCOVERY_HASH, ATTR_DISCOVERY_TOPIC
|
from .const import ATTR_DISCOVERY_HASH, ATTR_DISCOVERY_PAYLOAD, ATTR_DISCOVERY_TOPIC
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -135,6 +135,7 @@ async def async_start(
|
||||||
setattr(payload, "__configuration_source__", f"MQTT (topic: '{topic}')")
|
setattr(payload, "__configuration_source__", f"MQTT (topic: '{topic}')")
|
||||||
discovery_data = {
|
discovery_data = {
|
||||||
ATTR_DISCOVERY_HASH: discovery_hash,
|
ATTR_DISCOVERY_HASH: discovery_hash,
|
||||||
|
ATTR_DISCOVERY_PAYLOAD: payload,
|
||||||
ATTR_DISCOVERY_TOPIC: topic,
|
ATTR_DISCOVERY_TOPIC: topic,
|
||||||
}
|
}
|
||||||
setattr(payload, "discovery_data", discovery_data)
|
setattr(payload, "discovery_data", discovery_data)
|
||||||
|
|
|
@ -35,6 +35,7 @@ from . import (
|
||||||
MqttEntityDeviceInfo,
|
MqttEntityDeviceInfo,
|
||||||
subscription,
|
subscription,
|
||||||
)
|
)
|
||||||
|
from .debug_info import log_messages
|
||||||
from .discovery import MQTT_DISCOVERY_NEW, clear_discovery_hash
|
from .discovery import MQTT_DISCOVERY_NEW, clear_discovery_hash
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -137,6 +138,7 @@ class MqttSensor(
|
||||||
template.hass = self.hass
|
template.hass = self.hass
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@log_messages(self.hass, self.entity_id)
|
||||||
def message_received(msg):
|
def message_received(msg):
|
||||||
"""Handle new MQTT messages."""
|
"""Handle new MQTT messages."""
|
||||||
payload = msg.payload
|
payload = msg.payload
|
||||||
|
|
|
@ -8,6 +8,7 @@ from homeassistant.components import mqtt
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import bind_hass
|
||||||
|
|
||||||
|
from . import debug_info
|
||||||
from .const import DEFAULT_QOS
|
from .const import DEFAULT_QOS
|
||||||
from .models import MessageCallbackType
|
from .models import MessageCallbackType
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
class EntitySubscription:
|
class EntitySubscription:
|
||||||
"""Class to hold data about an active entity topic subscription."""
|
"""Class to hold data about an active entity topic subscription."""
|
||||||
|
|
||||||
|
hass = attr.ib(type=HomeAssistantType)
|
||||||
topic = attr.ib(type=str)
|
topic = attr.ib(type=str)
|
||||||
message_callback = attr.ib(type=MessageCallbackType)
|
message_callback = attr.ib(type=MessageCallbackType)
|
||||||
unsubscribe_callback = attr.ib(type=Optional[Callable[[], None]])
|
unsubscribe_callback = attr.ib(type=Optional[Callable[[], None]])
|
||||||
|
@ -31,11 +33,16 @@ class EntitySubscription:
|
||||||
|
|
||||||
if other is not None and other.unsubscribe_callback is not None:
|
if other is not None and other.unsubscribe_callback is not None:
|
||||||
other.unsubscribe_callback()
|
other.unsubscribe_callback()
|
||||||
|
# Clear debug data if it exists
|
||||||
|
debug_info.remove_topic(self.hass, other.message_callback, other.topic)
|
||||||
|
|
||||||
if self.topic is None:
|
if self.topic is None:
|
||||||
# We were asked to remove the subscription or not to create it
|
# We were asked to remove the subscription or not to create it
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Prepare debug data
|
||||||
|
debug_info.add_topic(self.hass, self.message_callback, self.topic)
|
||||||
|
|
||||||
self.unsubscribe_callback = await mqtt.async_subscribe(
|
self.unsubscribe_callback = await mqtt.async_subscribe(
|
||||||
hass, self.topic, self.message_callback, self.qos, self.encoding
|
hass, self.topic, self.message_callback, self.qos, self.encoding
|
||||||
)
|
)
|
||||||
|
@ -77,6 +84,7 @@ async def async_subscribe_topics(
|
||||||
unsubscribe_callback=None,
|
unsubscribe_callback=None,
|
||||||
qos=value.get("qos", DEFAULT_QOS),
|
qos=value.get("qos", DEFAULT_QOS),
|
||||||
encoding=value.get("encoding", "utf-8"),
|
encoding=value.get("encoding", "utf-8"),
|
||||||
|
hass=hass,
|
||||||
)
|
)
|
||||||
# Get the current subscription state
|
# Get the current subscription state
|
||||||
current = current_subscriptions.pop(key, None)
|
current = current_subscriptions.pop(key, None)
|
||||||
|
@ -87,6 +95,8 @@ async def async_subscribe_topics(
|
||||||
for remaining in current_subscriptions.values():
|
for remaining in current_subscriptions.values():
|
||||||
if remaining.unsubscribe_callback is not None:
|
if remaining.unsubscribe_callback is not None:
|
||||||
remaining.unsubscribe_callback()
|
remaining.unsubscribe_callback()
|
||||||
|
# Clear debug data if it exists
|
||||||
|
debug_info.remove_topic(hass, remaining.message_callback, remaining.topic)
|
||||||
|
|
||||||
return new_state
|
return new_state
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import json
|
||||||
from unittest.mock import ANY
|
from unittest.mock import ANY
|
||||||
|
|
||||||
from homeassistant.components import mqtt
|
from homeassistant.components import mqtt
|
||||||
|
from homeassistant.components.mqtt import debug_info
|
||||||
from homeassistant.components.mqtt.discovery import async_start
|
from homeassistant.components.mqtt.discovery import async_start
|
||||||
from homeassistant.const import ATTR_ASSUMED_STATE, STATE_UNAVAILABLE
|
from homeassistant.const import ATTR_ASSUMED_STATE, STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
@ -519,3 +520,232 @@ async def help_test_entity_id_update_discovery_update(
|
||||||
async_fire_mqtt_message(hass, f"{topic}_2", "online")
|
async_fire_mqtt_message(hass, f"{topic}_2", "online")
|
||||||
state = hass.states.get(f"{domain}.milk")
|
state = hass.states.get(f"{domain}.milk")
|
||||||
assert state.state != STATE_UNAVAILABLE
|
assert state.state != STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
|
||||||
|
async def help_test_entity_debug_info(hass, mqtt_mock, domain, config):
|
||||||
|
"""Test debug_info.
|
||||||
|
|
||||||
|
This is a test helper for MQTT debug_info.
|
||||||
|
"""
|
||||||
|
# Add device settings to config
|
||||||
|
config = copy.deepcopy(config[domain])
|
||||||
|
config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID)
|
||||||
|
config["unique_id"] = "veryunique"
|
||||||
|
|
||||||
|
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
data = json.dumps(config)
|
||||||
|
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
device = registry.async_get_device({("mqtt", "helloworld")}, set())
|
||||||
|
assert device is not None
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"]) == 1
|
||||||
|
assert (
|
||||||
|
debug_info_data["entities"][0]["discovery_data"]["topic"]
|
||||||
|
== f"homeassistant/{domain}/bla/config"
|
||||||
|
)
|
||||||
|
assert debug_info_data["entities"][0]["discovery_data"]["payload"] == config
|
||||||
|
assert len(debug_info_data["entities"][0]["topics"]) == 1
|
||||||
|
assert {"topic": "test-topic", "messages": []} in debug_info_data["entities"][0][
|
||||||
|
"topics"
|
||||||
|
]
|
||||||
|
assert len(debug_info_data["triggers"]) == 0
|
||||||
|
|
||||||
|
|
||||||
|
async def help_test_entity_debug_info_max_messages(hass, mqtt_mock, domain, config):
|
||||||
|
"""Test debug_info message overflow.
|
||||||
|
|
||||||
|
This is a test helper for MQTT debug_info.
|
||||||
|
"""
|
||||||
|
# Add device settings to config
|
||||||
|
config = copy.deepcopy(config[domain])
|
||||||
|
config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID)
|
||||||
|
config["unique_id"] = "veryunique"
|
||||||
|
|
||||||
|
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
data = json.dumps(config)
|
||||||
|
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
device = registry.async_get_device({("mqtt", "helloworld")}, set())
|
||||||
|
assert device is not None
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"][0]["topics"]) == 1
|
||||||
|
assert {"topic": "test-topic", "messages": []} in debug_info_data["entities"][0][
|
||||||
|
"topics"
|
||||||
|
]
|
||||||
|
|
||||||
|
for i in range(0, debug_info.STORED_MESSAGES + 1):
|
||||||
|
async_fire_mqtt_message(hass, "test-topic", f"{i}")
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"][0]["topics"]) == 1
|
||||||
|
assert (
|
||||||
|
len(debug_info_data["entities"][0]["topics"][0]["messages"])
|
||||||
|
== debug_info.STORED_MESSAGES
|
||||||
|
)
|
||||||
|
messages = [f"{i}" for i in range(1, debug_info.STORED_MESSAGES + 1)]
|
||||||
|
assert {"topic": "test-topic", "messages": messages} in debug_info_data["entities"][
|
||||||
|
0
|
||||||
|
]["topics"]
|
||||||
|
|
||||||
|
|
||||||
|
async def help_test_entity_debug_info_message(
|
||||||
|
hass, mqtt_mock, domain, config, topic=None, payload=None
|
||||||
|
):
|
||||||
|
"""Test debug_info message overflow.
|
||||||
|
|
||||||
|
This is a test helper for MQTT debug_info.
|
||||||
|
"""
|
||||||
|
# Add device settings to config
|
||||||
|
config = copy.deepcopy(config[domain])
|
||||||
|
config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID)
|
||||||
|
config["unique_id"] = "veryunique"
|
||||||
|
|
||||||
|
if topic is None:
|
||||||
|
# Add default topic to config
|
||||||
|
config["state_topic"] = "state-topic"
|
||||||
|
topic = "state-topic"
|
||||||
|
|
||||||
|
if payload is None:
|
||||||
|
payload = "ON"
|
||||||
|
|
||||||
|
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
data = json.dumps(config)
|
||||||
|
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
device = registry.async_get_device({("mqtt", "helloworld")}, set())
|
||||||
|
assert device is not None
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"][0]["topics"]) >= 1
|
||||||
|
assert {"topic": topic, "messages": []} in debug_info_data["entities"][0]["topics"]
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, topic, payload)
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"][0]["topics"]) >= 1
|
||||||
|
assert {"topic": topic, "messages": [payload]} in debug_info_data["entities"][0][
|
||||||
|
"topics"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
async def help_test_entity_debug_info_remove(hass, mqtt_mock, domain, config):
|
||||||
|
"""Test debug_info.
|
||||||
|
|
||||||
|
This is a test helper for MQTT debug_info.
|
||||||
|
"""
|
||||||
|
# Add device settings to config
|
||||||
|
config = copy.deepcopy(config[domain])
|
||||||
|
config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID)
|
||||||
|
config["unique_id"] = "veryunique"
|
||||||
|
|
||||||
|
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
data = json.dumps(config)
|
||||||
|
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
device = registry.async_get_device({("mqtt", "helloworld")}, set())
|
||||||
|
assert device is not None
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"]) == 1
|
||||||
|
assert (
|
||||||
|
debug_info_data["entities"][0]["discovery_data"]["topic"]
|
||||||
|
== f"homeassistant/{domain}/bla/config"
|
||||||
|
)
|
||||||
|
assert debug_info_data["entities"][0]["discovery_data"]["payload"] == config
|
||||||
|
assert len(debug_info_data["entities"][0]["topics"]) == 1
|
||||||
|
assert {"topic": "test-topic", "messages": []} in debug_info_data["entities"][0][
|
||||||
|
"topics"
|
||||||
|
]
|
||||||
|
assert len(debug_info_data["triggers"]) == 0
|
||||||
|
assert debug_info_data["entities"][0]["entity_id"] == f"{domain}.test"
|
||||||
|
entity_id = debug_info_data["entities"][0]["entity_id"]
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", "")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"]) == 0
|
||||||
|
assert len(debug_info_data["triggers"]) == 0
|
||||||
|
assert entity_id not in hass.data[debug_info.DATA_MQTT_DEBUG_INFO]["entities"]
|
||||||
|
|
||||||
|
|
||||||
|
async def help_test_entity_debug_info_update_entity_id(hass, mqtt_mock, domain, config):
|
||||||
|
"""Test debug_info.
|
||||||
|
|
||||||
|
This is a test helper for MQTT debug_info.
|
||||||
|
"""
|
||||||
|
# Add device settings to config
|
||||||
|
config = copy.deepcopy(config[domain])
|
||||||
|
config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID)
|
||||||
|
config["unique_id"] = "veryunique"
|
||||||
|
|
||||||
|
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
dev_registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
ent_registry = mock_registry(hass, {})
|
||||||
|
|
||||||
|
data = json.dumps(config)
|
||||||
|
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
device = dev_registry.async_get_device({("mqtt", "helloworld")}, set())
|
||||||
|
assert device is not None
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"]) == 1
|
||||||
|
assert (
|
||||||
|
debug_info_data["entities"][0]["discovery_data"]["topic"]
|
||||||
|
== f"homeassistant/{domain}/bla/config"
|
||||||
|
)
|
||||||
|
assert debug_info_data["entities"][0]["discovery_data"]["payload"] == config
|
||||||
|
assert debug_info_data["entities"][0]["entity_id"] == f"{domain}.test"
|
||||||
|
assert len(debug_info_data["entities"][0]["topics"]) == 1
|
||||||
|
assert {"topic": "test-topic", "messages": []} in debug_info_data["entities"][0][
|
||||||
|
"topics"
|
||||||
|
]
|
||||||
|
assert len(debug_info_data["triggers"]) == 0
|
||||||
|
|
||||||
|
ent_registry.async_update_entity(f"{domain}.test", new_entity_id=f"{domain}.milk")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"]) == 1
|
||||||
|
assert (
|
||||||
|
debug_info_data["entities"][0]["discovery_data"]["topic"]
|
||||||
|
== f"homeassistant/{domain}/bla/config"
|
||||||
|
)
|
||||||
|
assert debug_info_data["entities"][0]["discovery_data"]["payload"] == config
|
||||||
|
assert debug_info_data["entities"][0]["entity_id"] == f"{domain}.milk"
|
||||||
|
assert len(debug_info_data["entities"][0]["topics"]) == 1
|
||||||
|
assert {"topic": "test-topic", "messages": []} in debug_info_data["entities"][0][
|
||||||
|
"topics"
|
||||||
|
]
|
||||||
|
assert len(debug_info_data["triggers"]) == 0
|
||||||
|
assert (
|
||||||
|
f"{domain}.test" not in hass.data[debug_info.DATA_MQTT_DEBUG_INFO]["entities"]
|
||||||
|
)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import json
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
from homeassistant.components.mqtt import DOMAIN
|
from homeassistant.components.mqtt import DOMAIN, debug_info
|
||||||
from homeassistant.components.mqtt.device_trigger import async_attach_trigger
|
from homeassistant.components.mqtt.device_trigger import async_attach_trigger
|
||||||
from homeassistant.components.mqtt.discovery import async_start
|
from homeassistant.components.mqtt.discovery import async_start
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
@ -1104,3 +1104,44 @@ async def test_cleanup_device_with_entity2(hass, device_reg, entity_reg, mqtt_mo
|
||||||
# Verify device registry entry is cleared
|
# Verify device registry entry is cleared
|
||||||
device_entry = device_reg.async_get_device({("mqtt", "helloworld")}, set())
|
device_entry = device_reg.async_get_device({("mqtt", "helloworld")}, set())
|
||||||
assert device_entry is None
|
assert device_entry is None
|
||||||
|
|
||||||
|
|
||||||
|
async def test_trigger_debug_info(hass, mqtt_mock):
|
||||||
|
"""Test debug_info.
|
||||||
|
|
||||||
|
This is a test helper for MQTT debug_info.
|
||||||
|
"""
|
||||||
|
entry = MockConfigEntry(domain=DOMAIN)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"automation_type": "trigger",
|
||||||
|
"topic": "test-topic",
|
||||||
|
"type": "foo",
|
||||||
|
"subtype": "bar",
|
||||||
|
"device": {
|
||||||
|
"connections": [["mac", "02:5b:26:a8:dc:12"]],
|
||||||
|
"manufacturer": "Whatever",
|
||||||
|
"name": "Beer",
|
||||||
|
"model": "Glass",
|
||||||
|
"sw_version": "0.1-beta",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
data = json.dumps(config)
|
||||||
|
async_fire_mqtt_message(hass, "homeassistant/device_automation/bla/config", data)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
device = registry.async_get_device(set(), {("mac", "02:5b:26:a8:dc:12")})
|
||||||
|
assert device is not None
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"]) == 0
|
||||||
|
assert len(debug_info_data["triggers"]) == 1
|
||||||
|
assert (
|
||||||
|
debug_info_data["triggers"][0]["discovery_data"]["topic"]
|
||||||
|
== "homeassistant/device_automation/bla/config"
|
||||||
|
)
|
||||||
|
assert debug_info_data["triggers"][0]["discovery_data"]["payload"] == config
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
"""The tests for the MQTT component."""
|
"""The tests for the MQTT component."""
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
import json
|
||||||
import ssl
|
import ssl
|
||||||
import unittest
|
import unittest
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
@ -934,3 +935,48 @@ async def test_mqtt_ws_remove_non_mqtt_device(
|
||||||
response = await client.receive_json()
|
response = await client.receive_json()
|
||||||
assert not response["success"]
|
assert not response["success"]
|
||||||
assert response["error"]["code"] == websocket_api.const.ERR_NOT_FOUND
|
assert response["error"]["code"] == websocket_api.const.ERR_NOT_FOUND
|
||||||
|
|
||||||
|
|
||||||
|
async def test_mqtt_ws_get_device_debug_info(
|
||||||
|
hass, device_reg, hass_ws_client, mqtt_mock
|
||||||
|
):
|
||||||
|
"""Test MQTT websocket device debug info."""
|
||||||
|
config_entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
await async_start(hass, "homeassistant", {}, config_entry)
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"device": {"identifiers": ["0AFFD2"]},
|
||||||
|
"platform": "mqtt",
|
||||||
|
"state_topic": "foobar/sensor",
|
||||||
|
"unique_id": "unique",
|
||||||
|
}
|
||||||
|
data = json.dumps(config)
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Verify device entry is created
|
||||||
|
device_entry = device_reg.async_get_device({("mqtt", "0AFFD2")}, set())
|
||||||
|
assert device_entry is not None
|
||||||
|
|
||||||
|
client = await hass_ws_client(hass)
|
||||||
|
await client.send_json(
|
||||||
|
{"id": 5, "type": "mqtt/device/debug_info", "device_id": device_entry.id}
|
||||||
|
)
|
||||||
|
response = await client.receive_json()
|
||||||
|
assert response["success"]
|
||||||
|
expected_result = {
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"entity_id": "sensor.mqtt_sensor",
|
||||||
|
"topics": [{"topic": "foobar/sensor", "messages": []}],
|
||||||
|
"discovery_data": {
|
||||||
|
"payload": config,
|
||||||
|
"topic": "homeassistant/sensor/bla/config",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"triggers": [],
|
||||||
|
}
|
||||||
|
assert response["result"] == expected_result
|
||||||
|
|
|
@ -19,6 +19,11 @@ from .test_common import (
|
||||||
help_test_discovery_removal,
|
help_test_discovery_removal,
|
||||||
help_test_discovery_update,
|
help_test_discovery_update,
|
||||||
help_test_discovery_update_attr,
|
help_test_discovery_update_attr,
|
||||||
|
help_test_entity_debug_info,
|
||||||
|
help_test_entity_debug_info_max_messages,
|
||||||
|
help_test_entity_debug_info_message,
|
||||||
|
help_test_entity_debug_info_remove,
|
||||||
|
help_test_entity_debug_info_update_entity_id,
|
||||||
help_test_entity_device_info_remove,
|
help_test_entity_device_info_remove,
|
||||||
help_test_entity_device_info_update,
|
help_test_entity_device_info_update,
|
||||||
help_test_entity_device_info_with_connection,
|
help_test_entity_device_info_with_connection,
|
||||||
|
@ -437,3 +442,36 @@ async def test_entity_device_info_with_hub(hass, mqtt_mock):
|
||||||
device = registry.async_get_device({("mqtt", "helloworld")}, set())
|
device = registry.async_get_device({("mqtt", "helloworld")}, set())
|
||||||
assert device is not None
|
assert device is not None
|
||||||
assert device.via_device_id == hub.id
|
assert device.via_device_id == hub.id
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entity_debug_info(hass, mqtt_mock):
|
||||||
|
"""Test MQTT sensor debug info."""
|
||||||
|
await help_test_entity_debug_info(hass, mqtt_mock, sensor.DOMAIN, DEFAULT_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entity_debug_info_max_messages(hass, mqtt_mock):
|
||||||
|
"""Test MQTT sensor debug info."""
|
||||||
|
await help_test_entity_debug_info_max_messages(
|
||||||
|
hass, mqtt_mock, sensor.DOMAIN, DEFAULT_CONFIG
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entity_debug_info_message(hass, mqtt_mock):
|
||||||
|
"""Test MQTT debug info."""
|
||||||
|
await help_test_entity_debug_info_message(
|
||||||
|
hass, mqtt_mock, sensor.DOMAIN, DEFAULT_CONFIG
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entity_debug_info_remove(hass, mqtt_mock):
|
||||||
|
"""Test MQTT sensor debug info."""
|
||||||
|
await help_test_entity_debug_info_remove(
|
||||||
|
hass, mqtt_mock, sensor.DOMAIN, DEFAULT_CONFIG
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entity_debug_info_update_entity_id(hass, mqtt_mock):
|
||||||
|
"""Test MQTT sensor debug info."""
|
||||||
|
await help_test_entity_debug_info_update_entity_id(
|
||||||
|
hass, mqtt_mock, sensor.DOMAIN, DEFAULT_CONFIG
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue