python-chargepoint 1.8.0__tar.gz → 1.9.2__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.
@@ -0,0 +1,204 @@
1
+ Metadata-Version: 2.1
2
+ Name: python-chargepoint
3
+ Version: 1.9.2
4
+ Summary: A simple, Pythonic wrapper for the ChargePoint API.
5
+ License: MIT
6
+ Author: Marc Billow
7
+ Author-email: mbillow@users.noreply.github.compoetry
8
+ Requires-Python: >=3.9,<4.0
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Dist: requests (>=2.27.1,<3.0.0)
16
+ Description-Content-Type: text/markdown
17
+
18
+ # python-chargepoint
19
+
20
+ A simple Pythonic wrapper around the ChargePoint EV Charging Network API.
21
+
22
+ ## DISCLAIMER
23
+
24
+ I, nor this project, are in _any way_ associated with ChargePoint. Use this project at your own risk.
25
+ ChargePoint is a registered trademark of ChargePoint, Inc.
26
+
27
+ I just wanted a way to retrieve and store charging data from my ChargePoint Home Flex
28
+ in a way that is easy to model and query. This project is the first step in getting that data into a
29
+ more robust time series database.
30
+
31
+ ## Use
32
+
33
+ ### Login
34
+
35
+ ```python
36
+ from python_chargepoint import ChargePoint
37
+
38
+ client = ChargePoint(username="user", password="password")
39
+ print(client.user_id)
40
+ # 1234567890
41
+ ```
42
+
43
+ ### Home Chargers
44
+ ```python
45
+ from python_chargepoint import ChargePoint
46
+
47
+ client = ChargePoint(username="user", password="password")
48
+ chargers = client.get_home_chargers()
49
+ print(chargers)
50
+ # [12345678]
51
+
52
+ for charger_id in chargers:
53
+ charger = client.get_home_charger_status(charger_id=charger_id)
54
+ print(charger)
55
+ # HomeChargerStatus(
56
+ # brand='CP',
57
+ # plugged_in=True,
58
+ # connected=True,
59
+ # charging_status='NOT_CHARGING',
60
+ # last_connected_at=datetime.datetime(2022, 1, 30, 15, 14, 36),
61
+ # reminder_enabled=False,
62
+ # reminder_time='21:00',
63
+ # model='CPH50-NEMA6-50-L23',
64
+ # mac_address='0024B10000012345',
65
+ # amperage_limit=25,
66
+ # possible_amperage_limits=[20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32])
67
+ ```
68
+
69
+ ### Account Charging Status and Session
70
+
71
+ ```python
72
+ from python_chargepoint import ChargePoint
73
+
74
+ client = ChargePoint(username="user", password="password")
75
+ charging = client.get_user_charging_status()
76
+ if charging:
77
+ print(charging)
78
+ # UserChargingStatus(
79
+ # session_id=1234567890,
80
+ # start_time=datetime.datetime(2022, 1, 30, 13, 32, 45),
81
+ # state='fully_charged',
82
+ # stations=[
83
+ # ChargePointStation(
84
+ # id=12345678,
85
+ # name='CP HOME ',
86
+ # latitude=30.0000000,
87
+ # longitude=-90.0000000)
88
+ # ])
89
+
90
+ session = client.get_charging_session(charging.session_id)
91
+ print(session)
92
+ # ChargingSession(
93
+ # session_id=1234567890,
94
+ # start_time=datetime.datetime(2022, 1, 30, 13, 32, 45),
95
+ # device_id=12345678,
96
+ # device_name='CP HOME',
97
+ # charging_state='fully_charged',
98
+ # charging_time=2426000,
99
+ # energy_kwh=4.3404,
100
+ # miles_added=15.024461538461539,
101
+ # miles_added_per_hour=0.0,
102
+ # outlet_number=1,
103
+ # port_level=2,
104
+ # power_kw=0.0,
105
+ # purpose='PERSONAL',
106
+ # currency_iso_code='USD',
107
+ # payment_completed=True,
108
+ # payment_type='none',
109
+ # pricing_spec_id=0,
110
+ # total_amount=0.67,
111
+ # api_flag=False,
112
+ # enable_stop_charging=True,
113
+ # has_charging_receipt=False,
114
+ # has_utility_info=True,
115
+ # is_home_charger=True,
116
+ # is_purpose_finalized=True,
117
+ # last_update_data_timestamp=datetime.datetime(2022, 1, 30, 15, 12, 48),
118
+ # stop_charge_supported=True,
119
+ # company_id=12345,
120
+ # company_name='CP Home',
121
+ # latitude=30.0000000,
122
+ # longitude=-90.0000000,
123
+ # address='Home Charger',
124
+ # city='City',
125
+ # state_name='State',
126
+ # country='United States',
127
+ # zipcode='12345',
128
+ # update_data=[
129
+ # ChargingSessionUpdate(
130
+ # energy_kwh=0.0,
131
+ # power_kw=0.0002,
132
+ # timestamp=datetime.datetime(2022, 1, 30, 13, 32, 57)),
133
+ # ChargingSessionUpdate(
134
+ # energy_kwh=0.0001,
135
+ # power_kw=0.1568,
136
+ # timestamp=datetime.datetime(2022, 1, 30, 13, 33, 9)),
137
+ # ChargingSessionUpdate(
138
+ # energy_kwh=0.0025,
139
+ # power_kw=3.7337,
140
+ # timestamp=datetime.datetime(2022, 1, 30, 13, 33, 12)),
141
+ # ChargingSessionUpdate(
142
+ # energy_kwh=0.0161,
143
+ # power_kw=1.3854,
144
+ # timestamp=datetime.datetime(2022, 1, 30, 13, 33, 33)),
145
+ # ...],
146
+ # update_period=300000,
147
+ # utility=PowerUtility(
148
+ # id=0,
149
+ # name='Energy Company',
150
+ # plans=[
151
+ # PowerUtilityPlan(
152
+ # code='R',
153
+ # id=12345,
154
+ # is_ev_plan=False,
155
+ # name='Residential')
156
+ # ]))
157
+ ```
158
+
159
+ #### Starting or Stopping a Session
160
+
161
+ ```python
162
+ from python_chargepoint import ChargePoint
163
+
164
+ client = ChargePoint(username="user", password="password")
165
+ charging = client.get_user_charging_status()
166
+
167
+ if charging:
168
+ session = client.get_charging_session(charging.session_id)
169
+ session.stop()
170
+
171
+ # If you wanted to charge again, you can start a new session.
172
+ session = client.start_charging_session(session.device_id)
173
+ ```
174
+
175
+ You can also start a new session by providing any device ID you want to start charging on.
176
+
177
+ ```python
178
+ from python_chargepoint import ChargePoint
179
+
180
+ client = ChargePoint(username="user", password="password")
181
+ home_flex_id = client.get_home_chargers()[0]
182
+ home_flex = client.get_home_charger_status(home_flex_id)
183
+
184
+ if home_flex.charging_status == "AVAILABLE":
185
+ session = client.start_charging_session(home_flex_id)
186
+ ```
187
+
188
+ #### Setting the amperage limit
189
+
190
+ ```python
191
+ from python_chargepoint import ChargePoint
192
+
193
+ client = ChargePoint(username="user", password="password")
194
+ home_flex_id = client.get_home_chargers()[0]
195
+
196
+ # Print out valid amperage values.
197
+ print(client.get_home_charger_status(home_flex_id).possible_amperage_limits)
198
+ # [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
199
+
200
+ client.set_amperage_limit(home_flex_id, 23)
201
+ print(client.get_home_charger_status(home_flex_id).amperage_limit)
202
+ # 23
203
+ ```
204
+
@@ -0,0 +1,186 @@
1
+ # python-chargepoint
2
+
3
+ A simple Pythonic wrapper around the ChargePoint EV Charging Network API.
4
+
5
+ ## DISCLAIMER
6
+
7
+ I, nor this project, are in _any way_ associated with ChargePoint. Use this project at your own risk.
8
+ ChargePoint is a registered trademark of ChargePoint, Inc.
9
+
10
+ I just wanted a way to retrieve and store charging data from my ChargePoint Home Flex
11
+ in a way that is easy to model and query. This project is the first step in getting that data into a
12
+ more robust time series database.
13
+
14
+ ## Use
15
+
16
+ ### Login
17
+
18
+ ```python
19
+ from python_chargepoint import ChargePoint
20
+
21
+ client = ChargePoint(username="user", password="password")
22
+ print(client.user_id)
23
+ # 1234567890
24
+ ```
25
+
26
+ ### Home Chargers
27
+ ```python
28
+ from python_chargepoint import ChargePoint
29
+
30
+ client = ChargePoint(username="user", password="password")
31
+ chargers = client.get_home_chargers()
32
+ print(chargers)
33
+ # [12345678]
34
+
35
+ for charger_id in chargers:
36
+ charger = client.get_home_charger_status(charger_id=charger_id)
37
+ print(charger)
38
+ # HomeChargerStatus(
39
+ # brand='CP',
40
+ # plugged_in=True,
41
+ # connected=True,
42
+ # charging_status='NOT_CHARGING',
43
+ # last_connected_at=datetime.datetime(2022, 1, 30, 15, 14, 36),
44
+ # reminder_enabled=False,
45
+ # reminder_time='21:00',
46
+ # model='CPH50-NEMA6-50-L23',
47
+ # mac_address='0024B10000012345',
48
+ # amperage_limit=25,
49
+ # possible_amperage_limits=[20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32])
50
+ ```
51
+
52
+ ### Account Charging Status and Session
53
+
54
+ ```python
55
+ from python_chargepoint import ChargePoint
56
+
57
+ client = ChargePoint(username="user", password="password")
58
+ charging = client.get_user_charging_status()
59
+ if charging:
60
+ print(charging)
61
+ # UserChargingStatus(
62
+ # session_id=1234567890,
63
+ # start_time=datetime.datetime(2022, 1, 30, 13, 32, 45),
64
+ # state='fully_charged',
65
+ # stations=[
66
+ # ChargePointStation(
67
+ # id=12345678,
68
+ # name='CP HOME ',
69
+ # latitude=30.0000000,
70
+ # longitude=-90.0000000)
71
+ # ])
72
+
73
+ session = client.get_charging_session(charging.session_id)
74
+ print(session)
75
+ # ChargingSession(
76
+ # session_id=1234567890,
77
+ # start_time=datetime.datetime(2022, 1, 30, 13, 32, 45),
78
+ # device_id=12345678,
79
+ # device_name='CP HOME',
80
+ # charging_state='fully_charged',
81
+ # charging_time=2426000,
82
+ # energy_kwh=4.3404,
83
+ # miles_added=15.024461538461539,
84
+ # miles_added_per_hour=0.0,
85
+ # outlet_number=1,
86
+ # port_level=2,
87
+ # power_kw=0.0,
88
+ # purpose='PERSONAL',
89
+ # currency_iso_code='USD',
90
+ # payment_completed=True,
91
+ # payment_type='none',
92
+ # pricing_spec_id=0,
93
+ # total_amount=0.67,
94
+ # api_flag=False,
95
+ # enable_stop_charging=True,
96
+ # has_charging_receipt=False,
97
+ # has_utility_info=True,
98
+ # is_home_charger=True,
99
+ # is_purpose_finalized=True,
100
+ # last_update_data_timestamp=datetime.datetime(2022, 1, 30, 15, 12, 48),
101
+ # stop_charge_supported=True,
102
+ # company_id=12345,
103
+ # company_name='CP Home',
104
+ # latitude=30.0000000,
105
+ # longitude=-90.0000000,
106
+ # address='Home Charger',
107
+ # city='City',
108
+ # state_name='State',
109
+ # country='United States',
110
+ # zipcode='12345',
111
+ # update_data=[
112
+ # ChargingSessionUpdate(
113
+ # energy_kwh=0.0,
114
+ # power_kw=0.0002,
115
+ # timestamp=datetime.datetime(2022, 1, 30, 13, 32, 57)),
116
+ # ChargingSessionUpdate(
117
+ # energy_kwh=0.0001,
118
+ # power_kw=0.1568,
119
+ # timestamp=datetime.datetime(2022, 1, 30, 13, 33, 9)),
120
+ # ChargingSessionUpdate(
121
+ # energy_kwh=0.0025,
122
+ # power_kw=3.7337,
123
+ # timestamp=datetime.datetime(2022, 1, 30, 13, 33, 12)),
124
+ # ChargingSessionUpdate(
125
+ # energy_kwh=0.0161,
126
+ # power_kw=1.3854,
127
+ # timestamp=datetime.datetime(2022, 1, 30, 13, 33, 33)),
128
+ # ...],
129
+ # update_period=300000,
130
+ # utility=PowerUtility(
131
+ # id=0,
132
+ # name='Energy Company',
133
+ # plans=[
134
+ # PowerUtilityPlan(
135
+ # code='R',
136
+ # id=12345,
137
+ # is_ev_plan=False,
138
+ # name='Residential')
139
+ # ]))
140
+ ```
141
+
142
+ #### Starting or Stopping a Session
143
+
144
+ ```python
145
+ from python_chargepoint import ChargePoint
146
+
147
+ client = ChargePoint(username="user", password="password")
148
+ charging = client.get_user_charging_status()
149
+
150
+ if charging:
151
+ session = client.get_charging_session(charging.session_id)
152
+ session.stop()
153
+
154
+ # If you wanted to charge again, you can start a new session.
155
+ session = client.start_charging_session(session.device_id)
156
+ ```
157
+
158
+ You can also start a new session by providing any device ID you want to start charging on.
159
+
160
+ ```python
161
+ from python_chargepoint import ChargePoint
162
+
163
+ client = ChargePoint(username="user", password="password")
164
+ home_flex_id = client.get_home_chargers()[0]
165
+ home_flex = client.get_home_charger_status(home_flex_id)
166
+
167
+ if home_flex.charging_status == "AVAILABLE":
168
+ session = client.start_charging_session(home_flex_id)
169
+ ```
170
+
171
+ #### Setting the amperage limit
172
+
173
+ ```python
174
+ from python_chargepoint import ChargePoint
175
+
176
+ client = ChargePoint(username="user", password="password")
177
+ home_flex_id = client.get_home_chargers()[0]
178
+
179
+ # Print out valid amperage values.
180
+ print(client.get_home_charger_status(home_flex_id).possible_amperage_limits)
181
+ # [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
182
+
183
+ client.set_amperage_limit(home_flex_id, 23)
184
+ print(client.get_home_charger_status(home_flex_id).amperage_limit)
185
+ # 23
186
+ ```
@@ -1,12 +1,13 @@
1
1
  [tool.poetry]
