Use runtime_data in Subaru integration (#167747)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
epenet
2026-04-09 13:36:45 +02:00
committed by GitHub
parent f634525798
commit aa50822a82
9 changed files with 52 additions and 70 deletions

View File

@@ -4,7 +4,6 @@ import logging
from subarulink import Controller as SubaruAPI, InvalidCredentials, SubaruException
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_COUNTRY,
CONF_DEVICE_ID,
@@ -19,9 +18,6 @@ from homeassistant.helpers.device_registry import DeviceInfo
from .const import (
DOMAIN,
ENTRY_CONTROLLER,
ENTRY_COORDINATOR,
ENTRY_VEHICLES,
FETCH_INTERVAL,
MANUFACTURER,
PLATFORMS,
@@ -37,12 +33,16 @@ from .const import (
VEHICLE_NAME,
VEHICLE_VIN,
)
from .coordinator import SubaruDataUpdateCoordinator
from .coordinator import (
SubaruConfigEntry,
SubaruDataUpdateCoordinator,
SubaruRuntimeData,
)
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: SubaruConfigEntry) -> bool:
"""Set up Subaru from a config entry."""
config = entry.data
websession = aiohttp_client.async_create_clientsession(hass)
@@ -77,24 +77,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await coordinator.async_refresh()
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = {
ENTRY_CONTROLLER: controller,
ENTRY_COORDINATOR: coordinator,
ENTRY_VEHICLES: vehicle_info,
}
entry.runtime_data = SubaruRuntimeData(
controller=controller,
coordinator=coordinator,
vehicles=vehicle_info,
)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: SubaruConfigEntry) -> bool:
"""Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok:
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
def get_vehicle_info(controller, vin):

View File

@@ -15,12 +15,7 @@ from subarulink import (
from subarulink.const import COUNTRY_CAN, COUNTRY_USA
import voluptuous as vol
from homeassistant.config_entries import (
ConfigEntry,
ConfigFlow,
ConfigFlowResult,
OptionsFlow,
)
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult, OptionsFlow
from homeassistant.const import (
CONF_COUNTRY,
CONF_DEVICE_ID,
@@ -32,6 +27,7 @@ from homeassistant.core import callback
from homeassistant.helpers import aiohttp_client, config_validation as cv
from .const import CONF_UPDATE_ENABLED, DOMAIN
from .coordinator import SubaruConfigEntry
_LOGGER = logging.getLogger(__name__)
CONF_CONTACT_METHOD = "contact_method"
@@ -103,7 +99,7 @@ class SubaruConfigFlow(ConfigFlow, domain=DOMAIN):
@staticmethod
@callback
def async_get_options_flow(
config_entry: ConfigEntry,
config_entry: SubaruConfigEntry,
) -> OptionsFlowHandler:
"""Get the options flow for this handler."""
return OptionsFlowHandler()

View File

@@ -9,11 +9,6 @@ FETCH_INTERVAL = 300
UPDATE_INTERVAL = 7200
CONF_UPDATE_ENABLED = "update_enabled"
# entry fields
ENTRY_CONTROLLER = "controller"
ENTRY_COORDINATOR = "coordinator"
ENTRY_VEHICLES = "vehicles"
# update coordinator name
COORDINATOR_NAME = "subaru_data"

View File

@@ -2,6 +2,7 @@
from __future__ import annotations
from dataclasses import dataclass
from datetime import timedelta
import logging
import time
@@ -23,16 +24,27 @@ from .const import (
_LOGGER = logging.getLogger(__name__)
type SubaruConfigEntry = ConfigEntry[SubaruRuntimeData]
@dataclass
class SubaruRuntimeData:
"""Runtime data for Subaru."""
controller: SubaruAPI
coordinator: SubaruDataUpdateCoordinator
vehicles: dict[str, dict[str, Any]]
class SubaruDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
"""Class to manage fetching Subaru data."""
config_entry: ConfigEntry
config_entry: SubaruConfigEntry
def __init__(
self,
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: SubaruConfigEntry,
*,
controller: SubaruAPI,
vehicle_info: dict[str, dict[str, Any]],

View File

@@ -7,32 +7,23 @@ from typing import Any
from subarulink.const import LATITUDE, LONGITUDE, TIMESTAMP
from homeassistant.components.device_tracker import TrackerEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import get_device_info
from .const import (
DOMAIN,
ENTRY_COORDINATOR,
ENTRY_VEHICLES,
VEHICLE_HAS_REMOTE_SERVICE,
VEHICLE_STATUS,
VEHICLE_VIN,
)
from .coordinator import SubaruDataUpdateCoordinator
from .const import VEHICLE_HAS_REMOTE_SERVICE, VEHICLE_STATUS, VEHICLE_VIN
from .coordinator import SubaruConfigEntry, SubaruDataUpdateCoordinator
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: SubaruConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the Subaru device tracker by config_entry."""
entry: dict = hass.data[DOMAIN][config_entry.entry_id]
coordinator: SubaruDataUpdateCoordinator = entry[ENTRY_COORDINATOR]
vehicle_info: dict = entry[ENTRY_VEHICLES]
coordinator = config_entry.runtime_data.coordinator
vehicle_info = config_entry.runtime_data.vehicles
async_add_entities(
SubaruDeviceTracker(vehicle, coordinator)
for vehicle in vehicle_info.values()

View File

@@ -13,23 +13,23 @@ from subarulink.const import (
)
from homeassistant.components.diagnostics import async_redact_data
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE_ID, CONF_PASSWORD, CONF_PIN, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.device_registry import DeviceEntry
from .const import DOMAIN, ENTRY_CONTROLLER, ENTRY_COORDINATOR, VEHICLE_VIN
from .const import VEHICLE_VIN
from .coordinator import SubaruConfigEntry
CONFIG_FIELDS_TO_REDACT = [CONF_USERNAME, CONF_PASSWORD, CONF_PIN, CONF_DEVICE_ID]
DATA_FIELDS_TO_REDACT = [VEHICLE_VIN, VEHICLE_NAME, LATITUDE, LONGITUDE, ODOMETER]
async def async_get_config_entry_diagnostics(
hass: HomeAssistant, config_entry: ConfigEntry
hass: HomeAssistant, config_entry: SubaruConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
coordinator = hass.data[DOMAIN][config_entry.entry_id][ENTRY_COORDINATOR]
coordinator = config_entry.runtime_data.coordinator
return {
"config_entry": async_redact_data(config_entry.data, CONFIG_FIELDS_TO_REDACT),
@@ -42,12 +42,11 @@ async def async_get_config_entry_diagnostics(
async def async_get_device_diagnostics(
hass: HomeAssistant, config_entry: ConfigEntry, device: DeviceEntry
hass: HomeAssistant, config_entry: SubaruConfigEntry, device: DeviceEntry
) -> dict[str, Any]:
"""Return diagnostics for a device."""
entry = hass.data[DOMAIN][config_entry.entry_id]
coordinator = entry[ENTRY_COORDINATOR]
controller = entry[ENTRY_CONTROLLER]
coordinator = config_entry.runtime_data.coordinator
controller = config_entry.runtime_data.controller
vin = next(iter(device.identifiers))[1]

View File

@@ -6,17 +6,14 @@ from typing import Any
import voluptuous as vol
from homeassistant.components.lock import LockEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import SERVICE_LOCK, SERVICE_UNLOCK
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_platform
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import DOMAIN, get_device_info
from . import get_device_info
from .const import (
ATTR_DOOR,
ENTRY_CONTROLLER,
ENTRY_VEHICLES,
SERVICE_UNLOCK_SPECIFIC_DOOR,
UNLOCK_DOOR_ALL,
UNLOCK_VALID_DOORS,
@@ -24,6 +21,7 @@ from .const import (
VEHICLE_NAME,
VEHICLE_VIN,
)
from .coordinator import SubaruConfigEntry
from .remote_service import async_call_remote_service
_LOGGER = logging.getLogger(__name__)
@@ -31,13 +29,12 @@ _LOGGER = logging.getLogger(__name__)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: SubaruConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the Subaru locks by config_entry."""
entry = hass.data[DOMAIN][config_entry.entry_id]
controller = entry[ENTRY_CONTROLLER]
vehicle_info = entry[ENTRY_VEHICLES]
controller = config_entry.runtime_data.controller
vehicle_info = config_entry.runtime_data.vehicles
async_add_entities(
SubaruLock(vehicle, controller)
for vehicle in vehicle_info.values()

View File

@@ -26,15 +26,12 @@ from . import get_device_info
from .const import (
API_GEN_2,
API_GEN_3,
DOMAIN,
ENTRY_COORDINATOR,
ENTRY_VEHICLES,
VEHICLE_API_GEN,
VEHICLE_HAS_EV,
VEHICLE_STATUS,
VEHICLE_VIN,
)
from .coordinator import SubaruDataUpdateCoordinator
from .coordinator import SubaruConfigEntry, SubaruDataUpdateCoordinator
_LOGGER = logging.getLogger(__name__)
@@ -138,13 +135,12 @@ EV_SENSORS = [
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
config_entry: SubaruConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the Subaru sensors by config_entry."""
entry = hass.data[DOMAIN][config_entry.entry_id]
coordinator = entry[ENTRY_COORDINATOR]
vehicle_info = entry[ENTRY_VEHICLES]
coordinator = config_entry.runtime_data.coordinator
vehicle_info = config_entry.runtime_data.vehicles
entities = []
await _async_migrate_entries(hass, config_entry)
for info in vehicle_info.values():

View File

@@ -6,9 +6,9 @@ from unittest.mock import patch
import pytest
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.components.subaru.const import DOMAIN
from homeassistant.components.subaru.sensor import (
API_GEN_2_SENSORS,
DOMAIN,
EV_SENSORS,
SAFETY_SENSORS,
)