python-chargepoint 1.9.2__tar.gz → 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python_chargepoint-2.0.0/PKG-INFO +366 -0
- python_chargepoint-2.0.0/README.md +344 -0
- {python_chargepoint-1.9.2 → python_chargepoint-2.0.0}/pyproject.toml +22 -8
- python_chargepoint-2.0.0/python_chargepoint/__main__.py +613 -0
- python_chargepoint-2.0.0/python_chargepoint/client.py +580 -0
- python_chargepoint-2.0.0/python_chargepoint/constants.py +7 -0
- python_chargepoint-2.0.0/python_chargepoint/exceptions.py +51 -0
- python_chargepoint-2.0.0/python_chargepoint/global_config.py +79 -0
- python_chargepoint-2.0.0/python_chargepoint/session.py +295 -0
- python_chargepoint-2.0.0/python_chargepoint/types.py +419 -0
- python_chargepoint-1.9.2/PKG-INFO +0 -204
- python_chargepoint-1.9.2/README.md +0 -186
- python_chargepoint-1.9.2/python_chargepoint/__main__.py +0 -84
- python_chargepoint-1.9.2/python_chargepoint/client.py +0 -414
- python_chargepoint-1.9.2/python_chargepoint/constants.py +0 -5
- python_chargepoint-1.9.2/python_chargepoint/exceptions.py +0 -35
- python_chargepoint-1.9.2/python_chargepoint/global_config.py +0 -140
- python_chargepoint-1.9.2/python_chargepoint/session.py +0 -278
- python_chargepoint-1.9.2/python_chargepoint/types.py +0 -250
- {python_chargepoint-1.9.2 → python_chargepoint-2.0.0}/LICENSE +0 -0
- {python_chargepoint-1.9.2 → python_chargepoint-2.0.0}/python_chargepoint/__init__.py +0 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-chargepoint
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: A simple, Pythonic wrapper for the ChargePoint API.
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Author: Marc Billow
|
|
8
|
+
Author-email: mbillow@users.noreply.github.compoetry
|
|
9
|
+
Requires-Python: >=3.10,<4.0
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Requires-Dist: aiohttp (>=3.9,<4.0)
|
|
18
|
+
Requires-Dist: click (>=8.1,<9.0)
|
|
19
|
+
Requires-Dist: pydantic (>=2.12,<3.0)
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# python-chargepoint
|
|
23
|
+
|
|
24
|
+
A simple, async Pythonic wrapper around the ChargePoint EV Charging Network API.
|
|
25
|
+
|
|
26
|
+
## Disclaimer
|
|
27
|
+
|
|
28
|
+
This project is not affiliated with or endorsed by ChargePoint in any way. Use at your own risk.
|
|
29
|
+
ChargePoint is a registered trademark of ChargePoint, Inc.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install python-chargepoint
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Library Usage
|
|
42
|
+
|
|
43
|
+
All client methods are `async` and must be called from an async context.
|
|
44
|
+
|
|
45
|
+
### Authentication
|
|
46
|
+
|
|
47
|
+
Three authentication methods are supported. The client is created via the async factory `ChargePoint.create()`.
|
|
48
|
+
|
|
49
|
+
**Password:**
|
|
50
|
+
```python
|
|
51
|
+
import asyncio
|
|
52
|
+
from python_chargepoint import ChargePoint
|
|
53
|
+
|
|
54
|
+
async def main():
|
|
55
|
+
client = await ChargePoint.create(username="user@example.com")
|
|
56
|
+
await client.login_with_password("password")
|
|
57
|
+
# ...
|
|
58
|
+
await client.close()
|
|
59
|
+
|
|
60
|
+
asyncio.run(main())
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Long-lived session token** (recommended for automation):
|
|
64
|
+
```python
|
|
65
|
+
client = await ChargePoint.create(
|
|
66
|
+
username="user@example.com",
|
|
67
|
+
coulomb_token="<coulomb_sess cookie value>",
|
|
68
|
+
)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**SSO JWT:**
|
|
72
|
+
```python
|
|
73
|
+
client = await ChargePoint.create(username="user@example.com")
|
|
74
|
+
await client.login_with_sso_session("<sso jwt>")
|
|
75
|
+
# you can then grab client.coulomb_token and use the above pattern going forward
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### Account
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
acct = await client.get_account()
|
|
84
|
+
print(acct.user.full_name) # "Jane Smith"
|
|
85
|
+
print(acct.account_balance.amount) # "12.34"
|
|
86
|
+
|
|
87
|
+
evs = await client.get_vehicles()
|
|
88
|
+
for ev in evs:
|
|
89
|
+
print(f"{ev.year} {ev.make} {ev.model}") # "2023 Polestar 2"
|
|
90
|
+
print(f" AC: {ev.charging_speed} kW DC: {ev.dc_charging_speed} kW")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
### Home Charger
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
charger_ids = await client.get_home_chargers()
|
|
99
|
+
# [12345678]
|
|
100
|
+
|
|
101
|
+
charger_id = charger_ids[0]
|
|
102
|
+
|
|
103
|
+
status = await client.get_home_charger_status(charger_id)
|
|
104
|
+
# HomeChargerStatus(
|
|
105
|
+
# charger_id=12345678,
|
|
106
|
+
# brand='CP',
|
|
107
|
+
# model='HOME FLEX',
|
|
108
|
+
# charging_status='AVAILABLE',
|
|
109
|
+
# is_plugged_in=True,
|
|
110
|
+
# is_connected=True,
|
|
111
|
+
# amperage_limit=28,
|
|
112
|
+
# possible_amperage_limits=[20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32])
|
|
113
|
+
|
|
114
|
+
tech = await client.get_home_charger_technical_info(charger_id)
|
|
115
|
+
# HomeChargerTechnicalInfo(
|
|
116
|
+
# model_number='CPH50-NEMA6-50-L23',
|
|
117
|
+
# serial_number='...',
|
|
118
|
+
# software_version='1.2.3.4',
|
|
119
|
+
# last_connected_at=datetime(...))
|
|
120
|
+
|
|
121
|
+
config = await client.get_home_charger_config(charger_id)
|
|
122
|
+
# HomeChargerConfiguration(
|
|
123
|
+
# station_nickname='Home Flex',
|
|
124
|
+
# led_brightness=LEDBrightness(level=5, supported_levels=[0,1,2,3,4,5]),
|
|
125
|
+
# utility=PowerUtility(name='Austin Energy', ...))
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### Amperage limit
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# Print valid amperage values
|
|
132
|
+
print(status.possible_amperage_limits)
|
|
133
|
+
# [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
|
|
134
|
+
|
|
135
|
+
await client.set_amperage_limit(charger_id, 24)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### LED brightness
|
|
139
|
+
|
|
140
|
+
Levels map to: `0`=off, `1`=20%, `2`=40%, `3`=60%, `4`=80%, `5`=100%.
|
|
141
|
+
Available levels are returned by `get_home_charger_config()`.
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
await client.set_led_brightness(charger_id, 3) # 60%
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### Restart
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
await client.restart_home_charger(charger_id)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### Charging Status and Sessions
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
status = await client.get_user_charging_status()
|
|
159
|
+
if status:
|
|
160
|
+
print(status.state) # "fully_charged"
|
|
161
|
+
print(status.session_id) # 1234567890
|
|
162
|
+
|
|
163
|
+
session = await client.get_charging_session(status.session_id)
|
|
164
|
+
print(session.charging_state) # "fully_charged"
|
|
165
|
+
print(session.energy_kwh) # 6.42
|
|
166
|
+
print(session.miles_added) # 22.3
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
#### Starting and stopping a session
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
# Stop the current session
|
|
173
|
+
session = await client.get_charging_session(status.session_id)
|
|
174
|
+
await session.stop()
|
|
175
|
+
|
|
176
|
+
# Start a new session on any device
|
|
177
|
+
new_session = await client.start_charging_session(device_id=charger_id)
|
|
178
|
+
print(new_session.session_id)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### Station Info
|
|
184
|
+
|
|
185
|
+
Fetch detailed information about any station by device ID — ports, pricing, connector types, and real-time status.
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
info = await client.get_station(device_id=13055991)
|
|
189
|
+
print(f"{' / '.join(info.name)}") # "DOMAIN TOWER 2 / LVL 2_STATION 2"
|
|
190
|
+
print(info.address.address1) # "10025 Alterra Pkwy"
|
|
191
|
+
print(info.station_status_v2) # "available"
|
|
192
|
+
print(info.ports_info.port_count) # 2
|
|
193
|
+
|
|
194
|
+
for port in info.ports_info.ports:
|
|
195
|
+
print(f"Port {port.outlet_number}: {port.status_v2} ({port.level})")
|
|
196
|
+
for c in port.connector_list:
|
|
197
|
+
print(f" {c.display_plug_type}: {c.status_v2}")
|
|
198
|
+
|
|
199
|
+
if info.station_price:
|
|
200
|
+
for tou in info.station_price.tou_fees:
|
|
201
|
+
print(f"Rate: {tou.fee.amount} {info.station_price.currency_code}/{tou.fee.unit}")
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### Nearby Stations
|
|
207
|
+
|
|
208
|
+
Fetch all charging stations visible within a geographic bounding box. Results include
|
|
209
|
+
both public stations and the user's home charger (if it falls within the bounds).
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
from python_chargepoint.types import MapFilter, ZoomBounds
|
|
213
|
+
|
|
214
|
+
bounds = ZoomBounds(sw_lat=30.37, sw_lon=-97.66, ne_lat=30.40, ne_lon=-97.64)
|
|
215
|
+
|
|
216
|
+
# No filter — return all stations
|
|
217
|
+
stations = await client.get_nearby_stations(bounds)
|
|
218
|
+
|
|
219
|
+
# Optional: filter by connector type or status
|
|
220
|
+
f = MapFilter(connector_l2=True, connector_combo=True, status_available=True)
|
|
221
|
+
stations = await client.get_nearby_stations(bounds, station_filter=f)
|
|
222
|
+
|
|
223
|
+
for s in stations:
|
|
224
|
+
print(f"{s.name1} — {s.station_status_v2}")
|
|
225
|
+
if s.is_home and s.charging_info:
|
|
226
|
+
print(f" Charging: {s.charging_info.current_charging}")
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**`MapFilter` fields** (all `bool`, default `False`):
|
|
230
|
+
|
|
231
|
+
| Field | Description |
|
|
232
|
+
|---|---|
|
|
233
|
+
| `connector_l2` | Level 2 AC |
|
|
234
|
+
| `connector_combo` | CCS combo (DC) |
|
|
235
|
+
| `connector_chademo` | CHAdeMO (DC) |
|
|
236
|
+
| `connector_tesla` | Tesla proprietary |
|
|
237
|
+
| `connector_l1` | Level 1 AC |
|
|
238
|
+
| `connector_l2_tesla` | Tesla Level 2 |
|
|
239
|
+
| `connector_l2_nema_1450` | NEMA 14-50 |
|
|
240
|
+
| `dc_fast_charging` | Any DC fast charger |
|
|
241
|
+
| `status_available` | Only available stations |
|
|
242
|
+
| `price_free` | Only free stations |
|
|
243
|
+
| `van_accessible` | Van-accessible spaces |
|
|
244
|
+
| `disabled_parking` | Disability-accessible parking |
|
|
245
|
+
| `network_chargepoint` | ChargePoint network |
|
|
246
|
+
| `network_blink` | Blink network |
|
|
247
|
+
| `network_evgo` | EVgo network |
|
|
248
|
+
| `network_flo` | FLO network |
|
|
249
|
+
| `network_ionna` | IONNA network |
|
|
250
|
+
| `network_evconnect` | EV Connect |
|
|
251
|
+
| `network_evgateway` | EV Gateway |
|
|
252
|
+
| `network_bchydro` | BC Hydro |
|
|
253
|
+
| `network_greenlots` | Greenlots |
|
|
254
|
+
| `network_mercedes` | Mercedes-Benz |
|
|
255
|
+
| `network_circuitelectric` | Circuit Électrique |
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## CLI
|
|
260
|
+
|
|
261
|
+
After installation, a `chargepoint` command is available.
|
|
262
|
+
|
|
263
|
+
### Authentication
|
|
264
|
+
|
|
265
|
+
Credentials are read from environment variables. The CLI falls back to prompting for a password if no token is set.
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
export CP_USERNAME="user@example.com"
|
|
269
|
+
export CP_COULOMB_TOKEN="<coulomb_sess cookie value>"
|
|
270
|
+
# or
|
|
271
|
+
export CP_SSO_JWT="<sso jwt>"
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Global options
|
|
275
|
+
|
|
276
|
+
```
|
|
277
|
+
chargepoint [--debug] [--json] <command>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
`--json` dumps the raw API response as JSON — useful for scripting.
|
|
281
|
+
|
|
282
|
+
### Commands
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
# Account
|
|
286
|
+
chargepoint account
|
|
287
|
+
chargepoint vehicles
|
|
288
|
+
|
|
289
|
+
# Charging status
|
|
290
|
+
chargepoint charging-status
|
|
291
|
+
|
|
292
|
+
# Station info
|
|
293
|
+
chargepoint station <device_id>
|
|
294
|
+
|
|
295
|
+
# Nearby stations
|
|
296
|
+
chargepoint nearby --sw-lat 30.37 --sw-lon -97.66 --ne-lat 30.40 --ne-lon -97.64 \
|
|
297
|
+
[--connector-l2] [--connector-combo] [--connector-chademo] [--connector-tesla] \
|
|
298
|
+
[--dc-fast] [--available-only] [--free-only]
|
|
299
|
+
|
|
300
|
+
# Home charger
|
|
301
|
+
chargepoint charger list
|
|
302
|
+
chargepoint charger status <charger_id>
|
|
303
|
+
chargepoint charger tech-info <charger_id>
|
|
304
|
+
chargepoint charger config <charger_id>
|
|
305
|
+
chargepoint charger set-amperage <charger_id> <amps>
|
|
306
|
+
chargepoint charger set-led <charger_id> <level> # 0=off 1=20% 2=40% 3=60% 4=80% 5=100%
|
|
307
|
+
chargepoint charger restart <charger_id>
|
|
308
|
+
|
|
309
|
+
# Sessions
|
|
310
|
+
chargepoint session get <session_id>
|
|
311
|
+
chargepoint session start <device_id>
|
|
312
|
+
chargepoint session stop <session_id>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Use `--help` on any command or subgroup for details:
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
chargepoint nearby --help
|
|
319
|
+
chargepoint charger --help
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Development
|
|
325
|
+
|
|
326
|
+
### Setup
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
git clone https://github.com/mbillow/python-chargepoint.git
|
|
330
|
+
cd python-chargepoint
|
|
331
|
+
poetry install
|
|
332
|
+
poetry run pre-commit install
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Checks
|
|
336
|
+
|
|
337
|
+
The following checks run automatically on every commit via pre-commit, and are also enforced in CI:
|
|
338
|
+
|
|
339
|
+
| Tool | Purpose |
|
|
340
|
+
|---|---|
|
|
341
|
+
| `black` | Code formatting |
|
|
342
|
+
| `flake8` | Style and error linting |
|
|
343
|
+
| `mypy` | Static type checking |
|
|
344
|
+
| `pyright` | Pylance-compatible type checking |
|
|
345
|
+
|
|
346
|
+
To run them manually:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
poetry run pre-commit run --all-files
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Or individually:
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
poetry run black --check python_chargepoint/ tests/
|
|
356
|
+
poetry run flake8 python_chargepoint/ tests/
|
|
357
|
+
poetry run mypy python_chargepoint/
|
|
358
|
+
poetry run pyright python_chargepoint/
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Tests
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
poetry run pytest
|
|
365
|
+
```
|
|
366
|
+
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# python-chargepoint
|
|
2
|
+
|
|
3
|
+
A simple, async Pythonic wrapper around the ChargePoint EV Charging Network API.
|
|
4
|
+
|
|
5
|
+
## Disclaimer
|
|
6
|
+
|
|
7
|
+
This project is not affiliated with or endorsed by ChargePoint in any way. Use at your own risk.
|
|
8
|
+
ChargePoint is a registered trademark of ChargePoint, Inc.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install python-chargepoint
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Library Usage
|
|
21
|
+
|
|
22
|
+
All client methods are `async` and must be called from an async context.
|
|
23
|
+
|
|
24
|
+
### Authentication
|
|
25
|
+
|
|
26
|
+
Three authentication methods are supported. The client is created via the async factory `ChargePoint.create()`.
|
|
27
|
+
|
|
28
|
+
**Password:**
|
|
29
|
+
```python
|
|
30
|
+
import asyncio
|
|
31
|
+
from python_chargepoint import ChargePoint
|
|
32
|
+
|
|
33
|
+
async def main():
|
|
34
|
+
client = await ChargePoint.create(username="user@example.com")
|
|
35
|
+
await client.login_with_password("password")
|
|
36
|
+
# ...
|
|
37
|
+
await client.close()
|
|
38
|
+
|
|
39
|
+
asyncio.run(main())
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Long-lived session token** (recommended for automation):
|
|
43
|
+
```python
|
|
44
|
+
client = await ChargePoint.create(
|
|
45
|
+
username="user@example.com",
|
|
46
|
+
coulomb_token="<coulomb_sess cookie value>",
|
|
47
|
+
)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**SSO JWT:**
|
|
51
|
+
```python
|
|
52
|
+
client = await ChargePoint.create(username="user@example.com")
|
|
53
|
+
await client.login_with_sso_session("<sso jwt>")
|
|
54
|
+
# you can then grab client.coulomb_token and use the above pattern going forward
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### Account
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
acct = await client.get_account()
|
|
63
|
+
print(acct.user.full_name) # "Jane Smith"
|
|
64
|
+
print(acct.account_balance.amount) # "12.34"
|
|
65
|
+
|
|
66
|
+
evs = await client.get_vehicles()
|
|
67
|
+
for ev in evs:
|
|
68
|
+
print(f"{ev.year} {ev.make} {ev.model}") # "2023 Polestar 2"
|
|
69
|
+
print(f" AC: {ev.charging_speed} kW DC: {ev.dc_charging_speed} kW")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### Home Charger
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
charger_ids = await client.get_home_chargers()
|
|
78
|
+
# [12345678]
|
|
79
|
+
|
|
80
|
+
charger_id = charger_ids[0]
|
|
81
|
+
|
|
82
|
+
status = await client.get_home_charger_status(charger_id)
|
|
83
|
+
# HomeChargerStatus(
|
|
84
|
+
# charger_id=12345678,
|
|
85
|
+
# brand='CP',
|
|
86
|
+
# model='HOME FLEX',
|
|
87
|
+
# charging_status='AVAILABLE',
|
|
88
|
+
# is_plugged_in=True,
|
|
89
|
+
# is_connected=True,
|
|
90
|
+
# amperage_limit=28,
|
|
91
|
+
# possible_amperage_limits=[20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32])
|
|
92
|
+
|
|
93
|
+
tech = await client.get_home_charger_technical_info(charger_id)
|
|
94
|
+
# HomeChargerTechnicalInfo(
|
|
95
|
+
# model_number='CPH50-NEMA6-50-L23',
|
|
96
|
+
# serial_number='...',
|
|
97
|
+
# software_version='1.2.3.4',
|
|
98
|
+
# last_connected_at=datetime(...))
|
|
99
|
+
|
|
100
|
+
config = await client.get_home_charger_config(charger_id)
|
|
101
|
+
# HomeChargerConfiguration(
|
|
102
|
+
# station_nickname='Home Flex',
|
|
103
|
+
# led_brightness=LEDBrightness(level=5, supported_levels=[0,1,2,3,4,5]),
|
|
104
|
+
# utility=PowerUtility(name='Austin Energy', ...))
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Amperage limit
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
# Print valid amperage values
|
|
111
|
+
print(status.possible_amperage_limits)
|
|
112
|
+
# [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
|
|
113
|
+
|
|
114
|
+
await client.set_amperage_limit(charger_id, 24)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### LED brightness
|
|
118
|
+
|
|
119
|
+
Levels map to: `0`=off, `1`=20%, `2`=40%, `3`=60%, `4`=80%, `5`=100%.
|
|
120
|
+
Available levels are returned by `get_home_charger_config()`.
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
await client.set_led_brightness(charger_id, 3) # 60%
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### Restart
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
await client.restart_home_charger(charger_id)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
### Charging Status and Sessions
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
status = await client.get_user_charging_status()
|
|
138
|
+
if status:
|
|
139
|
+
print(status.state) # "fully_charged"
|
|
140
|
+
print(status.session_id) # 1234567890
|
|
141
|
+
|
|
142
|
+
session = await client.get_charging_session(status.session_id)
|
|
143
|
+
print(session.charging_state) # "fully_charged"
|
|
144
|
+
print(session.energy_kwh) # 6.42
|
|
145
|
+
print(session.miles_added) # 22.3
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### Starting and stopping a session
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
# Stop the current session
|
|
152
|
+
session = await client.get_charging_session(status.session_id)
|
|
153
|
+
await session.stop()
|
|
154
|
+
|
|
155
|
+
# Start a new session on any device
|
|
156
|
+
new_session = await client.start_charging_session(device_id=charger_id)
|
|
157
|
+
print(new_session.session_id)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### Station Info
|
|
163
|
+
|
|
164
|
+
Fetch detailed information about any station by device ID — ports, pricing, connector types, and real-time status.
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
info = await client.get_station(device_id=13055991)
|
|
168
|
+
print(f"{' / '.join(info.name)}") # "DOMAIN TOWER 2 / LVL 2_STATION 2"
|
|
169
|
+
print(info.address.address1) # "10025 Alterra Pkwy"
|
|
170
|
+
print(info.station_status_v2) # "available"
|
|
171
|
+
print(info.ports_info.port_count) # 2
|
|
172
|
+
|
|
173
|
+
for port in info.ports_info.ports:
|
|
174
|
+
print(f"Port {port.outlet_number}: {port.status_v2} ({port.level})")
|
|
175
|
+
for c in port.connector_list:
|
|
176
|
+
print(f" {c.display_plug_type}: {c.status_v2}")
|
|
177
|
+
|
|
178
|
+
if info.station_price:
|
|
179
|
+
for tou in info.station_price.tou_fees:
|
|
180
|
+
print(f"Rate: {tou.fee.amount} {info.station_price.currency_code}/{tou.fee.unit}")
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### Nearby Stations
|
|
186
|
+
|
|
187
|
+
Fetch all charging stations visible within a geographic bounding box. Results include
|
|
188
|
+
both public stations and the user's home charger (if it falls within the bounds).
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from python_chargepoint.types import MapFilter, ZoomBounds
|
|
192
|
+
|
|
193
|
+
bounds = ZoomBounds(sw_lat=30.37, sw_lon=-97.66, ne_lat=30.40, ne_lon=-97.64)
|
|
194
|
+
|
|
195
|
+
# No filter — return all stations
|
|
196
|
+
stations = await client.get_nearby_stations(bounds)
|
|
197
|
+
|
|
198
|
+
# Optional: filter by connector type or status
|
|
199
|
+
f = MapFilter(connector_l2=True, connector_combo=True, status_available=True)
|
|
200
|
+
stations = await client.get_nearby_stations(bounds, station_filter=f)
|
|
201
|
+
|
|
202
|
+
for s in stations:
|
|
203
|
+
print(f"{s.name1} — {s.station_status_v2}")
|
|
204
|
+
if s.is_home and s.charging_info:
|
|
205
|
+
print(f" Charging: {s.charging_info.current_charging}")
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**`MapFilter` fields** (all `bool`, default `False`):
|
|
209
|
+
|
|
210
|
+
| Field | Description |
|
|
211
|
+
|---|---|
|
|
212
|
+
| `connector_l2` | Level 2 AC |
|
|
213
|
+
| `connector_combo` | CCS combo (DC) |
|
|
214
|
+
| `connector_chademo` | CHAdeMO (DC) |
|
|
215
|
+
| `connector_tesla` | Tesla proprietary |
|
|
216
|
+
| `connector_l1` | Level 1 AC |
|
|
217
|
+
| `connector_l2_tesla` | Tesla Level 2 |
|
|
218
|
+
| `connector_l2_nema_1450` | NEMA 14-50 |
|
|
219
|
+
| `dc_fast_charging` | Any DC fast charger |
|
|
220
|
+
| `status_available` | Only available stations |
|
|
221
|
+
| `price_free` | Only free stations |
|
|
222
|
+
| `van_accessible` | Van-accessible spaces |
|
|
223
|
+
| `disabled_parking` | Disability-accessible parking |
|
|
224
|
+
| `network_chargepoint` | ChargePoint network |
|
|
225
|
+
| `network_blink` | Blink network |
|
|
226
|
+
| `network_evgo` | EVgo network |
|
|
227
|
+
| `network_flo` | FLO network |
|
|
228
|
+
| `network_ionna` | IONNA network |
|
|
229
|
+
| `network_evconnect` | EV Connect |
|
|
230
|
+
| `network_evgateway` | EV Gateway |
|
|
231
|
+
| `network_bchydro` | BC Hydro |
|
|
232
|
+
| `network_greenlots` | Greenlots |
|
|
233
|
+
| `network_mercedes` | Mercedes-Benz |
|
|
234
|
+
| `network_circuitelectric` | Circuit Électrique |
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## CLI
|
|
239
|
+
|
|
240
|
+
After installation, a `chargepoint` command is available.
|
|
241
|
+
|
|
242
|
+
### Authentication
|
|
243
|
+
|
|
244
|
+
Credentials are read from environment variables. The CLI falls back to prompting for a password if no token is set.
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
export CP_USERNAME="user@example.com"
|
|
248
|
+
export CP_COULOMB_TOKEN="<coulomb_sess cookie value>"
|
|
249
|
+
# or
|
|
250
|
+
export CP_SSO_JWT="<sso jwt>"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Global options
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
chargepoint [--debug] [--json] <command>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
`--json` dumps the raw API response as JSON — useful for scripting.
|
|
260
|
+
|
|
261
|
+
### Commands
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
# Account
|
|
265
|
+
chargepoint account
|
|
266
|
+
chargepoint vehicles
|
|
267
|
+
|
|
268
|
+
# Charging status
|
|
269
|
+
chargepoint charging-status
|
|
270
|
+
|
|
271
|
+
# Station info
|
|
272
|
+
chargepoint station <device_id>
|
|
273
|
+
|
|
274
|
+
# Nearby stations
|
|
275
|
+
chargepoint nearby --sw-lat 30.37 --sw-lon -97.66 --ne-lat 30.40 --ne-lon -97.64 \
|
|
276
|
+
[--connector-l2] [--connector-combo] [--connector-chademo] [--connector-tesla] \
|
|
277
|
+
[--dc-fast] [--available-only] [--free-only]
|
|
278
|
+
|
|
279
|
+
# Home charger
|
|
280
|
+
chargepoint charger list
|
|
281
|
+
chargepoint charger status <charger_id>
|
|
282
|
+
chargepoint charger tech-info <charger_id>
|
|
283
|
+
chargepoint charger config <charger_id>
|
|
284
|
+
chargepoint charger set-amperage <charger_id> <amps>
|
|
285
|
+
chargepoint charger set-led <charger_id> <level> # 0=off 1=20% 2=40% 3=60% 4=80% 5=100%
|
|
286
|
+
chargepoint charger restart <charger_id>
|
|
287
|
+
|
|
288
|
+
# Sessions
|
|
289
|
+
chargepoint session get <session_id>
|
|
290
|
+
chargepoint session start <device_id>
|
|
291
|
+
chargepoint session stop <session_id>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Use `--help` on any command or subgroup for details:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
chargepoint nearby --help
|
|
298
|
+
chargepoint charger --help
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Development
|
|
304
|
+
|
|
305
|
+
### Setup
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
git clone https://github.com/mbillow/python-chargepoint.git
|
|
309
|
+
cd python-chargepoint
|
|
310
|
+
poetry install
|
|
311
|
+
poetry run pre-commit install
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Checks
|
|
315
|
+
|
|
316
|
+
The following checks run automatically on every commit via pre-commit, and are also enforced in CI:
|
|
317
|
+
|
|
318
|
+
| Tool | Purpose |
|
|
319
|
+
|---|---|
|
|
320
|
+
| `black` | Code formatting |
|
|
321
|
+
| `flake8` | Style and error linting |
|
|
322
|
+
| `mypy` | Static type checking |
|
|
323
|
+
| `pyright` | Pylance-compatible type checking |
|
|
324
|
+
|
|
325
|
+
To run them manually:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
poetry run pre-commit run --all-files
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Or individually:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
poetry run black --check python_chargepoint/ tests/
|
|
335
|
+
poetry run flake8 python_chargepoint/ tests/
|
|
336
|
+
poetry run mypy python_chargepoint/
|
|
337
|
+
poetry run pyright python_chargepoint/
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Tests
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
poetry run pytest
|
|
344
|
+
```
|