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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: indevolt-api
3
- Version: 1.2.3
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 two custom exceptions:
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.2.3"
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.2.3
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 two custom exceptions:
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,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "indevolt-api"
7
- version = "1.2.3"
7
+ version = "1.3.1"
8
8
  description = "Python API client for Indevolt devices"
9
9
  readme = "readme.md"
10
10
  authors = [
@@ -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 two custom exceptions:
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