Add diagnostics to bmw_connected_drive (#74871)

* Add diagnostics to bmw_connected_drive

* Add tests for diagnostics

* Move get_fingerprints to library, bump bimmer_connected to 0.10.4

* Update bimmer_connected to 0.11.0

* Fix pytest

* Mock actual diagnostics HTTP calls

* Update tests for bimmer_connected 0.12.0

* Don't raise errors if vehicle is not found

Co-authored-by: rikroe <rikroe@users.noreply.github.com>
This commit is contained in:
rikroe 2023-01-11 01:09:45 +01:00 committed by GitHub
parent db428f2141
commit 1afb30344a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1559 additions and 43 deletions

View File

@ -0,0 +1,98 @@
"""Diagnostics support for the BMW Connected Drive integration."""
from __future__ import annotations
from dataclasses import asdict
import json
from typing import TYPE_CHECKING, Any
from bimmer_connected.utils import MyBMWJSONEncoder
from homeassistant.components.diagnostics.util import async_redact_data
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntry
from .const import CONF_REFRESH_TOKEN, DOMAIN
if TYPE_CHECKING:
from bimmer_connected.vehicle import MyBMWVehicle
from .coordinator import BMWDataUpdateCoordinator
TO_REDACT_INFO = [CONF_USERNAME, CONF_PASSWORD, CONF_REFRESH_TOKEN]
TO_REDACT_DATA = [
"lat",
"latitude",
"lon",
"longitude",
"heading",
"vin",
"licensePlate",
"city",
"street",
"streetNumber",
"postalCode",
"phone",
"formatted",
"subtitle",
]
def vehicle_to_dict(vehicle: MyBMWVehicle | None) -> dict:
"""Convert a MyBMWVehicle to a dictionary using MyBMWJSONEncoder."""
retval: dict = json.loads(json.dumps(vehicle, cls=MyBMWJSONEncoder))
return retval
async def async_get_config_entry_diagnostics(
hass: HomeAssistant, config_entry: ConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
coordinator: BMWDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
coordinator.account.config.log_responses = True
await coordinator.account.get_vehicles(force_init=True)
diagnostics_data = {
"info": async_redact_data(config_entry.data, TO_REDACT_INFO),
"data": [
async_redact_data(vehicle_to_dict(vehicle), TO_REDACT_DATA)
for vehicle in coordinator.account.vehicles
],
"fingerprint": async_redact_data(
[asdict(r) for r in coordinator.account.get_stored_responses()],
TO_REDACT_DATA,
),
}
coordinator.account.config.log_responses = False
return diagnostics_data
async def async_get_device_diagnostics(
hass: HomeAssistant, config_entry: ConfigEntry, device: DeviceEntry
) -> dict[str, Any]:
"""Return diagnostics for a device."""
coordinator: BMWDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
coordinator.account.config.log_responses = True
await coordinator.account.get_vehicles(force_init=True)
vin = next(iter(device.identifiers))[1]
vehicle = coordinator.account.get_vehicle(vin)
diagnostics_data = {
"info": async_redact_data(config_entry.data, TO_REDACT_INFO),
"data": async_redact_data(vehicle_to_dict(vehicle), TO_REDACT_DATA),
# Always have to get the full fingerprint as the VIN is redacted beforehand by the library
"fingerprint": async_redact_data(
[asdict(r) for r in coordinator.account.get_stored_responses()],
TO_REDACT_DATA,
),
}
coordinator.account.config.log_responses = False
return diagnostics_data

View File

@ -3,7 +3,10 @@
import json
from pathlib import Path
from bimmer_connected.account import MyBMWAccount
from bimmer_connected.api.authentication import MyBMWAuthentication
from bimmer_connected.const import VEHICLE_STATE_URL, VEHICLES_URL
import httpx
import respx
from homeassistant import config_entries
from homeassistant.components.bmw_connected_drive.const import (
@ -13,7 +16,6 @@ from homeassistant.components.bmw_connected_drive.const import (
)
from homeassistant.const import CONF_PASSWORD, CONF_REGION, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.util.dt import utcnow
from tests.common import MockConfigEntry, get_fixture_path, load_fixture
@ -39,49 +41,46 @@ FIXTURE_CONFIG_ENTRY = {
"unique_id": f"{FIXTURE_USER_INPUT[CONF_REGION]}-{FIXTURE_USER_INPUT[CONF_REGION]}",
}
FIXTURE_PATH = Path(get_fixture_path("", integration=BMW_DOMAIN))
async def mock_vehicles_from_fixture(account: MyBMWAccount) -> None:
"""Load MyBMWVehicle from fixtures and add them to the account."""
fixture_path = Path(get_fixture_path("", integration=BMW_DOMAIN))
def vehicles_sideeffect(request: httpx.Request) -> httpx.Response:
"""Return /vehicles response based on x-user-agent."""
x_user_agent = request.headers.get("x-user-agent", "").split(";")
brand = x_user_agent[1]
vehicles = []
for vehicle_file in FIXTURE_PATH.rglob(f"vehicles_v2_{brand}_*.json"):
vehicles.extend(json.loads(load_fixture(vehicle_file, integration=BMW_DOMAIN)))
return httpx.Response(200, json=vehicles)
fixture_vehicles_bmw = list(fixture_path.rglob("vehicles_v2_bmw_*.json"))
fixture_vehicles_mini = list(fixture_path.rglob("vehicles_v2_mini_*.json"))
# Load vehicle base lists as provided by vehicles/v2 API
vehicles = {
"bmw": [
vehicle
for bmw_file in fixture_vehicles_bmw
for vehicle in json.loads(load_fixture(bmw_file, integration=BMW_DOMAIN))
],
"mini": [
vehicle
for mini_file in fixture_vehicles_mini
for vehicle in json.loads(load_fixture(mini_file, integration=BMW_DOMAIN))
],
}
fetched_at = utcnow()
# Create a vehicle with base + specific state as provided by state/VIN API
for vehicle_base in [vehicle for brand in vehicles.values() for vehicle in brand]:
vehicle_state_path = (
Path("vehicles")
/ vehicle_base["attributes"]["bodyType"]
/ f"state_{vehicle_base['vin']}_0.json"
)
vehicle_state = json.loads(
load_fixture(
vehicle_state_path,
integration=BMW_DOMAIN,
)
def vehicle_state_sideeffect(request: httpx.Request) -> httpx.Response:
"""Return /vehicles/state response."""
state_file = next(FIXTURE_PATH.rglob(f"state_{request.headers['bmw-vin']}_*.json"))
try:
return httpx.Response(
200, json=json.loads(load_fixture(state_file, integration=BMW_DOMAIN))
)
except KeyError:
return httpx.Response(404)
account.add_vehicle(
vehicle_base,
vehicle_state,
fetched_at,
)
def mock_vehicles() -> respx.Router:
"""Return mocked adapter for vehicles."""
router = respx.mock(assert_all_called=False)
# Get vehicle list
router.get(VEHICLES_URL).mock(side_effect=vehicles_sideeffect)
# Get vehicle state
router.get(VEHICLE_STATE_URL).mock(side_effect=vehicle_state_sideeffect)
return router
async def mock_login(auth: MyBMWAuthentication) -> None:
"""Mock a successful login."""
auth.access_token = "SOME_ACCESS_TOKEN"
async def setup_mocked_integration(hass: HomeAssistant) -> MockConfigEntry:

View File

@ -1,12 +1,15 @@
"""Fixtures for BMW tests."""
from bimmer_connected.account import MyBMWAccount
from bimmer_connected.api.authentication import MyBMWAuthentication
import pytest
from . import mock_vehicles_from_fixture
from . import mock_login, mock_vehicles
@pytest.fixture
async def bmw_fixture(monkeypatch):
"""Patch the vehicle fixtures into a MyBMWAccount."""
monkeypatch.setattr(MyBMWAccount, "get_vehicles", mock_vehicles_from_fixture)
"""Patch the MyBMW Login and mock HTTP calls."""
monkeypatch.setattr(MyBMWAuthentication, "login", mock_login)
with mock_vehicles():
yield mock_vehicles

View File

@ -0,0 +1,657 @@
{
"info": {
"username": "**REDACTED**",
"password": "**REDACTED**",
"region": "rest_of_world",
"refresh_token": "**REDACTED**"
},
"data": [
{
"data": {
"appVehicleType": "CONNECTED",
"attributes": {
"a4aType": "USB_ONLY",
"bodyType": "I01",
"brand": "BMW_I",
"color": 4284110934,
"countryOfOrigin": "CZ",
"driveTrain": "ELECTRIC_WITH_RANGE_EXTENDER",
"driverGuideInfo": {
"androidAppScheme": "com.bmwgroup.driversguide.row",
"androidStoreUrl": "https://play.google.com/store/apps/details?id=com.bmwgroup.driversguide.row",
"iosAppScheme": "bmwdriversguide:///open",
"iosStoreUrl": "https://apps.apple.com/de/app/id714042749?mt=8"
},
"headUnitType": "NBT",
"hmiVersion": "ID4",
"lastFetched": "2022-07-10T09:25:53.104Z",
"model": "i3 (+ REX)",
"softwareVersionCurrent": {
"iStep": 510,
"puStep": { "month": 11, "year": 21 },
"seriesCluster": "I001"
},
"softwareVersionExFactory": {
"iStep": 502,
"puStep": { "month": 3, "year": 15 },
"seriesCluster": "I001"
},
"year": 2015
},
"mappingInfo": {
"isAssociated": false,
"isLmmEnabled": false,
"isPrimaryUser": true,
"mappingStatus": "CONFIRMED"
},
"vin": "**REDACTED**",
"is_metric": true,
"fetched_at": "2022-07-10T11:00:00+00:00",
"capabilities": {
"climateFunction": "AIR_CONDITIONING",
"climateNow": true,
"climateTimerTrigger": "DEPARTURE_TIMER",
"horn": true,
"isBmwChargingSupported": true,
"isCarSharingSupported": false,
"isChargeNowForBusinessSupported": false,
"isChargingHistorySupported": true,
"isChargingHospitalityEnabled": false,
"isChargingLoudnessEnabled": false,
"isChargingPlanSupported": true,
"isChargingPowerLimitEnabled": false,
"isChargingSettingsEnabled": false,
"isChargingTargetSocEnabled": false,
"isClimateTimerSupported": true,
"isCustomerEsimSupported": false,
"isDCSContractManagementSupported": true,
"isDataPrivacyEnabled": false,
"isEasyChargeEnabled": false,
"isEvGoChargingSupported": false,
"isMiniChargingSupported": false,
"isNonLscFeatureEnabled": false,
"isRemoteEngineStartSupported": false,
"isRemoteHistoryDeletionSupported": false,
"isRemoteHistorySupported": true,
"isRemoteParkingSupported": false,
"isRemoteServicesActivationRequired": false,
"isRemoteServicesBookingRequired": false,
"isScanAndChargeSupported": false,
"isSustainabilitySupported": false,
"isWifiHotspotServiceSupported": false,
"lastStateCallState": "ACTIVATED",
"lights": true,
"lock": true,
"remoteChargingCommands": {},
"sendPoi": true,
"specialThemeSupport": [],
"unlock": true,
"vehicleFinder": false,
"vehicleStateSource": "LAST_STATE_CALL"
},
"state": {
"chargingProfile": {
"chargingControlType": "WEEKLY_PLANNER",
"chargingMode": "DELAYED_CHARGING",
"chargingPreference": "CHARGING_WINDOW",
"chargingSettings": {
"hospitality": "NO_ACTION",
"idcc": "NO_ACTION",
"targetSoc": 100
},
"climatisationOn": false,
"departureTimes": [
{
"action": "DEACTIVATE",
"id": 1,
"timeStamp": { "hour": 7, "minute": 35 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY"
]
},
{
"action": "DEACTIVATE",
"id": 2,
"timeStamp": { "hour": 18, "minute": 0 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
]
},
{
"action": "DEACTIVATE",
"id": 3,
"timeStamp": { "hour": 7, "minute": 0 },
"timerWeekDays": []
},
{ "action": "DEACTIVATE", "id": 4, "timerWeekDays": [] }
],
"reductionOfChargeCurrent": {
"end": { "hour": 1, "minute": 30 },
"start": { "hour": 18, "minute": 1 }
}
},
"checkControlMessages": [],
"climateTimers": [
{
"departureTime": { "hour": 6, "minute": 40 },
"isWeeklyTimer": true,
"timerAction": "ACTIVATE",
"timerWeekDays": ["THURSDAY", "SUNDAY"]
},
{
"departureTime": { "hour": 12, "minute": 50 },
"isWeeklyTimer": false,
"timerAction": "ACTIVATE",
"timerWeekDays": ["MONDAY"]
},
{
"departureTime": { "hour": 18, "minute": 59 },
"isWeeklyTimer": true,
"timerAction": "DEACTIVATE",
"timerWeekDays": ["WEDNESDAY"]
}
],
"combustionFuelLevel": {
"range": 105,
"remainingFuelLiters": 6,
"remainingFuelPercent": 65
},
"currentMileage": 137009,
"doorsState": {
"combinedSecurityState": "UNLOCKED",
"combinedState": "CLOSED",
"hood": "CLOSED",
"leftFront": "CLOSED",
"leftRear": "CLOSED",
"rightFront": "CLOSED",
"rightRear": "CLOSED",
"trunk": "CLOSED"
},
"driverPreferences": { "lscPrivacyMode": "OFF" },
"electricChargingState": {
"chargingConnectionType": "CONDUCTIVE",
"chargingLevelPercent": 82,
"chargingStatus": "WAITING_FOR_CHARGING",
"chargingTarget": 100,
"isChargerConnected": true,
"range": 174
},
"isLeftSteering": true,
"isLscSupported": true,
"lastFetched": "2022-06-22T14:24:23.982Z",
"lastUpdatedAt": "2022-06-22T13:58:52Z",
"range": 174,
"requiredServices": [
{
"dateTime": "2022-10-01T00:00:00.000Z",
"description": "Next service due by the specified date.",
"status": "OK",
"type": "BRAKE_FLUID"
},
{
"dateTime": "2023-05-01T00:00:00.000Z",
"description": "Next vehicle check due after the specified distance or date.",
"status": "OK",
"type": "VEHICLE_CHECK"
},
{
"dateTime": "2023-05-01T00:00:00.000Z",
"description": "Next state inspection due by the specified date.",
"status": "OK",
"type": "VEHICLE_TUV"
}
],
"roofState": { "roofState": "CLOSED", "roofStateType": "SUN_ROOF" },
"windowsState": {
"combinedState": "CLOSED",
"leftFront": "CLOSED",
"rightFront": "CLOSED"
}
}
},
"fuel_and_battery": {
"remaining_range_fuel": [105, "km"],
"remaining_range_electric": [174, "km"],
"remaining_range_total": [279, "km"],
"remaining_fuel": [6, "L"],
"remaining_fuel_percent": 65,
"remaining_battery_percent": 82,
"charging_status": "WAITING_FOR_CHARGING",
"charging_start_time_no_tz": "2022-07-10T18:01:00",
"charging_end_time": null,
"is_charger_connected": true,
"account_timezone": {
"_std_offset": "0:00:00",
"_dst_offset": "0:00:00",
"_dst_saved": "0:00:00",
"_hasdst": false,
"_tznames": ["UTC", "UTC"]
},
"charging_start_time": "2022-07-10T18:01:00+00:00"
},
"vehicle_location": {
"location": null,
"heading": null,
"vehicle_update_timestamp": "2022-07-10T09:25:53+00:00",
"account_region": "row",
"remote_service_position": null
},
"doors_and_windows": {
"door_lock_state": "UNLOCKED",
"lids": [
{ "name": "hood", "state": "CLOSED", "is_closed": true },
{ "name": "leftFront", "state": "CLOSED", "is_closed": true },
{ "name": "leftRear", "state": "CLOSED", "is_closed": true },
{ "name": "rightFront", "state": "CLOSED", "is_closed": true },
{ "name": "rightRear", "state": "CLOSED", "is_closed": true },
{ "name": "trunk", "state": "CLOSED", "is_closed": true },
{ "name": "sunRoof", "state": "CLOSED", "is_closed": true }
],
"windows": [
{ "name": "leftFront", "state": "CLOSED", "is_closed": true },
{ "name": "rightFront", "state": "CLOSED", "is_closed": true }
],
"all_lids_closed": true,
"all_windows_closed": true,
"open_lids": [],
"open_windows": []
},
"condition_based_services": {
"messages": [
{
"service_type": "BRAKE_FLUID",
"state": "OK",
"due_date": "2022-10-01T00:00:00+00:00",
"due_distance": [null, null]
},
{
"service_type": "VEHICLE_CHECK",
"state": "OK",
"due_date": "2023-05-01T00:00:00+00:00",
"due_distance": [null, null]
},
{
"service_type": "VEHICLE_TUV",
"state": "OK",
"due_date": "2023-05-01T00:00:00+00:00",
"due_distance": [null, null]
}
],
"is_service_required": false
},
"check_control_messages": {
"messages": [],
"has_check_control_messages": false
},
"charging_profile": {
"is_pre_entry_climatization_enabled": false,
"timer_type": "WEEKLY_PLANNER",
"departure_times": [
{
"_timer_dict": {
"action": "DEACTIVATE",
"id": 1,
"timeStamp": { "hour": 7, "minute": 35 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY"
]
},
"action": "DEACTIVATE",
"start_time": "07:35:00",
"timer_id": 1,
"weekdays": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"]
},
{
"_timer_dict": {
"action": "DEACTIVATE",
"id": 2,
"timeStamp": { "hour": 18, "minute": 0 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
]
},
"action": "DEACTIVATE",
"start_time": "18:00:00",
"timer_id": 2,
"weekdays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
]
},
{
"_timer_dict": {
"action": "DEACTIVATE",
"id": 3,
"timeStamp": { "hour": 7, "minute": 0 },
"timerWeekDays": []
},
"action": "DEACTIVATE",
"start_time": "07:00:00",
"timer_id": 3,
"weekdays": []
},
{
"_timer_dict": {
"action": "DEACTIVATE",
"id": 4,
"timerWeekDays": []
},
"action": "DEACTIVATE",
"start_time": null,
"timer_id": 4,
"weekdays": []
}
],
"preferred_charging_window": {
"_window_dict": {
"end": { "hour": 1, "minute": 30 },
"start": { "hour": 18, "minute": 1 }
},
"end_time": "01:30:00",
"start_time": "18:01:00"
},
"charging_preferences": "CHARGING_WINDOW",
"charging_mode": "DELAYED_CHARGING"
},
"available_attributes": [
"gps_position",
"vin",
"remaining_range_total",
"mileage",
"charging_time_remaining",
"charging_end_time",
"charging_time_label",
"charging_status",
"connection_status",
"remaining_battery_percent",
"remaining_range_electric",
"last_charging_end_result",
"remaining_fuel",
"remaining_range_fuel",
"remaining_fuel_percent",
"condition_based_services",
"check_control_messages",
"door_lock_state",
"timestamp",
"lids",
"windows"
],
"brand": "bmw",
"drive_train": "ELECTRIC_WITH_RANGE_EXTENDER",
"drive_train_attributes": [
"remaining_range_total",
"mileage",
"charging_time_remaining",
"charging_end_time",
"charging_time_label",
"charging_status",
"connection_status",
"remaining_battery_percent",
"remaining_range_electric",
"last_charging_end_result",
"remaining_fuel",
"remaining_range_fuel",
"remaining_fuel_percent"
],
"has_combustion_drivetrain": true,
"has_electric_drivetrain": true,
"is_charging_plan_supported": true,
"is_lsc_enabled": true,
"is_vehicle_active": false,
"is_vehicle_tracking_enabled": false,
"lsc_type": "ACTIVATED",
"mileage": [137009, "km"],
"name": "i3 (+ REX)",
"timestamp": "2022-07-10T09:25:53+00:00",
"vin": "**REDACTED**"
}
],
"fingerprint": [
{
"filename": "bmw-vehicles.json",
"content": [
{
"appVehicleType": "CONNECTED",
"attributes": {
"a4aType": "USB_ONLY",
"bodyType": "I01",
"brand": "BMW_I",
"color": 4284110934,
"countryOfOrigin": "CZ",
"driveTrain": "ELECTRIC_WITH_RANGE_EXTENDER",
"driverGuideInfo": {
"androidAppScheme": "com.bmwgroup.driversguide.row",
"androidStoreUrl": "https://play.google.com/store/apps/details?id=com.bmwgroup.driversguide.row",
"iosAppScheme": "bmwdriversguide:///open",
"iosStoreUrl": "https://apps.apple.com/de/app/id714042749?mt=8"
},
"headUnitType": "NBT",
"hmiVersion": "ID4",
"lastFetched": "2022-07-10T09:25:53.104Z",
"model": "i3 (+ REX)",
"softwareVersionCurrent": {
"iStep": 510,
"puStep": { "month": 11, "year": 21 },
"seriesCluster": "I001"
},
"softwareVersionExFactory": {
"iStep": 502,
"puStep": { "month": 3, "year": 15 },
"seriesCluster": "I001"
},
"year": 2015
},
"mappingInfo": {
"isAssociated": false,
"isLmmEnabled": false,
"isPrimaryUser": true,
"mappingStatus": "CONFIRMED"
},
"vin": "**REDACTED**"
}
]
},
{ "filename": "mini-vehicles.json", "content": [] },
{
"filename": "bmw-vehicles_state_WBY0FINGERPRINT01.json",
"content": {
"capabilities": {
"climateFunction": "AIR_CONDITIONING",
"climateNow": true,
"climateTimerTrigger": "DEPARTURE_TIMER",
"horn": true,
"isBmwChargingSupported": true,
"isCarSharingSupported": false,
"isChargeNowForBusinessSupported": false,
"isChargingHistorySupported": true,
"isChargingHospitalityEnabled": false,
"isChargingLoudnessEnabled": false,
"isChargingPlanSupported": true,
"isChargingPowerLimitEnabled": false,
"isChargingSettingsEnabled": false,
"isChargingTargetSocEnabled": false,
"isClimateTimerSupported": true,
"isCustomerEsimSupported": false,
"isDCSContractManagementSupported": true,
"isDataPrivacyEnabled": false,
"isEasyChargeEnabled": false,
"isEvGoChargingSupported": false,
"isMiniChargingSupported": false,
"isNonLscFeatureEnabled": false,
"isRemoteEngineStartSupported": false,
"isRemoteHistoryDeletionSupported": false,
"isRemoteHistorySupported": true,
"isRemoteParkingSupported": false,
"isRemoteServicesActivationRequired": false,
"isRemoteServicesBookingRequired": false,
"isScanAndChargeSupported": false,
"isSustainabilitySupported": false,
"isWifiHotspotServiceSupported": false,
"lastStateCallState": "ACTIVATED",
"lights": true,
"lock": true,
"remoteChargingCommands": {},
"sendPoi": true,
"specialThemeSupport": [],
"unlock": true,
"vehicleFinder": false,
"vehicleStateSource": "LAST_STATE_CALL"
},
"state": {
"chargingProfile": {
"chargingControlType": "WEEKLY_PLANNER",
"chargingMode": "DELAYED_CHARGING",
"chargingPreference": "CHARGING_WINDOW",
"chargingSettings": {
"hospitality": "NO_ACTION",
"idcc": "NO_ACTION",
"targetSoc": 100
},
"climatisationOn": false,
"departureTimes": [
{
"action": "DEACTIVATE",
"id": 1,
"timeStamp": { "hour": 7, "minute": 35 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY"
]
},
{
"action": "DEACTIVATE",
"id": 2,
"timeStamp": { "hour": 18, "minute": 0 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
]
},
{
"action": "DEACTIVATE",
"id": 3,
"timeStamp": { "hour": 7, "minute": 0 },
"timerWeekDays": []
},
{ "action": "DEACTIVATE", "id": 4, "timerWeekDays": [] }
],
"reductionOfChargeCurrent": {
"end": { "hour": 1, "minute": 30 },
"start": { "hour": 18, "minute": 1 }
}
},
"checkControlMessages": [],
"climateTimers": [
{
"departureTime": { "hour": 6, "minute": 40 },
"isWeeklyTimer": true,
"timerAction": "ACTIVATE",
"timerWeekDays": ["THURSDAY", "SUNDAY"]
},
{
"departureTime": { "hour": 12, "minute": 50 },
"isWeeklyTimer": false,
"timerAction": "ACTIVATE",
"timerWeekDays": ["MONDAY"]
},
{
"departureTime": { "hour": 18, "minute": 59 },
"isWeeklyTimer": true,
"timerAction": "DEACTIVATE",
"timerWeekDays": ["WEDNESDAY"]
}
],
"combustionFuelLevel": {
"range": 105,
"remainingFuelLiters": 6,
"remainingFuelPercent": 65
},
"currentMileage": 137009,
"doorsState": {
"combinedSecurityState": "UNLOCKED",
"combinedState": "CLOSED",
"hood": "CLOSED",
"leftFront": "CLOSED",
"leftRear": "CLOSED",
"rightFront": "CLOSED",
"rightRear": "CLOSED",
"trunk": "CLOSED"
},
"driverPreferences": { "lscPrivacyMode": "OFF" },
"electricChargingState": {
"chargingConnectionType": "CONDUCTIVE",
"chargingLevelPercent": 82,
"chargingStatus": "WAITING_FOR_CHARGING",
"chargingTarget": 100,
"isChargerConnected": true,
"range": 174
},
"isLeftSteering": true,
"isLscSupported": true,
"lastFetched": "2022-06-22T14:24:23.982Z",
"lastUpdatedAt": "2022-06-22T13:58:52Z",
"range": 174,
"requiredServices": [
{
"dateTime": "2022-10-01T00:00:00.000Z",
"description": "Next service due by the specified date.",
"status": "OK",
"type": "BRAKE_FLUID"
},
{
"dateTime": "2023-05-01T00:00:00.000Z",
"description": "Next vehicle check due after the specified distance or date.",
"status": "OK",
"type": "VEHICLE_CHECK"
},
{
"dateTime": "2023-05-01T00:00:00.000Z",
"description": "Next state inspection due by the specified date.",
"status": "OK",
"type": "VEHICLE_TUV"
}
],
"roofState": { "roofState": "CLOSED", "roofStateType": "SUN_ROOF" },
"windowsState": {
"combinedState": "CLOSED",
"leftFront": "CLOSED",
"rightFront": "CLOSED"
}
}
}
}
]
}

View File

@ -0,0 +1,655 @@
{
"info": {
"username": "**REDACTED**",
"password": "**REDACTED**",
"region": "rest_of_world",
"refresh_token": "**REDACTED**"
},
"data": {
"data": {
"appVehicleType": "CONNECTED",
"attributes": {
"a4aType": "USB_ONLY",
"bodyType": "I01",
"brand": "BMW_I",
"color": 4284110934,
"countryOfOrigin": "CZ",
"driveTrain": "ELECTRIC_WITH_RANGE_EXTENDER",
"driverGuideInfo": {
"androidAppScheme": "com.bmwgroup.driversguide.row",
"androidStoreUrl": "https://play.google.com/store/apps/details?id=com.bmwgroup.driversguide.row",
"iosAppScheme": "bmwdriversguide:///open",
"iosStoreUrl": "https://apps.apple.com/de/app/id714042749?mt=8"
},
"headUnitType": "NBT",
"hmiVersion": "ID4",
"lastFetched": "2022-07-10T09:25:53.104Z",
"model": "i3 (+ REX)",
"softwareVersionCurrent": {
"iStep": 510,
"puStep": { "month": 11, "year": 21 },
"seriesCluster": "I001"
},
"softwareVersionExFactory": {
"iStep": 502,
"puStep": { "month": 3, "year": 15 },
"seriesCluster": "I001"
},
"year": 2015
},
"mappingInfo": {
"isAssociated": false,
"isLmmEnabled": false,
"isPrimaryUser": true,
"mappingStatus": "CONFIRMED"
},
"vin": "**REDACTED**",
"is_metric": true,
"fetched_at": "2022-07-10T11:00:00+00:00",
"capabilities": {
"climateFunction": "AIR_CONDITIONING",
"climateNow": true,
"climateTimerTrigger": "DEPARTURE_TIMER",
"horn": true,
"isBmwChargingSupported": true,
"isCarSharingSupported": false,
"isChargeNowForBusinessSupported": false,
"isChargingHistorySupported": true,
"isChargingHospitalityEnabled": false,
"isChargingLoudnessEnabled": false,
"isChargingPlanSupported": true,
"isChargingPowerLimitEnabled": false,
"isChargingSettingsEnabled": false,
"isChargingTargetSocEnabled": false,
"isClimateTimerSupported": true,
"isCustomerEsimSupported": false,
"isDCSContractManagementSupported": true,
"isDataPrivacyEnabled": false,
"isEasyChargeEnabled": false,
"isEvGoChargingSupported": false,
"isMiniChargingSupported": false,
"isNonLscFeatureEnabled": false,
"isRemoteEngineStartSupported": false,
"isRemoteHistoryDeletionSupported": false,
"isRemoteHistorySupported": true,
"isRemoteParkingSupported": false,
"isRemoteServicesActivationRequired": false,
"isRemoteServicesBookingRequired": false,
"isScanAndChargeSupported": false,
"isSustainabilitySupported": false,
"isWifiHotspotServiceSupported": false,
"lastStateCallState": "ACTIVATED",
"lights": true,
"lock": true,
"remoteChargingCommands": {},
"sendPoi": true,
"specialThemeSupport": [],
"unlock": true,
"vehicleFinder": false,
"vehicleStateSource": "LAST_STATE_CALL"
},
"state": {
"chargingProfile": {
"chargingControlType": "WEEKLY_PLANNER",
"chargingMode": "DELAYED_CHARGING",
"chargingPreference": "CHARGING_WINDOW",
"chargingSettings": {
"hospitality": "NO_ACTION",
"idcc": "NO_ACTION",
"targetSoc": 100
},
"climatisationOn": false,
"departureTimes": [
{
"action": "DEACTIVATE",
"id": 1,
"timeStamp": { "hour": 7, "minute": 35 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY"
]
},
{
"action": "DEACTIVATE",
"id": 2,
"timeStamp": { "hour": 18, "minute": 0 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
]
},
{
"action": "DEACTIVATE",
"id": 3,
"timeStamp": { "hour": 7, "minute": 0 },
"timerWeekDays": []
},
{ "action": "DEACTIVATE", "id": 4, "timerWeekDays": [] }
],
"reductionOfChargeCurrent": {
"end": { "hour": 1, "minute": 30 },
"start": { "hour": 18, "minute": 1 }
}
},
"checkControlMessages": [],
"climateTimers": [
{
"departureTime": { "hour": 6, "minute": 40 },
"isWeeklyTimer": true,
"timerAction": "ACTIVATE",
"timerWeekDays": ["THURSDAY", "SUNDAY"]
},
{
"departureTime": { "hour": 12, "minute": 50 },
"isWeeklyTimer": false,
"timerAction": "ACTIVATE",
"timerWeekDays": ["MONDAY"]
},
{
"departureTime": { "hour": 18, "minute": 59 },
"isWeeklyTimer": true,
"timerAction": "DEACTIVATE",
"timerWeekDays": ["WEDNESDAY"]
}
],
"combustionFuelLevel": {
"range": 105,
"remainingFuelLiters": 6,
"remainingFuelPercent": 65
},
"currentMileage": 137009,
"doorsState": {
"combinedSecurityState": "UNLOCKED",
"combinedState": "CLOSED",
"hood": "CLOSED",
"leftFront": "CLOSED",
"leftRear": "CLOSED",
"rightFront": "CLOSED",
"rightRear": "CLOSED",
"trunk": "CLOSED"
},
"driverPreferences": { "lscPrivacyMode": "OFF" },
"electricChargingState": {
"chargingConnectionType": "CONDUCTIVE",
"chargingLevelPercent": 82,
"chargingStatus": "WAITING_FOR_CHARGING",
"chargingTarget": 100,
"isChargerConnected": true,
"range": 174
},
"isLeftSteering": true,
"isLscSupported": true,
"lastFetched": "2022-06-22T14:24:23.982Z",
"lastUpdatedAt": "2022-06-22T13:58:52Z",
"range": 174,
"requiredServices": [
{
"dateTime": "2022-10-01T00:00:00.000Z",
"description": "Next service due by the specified date.",
"status": "OK",
"type": "BRAKE_FLUID"
},
{
"dateTime": "2023-05-01T00:00:00.000Z",
"description": "Next vehicle check due after the specified distance or date.",
"status": "OK",
"type": "VEHICLE_CHECK"
},
{
"dateTime": "2023-05-01T00:00:00.000Z",
"description": "Next state inspection due by the specified date.",
"status": "OK",
"type": "VEHICLE_TUV"
}
],
"roofState": { "roofState": "CLOSED", "roofStateType": "SUN_ROOF" },
"windowsState": {
"combinedState": "CLOSED",
"leftFront": "CLOSED",
"rightFront": "CLOSED"
}
}
},
"fuel_and_battery": {
"remaining_range_fuel": [105, "km"],
"remaining_range_electric": [174, "km"],
"remaining_range_total": [279, "km"],
"remaining_fuel": [6, "L"],
"remaining_fuel_percent": 65,
"remaining_battery_percent": 82,
"charging_status": "WAITING_FOR_CHARGING",
"charging_start_time_no_tz": "2022-07-10T18:01:00",
"charging_end_time": null,
"is_charger_connected": true,
"account_timezone": {
"_std_offset": "0:00:00",
"_dst_offset": "0:00:00",
"_dst_saved": "0:00:00",
"_hasdst": false,
"_tznames": ["UTC", "UTC"]
},
"charging_start_time": "2022-07-10T18:01:00+00:00"
},
"vehicle_location": {
"location": null,
"heading": null,
"vehicle_update_timestamp": "2022-07-10T09:25:53+00:00",
"account_region": "row",
"remote_service_position": null
},
"doors_and_windows": {
"door_lock_state": "UNLOCKED",
"lids": [
{ "name": "hood", "state": "CLOSED", "is_closed": true },
{ "name": "leftFront", "state": "CLOSED", "is_closed": true },
{ "name": "leftRear", "state": "CLOSED", "is_closed": true },
{ "name": "rightFront", "state": "CLOSED", "is_closed": true },
{ "name": "rightRear", "state": "CLOSED", "is_closed": true },
{ "name": "trunk", "state": "CLOSED", "is_closed": true },
{ "name": "sunRoof", "state": "CLOSED", "is_closed": true }
],
"windows": [
{ "name": "leftFront", "state": "CLOSED", "is_closed": true },
{ "name": "rightFront", "state": "CLOSED", "is_closed": true }
],
"all_lids_closed": true,
"all_windows_closed": true,
"open_lids": [],
"open_windows": []
},
"condition_based_services": {
"messages": [
{
"service_type": "BRAKE_FLUID",
"state": "OK",
"due_date": "2022-10-01T00:00:00+00:00",
"due_distance": [null, null]
},
{
"service_type": "VEHICLE_CHECK",
"state": "OK",
"due_date": "2023-05-01T00:00:00+00:00",
"due_distance": [null, null]
},
{
"service_type": "VEHICLE_TUV",
"state": "OK",
"due_date": "2023-05-01T00:00:00+00:00",
"due_distance": [null, null]
}
],
"is_service_required": false
},
"check_control_messages": {
"messages": [],
"has_check_control_messages": false
},
"charging_profile": {
"is_pre_entry_climatization_enabled": false,
"timer_type": "WEEKLY_PLANNER",
"departure_times": [
{
"_timer_dict": {
"action": "DEACTIVATE",
"id": 1,
"timeStamp": { "hour": 7, "minute": 35 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY"
]
},
"action": "DEACTIVATE",
"start_time": "07:35:00",
"timer_id": 1,
"weekdays": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"]
},
{
"_timer_dict": {
"action": "DEACTIVATE",
"id": 2,
"timeStamp": { "hour": 18, "minute": 0 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
]
},
"action": "DEACTIVATE",
"start_time": "18:00:00",
"timer_id": 2,
"weekdays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
]
},
{
"_timer_dict": {
"action": "DEACTIVATE",
"id": 3,
"timeStamp": { "hour": 7, "minute": 0 },
"timerWeekDays": []
},
"action": "DEACTIVATE",
"start_time": "07:00:00",
"timer_id": 3,
"weekdays": []
},
{
"_timer_dict": {
"action": "DEACTIVATE",
"id": 4,
"timerWeekDays": []
},
"action": "DEACTIVATE",
"start_time": null,
"timer_id": 4,
"weekdays": []
}
],
"preferred_charging_window": {
"_window_dict": {
"end": { "hour": 1, "minute": 30 },
"start": { "hour": 18, "minute": 1 }
},
"end_time": "01:30:00",
"start_time": "18:01:00"
},
"charging_preferences": "CHARGING_WINDOW",
"charging_mode": "DELAYED_CHARGING"
},
"available_attributes": [
"gps_position",
"vin",
"remaining_range_total",
"mileage",
"charging_time_remaining",
"charging_end_time",
"charging_time_label",
"charging_status",
"connection_status",
"remaining_battery_percent",
"remaining_range_electric",
"last_charging_end_result",
"remaining_fuel",
"remaining_range_fuel",
"remaining_fuel_percent",
"condition_based_services",
"check_control_messages",
"door_lock_state",
"timestamp",
"lids",
"windows"
],
"brand": "bmw",
"drive_train": "ELECTRIC_WITH_RANGE_EXTENDER",
"drive_train_attributes": [
"remaining_range_total",
"mileage",
"charging_time_remaining",
"charging_end_time",
"charging_time_label",
"charging_status",
"connection_status",
"remaining_battery_percent",
"remaining_range_electric",
"last_charging_end_result",
"remaining_fuel",
"remaining_range_fuel",
"remaining_fuel_percent"
],
"has_combustion_drivetrain": true,
"has_electric_drivetrain": true,
"is_charging_plan_supported": true,
"is_lsc_enabled": true,
"is_vehicle_active": false,
"is_vehicle_tracking_enabled": false,
"lsc_type": "ACTIVATED",
"mileage": [137009, "km"],
"name": "i3 (+ REX)",
"timestamp": "2022-07-10T09:25:53+00:00",
"vin": "**REDACTED**"
},
"fingerprint": [
{
"filename": "bmw-vehicles.json",
"content": [
{
"appVehicleType": "CONNECTED",
"attributes": {
"a4aType": "USB_ONLY",
"bodyType": "I01",
"brand": "BMW_I",
"color": 4284110934,
"countryOfOrigin": "CZ",
"driveTrain": "ELECTRIC_WITH_RANGE_EXTENDER",
"driverGuideInfo": {
"androidAppScheme": "com.bmwgroup.driversguide.row",
"androidStoreUrl": "https://play.google.com/store/apps/details?id=com.bmwgroup.driversguide.row",
"iosAppScheme": "bmwdriversguide:///open",
"iosStoreUrl": "https://apps.apple.com/de/app/id714042749?mt=8"
},
"headUnitType": "NBT",
"hmiVersion": "ID4",
"lastFetched": "2022-07-10T09:25:53.104Z",
"model": "i3 (+ REX)",
"softwareVersionCurrent": {
"iStep": 510,
"puStep": { "month": 11, "year": 21 },
"seriesCluster": "I001"
},
"softwareVersionExFactory": {
"iStep": 502,
"puStep": { "month": 3, "year": 15 },
"seriesCluster": "I001"
},
"year": 2015
},
"mappingInfo": {
"isAssociated": false,
"isLmmEnabled": false,
"isPrimaryUser": true,
"mappingStatus": "CONFIRMED"
},
"vin": "**REDACTED**"
}
]
},
{ "filename": "mini-vehicles.json", "content": [] },
{
"filename": "bmw-vehicles_state_WBY0FINGERPRINT01.json",
"content": {
"capabilities": {
"climateFunction": "AIR_CONDITIONING",
"climateNow": true,
"climateTimerTrigger": "DEPARTURE_TIMER",
"horn": true,
"isBmwChargingSupported": true,
"isCarSharingSupported": false,
"isChargeNowForBusinessSupported": false,
"isChargingHistorySupported": true,
"isChargingHospitalityEnabled": false,
"isChargingLoudnessEnabled": false,
"isChargingPlanSupported": true,
"isChargingPowerLimitEnabled": false,
"isChargingSettingsEnabled": false,
"isChargingTargetSocEnabled": false,
"isClimateTimerSupported": true,
"isCustomerEsimSupported": false,
"isDCSContractManagementSupported": true,
"isDataPrivacyEnabled": false,
"isEasyChargeEnabled": false,
"isEvGoChargingSupported": false,
"isMiniChargingSupported": false,
"isNonLscFeatureEnabled": false,
"isRemoteEngineStartSupported": false,
"isRemoteHistoryDeletionSupported": false,
"isRemoteHistorySupported": true,
"isRemoteParkingSupported": false,
"isRemoteServicesActivationRequired": false,
"isRemoteServicesBookingRequired": false,
"isScanAndChargeSupported": false,
"isSustainabilitySupported": false,
"isWifiHotspotServiceSupported": false,
"lastStateCallState": "ACTIVATED",
"lights": true,
"lock": true,
"remoteChargingCommands": {},
"sendPoi": true,
"specialThemeSupport": [],
"unlock": true,
"vehicleFinder": false,
"vehicleStateSource": "LAST_STATE_CALL"
},
"state": {
"chargingProfile": {
"chargingControlType": "WEEKLY_PLANNER",
"chargingMode": "DELAYED_CHARGING",
"chargingPreference": "CHARGING_WINDOW",
"chargingSettings": {
"hospitality": "NO_ACTION",
"idcc": "NO_ACTION",
"targetSoc": 100
},
"climatisationOn": false,
"departureTimes": [
{
"action": "DEACTIVATE",
"id": 1,
"timeStamp": { "hour": 7, "minute": 35 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY"
]
},
{
"action": "DEACTIVATE",
"id": 2,
"timeStamp": { "hour": 18, "minute": 0 },
"timerWeekDays": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
]
},
{
"action": "DEACTIVATE",
"id": 3,
"timeStamp": { "hour": 7, "minute": 0 },
"timerWeekDays": []
},
{ "action": "DEACTIVATE", "id": 4, "timerWeekDays": [] }
],
"reductionOfChargeCurrent": {
"end": { "hour": 1, "minute": 30 },
"start": { "hour": 18, "minute": 1 }
}
},
"checkControlMessages": [],
"climateTimers": [
{
"departureTime": { "hour": 6, "minute": 40 },
"isWeeklyTimer": true,
"timerAction": "ACTIVATE",
"timerWeekDays": ["THURSDAY", "SUNDAY"]
},
{
"departureTime": { "hour": 12, "minute": 50 },
"isWeeklyTimer": false,
"timerAction": "ACTIVATE",
"timerWeekDays": ["MONDAY"]
},
{
"departureTime": { "hour": 18, "minute": 59 },
"isWeeklyTimer": true,
"timerAction": "DEACTIVATE",
"timerWeekDays": ["WEDNESDAY"]
}
],
"combustionFuelLevel": {
"range": 105,
"remainingFuelLiters": 6,
"remainingFuelPercent": 65
},
"currentMileage": 137009,
"doorsState": {
"combinedSecurityState": "UNLOCKED",
"combinedState": "CLOSED",
"hood": "CLOSED",
"leftFront": "CLOSED",
"leftRear": "CLOSED",
"rightFront": "CLOSED",
"rightRear": "CLOSED",
"trunk": "CLOSED"
},
"driverPreferences": { "lscPrivacyMode": "OFF" },
"electricChargingState": {
"chargingConnectionType": "CONDUCTIVE",
"chargingLevelPercent": 82,
"chargingStatus": "WAITING_FOR_CHARGING",
"chargingTarget": 100,
"isChargerConnected": true,
"range": 174
},
"isLeftSteering": true,
"isLscSupported": true,
"lastFetched": "2022-06-22T14:24:23.982Z",
"lastUpdatedAt": "2022-06-22T13:58:52Z",
"range": 174,
"requiredServices": [
{
"dateTime": "2022-10-01T00:00:00.000Z",
"description": "Next service due by the specified date.",
"status": "OK",
"type": "BRAKE_FLUID"
},
{
"dateTime": "2023-05-01T00:00:00.000Z",
"description": "Next vehicle check due after the specified distance or date.",
"status": "OK",
"type": "VEHICLE_CHECK"
},
{
"dateTime": "2023-05-01T00:00:00.000Z",
"description": "Next state inspection due by the specified date.",
"status": "OK",
"type": "VEHICLE_TUV"
}
],
"roofState": { "roofState": "CLOSED", "roofStateType": "SUN_ROOF" },
"windowsState": {
"combinedState": "CLOSED",
"leftFront": "CLOSED",
"rightFront": "CLOSED"
}
}
}
}
]
}

View File

@ -0,0 +1,104 @@
"""Test BMW diagnostics."""
import datetime
import json
import os
import time
from freezegun import freeze_time
from homeassistant.components.bmw_connected_drive.const import DOMAIN
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from . import setup_mocked_integration
from tests.common import load_fixture
from tests.components.diagnostics import (
get_diagnostics_for_config_entry,
get_diagnostics_for_device,
)
@freeze_time(datetime.datetime(2022, 7, 10, 11))
async def test_config_entry_diagnostics(hass: HomeAssistant, hass_client, bmw_fixture):
"""Test config entry diagnostics."""
# Make sure that local timezone for test is UTC
os.environ["TZ"] = "UTC"
time.tzset()
mock_config_entry = await setup_mocked_integration(hass)
diagnostics = await get_diagnostics_for_config_entry(
hass, hass_client, mock_config_entry
)
diagnostics_fixture = json.loads(
load_fixture("diagnostics/diagnostics_config_entry.json", DOMAIN)
)
assert diagnostics == diagnostics_fixture
@freeze_time(datetime.datetime(2022, 7, 10, 11))
async def test_device_diagnostics(hass: HomeAssistant, hass_client, bmw_fixture):
"""Test device diagnostics."""
# Make sure that local timezone for test is UTC
os.environ["TZ"] = "UTC"
time.tzset()
mock_config_entry = await setup_mocked_integration(hass)
device_registry = dr.async_get(hass)
reg_device = device_registry.async_get_device(
identifiers={(DOMAIN, "WBY00000000REXI01")},
)
assert reg_device is not None
diagnostics = await get_diagnostics_for_device(
hass, hass_client, mock_config_entry, reg_device
)
diagnostics_fixture = json.loads(
load_fixture("diagnostics/diagnostics_device.json", DOMAIN)
)
assert diagnostics == diagnostics_fixture
@freeze_time(datetime.datetime(2022, 7, 10, 11))
async def test_device_diagnostics_vehicle_not_found(
hass: HomeAssistant, hass_client, bmw_fixture
):
"""Test device diagnostics when the vehicle cannot be found."""
# Make sure that local timezone for test is UTC
os.environ["TZ"] = "UTC"
time.tzset()
mock_config_entry = await setup_mocked_integration(hass)
device_registry = dr.async_get(hass)
reg_device = device_registry.async_get_device(
identifiers={(DOMAIN, "WBY00000000REXI01")},
)
assert reg_device is not None
# Change vehicle identifier so that vehicle will not be found
device_registry.async_update_device(
reg_device.id, new_identifiers={(DOMAIN, "WBY00000000REXI99")}
)
diagnostics = await get_diagnostics_for_device(
hass, hass_client, mock_config_entry, reg_device
)
diagnostics_fixture = json.loads(
load_fixture("diagnostics/diagnostics_device.json", DOMAIN)
)
# Mock empty data if car is not found in account anymore
diagnostics_fixture["data"] = None
assert diagnostics == diagnostics_fixture