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>pull/85662/head
parent
db428f2141
commit
1afb30344a
|
@ -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
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue