diff --git a/custom_components/daikinone/__init__.py b/custom_components/daikinone/__init__.py index 5ec72fc..77deaca 100644 --- a/custom_components/daikinone/__init__.py +++ b/custom_components/daikinone/__init__.py @@ -6,7 +6,12 @@ from homeassistant.core import HomeAssistant from homeassistant.util import Throttle -from custom_components.daikinone.const import PLATFORMS, DOMAIN, MIN_TIME_BETWEEN_UPDATES +from custom_components.daikinone.const import ( + CONF_OPTION_ENTITY_UID_SCHEMA_VERSION_KEY, + PLATFORMS, + DOMAIN, + MIN_TIME_BETWEEN_UPDATES, +) from custom_components.daikinone.daikinone import DaikinOne, DaikinUserCredentials log = logging.getLogger(__name__) @@ -56,3 +61,32 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: if ok: hass.data.pop(DOMAIN) return ok + + +async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Migrate old entry.""" + log.debug("Migrating from version %s.%s", entry.version, entry.minor_version) + + if entry.version > 1: + log.error( + "Incompatible downgrade detected, please restore from a earlier backup or remove and re-add the integration", + entry.version, + entry.minor_version, + ) + return False + + if entry.version == 1: + new = {**entry.data} + + # migrate to 1.2 + if entry.minor_version < 2: + entry.minor_version = 2 + + # retain legacy id schema if this is an upgrade of an existing entry + new[CONF_OPTION_ENTITY_UID_SCHEMA_VERSION_KEY] = 0 + + hass.config_entries.async_update_entry(entry, data=new) + + log.info("Migration to version %s.%s successful", entry.version, entry.minor_version) + + return True diff --git a/custom_components/daikinone/config_flow.py b/custom_components/daikinone/config_flow.py index a912841..9b5d315 100644 --- a/custom_components/daikinone/config_flow.py +++ b/custom_components/daikinone/config_flow.py @@ -5,16 +5,17 @@ from homeassistant import config_entries from homeassistant.const import CONF_EMAIL, CONF_PASSWORD -from .const import DOMAIN +from .const import DOMAIN, CONF_OPTION_ENTITY_UID_SCHEMA_VERSION_KEY from .daikinone import DaikinOne, DaikinUserCredentials log = logging.getLogger(__name__) -class DaikinSkyportConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): +class DaikinOneConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Daikin One config flow.""" VERSION = 1 + MINOR_VERSION = 2 @property def schema(self): @@ -40,6 +41,8 @@ async def async_step_user(self, user_input: dict[str, Any] | None = None): data={ CONF_EMAIL: email, CONF_PASSWORD: password, + # internal options + CONF_OPTION_ENTITY_UID_SCHEMA_VERSION_KEY: 1, }, ) diff --git a/custom_components/daikinone/const.py b/custom_components/daikinone/const.py index 8c1317d..4ac6c80 100644 --- a/custom_components/daikinone/const.py +++ b/custom_components/daikinone/const.py @@ -13,3 +13,5 @@ ] MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30) + +CONF_OPTION_ENTITY_UID_SCHEMA_VERSION_KEY = "entity_uid_schema_version" diff --git a/custom_components/daikinone/daikinone.py b/custom_components/daikinone/daikinone.py index 523c246..ca0949b 100644 --- a/custom_components/daikinone/daikinone.py +++ b/custom_components/daikinone/daikinone.py @@ -256,8 +256,6 @@ def __map_thermostat(self, payload: DaikinDeviceDataResponse) -> DaikinThermosta if payload.data["ctSystemCapEmergencyHeat"]: capabilities.add(DaikinThermostatCapability.EMERGENCY_HEAT) - schedule = DaikinThermostatSchedule(enabled=payload.data["schedEnabled"]) - thermostat = DaikinThermostat( id=payload.id, location_id=payload.locationId, @@ -268,7 +266,7 @@ def __map_thermostat(self, payload: DaikinDeviceDataResponse) -> DaikinThermosta capabilities=capabilities, mode=DaikinThermostatMode(payload.data["mode"]), status=DaikinThermostatStatus(payload.data["equipmentStatus"]), - schedule=schedule, + schedule=DaikinThermostatSchedule(enabled=payload.data["schedEnabled"]), indoor_temperature=Temperature.from_celsius(payload.data["tempIndoor"]), indoor_humidity=payload.data["humIndoor"], set_point_heat=Temperature.from_celsius(payload.data["hspActive"]), diff --git a/custom_components/daikinone/sensor.py b/custom_components/daikinone/sensor.py index 56818ad..9687699 100644 --- a/custom_components/daikinone/sensor.py +++ b/custom_components/daikinone/sensor.py @@ -18,7 +18,7 @@ from homeassistant.helpers.typing import StateType from custom_components.daikinone import DOMAIN, DaikinOneData -from custom_components.daikinone.const import MANUFACTURER +from custom_components.daikinone.const import CONF_OPTION_ENTITY_UID_SCHEMA_VERSION_KEY, MANUFACTURER from custom_components.daikinone.daikinone import ( DaikinDevice, DaikinEEVCoil, @@ -706,7 +706,6 @@ def __init__( self._device: D = device self._attribute = attribute - self._attr_unique_id = f"{self._device.id}-{self.name}" self._attr_device_info = self.get_device_info() def get_device_info(self) -> DeviceInfo | None: @@ -746,6 +745,14 @@ def __init__( ) -> None: super().__init__(description, data, device, attribute) + match data.entry.data[CONF_OPTION_ENTITY_UID_SCHEMA_VERSION_KEY]: + case 0: + self._attr_unique_id = f"{self._device.id}-{self.name}" + case 1: + self._attr_unique_id = f"{self._device.id}-{self.entity_description.key}" + case _: + raise ValueError("unexpected entity uid schema version") + @property def device_name(self) -> str: return f"{self._device.name} Thermostat" @@ -763,6 +770,14 @@ def __init__( ) -> None: super().__init__(description, data, device, attribute) + match data.entry.data[CONF_OPTION_ENTITY_UID_SCHEMA_VERSION_KEY]: + case 0: + self._attr_unique_id = f"{self._device.id}-{self.name}" + case 1: + self._attr_unique_id = f"{self._device.thermostat_id}-{self._device.id}-{self.entity_description.key}" + case _: + raise ValueError("unexpected entity uid schema version") + @property def device_name(self) -> str: thermostat = self._data.daikin.get_thermostat(self._device.thermostat_id)