From 22afa3b871c6e09b085404b93621ad06be2a6141 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Thu, 31 Oct 2024 07:37:35 +0100 Subject: [PATCH] Add device based MQTT auto discovery (#33072) * Revert "Revert "Add device based MQTT auto discovery (#31122)" (#33059)" This reverts commit ba80f8b73ac22fbfdb328cfd6cdad475e7aa187e. * Document `migrate_discovery` option * Add note that unique_id is required for device based discovery * Rework docs for different use of migrate_discovery option flag * Follow up from code-review * Re-using discovery_id is no longer required * Follow up on review * more follow up * More corrections * Add column * typo * Remove duplicate header * Clearify json example * changed abbreviation `cmps` and added abbreviation `p` * Update source/_integrations/mqtt.markdown Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * More follow up actions * Fix back ticks * Remove redundant header and redundant origing documentation --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../alarm_control_panel.mqtt.markdown | 6 +- .../_integrations/binary_sensor.mqtt.markdown | 6 +- source/_integrations/button.mqtt.markdown | 6 +- source/_integrations/camera.mqtt.markdown | 2 +- source/_integrations/climate.mqtt.markdown | 2 +- source/_integrations/cover.mqtt.markdown | 6 +- .../device_tracker.mqtt.markdown | 6 +- .../device_trigger.mqtt.markdown | 4 + source/_integrations/event.mqtt.markdown | 6 +- source/_integrations/fan.mqtt.markdown | 6 +- source/_integrations/humidifier.mqtt.markdown | 6 +- source/_integrations/image.mqtt.markdown | 2 +- source/_integrations/lawn_mower.mqtt.markdown | 6 +- source/_integrations/light.mqtt.markdown | 18 +- source/_integrations/lock.mqtt.markdown | 6 +- source/_integrations/mqtt.markdown | 423 ++++++++++++++++-- source/_integrations/notify.mqtt.markdown | 2 +- source/_integrations/number.mqtt.markdown | 6 +- source/_integrations/scene.mqtt.markdown | 6 +- source/_integrations/select.mqtt.markdown | 6 +- source/_integrations/sensor.mqtt.markdown | 6 +- source/_integrations/siren.mqtt.markdown | 6 +- source/_integrations/switch.mqtt.markdown | 6 +- source/_integrations/text.mqtt.markdown | 6 +- source/_integrations/update.mqtt.markdown | 4 + source/_integrations/vacuum.mqtt.markdown | 6 +- source/_integrations/valve.mqtt.markdown | 6 +- .../_integrations/water_heater.mqtt.markdown | 6 +- 28 files changed, 505 insertions(+), 72 deletions(-) diff --git a/source/_integrations/alarm_control_panel.mqtt.markdown b/source/_integrations/alarm_control_panel.mqtt.markdown index efc95565ff3..ca3da05d9d2 100644 --- a/source/_integrations/alarm_control_panel.mqtt.markdown +++ b/source/_integrations/alarm_control_panel.mqtt.markdown @@ -243,6 +243,10 @@ payload_trigger: required: false type: string default: TRIGGER +platform: + description: Must be `alarm_control_panel`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -263,7 +267,7 @@ supported_features: type: list default: ["arm_home", "arm_away", "arm_night", "arm_vacation", "arm_custom_bypass", "trigger"] unique_id: - description: An ID that uniquely identifies this alarm panel. If two alarm panels have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this alarm panel. If two alarm panels have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: diff --git a/source/_integrations/binary_sensor.mqtt.markdown b/source/_integrations/binary_sensor.mqtt.markdown index cf8e53b0715..67870e33c85 100644 --- a/source/_integrations/binary_sensor.mqtt.markdown +++ b/source/_integrations/binary_sensor.mqtt.markdown @@ -196,6 +196,10 @@ payload_on: required: false type: string default: "ON" +platform: + description: Must be `binary_sensor`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -206,7 +210,7 @@ state_topic: required: true type: string unique_id: - description: An ID that uniquely identifies this sensor. If two sensors have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this sensor. If two sensors have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: diff --git a/source/_integrations/button.mqtt.markdown b/source/_integrations/button.mqtt.markdown index 614eb0ad227..98eeb6fa466 100644 --- a/source/_integrations/button.mqtt.markdown +++ b/source/_integrations/button.mqtt.markdown @@ -175,6 +175,10 @@ payload_press: required: false type: string default: "PRESS" +platform: + description: Must be `button`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -186,7 +190,7 @@ retain: type: boolean default: false unique_id: - description: An ID that uniquely identifies this button entity. If two buttons have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this button entity. If two buttons have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string {% endconfiguration %} diff --git a/source/_integrations/camera.mqtt.markdown b/source/_integrations/camera.mqtt.markdown index 1a1b8f65f11..ff672f202b9 100644 --- a/source/_integrations/camera.mqtt.markdown +++ b/source/_integrations/camera.mqtt.markdown @@ -166,7 +166,7 @@ topic: required: true type: string unique_id: - description: An ID that uniquely identifies this camera. If two cameras have the same unique ID Home Assistant will raise an exception. + description: An ID that uniquely identifies this camera. If two cameras have the same unique ID Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string {% endconfiguration %} diff --git a/source/_integrations/climate.mqtt.markdown b/source/_integrations/climate.mqtt.markdown index dcedf53c265..f0149f75f5a 100644 --- a/source/_integrations/climate.mqtt.markdown +++ b/source/_integrations/climate.mqtt.markdown @@ -406,7 +406,7 @@ temp_step: required: false default: 1 unique_id: - description: An ID that uniquely identifies this HVAC device. If two HVAC devices have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this HVAC device. If two HVAC devices have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: diff --git a/source/_integrations/cover.mqtt.markdown b/source/_integrations/cover.mqtt.markdown index d1727d2ea14..f847fd28ad5 100644 --- a/source/_integrations/cover.mqtt.markdown +++ b/source/_integrations/cover.mqtt.markdown @@ -203,6 +203,10 @@ payload_stop: required: false type: string default: STOP +platform: + description: Must be `cover`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string position_closed: description: Number which represents closed position. required: false @@ -310,7 +314,7 @@ tilt_status_topic: required: false type: string unique_id: - description: An ID that uniquely identifies this cover. If two covers have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this cover. If two covers have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: diff --git a/source/_integrations/device_tracker.mqtt.markdown b/source/_integrations/device_tracker.mqtt.markdown index e36c0db84ba..47346c4564f 100644 --- a/source/_integrations/device_tracker.mqtt.markdown +++ b/source/_integrations/device_tracker.mqtt.markdown @@ -167,6 +167,10 @@ payload_reset: required: false type: string default: '"None"' +platform: + description: Must be `device_tracker`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -181,7 +185,7 @@ state_topic: required: false type: string unique_id: - description: "An ID that uniquely identifies this device_tracker. If two device_trackers have the same unique ID, Home Assistant will raise an exception." + description: "An ID that uniquely identifies this device_tracker. If two device_trackers have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery." required: false type: string value_template: diff --git a/source/_integrations/device_trigger.mqtt.markdown b/source/_integrations/device_trigger.mqtt.markdown index bc2e1dff2a0..82fad046f0e 100644 --- a/source/_integrations/device_trigger.mqtt.markdown +++ b/source/_integrations/device_trigger.mqtt.markdown @@ -26,6 +26,10 @@ payload: description: Optional payload to match the payload being sent over the topic. required: false type: string +platform: + description: Must be `device_automation`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false diff --git a/source/_integrations/event.mqtt.markdown b/source/_integrations/event.mqtt.markdown index 484d864faea..7393e23030c 100644 --- a/source/_integrations/event.mqtt.markdown +++ b/source/_integrations/event.mqtt.markdown @@ -168,6 +168,10 @@ payload_not_available: required: false type: string default: offline +platform: + description: Must be `event`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -178,7 +182,7 @@ state_topic: required: true type: string unique_id: - description: An ID that uniquely identifies this event entity. If two events have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this event entity. If two events have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: diff --git a/source/_integrations/fan.mqtt.markdown b/source/_integrations/fan.mqtt.markdown index 8eef4c3a2b6..8832c7c3461 100644 --- a/source/_integrations/fan.mqtt.markdown +++ b/source/_integrations/fan.mqtt.markdown @@ -258,6 +258,10 @@ percentage_value_template: description: Defines a [template](/docs/configuration/templating/#using-templates-with-the-mqtt-integration) to extract the `percentage` value from the payload received on `percentage_state_topic`. required: false type: template +platform: + description: Must be `fan`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string preset_mode_command_template: description: Defines a [template](/docs/configuration/templating/#using-templates-with-the-mqtt-integration) to generate the payload to send to `preset_mode_command_topic`. required: false @@ -308,7 +312,7 @@ state_value_template: required: false type: template unique_id: - description: An ID that uniquely identifies this fan. If two fans have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this fan. If two fans have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string {% endconfiguration %} diff --git a/source/_integrations/humidifier.mqtt.markdown b/source/_integrations/humidifier.mqtt.markdown index fbbc9883563..26039efe1c0 100644 --- a/source/_integrations/humidifier.mqtt.markdown +++ b/source/_integrations/humidifier.mqtt.markdown @@ -270,6 +270,10 @@ modes: required: false type: [list] default: [] +platform: + description: Must be `humidifier`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -289,7 +293,7 @@ state_value_template: required: false type: template unique_id: - description: An ID that uniquely identifies this humidifier. If two humidifiers have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this humidifier. If two humidifiers have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string {% endconfiguration %} diff --git a/source/_integrations/image.mqtt.markdown b/source/_integrations/image.mqtt.markdown index 86b27ebe6e8..9186abdae55 100644 --- a/source/_integrations/image.mqtt.markdown +++ b/source/_integrations/image.mqtt.markdown @@ -169,7 +169,7 @@ object_id: required: false type: string unique_id: - description: An ID that uniquely identifies this image. If two images have the same unique ID Home Assistant will raise an exception. + description: An ID that uniquely identifies this image. If two images have the same unique ID Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string url_template: diff --git a/source/_integrations/lawn_mower.mqtt.markdown b/source/_integrations/lawn_mower.mqtt.markdown index e4f73c22d46..af41a8f0fb2 100644 --- a/source/_integrations/lawn_mower.mqtt.markdown +++ b/source/_integrations/lawn_mower.mqtt.markdown @@ -179,6 +179,10 @@ pause_command_topic: description: The MQTT topic that publishes commands when the `lawn_mower.pause` action is performed. The value `pause` is published when the action is used. Use a `pause_command_template` to publish a custom format. required: false type: string +platform: + description: Must be `lawn_mower`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -198,7 +202,7 @@ retain: type: boolean default: false unique_id: - description: An ID that uniquely identifies this lawn mower. If two lawn mowers have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this lawn mower. If two lawn mowers have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string {% endconfiguration %} diff --git a/source/_integrations/light.mqtt.markdown b/source/_integrations/light.mqtt.markdown index 583db12a618..245ba223fe4 100644 --- a/source/_integrations/light.mqtt.markdown +++ b/source/_integrations/light.mqtt.markdown @@ -303,6 +303,10 @@ payload_on: required: false type: string default: "ON" +platform: + description: Must be `light`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -375,7 +379,7 @@ state_value_template: required: false type: template unique_id: - description: An ID that uniquely identifies this light. If two lights have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this light. If two lights have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string white_command_topic: @@ -696,6 +700,10 @@ payload_not_available: required: false type: string default: offline +platform: + description: Must be `light`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -720,7 +728,7 @@ supported_color_modes: required: false type: list unique_id: - description: An ID that uniquely identifies this light. If two lights have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this light. If two lights have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string white_scale: @@ -1078,6 +1086,10 @@ payload_not_available: required: false type: string default: offline +platform: + description: Must be `light`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -1101,7 +1113,7 @@ state_topic: required: false type: string unique_id: - description: An ID that uniquely identifies this light. If two lights have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this light. If two lights have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string {% endconfiguration %} diff --git a/source/_integrations/lock.mqtt.markdown b/source/_integrations/lock.mqtt.markdown index 95705091b0b..69fa475d9f0 100644 --- a/source/_integrations/lock.mqtt.markdown +++ b/source/_integrations/lock.mqtt.markdown @@ -205,6 +205,10 @@ payload_reset: required: false type: string default: '"None"' +platform: + description: Must be `lock`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -245,7 +249,7 @@ state_unlocking: type: string default: UNLOCKING unique_id: - description: An ID that uniquely identifies this lock. If two locks have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this lock. If two locks have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: diff --git a/source/_integrations/mqtt.markdown b/source/_integrations/mqtt.markdown index 3538aabbbb1..7b9cb3beff4 100644 --- a/source/_integrations/mqtt.markdown +++ b/source/_integrations/mqtt.markdown @@ -296,15 +296,333 @@ The discovery topic needs to follow a specific format: //[/]/config ``` -- ``: The Discovery Prefix defaults to `homeassistant`. This prefix can be [changed](#discovery-options). -- ``: One of the supported MQTT integrations, eg. `binary_sensor`. -- `` (*Optional*): ID of the node providing the topic, this is not used by Home Assistant but may be used to structure the MQTT topic. The ID of the node must only consist of characters from the character class `[a-zA-Z0-9_-]` (alphanumerics, underscore and hyphen). +- ``: The Discovery Prefix defaults to `homeassistant` and this prefix can be [changed](#discovery-options). +- ``: One of the supported MQTT integrations, e.g., `binary_sensor`, or `device` in case of a device discovery. +- ``: (*Optional*): ID of the node providing the topic, this is not used by Home Assistant but may be used to structure the MQTT topic. The ID of the node must only consist of characters from the character class `[a-zA-Z0-9_-]` (alphanumerics, underscore and hyphen). - ``: The ID of the device. This is only to allow for separate topics for each device and is not used for the `entity_id`. The ID of the device must only consist of characters from the character class `[a-zA-Z0-9_-]` (alphanumerics, underscore and hyphen). The `` level can be used by clients to only subscribe to their own (command) topics by using one wildcard topic like `/+//+/set`. Best practice for entities with a `unique_id` is to set `` to `unique_id` and omit the ``. +#### Device discovery payload + +A device can send a discovery payload to expose all components for a device. +The `` part in the discovery topic must be set to `device`. + +As an alternative, it is also possible a device [can send a discovery payload for each component](/integrations/mqtt/#single-component-discovery-payload) it wants to set up. + +The shared options at the root level of the JSON message must include: + +- `device` mapping (abbreviated as `dev`) +- `origin` mapping (abbreviated as `o`) + +These mappings are mandatory and cannot be overridden at the entity/component level. + +Supported shared options are: + +- The `availability` [options](/integrations/mqtt/#using-availability-topics). +- The `origin` (required) [options](/integrations/mqtt/#adding-information-about-the-origin-of-a-discovery-message) +- `command_topic` +- `state_topic` +- `qos` +- `encoding` + +The component specific options are placed as mappings under the `components` key (abbreviated as `cmp`) like: + +```json +{ + "dev": { + "ids": "ea334450945afc", + "name": "Kitchen", + "mf": "Bla electronics", + "mdl": "xya", + "sw": "1.0", + "sn": "ea334450945afc", + "hw": "1.0rev2", + }, + "o": { + "name":"bla2mqtt", + "sw": "2.1", + "url": "https://bla2mqtt.example.com/support", + }, + "cmps": { + "some_unique_component_id1": { + "p": "sensor", + "device_class":"temperature", + "unit_of_measurement":"°C", + "value_template":"{% raw %}{{ value_json.temperature}}{% endraw %}", + "unique_id":"temp01ae_t", + }, + "some_unique_id2": { + "p": "sensor", + "device_class":"humidity", + "unit_of_measurement":"%", + "value_template":"{% raw %}{{ value_json.humidity}}{% endraw %}", + "unique_id":"temp01ae_h", + } + }, + "state_topic":"sensorBedroom/state", + "qos": 2, +} +``` + +The components id's under the `components` (`cmp`) key, are used as part of the discovery identification. A `platform` (`p`) config option is required for each component config that is added to identify the component platform. Also required is a `unique_id` for entity-based components. + +To remove the components, publish an empty (retained) string payload to the discovery topic. This will remove the component and clear the published discovery payload. It will also remove the device entry if there are no further references to it. + +An empty config can be published as an update to remove a single component from the device discovery. Note that adding the `platform` (`p`) option is still required. + +```json +{ + "dev": { + "ids": "ea334450945afc", + "name": "Kitchen", + "mf": "Bla electronics", + "mdl": "xya", + "sw": "1.0", + "sn": "ea334450945afc", + "hw": "1.0rev2", + }, + "o": { + "name":"bla2mqtt", + "sw": "2.1", + "url": "https://bla2mqtt.example.com/support", + }, + "cmps": { + "some_unique_component_id1": { + "p": "sensor", + "device_class":"temperature", + "unit_of_measurement":"°C", + "value_template":"{% raw %}{{ value_json.temperature}}{% endraw %}", + "unique_id":"temp01ae_t", + }, + "some_unique_id2": { + "p": "sensor", + } + }, + "state_topic":"sensorBedroom/state", + "qos": 2, +} +``` + +This will explicitly remove the humidity sensor and its entry. + +After removing a component, you should send another update with the removed component omitted from the configuration. This ensures that Home Assistant has the most up-to-date device configuration. For example: + +```json +{ + "dev": { + "ids": "ea334450945afc", + "name": "Kitchen", + "mf": "Bla electronics", + "mdl": "xya", + "sw": "1.0", + "sn": "ea334450945afc", + "hw": "1.0rev2", + }, + "o": { + "name":"bla2mqtt", + "sw": "2.1", + "url": "https://bla2mqtt.example.com/support", + }, + "cmps": { + "some_unique_component_id1": { + "p": "sensor", + "device_class":"temperature", + "unit_of_measurement":"°C", + "value_template":"{% raw %}{{ value_json.temperature}}{% endraw %}", + "unique_id":"temp01ae_t", + } + }, + "state_topic":"sensorBedroom/state", + "qos": 2, +} +``` + +
+ +A component config part in a device discovery payload must have the `platform` (`p`) option set with the name of the `component` and also must have at least one component specific config option. Entity components must have set the `unique_id` option and have a `device` context. + +
+ +##### Migration from single component to device-based discovery + +To allow a smooth migration from single component discovery to device-based discovery: + +1. Ensure all entities have a `unique_id` and a `device` context. +2. Move the `object_id` inside the discovery payload, if that is available, or use a unique ID or the component. +3. Consider using the previous `node_id` as the new `object_id` of the device discovery topic. +4. Ensure the `unique_id` matches and the `device` context has the correct identifiers. +5. Send the following payload to all existing single component discovery topics: + +```json +{"migrate_discovery": true } +``` + +This will unload the discovered item, but its settings will be retained. +6. Switch the discovery topic to the device-based discovery topic and include all the component configurations. +7. Clean up the single component discovery messages with an empty payload. + +During the migration steps, INFO messages will be logged to inform you about the progress of the migration. + +{% important %} +Consider testing the migration process in a non-production environment before applying it to a live system. +{% endimportant %} + +#### Discovery migration example with a device automation and a sensor + +**Step 1: Original single component discovery configurations:** + +Discovery topic single: `homeassistant/device_automation/0AFFD2/bla1/config` +Discovery id: `0AFFD2 bla1` *(both `0AFFD2` and `bla1` from the discovery topic)* +Discovery payload single: + +```json +{ + "device": { + "identifiers": ["0AFFD2"], + "name": "Test device" + }, + "o": { + "name": "foobar" + }, + "automation_type": "trigger", + "payload": "short_press", + "topic": "foobar/triggers/button1", + "type": "button_short_press", + "subtype": "button_1" +} +``` + +Discovery topic single: `homeassistant/sensor/0AFFD2/bla2/config` +Discovery id: `0AFFD2 bla2` *(both `0AFFD2` and `bla2` from the discovery topic)* +Discovery payload single: + +```json +{ + "device": { + "identifiers": ["0AFFD2"], + "name": "Test device" + }, + "o": { + "name": "foobar" + }, + "state_topic": "foobar/sensor/sensor1", + "unique_id": "bla_sensor001" +} +``` + +**Step 2: Initiate migration by publishing to both discovery topics:** + +When these single component discovery payloads are processed, and we want to initiate migration to a device-based discovery, we need to publish ... + +```json +{"migrate_discovery": true } +``` + +... to both discovery topics ... + +- `homeassistant/device_automation/0AFFD2/bla1/config` +- `homeassistant/sensor/0AFFD2/bla2/config` + +{% important %} +Check the logs to ensure this step is executed correctly. +{% endimportant %} + +**Step 3: Publish the new device-based discovery configuration:** + +Discovery topic device: `homeassistant/device/0AFFD2/config` +Discovery id: `0AFFD2 bla` *(`0AFFD2`from discovery topic, `bla`: The key under `cmp` in the discovery payload)* +Discovery payload device: + +```json +{ + "device": { + "identifiers": [ + "0AFFD2" + ] + }, + "o": { + "name": "foobar" + }, + "cmps": { + "bla1": { + "p": "device_automation", + "automation_type": "trigger", + "payload": "short_press", + "topic": "foobar/triggers/button1", + "type": "button_short_press", + "subtype": "button_1" + }, + "bla2": { + "p": "sensor", + "state_topic": "foobar/sensor/sensor1", + "unique_id": "bla_sensor001" + } + }, +} +``` + +{% important %} +Check the logs to ensure the migration was successful. +{% endimportant %} + +**Step 4: Clean up after successful migration:** + +After the logs show a successful migration, the single component discovery topics can be cleaned up safely by publishing an empty payload to them. +The logs should indicate if the discovery migration was successful. + +**Optional: Rolling back the migration:** + +To rollback publish ... + +```json +{"migrate_discovery": true } +``` + +To the device-based discovery topic(s). +After that, re-publish the single component discovery payloads. +At last, clean up the device-based discovery payloads by publishing an empty payload. + +Check the logs for every step. + +#### Single component discovery payload + +The `` part in the discovery topic must be one of the supported MQTT-platforms. +The options in the payload are only used to set up one specific component. If there are more components, more discovery payloads need to be sent for the other components, and it is then recommended to use [device-based discovery](/integrations/mqtt/#device-discovery-payload) instead. + +Example discovery payload: + +```json +{ + "dev": { + "ids": "ea334450945afc", + "name": "Kitchen", + "mf": "Bla electronics", + "mdl": "xya", + "sw": "1.0", + "sn": "ea334450945afc", + "hw": "1.0rev2", + }, + "o": { + "name":"bla2mqtt", + "sw": "2.1", + "url": "https://bla2mqtt.example.com/support", + }, + "device_class":"temperature", + "unit_of_measurement":"°C", + "value_template":"{% raw %}{{ value_json.temperature}}{% endraw %}", + "unique_id":"temp01ae_t", + "state_topic":"sensorBedroom/state", + "qos": 2, +} +``` + +To remove the component, publish an empty string to the discovery topic. This will remove the component and clear the published discovery payload. It will also remove the device entry if there are no further references to it. + +For more examples [see](/integrations/mqtt/#discovery-examples-with-component-discovery). + #### Discovery payload The payload must be a serialized JSON dictionary and will be checked like an entry in your {% term "`configuration.yaml`" %} file if a new device is added, with the exception that unknown configuration keys are allowed but ignored. This means that missing variables will be filled with the integration's default values. All configuration variables which are *required* must be present in the payload. The reason for allowing unknown documentation keys is allow some backwards compatibility, software generating MQTT discovery messages can then be used with older Home Assistant versions which will simply ignore new features. @@ -316,17 +634,21 @@ In the value of configuration variables ending with `_topic`, `~` will be replac Configuration variable names in the discovery payload may be abbreviated to conserve memory when sending a discovery message from memory constrained devices. -It is encouraged to add additional information about the origin that supplies MQTT entities via MQTT discovery by adding the `origin` option (can be abbreviated to `o`) to the discovery payload. Note that these options also support abbreviations. Information of the origin will be logged to the core event log when an item is discovered or updated. +It is recommended to add information about the origin of MQTT entities by including the `origin` option (abbreviated as `o`) in the discovery payload. For device-based discovery, this information is required. The origin details will be logged in the core event log when an item is discovered or updated. Adding origin information helps with troubleshooting and provides valuable context about the source of MQTT messages in your Home Assistant setup. + +Note: These options also support abbreviations, as shown in the table below. {% configuration_basic %} name: - description: The name of the application that is the origin the discovered MQTT item. This option is required. + description: The name of the application that is the origin of the discovered MQTT item. (Required) sw_version: description: Software version of the application that supplies the discovered MQTT item. support_url: description: Support URL of the application that supplies the discovered MQTT item. {% endconfiguration_basic %} +#### Supported abbreviations in MQTT discovery messages + {% details "Supported abbreviations" %} ```txt @@ -363,6 +685,7 @@ support_url: 'cmd_on_tpl': 'command_on_template', 'cmd_t': 'command_topic', 'cmd_tpl': 'command_template', + 'cmps': 'components', 'cod_arm_req': 'code_arm_required', 'cod_dis_req': 'code_disarm_required', 'cod_trig_req': 'code_trigger_required', @@ -419,6 +742,7 @@ support_url: 'max_hum': 'max_humidity', 'max_mirs': 'max_mireds', 'max_temp': 'max_temp', + 'migr_discvry': 'migrate_discovery', 'min': 'min', 'min_hum': 'min_humidity', 'min_mirs': 'min_mireds', @@ -440,6 +764,7 @@ support_url: 'osc_cmd_tpl': 'oscillation_command_template', 'osc_stat_t': 'oscillation_state_topic', 'osc_val_tpl': 'oscillation_value_template', + 'platform': 'p', 'pct_cmd_t': 'percentage_command_topic', 'pct_cmd_tpl': 'percentage_command_template', 'pct_stat_t': 'percentage_state_topic', @@ -612,7 +937,7 @@ support_url: {% enddetails %} -### How to use discovery messages +### Discovery messages en availability When MQTT discovery is set up, and a device or service sends a discovery message, an MQTT entity, tag, or device automation will be set up directly after receiving the message. @@ -702,47 +1027,21 @@ availability_template: description: "Defines a [template](/docs/configuration/templating/#using-templates-with-the-mqtt-integration) to extract device's availability from the `availability_topic`. To determine the devices's availability result of this template will be compared to `payload_available` and `payload_not_available`." required: false type: template +payload_available: + description: The payload that represents the available state. + required: false + type: string + default: online +payload_not_available: + description: The payload that represents the unavailable state. + required: false + type: string + default: offline {% endconfiguration %} {% enddetails %} -### Support by third-party tools - -The following software has built-in support for MQTT discovery: - -- [ArduinoHA](https://github.com/dawidchyrzynski/arduino-home-assistant) -- [Arilux AL-LC0X LED controllers](https://github.com/smrtnt/Arilux_AL-LC0X) -- [ble2mqtt](https://github.com/devbis/ble2mqtt) -- [digitalstrom-mqtt](https://github.com/gaetancollaud/digitalstrom-mqtt) -- [ebusd](https://github.com/john30/ebusd) -- [ecowitt2mqtt](https://github.com/bachya/ecowitt2mqtt) -- [EMS-ESP32 (and EMS-ESP)](https://github.com/emsesp/EMS-ESP32) -- [ESPHome](https://esphome.io) -- [ESPurna](https://github.com/xoseperez/espurna) -- [go-iotdevice](https://github.com/koestler/go-iotdevice) -- [HASS.Agent](https://github.com/LAB02-Research/HASS.Agent) -- [IOTLink](https://iotlink.gitlab.io) (starting with 2.0.0) -- [MiFlora MQTT Daemon](https://github.com/ThomDietrich/miflora-mqtt-daemon) -- [MyElectricalData](https://github.com/MyElectricalData/myelectricaldata_import#english) -- [Nuki Hub](https://github.com/technyon/nuki_hub) -- [Nuki Smart Lock 3.0 Pro](https://support.nuki.io/hc/articles/12947926779409-MQTT-support), [more info](https://developer.nuki.io/t/mqtt-api-specification-v1-3/17626) -- [OpenMQTTGateway](https://github.com/1technophile/OpenMQTTGateway) -- [room-assistant](https://github.com/mKeRix/room-assistant) (starting with 1.1.0) -- [SmartHome](https://github.com/roncoa/SmartHome) -- [SpeedTest-CLI MQTT](https://github.com/adorobis/speedtest-CLI2mqtt) -- [SwitchBot-MQTT-BLE-ESP32](https://github.com/devWaves/SwitchBot-MQTT-BLE-ESP32) -- [Tasmota](https://github.com/arendst/Tasmota) (starting with 5.11.1e, development halted) -- [TeddyCloud](https://github.com/toniebox-reverse-engineering/teddycloud) -- [Teleinfo MQTT](https://fmartinou.github.io/teleinfo2mqtt) (starting with 3.0.0) -- [Tydom2MQTT](https://fmartinou.github.io/tydom2mqtt/) -- [What's up Docker?](https://fmartinou.github.io/whats-up-docker/) (starting with 3.5.0) -- [WyzeSense2MQTT](https://github.com/raetha/wyzesense2mqtt) -- [Xiaomi DaFang Hacks](https://github.com/EliasKotlyar/Xiaomi-Dafang-Hacks) -- [Zehnder Comfoair RS232 MQTT](https://github.com/adorobis/hacomfoairmqtt) -- [Zigbee2MQTT](https://github.com/koenkk/zigbee2mqtt) -- [OTGateway](https://github.com/Laxilef/OTGateway) - -### Discovery examples +### Discovery examples with component discovery #### Motion detection (binary sensor) @@ -996,6 +1295,42 @@ The entity id is automatically generated from the entity's name. All MQTT integr In the example above, the entity_id will be `sensor.my_super_device` instead of `sensor.device1`. +### Support by third-party tools + +The following software has built-in support for MQTT discovery: + +- [ArduinoHA](https://github.com/dawidchyrzynski/arduino-home-assistant) +- [Arilux AL-LC0X LED controllers](https://github.com/smrtnt/Arilux_AL-LC0X) +- [ble2mqtt](https://github.com/devbis/ble2mqtt) +- [digitalstrom-mqtt](https://github.com/gaetancollaud/digitalstrom-mqtt) +- [ebusd](https://github.com/john30/ebusd) +- [ecowitt2mqtt](https://github.com/bachya/ecowitt2mqtt) +- [EMS-ESP32 (and EMS-ESP)](https://github.com/emsesp/EMS-ESP32) +- [ESPHome](https://esphome.io) +- [ESPurna](https://github.com/xoseperez/espurna) +- [go-iotdevice](https://github.com/koestler/go-iotdevice) +- [HASS.Agent](https://github.com/LAB02-Research/HASS.Agent) +- [IOTLink](https://iotlink.gitlab.io) (starting with 2.0.0) +- [MiFlora MQTT Daemon](https://github.com/ThomDietrich/miflora-mqtt-daemon) +- [MyElectricalData](https://github.com/MyElectricalData/myelectricaldata_import#english) +- [Nuki Hub](https://github.com/technyon/nuki_hub) +- [Nuki Smart Lock 3.0 Pro](https://support.nuki.io/hc/articles/12947926779409-MQTT-support), [more info](https://developer.nuki.io/t/mqtt-api-specification-v1-3/17626) +- [OpenMQTTGateway](https://github.com/1technophile/OpenMQTTGateway) +- [room-assistant](https://github.com/mKeRix/room-assistant) (starting with 1.1.0) +- [SmartHome](https://github.com/roncoa/SmartHome) +- [SpeedTest-CLI MQTT](https://github.com/adorobis/speedtest-CLI2mqtt) +- [SwitchBot-MQTT-BLE-ESP32](https://github.com/devWaves/SwitchBot-MQTT-BLE-ESP32) +- [Tasmota](https://github.com/arendst/Tasmota) (starting with 5.11.1e, development halted) +- [TeddyCloud](https://github.com/toniebox-reverse-engineering/teddycloud) +- [Teleinfo MQTT](https://fmartinou.github.io/teleinfo2mqtt) (starting with 3.0.0) +- [Tydom2MQTT](https://fmartinou.github.io/tydom2mqtt/) +- [What's up Docker?](https://fmartinou.github.io/whats-up-docker/) (starting with 3.5.0) +- [WyzeSense2MQTT](https://github.com/raetha/wyzesense2mqtt) +- [Xiaomi DaFang Hacks](https://github.com/EliasKotlyar/Xiaomi-Dafang-Hacks) +- [Zehnder Comfoair RS232 MQTT](https://github.com/adorobis/hacomfoairmqtt) +- [Zigbee2MQTT](https://github.com/koenkk/zigbee2mqtt) +- [OTGateway](https://github.com/Laxilef/OTGateway) + ## Manual configured MQTT items For most integrations, it is also possible to manually set up MQTT items in {% term "`configuration.yaml`" %}. Read more [about configuration in YAML](/docs/configuration/yaml). @@ -1098,7 +1433,6 @@ The MQTT integration will register the `mqtt.publish` action, which allows publi | `qos` | yes | Quality of Service to use. (default: 0) | | `retain` | yes | If message should have the retain flag set. (default: false) | - {% note %} When `payload` is rendered from [template](/docs/configuration/templating/#using-templates-with-the-mqtt-integration) in a YAML script or automation, and the template renders to a `bytes` literal, the outgoing MQTT payload will only be sent as `raw` data, if the `evaluate_payload` option flag is set to `true`. {% endnote %} @@ -1107,7 +1441,6 @@ When `payload` is rendered from [template](/docs/configuration/templating/#using You must include either `topic` or `topic_template`, but not both. If providing a payload, you need to include either `payload` or `payload_template`, but not both. {% endimportant %} - ```yaml topic: homeassistant/light/1/command payload: on diff --git a/source/_integrations/notify.mqtt.markdown b/source/_integrations/notify.mqtt.markdown index deb14bb71b1..1f3de5342a0 100644 --- a/source/_integrations/notify.mqtt.markdown +++ b/source/_integrations/notify.mqtt.markdown @@ -177,7 +177,7 @@ retain: type: boolean default: false unique_id: - description: An ID that uniquely identifies this notify entity. If two notify entities have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this notify entity. If two notify entities have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string {% endconfiguration %} diff --git a/source/_integrations/number.mqtt.markdown b/source/_integrations/number.mqtt.markdown index 87aa01ed83a..990fbef9639 100644 --- a/source/_integrations/number.mqtt.markdown +++ b/source/_integrations/number.mqtt.markdown @@ -178,6 +178,10 @@ payload_reset: required: false type: string default: '"None"' +platform: + description: Must be `number`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -198,7 +202,7 @@ step: type: float default: 1 unique_id: - description: An ID that uniquely identifies this Number. If two Numbers have the same unique ID Home Assistant will raise an exception. + description: An ID that uniquely identifies this Number. If two Numbers have the same unique ID Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string unit_of_measurement: diff --git a/source/_integrations/scene.mqtt.markdown b/source/_integrations/scene.mqtt.markdown index 25337acdb79..c581f777c31 100644 --- a/source/_integrations/scene.mqtt.markdown +++ b/source/_integrations/scene.mqtt.markdown @@ -169,6 +169,10 @@ payload_on: required: false type: string default: "ON" +platform: + description: Must be `scene`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -180,7 +184,7 @@ retain: type: boolean default: false unique_id: - description: An ID that uniquely identifies this scene entity. If two scenes have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this scene entity. If two scenes have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string {% endconfiguration %} diff --git a/source/_integrations/select.mqtt.markdown b/source/_integrations/select.mqtt.markdown index 5ee03fa90cb..f37de8c0236 100644 --- a/source/_integrations/select.mqtt.markdown +++ b/source/_integrations/select.mqtt.markdown @@ -170,6 +170,10 @@ options: description: List of options that can be selected. An empty list or a list with a single item is allowed. required: true type: list +platform: + description: Must be `select`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -185,7 +189,7 @@ state_topic: required: false type: string unique_id: - description: An ID that uniquely identifies this Select. If two Selects have the same unique ID Home Assistant will raise an exception. + description: An ID that uniquely identifies this Select. If two Selects have the same unique ID Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: diff --git a/source/_integrations/sensor.mqtt.markdown b/source/_integrations/sensor.mqtt.markdown index 82e35147b6b..06fc7dee130 100644 --- a/source/_integrations/sensor.mqtt.markdown +++ b/source/_integrations/sensor.mqtt.markdown @@ -183,6 +183,10 @@ payload_not_available: required: false type: string default: offline +platform: + description: Must be `sensor`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string suggested_display_precision: description: The number of decimals which should be used in the sensor's state after rounding. required: false @@ -201,7 +205,7 @@ state_topic: required: true type: string unique_id: - description: "An ID that uniquely identifies this sensor. If two sensors have the same unique ID, Home Assistant will raise an exception." + description: "An ID that uniquely identifies this sensor. If two sensors have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery." required: false type: string unit_of_measurement: diff --git a/source/_integrations/siren.mqtt.markdown b/source/_integrations/siren.mqtt.markdown index 998a6d2a91e..342ee7782f5 100644 --- a/source/_integrations/siren.mqtt.markdown +++ b/source/_integrations/siren.mqtt.markdown @@ -198,6 +198,10 @@ payload_on: required: false type: string default: "ON" +platform: + description: Must be `siren`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -237,7 +241,7 @@ support_volume_set: type: boolean default: true unique_id: - description: An ID that uniquely identifies this siren device. If two sirens have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this siren device. If two sirens have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string {% endconfiguration %} diff --git a/source/_integrations/switch.mqtt.markdown b/source/_integrations/switch.mqtt.markdown index 791d993b077..dd71faec44c 100644 --- a/source/_integrations/switch.mqtt.markdown +++ b/source/_integrations/switch.mqtt.markdown @@ -193,6 +193,10 @@ payload_on: required: false type: string default: "ON" +platform: + description: Must be `switch`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -218,7 +222,7 @@ state_topic: required: false type: string unique_id: - description: An ID that uniquely identifies this switch device. If two switches have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this switch device. If two switches have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: diff --git a/source/_integrations/text.mqtt.markdown b/source/_integrations/text.mqtt.markdown index 4c64722a8c6..c4506cbcffa 100644 --- a/source/_integrations/text.mqtt.markdown +++ b/source/_integrations/text.mqtt.markdown @@ -173,6 +173,10 @@ pattern: description: A valid regular expression the text being set or received must match with. required: false type: string +platform: + description: Must be `text`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -188,7 +192,7 @@ state_topic: required: false type: string unique_id: - description: An ID that uniquely identifies this Select. If two Selects have the same unique ID Home Assistant will raise an exception. + description: An ID that uniquely identifies this Select. If two Selects have the same unique ID Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: diff --git a/source/_integrations/update.mqtt.markdown b/source/_integrations/update.mqtt.markdown index 522f5c9ed7b..33c9f7f8793 100644 --- a/source/_integrations/update.mqtt.markdown +++ b/source/_integrations/update.mqtt.markdown @@ -170,6 +170,10 @@ payload_install: description: The MQTT payload to start installing process. required: false type: string +platform: + description: Must be `update`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false diff --git a/source/_integrations/vacuum.mqtt.markdown b/source/_integrations/vacuum.mqtt.markdown index dd09750f59d..4260dc9bd0d 100644 --- a/source/_integrations/vacuum.mqtt.markdown +++ b/source/_integrations/vacuum.mqtt.markdown @@ -174,6 +174,10 @@ payload_stop: required: false type: string default: stop +platform: + description: Must be `vacuum`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string qos: description: The maximum QoS level to be used when receiving and publishing messages. required: false @@ -202,7 +206,7 @@ supported_features: type: [string, list] default: "`start`, `stop`, `return_home`, `status`, `battery`, `clean_spot`" unique_id: - description: An ID that uniquely identifies this vacuum. If two vacuums have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this vacuum. If two vacuums have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string {% endconfiguration %} diff --git a/source/_integrations/valve.mqtt.markdown b/source/_integrations/valve.mqtt.markdown index 9b476f8b518..77b609bd5ba 100644 --- a/source/_integrations/valve.mqtt.markdown +++ b/source/_integrations/valve.mqtt.markdown @@ -226,6 +226,10 @@ payload_stop: description: The command payload that stops the valve. When not configured, the valve will not support the `valve.stop` action. required: false type: string +platform: + description: Must be `valve`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string position_closed: description: Number which represents closed position. The valve's position will be scaled to the(`position_closed`...`position_open`) range when an action is performed and scaled back when a value is received. required: false @@ -276,7 +280,7 @@ state_topic: required: false type: string unique_id: - description: An ID that uniquely identifies this valve. If two valves have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this valve. If two valves have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: diff --git a/source/_integrations/water_heater.mqtt.markdown b/source/_integrations/water_heater.mqtt.markdown index 4b89908dea7..14c80540055 100644 --- a/source/_integrations/water_heater.mqtt.markdown +++ b/source/_integrations/water_heater.mqtt.markdown @@ -217,6 +217,10 @@ payload_on: required: false type: string default: "ON" +platform: + description: Must be `water_heater`. Only allowed and required in [MQTT auto discovery device messages](/integrations/mqtt/#device-discovery-payload). + required: true + type: string power_command_template: description: A template to render the value sent to the `power_command_topic` with. The `value` parameter is the payload set for `payload_on` or `payload_off`. required: false @@ -261,7 +265,7 @@ temperature_unit: required: false type: string unique_id: - description: An ID that uniquely identifies this water heater device. If two water heater devices have the same unique ID, Home Assistant will raise an exception. + description: An ID that uniquely identifies this water heater device. If two water heater devices have the same unique ID, Home Assistant will raise an exception. Required when used with device-based discovery. required: false type: string value_template: