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.0rc2.tar.gz (45.1 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.0rc2-py3-none-any.whl (21.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pybluecurrent-0.3.0rc2.tar.gz
  • Upload date:
  • Size: 45.1 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.0rc2.tar.gz
Algorithm Hash digest
SHA256 8d437eb06f0724c1f563af9c24760ca868f29cc87d9d1832b820912c06873577
MD5 debf8c095890ab1d5b7aabdd59e5d841
BLAKE2b-256 2ac562ec23051a3203e58ed7a4ee2359e5c07f7883dc534c0e3d39e9686d606a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pybluecurrent-0.3.0rc2.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.0rc2-py3-none-any.whl.

File metadata

File hashes

Hashes for pybluecurrent-0.3.0rc2-py3-none-any.whl
Algorithm Hash digest
SHA256 198c545736f1aea5d5b274774ac37dc2892c15f6fdb5542e1cd0264e15c13602
MD5 6e468520429ab466d6acf704d05b34cc
BLAKE2b-256 f6ee26d22a0114f2e3fad33fb4f96fc4fe42d5b61145b2db62bb58537291b022

See more details on using hashes here.

Provenance

The following attestation bundles were made for pybluecurrent-0.3.0rc2-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