bimmer_connected
This is a simple library to query and control the status of your BMW or Mini vehicle from the MyBMW portal.
Installation
bimmer_connected
is tested against Python 3.8 or above. Just install the latest release from PyPI
using pip3 install --upgrade bimmer_connected
.
Alternatively, clone the project and execute pip install -e .
to install the current
master
branch.
Note
If you want to connect to a chinese server, you need to install the [china]
extra, e.g. pip3 install --upgrade bimmer_connected[china]
.
Usage
While this library is mainly written to be included in Home Assistant, it can be use on its own.
After installation, execute bimmerconnected
from command line for usage instruction
or see the full CLI documentation.
Please be aware that bimmer_connected
is an async
library when using it in Python code.
The description of the modules
can be found in the module documentation.
Example in an asyncio
event loop
import asyncio
from bimmer_connected.account import MyBMWAccount
from bimmer_connected.api.regions import Regions
async def main():
account = MyBMWAccount(USERNAME, PASSWORD, Regions.REST_OF_WORLD)
await account.get_vehicles()
vehicle = account.get_vehicle(VIN)
print(vehicle.brand, vehicle.name, vehicle.vin)
result = await vehicle.remote_services.trigger_remote_light_flash()
print(result.state)
asyncio.run(main())
Example in non-async code
import asyncio
from bimmer_connected.account import MyBMWAccount
from bimmer_connected.api.regions import Regions
account = MyBMWAccount(USERNAME, PASSWORD, Regions.REST_OF_WORLD)
asyncio.run(account.get_vehicles())
vehicle = account.get_vehicle(VIN)
print(vehicle.brand, vehicle.name, vehicle.vin)
result = asyncio.run(vehicle.remote_services.trigger_remote_light_flash())
print(result.state)
Compatibility
This works with BMW (and Mini) vehicles with a MyBMW account. So far it is tested on vehicles with a ‘MGU’, ‘NBTEvo’, ‘EntryEvo’, ‘NBT’, or ‘EntryNav’ navigation system. If you have any trouble with other navigation systems, please create an issue with your server responses (see next section).
To use this library, your BMW (or Mini) must have the remote services enabled for your vehicle. You might need to book this in the MyBMW/Mini Connected portal and this might cost some money. In addition to that you need to enable the Remote Services in your infotainment system in the vehicle.
Different models of vehicles and infotainment systems result in different types of attributes provided by the server. So the experience with the library will certainly vary across the different vehicle models.
Data Contributions
If some features do not work for your vehicle, we would need the data returned form the server to analyse this and potentially extend the code. Different models and head unit generations lead to different responses from the server.
If you want to contribute your data, perform the following steps:
# get the latest version of the library
pip3 install --upgrade bimmer_connected
# run the fingerprint function
bimmerconnected fingerprint <username> <password> <region>
This will create a set of log files in the “vehicle_fingerprint” folder. Before sending the data to anyone please check for any personal data such as dealer name or country.
The following attributes are by default replaced with anonymized values:
vin
(Vehicle Identification Number)lat
andlon
(GPS position)licensePlate
information of dealer
Create a new fingerprint data contribution and add the files as attachment to the discussion.
Please add your model and year to the title of the issue, to make it easier to organize. If you know the “chassis code” of your car, you can include that too. (For example, googling “2017 BMW X5” will show a Wikipedia article entitled “BMW X5 (F15)”. F15 is therefore the chassis code of the car.)
Note: We will then use this data as additional test cases. So we will publish (parts of) it (after checking for personal information again) and use this as test cases for our library. If you do not want this, please let us know in advance.
Code Contributions
Contributions are welcome! Please make sure that your code passes the checks in .github/workflows/test.yml
.
We currently test against flake8
, pylint
and our own pytest
suite.
And please add tests where it makes sense. The more the better.
See the contributing guidelines for more details.
Thank you
Thank you to all contributors for your research and contributions! And thanks to everyone who shares the fingerprint data of their vehicles which we use to test the code. A special thanks to @HuChundong, @muxiachuixue, @vividmuse for figuring out how to solve login issues!
This library is basically a best-of of other similar solutions, yet none of them provided a ready to use library with a matching interface to be used in Home Assistant and is available on pypi.
https://gitee.com/ichuixue/bmw_shortcuts / https://www.icloud.com/shortcuts/eb064e89e6b647d2828a404227b91c4a
Thank you for your great software!
License
The bimmer_connected library is licensed under the Apache License 2.0.
Disclaimer
This library is not affiliated with or endorsed by BMW Group.
bimmer_connected
This is a simple library to query and control the status of your BMW or Mini vehicle from the MyBMW portal.
Installation
bimmer_connected
is tested against Python 3.8 or above. Just install the latest release from PyPI
using pip3 install --upgrade bimmer_connected
.
Alternatively, clone the project and execute pip install -e .
to install the current
master
branch.
Note
If you want to connect to a chinese server, you need to install the [china]
extra, e.g. pip3 install --upgrade bimmer_connected[china]
.
Usage
While this library is mainly written to be included in Home Assistant, it can be use on its own.
After installation, execute bimmerconnected
from command line for usage instruction
or see the full CLI documentation.
Please be aware that bimmer_connected
is an async
library when using it in Python code.
The description of the modules
can be found in the module documentation.
Example in an asyncio
event loop
import asyncio
from bimmer_connected.account import MyBMWAccount
from bimmer_connected.api.regions import Regions
async def main():
account = MyBMWAccount(USERNAME, PASSWORD, Regions.REST_OF_WORLD)
await account.get_vehicles()
vehicle = account.get_vehicle(VIN)
print(vehicle.brand, vehicle.name, vehicle.vin)
result = await vehicle.remote_services.trigger_remote_light_flash()
print(result.state)
asyncio.run(main())
Example in non-async code
import asyncio
from bimmer_connected.account import MyBMWAccount
from bimmer_connected.api.regions import Regions
account = MyBMWAccount(USERNAME, PASSWORD, Regions.REST_OF_WORLD)
asyncio.run(account.get_vehicles())
vehicle = account.get_vehicle(VIN)
print(vehicle.brand, vehicle.name, vehicle.vin)
result = asyncio.run(vehicle.remote_services.trigger_remote_light_flash())
print(result.state)
Compatibility
This works with BMW (and Mini) vehicles with a MyBMW account. So far it is tested on vehicles with a ‘MGU’, ‘NBTEvo’, ‘EntryEvo’, ‘NBT’, or ‘EntryNav’ navigation system. If you have any trouble with other navigation systems, please create an issue with your server responses (see next section).
To use this library, your BMW (or Mini) must have the remote services enabled for your vehicle. You might need to book this in the MyBMW/Mini Connected portal and this might cost some money. In addition to that you need to enable the Remote Services in your infotainment system in the vehicle.
Different models of vehicles and infotainment systems result in different types of attributes provided by the server. So the experience with the library will certainly vary across the different vehicle models.
Data Contributions
If some features do not work for your vehicle, we would need the data returned form the server to analyse this and potentially extend the code. Different models and head unit generations lead to different responses from the server.
If you want to contribute your data, perform the following steps:
# get the latest version of the library
pip3 install --upgrade bimmer_connected
# run the fingerprint function
bimmerconnected fingerprint <username> <password> <region>
This will create a set of log files in the “vehicle_fingerprint” folder. Before sending the data to anyone please check for any personal data such as dealer name or country.
The following attributes are by default replaced with anonymized values:
vin
(Vehicle Identification Number)lat
andlon
(GPS position)licensePlate
information of dealer
Create a new fingerprint data contribution and add the files as attachment to the discussion.
Please add your model and year to the title of the issue, to make it easier to organize. If you know the “chassis code” of your car, you can include that too. (For example, googling “2017 BMW X5” will show a Wikipedia article entitled “BMW X5 (F15)”. F15 is therefore the chassis code of the car.)
Note: We will then use this data as additional test cases. So we will publish (parts of) it (after checking for personal information again) and use this as test cases for our library. If you do not want this, please let us know in advance.
Code Contributions
Contributions are welcome! Please make sure that your code passes the checks in .github/workflows/test.yml
.
We currently test against flake8
, pylint
and our own pytest
suite.
And please add tests where it makes sense. The more the better.
See the contributing guidelines for more details.
Thank you
Thank you to all contributors for your research and contributions! And thanks to everyone who shares the fingerprint data of their vehicles which we use to test the code. A special thanks to @HuChundong, @muxiachuixue, @vividmuse for figuring out how to solve login issues!
This library is basically a best-of of other similar solutions, yet none of them provided a ready to use library with a matching interface to be used in Home Assistant and is available on pypi.
https://gitee.com/ichuixue/bmw_shortcuts / https://www.icloud.com/shortcuts/eb064e89e6b647d2828a404227b91c4a
Thank you for your great software!
License
The bimmer_connected library is licensed under the Apache License 2.0.
Disclaimer
This library is not affiliated with or endorsed by BMW Group.
Using fingerprints in Home Assistant
Sometimes it can be useful to load the fingerprints used for our pytest suite in the development of the Home Assistant component.
Set up bimmer_connected
Clone the repository to ~/bimmer_connected
:
git clone https://github.com/bimmerconnected/bimmer_connected.git ~/bimmer_connected
Note
Make sure that you can access this path from inside your Home Assistant virtual environment!
Edit the _get_vehicles()
function in account.py#L370-L392
and add the following code between self._get_oauth_token()
and for brand in CarBrand:
:
from pathlib import Path
files = (Path().home() / "bimmer_connected" / "test" / "responses").rglob("vehicles_v2_*_0.json")
for file in files:
for vehicle_dict in json.load(open(file, 'r')):
# If vehicle already exists, just update it's state
existing_vehicle = self.get_vehicle(vehicle_dict["vin"])
if existing_vehicle:
existing_vehicle.update_state(vehicle_dict)
else:
self._vehicles.append(MyBMWVehicle(self, vehicle_dict))
Set up Home Assistant
If not already done, set up the Home Assistant development environment.
Now start Home Assistant at least once and let all python packages install (hass -c ./config
).
If not already done, set up the BMW Connected Drive Integration in Home Assistant.
Shut down Homeassistant afterwards.
In the Home Assistant virtual environment, install the freshly adjusted version of bimmer_connected
:
pip3 install -e ~/bimmer_connected
Start Home Assistant using hass -c ./config --skip-pip
and see all cars we have fingerprints of + your own cars.
Warning
If --skip-pip
is omitted when starting Home Assistant, the version of bimmer_connected
defined in
homeassistant/components/bmw_connected_drive/manifest.json
will be loaded and the Home Assistant last two steps have to be executed again.
Reverse engineering the MyBMW API
This document should be seen as a help in setting up a working environment to intercept traffic of the MyBMW app. Not every step will be described fully, this guide is rather a summary and list for further reading. It will most likely need adjustments to your specific setup.
The MyBMW app is built with the Flutter framework and needs some additional persuasion to reveal the traffic.
Disclaimer
Note that we are actively disabling important security measures such as SSL/TLS encryption to understand which commands and messages are shared between the MyBMW app and the MyBMW servers.
Also note that there could always be changes to the API or the app itself made by BMW to stop us from understanding what is going on.
Acknowledgement
Most of this document would not exist without the amazing work of Jeroen Becker:
Software & hardware requirements
Note
This document is based on the MyBMW Android app. It should work similarly using iPhones. If possible, please create a PR with more details.
You will need:
A proxy with MITM capabilities such as mitmproxy
A rooted android phone with a version supported by MyBMW (currently Android 6.0 Marshmallow). It could also work using an Android emulator.
Access to your phone using ADB (via USB)
ProxyDroid to forward all traffic to your proxy
Ghidra to find the location to patch out SSL verification
A python environment with frida
frida-android-helper to help installing
frida
on your phone
Finding the location of SSL verification
The following steps are required if the location of the SSL verification function is not known. If it is, please continue with the next section. For more details, please refer to Jeroen Becker’s work.
Get an APK/XAPK of the MyBMW app (from your phone or one of the many download sites). APK names include:
de.bmw.connected.mobile20.cn
(china)de.bmw.connected.mobile20.na
(north america)de.bmw.connected.mobile20.row
(rest of world)
Now extract config.arm64-v8a.apk
or config.armeabi-v7a.apk
from the APK package (depending of your phone’s target architecture).
In Ghidra, load and analyze lib/ARCH/libflutter.so
.
After analyze has finished, go to Search
> For Scalar
and search for value 390
. Find mov r3, #0x186
and jump to it.
Double click on function name on right side to get the hex address and first bytes of the function
Example: 2d e9 f0 4f a3 b0 81 46 50 20 10 70
Preparations on phone
On your phone, add your custom CA certificates to the system store (instructions for emulator, but works on rooted devies in similar fashion). This is required as the login screen is using the default Android WebView component, which again behaves differently from Flutter (or rather, behaves like expected).
Add your local proxy server to your Android system using ProxyDroid.
Disabling SSL verification with frida
Install & upgrade frida-tools
& frida-android-helper
(see requirements).
Make sure that both are on the latest version.
Create a frida hook named hook_flutter_disable_ssl.js
with the following content.
If needed, replace the search pattern and disable adding 0x01
on ARMv8.
function hook_ssl_verify_result(address)
{
Interceptor.attach(address, {
onEnter: function(args) {
console.log("Disabling SSL validation")
},
onLeave: function(retval)
{
console.log("Retval: " + retval)
retval.replace(0x1);
}
});
}
function disablePinning()
{
var m = Process.findModuleByName("libflutter.so");
var pattern = "2d e9 f0 4f a3 b0 81 46 50 20 10 70" // MyBMW 1.5.1 to 1.7.0 (all regions)
var res = Memory.scan(m.base, m.size, pattern, {
onMatch: function(address, size){
console.log('[+] ssl_verify_result found at: ' + address.toString());
// Add 0x01 because it's a THUMB function
// Otherwise, we would get 'Error: unable to intercept function at 0x9906f8ac; please file a bug'
// REQUIRED ON ARMv7 ONLY!!
hook_ssl_verify_result(address.add(0x01));
},
onError: function(reason){
console.log('[!] There was an error scanning memory');
},
onComplete: function()
{
console.log("All done")
}
});
}
setTimeout(disablePinning, 1000)
Connect to your phone via ADB with root permissions.
adb root && adb remount
Update & start frida server on the phone with frida-android-helper
.
fah server update && fah server start
Start the MyBMW app from your computer via frida
(adjust app identifier if needed).
frida -Uf de.bmw.connected.mobile20.row -l .\hook_flutter_disable_ssl.js --no-pause
Now you should be able to capture all traffic between your phone and the MyBMW API.
Using the information in bimmer_connected
If you learn anything by capturing the traffic, please create Issues/Feature Requests or Pull Requests to our repository. Information that should be included contains:
The URL of the endpoint
HTTP headers of your request (DO NOT include Cookie or Authentication headers)
The request payload (if available)
The request response (if available)
If the data contains personal information, please do not delete it but replace it with random data.
Warning
Double check if all information is sanitized and no personal information or authentication data is included.
bimmerconnected
A simple executable to use and test the library.
usage: bimmerconnected [-h]
{status,fingerprint,lightflash,horn,vehiclefinder,chargingsettings,chargingprofile,charge,image,sendpoi,sendpoi_from_address}
...
Positional Arguments
- cmd
Possible choices: status, fingerprint, lightflash, horn, vehiclefinder, chargingsettings, chargingprofile, charge, image, sendpoi, sendpoi_from_address
Sub-commands
status
Get the current status of the vehicle.
bimmerconnected status [-h] [-j]
username password {north_america,china,rest_of_world}
[lat] [lng]
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- lat
(optional) Your current GPS latitude (as float)
- lng
(optional) Your current GPS longitude (as float)
Named Arguments
- -j, --json
Output as JSON only. Removes all other output.
Default: False
fingerprint
Save a vehicle fingerprint.
bimmerconnected fingerprint [-h]
username password
{north_america,china,rest_of_world} [lat] [lng]
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- lat
(optional) Your current GPS latitude (as float)
- lng
(optional) Your current GPS longitude (as float)
lightflash
Flash the vehicle lights.
bimmerconnected lightflash [-h]
username password
{north_america,china,rest_of_world} vin
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- vin
Vehicle Identification Number
horn
Trigger the vehicle horn
bimmerconnected horn [-h]
username password {north_america,china,rest_of_world} vin
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- vin
Vehicle Identification Number
vehiclefinder
Update the vehicle GPS location.
bimmerconnected vehiclefinder [-h]
username password
{north_america,china,rest_of_world} vin [lat]
[lng]
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- vin
Vehicle Identification Number
- lat
(optional) Your current GPS latitude (as float)
- lng
(optional) Your current GPS longitude (as float)
chargingsettings
Set vehicle charging settings.
bimmerconnected chargingsettings [-h] [--target-soc [TARGET_SOC]]
[--ac-limit [AC_LIMIT]]
username password
{north_america,china,rest_of_world} vin
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- vin
Vehicle Identification Number
Named Arguments
- --target-soc
Desired charging target SoC
- --ac-limit
Maximum AC limit
chargingprofile
Set vehicle charging profile.
bimmerconnected chargingprofile [-h]
[--charging-mode [{IMMEDIATE_CHARGING,DELAYED_CHARGING}]]
[--precondition-climate [PRECONDITION_CLIMATE]]
username password
{north_america,china,rest_of_world} vin
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- vin
Vehicle Identification Number
Named Arguments
- --charging-mode
Possible choices: IMMEDIATE_CHARGING, DELAYED_CHARGING
Desired charging mode
- --precondition-climate
Precondition climate on charging windows
charge
Start/stop charging on enabled vehicles.
bimmerconnected charge [-h]
username password {north_america,china,rest_of_world}
vin {start,stop}
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- vin
Vehicle Identification Number
- action
Possible choices: start, stop
image
Download a vehicle image.
bimmerconnected image [-h]
username password {north_america,china,rest_of_world}
vin
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- vin
Vehicle Identification Number
sendpoi
Send a point of interest to the vehicle.
bimmerconnected sendpoi [-h] [--name [NAME]] [--street [STREET]]
[--city [CITY]] [--postalcode [POSTALCODE]]
[--country [COUNTRY]]
username password {north_america,china,rest_of_world}
vin latitude longitude
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- vin
Vehicle Identification Number
- latitude
Latitude of the POI
- longitude
Longitude of the POI
Named Arguments
- --name
Name of the POI
Default: “Sent with ♥ by bimmer_connected”
- --street
(optional, display only) Street & House No. of the POI
- --city
(optional, display only) City of the POI
- --postalcode
(optional, display only) Postal code of the POI
- --country
(optional, display only) Country of the POI
sendpoi_from_address
Send a point of interest parsed from a street address to the vehicle.
bimmerconnected sendpoi_from_address [-h] [-n [NAME]]
[-a ADDRESS [ADDRESS ...]]
username password
{north_america,china,rest_of_world} vin
Positional Arguments
- username
Connected Drive username
- password
Connected Drive password
- region
Possible choices: north_america, china, rest_of_world
Region of the Connected Drive account
- vin
Vehicle Identification Number
Named Arguments
- -n, --name
(optional, display only) Name of the POI
- -a, --address
Address (e.g. ‘Street 17, city, zip, country’)
bimmer_connected.account
Access to a MyBMW account and all vehicles therein.
- class bimmer_connected.account.MyBMWAccount(username: str, password: dataclasses.InitVar[str], region: Regions, config: MyBMWClientConfiguration = None, log_responses: dataclasses.InitVar[bool] = False, observer_position: dataclasses.InitVar[GPSPosition] = None, use_metric_units: dataclasses.InitVar[Optional[bool]] = None)[source]
Create a new connection to the MyBMW web service.
- add_vehicle(vehicle_base: dict, vehicle_state: dict | None, charging_settings: dict | None, fetched_at: datetime | None = None) None [source]
Add or update a vehicle from the API responses.
- config: MyBMWClientConfiguration = None
Optional. If provided, username/password/region are ignored.
- property gcid: str | None
Returns the current GCID.
- static get_stored_responses() List[AnonymizedResponse] [source]
Return responses stored if log_responses was set to True.
- get_vehicle(vin: str) MyBMWVehicle | None [source]
Get vehicle with given VIN.
The search is NOT case sensitive. :param vin: VIN of the vehicle you want to get. :return: Returns None if no vehicle is found.
- log_responses: dataclasses.InitVar[bool] = False
Optional. If set, all responses from the server will be logged to this directory.
- observer_position: dataclasses.InitVar[GPSPosition] = None
Optional. Required for getting a position on older cars.
- password: dataclasses.InitVar[str]
MyBMW password.
- property refresh_token: str | None
Returns the current refresh_token.
- set_observer_position(latitude: float, longitude: float) None [source]
Set the position of the observer for all vehicles.
- set_refresh_token(refresh_token: str, gcid: str | None = None) None [source]
Overwrite the current value of the MyBMW refresh token and GCID (if available).
- property timezone
Returns the current tzinfo.
- use_metric_units: dataclasses.InitVar[Optional[bool]] = None
Deprecated. All returned values are metric units (km, l).
- username: str
MyBMW user name (email) or 86-prefixed phone number (China only).
- property utcdiff
Returns the difference to UTC in minutes.
- vehicles: List[MyBMWVehicle]
bimmer_connected.api
The bimmer_connected.api
module contains helper functions to communicate with the BMW APIs.
bimmer_connected.api.authentication
Authentication management for BMW APIs.
- class bimmer_connected.api.authentication.MyBMWAuthentication(username: str, password: str, region: Regions, access_token: str | None = None, expires_at: datetime | None = None, refresh_token: str | None = None, gcid: str | None = None)[source]
Authentication and Retry Handler for MyBMW API.
- async async_auth_flow(request: Request) AsyncGenerator[Request, Response] [source]
Execute the authentication flow asynchronously.
By default, this defers to .auth_flow(). You should override this method when the authentication scheme does I/O and/or uses concurrency primitives.
- property login_lock: Lock
Make sure that there is a lock in the current event loop.
- class bimmer_connected.api.authentication.MyBMWLoginClient(*args, **kwargs)[source]
Async HTTP client based on httpx.AsyncClient with automated OAuth token refresh.
- class bimmer_connected.api.authentication.MyBMWLoginRetry[source]
httpx.Auth used as workaround to retry & sleep on 429 Too Many Requests.
bimmer_connected.api.client
Generic API management.
- class bimmer_connected.api.client.MyBMWClient(config: MyBMWClientConfiguration, *args, brand: CarBrands | None = None, **kwargs)[source]
Async HTTP client based on httpx.AsyncClient with automated OAuth token refresh.
- class bimmer_connected.api.client.MyBMWClientConfiguration(authentication: MyBMWAuthentication, log_responses: bool | None = False, observer_position: GPSPosition | None = None)[source]
Stores global settings for MyBMWClient.
- authentication: MyBMWAuthentication
- log_responses: bool | None = False
- observer_position: GPSPosition | None = None
bimmer_connected.api.regions
Get the right url for the different countries.
- bimmer_connected.api.regions.get_app_version(region: Regions) str [source]
Get the app version & build number for the region.
- bimmer_connected.api.regions.get_ocp_apim_key(region: Regions) str [source]
Get the authorization for OAuth settings.
- bimmer_connected.api.regions.get_region_from_name(name: str) Regions [source]
Get a region for a string.
This function is not case-sensitive.
- bimmer_connected.api.regions.get_server_url(region: Regions) str [source]
Get the url of the server for the region.
bimmer_connected.api.utils
Utils for bimmer_connected.api.
- bimmer_connected.api.utils.anonymize_data(json_data: List | Dict) List | Dict [source]
Replace parts of the logfiles containing personal information.
- bimmer_connected.api.utils.anonymize_response(response: Response) AnonymizedResponse [source]
Anonymize a responses URL and content.
- bimmer_connected.api.utils.create_s256_code_challenge(code_verifier: str) str [source]
Create S256 code_challenge with the given code_verifier.
- bimmer_connected.api.utils.generate_cn_nonce(username: str) str [source]
Generate a x-login-nonce string.
- bimmer_connected.api.utils.generate_random_base64_string(size: int) str [source]
Generate a random base64 string with size.
- bimmer_connected.api.utils.generate_token(length: int = 30, chars: str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~') str [source]
Generate a random token with given length and characters.
- bimmer_connected.api.utils.get_capture_position(base64_background_img: str) str [source]
Get the position of the capture in the background image.
- bimmer_connected.api.utils.get_correlation_id() Dict[str, str] [source]
Generate corrlation headers.
bimmer_connected.const
URLs for different services and error code mapping.
bimmer_connected.models
Generals models used for bimmer_connected.
- class bimmer_connected.models.AnonymizedResponse(filename: str, content: List | Dict | str | None = None)[source]
An anonymized response.
- content: List | Dict | str | None = None
- filename: str
- class bimmer_connected.models.ChargingSettings(chargingTarget: int | None, acLimitValue: int | None = None)[source]
Charging settings to control the vehicle.
- acLimitValue: int | None = None
- chargingTarget: int | None
- dcLoudness = None
- isUnlockCableActive = None
- class bimmer_connected.models.GPSPosition(latitude: float | None, longitude: float | None)[source]
GPS coordinates.
- latitude: float | None
- longitude: float | None
- exception bimmer_connected.models.MyBMWAuthError[source]
Auth-related error from BMW API (HTTP status codes 401 and 403).
- exception bimmer_connected.models.MyBMWRemoteServiceError[source]
Error when executing remote services.
- class bimmer_connected.models.PointOfInterest(lat: dataclasses.InitVar[float], lon: dataclasses.InitVar[float], name: str | None = 'Sent with ♥ by bimmer_connected', street: dataclasses.InitVar[str] = None, postal_code: dataclasses.InitVar[str] = None, city: dataclasses.InitVar[str] = None, country: dataclasses.InitVar[str] = None, formattedAddress: str | None = None, address: str | None = None, baseCategoryId: str | None = None, phoneNumber: str | None = None, provider: str | None = None, providerId: str | None = None, providerPoiId: str = '', sourceType: str | None = None, type: str | None = None, vehicleCategoryId: str | None = None)[source]
A Point of Interest to be sent to the car.
- address: str | None = None
- baseCategoryId: str | None = None
- city: dataclasses.InitVar[str] = None
- coordinates: GPSPosition
- country: dataclasses.InitVar[str] = None
- entryPoints: List
- formattedAddress: str | None = None
- lat: dataclasses.InitVar[float]
- locationAddress: PointOfInterestAddress | None
- lon: dataclasses.InitVar[float]
- name: str | None = 'Sent with ♥ by bimmer_connected'
- phoneNumber: str | None = None
- postal_code: dataclasses.InitVar[str] = None
- provider: str | None = None
- providerId: str | None = None
- providerPoiId: str = ''
- sourceType: str | None = None
- street: dataclasses.InitVar[str] = None
- type: str | None = None
- vehicleCategoryId: str | None = None
- class bimmer_connected.models.PointOfInterestAddress(street: str | None = None, postalCode: str | None = None, city: str | None = None, country: str | None = None, banchi: str | None = None, chome: str | None = None, countryCode: str | None = None, district: str | None = None, go: str | None = None, houseNumber: str | None = None, region: str | None = None, regionCode: str | None = None, settlement: str | None = None)[source]
Address data of a PointOfInterest.
- banchi: str | None = None
- chome: str | None = None
- city: str | None = None
- country: str | None = None
- countryCode: str | None = None
- district: str | None = None
- go: str | None = None
- houseNumber: str | None = None
- postalCode: str | None = None
- region: str | None = None
- regionCode: str | None = None
- settlement: str | None = None
- street: str | None = None
- class bimmer_connected.models.StrEnum(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
A string enumeration of type (str, Enum). All members are compared via upper(). Defaults to UNKNOWN.
- class bimmer_connected.models.ValueWithUnit(value: int | float | None, unit: str | None)[source]
A value with a corresponding unit.
- unit: str | None
Alias for field number 1
- value: int | float | None
Alias for field number 0
bimmer_connected.utils
General utils and base classes used in the library.
- class bimmer_connected.utils.MyBMWJSONEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)[source]
JSON Encoder that handles data classes, properties and additional data types.
- default(o) str | dict [source]
Implement this method in a subclass such that it returns a serializable object for
o
, or calls the base implementation (to raise aTypeError
).For example, to support arbitrary iterators, you could implement default like this:
def default(self, o): try: iterable = iter(o) except TypeError: pass else: return list(iterable) # Let the base class default method raise the TypeError return JSONEncoder.default(self, o)
- bimmer_connected.utils.get_class_property_names(obj: object)[source]
Return the names of all properties of a class.
- bimmer_connected.utils.log_response_store_to_file(response_store: List[AnonymizedResponse], logfile_path: Path) None [source]
Log all responses to files.
bimmer_connected.vehicle
The bimmer_connected.vehicle
module contains all data & parsers for a vehicle.
bimmer_connected.vehicle.vehicle
Models state and remote services of one vehicle.
- class bimmer_connected.vehicle.vehicle.LscType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Known Values for lsc_type field.
Not really sure, what this value really contains.
- ACTIVATED = 'ACTIVATED'
- NOT_CAPABLE = 'NOT_CAPABLE'
- NOT_SUPPORTED = 'NOT_SUPPORTED'
- UNKNOWN = 'UNKNOWN'
- class bimmer_connected.vehicle.vehicle.MyBMWVehicle(account: MyBMWAccount, vehicle_base: dict, vehicle_state: dict | None = None, charging_settings: dict | None = None, fetched_at: datetime | None = None)[source]
Models state and remote services of one vehicle.
- Parameters:
account – MyBMW account this vehicle belongs to
attributes – attributes of the vehicle as provided by the server
- property available_attributes: List[str]
Get the list of non-drivetrain attributes available for this vehicle.
- static combine_data(account: MyBMWAccount, vehicle_base: dict, vehicle_state: dict | None, charging_settings: dict | None, fetched_at: datetime | None = None) Dict [source]
Combine API responses and additional information to a single dictionary.
- property drive_train: DriveTrainType
Get the type of drive train of the vehicle.
- property drive_train_attributes: List[str]
Get list of attributes available for the drive train of the vehicle.
The list of available attributes depends if on the type of drive train. Some attributes only exist for electric/hybrid vehicles, others only if you have a combustion engine. Depending on the state of the vehicle, some of the attributes might still be None.
- async get_vehicle_image(direction: VehicleViewDirection) bytes [source]
Get a rendered image of the vehicle.
:returns bytes containing the image in PNG format.
- property has_combustion_drivetrain: bool
Return True if vehicle is equipped with an internal combustion engine.
In this case we can get the state of the gas tank.
- property has_electric_drivetrain: bool
Return True if vehicle is equipped with a high voltage battery.
In this case we can get the state of the battery in the state attributes.
- property is_charging_plan_supported: bool
Return True if charging profile is available and can be set via API.
- property is_lsc_enabled: bool
Return True if LastStateCall is enabled (vehicle automatically updates API).
- property is_remote_charge_start_enabled: bool
Return True if charging can be started via the API.
- property is_remote_charge_stop_enabled: bool
Return True if charging can be stop via the API.
- property is_remote_climate_start_enabled: bool
Return True if AC/ventilation can be started via the API.
- property is_remote_climate_stop_enabled: bool
Return True if AC/ventilation can be stopped via the API.
- property is_remote_horn_enabled: bool
Return True if the horn can be activated via the API.
- property is_remote_lights_enabled: bool
Return True if the lights can be activated via the API.
- property is_remote_lock_enabled: bool
Return True if vehicle can be locked via the API.
- property is_remote_sendpoi_enabled: bool
Return True if POIs can be set via the API.
- property is_remote_set_ac_limit_enabled: bool
Return True if AC limit can be set via the API.
- property is_remote_set_target_soc_enabled: bool
Return True if Target SoC can be set via the API.
- property is_remote_unlock_enabled: bool
Return True if POIs can be unlocked via the API.
- property is_vehicle_active: bool
Deprecated, always returns False.
Check if the vehicle is active/moving.
If the vehicle was active/moving at the time of the last status update, current position is not available.
- property is_vehicle_tracking_enabled: bool
Return True if vehicle finder is enabled in vehicle.
- property lsc_type: LscType
Get the lscType of the vehicle.
Not really sure what that value really means. If it is NOT_CAPABLE, that probably means that the vehicle state will not contain much data.
- property mileage: ValueWithUnit
Get the mileage of the vehicle.
- property name: str
Get the name of the vehicle.
- property timestamp: datetime | None
Get the timestamp when the data was recorded.
- update_state(vehicle_base: dict, vehicle_state: dict | None = None, charging_settings: dict | None = None, fetched_at: datetime | None = None) None [source]
Update the state of a vehicle.
- property vin: str
Get the VIN (vehicle identification number) of the vehicle.
- class bimmer_connected.vehicle.vehicle.VehicleViewDirection(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Viewing angles for the vehicle.
This is used to get a rendered image of the vehicle.
- FRONT = 'FrontView'
- FRONTSIDE = 'VehicleStatus'
- SIDE = 'SideViewLeft'
- UNKNOWN = 'UNKNOWN'
bimmer_connected.vehicle.remote_services
Trigger remote services on a vehicle.
- class bimmer_connected.vehicle.remote_services.ExecutionState(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Enumeration of possible states of the execution of a remote service.
- DELIVERED = 'DELIVERED'
- ERROR = 'ERROR'
- EXECUTED = 'EXECUTED'
- IGNORED = 'IGNORED'
- INITIATED = 'INITIATED'
- PENDING = 'PENDING'
- UNKNOWN = 'UNKNOWN'
- class bimmer_connected.vehicle.remote_services.RemoteServiceStatus(response: dict, event_id: str | None = None)[source]
Wraps the status of the execution of a remote service.
- class bimmer_connected.vehicle.remote_services.RemoteServices(vehicle: MyBMWVehicle)[source]
Trigger remote services on a vehicle.
- async trigger_charge_start() RemoteServiceStatus [source]
Trigger the vehicle to start charging.
- async trigger_charge_stop() RemoteServiceStatus [source]
Trigger the vehicle to stop charging.
- async trigger_charging_profile_update(charging_mode: ChargingMode | None = None, precondition_climate: bool | None = None) RemoteServiceStatus [source]
Update the charging profile on the vehicle.
- async trigger_charging_settings_update(target_soc: int | None = None, ac_limit: int | None = None) RemoteServiceStatus [source]
Update the charging settings on the vehicle.
- async trigger_remote_air_conditioning() RemoteServiceStatus [source]
Trigger the air conditioning to start.
- async trigger_remote_air_conditioning_stop() RemoteServiceStatus [source]
Trigger the air conditioning to stop.
- async trigger_remote_door_lock() RemoteServiceStatus [source]
Trigger the vehicle to lock its doors.
- async trigger_remote_door_unlock() RemoteServiceStatus [source]
Trigger the vehicle to unlock its doors.
- async trigger_remote_horn() RemoteServiceStatus [source]
Trigger the vehicle to sound its horn.
- async trigger_remote_light_flash() RemoteServiceStatus [source]
Trigger the vehicle to flash its headlights.
- async trigger_remote_service(service_id: Services, params: Dict | None = None, data: Any = None, refresh: bool = False) RemoteServiceStatus [source]
Trigger a remote service and wait for the result.
- async trigger_remote_vehicle_finder() RemoteServiceStatus [source]
Trigger the vehicle finder.
- async trigger_send_poi(poi: PointOfInterest | Dict) RemoteServiceStatus [source]
Send a PointOfInterest to the vehicle.
- Parameters:
poi – A PointOfInterest containing at least ‘lat’ and ‘lon’ and optionally ‘name’, ‘street’, ‘city’, ‘postalCode’, ‘country’
- class bimmer_connected.vehicle.remote_services.Services(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Enumeration of possible services to be executed.
- AIR_CONDITIONING = 'climate-now'
- CHARGE_START = 'start-charging'
- CHARGE_STOP = 'stop-charging'
- CHARGING_PROFILE = 'CHARGING_PROFILE'
- CHARGING_SETTINGS = 'CHARGING_SETTINGS'
- DOOR_LOCK = 'door-lock'
- DOOR_UNLOCK = 'door-unlock'
- HORN = 'horn-blow'
- LIGHT_FLASH = 'light-flash'
- SEND_POI = 'SEND_POI'
- VEHICLE_FINDER = 'vehicle-finder'
bimmer_connected.vehicle.charging_profile
Models the charging profiles of a vehicle.
- class bimmer_connected.vehicle.charging_profile.ChargingMode(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Charging mode of electric vehicle.
- DELAYED_CHARGING = 'DELAYED_CHARGING'
- IMMEDIATE_CHARGING = 'IMMEDIATE_CHARGING'
- UNKNOWN = 'UNKNOWN'
- class bimmer_connected.vehicle.charging_profile.ChargingPreferences(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Charging preferences of electric vehicle.
- CHARGING_WINDOW = 'CHARGING_WINDOW'
- NO_PRESELECTION = 'NO_PRESELECTION'
- UNKNOWN = 'UNKNOWN'
- class bimmer_connected.vehicle.charging_profile.ChargingProfile(is_pre_entry_climatization_enabled: bool, timer_type: TimerTypes, departure_times: List[DepartureTimer], preferred_charging_window: ChargingWindow, charging_preferences: ChargingPreferences, charging_mode: ChargingMode, ac_current_limit: int | None = None, ac_available_limits: list | None = None, charging_preferences_service_pack: str | None = None)[source]
Models the charging profile of a vehicle.
- ac_available_limits: list | None = None
Available AC limits to be selected.
- ac_current_limit: int | None = None
Returns the ac current limit.
- charging_mode: ChargingMode
Returns the preferred charging mode.
- charging_preferences: ChargingPreferences
Returns the preferred charging preferences.
- charging_preferences_service_pack: str | None = None
Service Pack required for remote service format.
- departure_times: List[DepartureTimer]
List of timers.
- format_for_remote_service() dict [source]
Format current charging profile as base to be sent to remote service.
- is_pre_entry_climatization_enabled: bool
Get status of pre-entry climatization.
- preferred_charging_window: ChargingWindow
Returns the preferred charging window.
- timer_type: TimerTypes
Returns the current timer plan type.
- class bimmer_connected.vehicle.charging_profile.ChargingWindow(window_dict: dict)[source]
A charging window.
- property end_time: time
End of the charging window.
- property start_time: time
Start of the charging window.
- class bimmer_connected.vehicle.charging_profile.DepartureTimer(timer_dict: dict)[source]
A departure timer.
- property action: str | None
What does the timer do.
- property start_time: time | None
Deperture time for this timer.
- property timer_id: int | None
ID of this timer.
- property weekdays: List[str]
Active weekdays for this timer.
bimmer_connected.vehicle.doors_windows
Models the state of a vehicle.
- class bimmer_connected.vehicle.doors_windows.DoorsAndWindows(door_lock_state: ~bimmer_connected.vehicle.doors_windows.LockState = LockState.UNKNOWN, lids: ~typing.List[~bimmer_connected.vehicle.doors_windows.Lid] = <factory>, windows: ~typing.List[~bimmer_connected.vehicle.doors_windows.Window] = <factory>)[source]
Provides an accessible version of properties.doorsAndWindows.
- property all_lids_closed: bool
Check if all lids are closed.
- property all_windows_closed: bool
Check if all windows are closed.
- class bimmer_connected.vehicle.doors_windows.Lid(name: str, state: str)[source]
A lid of the vehicle.
Lids are: Doors + Trunk + Hatch
- property is_closed: bool
Check if the lid is closed.
- name
name of the lid
- class bimmer_connected.vehicle.doors_windows.LidState(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Possible states of the hatch, trunk, doors, windows, sun roof.
- CLOSED = 'CLOSED'
- INTERMEDIATE = 'INTERMEDIATE'
- INVALID = 'INVALID'
- OPEN = 'OPEN'
- OPEN_TILT = 'OPEN_TILT'
- UNKNOWN = 'UNKNOWN'
- class bimmer_connected.vehicle.doors_windows.LockState(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Possible states of the door locks.
- LOCKED = 'LOCKED'
- PARTIALLY_LOCKED = 'PARTIALLY_LOCKED'
- SECURED = 'SECURED'
- SELECTIVE_LOCKED = 'SELECTIVE_LOCKED'
- UNKNOWN = 'UNKNOWN'
- UNLOCKED = 'UNLOCKED'
bimmer_connected.vehicle.fuel_and_battery
Generals models used for bimmer_connected.
- class bimmer_connected.vehicle.fuel_and_battery.ChargingState(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Charging state of electric vehicle.
- CHARGING = 'CHARGING'
- COMPLETE = 'COMPLETE'
- DEFAULT = 'DEFAULT'
- ERROR = 'ERROR'
- FINISHED_FULLY_CHARGED = 'FINISHED_FULLY_CHARGED'
- FINISHED_NOT_FULL = 'FINISHED_NOT_FULL'
- FULLY_CHARGED = 'FULLY_CHARGED'
- INVALID = 'INVALID'
- NOT_CHARGING = 'NOT_CHARGING'
- PLUGGED_IN = 'PLUGGED_IN'
- TARGET_REACHED = 'TARGET_REACHED'
- UNKNOWN = 'UNKNOWN'
- WAITING_FOR_CHARGING = 'WAITING_FOR_CHARGING'
- class bimmer_connected.vehicle.fuel_and_battery.FuelAndBattery(remaining_range_fuel: ValueWithUnit | None = (None, None), remaining_range_electric: ValueWithUnit | None = (None, None), remaining_range_total: ValueWithUnit | None = (None, None), remaining_fuel: ValueWithUnit | None = (None, None), remaining_fuel_percent: int | None = None, remaining_battery_percent: int | None = None, charging_status: ChargingState | None = None, charging_start_time_no_tz: datetime | None = None, charging_end_time: datetime | None = None, is_charger_connected: bool = False, charging_target: int | None = None, account_timezone: timezone = datetime.timezone.utc)[source]
Provides an accessible version of status.FuelAndBattery.
- account_timezone: timezone = datetime.timezone.utc
- charging_end_time: datetime | None = None
The estimated time the vehicle will have finished charging.
- property charging_start_time: datetime | None
The planned time the vehicle will start charging.
- charging_start_time_no_tz: datetime | None = None
The planned time the vehicle will start charging without time zone information.
- charging_status: ChargingState | None = None
Charging state of the vehicle.
- charging_target: int | None = None
State of charging target in percent.
- classmethod from_vehicle_data(vehicle_data: Dict)[source]
Create the class based on vehicle data from API.
- is_charger_connected: bool = False
Get status of the connection
- remaining_battery_percent: int | None = None
State of charge of the high voltage battery in percent.
- remaining_fuel: ValueWithUnit | None = (None, None)
Get the remaining fuel of the vehicle.
- remaining_fuel_percent: int | None = None
State of charge of the high voltage battery in percent.
- remaining_range_electric: ValueWithUnit | None = (None, None)
Get the remaining range of the vehicle on electricity.
- remaining_range_fuel: ValueWithUnit | None = (None, None)
Get the remaining range of the vehicle on fuel.
- remaining_range_total: ValueWithUnit | None = (None, None)
Get the total remaining range of the vehicle (fuel + electricity, if available).
bimmer_connected.vehicle.location
Generals models used for bimmer_connected.
- class bimmer_connected.vehicle.location.VehicleLocation(location: GPSPosition | None = None, heading: int | None = None, vehicle_update_timestamp: datetime | None = None, account_region: Regions | None = None, remote_service_position: Dict | None = None)[source]
The current position of a vehicle.
- classmethod from_vehicle_data(vehicle_data: Dict)[source]
Create the class based on vehicle data from API.
- heading: int | None = None
The last known heading/direction of the vehicle.
- location: GPSPosition | None = None
The last known position of the vehicle.
- remote_service_position: Dict | None = None
- set_remote_service_position(remote_service_dict: Dict)[source]
Store remote service position returned from vehicle finder service.
- vehicle_update_timestamp: datetime | None = None
bimmer_connected.vehicle.reports
Models the state of a vehicle.
- class bimmer_connected.vehicle.reports.CheckControlMessage(description_short: str, description_long: str | None, state: CheckControlStatus)[source]
Check control message sent from the server.
- description_long: str | None
- description_short: str
- classmethod from_api_entry(type: str, severity: str, longDescription: str | None = None, **kwargs)[source]
Parse a check control entry from the API format to CheckControlMessage.
- state: CheckControlStatus
- class bimmer_connected.vehicle.reports.CheckControlMessageReport(messages: ~typing.List[~bimmer_connected.vehicle.reports.CheckControlMessage] = <factory>, has_check_control_messages: bool = False)[source]
Parse and summarizes check control messages (e.g. low tire pressure).
- has_check_control_messages: bool = False
Indicate if check control messages are present.
- messages: List[CheckControlMessage]
List of check control messages.
- class bimmer_connected.vehicle.reports.CheckControlStatus(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Status of the condition based services.
- CRITICAL = 'CRITICAL'
- HIGH = 'HIGH'
- LOW = 'LOW'
- MEDIUM = 'MEDIUM'
- OK = 'OK'
- UNKNOWN = 'UNKNOWN'
- class bimmer_connected.vehicle.reports.ConditionBasedService(service_type: str, state: ConditionBasedServiceStatus, due_date: datetime | None, due_distance: ValueWithUnit)[source]
Entry in the list of condition based services.
- due_date: datetime | None
- due_distance: ValueWithUnit
- classmethod from_api_entry(type: str, status: str, dateTime: str | None = None, mileage: int | None = None, **kwargs)[source]
Parse a condition based service entry from the API format to ConditionBasedService.
- service_type: str
- state: ConditionBasedServiceStatus
- class bimmer_connected.vehicle.reports.ConditionBasedServiceReport(messages: ~typing.List[~bimmer_connected.vehicle.reports.ConditionBasedService] = <factory>, is_service_required: bool = False)[source]
Parse and summarizes condition based services (e.g. next oil service).
- is_service_required: bool = False
Indicate if a service is required.
- messages: List[ConditionBasedService]
List of the condition based services.
- class bimmer_connected.vehicle.reports.ConditionBasedServiceStatus(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Status of the condition based services.
- OK = 'OK'
- OVERDUE = 'OVERDUE'
- PENDING = 'PENDING'
- UNKNOWN = 'UNKNOWN'
- class bimmer_connected.vehicle.reports.Headunit(idrive_version: str = '', headunit_type: str = '', software_version: str = '')[source]
Parse and summarizes headunit hard/software versions.
- headunit_type: str = ''
Type of headunit.
- idrive_version: str = ''
IDRIVE generation.
- software_version: str = ''
Current software revision of vehicle