Python client for BlueCurrent charge points.
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 = client.get_transactions(charge_points[0]["evse_id"])
BlueCurrent exposes two APIs, a synchronous REST API as well as an asynchronous Websocket API.
As a result, the BlueCurrentClient
also exposes synchronous as well as asynchronous methods:
The async methods 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.
async def get_account(self) -> dict[str, bool | str]
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": date(2020, 1, 1),
"hubspot_user_identity": "a_very_long_string"
}
async def get_charge_cards(self) -> list[dict[str, date | int | str | None]]
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
}
async def get_charge_points(self) -> list[dict[str, bool | dict | str]]
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": "none"}
}
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]
evse_id
: The ID of the charge point.
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"}
}
async def get_grid_status(self, evse_id: str) -> dict[str, int | str]
evse_id
: The ID of the charge point.
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
}
async def get_sustainability_status(self) -> dict[str, float | int]
A dictionary with two keys: {"trees": 1, "co2": 12.345}
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.
async def set_status(self, evse_id: str, enabled: bool) -> None
evse_id
: The ID of the charge point.enabled
: Boolean that indicates the desired status.
def login(self) -> None
This method does not do anything if the client is already logged in. Connection to the websocket api (async with client) automatically logs in the client, so this endpoint is not needed when using the async API.
def get_charge_point_status(self, evse_id: str) -> dict[str, datetime | float | int | str | None]
evse_id
: The ID of the charge point.
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,
"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",
}
def get_contracts(self) -> list[dict[str, str]]
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"
}
]
def get_grids(self) -> list[dict[str, bool | dict[str, str] | str]]
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"
}
]
def get_transactions(
self, evse_id: str, newest_first: bool = True, page: int = 1
) -> dict[str, int | list[dict[str, Any]]]
evse_id
: The ID of the charge point.newest_first
: IfTrue
, start with the most recent transaction. Defaults toTrue
.page
: Page number to get. Defaults to1
.
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"
},
...
]
}
def iterate_transactions(self, evse_id: str, newest_first: bool = True) -> Iterable[dict[str, Any]]
evse_id
: The ID of the charge point.newest_first
: IfTrue
, start with the most recent transaction. Defaults toTrue
.
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"
}