diff --git a/.coveragerc b/.coveragerc index 0d02af162fb..13cab09e294 100644 --- a/.coveragerc +++ b/.coveragerc @@ -283,6 +283,7 @@ omit = homeassistant/components/econet/water_heater.py homeassistant/components/ecovacs/controller.py homeassistant/components/ecovacs/entity.py + homeassistant/components/ecovacs/image.py homeassistant/components/ecovacs/util.py homeassistant/components/ecovacs/vacuum.py homeassistant/components/ecowitt/__init__.py diff --git a/homeassistant/components/ecovacs/__init__.py b/homeassistant/components/ecovacs/__init__.py index 5a17fd6d66f..1f28240c06a 100644 --- a/homeassistant/components/ecovacs/__init__.py +++ b/homeassistant/components/ecovacs/__init__.py @@ -26,6 +26,7 @@ CONFIG_SCHEMA = vol.Schema( PLATFORMS = [ Platform.BINARY_SENSOR, + Platform.IMAGE, Platform.SELECT, Platform.SENSOR, Platform.VACUUM, diff --git a/homeassistant/components/ecovacs/image.py b/homeassistant/components/ecovacs/image.py new file mode 100644 index 00000000000..18c162138fb --- /dev/null +++ b/homeassistant/components/ecovacs/image.py @@ -0,0 +1,84 @@ +"""Ecovacs image entities.""" + +from deebot_client.capabilities import CapabilityMap +from deebot_client.device import Device +from deebot_client.events.map import CachedMapInfoEvent, MapChangedEvent + +from homeassistant.components.image import ImageEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import EntityDescription +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DOMAIN +from .controller import EcovacsController +from .entity import EcovacsEntity + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Add entities for passed config_entry in HA.""" + controller: EcovacsController = hass.data[DOMAIN][config_entry.entry_id] + entities = [] + for device in controller.devices: + if caps := device.capabilities.map: + entities.append(EcovacsMap(device, caps, hass)) + + if entities: + async_add_entities(entities) + + +class EcovacsMap( + EcovacsEntity[CapabilityMap], + ImageEntity, +): + """Ecovacs map.""" + + _attr_content_type = "image/svg+xml" + + def __init__( + self, + device: Device, + capability: CapabilityMap, + hass: HomeAssistant, + ) -> None: + """Initialize entity.""" + super().__init__(device, capability, hass=hass) + self._attr_extra_state_attributes = {} + + entity_description = EntityDescription( + key="map", + translation_key="map", + ) + + def image(self) -> bytes | None: + """Return bytes of image or None.""" + if svg := self._device.map.get_svg_map(): + return svg.encode() + + return None + + async def async_added_to_hass(self) -> None: + """Set up the event listeners now that hass is ready.""" + await super().async_added_to_hass() + + async def on_info(event: CachedMapInfoEvent) -> None: + self._attr_extra_state_attributes["map_name"] = event.name + + async def on_changed(event: MapChangedEvent) -> None: + self._attr_image_last_updated = event.when + self.async_write_ha_state() + + self._subscribe(self._capability.chached_info.event, on_info) + self._subscribe(self._capability.changed.event, on_changed) + + async def async_update(self) -> None: + """Update the entity. + + Only used by the generic entity update service. + """ + await super().async_update() + self._device.map.refresh() diff --git a/homeassistant/components/ecovacs/strings.json b/homeassistant/components/ecovacs/strings.json index 7a9065d7706..016c43ceb09 100644 --- a/homeassistant/components/ecovacs/strings.json +++ b/homeassistant/components/ecovacs/strings.json @@ -24,6 +24,11 @@ "name": "Mop attached" } }, + "image": { + "map": { + "name": "Map" + } + }, "sensor": { "error": { "name": "Error", diff --git a/tests/components/ecovacs/test_init.py b/tests/components/ecovacs/test_init.py index c64d3055624..04e71567dda 100644 --- a/tests/components/ecovacs/test_init.py +++ b/tests/components/ecovacs/test_init.py @@ -116,7 +116,7 @@ async def test_devices_in_dr( @pytest.mark.parametrize( ("device_fixture", "entities"), [ - ("yna5x1", 16), + ("yna5x1", 17), ], ) async def test_all_entities_loaded(