2
2
  name = "python-chargepoint"
3
- version = "1.8.0"
3
+ version = "1.9.2"
4
4
  description = "A simple, Pythonic wrapper for the ChargePoint API."
5
5
  authors = ["Marc Billow <mbillow@users.noreply.github.compoetry>"]
6
6
  license = "MIT"
7
7
  packages = [
8
8
  { include = "python_chargepoint" },
9
9
  ]
10
+ readme = "README.md"
10
11
 
11
12
  [tool.poetry.dependencies]
12
13
  python = "^3.9"
@@ -1,6 +1,7 @@
1
1
  from uuid import uuid4
2
2
  from typing import List, Optional
3
3
  from functools import wraps
4
+ from time import sleep
4
5
 
5
6
  from requests import Session, codes, post
6
7
 
@@ -357,6 +358,48 @@ class ChargePoint:
357
358
 
358
359
  return UserChargingStatus.from_json(status["user_status"])
359
360
 
361
+ @_require_login
362
+ def set_amperage_limit(self, charger_id: int, amperage_limit: int, max_retry: int = 5) -> None:
363
+ _LOGGER.debug(f"Setting amperage limit for {charger_id} to {amperage_limit}")
364
+ request = {"deviceData": self._device_data, "chargeAmperageLimit": amperage_limit}
365
+ response = self._session.post(
366
+ f"{self._global_config.endpoints.internal_api}/driver/charger/{charger_id}/config/v1/charge-amperage-limit",
367
+ json=request
368
+ )
369
+
370
+ if response.status_code != codes.ok:
371
+ _LOGGER.error(
372
+ "Failed to set amperage limit! status_code=%s err=%s",
373
+ response.status_code,
374
+ response.text,
375
+ )
376
+ raise ChargePointCommunicationException(
377
+ response=response, message="Failed to set amperage limit."
378
+ )
379
+ status = response.json()
380
+ # The API can return 200 but still have a failure status.
381
+ if status["status"] != "success":
382
+ message = status.get("message", "empty message")
383
+ _LOGGER.error(
384
+ "Failed to set amperage limit! status=%s err=%s",
385
+ status["status"],
386
+ message,
387
+ )
388
+ raise ChargePointCommunicationException(
389
+ response=response, message=f"Failed to set amperage limit: {message}"
390
+ )
391
+
392
+ # This is eventually consistent so we wait until the new limit is reflected.
393
+ for _ in range(1, max_retry): # pragma: no cover
394
+ charger_status = self.get_home_charger_status(charger_id)
395
+ if charger_status.amperage_limit == amperage_limit:
396
+ return
397
+ sleep(1)
398
+
399
+ raise ChargePointCommunicationException(
400
+ response=response, message="New amperage limit did not persist to charger after retries"
401
+ )
402
+
360
403
  @_require_login
