1 """Helper to handle a set of topics to subscribe to."""
3 from __future__
import annotations
5 from collections
import deque
6 from dataclasses
import dataclass
9 from typing
import TYPE_CHECKING, Any
16 from .const
import ATTR_DISCOVERY_PAYLOAD, ATTR_DISCOVERY_TOPIC
17 from .models
import DATA_MQTT, PublishPayloadType
27 payload: PublishPayloadType
37 payload: PublishPayloadType,
41 """Log an outgoing MQTT message."""
42 entity_info = hass.data[DATA_MQTT].debug_info_entities.setdefault(
43 entity_id, {
"subscriptions": {},
"discovery_data": {},
"transmitted": {}}
45 if topic
not in entity_info[
"transmitted"]:
46 entity_info[
"transmitted"][topic] = {
47 "messages": deque([], STORED_MESSAGES),
50 topic, payload, qos, retain, timestamp=time.monotonic()
52 entity_info[
"transmitted"][topic][
"messages"].append(msg)
56 hass: HomeAssistant, subscription: str, entity_id: str |
None
58 """Prepare debug data for subscription."""
60 entity_info = hass.data[DATA_MQTT].debug_info_entities.setdefault(
61 entity_id, {
"subscriptions": {},
"discovery_data": {},
"transmitted": {}}
63 if subscription
not in entity_info[
"subscriptions"]:
64 entity_info[
"subscriptions"][subscription] = {
66 "messages": deque([], STORED_MESSAGES),
69 entity_info[
"subscriptions"][subscription][
"count"] += 1
73 hass: HomeAssistant, subscription: str, entity_id: str |
None
75 """Remove debug data for subscription if it exists."""
76 if entity_id
and entity_id
in (
77 debug_info_entities := hass.data[DATA_MQTT].debug_info_entities
79 subscriptions = debug_info_entities[entity_id][
"subscriptions"]
80 subscriptions[subscription][
"count"] -= 1
81 if not subscriptions[subscription][
"count"]:
82 del subscriptions[subscription]
86 hass: HomeAssistant, discovery_data: DiscoveryInfoType, entity_id: str
88 """Add discovery data."""
89 entity_info = hass.data[DATA_MQTT].debug_info_entities.setdefault(
90 entity_id, {
"subscriptions": {},
"discovery_data": {},
"transmitted": {}}
92 entity_info[
"discovery_data"] = discovery_data
96 hass: HomeAssistant, discovery_payload: DiscoveryInfoType, entity_id: str
98 """Update discovery data."""
99 discovery_data = hass.data[DATA_MQTT].debug_info_entities[entity_id][
103 assert discovery_data
is not None
104 discovery_data[ATTR_DISCOVERY_PAYLOAD] = discovery_payload
108 """Remove discovery data."""
109 if entity_id
in (debug_info_entities := hass.data[DATA_MQTT].debug_info_entities):
110 del debug_info_entities[entity_id]
115 discovery_hash: tuple[str, str],
116 discovery_data: DiscoveryInfoType,
119 """Add discovery data."""
120 hass.data[DATA_MQTT].debug_info_triggers[discovery_hash] = {
121 "device_id": device_id,
122 "discovery_data": discovery_data,
128 discovery_hash: tuple[str, str],
129 discovery_payload: DiscoveryInfoType,
131 """Update discovery data."""
132 hass.data[DATA_MQTT].debug_info_triggers[discovery_hash][
"discovery_data"][
133 ATTR_DISCOVERY_PAYLOAD
134 ] = discovery_payload
138 hass: HomeAssistant, discovery_hash: tuple[str, str]
140 """Remove discovery data."""
141 hass.data[DATA_MQTT].debug_info_triggers.pop(discovery_hash,
None)
145 entity_info = hass.data[DATA_MQTT].debug_info_entities[entity_id]
146 monotonic_time_diff = time.time() - time.monotonic()
152 "payload":
str(msg.payload),
154 "retain": msg.retain,
155 "time": dt_util.utc_from_timestamp(
156 msg.timestamp + monotonic_time_diff,
161 for msg
in subscription[
"messages"]
164 for topic, subscription
in entity_info[
"subscriptions"].items()
171 "payload":
str(msg.payload),
173 "retain": msg.retain,
174 "time": dt_util.utc_from_timestamp(
175 msg.timestamp + monotonic_time_diff,
180 for msg
in subscription[
"messages"]
183 for topic, subscription
in entity_info[
"transmitted"].items()
186 "topic": entity_info[
"discovery_data"].
get(ATTR_DISCOVERY_TOPIC,
""),
187 "payload": entity_info[
"discovery_data"].
get(ATTR_DISCOVERY_PAYLOAD,
""),
191 "entity_id": entity_id,
192 "subscriptions": subscriptions,
193 "discovery_data": discovery_data,
194 "transmitted": transmitted,
199 hass: HomeAssistant, trigger_key: tuple[str, str]
201 trigger = hass.data[DATA_MQTT].debug_info_triggers[trigger_key]
202 discovery_data =
None
203 if trigger[
"discovery_data"]
is not None:
205 "topic": trigger[
"discovery_data"][ATTR_DISCOVERY_TOPIC],
206 "payload": trigger[
"discovery_data"][ATTR_DISCOVERY_PAYLOAD],
208 return {
"discovery_data": discovery_data,
"trigger_key": trigger_key}
212 """Get debug info for all entities and triggers."""
214 mqtt_data = hass.data[DATA_MQTT]
215 mqtt_info: dict[str, list[Any]] = {
"entities": [],
"triggers": []}
217 mqtt_info[
"entities"].extend(
218 _info_for_entity(hass, entity_id)
for entity_id
in mqtt_data.debug_info_entities
221 mqtt_info[
"triggers"].extend(
223 for trigger_key
in mqtt_data.debug_info_triggers
230 """Get debug info for a device."""
232 mqtt_data = hass.data[DATA_MQTT]
234 mqtt_info: dict[str, list[Any]] = {
"entities": [],
"triggers": []}
235 entity_registry = er.async_get(hass)
237 entries = er.async_entries_for_device(
238 entity_registry, device_id, include_disabled_entities=
True
240 mqtt_info[
"entities"].extend(
243 if entry.entity_id
in mqtt_data.debug_info_entities
246 mqtt_info[
"triggers"].extend(
248 for trigger_key, trigger
in mqtt_data.debug_info_triggers.items()
249 if trigger[
"device_id"] == device_id
web.Response get(self, web.Request request, str config_key)
None remove_trigger_discovery_data(HomeAssistant hass, tuple[str, str] discovery_hash)
None add_entity_discovery_data(HomeAssistant hass, DiscoveryInfoType discovery_data, str entity_id)
dict[str, list[Any]] info_for_device(HomeAssistant hass, str device_id)
None remove_entity_data(HomeAssistant hass, str entity_id)
dict[str, list[Any]] info_for_config_entry(HomeAssistant hass)
None update_trigger_discovery_data(HomeAssistant hass, tuple[str, str] discovery_hash, DiscoveryInfoType discovery_payload)
None add_subscription(HomeAssistant hass, str subscription, str|None entity_id)
dict[str, Any] _info_for_entity(HomeAssistant hass, str entity_id)
dict[str, Any] _info_for_trigger(HomeAssistant hass, tuple[str, str] trigger_key)
None add_trigger_discovery_data(HomeAssistant hass, tuple[str, str] discovery_hash, DiscoveryInfoType discovery_data, str device_id)
None update_entity_discovery_data(HomeAssistant hass, DiscoveryInfoType discovery_payload, str entity_id)
None remove_subscription(HomeAssistant hass, str subscription, str|None entity_id)
None log_message(HomeAssistant hass, str entity_id, str topic, PublishPayloadType payload, int qos, bool retain)