CarConnectivity Python API

repository·main·Indexed 42 days ago

https://github.com/tillsteinbach/carconnectivity

A Python library for retrieving information from car connectivity services and manufacturer platforms. It features a modular architecture with connector plugins for brands like Audi, Volkswagen, Skoda, and Lucid Motors, and service plugins for integration with MQTT, Home Assistant, Apple HomeKit, and WebUI.

Tokens
11.2K
Snippets
46
Records
56
Agent score
53%

What's inside CarConnectivity

  1. Define geofences for location-based services

    main

    The geofences section allows you to predefine geofences used for location-based services. Each geofence entry requires a name, latitude, longitude, and radius (in meters).

    You can optionally provide:

    • location: Detailed address information including display_name, house_number, road, neighbourhood, city, postcode, state, and country.
    • charging_station: Data about a charging station at that location, including name, operator_id, operator_name, address, max_power (in kW), and num_spots.
    "geofences": [
        {
            "name": "Home",
            "latitude": 53.625193,
            "longitude": 10.100695,
            "radius": 40,
            "location": {
                "display_name": "Home",
                "city": "Berlin",
                "country": "Deutschland"
            },
            "charging_station": {
                "name": "Home Wallbox",
                "operator_id": "myhome",
                "max_power": 11.0
            }
        }
    ]
  2. How CarConnectivity's plugin architecture works

    main

    CarConnectivity uses a two-tier plugin architecture to provide access to vehicle data and integrate with external services:

    1. Connector Plugins: These provide the actual connection to specific car brands (e.g., Audi, Volkswagen, Skoda). You must install and configure a connector plugin for the specific brand you wish to access.
    2. Service/Protocol Plugins: These enable connectivity to other services or protocols using the data provided by the connectors (e.g., MQTT, Home Assistant, Apple HomeKit, or a WebUI).

    To use the library, you typically install a connector for your car brand and one or more plugins to expose that data to your preferred interface or automation system.

  3. Use the initialization section to predefine vehicle data

    main

    The initialization section allows you to predefine data that is not supplied by connectors. This can improve user experience by ensuring additional data is available immediately. If a connector later provides this same data, the connector's data will override the predefined values.

    You can define data per VIN (Vehicle Identification Number) within the garage object. Supported data includes:

    • range_wltp: Can be provided as an object with val and uni (e.g., {"val": 550, "uni": "km"}) or as a raw number (assumed to be in km).
    • battery: Includes total_capacity and available_capacity (in kWh).
    • fuel_tank: Includes available_capacity (for hybrid/combustion vehicles).
    • drives: Supports primary and secondary drive definitions.
    "initialization": {
        "garage": {
            "TMBLJ9NY8SF008152": {
                "drives": {
                    "primary": {
                        "range_wltp": {"val": 550, "uni": "km"},
                        "battery": {
                            "total_capacity": 82.0,
                            "available_capacity": 77.0
                        }
                    }
                }
            }
        }
    }
  4. Configure CarConnectivity using a JSON file

    main

    CarConnectivity is configured via a .json file. The structure requires a top-level carConnectivity object containing a log_level, a list of connectors, and a list of plugins.

    Each item in the connectors and plugins arrays must include:

    • type: A string identifying the specific connector or plugin.
    • config: An object containing the configuration parameters specific to that type.

    Note that while you can set a global log_level in the carConnectivity section, individual connectors and plugins can override this with their own specific log levels.

    {
        "carConnectivity": {
            "log_level": "error",
            "connectors": [
                {
                    "type": "skoda",
                    "config": {
                        "interval": 600,
                        "username": "test@test.de",
                        "password": "testpassword123"
                    }
                }
            ],
            "plugins": [
                {
                    "type": "database",
                    "config": {
                        "db_url": "sqlite:///carconnectivity.db"
                    }
                }
            ]
        }
    }
  5. Implement a custom LocationService

    main

    To add new location-based capabilities to the car connectivity ecosystem, you must extend the LocationService abstract base class. A concrete implementation of LocationService is required to provide actual logic for resolving coordinates, finding gas stations, and finding charging stations.

    When implementing a subclass, you must provide implementations for the following methods, otherwise they will raise NotImplementedError:

    • get_types(): Returns a list of (ServiceType, int) tuples representing the supported connector types and their associated priorities.
    • location_from_lat_lon(latitude, longitude, location): Converts raw latitude and longitude into a Location object.
    • gas_station_from_lat_lon(latitude, longitude, radius, location): Searches for the nearest gas station within a specified radius (in meters).
    • charging_station_from_lat_lon(latitude, longitude, radius, charging_station): Searches for the nearest charging station within a specified radius (in meters).
  6. Configure connectors in carconnectivity.json

    main

    To use specific car brand connectors, you must define them in a carconnectivity.json configuration file. Each connector is defined within the carConnectivity.connectors array. You specify the type (matching the connector name) and a config object containing the credentials or settings required by that specific connector.

    Note: Detailed configuration options (like username or password) vary by connector; refer to the specific connector's README for its required schema.

    {
        "carConnectivity": {
            "connectors": [
                {
                    "type": "volkswagen",
                    "config": {
                        "username": "test@test.de",
                        "password": "testpassword123"
                    }
                },
                {
                    "type": "skoda",
                    "config": {
                        "username": "test@test.de",
                        "password": "testpassword123"
                    }
                }
            ]
        }
    }
  7. Implement a new service by extending BaseService

    main

    To implement a new service in CarConnectivity, you must create a subclass of BaseService. A service is a component that provides specific functionality (like location or amenity lookup) for data processing.

    When implementing a subclass, you must override the get_types() method to define the specific ServiceTypes the service provides and their associated priorities.

    from carconnectivity_services.base.service import BaseService, ServiceType
    import logging
    
    class MyCustomService(BaseService):
        def get_types(self) -> list[tuple[ServiceType, int]]:
            # Return a list of tuples containing the ServiceType and its priority (int)
            return [(ServiceType.LOCATION_REVERSE, 1)]
  8. How the Observable pattern works in CarConnectivity

    main

    The Observable class implements a publish-subscribe pattern used to react to changes in vehicle data. Objects inheriting from or using Observable can maintain a list of observers that are notified when specific ObserverEvent flags are triggered.

    Key Concepts:

    • Observers: Callables that accept two arguments: element (the Observable instance) and flags (the ObserverEvent that triggered the notification).
    • Events (ObserverEvent): A bitwise flag indicating what happened (e.g., a value changed, or an object was enabled/disabled).
    • Priority (ObserverPriority): Observers can be registered with different priority levels. When notifying, observers are triggered in order of their priority.
    • Transactions: You can register observers to be notified only at the end of a transaction using the on_transaction_end parameter. Use transaction_end() to trigger these notifications.
    • Delayed Notifications: If delay_notifications is set to True, calls to notify() will buffer the flags instead of immediately calling observers. Setting delay_notifications = False will trigger all buffered notifications.
    from carconnectivity.observable import Observable, ObserverEvent, ObserverPriority
    
    class MyData(Observable):
        def update_value(self, new_val):
            # ... logic to update value ...
            self.notify(ObserverEvent.VALUE_CHANGED)
    
    # Usage
    data = MyData()
    
    def my_callback(element, flags):
        print(f"Event received: {flags}")
    
    data.add_observer(my_callback, ObserverEvent.VALUE_CHANGED, priority=ObserverPriority.USER_HIGH)
    data.update_value(10)
  9. Reference of supported car brand connectors

    main

    The following connector plugins are available for different car brands:

    BrandConnector
    AudiCarConnectivity-connector-audi
    Lucid MotorsCarConnectivity-connector-lucid
    Seat/CupraCarConnectivity-connector-seatcupra
    SkodaCarConnectivity-connector-skoda
    TronityCarConnectivity-connector-tronity
    VolkswagenCarConnectivity-connector-volkswagen
    Volkswagen (North America)CarConnectivity-connector-volkswagen-na
    Volkswagen Group EU Data ActCarConnectivity-connector-vw-eu-data-act
  10. Reference connector configuration options

    main

    Connector-specific configuration options (such as interval, username, and password) are defined within the config block of each connector entry. Because options vary by brand, you must refer to the specific documentation for the connector type you are using.

    Supported connector types include:

    • skoda
    • volkswagen
    • seatcupra
    • tronity
  11. Reference of supported service plugins

    main

    The following plugins are available to integrate vehicle data with other services or protocols:

    Service/ProtocolPlugin
    WebUICarConnectivity-plugin-webui
    MQTTCarConnectivity-plugin-mqtt
    Home Assistant MQTTCarConnectivity-plugin-mqtt_homeassistant
    A Better Routeplanner (ABRP)CarConnectivity-plugin-abrp
    Apple HomekitCarConnectivity-plugin-homekit
    CampermodeCarConnectivity-plugin-campermode
  12. Handle multiple retrieval errors with MultipleRetrievalError

    main

    When multiple adapters fail simultaneously, MultipleRetrievalError is raised. You can iterate through the errors attribute to inspect each individual RetrievalError that occurred.

    from carconnectivity.errors import MultipleRetrievalError
    
    try:
        # Perform operation involving multiple adapters
        pass
    except MultipleRetrievalError as e:
        print(f"Multiple errors occurred: {len(e.errors)} errors found.")
        for error in e.errors:
            print(f"- Individual error: {error}")