"""Support for Launch Library sensors.""" from __future__ import annotations import logging from typing import Any from pylaunches.objects.launch import Launch import voluptuous as vol from homeassistant.components.sensor import ( PLATFORM_SCHEMA, SensorEntity, SensorEntityDescription, ) from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.const import CONF_NAME from homeassistant.core import HomeAssistant, callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, DataUpdateCoordinator, ) from .const import ( ATTR_AGENCY, ATTR_AGENCY_COUNTRY_CODE, ATTR_LAUNCH_TIME, ATTR_STREAM, ATTRIBUTION, DEFAULT_NAME, DOMAIN, ) _LOGGER = logging.getLogger(__name__) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( {vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string} ) SENSOR_DESCRIPTION = SensorEntityDescription( key="next_launch", icon="mdi:rocket-launch", name=DEFAULT_NAME, ) async def async_setup_platform( hass: HomeAssistant, config: ConfigType, async_add_entities: AddEntitiesCallback, discovery_info: DiscoveryInfoType | None = None, ) -> None: """Import Launch Library configuration from yaml.""" _LOGGER.warning( "Configuration of the launch_library platform in YAML is deprecated and will be " "removed in Home Assistant 2022.4; Your existing configuration " "has been imported into the UI automatically and can be safely removed " "from your configuration.yaml file" ) hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_IMPORT}, data=config, ) ) async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up the sensor platform.""" name = entry.data.get(CONF_NAME, DEFAULT_NAME) coordinator = hass.data[DOMAIN] async_add_entities( [ NextLaunchSensor( coordinator, entry.entry_id, name, SENSOR_DESCRIPTION, ), ] ) class NextLaunchSensor(CoordinatorEntity, SensorEntity): """Representation of the next launch sensor.""" _attr_attribution = ATTRIBUTION _next_launch: Launch | None = None def __init__( self, coordinator: DataUpdateCoordinator, entry_id: str, name: str, description: SensorEntityDescription, ) -> None: """Initialize a Launch Library entity.""" super().__init__(coordinator) self._attr_name = name self._attr_unique_id = f"{entry_id}_{description.key}" self.entity_description = description @property def available(self) -> bool: """Return if the sensor is available.""" return super().available and self._next_launch is not None @property def native_value(self) -> str | None: """Return the state of the sensor.""" if self._next_launch is None: return None return self._next_launch.name @property def extra_state_attributes(self) -> dict[str, Any] | None: """Return the attributes of the sensor.""" if self._next_launch is None: return None return { ATTR_LAUNCH_TIME: self._next_launch.net, ATTR_AGENCY: self._next_launch.launch_service_provider.name, ATTR_AGENCY_COUNTRY_CODE: self._next_launch.pad.location.country_code, ATTR_STREAM: self._next_launch.webcast_live, } @callback def _handle_coordinator_update(self) -> None: """Handle updated data from the coordinator.""" self._next_launch = next((launch for launch in self.coordinator.data), None) super()._handle_coordinator_update() async def async_added_to_hass(self) -> None: """When entity is added to hass.""" await super().async_added_to_hass() self._handle_coordinator_update()