Allow to set `entity picture` on mqtt entity platforms (#128404)

pull/129185/head
Jan Bouwhuis 2024-10-25 20:16:11 +02:00 committed by GitHub
parent 3734fa948f
commit 4b63829eef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 181 additions and 0 deletions

View File

@ -61,6 +61,7 @@ CONF_CURRENT_HUMIDITY_TOPIC = "current_humidity_topic"
CONF_CURRENT_TEMP_TEMPLATE = "current_temperature_template"
CONF_CURRENT_TEMP_TOPIC = "current_temperature_topic"
CONF_ENABLED_BY_DEFAULT = "enabled_by_default"
CONF_ENTITY_PICTURE = "entity_picture"
CONF_MODE_COMMAND_TEMPLATE = "mode_command_template"
CONF_MODE_COMMAND_TOPIC = "mode_command_topic"
CONF_MODE_LIST = "modes"

View File

@ -76,6 +76,7 @@ from .const import (
CONF_CONNECTIONS,
CONF_ENABLED_BY_DEFAULT,
CONF_ENCODING,
CONF_ENTITY_PICTURE,
CONF_HW_VERSION,
CONF_IDENTIFIERS,
CONF_JSON_ATTRS_TEMPLATE,
@ -1211,6 +1212,7 @@ class MqttEntity(
config.get(CONF_ENABLED_BY_DEFAULT)
)
self._attr_icon = config.get(CONF_ICON)
self._attr_entity_picture = config.get(CONF_ENTITY_PICTURE)
# Set the entity name if needed
self._set_entity_name(config)

View File

@ -29,6 +29,7 @@ from .const import (
CONF_CONNECTIONS,
CONF_DEPRECATED_VIA_HUB,
CONF_ENABLED_BY_DEFAULT,
CONF_ENTITY_PICTURE,
CONF_HW_VERSION,
CONF_IDENTIFIERS,
CONF_JSON_ATTRS_TEMPLATE,
@ -140,6 +141,7 @@ MQTT_ORIGIN_INFO_SCHEMA = vol.All(
MQTT_ENTITY_COMMON_SCHEMA = MQTT_AVAILABILITY_SCHEMA.extend(
{
vol.Optional(CONF_DEVICE): MQTT_ENTITY_DEVICE_INFO_SCHEMA,
vol.Optional(CONF_ENTITY_PICTURE): cv.string,
vol.Optional(CONF_ORIGIN): MQTT_ORIGIN_INFO_SCHEMA,
vol.Optional(CONF_ENABLED_BY_DEFAULT, default=True): cv.boolean,
vol.Optional(CONF_ENTITY_CATEGORY): ENTITY_CATEGORIES_SCHEMA,

View File

@ -50,6 +50,7 @@ from .test_common import (
help_test_entity_device_info_update,
help_test_entity_device_info_with_connection,
help_test_entity_device_info_with_identifier,
help_test_entity_icon_and_entity_picture,
help_test_entity_id_update_discovery_update,
help_test_entity_id_update_subscriptions,
help_test_entity_name,
@ -1280,6 +1281,18 @@ async def test_entity_name(
)
async def test_entity_icon_and_entity_picture(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test the entity icon or picture setup."""
domain = alarm_control_panel.DOMAIN
config = DEFAULT_CONFIG
await help_test_entity_icon_and_entity_picture(
hass, mqtt_mock_entry, domain, config
)
@pytest.mark.parametrize(
"hass_config",
[

View File

@ -40,6 +40,7 @@ from .test_common import (
help_test_entity_device_info_update,
help_test_entity_device_info_with_connection,
help_test_entity_device_info_with_identifier,
help_test_entity_icon_and_entity_picture,
help_test_entity_id_update_discovery_update,
help_test_entity_id_update_subscriptions,
help_test_entity_name,
@ -1193,6 +1194,18 @@ async def test_entity_name(
)
async def test_entity_icon_and_entity_picture(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test the entity icon or picture setup."""
domain = binary_sensor.DOMAIN
config = DEFAULT_CONFIG
await help_test_entity_icon_and_entity_picture(
hass, mqtt_mock_entry, domain, config
)
@pytest.mark.parametrize(
"hass_config",
[

View File

@ -25,6 +25,7 @@ from .test_common import (
help_test_entity_device_info_update,
help_test_entity_device_info_with_connection,
help_test_entity_device_info_with_identifier,
help_test_entity_icon_and_entity_picture,
help_test_entity_id_update_discovery_update,
help_test_entity_name,
help_test_publishing_with_custom_encoding,
@ -534,3 +535,15 @@ async def test_entity_name(
await help_test_entity_name(
hass, mqtt_mock_entry, domain, config, expected_friendly_name, device_class
)
async def test_entity_icon_and_entity_picture(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test the entity icon or picture setup."""
domain = button.DOMAIN
config = DEFAULT_CONFIG
await help_test_entity_icon_and_entity_picture(
hass, mqtt_mock_entry, domain, config
)

View File

@ -53,6 +53,7 @@ from .test_common import (
help_test_entity_device_info_update,
help_test_entity_device_info_with_connection,
help_test_entity_device_info_with_identifier,
help_test_entity_icon_and_entity_picture,
help_test_entity_id_update_discovery_update,
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
@ -2448,3 +2449,15 @@ async def test_value_template_fails(
"TypeError: unsupported operand type(s) for *: 'NoneType' and 'int' rendering template"
in caplog.text
)
async def test_entity_icon_and_entity_picture(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test the entity name setup."""
domain = climate.DOMAIN
config = DEFAULT_CONFIG
await help_test_entity_icon_and_entity_picture(
hass, mqtt_mock_entry, domain, config
)

View File

@ -1668,6 +1668,61 @@ async def help_test_entity_category(
assert not ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, unique_id)
async def help_test_entity_icon_and_entity_picture(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
domain: str,
config: ConfigType,
default_entity_picture: str | None = None,
) -> None:
"""Test entity picture and icon."""
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)
ent_registry = er.async_get(hass)
# Discover an entity without entity icon or picture
unique_id = "veryunique1"
config["unique_id"] = unique_id
data = json.dumps(config)
async_fire_mqtt_message(hass, f"homeassistant/{domain}/{unique_id}/config", data)
await hass.async_block_till_done()
entity_id = ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, unique_id)
state = hass.states.get(entity_id)
assert entity_id is not None and state
assert state.attributes.get("icon") is None
assert state.attributes.get("entity_picture") == default_entity_picture
# Discover an entity with an entity picture set
unique_id = "veryunique2"
config["entity_picture"] = "https://example.com/mypicture.png"
config["unique_id"] = unique_id
data = json.dumps(config)
async_fire_mqtt_message(hass, f"homeassistant/{domain}/{unique_id}/config", data)
await hass.async_block_till_done()
entity_id = ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, unique_id)
state = hass.states.get(entity_id)
assert entity_id is not None and state
assert state.attributes.get("icon") is None
assert state.attributes.get("entity_picture") == "https://example.com/mypicture.png"
config.pop("entity_picture")
# Discover an entity with an entity icon set
unique_id = "veryunique3"
config["icon"] = "mdi:emoji-happy-outline"
config["unique_id"] = unique_id
data = json.dumps(config)
async_fire_mqtt_message(hass, f"homeassistant/{domain}/{unique_id}/config", data)
await hass.async_block_till_done()
entity_id = ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, unique_id)
state = hass.states.get(entity_id)
assert entity_id is not None and state
assert state.attributes.get("icon") == "mdi:emoji-happy-outline"
assert state.attributes.get("entity_picture") == default_entity_picture
async def help_test_publishing_with_custom_encoding(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,

View File

@ -62,6 +62,7 @@ from .test_common import (
help_test_entity_device_info_update,
help_test_entity_device_info_with_connection,
help_test_entity_device_info_with_identifier,
help_test_entity_icon_and_entity_picture,
help_test_entity_id_update_discovery_update,
help_test_entity_id_update_subscriptions,
help_test_publishing_with_custom_encoding,
@ -3548,3 +3549,15 @@ async def test_value_template_fails(
"TypeError: unsupported operand type(s) for *: 'NoneType' and 'int' rendering template"
in caplog.text
)
async def test_entity_icon_and_entity_picture(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test the entity name setup."""
domain = cover.DOMAIN
config = DEFAULT_CONFIG
await help_test_entity_icon_and_entity_picture(
hass, mqtt_mock_entry, domain, config
)

View File

@ -37,6 +37,7 @@ from .test_common import (
help_test_entity_device_info_with_connection,
help_test_entity_device_info_with_identifier,
help_test_entity_disabled_by_default,
help_test_entity_icon_and_entity_picture,
help_test_entity_id_update_discovery_update,
help_test_entity_id_update_subscriptions,
help_test_entity_name,
@ -705,6 +706,18 @@ async def test_entity_name(
)
async def test_entity_icon_and_entity_picture(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test the entity icon or picture setup."""
domain = event.DOMAIN
config = DEFAULT_CONFIG
await help_test_entity_icon_and_entity_picture(
hass, mqtt_mock_entry, domain, config
)
@pytest.mark.parametrize(
"hass_config",
[

View File

@ -47,6 +47,7 @@ from .test_common import (
help_test_entity_device_info_update,
help_test_entity_device_info_with_connection,
help_test_entity_device_info_with_identifier,
help_test_entity_icon_and_entity_picture,
help_test_entity_id_update_discovery_update,
help_test_entity_id_update_subscriptions,
help_test_entity_name,
@ -1100,6 +1101,18 @@ async def test_entity_name(
)
async def test_entity_icon_and_entity_picture(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test the entity icon or picture setup."""
domain = number.DOMAIN
config = DEFAULT_CONFIG
await help_test_entity_icon_and_entity_picture(
hass, mqtt_mock_entry, domain, config
)
@pytest.mark.parametrize(
"hass_config",
[

View File

@ -53,6 +53,7 @@ from .test_common import (
help_test_entity_device_info_with_connection,
help_test_entity_device_info_with_identifier,
help_test_entity_disabled_by_default,
help_test_entity_icon_and_entity_picture,
help_test_entity_id_update_discovery_update,
help_test_entity_id_update_subscriptions,
help_test_entity_name,
@ -1583,6 +1584,18 @@ async def test_entity_name(
)
async def test_entity_icon_and_entity_picture(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test the entity name setup."""
domain = sensor.DOMAIN
config = DEFAULT_CONFIG
await help_test_entity_icon_and_entity_picture(
hass, mqtt_mock_entry, domain, config
)
@pytest.mark.parametrize(
"hass_config",
[

View File

@ -25,6 +25,7 @@ from .test_common import (
help_test_entity_device_info_update,
help_test_entity_device_info_with_connection,
help_test_entity_device_info_with_identifier,
help_test_entity_icon_and_entity_picture,
help_test_entity_id_update_discovery_update,
help_test_reloadable,
help_test_setting_attribute_via_mqtt_json_message,
@ -775,3 +776,19 @@ async def test_value_template_fails(
"TypeError: unsupported operand type(s) for *: 'NoneType' and 'int' rendering template"
in caplog.text
)
async def test_entity_icon_and_entity_picture(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test the entity icon or picture setup."""
domain = update.DOMAIN
config = DEFAULT_CONFIG
await help_test_entity_icon_and_entity_picture(
hass,
mqtt_mock_entry,
domain,
config,
default_entity_picture="https://brands.home-assistant.io/_/mqtt/icon.png",
)