361
404
  def get_charging_session(self, session_id: int) -> ChargingSession:
362
405
  return ChargingSession(session_id=session_id, client=self)
@@ -53,6 +53,7 @@ def _safe_get_endpoint(json: dict, endpoint_key: str) -> str:
53
53
  @dataclass
54
54
  class ChargePointEndpoints:
55
55
  accounts: str
56
+ internal_api: str
56
57
  mapcache: str
57
58
  panda_websocket: str
58
59
  payment_java: str
@@ -67,6 +68,7 @@ class ChargePointEndpoints:
67
68
  def from_json(cls, json: dict):
68
69
  return cls(
69
70
  accounts=_safe_get_endpoint(json, "accounts_endpoint"),
71
+ internal_api=_safe_get_endpoint(json, "internal_api_gateway_endpoint"),
70
72
  mapcache=_safe_get_endpoint(json, "mapcache_endpoint"),
71
73
  panda_websocket=_safe_get_endpoint(json, "panda_websocket_endpoint"),
72
74
  payment_java=_safe_get_endpoint(json, "payment_java_endpoint"),
@@ -102,6 +102,8 @@ class HomeChargerStatus:
102
102
  reminder_time: str
103
103
  model: str
104
104
  mac_address: str
105
+ amperage_limit: int
106
+ possible_amperage_limits: List[int]
105
107
 
106
108
  @classmethod
107
109
  def from_json(cls, charger_id: int, json: dict):
@@ -118,6 +120,8 @@ class HomeChargerStatus:
118
120
  reminder_time=json.get("plug_in_reminder_time", ""),
119
121
  model=json.get("model", ""),
120
122
  mac_address=json.get("mac_address", "00:00:00:00:00:00"),
123
+ amperage_limit=json.get("charge_amperage_setting", {}).get("charge_limit", 0),
124
+ possible_amperage_limits=json.get("charge_amperage_setting", {}).get("possible_charge_limit", 0),
121
125
  )
