Change naming of MQTT entities to correspond with HA guidelines (#95159)
* Set has_entity_name if device_name is set * revert unneeded formatting change * Add image platform * Follow up comment * Don't set `has_entity_name` without device name * Only set has_entity_name if a valid name is set * Follow device_class name and add tests * Follow up comments add extra tests * Move to helper - Log a warning * fix test * Allow to assign None as name explictly * Refactor * Log info messages when device name is not set * Revert scene schema change - no device link * Always set has_entity_name with device mapping * Always set `_attr_has_entity_name` * Cleanup
This commit is contained in:
parent
747f4d4a73
commit
447fbf58c9
36 changed files with 433 additions and 66 deletions
|
@ -89,7 +89,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
|
||||||
CONF_COMMAND_TEMPLATE, default=DEFAULT_COMMAND_TEMPLATE
|
CONF_COMMAND_TEMPLATE, default=DEFAULT_COMMAND_TEMPLATE
|
||||||
): cv.template,
|
): cv.template,
|
||||||
vol.Required(CONF_COMMAND_TOPIC): valid_publish_topic,
|
vol.Required(CONF_COMMAND_TOPIC): valid_publish_topic,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_ARM_AWAY): cv.string,
|
vol.Optional(CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_ARM_AWAY): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_ARM_HOME, default=DEFAULT_ARM_HOME): cv.string,
|
vol.Optional(CONF_PAYLOAD_ARM_HOME, default=DEFAULT_ARM_HOME): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_ARM_NIGHT, default=DEFAULT_ARM_NIGHT): cv.string,
|
vol.Optional(CONF_PAYLOAD_ARM_NIGHT, default=DEFAULT_ARM_NIGHT): cv.string,
|
||||||
|
@ -136,6 +136,7 @@ async def _async_setup_entity(
|
||||||
class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity):
|
class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity):
|
||||||
"""Representation of a MQTT alarm status."""
|
"""Representation of a MQTT alarm status."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = alarm.ENTITY_ID_FORMAT
|
_entity_id_format = alarm.ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_ALARM_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_ALARM_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_RO_SCHEMA.extend(
|
||||||
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
|
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
|
||||||
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
|
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
|
||||||
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_OFF_DELAY): cv.positive_int,
|
vol.Optional(CONF_OFF_DELAY): cv.positive_int,
|
||||||
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
|
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
|
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
|
||||||
|
@ -97,6 +97,7 @@ async def _async_setup_entity(
|
||||||
class MqttBinarySensor(MqttEntity, BinarySensorEntity, RestoreEntity):
|
class MqttBinarySensor(MqttEntity, BinarySensorEntity, RestoreEntity):
|
||||||
"""Representation a binary sensor that is updated by MQTT."""
|
"""Representation a binary sensor that is updated by MQTT."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = binary_sensor.ENTITY_ID_FORMAT
|
_entity_id_format = binary_sensor.ENTITY_ID_FORMAT
|
||||||
_expired: bool | None
|
_expired: bool | None
|
||||||
_expire_after: int | None
|
_expire_after: int | None
|
||||||
|
|
|
@ -35,7 +35,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
|
||||||
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Required(CONF_COMMAND_TOPIC): valid_publish_topic,
|
vol.Required(CONF_COMMAND_TOPIC): valid_publish_topic,
|
||||||
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
|
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_PAYLOAD_PRESS, default=DEFAULT_PAYLOAD_PRESS): cv.string,
|
vol.Optional(CONF_PAYLOAD_PRESS, default=DEFAULT_PAYLOAD_PRESS): cv.string,
|
||||||
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
|
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ async def _async_setup_entity(
|
||||||
class MqttButton(MqttEntity, ButtonEntity):
|
class MqttButton(MqttEntity, ButtonEntity):
|
||||||
"""Representation of a switch that can be toggled using MQTT."""
|
"""Representation of a switch that can be toggled using MQTT."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = button.ENTITY_ID_FORMAT
|
_entity_id_format = button.ENTITY_ID_FORMAT
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|
|
@ -41,7 +41,7 @@ MQTT_CAMERA_ATTRIBUTES_BLOCKED = frozenset(
|
||||||
|
|
||||||
PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Required(CONF_TOPIC): valid_subscribe_topic,
|
vol.Required(CONF_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_IMAGE_ENCODING): "b64",
|
vol.Optional(CONF_IMAGE_ENCODING): "b64",
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,7 @@ async def _async_setup_entity(
|
||||||
class MqttCamera(MqttEntity, Camera):
|
class MqttCamera(MqttEntity, Camera):
|
||||||
"""representation of a MQTT camera."""
|
"""representation of a MQTT camera."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format: str = camera.ENTITY_ID_FORMAT
|
_entity_id_format: str = camera.ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked: frozenset[str] = MQTT_CAMERA_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked: frozenset[str] = MQTT_CAMERA_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -296,7 +296,7 @@ _PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
||||||
): cv.ensure_list,
|
): cv.ensure_list,
|
||||||
vol.Optional(CONF_MODE_STATE_TEMPLATE): cv.template,
|
vol.Optional(CONF_MODE_STATE_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_MODE_STATE_TOPIC): valid_subscribe_topic,
|
vol.Optional(CONF_MODE_STATE_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
||||||
vol.Optional(CONF_PAYLOAD_ON, default="ON"): cv.string,
|
vol.Optional(CONF_PAYLOAD_ON, default="ON"): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_OFF, default="OFF"): cv.string,
|
vol.Optional(CONF_PAYLOAD_OFF, default="OFF"): cv.string,
|
||||||
|
@ -597,6 +597,7 @@ class MqttTemperatureControlEntity(MqttEntity, ABC):
|
||||||
class MqttClimate(MqttTemperatureControlEntity, ClimateEntity):
|
class MqttClimate(MqttTemperatureControlEntity, ClimateEntity):
|
||||||
"""Representation of an MQTT climate device."""
|
"""Representation of an MQTT climate device."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = climate.ENTITY_ID_FORMAT
|
_entity_id_format = climate.ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_CLIMATE_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_CLIMATE_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,7 @@ _PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
||||||
vol.Optional(CONF_COMMAND_TOPIC): valid_publish_topic,
|
vol.Optional(CONF_COMMAND_TOPIC): valid_publish_topic,
|
||||||
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
|
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
|
||||||
vol.Optional(CONF_GET_POSITION_TOPIC): valid_subscribe_topic,
|
vol.Optional(CONF_GET_POSITION_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
||||||
vol.Optional(CONF_PAYLOAD_CLOSE, default=DEFAULT_PAYLOAD_CLOSE): vol.Any(
|
vol.Optional(CONF_PAYLOAD_CLOSE, default=DEFAULT_PAYLOAD_CLOSE): vol.Any(
|
||||||
cv.string, None
|
cv.string, None
|
||||||
|
@ -236,6 +236,7 @@ async def _async_setup_entity(
|
||||||
class MqttCover(MqttEntity, CoverEntity):
|
class MqttCover(MqttEntity, CoverEntity):
|
||||||
"""Representation of a cover that can be controlled using MQTT."""
|
"""Representation of a cover that can be controlled using MQTT."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format: str = cover.ENTITY_ID_FORMAT
|
_entity_id_format: str = cover.ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked: frozenset[str] = MQTT_COVER_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked: frozenset[str] = MQTT_COVER_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ PLATFORM_SCHEMA_MODERN_BASE = MQTT_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_STATE_TOPIC): valid_subscribe_topic,
|
vol.Optional(CONF_STATE_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_PAYLOAD_HOME, default=STATE_HOME): cv.string,
|
vol.Optional(CONF_PAYLOAD_HOME, default=STATE_HOME): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_NOT_HOME, default=STATE_NOT_HOME): cv.string,
|
vol.Optional(CONF_PAYLOAD_NOT_HOME, default=STATE_NOT_HOME): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_RESET, default=DEFAULT_PAYLOAD_RESET): cv.string,
|
vol.Optional(CONF_PAYLOAD_RESET, default=DEFAULT_PAYLOAD_RESET): cv.string,
|
||||||
|
@ -104,6 +104,7 @@ async def _async_setup_entity(
|
||||||
class MqttDeviceTracker(MqttEntity, TrackerEntity):
|
class MqttDeviceTracker(MqttEntity, TrackerEntity):
|
||||||
"""Representation of a device tracker using MQTT."""
|
"""Representation of a device tracker using MQTT."""
|
||||||
|
|
||||||
|
_default_name = None
|
||||||
_entity_id_format = device_tracker.ENTITY_ID_FORMAT
|
_entity_id_format = device_tracker.ENTITY_ID_FORMAT
|
||||||
_value_template: Callable[..., ReceivePayloadType]
|
_value_template: Callable[..., ReceivePayloadType]
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ def valid_preset_mode_configuration(config: ConfigType) -> ConfigType:
|
||||||
|
|
||||||
_PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
|
_PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_DIRECTION_COMMAND_TOPIC): valid_publish_topic,
|
vol.Optional(CONF_DIRECTION_COMMAND_TOPIC): valid_publish_topic,
|
||||||
vol.Optional(CONF_DIRECTION_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_DIRECTION_COMMAND_TEMPLATE): cv.template,
|
||||||
|
@ -215,6 +215,7 @@ async def _async_setup_entity(
|
||||||
class MqttFan(MqttEntity, FanEntity):
|
class MqttFan(MqttEntity, FanEntity):
|
||||||
"""A MQTT fan component."""
|
"""A MQTT fan component."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = fan.ENTITY_ID_FORMAT
|
_entity_id_format = fan.ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_FAN_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_FAN_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ _PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
|
||||||
vol.Optional(CONF_MODE_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_MODE_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_MODE_STATE_TOPIC): valid_subscribe_topic,
|
vol.Optional(CONF_MODE_STATE_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_MODE_STATE_TEMPLATE): cv.template,
|
vol.Optional(CONF_MODE_STATE_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
|
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
|
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
|
||||||
vol.Optional(CONF_STATE_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_STATE_VALUE_TEMPLATE): cv.template,
|
||||||
|
@ -207,6 +207,7 @@ async def _async_setup_entity(
|
||||||
class MqttHumidifier(MqttEntity, HumidifierEntity):
|
class MqttHumidifier(MqttEntity, HumidifierEntity):
|
||||||
"""A MQTT humidifier component."""
|
"""A MQTT humidifier component."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = humidifier.ENTITY_ID_FORMAT
|
_entity_id_format = humidifier.ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_HUMIDIFIER_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_HUMIDIFIER_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ def validate_topic_required(config: ConfigType) -> ConfigType:
|
||||||
PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_CONTENT_TYPE): cv.string,
|
vol.Optional(CONF_CONTENT_TYPE): cv.string,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Exclusive(CONF_URL_TOPIC, "image_topic"): valid_subscribe_topic,
|
vol.Exclusive(CONF_URL_TOPIC, "image_topic"): valid_subscribe_topic,
|
||||||
vol.Exclusive(CONF_IMAGE_TOPIC, "image_topic"): valid_subscribe_topic,
|
vol.Exclusive(CONF_IMAGE_TOPIC, "image_topic"): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_IMAGE_ENCODING): "b64",
|
vol.Optional(CONF_IMAGE_ENCODING): "b64",
|
||||||
|
@ -102,6 +102,7 @@ async def _async_setup_entity(
|
||||||
class MqttImage(MqttEntity, ImageEntity):
|
class MqttImage(MqttEntity, ImageEntity):
|
||||||
"""representation of a MQTT image."""
|
"""representation of a MQTT image."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format: str = image.ENTITY_ID_FORMAT
|
_entity_id_format: str = image.ENTITY_ID_FORMAT
|
||||||
_last_image: bytes | None = None
|
_last_image: bytes | None = None
|
||||||
_client: httpx.AsyncClient
|
_client: httpx.AsyncClient
|
||||||
|
|
|
@ -190,7 +190,7 @@ PLATFORM_SCHEMA_MODERN_BASIC = (
|
||||||
vol.Optional(CONF_HS_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_HS_VALUE_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_MAX_MIREDS): cv.positive_int,
|
vol.Optional(CONF_MAX_MIREDS): cv.positive_int,
|
||||||
vol.Optional(CONF_MIN_MIREDS): cv.positive_int,
|
vol.Optional(CONF_MIN_MIREDS): cv.positive_int,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_ON_COMMAND_TYPE, default=DEFAULT_ON_COMMAND_TYPE): vol.In(
|
vol.Optional(CONF_ON_COMMAND_TYPE, default=DEFAULT_ON_COMMAND_TYPE): vol.In(
|
||||||
VALUES_ON_COMMAND_TYPE
|
VALUES_ON_COMMAND_TYPE
|
||||||
),
|
),
|
||||||
|
@ -242,6 +242,7 @@ async def async_setup_entity_basic(
|
||||||
class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
class MqttLight(MqttEntity, LightEntity, RestoreEntity):
|
||||||
"""Representation of a MQTT light."""
|
"""Representation of a MQTT light."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = ENTITY_ID_FORMAT
|
_entity_id_format = ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_LIGHT_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_LIGHT_ATTRIBUTES_BLOCKED
|
||||||
_topic: dict[str, str | None]
|
_topic: dict[str, str | None]
|
||||||
|
|
|
@ -132,7 +132,7 @@ _PLATFORM_SCHEMA_BASE = (
|
||||||
vol.Optional(CONF_HS, default=DEFAULT_HS): cv.boolean,
|
vol.Optional(CONF_HS, default=DEFAULT_HS): cv.boolean,
|
||||||
vol.Optional(CONF_MAX_MIREDS): cv.positive_int,
|
vol.Optional(CONF_MAX_MIREDS): cv.positive_int,
|
||||||
vol.Optional(CONF_MIN_MIREDS): cv.positive_int,
|
vol.Optional(CONF_MIN_MIREDS): cv.positive_int,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_QOS, default=DEFAULT_QOS): vol.All(
|
vol.Optional(CONF_QOS, default=DEFAULT_QOS): vol.All(
|
||||||
vol.Coerce(int), vol.In([0, 1, 2])
|
vol.Coerce(int), vol.In([0, 1, 2])
|
||||||
),
|
),
|
||||||
|
@ -180,6 +180,7 @@ async def async_setup_entity_json(
|
||||||
class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
||||||
"""Representation of a MQTT JSON light."""
|
"""Representation of a MQTT JSON light."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = ENTITY_ID_FORMAT
|
_entity_id_format = ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_LIGHT_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_LIGHT_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ PLATFORM_SCHEMA_MODERN_TEMPLATE = (
|
||||||
vol.Optional(CONF_GREEN_TEMPLATE): cv.template,
|
vol.Optional(CONF_GREEN_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_MAX_MIREDS): cv.positive_int,
|
vol.Optional(CONF_MAX_MIREDS): cv.positive_int,
|
||||||
vol.Optional(CONF_MIN_MIREDS): cv.positive_int,
|
vol.Optional(CONF_MIN_MIREDS): cv.positive_int,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_RED_TEMPLATE): cv.template,
|
vol.Optional(CONF_RED_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_STATE_TEMPLATE): cv.template,
|
vol.Optional(CONF_STATE_TEMPLATE): cv.template,
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,7 @@ async def async_setup_entity_template(
|
||||||
class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
|
||||||
"""Representation of a MQTT Template light."""
|
"""Representation of a MQTT Template light."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = ENTITY_ID_FORMAT
|
_entity_id_format = ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_LIGHT_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_LIGHT_ATTRIBUTES_BLOCKED
|
||||||
_optimistic: bool
|
_optimistic: bool
|
||||||
|
|
|
@ -76,7 +76,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_RW_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_CODE_FORMAT): cv.is_regex,
|
vol.Optional(CONF_CODE_FORMAT): cv.is_regex,
|
||||||
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_PAYLOAD_LOCK, default=DEFAULT_PAYLOAD_LOCK): cv.string,
|
vol.Optional(CONF_PAYLOAD_LOCK, default=DEFAULT_PAYLOAD_LOCK): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_UNLOCK, default=DEFAULT_PAYLOAD_UNLOCK): cv.string,
|
vol.Optional(CONF_PAYLOAD_UNLOCK, default=DEFAULT_PAYLOAD_UNLOCK): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_OPEN): cv.string,
|
vol.Optional(CONF_PAYLOAD_OPEN): cv.string,
|
||||||
|
@ -126,6 +126,7 @@ async def _async_setup_entity(
|
||||||
class MqttLock(MqttEntity, LockEntity):
|
class MqttLock(MqttEntity, LockEntity):
|
||||||
"""Representation of a lock that can be toggled using MQTT."""
|
"""Representation of a lock that can be toggled using MQTT."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = lock.ENTITY_ID_FORMAT
|
_entity_id_format = lock.ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_LOCK_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_LOCK_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,12 @@ from homeassistant.helpers.event import (
|
||||||
async_track_device_registry_updated_event,
|
async_track_device_registry_updated_event,
|
||||||
async_track_entity_registry_updated_event,
|
async_track_entity_registry_updated_event,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import (
|
||||||
|
UNDEFINED,
|
||||||
|
ConfigType,
|
||||||
|
DiscoveryInfoType,
|
||||||
|
UndefinedType,
|
||||||
|
)
|
||||||
from homeassistant.util.json import json_loads
|
from homeassistant.util.json import json_loads
|
||||||
|
|
||||||
from . import debug_info, subscription
|
from . import debug_info, subscription
|
||||||
|
@ -999,7 +1004,9 @@ class MqttEntity(
|
||||||
):
|
):
|
||||||
"""Representation of an MQTT entity."""
|
"""Representation of an MQTT entity."""
|
||||||
|
|
||||||
|
_attr_has_entity_name = True
|
||||||
_attr_should_poll = False
|
_attr_should_poll = False
|
||||||
|
_default_name: str | None
|
||||||
_entity_id_format: str
|
_entity_id_format: str
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -1016,8 +1023,8 @@ class MqttEntity(
|
||||||
self._sub_state: dict[str, EntitySubscription] = {}
|
self._sub_state: dict[str, EntitySubscription] = {}
|
||||||
|
|
||||||
# Load config
|
# Load config
|
||||||
self._setup_common_attributes_from_config(self._config)
|
|
||||||
self._setup_from_config(self._config)
|
self._setup_from_config(self._config)
|
||||||
|
self._setup_common_attributes_from_config(self._config)
|
||||||
|
|
||||||
# Initialize entity_id from config
|
# Initialize entity_id from config
|
||||||
self._init_entity_id()
|
self._init_entity_id()
|
||||||
|
@ -1058,8 +1065,8 @@ class MqttEntity(
|
||||||
async_handle_schema_error(discovery_payload, err)
|
async_handle_schema_error(discovery_payload, err)
|
||||||
return
|
return
|
||||||
self._config = config
|
self._config = config
|
||||||
self._setup_common_attributes_from_config(self._config)
|
|
||||||
self._setup_from_config(self._config)
|
self._setup_from_config(self._config)
|
||||||
|
self._setup_common_attributes_from_config(self._config)
|
||||||
|
|
||||||
# Prepare MQTT subscriptions
|
# Prepare MQTT subscriptions
|
||||||
self.attributes_prepare_discovery_update(config)
|
self.attributes_prepare_discovery_update(config)
|
||||||
|
@ -1107,6 +1114,23 @@ class MqttEntity(
|
||||||
def config_schema() -> vol.Schema:
|
def config_schema() -> vol.Schema:
|
||||||
"""Return the config schema."""
|
"""Return the config schema."""
|
||||||
|
|
||||||
|
def _set_entity_name(self, config: ConfigType) -> None:
|
||||||
|
"""Help setting the entity name if needed."""
|
||||||
|
entity_name: str | None | UndefinedType = config.get(CONF_NAME, UNDEFINED)
|
||||||
|
# Only set _attr_name if it is needed
|
||||||
|
if entity_name is not UNDEFINED:
|
||||||
|
self._attr_name = entity_name
|
||||||
|
elif not self._default_to_device_class_name():
|
||||||
|
# Assign the default name
|
||||||
|
self._attr_name = self._default_name
|
||||||
|
if CONF_DEVICE in config:
|
||||||
|
if CONF_NAME not in config[CONF_DEVICE]:
|
||||||
|
_LOGGER.info(
|
||||||
|
"MQTT device information always needs to include a name, got %s, "
|
||||||
|
"if device information is shared between multiple entities, the device "
|
||||||
|
"name must be included in each entity's device configuration",
|
||||||
|
)
|
||||||
|
|
||||||
def _setup_common_attributes_from_config(self, config: ConfigType) -> None:
|
def _setup_common_attributes_from_config(self, config: ConfigType) -> None:
|
||||||
"""(Re)Setup the common attributes for the entity."""
|
"""(Re)Setup the common attributes for the entity."""
|
||||||
self._attr_entity_category = config.get(CONF_ENTITY_CATEGORY)
|
self._attr_entity_category = config.get(CONF_ENTITY_CATEGORY)
|
||||||
|
@ -1114,7 +1138,8 @@ class MqttEntity(
|
||||||
config.get(CONF_ENABLED_BY_DEFAULT)
|
config.get(CONF_ENABLED_BY_DEFAULT)
|
||||||
)
|
)
|
||||||
self._attr_icon = config.get(CONF_ICON)
|
self._attr_icon = config.get(CONF_ICON)
|
||||||
self._attr_name = config.get(CONF_NAME)
|
# Set the entity name if needed
|
||||||
|
self._set_entity_name(config)
|
||||||
|
|
||||||
def _setup_from_config(self, config: ConfigType) -> None:
|
def _setup_from_config(self, config: ConfigType) -> None:
|
||||||
"""(Re)Setup the entity."""
|
"""(Re)Setup the entity."""
|
||||||
|
|
|
@ -87,7 +87,7 @@ _PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
|
||||||
vol.Optional(CONF_MAX, default=DEFAULT_MAX_VALUE): vol.Coerce(float),
|
vol.Optional(CONF_MAX, default=DEFAULT_MAX_VALUE): vol.Coerce(float),
|
||||||
vol.Optional(CONF_MIN, default=DEFAULT_MIN_VALUE): vol.Coerce(float),
|
vol.Optional(CONF_MIN, default=DEFAULT_MIN_VALUE): vol.Coerce(float),
|
||||||
vol.Optional(CONF_MODE, default=NumberMode.AUTO): vol.Coerce(NumberMode),
|
vol.Optional(CONF_MODE, default=NumberMode.AUTO): vol.Coerce(NumberMode),
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_PAYLOAD_RESET, default=DEFAULT_PAYLOAD_RESET): cv.string,
|
vol.Optional(CONF_PAYLOAD_RESET, default=DEFAULT_PAYLOAD_RESET): cv.string,
|
||||||
vol.Optional(CONF_STEP, default=DEFAULT_STEP): vol.All(
|
vol.Optional(CONF_STEP, default=DEFAULT_STEP): vol.All(
|
||||||
vol.Coerce(float), vol.Range(min=1e-3)
|
vol.Coerce(float), vol.Range(min=1e-3)
|
||||||
|
@ -134,6 +134,7 @@ async def _async_setup_entity(
|
||||||
class MqttNumber(MqttEntity, RestoreNumber):
|
class MqttNumber(MqttEntity, RestoreNumber):
|
||||||
"""representation of an MQTT number."""
|
"""representation of an MQTT number."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = number.ENTITY_ID_FORMAT
|
_entity_id_format = number.ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_NUMBER_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_NUMBER_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_COMMAND_TOPIC): valid_publish_topic,
|
vol.Required(CONF_COMMAND_TOPIC): valid_publish_topic,
|
||||||
vol.Optional(CONF_ICON): cv.icon,
|
vol.Optional(CONF_ICON): cv.icon,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_ON): cv.string,
|
vol.Optional(CONF_PAYLOAD_ON): cv.string,
|
||||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||||
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
|
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
|
||||||
|
@ -77,6 +77,7 @@ class MqttScene(
|
||||||
):
|
):
|
||||||
"""Representation of a scene that can be activated using MQTT."""
|
"""Representation of a scene that can be activated using MQTT."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = scene.DOMAIN + ".{}"
|
_entity_id_format = scene.DOMAIN + ".{}"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|
|
@ -54,7 +54,7 @@ MQTT_SELECT_ATTRIBUTES_BLOCKED = frozenset(
|
||||||
PLATFORM_SCHEMA_MODERN = MQTT_RW_SCHEMA.extend(
|
PLATFORM_SCHEMA_MODERN = MQTT_RW_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Required(CONF_OPTIONS): cv.ensure_list,
|
vol.Required(CONF_OPTIONS): cv.ensure_list,
|
||||||
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
||||||
},
|
},
|
||||||
|
@ -89,6 +89,7 @@ async def _async_setup_entity(
|
||||||
class MqttSelect(MqttEntity, SelectEntity, RestoreEntity):
|
class MqttSelect(MqttEntity, SelectEntity, RestoreEntity):
|
||||||
"""representation of an MQTT select."""
|
"""representation of an MQTT select."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = select.ENTITY_ID_FORMAT
|
_entity_id_format = select.ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_SELECT_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_SELECT_ATTRIBUTES_BLOCKED
|
||||||
_command_template: Callable[[PublishPayloadType], PublishPayloadType]
|
_command_template: Callable[[PublishPayloadType], PublishPayloadType]
|
||||||
|
|
|
@ -78,7 +78,7 @@ _PLATFORM_SCHEMA_BASE = MQTT_RO_SCHEMA.extend(
|
||||||
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
|
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
|
||||||
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
||||||
vol.Optional(CONF_LAST_RESET_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_LAST_RESET_VALUE_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_SUGGESTED_DISPLAY_PRECISION): cv.positive_int,
|
vol.Optional(CONF_SUGGESTED_DISPLAY_PRECISION): cv.positive_int,
|
||||||
vol.Optional(CONF_STATE_CLASS): vol.Any(STATE_CLASSES_SCHEMA, None),
|
vol.Optional(CONF_STATE_CLASS): vol.Any(STATE_CLASSES_SCHEMA, None),
|
||||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): vol.Any(cv.string, None),
|
vol.Optional(CONF_UNIT_OF_MEASUREMENT): vol.Any(cv.string, None),
|
||||||
|
@ -126,6 +126,7 @@ async def _async_setup_entity(
|
||||||
class MqttSensor(MqttEntity, RestoreSensor):
|
class MqttSensor(MqttEntity, RestoreSensor):
|
||||||
"""Representation of a sensor that can be updated using MQTT."""
|
"""Representation of a sensor that can be updated using MQTT."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = ENTITY_ID_FORMAT
|
_entity_id_format = ENTITY_ID_FORMAT
|
||||||
_attr_last_reset: datetime | None = None
|
_attr_last_reset: datetime | None = None
|
||||||
_attributes_extra_blocked = MQTT_SENSOR_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_SENSOR_ATTRIBUTES_BLOCKED
|
||||||
|
|
|
@ -79,7 +79,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_RW_SCHEMA.extend(
|
||||||
vol.Optional(CONF_AVAILABLE_TONES): cv.ensure_list,
|
vol.Optional(CONF_AVAILABLE_TONES): cv.ensure_list,
|
||||||
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_COMMAND_OFF_TEMPLATE): cv.template,
|
vol.Optional(CONF_COMMAND_OFF_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
|
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
|
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
|
||||||
vol.Optional(CONF_STATE_OFF): cv.string,
|
vol.Optional(CONF_STATE_OFF): cv.string,
|
||||||
|
@ -138,6 +138,7 @@ async def _async_setup_entity(
|
||||||
class MqttSiren(MqttEntity, SirenEntity):
|
class MqttSiren(MqttEntity, SirenEntity):
|
||||||
"""Representation of a siren that can be controlled using MQTT."""
|
"""Representation of a siren that can be controlled using MQTT."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = ENTITY_ID_FORMAT
|
_entity_id_format = ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_SIREN_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_SIREN_ATTRIBUTES_BLOCKED
|
||||||
_extra_attributes: dict[str, Any]
|
_extra_attributes: dict[str, Any]
|
||||||
|
|
|
@ -49,7 +49,7 @@ CONF_STATE_OFF = "state_off"
|
||||||
|
|
||||||
PLATFORM_SCHEMA_MODERN = MQTT_RW_SCHEMA.extend(
|
PLATFORM_SCHEMA_MODERN = MQTT_RW_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
|
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
|
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
|
||||||
vol.Optional(CONF_STATE_OFF): cv.string,
|
vol.Optional(CONF_STATE_OFF): cv.string,
|
||||||
|
@ -88,6 +88,7 @@ async def _async_setup_entity(
|
||||||
class MqttSwitch(MqttEntity, SwitchEntity, RestoreEntity):
|
class MqttSwitch(MqttEntity, SwitchEntity, RestoreEntity):
|
||||||
"""Representation of a switch that can be toggled using MQTT."""
|
"""Representation of a switch that can be toggled using MQTT."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = switch.ENTITY_ID_FORMAT
|
_entity_id_format = switch.ENTITY_ID_FORMAT
|
||||||
|
|
||||||
_optimistic: bool
|
_optimistic: bool
|
||||||
|
|
|
@ -78,7 +78,7 @@ def valid_text_size_configuration(config: ConfigType) -> ConfigType:
|
||||||
_PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
|
_PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_MAX, default=MAX_LENGTH_STATE_STATE): cv.positive_int,
|
vol.Optional(CONF_MAX, default=MAX_LENGTH_STATE_STATE): cv.positive_int,
|
||||||
vol.Optional(CONF_MIN, default=0): cv.positive_int,
|
vol.Optional(CONF_MIN, default=0): cv.positive_int,
|
||||||
vol.Optional(CONF_MODE, default=text.TextMode.TEXT): vol.In(
|
vol.Optional(CONF_MODE, default=text.TextMode.TEXT): vol.In(
|
||||||
|
@ -125,6 +125,7 @@ class MqttTextEntity(MqttEntity, TextEntity):
|
||||||
"""Representation of the MQTT text entity."""
|
"""Representation of the MQTT text entity."""
|
||||||
|
|
||||||
_attributes_extra_blocked = MQTT_TEXT_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_TEXT_ATTRIBUTES_BLOCKED
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = text.ENTITY_ID_FORMAT
|
_entity_id_format = text.ENTITY_ID_FORMAT
|
||||||
|
|
||||||
_compiled_pattern: re.Pattern[Any] | None
|
_compiled_pattern: re.Pattern[Any] | None
|
||||||
|
|
|
@ -57,7 +57,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_RO_SCHEMA.extend(
|
||||||
vol.Optional(CONF_ENTITY_PICTURE): cv.string,
|
vol.Optional(CONF_ENTITY_PICTURE): cv.string,
|
||||||
vol.Optional(CONF_LATEST_VERSION_TEMPLATE): cv.template,
|
vol.Optional(CONF_LATEST_VERSION_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_LATEST_VERSION_TOPIC): valid_subscribe_topic,
|
vol.Optional(CONF_LATEST_VERSION_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_PAYLOAD_INSTALL): cv.string,
|
vol.Optional(CONF_PAYLOAD_INSTALL): cv.string,
|
||||||
vol.Optional(CONF_RELEASE_SUMMARY): cv.string,
|
vol.Optional(CONF_RELEASE_SUMMARY): cv.string,
|
||||||
vol.Optional(CONF_RELEASE_URL): cv.string,
|
vol.Optional(CONF_RELEASE_URL): cv.string,
|
||||||
|
@ -107,6 +107,7 @@ async def _async_setup_entity(
|
||||||
class MqttUpdate(MqttEntity, UpdateEntity, RestoreEntity):
|
class MqttUpdate(MqttEntity, UpdateEntity, RestoreEntity):
|
||||||
"""Representation of the MQTT update entity."""
|
"""Representation of the MQTT update entity."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = update.ENTITY_ID_FORMAT
|
_entity_id_format = update.ENTITY_ID_FORMAT
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|
|
@ -131,7 +131,7 @@ PLATFORM_SCHEMA_LEGACY_MODERN = (
|
||||||
),
|
),
|
||||||
vol.Inclusive(CONF_FAN_SPEED_TEMPLATE, "fan_speed"): cv.template,
|
vol.Inclusive(CONF_FAN_SPEED_TEMPLATE, "fan_speed"): cv.template,
|
||||||
vol.Inclusive(CONF_FAN_SPEED_TOPIC, "fan_speed"): valid_publish_topic,
|
vol.Inclusive(CONF_FAN_SPEED_TOPIC, "fan_speed"): valid_publish_topic,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_PAYLOAD_CLEAN_SPOT, default=DEFAULT_PAYLOAD_CLEAN_SPOT
|
CONF_PAYLOAD_CLEAN_SPOT, default=DEFAULT_PAYLOAD_CLEAN_SPOT
|
||||||
): cv.string,
|
): cv.string,
|
||||||
|
@ -215,6 +215,7 @@ async def async_setup_entity_legacy(
|
||||||
class MqttVacuum(MqttEntity, VacuumEntity):
|
class MqttVacuum(MqttEntity, VacuumEntity):
|
||||||
"""Representation of a MQTT-controlled legacy vacuum."""
|
"""Representation of a MQTT-controlled legacy vacuum."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = ENTITY_ID_FORMAT
|
_entity_id_format = ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_LEGACY_VACUUM_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_LEGACY_VACUUM_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ PLATFORM_SCHEMA_STATE_MODERN = (
|
||||||
vol.Optional(CONF_FAN_SPEED_LIST, default=[]): vol.All(
|
vol.Optional(CONF_FAN_SPEED_LIST, default=[]): vol.All(
|
||||||
cv.ensure_list, [cv.string]
|
cv.ensure_list, [cv.string]
|
||||||
),
|
),
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_PAYLOAD_CLEAN_SPOT, default=DEFAULT_PAYLOAD_CLEAN_SPOT
|
CONF_PAYLOAD_CLEAN_SPOT, default=DEFAULT_PAYLOAD_CLEAN_SPOT
|
||||||
): cv.string,
|
): cv.string,
|
||||||
|
@ -170,6 +170,7 @@ async def async_setup_entity_state(
|
||||||
class MqttStateVacuum(MqttEntity, StateVacuumEntity):
|
class MqttStateVacuum(MqttEntity, StateVacuumEntity):
|
||||||
"""Representation of a MQTT-controlled state vacuum."""
|
"""Representation of a MQTT-controlled state vacuum."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = ENTITY_ID_FORMAT
|
_entity_id_format = ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_VACUUM_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_VACUUM_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ _PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
||||||
): cv.ensure_list,
|
): cv.ensure_list,
|
||||||
vol.Optional(CONF_MODE_STATE_TEMPLATE): cv.template,
|
vol.Optional(CONF_MODE_STATE_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_MODE_STATE_TOPIC): valid_subscribe_topic,
|
vol.Optional(CONF_MODE_STATE_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||||
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
||||||
vol.Optional(CONF_PAYLOAD_ON, default="ON"): cv.string,
|
vol.Optional(CONF_PAYLOAD_ON, default="ON"): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_OFF, default="OFF"): cv.string,
|
vol.Optional(CONF_PAYLOAD_OFF, default="OFF"): cv.string,
|
||||||
|
@ -180,6 +180,7 @@ async def _async_setup_entity(
|
||||||
class MqttWaterHeater(MqttTemperatureControlEntity, WaterHeaterEntity):
|
class MqttWaterHeater(MqttTemperatureControlEntity, WaterHeaterEntity):
|
||||||
"""Representation of an MQTT water heater device."""
|
"""Representation of an MQTT water heater device."""
|
||||||
|
|
||||||
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = water_heater.ENTITY_ID_FORMAT
|
_entity_id_format = water_heater.ENTITY_ID_FORMAT
|
||||||
_attributes_extra_blocked = MQTT_WATER_HEATER_ATTRIBUTES_BLOCKED
|
_attributes_extra_blocked = MQTT_WATER_HEATER_ATTRIBUTES_BLOCKED
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ from .test_common import (
|
||||||
help_test_entity_device_info_with_identifier,
|
help_test_entity_device_info_with_identifier,
|
||||||
help_test_entity_id_update_discovery_update,
|
help_test_entity_id_update_discovery_update,
|
||||||
help_test_entity_id_update_subscriptions,
|
help_test_entity_id_update_subscriptions,
|
||||||
|
help_test_entity_name,
|
||||||
help_test_publishing_with_custom_encoding,
|
help_test_publishing_with_custom_encoding,
|
||||||
help_test_reloadable,
|
help_test_reloadable,
|
||||||
help_test_setting_attribute_via_mqtt_json_message,
|
help_test_setting_attribute_via_mqtt_json_message,
|
||||||
|
@ -1120,3 +1121,21 @@ async def test_unload_entry(
|
||||||
await help_test_unload_config_entry_with_platform(
|
await help_test_unload_config_entry_with_platform(
|
||||||
hass, mqtt_mock_entry, domain, config
|
hass, mqtt_mock_entry, domain, config
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("expected_friendly_name", "device_class"),
|
||||||
|
[("test", None)],
|
||||||
|
)
|
||||||
|
async def test_entity_name(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
expected_friendly_name: str | None,
|
||||||
|
device_class: str | None,
|
||||||
|
) -> None:
|
||||||
|
"""Test the entity name setup."""
|
||||||
|
domain = alarm_control_panel.DOMAIN
|
||||||
|
config = DEFAULT_CONFIG
|
||||||
|
await help_test_entity_name(
|
||||||
|
hass, mqtt_mock_entry, domain, config, expected_friendly_name, device_class
|
||||||
|
)
|
||||||
|
|
|
@ -41,6 +41,7 @@ from .test_common import (
|
||||||
help_test_entity_device_info_with_identifier,
|
help_test_entity_device_info_with_identifier,
|
||||||
help_test_entity_id_update_discovery_update,
|
help_test_entity_id_update_discovery_update,
|
||||||
help_test_entity_id_update_subscriptions,
|
help_test_entity_id_update_subscriptions,
|
||||||
|
help_test_entity_name,
|
||||||
help_test_reload_with_config,
|
help_test_reload_with_config,
|
||||||
help_test_reloadable,
|
help_test_reloadable,
|
||||||
help_test_setting_attribute_via_mqtt_json_message,
|
help_test_setting_attribute_via_mqtt_json_message,
|
||||||
|
@ -1227,3 +1228,21 @@ async def test_unload_entry(
|
||||||
await help_test_unload_config_entry_with_platform(
|
await help_test_unload_config_entry_with_platform(
|
||||||
hass, mqtt_mock_entry, domain, config
|
hass, mqtt_mock_entry, domain, config
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("expected_friendly_name", "device_class"),
|
||||||
|
[("test", None), ("Door", "door"), ("Battery", "battery"), ("Motion", "motion")],
|
||||||
|
)
|
||||||
|
async def test_entity_name(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
expected_friendly_name: str | None,
|
||||||
|
device_class: str | None,
|
||||||
|
) -> None:
|
||||||
|
"""Test the entity name setup."""
|
||||||
|
domain = binary_sensor.DOMAIN
|
||||||
|
config = DEFAULT_CONFIG
|
||||||
|
await help_test_entity_name(
|
||||||
|
hass, mqtt_mock_entry, domain, config, expected_friendly_name, device_class
|
||||||
|
)
|
||||||
|
|
|
@ -30,6 +30,7 @@ from .test_common import (
|
||||||
help_test_entity_device_info_with_connection,
|
help_test_entity_device_info_with_connection,
|
||||||
help_test_entity_device_info_with_identifier,
|
help_test_entity_device_info_with_identifier,
|
||||||
help_test_entity_id_update_discovery_update,
|
help_test_entity_id_update_discovery_update,
|
||||||
|
help_test_entity_name,
|
||||||
help_test_publishing_with_custom_encoding,
|
help_test_publishing_with_custom_encoding,
|
||||||
help_test_reloadable,
|
help_test_reloadable,
|
||||||
help_test_setting_attribute_via_mqtt_json_message,
|
help_test_setting_attribute_via_mqtt_json_message,
|
||||||
|
@ -569,3 +570,26 @@ async def test_unload_entry(
|
||||||
await help_test_unload_config_entry_with_platform(
|
await help_test_unload_config_entry_with_platform(
|
||||||
hass, mqtt_mock_entry, domain, config
|
hass, mqtt_mock_entry, domain, config
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("expected_friendly_name", "device_class"),
|
||||||
|
[
|
||||||
|
("test", None),
|
||||||
|
("Update", "update"),
|
||||||
|
("Identify", "identify"),
|
||||||
|
("Restart", "restart"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_entity_name(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
expected_friendly_name: str | None,
|
||||||
|
device_class: str | None,
|
||||||
|
) -> None:
|
||||||
|
"""Test the entity name setup."""
|
||||||
|
domain = button.DOMAIN
|
||||||
|
config = DEFAULT_CONFIG
|
||||||
|
await help_test_entity_name(
|
||||||
|
hass, mqtt_mock_entry, domain, config, expected_friendly_name, device_class
|
||||||
|
)
|
||||||
|
|
|
@ -1117,6 +1117,45 @@ async def help_test_entity_device_info_update(
|
||||||
assert device.name == "Milk"
|
assert device.name == "Milk"
|
||||||
|
|
||||||
|
|
||||||
|
async def help_test_entity_name(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
domain: str,
|
||||||
|
config: ConfigType,
|
||||||
|
expected_friendly_name: str | None = None,
|
||||||
|
device_class: str | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Test device name setup with and without a device_class set.
|
||||||
|
|
||||||
|
This is a test helper for the _setup_common_attributes_from_config mixin.
|
||||||
|
"""
|
||||||
|
await mqtt_mock_entry()
|
||||||
|
# Add device settings to config
|
||||||
|
config = copy.deepcopy(config[mqtt.DOMAIN][domain])
|
||||||
|
config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID)
|
||||||
|
config["unique_id"] = "veryunique"
|
||||||
|
expected_entity_name = "test"
|
||||||
|
if device_class is not None:
|
||||||
|
config["device_class"] = device_class
|
||||||
|
# Do not set a name
|
||||||
|
config.pop("name")
|
||||||
|
expected_entity_name = device_class
|
||||||
|
|
||||||
|
registry = dr.async_get(hass)
|
||||||
|
|
||||||
|
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")})
|
||||||
|
assert device is not None
|
||||||
|
|
||||||
|
entity_id = f"{domain}.beer_{expected_entity_name}"
|
||||||
|
state = hass.states.get(entity_id)
|
||||||
|
assert state is not None
|
||||||
|
assert state.name == f"Beer {expected_friendly_name}"
|
||||||
|
|
||||||
|
|
||||||
async def help_test_entity_id_update_subscriptions(
|
async def help_test_entity_id_update_subscriptions(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mqtt_mock_entry: MqttMockHAClientGenerator,
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
@ -1390,7 +1429,7 @@ async def help_test_entity_debug_info_message(
|
||||||
with patch("homeassistant.util.dt.utcnow") as dt_utcnow:
|
with patch("homeassistant.util.dt.utcnow") as dt_utcnow:
|
||||||
dt_utcnow.return_value = start_dt
|
dt_utcnow.return_value = start_dt
|
||||||
if service:
|
if service:
|
||||||
service_data = {ATTR_ENTITY_ID: f"{domain}.test"}
|
service_data = {ATTR_ENTITY_ID: f"{domain}.beer_test"}
|
||||||
if service_parameters:
|
if service_parameters:
|
||||||
service_data.update(service_parameters)
|
service_data.update(service_parameters)
|
||||||
|
|
||||||
|
@ -1458,7 +1497,7 @@ async def help_test_entity_debug_info_remove(
|
||||||
"subscriptions"
|
"subscriptions"
|
||||||
]
|
]
|
||||||
assert len(debug_info_data["triggers"]) == 0
|
assert len(debug_info_data["triggers"]) == 0
|
||||||
assert debug_info_data["entities"][0]["entity_id"] == f"{domain}.test"
|
assert debug_info_data["entities"][0]["entity_id"] == f"{domain}.beer_test"
|
||||||
entity_id = debug_info_data["entities"][0]["entity_id"]
|
entity_id = debug_info_data["entities"][0]["entity_id"]
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", "")
|
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", "")
|
||||||
|
@ -1503,7 +1542,7 @@ async def help_test_entity_debug_info_update_entity_id(
|
||||||
== f"homeassistant/{domain}/bla/config"
|
== f"homeassistant/{domain}/bla/config"
|
||||||
)
|
)
|
||||||
assert debug_info_data["entities"][0]["discovery_data"]["payload"] == config
|
assert debug_info_data["entities"][0]["discovery_data"]["payload"] == config
|
||||||
assert debug_info_data["entities"][0]["entity_id"] == f"{domain}.test"
|
assert debug_info_data["entities"][0]["entity_id"] == f"{domain}.beer_test"
|
||||||
assert len(debug_info_data["entities"][0]["subscriptions"]) == 1
|
assert len(debug_info_data["entities"][0]["subscriptions"]) == 1
|
||||||
assert {"topic": "test-topic", "messages": []} in debug_info_data["entities"][0][
|
assert {"topic": "test-topic", "messages": []} in debug_info_data["entities"][0][
|
||||||
"subscriptions"
|
"subscriptions"
|
||||||
|
@ -1511,7 +1550,7 @@ async def help_test_entity_debug_info_update_entity_id(
|
||||||
assert len(debug_info_data["triggers"]) == 0
|
assert len(debug_info_data["triggers"]) == 0
|
||||||
|
|
||||||
entity_registry.async_update_entity(
|
entity_registry.async_update_entity(
|
||||||
f"{domain}.test", new_entity_id=f"{domain}.milk"
|
f"{domain}.beer_test", new_entity_id=f"{domain}.milk"
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -1529,7 +1568,7 @@ async def help_test_entity_debug_info_update_entity_id(
|
||||||
"subscriptions"
|
"subscriptions"
|
||||||
]
|
]
|
||||||
assert len(debug_info_data["triggers"]) == 0
|
assert len(debug_info_data["triggers"]) == 0
|
||||||
assert f"{domain}.test" not in hass.data["mqtt"].debug_info_entities
|
assert f"{domain}.beer_test" not in hass.data["mqtt"].debug_info_entities
|
||||||
|
|
||||||
|
|
||||||
async def help_test_entity_disabled_by_default(
|
async def help_test_entity_disabled_by_default(
|
||||||
|
|
|
@ -80,7 +80,7 @@ async def test_entry_diagnostics(
|
||||||
expected_debug_info = {
|
expected_debug_info = {
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"entity_id": "sensor.mqtt_sensor",
|
"entity_id": "sensor.none_mqtt_sensor",
|
||||||
"subscriptions": [{"topic": "foobar/sensor", "messages": []}],
|
"subscriptions": [{"topic": "foobar/sensor", "messages": []}],
|
||||||
"discovery_data": {
|
"discovery_data": {
|
||||||
"payload": config_sensor,
|
"payload": config_sensor,
|
||||||
|
@ -109,13 +109,13 @@ async def test_entry_diagnostics(
|
||||||
"disabled": False,
|
"disabled": False,
|
||||||
"disabled_by": None,
|
"disabled_by": None,
|
||||||
"entity_category": None,
|
"entity_category": None,
|
||||||
"entity_id": "sensor.mqtt_sensor",
|
"entity_id": "sensor.none_mqtt_sensor",
|
||||||
"icon": None,
|
"icon": None,
|
||||||
"original_device_class": None,
|
"original_device_class": None,
|
||||||
"original_icon": None,
|
"original_icon": None,
|
||||||
"state": {
|
"state": {
|
||||||
"attributes": {"friendly_name": "MQTT Sensor"},
|
"attributes": {"friendly_name": "MQTT Sensor"},
|
||||||
"entity_id": "sensor.mqtt_sensor",
|
"entity_id": "sensor.none_mqtt_sensor",
|
||||||
"last_changed": ANY,
|
"last_changed": ANY,
|
||||||
"last_updated": ANY,
|
"last_updated": ANY,
|
||||||
"state": "unknown",
|
"state": "unknown",
|
||||||
|
|
|
@ -729,10 +729,10 @@ async def test_cleanup_device(
|
||||||
# Verify device and registry entries are created
|
# Verify device and registry entries are created
|
||||||
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
||||||
assert device_entry is not None
|
assert device_entry is not None
|
||||||
entity_entry = entity_registry.async_get("sensor.mqtt_sensor")
|
entity_entry = entity_registry.async_get("sensor.none_mqtt_sensor")
|
||||||
assert entity_entry is not None
|
assert entity_entry is not None
|
||||||
|
|
||||||
state = hass.states.get("sensor.mqtt_sensor")
|
state = hass.states.get("sensor.none_mqtt_sensor")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
|
|
||||||
# Remove MQTT from the device
|
# Remove MQTT from the device
|
||||||
|
@ -753,11 +753,11 @@ async def test_cleanup_device(
|
||||||
# Verify device and registry entries are cleared
|
# Verify device and registry entries are cleared
|
||||||
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
||||||
assert device_entry is None
|
assert device_entry is None
|
||||||
entity_entry = entity_registry.async_get("sensor.mqtt_sensor")
|
entity_entry = entity_registry.async_get("sensor.none_mqtt_sensor")
|
||||||
assert entity_entry is None
|
assert entity_entry is None
|
||||||
|
|
||||||
# Verify state is removed
|
# Verify state is removed
|
||||||
state = hass.states.get("sensor.mqtt_sensor")
|
state = hass.states.get("sensor.none_mqtt_sensor")
|
||||||
assert state is None
|
assert state is None
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -788,10 +788,10 @@ async def test_cleanup_device_mqtt(
|
||||||
# Verify device and registry entries are created
|
# Verify device and registry entries are created
|
||||||
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
||||||
assert device_entry is not None
|
assert device_entry is not None
|
||||||
entity_entry = entity_registry.async_get("sensor.mqtt_sensor")
|
entity_entry = entity_registry.async_get("sensor.none_mqtt_sensor")
|
||||||
assert entity_entry is not None
|
assert entity_entry is not None
|
||||||
|
|
||||||
state = hass.states.get("sensor.mqtt_sensor")
|
state = hass.states.get("sensor.none_mqtt_sensor")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", "")
|
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", "")
|
||||||
|
@ -801,11 +801,11 @@ async def test_cleanup_device_mqtt(
|
||||||
# Verify device and registry entries are cleared
|
# Verify device and registry entries are cleared
|
||||||
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")})
|
||||||
assert device_entry is None
|
assert device_entry is None
|
||||||
entity_entry = entity_registry.async_get("sensor.mqtt_sensor")
|
entity_entry = entity_registry.async_get("sensor.none_mqtt_sensor")
|
||||||
assert entity_entry is None
|
assert entity_entry is None
|
||||||
|
|
||||||
# Verify state is removed
|
# Verify state is removed
|
||||||
state = hass.states.get("sensor.mqtt_sensor")
|
state = hass.states.get("sensor.none_mqtt_sensor")
|
||||||
assert state is None
|
assert state is None
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -873,10 +873,10 @@ async def test_cleanup_device_multiple_config_entries(
|
||||||
mqtt_config_entry.entry_id,
|
mqtt_config_entry.entry_id,
|
||||||
config_entry.entry_id,
|
config_entry.entry_id,
|
||||||
}
|
}
|
||||||
entity_entry = entity_registry.async_get("sensor.mqtt_sensor")
|
entity_entry = entity_registry.async_get("sensor.none_mqtt_sensor")
|
||||||
assert entity_entry is not None
|
assert entity_entry is not None
|
||||||
|
|
||||||
state = hass.states.get("sensor.mqtt_sensor")
|
state = hass.states.get("sensor.none_mqtt_sensor")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
|
|
||||||
# Remove MQTT from the device
|
# Remove MQTT from the device
|
||||||
|
@ -900,12 +900,12 @@ async def test_cleanup_device_multiple_config_entries(
|
||||||
connections={("mac", "12:34:56:AB:CD:EF")}
|
connections={("mac", "12:34:56:AB:CD:EF")}
|
||||||
)
|
)
|
||||||
assert device_entry is not None
|
assert device_entry is not None
|
||||||
entity_entry = entity_registry.async_get("sensor.mqtt_sensor")
|
entity_entry = entity_registry.async_get("sensor.none_mqtt_sensor")
|
||||||
assert device_entry.config_entries == {config_entry.entry_id}
|
assert device_entry.config_entries == {config_entry.entry_id}
|
||||||
assert entity_entry is None
|
assert entity_entry is None
|
||||||
|
|
||||||
# Verify state is removed
|
# Verify state is removed
|
||||||
state = hass.states.get("sensor.mqtt_sensor")
|
state = hass.states.get("sensor.none_mqtt_sensor")
|
||||||
assert state is None
|
assert state is None
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -973,10 +973,10 @@ async def test_cleanup_device_multiple_config_entries_mqtt(
|
||||||
mqtt_config_entry.entry_id,
|
mqtt_config_entry.entry_id,
|
||||||
config_entry.entry_id,
|
config_entry.entry_id,
|
||||||
}
|
}
|
||||||
entity_entry = entity_registry.async_get("sensor.mqtt_sensor")
|
entity_entry = entity_registry.async_get("sensor.none_mqtt_sensor")
|
||||||
assert entity_entry is not None
|
assert entity_entry is not None
|
||||||
|
|
||||||
state = hass.states.get("sensor.mqtt_sensor")
|
state = hass.states.get("sensor.none_mqtt_sensor")
|
||||||
assert state is not None
|
assert state is not None
|
||||||
|
|
||||||
# Send MQTT messages to remove
|
# Send MQTT messages to remove
|
||||||
|
@ -992,12 +992,12 @@ async def test_cleanup_device_multiple_config_entries_mqtt(
|
||||||
connections={("mac", "12:34:56:AB:CD:EF")}
|
connections={("mac", "12:34:56:AB:CD:EF")}
|
||||||
)
|
)
|
||||||
assert device_entry is not None
|
assert device_entry is not None
|
||||||
entity_entry = entity_registry.async_get("sensor.mqtt_sensor")
|
entity_entry = entity_registry.async_get("sensor.none_mqtt_sensor")
|
||||||
assert device_entry.config_entries == {config_entry.entry_id}
|
assert device_entry.config_entries == {config_entry.entry_id}
|
||||||
assert entity_entry is None
|
assert entity_entry is None
|
||||||
|
|
||||||
# Verify state is removed
|
# Verify state is removed
|
||||||
state = hass.states.get("sensor.mqtt_sensor")
|
state = hass.states.get("sensor.none_mqtt_sensor")
|
||||||
assert state is None
|
assert state is None
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -1474,13 +1474,12 @@ async def test_clear_config_topic_disabled_entity(
|
||||||
mqtt_mock = await mqtt_mock_entry()
|
mqtt_mock = await mqtt_mock_entry()
|
||||||
# discover an entity that is not enabled by default
|
# discover an entity that is not enabled by default
|
||||||
config = {
|
config = {
|
||||||
"name": "sbfspot_12345",
|
|
||||||
"state_topic": "homeassistant_test/sensor/sbfspot_0/sbfspot_12345/",
|
"state_topic": "homeassistant_test/sensor/sbfspot_0/sbfspot_12345/",
|
||||||
"unique_id": "sbfspot_12345",
|
"unique_id": "sbfspot_12345",
|
||||||
"enabled_by_default": False,
|
"enabled_by_default": False,
|
||||||
"device": {
|
"device": {
|
||||||
"identifiers": ["sbfspot_12345"],
|
"identifiers": ["sbfspot_12345"],
|
||||||
"name": "sbfspot_12345",
|
"name": "abc123",
|
||||||
"sw_version": "1.0",
|
"sw_version": "1.0",
|
||||||
"connections": [["mac", "12:34:56:AB:CD:EF"]],
|
"connections": [["mac", "12:34:56:AB:CD:EF"]],
|
||||||
},
|
},
|
||||||
|
@ -1512,9 +1511,9 @@ async def test_clear_config_topic_disabled_entity(
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert "Platform mqtt does not generate unique IDs" in caplog.text
|
assert "Platform mqtt does not generate unique IDs" in caplog.text
|
||||||
|
|
||||||
assert hass.states.get("sensor.sbfspot_12345") is None # disabled
|
assert hass.states.get("sensor.abc123_sbfspot_12345") is None # disabled
|
||||||
assert hass.states.get("sensor.sbfspot_12345_1") is not None # enabled
|
assert hass.states.get("sensor.abc123_sbfspot_12345_1") is not None # enabled
|
||||||
assert hass.states.get("sensor.sbfspot_12345_2") is None # not unique
|
assert hass.states.get("sensor.abc123_sbfspot_12345_2") is None # not unique
|
||||||
|
|
||||||
# Verify device is created
|
# Verify device is created
|
||||||
device_entry = device_registry.async_get_device(
|
device_entry = device_registry.async_get_device(
|
||||||
|
@ -1603,13 +1602,12 @@ async def test_unique_id_collission_has_priority(
|
||||||
"""Test the unique_id collision detection has priority over registry disabled items."""
|
"""Test the unique_id collision detection has priority over registry disabled items."""
|
||||||
await mqtt_mock_entry()
|
await mqtt_mock_entry()
|
||||||
config = {
|
config = {
|
||||||
"name": "sbfspot_12345",
|
|
||||||
"state_topic": "homeassistant_test/sensor/sbfspot_0/sbfspot_12345/",
|
"state_topic": "homeassistant_test/sensor/sbfspot_0/sbfspot_12345/",
|
||||||
"unique_id": "sbfspot_12345",
|
"unique_id": "sbfspot_12345",
|
||||||
"enabled_by_default": False,
|
"enabled_by_default": False,
|
||||||
"device": {
|
"device": {
|
||||||
"identifiers": ["sbfspot_12345"],
|
"identifiers": ["sbfspot_12345"],
|
||||||
"name": "sbfspot_12345",
|
"name": "abc123",
|
||||||
"sw_version": "1.0",
|
"sw_version": "1.0",
|
||||||
"connections": [["mac", "12:34:56:AB:CD:EF"]],
|
"connections": [["mac", "12:34:56:AB:CD:EF"]],
|
||||||
},
|
},
|
||||||
|
@ -1633,13 +1631,13 @@ async def test_unique_id_collission_has_priority(
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert hass.states.get("sensor.sbfspot_12345_1") is None # not enabled
|
assert hass.states.get("sensor.abc123_sbfspot_12345_1") is None # not enabled
|
||||||
assert hass.states.get("sensor.sbfspot_12345_2") is None # not unique
|
assert hass.states.get("sensor.abc123_sbfspot_12345_2") is None # not unique
|
||||||
|
|
||||||
# Verify the first entity is created
|
# Verify the first entity is created
|
||||||
assert entity_registry.async_get("sensor.sbfspot_12345_1") is not None
|
assert entity_registry.async_get("sensor.abc123_sbfspot_12345_1") is not None
|
||||||
# Verify the second entity is not created because it is not unique
|
# Verify the second entity is not created because it is not unique
|
||||||
assert entity_registry.async_get("sensor.sbfspot_12345_2") is None
|
assert entity_registry.async_get("sensor.abc123_sbfspot_12345_2") is None
|
||||||
|
|
||||||
|
|
||||||
@patch("homeassistant.components.mqtt.PLATFORMS", [Platform.SENSOR])
|
@patch("homeassistant.components.mqtt.PLATFORMS", [Platform.SENSOR])
|
||||||
|
|
|
@ -2821,7 +2821,7 @@ async def test_mqtt_ws_get_device_debug_info(
|
||||||
expected_result = {
|
expected_result = {
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"entity_id": "sensor.mqtt_sensor",
|
"entity_id": "sensor.none_mqtt_sensor",
|
||||||
"subscriptions": [{"topic": "foobar/sensor", "messages": []}],
|
"subscriptions": [{"topic": "foobar/sensor", "messages": []}],
|
||||||
"discovery_data": {
|
"discovery_data": {
|
||||||
"payload": config_sensor,
|
"payload": config_sensor,
|
||||||
|
@ -2884,7 +2884,7 @@ async def test_mqtt_ws_get_device_debug_info_binary(
|
||||||
expected_result = {
|
expected_result = {
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"entity_id": "camera.mqtt_camera",
|
"entity_id": "camera.none_mqtt_camera",
|
||||||
"subscriptions": [
|
"subscriptions": [
|
||||||
{
|
{
|
||||||
"topic": "foobar/image",
|
"topic": "foobar/image",
|
||||||
|
|
|
@ -5,8 +5,12 @@ from unittest.mock import patch
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components import mqtt, sensor
|
from homeassistant.components import mqtt, sensor
|
||||||
|
from homeassistant.components.mqtt.sensor import DEFAULT_NAME as DEFAULT_SENSOR_NAME
|
||||||
from homeassistant.const import EVENT_STATE_CHANGED, Platform
|
from homeassistant.const import EVENT_STATE_CHANGED, Platform
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers import (
|
||||||
|
device_registry as dr,
|
||||||
|
)
|
||||||
|
|
||||||
from tests.common import async_fire_mqtt_message
|
from tests.common import async_fire_mqtt_message
|
||||||
from tests.typing import MqttMockHAClientGenerator
|
from tests.typing import MqttMockHAClientGenerator
|
||||||
|
@ -73,3 +77,179 @@ async def test_availability_with_shared_state_topic(
|
||||||
# The availability is changed but the topic is shared,
|
# The availability is changed but the topic is shared,
|
||||||
# hence there the state will be written when the value is updated
|
# hence there the state will be written when the value is updated
|
||||||
assert len(events) == 1
|
assert len(events) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("hass_config", "entity_id", "friendly_name", "device_name", "assert_log"),
|
||||||
|
[
|
||||||
|
( # default_entity_name_without_device_name
|
||||||
|
{
|
||||||
|
mqtt.DOMAIN: {
|
||||||
|
sensor.DOMAIN: {
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "veryunique",
|
||||||
|
"device": {"identifiers": ["helloworld"]},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sensor.none_mqtt_sensor",
|
||||||
|
DEFAULT_SENSOR_NAME,
|
||||||
|
None,
|
||||||
|
True,
|
||||||
|
),
|
||||||
|
( # default_entity_name_with_device_name
|
||||||
|
{
|
||||||
|
mqtt.DOMAIN: {
|
||||||
|
sensor.DOMAIN: {
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "veryunique",
|
||||||
|
"device": {"name": "Test", "identifiers": ["helloworld"]},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sensor.test_mqtt_sensor",
|
||||||
|
"Test MQTT Sensor",
|
||||||
|
"Test",
|
||||||
|
False,
|
||||||
|
),
|
||||||
|
( # name_follows_device_class
|
||||||
|
{
|
||||||
|
mqtt.DOMAIN: {
|
||||||
|
sensor.DOMAIN: {
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "veryunique",
|
||||||
|
"device_class": "humidity",
|
||||||
|
"device": {"name": "Test", "identifiers": ["helloworld"]},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sensor.test_humidity",
|
||||||
|
"Test Humidity",
|
||||||
|
"Test",
|
||||||
|
False,
|
||||||
|
),
|
||||||
|
( # name_follows_device_class_without_device_name
|
||||||
|
{
|
||||||
|
mqtt.DOMAIN: {
|
||||||
|
sensor.DOMAIN: {
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "veryunique",
|
||||||
|
"device_class": "humidity",
|
||||||
|
"device": {"identifiers": ["helloworld"]},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sensor.none_humidity",
|
||||||
|
"Humidity",
|
||||||
|
None,
|
||||||
|
True,
|
||||||
|
),
|
||||||
|
( # name_overrides_device_class
|
||||||
|
{
|
||||||
|
mqtt.DOMAIN: {
|
||||||
|
sensor.DOMAIN: {
|
||||||
|
"name": "MySensor",
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "veryunique",
|
||||||
|
"device_class": "humidity",
|
||||||
|
"device": {"name": "Test", "identifiers": ["helloworld"]},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sensor.test_mysensor",
|
||||||
|
"Test MySensor",
|
||||||
|
"Test",
|
||||||
|
False,
|
||||||
|
),
|
||||||
|
( # name_set_no_device_name_set
|
||||||
|
{
|
||||||
|
mqtt.DOMAIN: {
|
||||||
|
sensor.DOMAIN: {
|
||||||
|
"name": "MySensor",
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "veryunique",
|
||||||
|
"device_class": "humidity",
|
||||||
|
"device": {"identifiers": ["helloworld"]},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sensor.none_mysensor",
|
||||||
|
"MySensor",
|
||||||
|
None,
|
||||||
|
True,
|
||||||
|
),
|
||||||
|
( # none_entity_name_with_device_name
|
||||||
|
{
|
||||||
|
mqtt.DOMAIN: {
|
||||||
|
sensor.DOMAIN: {
|
||||||
|
"name": None,
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "veryunique",
|
||||||
|
"device_class": "humidity",
|
||||||
|
"device": {"name": "Test", "identifiers": ["helloworld"]},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sensor.test",
|
||||||
|
"Test",
|
||||||
|
"Test",
|
||||||
|
False,
|
||||||
|
),
|
||||||
|
( # none_entity_name_without_device_name
|
||||||
|
{
|
||||||
|
mqtt.DOMAIN: {
|
||||||
|
sensor.DOMAIN: {
|
||||||
|
"name": None,
|
||||||
|
"state_topic": "test-topic",
|
||||||
|
"unique_id": "veryunique",
|
||||||
|
"device_class": "humidity",
|
||||||
|
"device": {"identifiers": ["helloworld"]},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sensor.mqtt_veryunique",
|
||||||
|
"mqtt veryunique",
|
||||||
|
None,
|
||||||
|
True,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
ids=[
|
||||||
|
"default_entity_name_without_device_name",
|
||||||
|
"default_entity_name_with_device_name",
|
||||||
|
"name_follows_device_class",
|
||||||
|
"name_follows_device_class_without_device_name",
|
||||||
|
"name_overrides_device_class",
|
||||||
|
"name_set_no_device_name_set",
|
||||||
|
"none_entity_name_with_device_name",
|
||||||
|
"none_entity_name_without_device_name",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@patch("homeassistant.components.mqtt.PLATFORMS", [Platform.SENSOR])
|
||||||
|
async def test_default_entity_and_device_name(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
entity_id: str,
|
||||||
|
friendly_name: str,
|
||||||
|
device_name: str | None,
|
||||||
|
assert_log: bool,
|
||||||
|
) -> None:
|
||||||
|
"""Test device name setup with and without a device_class set.
|
||||||
|
|
||||||
|
This is a test helper for the _setup_common_attributes_from_config mixin.
|
||||||
|
"""
|
||||||
|
await mqtt_mock_entry()
|
||||||
|
|
||||||
|
registry = dr.async_get(hass)
|
||||||
|
|
||||||
|
device = registry.async_get_device({("mqtt", "helloworld")})
|
||||||
|
assert device is not None
|
||||||
|
assert device.name == device_name
|
||||||
|
|
||||||
|
state = hass.states.get(entity_id)
|
||||||
|
assert state is not None
|
||||||
|
assert state.name == friendly_name
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"MQTT device information always needs to include a name" in caplog.text
|
||||||
|
) is assert_log
|
||||||
|
|
|
@ -48,6 +48,7 @@ from .test_common import (
|
||||||
help_test_entity_device_info_with_identifier,
|
help_test_entity_device_info_with_identifier,
|
||||||
help_test_entity_id_update_discovery_update,
|
help_test_entity_id_update_discovery_update,
|
||||||
help_test_entity_id_update_subscriptions,
|
help_test_entity_id_update_subscriptions,
|
||||||
|
help_test_entity_name,
|
||||||
help_test_publishing_with_custom_encoding,
|
help_test_publishing_with_custom_encoding,
|
||||||
help_test_reloadable,
|
help_test_reloadable,
|
||||||
help_test_setting_attribute_via_mqtt_json_message,
|
help_test_setting_attribute_via_mqtt_json_message,
|
||||||
|
@ -1121,3 +1122,21 @@ async def test_unload_entry(
|
||||||
await help_test_unload_config_entry_with_platform(
|
await help_test_unload_config_entry_with_platform(
|
||||||
hass, mqtt_mock_entry, domain, config
|
hass, mqtt_mock_entry, domain, config
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("expected_friendly_name", "device_class"),
|
||||||
|
[("test", None), ("Humidity", "humidity"), ("Temperature", "temperature")],
|
||||||
|
)
|
||||||
|
async def test_entity_name(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
expected_friendly_name: str | None,
|
||||||
|
device_class: str | None,
|
||||||
|
) -> None:
|
||||||
|
"""Test the entity name setup."""
|
||||||
|
domain = number.DOMAIN
|
||||||
|
config = DEFAULT_CONFIG
|
||||||
|
await help_test_entity_name(
|
||||||
|
hass, mqtt_mock_entry, domain, config, expected_friendly_name, device_class
|
||||||
|
)
|
||||||
|
|
|
@ -53,6 +53,7 @@ from .test_common import (
|
||||||
help_test_entity_disabled_by_default,
|
help_test_entity_disabled_by_default,
|
||||||
help_test_entity_id_update_discovery_update,
|
help_test_entity_id_update_discovery_update,
|
||||||
help_test_entity_id_update_subscriptions,
|
help_test_entity_id_update_subscriptions,
|
||||||
|
help_test_entity_name,
|
||||||
help_test_reload_with_config,
|
help_test_reload_with_config,
|
||||||
help_test_reloadable,
|
help_test_reloadable,
|
||||||
help_test_setting_attribute_via_mqtt_json_message,
|
help_test_setting_attribute_via_mqtt_json_message,
|
||||||
|
@ -1409,3 +1410,21 @@ async def test_unload_entry(
|
||||||
await help_test_unload_config_entry_with_platform(
|
await help_test_unload_config_entry_with_platform(
|
||||||
hass, mqtt_mock_entry, domain, config
|
hass, mqtt_mock_entry, domain, config
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("expected_friendly_name", "device_class"),
|
||||||
|
[("test", None), ("Humidity", "humidity"), ("Temperature", "temperature")],
|
||||||
|
)
|
||||||
|
async def test_entity_name(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
expected_friendly_name: str | None,
|
||||||
|
device_class: str | None,
|
||||||
|
) -> None:
|
||||||
|
"""Test the entity name setup."""
|
||||||
|
domain = sensor.DOMAIN
|
||||||
|
config = DEFAULT_CONFIG
|
||||||
|
await help_test_entity_name(
|
||||||
|
hass, mqtt_mock_entry, domain, config, expected_friendly_name, device_class
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue