Skip to main content

Python client for BlueCurrent charge points.

Project description

pybluecurrent

Python client for BlueCurrent charge points.

GitHub Workflow Status PyPI PyPI - License PyPI - Downloads

Usage

Using the client is as simple as:

from pybluecurrent import BlueCurrentClient

client = BlueCurrentClient("your_username", "your_secret_password")

async with client:
    charge_points = await client.get_charge_points()
    transactions = await client.get_transactions(charge_points[0]["evse_id"])

Methods

The BlueCurrentClient exposes the following methods:

Connection

The client can only be used when the websocket client is connected. For example:

client = BlueCurrentClient("your_username", "your_secret_password")
async with client:
    result = await client.get_account()

Entering the async context will automatically login.

Instead of a username and password, you can authenticate with an API token:

client = BlueCurrentClient(api_token="your_api_token")

Retrieve or rotate the token with get_api_token and generate_api_token, or from the BlueCurrent website.

get_account - Get your account information.

async def get_account(self) -> dict[str, bool | str]
Returns

A dictionary describing your account:

{
    "full_name": "Your Full Name",
    "email": "your@email.address",
    "login": "your@email.address",
    "should_reset_password": False,
    "developer_mode_enabled": False,
    "tel": "",
    "marketing_target": "bluecurrent",
    "first_login_app": datetime(2020, 1, 15, 13, 33, 52),
    "hubspot_user_identity": "a_very_long_string"
}

get_api_token - Get your API token.

async def get_api_token(self) -> str

Returns the API token (home automation key) for your account. This token can be used to authenticate instead of a username and password, by constructing the client with BlueCurrentClient(api_token=...).

generate_api_token - Generate a new API token.

async def generate_api_token(self) -> str

Generates a new API token and returns it. Warning: this rotates the token — any previously issued token is invalidated, which will break anything still using the old one (for example a Home Assistant integration).

get_charge_cards - Get your charge cards.

async def get_charge_cards(self) -> list[dict[str, date | int | str | None]]
Returns

A list of dictionaries, each representing a charge card:

{
    "uid": "A1B2C3D4E5F6",
    "id": "NL-ABC-123456-0",
    "name": "My Charge Cards",
    "customer_name": "Your Name",
    "valid": 1,
    "date_created": date(2023, 6, 27),
    "date_modified": date(2023, 7, 11),
    "date_became_invalid": None
}

get_charge_points - Get your charge points.

async def get_charge_points(self) -> list[dict[str, bool | dict | str]]
Returns

A list of dictionaries, each representing a charge card:

{
    "evse_id": "BCU123456",
    "name": "",
    "model_type": "H:MOVE-C32T2",
    "chargepoint_type": "HIDDEN",
    "is_cable": True,
    "public_charging": {"value": False, "permission": "write"},
                    "default_card": {"uid": "A1B2C3D4E5F6", "id": "NL-ABC-123456-0", "name": "Your Card",
                     "customer_name": "Your Name", "valid": 1},
    "preferred_card": {"uid": "A1B2C3D4E5F6", "id": "NL-ABC-123456-0", "name": "Your Card",
                       "customer_name": "Your Name", "valid": 1},
    "plug_and_charge_card": {"uid": "A1B2C3D4E5F6", "id": "NL-ABC-123456-0", "name": "Your Card",
                             "customer_name": "Your Name", "valid": 1},
    "tariff":  {"tariff_id","NLBCUT58", "price_ex_vat": 0.2, "start_price_ex_vat": 0, "price_in_vat": 0.242,
                "start_price_in_vat": 0, "currency": "EUR", "vat_percentage": 21},
    "plug_and_charge_notification": False,
    "plug_and_charge": {"value": True, "permission": "write"},
    "led_interaction": {"value": False, "permission": "read"},
    "publish_location": {"value": False, "permission": "write"},
    "smart_charging": True,
    "smart_charging_dynamic": True,
    "activity": "available",
    "location": {"x_coord": 50.1234, "y_coord": 5.01234, "street": "Europalaan", "housenumber": "100",
                 "zipcode": "3526KS", "city": "Utrecht", "country": "NL"},
    "delayed_charging": {"value": False, "permission": "write", "start_time": "23:00", "end_time": "07:00",
                         "selected_days": [1, 2, 3, 4, 5]},
    "price_based_charging": {"value": False, "permission": "write"}
}

get_charge_point_settings - Get the settings of a charge point.

All the information returned by this endpoint is already included in the response of get_charge_points.

async def get_charge_point_settings(self, evse_id: str) -> dict[str, bool | dict[str, Any] | str]
Arguments
  • evse_id: The ID of the charge point.
Returns

A dictionary describing the settings:

{
    "evse_id": "BCU123456",
    "plug_and_charge": {"value": True, "permission": "write"},
    "public_charging": {"value": False, "permission": "write"},
    "default_card": {"uid": "A1B2C3D4E5F6", "id": "NL-ABC-123456-0", "name": "Your Card",
                     "customer_name": "Your Name", "valid": 1},
    "preferred_card": {"uid": "A1B2C3D4E5F6", "id": "NL-ABC-123456-0", "name": "Your Card",
                       "customer_name": "Your Name", "valid": 1},
    "plug_and_charge_card": {"uid": "A1B2C3D4E5F6", "id": "NL-ABC-123456-0", "name": "Your Card",
                             "customer_name": "Your Name", "valid": 1},
    "smart_charging": True,
    "smart_charging_dynamic": True,
    "model_type": "H:MOVE-C32T2",
    "is_cable": True,
    "chargepoint_type": "HIDDEN",
    "plug_and_charge_notification": False,
    "led_intensity": {"value": 0, "permission": "none"},
    "led_interaction": {"value": False, "permission": "none"},
    "delayed_charging": {"value": False, "permission": "write", "start_time": "23:00", "end_time": "07:00",
                         "selected_days": [1, 2, 3, 4, 5]},
    "price_based_charging": {"value": True, "permission": "write", "expected_leave_time": "07:00",
                             "expected_kwh": 25, "minimum_kwh": 10}
}

get_grid_status - Get the grid status associated to a charge point.

async def get_grid_status(self, evse_id: str) -> dict[str, int | str]
Arguments
  • evse_id: The ID of the charge point.
Returns

A dictionary describing the actual grid current and maximum current in amps:

{
    "id": "GRID-BCU123456",
    "grid_actual_p1": 1,
    "grid_actual_p2": 2,
    "grid_actual_p3": 3,
    "grid_max_install": 25,
    "grid_max_reserved": 25
}

get_sustainability_status - Get statistics on the sustainability of all your charge points.

async def get_sustainability_status(self) -> dict[str, float | int]
Returns

A dictionary with two keys: {"trees": 1, "co2": 12.345}

set_plug_and_charge_charge_card - Set the charge card for plug-and-charge

async def set_plug_and_charge_charge_card(self, evse_id: str, uid: str | None = None) -> None

Sets the plug-and-charge card for the charge point. The uid must be a uid of one of your charge cards (see get_charge_cards) or None to use no charge card.

set_status - Enable or disable a charge point.

async def set_status(self, evse_id: str, enabled: bool) -> None
Arguments
  • evse_id: The ID of the charge point.
  • enabled: Boolean that indicates the desired status.

get_charge_point_status - Get the status of a charge point.

async def get_charge_point_status(self, evse_id: str) -> dict[str, datetime | float | int | str | None]
Arguments
  • evse_id: The ID of the charge point.
Returns

A dictionary with the chargepoint status:

{
    "actual_p1": 0,
    "actual_p2": 0,
    "actual_p3": 0,
    "activity": "available",
    "actual_v1": 0,
    "actual_v2": 0,
    "actual_v3": 0,
    "actual_kwh": 0,
    "boosting": False,
    "max_usage": 20,
    "smartcharging_max_usage": 6,
    "max_offline": 10,
    "offline_since": "",
    "start_datetime": datetime(2023, 7, 24, 15, 25, 33),
    "stop_datetime": datetime(2023, 7, 26, 7, 48, 40),
    "total_cost": 9.93,
    "vehicle_status": "A",
    "evse_id": "BCU123456",
}

set_delayed_charging - Enable or disable delayed charging.

async def set_delayed_charging(self, evse_id: str, enabled: bool) -> None

While delayed charging is enabled, the charge point only charges within the window configured with set_delayed_charging_schedule, and delays charging outside of it. A charge point has at most one smart charging profile active, so enabling delayed charging disables any other profile.

Arguments
  • evse_id: The ID of the charge point.
  • enabled: Boolean that indicates whether delayed charging should be enabled.

set_delayed_charging_schedule - Set the delayed charging schedule.

async def set_delayed_charging_schedule(
    self,
    evse_id: str,
    start_time: time | str,
    end_time: time | str,
    days: Iterable[Weekday | int | str],
) -> None

Sets the window in which the charge point may charge on the selected days. The window may span midnight. It is only applied while delayed charging is enabled with set_delayed_charging.

from datetime import time
from pybluecurrent import Weekday

await client.set_delayed_charging_schedule(
    "BCU123456", start_time=time(23, 0), end_time=time(7, 0), days=[Weekday.MONDAY, "tu", 3]
)
Arguments
  • evse_id: The ID of the charge point.
  • start_time: The time at which charging may start, as a time or a "HH:MM" string.
  • end_time: The time at which charging must stop, as a time or a "HH:MM" string.
  • days: The days on which the schedule applies. Each day may be a pybluecurrent.Weekday, an isoweekday number (1 for Monday through 7 for Sunday), or a weekday name such as "monday" or "mo".

The schedule is read back from the delayed_charging key of get_charge_point_settings.

set_price_based_charging - Enable or disable price-based charging.

async def set_price_based_charging(self, evse_id: str, enabled: bool) -> None

While price-based charging is enabled, the charge point charges during the cheapest hours before the expected departure time, as configured with set_price_based_charging_settings. A charge point has at most one smart charging profile active, so enabling price-based charging disables any other profile.

Arguments
  • evse_id: The ID of the charge point.
  • enabled: Boolean that indicates whether price-based charging should be enabled.

set_price_based_charging_settings - Set the price-based charging settings.

async def set_price_based_charging_settings(
    self,
    evse_id: str,
    expected_departure_time: time | str,
    expected_kwh: float,
    minimum_kwh: float,
) -> None

Configures how much energy to charge before departure. Only applied while price-based charging is enabled with set_price_based_charging.

Arguments
  • evse_id: The ID of the charge point.
  • expected_departure_time: The time the vehicle is expected to leave, as a time or a "HH:MM" string. Note this is read back as expected_leave_time from the price_based_charging settings.
  • expected_kwh: The amount of energy, in kWh, expected to be charged before departure.
  • minimum_kwh: The amount of energy, in kWh, to charge immediately regardless of price.

The settings are read back from the price_based_charging key of get_charge_point_settings.

boost - Charge now, overriding the active smart charging profile.

async def boost(self, evse_id: str) -> None

Starts charging immediately, overriding whichever smart charging profile is currently delaying charging — delayed charging or price-based charging — for the ongoing session. The override cannot be undone. While it is active, get_charge_point_status reports "boosting": True. Raises ValueError if no smart charging profile is active.

Arguments
  • evse_id: The ID of the charge point.

get_contracts - Get your contracts.

async def get_contracts(self) -> list[dict[str, str]]
Returns

A list of dictionaries, each representing a contract:

[
    {
        "contract_id": "BCU12345678",
        "contact_email": "your@email.address",
        "subscription_type": "BASIS",
        "beneficiary_name": "Your Name",
        "iban_beneficiary": "NL00ABCD0123456789"
    }
]

get_grids - Get your grid connections.

async def get_grids(self) -> list[dict[str, bool | dict[str, str] | str]]
Returns

A list of dictionaries, each representing a grid:

[
    {
        "address": {"street": "Street Name", "housenumber": "1", "postal_code": "1234AB",
                    "city": "Amsterdam", "country": "NL", "region": ""},
        "smart_charging": True,
        "id": "GRID-BCU123456"
    }
]

get_transactions - Get a list of transactions.

async def get_transactions(
        self, evse_id: str, newest_first: bool = True, page: int = 1
    ) -> dict[str, int | list[dict[str, Any]]]
Arguments
  • evse_id: The ID of the charge point.
  • newest_first: If True, start with the most recent transaction. Defaults to True.
  • page: Page number to get. Defaults to 1.
Returns

A dictionary like this:

{
    "current_page": 1,
    "next_page": 2,  # This is None when there is no next page.
    "max_per_page": 25,
    "total_pages": 8,
    "transactions: [
        {
            "transaction_id": 12345678,
            "chargepoint_id": "BCU123456",
            "chargepoint_type": "HIDDEN",
            "evse_name": "Charge Point Name",
            "started_at": datetime(2023, 7, 1, 12, 34, 56),
            "end_time": datetime(2023, 7, 1, 14, 0, 0),
            "kwh": 12.34,
            "card_id": "NL-ABC-123456-0",
            "card_name": "Card Name",
            "total_costs": 5.97,
            "total_costs_ex_vat": 4.93,
            "vat": 21,
            "currency": "EUR"
        },
        ...
    ]
}

iterate_transactions - Iterate through your transactions

async def iterate_transactions(self, evse_id: str, newest_first: bool = True) -> AsyncIterable[dict[str, Any]]
Arguments
  • evse_id: The ID of the charge point.
  • newest_first: If True, start with the most recent transaction. Defaults to True.
Returns

An iterable of dictionaries describing the transactions. Each dictionary looks like this:

{
    "transaction_id": 12345678,
    "chargepoint_id": "BCU123456",
    "chargepoint_type": "HIDDEN",
    "evse_name": "Charge Point Name",
    "started_at": datetime(2023, 7, 1, 12, 34, 56),
    "end_time": datetime(2023, 7, 1, 14, 0, 0),
    "kwh": 12.34,
    "card_id": "NL-ABC-123456-0",
    "card_name": "Card Name",
    "total_costs": 5.97,
    "total_costs_ex_vat": 4.93,
    "vat": 21,
    "currency": "EUR"
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pybluecurrent-0.3.0rc1.tar.gz (35.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pybluecurrent-0.3.0rc1-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

Details for the file pybluecurrent-0.3.0rc1.tar.gz.

File metadata

  • Download URL: pybluecurrent-0.3.0rc1.tar.gz
  • Upload date:
  • Size: 35.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pybluecurrent-0.3.0rc1.tar.gz
Algorithm Hash digest
SHA256 3b1eafe3d7375c903a50214b11f388e0be5d4e2b2103b91290fc54994ac62143
MD5 803998bd8a5b5d5c26ac0684a5914e39
BLAKE2b-256 1cc1779161f33794b7ee6dc91fb12c820c50575a61587b630b908048eb65fce7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pybluecurrent-0.3.0rc1.tar.gz:

Publisher: publish.yaml on rogiervandergeer/pybluecurrent

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pybluecurrent-0.3.0rc1-py3-none-any.whl.

File metadata

File hashes

Hashes for pybluecurrent-0.3.0rc1-py3-none-any.whl
Algorithm Hash digest
SHA256 867a9e5451bd127f63ebe5358c589dadf1f4e0fecc13fabd18061c09af7ab772
MD5 b186cb9d5ff73bd9dbd9e040e7f6afb6
BLAKE2b-256 e143c26cf52a7c310e9673ad026c0ea0dc813fc64bf6dc3599e2cc576e4e9b5d

See more details on using hashes here.

Provenance

The following attestation bundles were made for pybluecurrent-0.3.0rc1-py3-none-any.whl:

Publisher: publish.yaml on rogiervandergeer/pybluecurrent

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page