1 """Provides tag scanning for MQTT."""
3 from __future__
import annotations
5 from collections.abc
import Callable
9 import voluptuous
as vol
19 from .
import subscription
20 from .config
import MQTT_BASE_SCHEMA
21 from .const
import ATTR_DISCOVERY_HASH, CONF_QOS, CONF_TOPIC
22 from .discovery
import MQTTDiscoveryPayload
24 MqttDiscoveryDeviceUpdateMixin,
25 async_handle_schema_error,
26 async_setup_non_entity_entry_helper,
33 MqttValueTemplateException,
36 from .schemas
import MQTT_ENTITY_DEVICE_INFO_SCHEMA
37 from .subscription
import EntitySubscription
38 from .util
import valid_subscribe_topic
40 _LOGGER = logging.getLogger(__name__)
46 DISCOVERY_SCHEMA = MQTT_BASE_SCHEMA.extend(
48 vol.Optional(CONF_DEVICE): MQTT_ENTITY_DEVICE_INFO_SCHEMA,
49 vol.Required(CONF_TOPIC): valid_subscribe_topic,
50 vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
52 extra=vol.REMOVE_EXTRA,
57 """Set up MQTT tag scanner dynamically through MQTT discovery."""
59 setup = functools.partial(_async_setup_tag, hass, config_entry=config_entry)
66 config_entry: ConfigEntry,
67 discovery_data: DiscoveryInfoType,
69 """Set up the MQTT tag scanner."""
70 discovery_hash = discovery_data[ATTR_DISCOVERY_HASH]
71 discovery_id = discovery_hash[1]
74 if device_id
is not None and device_id
not in (tags := hass.data[DATA_MQTT].tags):
85 await tag_scanner.subscribe_topics()
88 tags[device_id][discovery_id] = tag_scanner
94 """Device has tag scanners."""
95 if device_id
not in (tags := hass.data[DATA_MQTT].tags):
97 return tags[device_id] != {}
101 """MQTT Tag scanner."""
103 _value_template: Callable[[ReceivePayloadType, str], ReceivePayloadType]
109 device_id: str |
None,
110 discovery_data: DiscoveryInfoType,
111 config_entry: ConfigEntry,
119 self.
_sub_state_sub_state: dict[str, EntitySubscription] |
None =
None
121 config.get(CONF_VALUE_TEMPLATE)
122 ).async_render_with_possible_json_value
124 MqttDiscoveryDeviceUpdateMixin.__init__(
125 self, hass, discovery_data, device_id, config_entry, LOG_NAME
128 async
def async_update(self, discovery_data: MQTTDiscoveryPayload) ->
None:
129 """Handle MQTT tag discovery updates."""
133 except vol.Invalid
as err:
138 config.get(CONF_VALUE_TEMPLATE)
139 ).async_render_with_possible_json_value
145 """Handle new tag scanned."""
148 except MqttValueTemplateException
as exc:
154 self.
hasshasshass.async_create_task(
159 """Subscribe to MQTT topics."""
160 self.
_sub_state_sub_state = subscription.async_prepare_subscribe_topics(
165 "topic": self.
_config_config[CONF_TOPIC],
167 "qos": self.
_config_config[CONF_QOS],
168 "job_type": HassJobType.Callback,
172 subscription.async_subscribe_topics_internal(self.
hasshasshass, self.
_sub_state_sub_state)
175 """Cleanup tag scanner."""
176 discovery_hash = self.
discovery_datadiscovery_data[ATTR_DISCOVERY_HASH]
177 discovery_id = discovery_hash[1]
178 self.
_sub_state_sub_state = subscription.async_unsubscribe_topics(
181 tags = self.
hasshasshass.data[DATA_MQTT].tags
183 del tags[self.
device_iddevice_id][discovery_id]
str|None update_device(HomeAssistant hass, ConfigEntry config_entry, ConfigType config)
None send_discovery_done(HomeAssistant hass, DiscoveryInfoType discovery_data)
None async_setup_non_entity_entry_helper(HomeAssistant hass, str domain, _SetupNonEntityHelperCallbackProtocol async_setup, vol.Schema discovery_schema)
None async_handle_schema_error(MQTTDiscoveryPayload discovery_payload, vol.Invalid err)
None _async_setup_tag(HomeAssistant hass, ConfigType config, ConfigEntry config_entry, DiscoveryInfoType discovery_data)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry)
bool async_has_tags(HomeAssistant hass, str device_id)