diff --git a/homeassistant/components/bmw_connected_drive/__init__.py b/homeassistant/components/bmw_connected_drive/__init__.py index 060c8b68ae7..495359ca314 100644 --- a/homeassistant/components/bmw_connected_drive/__init__.py +++ b/homeassistant/components/bmw_connected_drive/__init__.py @@ -87,8 +87,20 @@ async def _async_migrate_entries( @callback def update_unique_id(entry: er.RegistryEntry) -> dict[str, str] | None: replacements = { - "charging_level_hv": "remaining_battery_percent", - "fuel_percent": "remaining_fuel_percent", + "charging_level_hv": "fuel_and_battery.remaining_battery_percent", + "fuel_percent": "fuel_and_battery.remaining_fuel_percent", + "ac_current_limit": "charging_profile.ac_current_limit", + "charging_start_time": "fuel_and_battery.charging_start_time", + "charging_end_time": "fuel_and_battery.charging_end_time", + "charging_status": "fuel_and_battery.charging_status", + "charging_target": "fuel_and_battery.charging_target", + "remaining_battery_percent": "fuel_and_battery.remaining_battery_percent", + "remaining_range_total": "fuel_and_battery.remaining_range_total", + "remaining_range_electric": "fuel_and_battery.remaining_range_electric", + "remaining_range_fuel": "fuel_and_battery.remaining_range_fuel", + "remaining_fuel": "fuel_and_battery.remaining_fuel", + "remaining_fuel_percent": "fuel_and_battery.remaining_fuel_percent", + "activity": "climate.activity", } if (key := entry.unique_id.split("-")[-1]) in replacements: new_unique_id = entry.unique_id.replace(key, replacements[key]) diff --git a/homeassistant/components/bmw_connected_drive/sensor.py b/homeassistant/components/bmw_connected_drive/sensor.py index dae1eaa0b13..976c32bd332 100644 --- a/homeassistant/components/bmw_connected_drive/sensor.py +++ b/homeassistant/components/bmw_connected_drive/sensor.py @@ -46,9 +46,8 @@ class BMWSensorEntityDescription(SensorEntityDescription): SENSOR_TYPES: list[BMWSensorEntityDescription] = [ BMWSensorEntityDescription( - key="ac_current_limit", + key="charging_profile.ac_current_limit", translation_key="ac_current_limit", - key_class="charging_profile", device_class=SensorDeviceClass.CURRENT, native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, entity_registry_enabled_default=False, @@ -56,41 +55,36 @@ SENSOR_TYPES: list[BMWSensorEntityDescription] = [ is_available=lambda v: v.is_lsc_enabled and v.has_electric_drivetrain, ), BMWSensorEntityDescription( - key="charging_start_time", + key="fuel_and_battery.charging_start_time", translation_key="charging_start_time", - key_class="fuel_and_battery", device_class=SensorDeviceClass.TIMESTAMP, entity_registry_enabled_default=False, is_available=lambda v: v.is_lsc_enabled and v.has_electric_drivetrain, ), BMWSensorEntityDescription( - key="charging_end_time", + key="fuel_and_battery.charging_end_time", translation_key="charging_end_time", - key_class="fuel_and_battery", device_class=SensorDeviceClass.TIMESTAMP, is_available=lambda v: v.is_lsc_enabled and v.has_electric_drivetrain, ), BMWSensorEntityDescription( - key="charging_status", + key="fuel_and_battery.charging_status", translation_key="charging_status", - key_class="fuel_and_battery", device_class=SensorDeviceClass.ENUM, options=[s.value.lower() for s in ChargingState if s != ChargingState.UNKNOWN], is_available=lambda v: v.is_lsc_enabled and v.has_electric_drivetrain, ), BMWSensorEntityDescription( - key="charging_target", + key="fuel_and_battery.charging_target", translation_key="charging_target", - key_class="fuel_and_battery", device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=PERCENTAGE, suggested_display_precision=0, is_available=lambda v: v.is_lsc_enabled and v.has_electric_drivetrain, ), BMWSensorEntityDescription( - key="remaining_battery_percent", + key="fuel_and_battery.remaining_battery_percent", translation_key="remaining_battery_percent", - key_class="fuel_and_battery", device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, @@ -106,18 +100,16 @@ SENSOR_TYPES: list[BMWSensorEntityDescription] = [ suggested_display_precision=0, ), BMWSensorEntityDescription( - key="remaining_range_total", + key="fuel_and_battery.remaining_range_total", translation_key="remaining_range_total", - key_class="fuel_and_battery", device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=UnitOfLength.KILOMETERS, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=0, ), BMWSensorEntityDescription( - key="remaining_range_electric", + key="fuel_and_battery.remaining_range_electric", translation_key="remaining_range_electric", - key_class="fuel_and_battery", device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=UnitOfLength.KILOMETERS, state_class=SensorStateClass.MEASUREMENT, @@ -125,9 +117,8 @@ SENSOR_TYPES: list[BMWSensorEntityDescription] = [ is_available=lambda v: v.is_lsc_enabled and v.has_electric_drivetrain, ), BMWSensorEntityDescription( - key="remaining_range_fuel", + key="fuel_and_battery.remaining_range_fuel", translation_key="remaining_range_fuel", - key_class="fuel_and_battery", device_class=SensorDeviceClass.DISTANCE, native_unit_of_measurement=UnitOfLength.KILOMETERS, state_class=SensorStateClass.MEASUREMENT, @@ -135,9 +126,8 @@ SENSOR_TYPES: list[BMWSensorEntityDescription] = [ is_available=lambda v: v.is_lsc_enabled and v.has_combustion_drivetrain, ), BMWSensorEntityDescription( - key="remaining_fuel", + key="fuel_and_battery.remaining_fuel", translation_key="remaining_fuel", - key_class="fuel_and_battery", device_class=SensorDeviceClass.VOLUME, native_unit_of_measurement=UnitOfVolume.LITERS, state_class=SensorStateClass.MEASUREMENT, @@ -145,18 +135,16 @@ SENSOR_TYPES: list[BMWSensorEntityDescription] = [ is_available=lambda v: v.is_lsc_enabled and v.has_combustion_drivetrain, ), BMWSensorEntityDescription( - key="remaining_fuel_percent", + key="fuel_and_battery.remaining_fuel_percent", translation_key="remaining_fuel_percent", - key_class="fuel_and_battery", native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=0, is_available=lambda v: v.is_lsc_enabled and v.has_combustion_drivetrain, ), BMWSensorEntityDescription( - key="activity", + key="climate.activity", translation_key="climate_status", - key_class="climate", device_class=SensorDeviceClass.ENUM, options=[ s.value.lower() @@ -208,13 +196,12 @@ class BMWSensor(BMWBaseEntity, SensorEntity): _LOGGER.debug( "Updating sensor '%s' of %s", self.entity_description.key, self.vehicle.name ) - if self.entity_description.key_class is None: - state = getattr(self.vehicle, self.entity_description.key) - else: - state = getattr( - getattr(self.vehicle, self.entity_description.key_class), - self.entity_description.key, - ) + + key_path = self.entity_description.key.split(".") + state = getattr(self.vehicle, key_path.pop(0)) + + for key in key_path: + state = getattr(state, key) # For datetime without tzinfo, we assume it to be the same timezone as the HA instance if isinstance(state, datetime.datetime) and state.tzinfo is None: diff --git a/tests/components/bmw_connected_drive/snapshots/test_sensor.ambr b/tests/components/bmw_connected_drive/snapshots/test_sensor.ambr index eea2db57675..e33aaef47fd 100644 --- a/tests/components/bmw_connected_drive/snapshots/test_sensor.ambr +++ b/tests/components/bmw_connected_drive/snapshots/test_sensor.ambr @@ -31,7 +31,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'ac_current_limit', - 'unique_id': 'WBY00000000REXI01-ac_current_limit', + 'unique_id': 'WBY00000000REXI01-charging_profile.ac_current_limit', 'unit_of_measurement': , }) # --- @@ -79,7 +79,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_end_time', - 'unique_id': 'WBY00000000REXI01-charging_end_time', + 'unique_id': 'WBY00000000REXI01-fuel_and_battery.charging_end_time', 'unit_of_measurement': None, }) # --- @@ -126,7 +126,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_start_time', - 'unique_id': 'WBY00000000REXI01-charging_start_time', + 'unique_id': 'WBY00000000REXI01-fuel_and_battery.charging_start_time', 'unit_of_measurement': None, }) # --- @@ -188,7 +188,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_status', - 'unique_id': 'WBY00000000REXI01-charging_status', + 'unique_id': 'WBY00000000REXI01-fuel_and_battery.charging_status', 'unit_of_measurement': None, }) # --- @@ -252,7 +252,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_target', - 'unique_id': 'WBY00000000REXI01-charging_target', + 'unique_id': 'WBY00000000REXI01-fuel_and_battery.charging_target', 'unit_of_measurement': '%', }) # --- @@ -359,7 +359,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_battery_percent', - 'unique_id': 'WBY00000000REXI01-remaining_battery_percent', + 'unique_id': 'WBY00000000REXI01-fuel_and_battery.remaining_battery_percent', 'unit_of_measurement': '%', }) # --- @@ -413,7 +413,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_fuel', - 'unique_id': 'WBY00000000REXI01-remaining_fuel', + 'unique_id': 'WBY00000000REXI01-fuel_and_battery.remaining_fuel', 'unit_of_measurement': , }) # --- @@ -467,7 +467,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_fuel_percent', - 'unique_id': 'WBY00000000REXI01-remaining_fuel_percent', + 'unique_id': 'WBY00000000REXI01-fuel_and_battery.remaining_fuel_percent', 'unit_of_measurement': '%', }) # --- @@ -520,7 +520,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_range_electric', - 'unique_id': 'WBY00000000REXI01-remaining_range_electric', + 'unique_id': 'WBY00000000REXI01-fuel_and_battery.remaining_range_electric', 'unit_of_measurement': , }) # --- @@ -574,7 +574,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_range_fuel', - 'unique_id': 'WBY00000000REXI01-remaining_range_fuel', + 'unique_id': 'WBY00000000REXI01-fuel_and_battery.remaining_range_fuel', 'unit_of_measurement': , }) # --- @@ -628,7 +628,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_range_total', - 'unique_id': 'WBY00000000REXI01-remaining_range_total', + 'unique_id': 'WBY00000000REXI01-fuel_and_battery.remaining_range_total', 'unit_of_measurement': , }) # --- @@ -680,7 +680,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'ac_current_limit', - 'unique_id': 'WBA00000000DEMO02-ac_current_limit', + 'unique_id': 'WBA00000000DEMO02-charging_profile.ac_current_limit', 'unit_of_measurement': , }) # --- @@ -728,7 +728,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_end_time', - 'unique_id': 'WBA00000000DEMO02-charging_end_time', + 'unique_id': 'WBA00000000DEMO02-fuel_and_battery.charging_end_time', 'unit_of_measurement': None, }) # --- @@ -775,7 +775,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_start_time', - 'unique_id': 'WBA00000000DEMO02-charging_start_time', + 'unique_id': 'WBA00000000DEMO02-fuel_and_battery.charging_start_time', 'unit_of_measurement': None, }) # --- @@ -837,7 +837,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_status', - 'unique_id': 'WBA00000000DEMO02-charging_status', + 'unique_id': 'WBA00000000DEMO02-fuel_and_battery.charging_status', 'unit_of_measurement': None, }) # --- @@ -901,7 +901,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_target', - 'unique_id': 'WBA00000000DEMO02-charging_target', + 'unique_id': 'WBA00000000DEMO02-fuel_and_battery.charging_target', 'unit_of_measurement': '%', }) # --- @@ -956,7 +956,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'climate_status', - 'unique_id': 'WBA00000000DEMO02-activity', + 'unique_id': 'WBA00000000DEMO02-climate.activity', 'unit_of_measurement': None, }) # --- @@ -1068,7 +1068,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_battery_percent', - 'unique_id': 'WBA00000000DEMO02-remaining_battery_percent', + 'unique_id': 'WBA00000000DEMO02-fuel_and_battery.remaining_battery_percent', 'unit_of_measurement': '%', }) # --- @@ -1122,7 +1122,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_range_electric', - 'unique_id': 'WBA00000000DEMO02-remaining_range_electric', + 'unique_id': 'WBA00000000DEMO02-fuel_and_battery.remaining_range_electric', 'unit_of_measurement': , }) # --- @@ -1176,7 +1176,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_range_total', - 'unique_id': 'WBA00000000DEMO02-remaining_range_total', + 'unique_id': 'WBA00000000DEMO02-fuel_and_battery.remaining_range_total', 'unit_of_measurement': , }) # --- @@ -1228,7 +1228,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'ac_current_limit', - 'unique_id': 'WBA00000000DEMO01-ac_current_limit', + 'unique_id': 'WBA00000000DEMO01-charging_profile.ac_current_limit', 'unit_of_measurement': , }) # --- @@ -1276,7 +1276,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_end_time', - 'unique_id': 'WBA00000000DEMO01-charging_end_time', + 'unique_id': 'WBA00000000DEMO01-fuel_and_battery.charging_end_time', 'unit_of_measurement': None, }) # --- @@ -1323,7 +1323,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_start_time', - 'unique_id': 'WBA00000000DEMO01-charging_start_time', + 'unique_id': 'WBA00000000DEMO01-fuel_and_battery.charging_start_time', 'unit_of_measurement': None, }) # --- @@ -1385,7 +1385,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_status', - 'unique_id': 'WBA00000000DEMO01-charging_status', + 'unique_id': 'WBA00000000DEMO01-fuel_and_battery.charging_status', 'unit_of_measurement': None, }) # --- @@ -1449,7 +1449,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'charging_target', - 'unique_id': 'WBA00000000DEMO01-charging_target', + 'unique_id': 'WBA00000000DEMO01-fuel_and_battery.charging_target', 'unit_of_measurement': '%', }) # --- @@ -1504,7 +1504,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'climate_status', - 'unique_id': 'WBA00000000DEMO01-activity', + 'unique_id': 'WBA00000000DEMO01-climate.activity', 'unit_of_measurement': None, }) # --- @@ -1616,7 +1616,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_battery_percent', - 'unique_id': 'WBA00000000DEMO01-remaining_battery_percent', + 'unique_id': 'WBA00000000DEMO01-fuel_and_battery.remaining_battery_percent', 'unit_of_measurement': '%', }) # --- @@ -1670,7 +1670,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_range_electric', - 'unique_id': 'WBA00000000DEMO01-remaining_range_electric', + 'unique_id': 'WBA00000000DEMO01-fuel_and_battery.remaining_range_electric', 'unit_of_measurement': , }) # --- @@ -1724,7 +1724,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_range_total', - 'unique_id': 'WBA00000000DEMO01-remaining_range_total', + 'unique_id': 'WBA00000000DEMO01-fuel_and_battery.remaining_range_total', 'unit_of_measurement': , }) # --- @@ -1780,7 +1780,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'climate_status', - 'unique_id': 'WBA00000000DEMO03-activity', + 'unique_id': 'WBA00000000DEMO03-climate.activity', 'unit_of_measurement': None, }) # --- @@ -1892,7 +1892,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_fuel', - 'unique_id': 'WBA00000000DEMO03-remaining_fuel', + 'unique_id': 'WBA00000000DEMO03-fuel_and_battery.remaining_fuel', 'unit_of_measurement': , }) # --- @@ -1946,7 +1946,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_fuel_percent', - 'unique_id': 'WBA00000000DEMO03-remaining_fuel_percent', + 'unique_id': 'WBA00000000DEMO03-fuel_and_battery.remaining_fuel_percent', 'unit_of_measurement': '%', }) # --- @@ -1999,7 +1999,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_range_fuel', - 'unique_id': 'WBA00000000DEMO03-remaining_range_fuel', + 'unique_id': 'WBA00000000DEMO03-fuel_and_battery.remaining_range_fuel', 'unit_of_measurement': , }) # --- @@ -2053,7 +2053,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'remaining_range_total', - 'unique_id': 'WBA00000000DEMO03-remaining_range_total', + 'unique_id': 'WBA00000000DEMO03-fuel_and_battery.remaining_range_total', 'unit_of_measurement': , }) # --- diff --git a/tests/components/bmw_connected_drive/test_init.py b/tests/components/bmw_connected_drive/test_init.py index 5cd6362d6fa..e523b2b3d02 100644 --- a/tests/components/bmw_connected_drive/test_init.py +++ b/tests/components/bmw_connected_drive/test_init.py @@ -85,7 +85,7 @@ async def test_migrate_options_from_data(hass: HomeAssistant) -> None: "disabled_by": None, }, f"{VIN}-charging_level_hv", - f"{VIN}-remaining_battery_percent", + f"{VIN}-fuel_and_battery.remaining_battery_percent", ), ( { @@ -96,7 +96,18 @@ async def test_migrate_options_from_data(hass: HomeAssistant) -> None: "disabled_by": None, }, f"{VIN}-remaining_range_total", - f"{VIN}-remaining_range_total", + f"{VIN}-fuel_and_battery.remaining_range_total", + ), + ( + { + "domain": SENSOR_DOMAIN, + "platform": BMW_DOMAIN, + "unique_id": f"{VIN}-mileage", + "suggested_object_id": f"{VEHICLE_NAME} mileage", + "disabled_by": None, + }, + f"{VIN}-mileage", + f"{VIN}-mileage", ), ], ) @@ -143,7 +154,7 @@ async def test_migrate_unique_ids( "disabled_by": None, }, f"{VIN}-charging_level_hv", - f"{VIN}-remaining_battery_percent", + f"{VIN}-fuel_and_battery.remaining_battery_percent", ), ], ) @@ -163,8 +174,8 @@ async def test_dont_migrate_unique_ids( existing_entity = entity_registry.async_get_or_create( SENSOR_DOMAIN, BMW_DOMAIN, - unique_id=f"{VIN}-remaining_battery_percent", - suggested_object_id=f"{VEHICLE_NAME} remaining_battery_percent", + unique_id=f"{VIN}-fuel_and_battery.remaining_battery_percent", + suggested_object_id=f"{VEHICLE_NAME} fuel_and_battery.remaining_battery_percent", config_entry=mock_config_entry, )