1 """Support for Subaru sensors."""
3 from __future__
import annotations
8 import subarulink.const
as sc
13 SensorEntityDescription,
23 DataUpdateCoordinator,
28 from .
import get_device_info
41 _LOGGER = logging.getLogger(__name__)
45 FUEL_CONSUMPTION_LITERS_PER_HUNDRED_KILOMETERS =
"L/100km"
46 FUEL_CONSUMPTION_MILES_PER_GALLON =
"mi/gal"
48 L_PER_GAL = VolumeConverter.convert(1, UnitOfVolume.GALLONS, UnitOfVolume.LITERS)
49 KM_PER_MI = DistanceConverter.convert(1, UnitOfLength.MILES, UnitOfLength.KILOMETERS)
55 translation_key=
"odometer",
56 device_class=SensorDeviceClass.DISTANCE,
57 native_unit_of_measurement=UnitOfLength.MILES,
58 state_class=SensorStateClass.TOTAL_INCREASING,
65 key=sc.AVG_FUEL_CONSUMPTION,
66 translation_key=
"average_fuel_consumption",
67 native_unit_of_measurement=FUEL_CONSUMPTION_MILES_PER_GALLON,
68 state_class=SensorStateClass.MEASUREMENT,
72 translation_key=
"range",
73 device_class=SensorDeviceClass.DISTANCE,
74 native_unit_of_measurement=UnitOfLength.MILES,
75 state_class=SensorStateClass.MEASUREMENT,
78 key=sc.TIRE_PRESSURE_FL,
79 translation_key=
"tire_pressure_front_left",
80 device_class=SensorDeviceClass.PRESSURE,
81 native_unit_of_measurement=UnitOfPressure.PSI,
82 state_class=SensorStateClass.MEASUREMENT,
85 key=sc.TIRE_PRESSURE_FR,
86 translation_key=
"tire_pressure_front_right",
87 device_class=SensorDeviceClass.PRESSURE,
88 native_unit_of_measurement=UnitOfPressure.PSI,
89 state_class=SensorStateClass.MEASUREMENT,
92 key=sc.TIRE_PRESSURE_RL,
93 translation_key=
"tire_pressure_rear_left",
94 device_class=SensorDeviceClass.PRESSURE,
95 native_unit_of_measurement=UnitOfPressure.PSI,
96 state_class=SensorStateClass.MEASUREMENT,
99 key=sc.TIRE_PRESSURE_RR,
100 translation_key=
"tire_pressure_rear_right",
101 device_class=SensorDeviceClass.PRESSURE,
102 native_unit_of_measurement=UnitOfPressure.PSI,
103 state_class=SensorStateClass.MEASUREMENT,
108 API_GEN_3_SENSORS = [
110 key=sc.REMAINING_FUEL_PERCENT,
111 translation_key=
"fuel_level",
112 native_unit_of_measurement=PERCENTAGE,
113 state_class=SensorStateClass.MEASUREMENT,
120 key=sc.EV_DISTANCE_TO_EMPTY,
121 translation_key=
"ev_range",
122 device_class=SensorDeviceClass.DISTANCE,
123 native_unit_of_measurement=UnitOfLength.MILES,
124 state_class=SensorStateClass.MEASUREMENT,
127 key=sc.EV_STATE_OF_CHARGE_PERCENT,
128 translation_key=
"ev_battery_level",
129 device_class=SensorDeviceClass.BATTERY,
130 native_unit_of_measurement=PERCENTAGE,
131 state_class=SensorStateClass.MEASUREMENT,
134 key=sc.EV_TIME_TO_FULLY_CHARGED_UTC,
135 translation_key=
"ev_time_to_full_charge",
136 device_class=SensorDeviceClass.TIMESTAMP,
143 config_entry: ConfigEntry,
144 async_add_entities: AddEntitiesCallback,
146 """Set up the Subaru sensors by config_entry."""
147 entry = hass.data[DOMAIN][config_entry.entry_id]
148 coordinator = entry[ENTRY_COORDINATOR]
149 vehicle_info = entry[ENTRY_VEHICLES]
152 for info
in vehicle_info.values():
158 vehicle_info, coordinator: DataUpdateCoordinator
159 ) -> list[SubaruSensor]:
160 """Instantiate all available sensors for the vehicle."""
161 sensor_descriptions_to_add = []
162 sensor_descriptions_to_add.extend(SAFETY_SENSORS)
164 if vehicle_info[VEHICLE_API_GEN]
in [API_GEN_2, API_GEN_3]:
165 sensor_descriptions_to_add.extend(API_GEN_2_SENSORS)
167 if vehicle_info[VEHICLE_API_GEN] == API_GEN_3:
168 sensor_descriptions_to_add.extend(API_GEN_3_SENSORS)
170 if vehicle_info[VEHICLE_HAS_EV]:
171 sensor_descriptions_to_add.extend(EV_SENSORS)
179 for description
in sensor_descriptions_to_add
184 CoordinatorEntity[DataUpdateCoordinator[dict[str, Any]]], SensorEntity
186 """Class for Subaru sensors."""
188 _attr_has_entity_name =
True
193 coordinator: DataUpdateCoordinator,
194 description: SensorEntityDescription,
196 """Initialize the sensor."""
198 self.
vinvin = vehicle_info[VEHICLE_VIN]
205 """Return the state of the sensor."""
206 current_value = self.coordinator.data[self.
vinvin][VEHICLE_STATUS].
get(
212 and self.
hasshasshass.config.units == METRIC_SYSTEM
214 return round((100.0 * L_PER_GAL) / (KM_PER_MI * current_value), 1)
220 """Return the unit_of_measurement of the device."""
223 and self.
hasshasshass.config.units == METRIC_SYSTEM
225 return FUEL_CONSUMPTION_LITERS_PER_HUNDRED_KILOMETERS
230 """Return if entity is available."""
231 last_update_success = super().available
232 if last_update_success
and self.
vinvin
not in self.coordinator.data:
234 return last_update_success
238 hass: HomeAssistant, config_entry: ConfigEntry
240 """Migrate sensor entries from HA<=2022.10 to use preferred unique_id."""
241 entity_registry = er.async_get(hass)
244 "ODOMETER": sc.ODOMETER,
245 "AVG FUEL CONSUMPTION": sc.AVG_FUEL_CONSUMPTION,
246 "RANGE": sc.DIST_TO_EMPTY,
247 "TIRE PRESSURE FL": sc.TIRE_PRESSURE_FL,
248 "TIRE PRESSURE FR": sc.TIRE_PRESSURE_FR,
249 "TIRE PRESSURE RL": sc.TIRE_PRESSURE_RL,
250 "TIRE PRESSURE RR": sc.TIRE_PRESSURE_RR,
251 "FUEL LEVEL": sc.REMAINING_FUEL_PERCENT,
252 "EV RANGE": sc.EV_DISTANCE_TO_EMPTY,
253 "EV BATTERY LEVEL": sc.EV_STATE_OF_CHARGE_PERCENT,
254 "EV TIME TO FULL CHARGE": sc.EV_TIME_TO_FULLY_CHARGED_UTC,
259 id_split = entry.unique_id.split(
"_")
260 key = id_split[1].upper()
if len(id_split) == 2
else None
262 if key
not in replacements
or id_split[1] == replacements[key]:
265 new_unique_id = entry.unique_id.replace(id_split[1], replacements[key])
267 "Migrating entity '%s' unique_id from '%s' to '%s'",
272 if existing_entity_id := entity_registry.async_get_entity_id(
273 entry.domain, entry.platform, new_unique_id
276 "Cannot migrate to unique_id '%s', already exists for '%s'",
282 "new_unique_id": new_unique_id,
285 await er.async_migrate_entries(hass, config_entry.entry_id, update_unique_id)
None __init__(self, dict vehicle_info, DataUpdateCoordinator coordinator, SensorEntityDescription description)
str|None native_unit_of_measurement(self)
int|float|None native_value(self)
web.Response get(self, web.Request request, str config_key)
dict[str, str]|None update_unique_id(er.RegistryEntry entity_entry, str unique_id)
list[SubaruSensor] create_vehicle_sensors(vehicle_info, DataUpdateCoordinator coordinator)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
None _async_migrate_entries(HomeAssistant hass, ConfigEntry config_entry)
def get_device_info(vehicle_info)