122
126
 
123
127
 
@@ -1,14 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: python-chargepoint
3
- Version: 1.8.0
4
- Summary: A simple, Pythonic wrapper for the ChargePoint API.
5
- License: MIT
6
- Author: Marc Billow
7
- Author-email: mbillow@users.noreply.github.compoetry
8
- Requires-Python: >=3.9,<4.0
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.9
12
- Classifier: Programming Language :: Python :: 3.10
13
- Classifier: Programming Language :: Python :: 3.11
14
- Requires-Dist: requests (>=2.27.1,<3.0.0)
@@ -1,30 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from setuptools import setup
3
-
4
- packages = \
5
- ['python_chargepoint']
6
-
7
- package_data = \
8
- {'': ['*']}
9
-
10
- install_requires = \
11
- ['requests>=2.27.1,<3.0.0']
12
-
13
- setup_kwargs = {
14
- 'name': 'python-chargepoint',
15
- 'version': '1.8.0',
16
- 'description': 'A simple, Pythonic wrapper for the ChargePoint API.',
17
- 'long_description': 'None',
18
- 'author': 'Marc Billow',
19
- 'author_email': 'mbillow@users.noreply.github.compoetry',
20
- 'maintainer': 'None',
21
- 'maintainer_email': 'None',
22
- 'url': 'None',
23
- 'packages': packages,
24
- 'package_data': package_data,
25
- 'install_requires': install_requires,
26
- 'python_requires': '>=3.9,<4.0',
27
- }
28
-
29
-
30
- setup(**setup_kwargs)