indevolt-api 1.2.3__tar.gz → 1.3.1__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.
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/PKG-INFO +76 -2
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/indevolt_api/__init__.py +10 -2
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/indevolt_api/client.py +63 -0
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/indevolt_api.egg-info/PKG-INFO +76 -2
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/pyproject.toml +1 -1
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/readme.md +75 -1
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/LICENSE +0 -0
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/indevolt_api.egg-info/SOURCES.txt +0 -0
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/indevolt_api.egg-info/dependency_links.txt +0 -0
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/indevolt_api.egg-info/requires.txt +0 -0
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/indevolt_api.egg-info/top_level.txt +0 -0
- {indevolt_api-1.2.3 → indevolt_api-1.3.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: indevolt-api
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: Python API client for Indevolt devices
|
|
5
5
|
Author: A. Gideonse
|
|
6
6
|
License: MIT
|
|
@@ -223,6 +223,64 @@ config = await api.get_config()
|
|
|
223
223
|
print(config)
|
|
224
224
|
```
|
|
225
225
|
|
|
226
|
+
#### `check_charge_limits(power: int, target_soc: int, generation: int) -> None`
|
|
227
|
+
|
|
228
|
+
Check that charge parameters do not exceed device limits. Raises an exception if any boundary is violated.
|
|
229
|
+
|
|
230
|
+
**Parameters:**
|
|
231
|
+
|
|
232
|
+
- `power` (int): Requested charge power in watts
|
|
233
|
+
- `target_soc` (int): Target state of charge percentage
|
|
234
|
+
- `generation` (int): Device hardware generation (`1` or `2`), available from `get_config()` under `device.generation`
|
|
235
|
+
|
|
236
|
+
**Raises:**
|
|
237
|
+
|
|
238
|
+
- `PowerExceedsMaxError`: If `power` exceeds the maximum for the given generation
|
|
239
|
+
- `SocBelowMinimumError`: If `target_soc` is below `MINIMUM_SOC` (5%)
|
|
240
|
+
|
|
241
|
+
**Example:**
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
config = await api.get_config()
|
|
245
|
+
generation = config["device"]["generation"]
|
|
246
|
+
|
|
247
|
+
try:
|
|
248
|
+
api.check_charge_limits(power=1000, target_soc=80, generation=generation)
|
|
249
|
+
except PowerExceedsMaxError as e:
|
|
250
|
+
print(f"Power {e.power}W exceeds max {e.max_power}W for gen {e.generation}")
|
|
251
|
+
except SocBelowMinimumError as e:
|
|
252
|
+
print(f"Target SOC {e.target_soc}% is below minimum {e.minimum_soc}%")
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### `check_discharge_limits(power: int, target_soc: int, generation: int) -> None`
|
|
256
|
+
|
|
257
|
+
Check that discharge parameters do not exceed device limits. Raises an exception if any boundary is violated.
|
|
258
|
+
|
|
259
|
+
**Parameters:**
|
|
260
|
+
|
|
261
|
+
- `power` (int): Requested discharge power in watts
|
|
262
|
+
- `target_soc` (int): Target state of charge percentage
|
|
263
|
+
- `generation` (int): Device hardware generation (`1` or `2`), available from `get_config()` under `device.generation`
|
|
264
|
+
|
|
265
|
+
**Raises:**
|
|
266
|
+
|
|
267
|
+
- `PowerExceedsMaxError`: If `power` exceeds the maximum for the given generation
|
|
268
|
+
- `SocBelowMinimumError`: If `target_soc` is below `MINIMUM_SOC` (5%)
|
|
269
|
+
|
|
270
|
+
**Example:**
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
config = await api.get_config()
|
|
274
|
+
generation = config["device"]["generation"]
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
api.check_discharge_limits(power=600, target_soc=10, generation=generation)
|
|
278
|
+
except PowerExceedsMaxError as e:
|
|
279
|
+
print(f"Power {e.power}W exceeds max {e.max_power}W for gen {e.generation}")
|
|
280
|
+
except SocBelowMinimumError as e:
|
|
281
|
+
print(f"Target SOC {e.target_soc}% is below minimum {e.minimum_soc}%")
|
|
282
|
+
```
|
|
283
|
+
|
|
226
284
|
### async_discover(timeout: float = 5.0) -> list[DiscoveredDevice]
|
|
227
285
|
|
|
228
286
|
Discover Indevolt devices on the local network using UDP broadcast.
|
|
@@ -265,7 +323,7 @@ if device.name:
|
|
|
265
323
|
|
|
266
324
|
## Exception Handling
|
|
267
325
|
|
|
268
|
-
The library provides
|
|
326
|
+
The library provides custom exceptions for API errors and limit violations.
|
|
269
327
|
|
|
270
328
|
### `APIException`
|
|
271
329
|
|
|
@@ -275,6 +333,22 @@ Raised when there's a client error during API communication (network errors, HTT
|
|
|
275
333
|
|
|
276
334
|
Raised when an API request times out (default timeout: 10 seconds).
|
|
277
335
|
|
|
336
|
+
### `ChargePowerExceedsMaxError` / `DischargePowerExceedsMaxError`
|
|
337
|
+
|
|
338
|
+
Replaced by `PowerExceedsMaxError`.
|
|
339
|
+
|
|
340
|
+
### `PowerExceedsMaxError`
|
|
341
|
+
|
|
342
|
+
Raised by `check_charge_limits()` or `check_discharge_limits()` when the requested power exceeds the device maximum.
|
|
343
|
+
|
|
344
|
+
**Attributes:** `power`, `max_power`, `generation`
|
|
345
|
+
|
|
346
|
+
### `SocBelowMinimumError`
|
|
347
|
+
|
|
348
|
+
Raised by `check_charge_limits()` or `check_discharge_limits()` when the target SOC is below the hard minimum of 5%.
|
|
349
|
+
|
|
350
|
+
**Attributes:** `target_soc`, `minimum_soc`
|
|
351
|
+
|
|
278
352
|
**Example:**
|
|
279
353
|
|
|
280
354
|
```python
|
|
@@ -4,16 +4,24 @@ from .client import (
|
|
|
4
4
|
APIException,
|
|
5
5
|
DiscoveredDevice,
|
|
6
6
|
IndevoltAPI,
|
|
7
|
+
MINIMUM_SOC,
|
|
8
|
+
POWER_LIMITS,
|
|
9
|
+
PowerExceedsMaxError,
|
|
10
|
+
SocBelowMinimumError,
|
|
7
11
|
TimeOutException,
|
|
8
12
|
async_discover,
|
|
9
13
|
)
|
|
10
14
|
|
|
11
|
-
__version__ = "1.
|
|
15
|
+
__version__ = "1.3.1"
|
|
12
16
|
|
|
13
17
|
__all__ = [
|
|
14
18
|
"IndevoltAPI",
|
|
15
19
|
"APIException",
|
|
20
|
+
"DiscoveredDevice",
|
|
21
|
+
"MINIMUM_SOC",
|
|
22
|
+
"POWER_LIMITS",
|
|
23
|
+
"PowerExceedsMaxError",
|
|
24
|
+
"SocBelowMinimumError",
|
|
16
25
|
"TimeOutException",
|
|
17
26
|
"async_discover",
|
|
18
|
-
"DiscoveredDevice",
|
|
19
27
|
]
|
|
@@ -18,6 +18,31 @@ class APIException(Exception):
|
|
|
18
18
|
"""Raised on client error during API call."""
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
MINIMUM_SOC: int = 5
|
|
22
|
+
|
|
23
|
+
POWER_LIMITS: dict[int, dict[str, int]] = {
|
|
24
|
+
1: {"max_discharge_power": 800, "max_charge_power": 1200},
|
|
25
|
+
2: {"max_discharge_power": 2400, "max_charge_power": 2400},
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PowerExceedsMaxError(Exception):
|
|
30
|
+
"""Raised when requested (dis)charge power exceeds the device maximum."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, power: int, max_power: int, generation: int) -> None:
|
|
33
|
+
self.power = power
|
|
34
|
+
self.max_power = max_power
|
|
35
|
+
self.generation = generation
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class SocBelowMinimumError(Exception):
|
|
39
|
+
"""Raised when target SOC is below the API's hard minimum."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, target_soc: int) -> None:
|
|
42
|
+
self.target_soc = target_soc
|
|
43
|
+
self.minimum_soc = MINIMUM_SOC
|
|
44
|
+
|
|
45
|
+
|
|
21
46
|
# Discovery configuration
|
|
22
47
|
DISCOVERY_PORT = 10000
|
|
23
48
|
BROADCAST_PORT = 8099
|
|
@@ -282,6 +307,44 @@ class IndevoltAPI:
|
|
|
282
307
|
|
|
283
308
|
return bool(response.get("result", False))
|
|
284
309
|
|
|
310
|
+
def check_charge_limits(self, power: int, target_soc: int, generation: int) -> None:
|
|
311
|
+
"""Check that charge parameters do not exceed device limits.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
power: Requested charge power in watts
|
|
315
|
+
target_soc: Target state of charge percentage
|
|
316
|
+
generation: Device hardware generation (1 or 2)
|
|
317
|
+
|
|
318
|
+
Raises:
|
|
319
|
+
PowerExceedsMaxError: If power exceeds the device maximum
|
|
320
|
+
SocBelowMinimumError: If target_soc is below MINIMUM_SOC
|
|
321
|
+
"""
|
|
322
|
+
max_power = POWER_LIMITS[generation]["max_charge_power"]
|
|
323
|
+
if power > max_power:
|
|
324
|
+
raise PowerExceedsMaxError(power, max_power, generation)
|
|
325
|
+
if target_soc < MINIMUM_SOC:
|
|
326
|
+
raise SocBelowMinimumError(target_soc)
|
|
327
|
+
|
|
328
|
+
def check_discharge_limits(
|
|
329
|
+
self, power: int, target_soc: int, generation: int
|
|
330
|
+
) -> None:
|
|
331
|
+
"""Check that discharge parameters do not exceed device limits.
|
|
332
|
+
|
|
333
|
+
Args:
|
|
334
|
+
power: Requested discharge power in watts
|
|
335
|
+
target_soc: Target state of charge percentage
|
|
336
|
+
generation: Device hardware generation (1 or 2)
|
|
337
|
+
|
|
338
|
+
Raises:
|
|
339
|
+
PowerExceedsMaxError: If power exceeds the device maximum
|
|
340
|
+
SocBelowMinimumError: If target_soc is below MINIMUM_SOC
|
|
341
|
+
"""
|
|
342
|
+
max_power = POWER_LIMITS[generation]["max_discharge_power"]
|
|
343
|
+
if power > max_power:
|
|
344
|
+
raise PowerExceedsMaxError(power, max_power, generation)
|
|
345
|
+
if target_soc < MINIMUM_SOC:
|
|
346
|
+
raise SocBelowMinimumError(target_soc)
|
|
347
|
+
|
|
285
348
|
async def get_config(self) -> dict[str, Any]:
|
|
286
349
|
"""Get system configuration from the device.
|
|
287
350
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: indevolt-api
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: Python API client for Indevolt devices
|
|
5
5
|
Author: A. Gideonse
|
|
6
6
|
License: MIT
|
|
@@ -223,6 +223,64 @@ config = await api.get_config()
|
|
|
223
223
|
print(config)
|
|
224
224
|
```
|
|
225
225
|
|
|
226
|
+
#### `check_charge_limits(power: int, target_soc: int, generation: int) -> None`
|
|
227
|
+
|
|
228
|
+
Check that charge parameters do not exceed device limits. Raises an exception if any boundary is violated.
|
|
229
|
+
|
|
230
|
+
**Parameters:**
|
|
231
|
+
|
|
232
|
+
- `power` (int): Requested charge power in watts
|
|
233
|
+
- `target_soc` (int): Target state of charge percentage
|
|
234
|
+
- `generation` (int): Device hardware generation (`1` or `2`), available from `get_config()` under `device.generation`
|
|
235
|
+
|
|
236
|
+
**Raises:**
|
|
237
|
+
|
|
238
|
+
- `PowerExceedsMaxError`: If `power` exceeds the maximum for the given generation
|
|
239
|
+
- `SocBelowMinimumError`: If `target_soc` is below `MINIMUM_SOC` (5%)
|
|
240
|
+
|
|
241
|
+
**Example:**
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
config = await api.get_config()
|
|
245
|
+
generation = config["device"]["generation"]
|
|
246
|
+
|
|
247
|
+
try:
|
|
248
|
+
api.check_charge_limits(power=1000, target_soc=80, generation=generation)
|
|
249
|
+
except PowerExceedsMaxError as e:
|
|
250
|
+
print(f"Power {e.power}W exceeds max {e.max_power}W for gen {e.generation}")
|
|
251
|
+
except SocBelowMinimumError as e:
|
|
252
|
+
print(f"Target SOC {e.target_soc}% is below minimum {e.minimum_soc}%")
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### `check_discharge_limits(power: int, target_soc: int, generation: int) -> None`
|
|
256
|
+
|
|
257
|
+
Check that discharge parameters do not exceed device limits. Raises an exception if any boundary is violated.
|
|
258
|
+
|
|
259
|
+
**Parameters:**
|
|
260
|
+
|
|
261
|
+
- `power` (int): Requested discharge power in watts
|
|
262
|
+
- `target_soc` (int): Target state of charge percentage
|
|
263
|
+
- `generation` (int): Device hardware generation (`1` or `2`), available from `get_config()` under `device.generation`
|
|
264
|
+
|
|
265
|
+
**Raises:**
|
|
266
|
+
|
|
267
|
+
- `PowerExceedsMaxError`: If `power` exceeds the maximum for the given generation
|
|
268
|
+
- `SocBelowMinimumError`: If `target_soc` is below `MINIMUM_SOC` (5%)
|
|
269
|
+
|
|
270
|
+
**Example:**
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
config = await api.get_config()
|
|
274
|
+
generation = config["device"]["generation"]
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
api.check_discharge_limits(power=600, target_soc=10, generation=generation)
|
|
278
|
+
except PowerExceedsMaxError as e:
|
|
279
|
+
print(f"Power {e.power}W exceeds max {e.max_power}W for gen {e.generation}")
|
|
280
|
+
except SocBelowMinimumError as e:
|
|
281
|
+
print(f"Target SOC {e.target_soc}% is below minimum {e.minimum_soc}%")
|
|
282
|
+
```
|
|
283
|
+
|
|
226
284
|
### async_discover(timeout: float = 5.0) -> list[DiscoveredDevice]
|
|
227
285
|
|
|
228
286
|
Discover Indevolt devices on the local network using UDP broadcast.
|
|
@@ -265,7 +323,7 @@ if device.name:
|
|
|
265
323
|
|
|
266
324
|
## Exception Handling
|
|
267
325
|
|
|
268
|
-
The library provides
|
|
326
|
+
The library provides custom exceptions for API errors and limit violations.
|
|
269
327
|
|
|
270
328
|
### `APIException`
|
|
271
329
|
|
|
@@ -275,6 +333,22 @@ Raised when there's a client error during API communication (network errors, HTT
|
|
|
275
333
|
|
|
276
334
|
Raised when an API request times out (default timeout: 10 seconds).
|
|
277
335
|
|
|
336
|
+
### `ChargePowerExceedsMaxError` / `DischargePowerExceedsMaxError`
|
|
337
|
+
|
|
338
|
+
Replaced by `PowerExceedsMaxError`.
|
|
339
|
+
|
|
340
|
+
### `PowerExceedsMaxError`
|
|
341
|
+
|
|
342
|
+
Raised by `check_charge_limits()` or `check_discharge_limits()` when the requested power exceeds the device maximum.
|
|
343
|
+
|
|
344
|
+
**Attributes:** `power`, `max_power`, `generation`
|
|
345
|
+
|
|
346
|
+
### `SocBelowMinimumError`
|
|
347
|
+
|
|
348
|
+
Raised by `check_charge_limits()` or `check_discharge_limits()` when the target SOC is below the hard minimum of 5%.
|
|
349
|
+
|
|
350
|
+
**Attributes:** `target_soc`, `minimum_soc`
|
|
351
|
+
|
|
278
352
|
**Example:**
|
|
279
353
|
|
|
280
354
|
```python
|
|
@@ -197,6 +197,64 @@ config = await api.get_config()
|
|
|
197
197
|
print(config)
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
+
#### `check_charge_limits(power: int, target_soc: int, generation: int) -> None`
|
|
201
|
+
|
|
202
|
+
Check that charge parameters do not exceed device limits. Raises an exception if any boundary is violated.
|
|
203
|
+
|
|
204
|
+
**Parameters:**
|
|
205
|
+
|
|
206
|
+
- `power` (int): Requested charge power in watts
|
|
207
|
+
- `target_soc` (int): Target state of charge percentage
|
|
208
|
+
- `generation` (int): Device hardware generation (`1` or `2`), available from `get_config()` under `device.generation`
|
|
209
|
+
|
|
210
|
+
**Raises:**
|
|
211
|
+
|
|
212
|
+
- `PowerExceedsMaxError`: If `power` exceeds the maximum for the given generation
|
|
213
|
+
- `SocBelowMinimumError`: If `target_soc` is below `MINIMUM_SOC` (5%)
|
|
214
|
+
|
|
215
|
+
**Example:**
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
config = await api.get_config()
|
|
219
|
+
generation = config["device"]["generation"]
|
|
220
|
+
|
|
221
|
+
try:
|
|
222
|
+
api.check_charge_limits(power=1000, target_soc=80, generation=generation)
|
|
223
|
+
except PowerExceedsMaxError as e:
|
|
224
|
+
print(f"Power {e.power}W exceeds max {e.max_power}W for gen {e.generation}")
|
|
225
|
+
except SocBelowMinimumError as e:
|
|
226
|
+
print(f"Target SOC {e.target_soc}% is below minimum {e.minimum_soc}%")
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### `check_discharge_limits(power: int, target_soc: int, generation: int) -> None`
|
|
230
|
+
|
|
231
|
+
Check that discharge parameters do not exceed device limits. Raises an exception if any boundary is violated.
|
|
232
|
+
|
|
233
|
+
**Parameters:**
|
|
234
|
+
|
|
235
|
+
- `power` (int): Requested discharge power in watts
|
|
236
|
+
- `target_soc` (int): Target state of charge percentage
|
|
237
|
+
- `generation` (int): Device hardware generation (`1` or `2`), available from `get_config()` under `device.generation`
|
|
238
|
+
|
|
239
|
+
**Raises:**
|
|
240
|
+
|
|
241
|
+
- `PowerExceedsMaxError`: If `power` exceeds the maximum for the given generation
|
|
242
|
+
- `SocBelowMinimumError`: If `target_soc` is below `MINIMUM_SOC` (5%)
|
|
243
|
+
|
|
244
|
+
**Example:**
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
config = await api.get_config()
|
|
248
|
+
generation = config["device"]["generation"]
|
|
249
|
+
|
|
250
|
+
try:
|
|
251
|
+
api.check_discharge_limits(power=600, target_soc=10, generation=generation)
|
|
252
|
+
except PowerExceedsMaxError as e:
|
|
253
|
+
print(f"Power {e.power}W exceeds max {e.max_power}W for gen {e.generation}")
|
|
254
|
+
except SocBelowMinimumError as e:
|
|
255
|
+
print(f"Target SOC {e.target_soc}% is below minimum {e.minimum_soc}%")
|
|
256
|
+
```
|
|
257
|
+
|
|
200
258
|
### async_discover(timeout: float = 5.0) -> list[DiscoveredDevice]
|
|
201
259
|
|
|
202
260
|
Discover Indevolt devices on the local network using UDP broadcast.
|
|
@@ -239,7 +297,7 @@ if device.name:
|
|
|
239
297
|
|
|
240
298
|
## Exception Handling
|
|
241
299
|
|
|
242
|
-
The library provides
|
|
300
|
+
The library provides custom exceptions for API errors and limit violations.
|
|
243
301
|
|
|
244
302
|
### `APIException`
|
|
245
303
|
|
|
@@ -249,6 +307,22 @@ Raised when there's a client error during API communication (network errors, HTT
|
|
|
249
307
|
|
|
250
308
|
Raised when an API request times out (default timeout: 10 seconds).
|
|
251
309
|
|
|
310
|
+
### `ChargePowerExceedsMaxError` / `DischargePowerExceedsMaxError`
|
|
311
|
+
|
|
312
|
+
Replaced by `PowerExceedsMaxError`.
|
|
313
|
+
|
|
314
|
+
### `PowerExceedsMaxError`
|
|
315
|
+
|
|
316
|
+
Raised by `check_charge_limits()` or `check_discharge_limits()` when the requested power exceeds the device maximum.
|
|
317
|
+
|
|
318
|
+
**Attributes:** `power`, `max_power`, `generation`
|
|
319
|
+
|
|
320
|
+
### `SocBelowMinimumError`
|
|
321
|
+
|
|
322
|
+
Raised by `check_charge_limits()` or `check_discharge_limits()` when the target SOC is below the hard minimum of 5%.
|
|
323
|
+
|
|
324
|
+
**Attributes:** `target_soc`, `minimum_soc`
|
|
325
|
+
|
|
252
326
|
**Example:**
|
|
253
327
|
|
|
254
328
|
```python
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|