Python API client for Indevolt devices
Project description
Indevolt API
Python client library for communicating with Indevolt devices (home battery systems).
Features
- Async/await support using aiohttp
- Fully typed with type hints
- Simple and intuitive API
- Comprehensive error handling
Installation
pip install indevolt-api
Quick Start
import asyncio
import aiohttp
from indevolt_api import IndevoltAPI
async def main():
async with aiohttp.ClientSession() as session:
api = IndevoltAPI(host="192.168.1.100", port=8080, session=session)
# Get device configuration
config = await api.get_config()
print(f"Device config: {config}")
# Fetch data from specific cJson points
data = await api.fetch_data(["7101", "1664"])
print(f"Data: {data}")
# Write data (single data point) to device
response = await api.set_data("1142", 50)
print(f"Set data response: {response}")
# Write data (multiple data points) to device
response = await api.set_data("47015", [2, 700, 5])
print(f"Set data response: {response}")
asyncio.run(main())
Device Discovery
The library supports automatic discovery of Indevolt devices on your local network using UDP broadcast.
Quick Discovery Example
import asyncio
import aiohttp
from indevolt_api import async_discover, IndevoltAPI
async def main():
# Discover devices on the network (overrides default 5-second timeout)
devices = await async_discover(timeout=3.0)
if not devices:
print("No devices found")
return
print(f"Found {len(devices)} device(s):")
for device in devices:
print(f" - {device.host}:{device.port} (name: {device.name})")
# Connect to the first discovered device
async with aiohttp.ClientSession() as session:
api = IndevoltAPI.from_discovered_device(devices[0], session)
config = await api.get_config()
print(f"Device config: {config}")
asyncio.run(main())
Discovery Details
The discovery mechanism:
- Sends AT command
AT+IGDEVICEIPvia UDP broadcast to255.255.255.255:8099 - Indevolt devices on the same network respond to local port
10000with their IP - Returns a list of
DiscoveredDeviceobjects with device information
Note: Ensure your device and computer are on the same local network and that UDP port 10000 is available.
API Reference
IndevoltAPI
__init__(host: str, port: int, session: aiohttp.ClientSession, timeout: float = 10.0)
Initialize the API client.
Parameters:
host(str): Device hostname or IP addressport(int): Device port number (typically 80 or 8080)session(aiohttp.ClientSession): An aiohttp client sessiontimeout(float): Request timeout in seconds (default: 10.0)
Example:
# Default 10-second timeout (recommended for local devices)
api = IndevoltAPI(host="192.168.1.100", port=8080, session=session)
# Custom timeout
api = IndevoltAPI(host="192.168.1.100", port=8080, session=session, timeout=15.0)
classmethod from_discovered_device(device: DiscoveredDevice, session: aiohttp.ClientSession, timeout: float = 10.0)
Create an API client from a discovered device.
Parameters:
device(DiscoveredDevice): A device object returned byasync_discover()session(aiohttp.ClientSession): An aiohttp client sessiontimeout(float): Request timeout in seconds (default: 10.0)
Returns:
- IndevoltAPI instance configured for the discovered device
Example:
devices = await async_discover()
if devices:
api = IndevoltAPI.from_discovered_device(devices[0], session)
async fetch_data(t: str | list[str]) -> dict[str, Any]
Fetch data from the device.
Parameters:
t: Single cJson point or list of cJson points to retrieve (e.g.,"7101"or["7101", "1664"])
Returns:
- Dictionary with device response containing cJson point data
Example:
# Single point
data = await api.fetch_data("7101")
# Multiple points
data = await api.fetch_data(["7101", "1664", "7102"])
async set_data(t: str | int, v: Any) -> bool
Write data to the device.
Parameters:
t: cJson point identifier (e.g.,"47015"or47015)v: Value(s) to write (automatically converted to list of integers)
Returns:
- True on success, false otherwhise
Example:
# Single value
await api.set_data("47016", 100)
# Multiple values
await api.set_data("47015", [2, 700, 5])
# String or int identifiers
await api.set_data(47016, "100")
async get_config() -> dict[str, Any]
Get system configuration from the device.
Returns:
- Dictionary with device system configuration
Example:
config = await api.get_config()
print(config)
check_charge_limits(power: int, target_soc: int, generation: int) -> None
Check that charge parameters do not exceed device limits. Raises an exception if any boundary is violated.
Parameters:
power(int): Requested charge power in wattstarget_soc(int): Target state of charge percentagegeneration(int): Device hardware generation (1or2), available fromget_config()underdevice.generation
Raises:
PowerExceedsMaxError: Ifpowerexceeds the maximum for the given generationSocBelowMinimumError: Iftarget_socis below the minimum SOC (5%)
Example:
config = await api.get_config()
generation = config["device"]["generation"]
try:
api.check_charge_limits(power=1000, target_soc=80, generation=generation)
except PowerExceedsMaxError as e:
print(f"Power {e.power}W exceeds max {e.max_power}W for gen {e.generation}")
except SocBelowMinimumError as e:
print(f"Target SOC {e.target_soc}% is below minimum {e.minimum_soc}%")
check_discharge_limits(power: int, target_soc: int, generation: int) -> None
Check that discharge parameters do not exceed device limits. Raises an exception if any boundary is violated.
Parameters:
power(int): Requested discharge power in wattstarget_soc(int): Target state of charge percentagegeneration(int): Device hardware generation (1or2), available fromget_config()underdevice.generation
Raises:
PowerExceedsMaxError: Ifpowerexceeds the maximum for the given generationSocBelowMinimumError: Iftarget_socis below the minimum SOC (5%)
Example:
config = await api.get_config()
generation = config["device"]["generation"]
try:
api.check_discharge_limits(power=600, target_soc=10, generation=generation)
except PowerExceedsMaxError as e:
print(f"Power {e.power}W exceeds max {e.max_power}W for gen {e.generation}")
except SocBelowMinimumError as e:
print(f"Target SOC {e.target_soc}% is below minimum {e.minimum_soc}%")
async_discover(timeout: float = 3.0) -> list[DiscoveredDevice]
Discover Indevolt devices on the local network using UDP broadcast.
Parameters:
timeout(float): Discovery timeout in seconds (default: 5.0 for local discovery)
Returns:
- List of
DiscoveredDeviceobjects representing found devices
Example:
devices = await async_discover(timeout=3.0)
for device in devices:
print(f"Found: {device.host}:{device.port}")
DiscoveredDevice
Represents a discovered Indevolt device with the following attributes:
Attributes:
host(str): Device IP addressport(int): Device port number (default: 8080)name(str | None): Device name if provided in discovery responsemetadata(dict): Additional device information from discovery response
Example:
device = devices[0]
print(f"Device at {device.host}:{device.port}")
if device.name:
print(f"Name: {device.name}")
Exception Handling
The library provides custom exceptions for API errors and limit violations.
APIException
Raised when there's a client error during API communication (network errors, HTTP errors).
TimeOutException
Raised when an API request times out (default timeout: 10 seconds).
PowerExceedsMaxError
Raised by check_charge_limits() or check_discharge_limits() when the requested power exceeds the device maximum.
Attributes: power, max_power, generation
SocBelowMinimumError
Raised by check_charge_limits() or check_discharge_limits() when the target SOC is below the hard minimum of 5%.
Attributes: target_soc, minimum_soc
Example:
from indevolt_api import IndevoltAPI, APIException, TimeOutException
try:
data = await api.fetch_data("7101")
except TimeOutException:
print("Request timed out")
except APIException as e:
print(f"API error: {e}")
Note: You can adjust the timeout when creating the API client:
# Increase timeout if needed (e.g., for slower networks)
api = IndevoltAPI(host="192.168.1.100", port=8080, session=session, timeout=10.0)
Constants and Enums
All register keys and action values are available as typed IntEnum classes, importable directly from indevolt_api.
IndevoltConfig
Register keys for configurable device settings (read and write).
from indevolt_api import IndevoltConfig
# Write registers
IndevoltConfig.WRITE_ENERGY_MODE # 47005
IndevoltConfig.WRITE_DISCHARGE_LIMIT # 1142
# ... and more
# Read registers
IndevoltConfig.READ_ENERGY_MODE # 7101
IndevoltConfig.READ_DISCHARGE_LIMIT # 6105
# ... and more
IndevoltRealtimeAction
Action values for real-time control mode, used with SET_REALTIME_ACTION.
from indevolt_api import IndevoltRealtimeAction
IndevoltRealtimeAction.STOP # 0
IndevoltRealtimeAction.CHARGE # 1
IndevoltRealtimeAction.DISCHARGE # 2
IndevoltEnergyMode
Energy mode values for IndevoltConfig.WRITE_ENERGY_MODE.
from indevolt_api import IndevoltEnergyMode
IndevoltEnergyMode.OUTDOOR_PORTABLE
IndevoltEnergyMode.SELF_CONSUMED_PRIORITIZED
IndevoltEnergyMode.REAL_TIME_CONTROL
IndevoltEnergyMode.CHARGE_DISCHARGE_SCHEDULE
IndevoltBattery, IndevoltSystem, IndevoltGrid, IndevoltSolar
Register key enums for reading battery, system-level, grid, and solar data points.
from indevolt_api import IndevoltBattery, IndevoltSystem, IndevoltGrid, IndevoltSolar
data = await api.fetch_data([
IndevoltBattery.SOC,
IndevoltBattery.POWER,
IndevoltSystem.OUTPUT_POWER,
IndevoltGrid.METER_POWER_GEN2,
IndevoltSolar.DC_INPUT_POWER_1,
])
SET_REALTIME_ACTION
The register key used to send real-time charge/discharge commands to the device.
from indevolt_api import SET_REALTIME_ACTION
await api.set_data(SET_REALTIME_ACTION, [IndevoltRealtimeAction.CHARGE, 700, 80])
DEVICE_LIMITS
Dictionary of per-generation device limits used by check_charge_limits() and check_discharge_limits().
from indevolt_api import DEVICE_LIMITS
print(DEVICE_LIMITS[1]) # {'max_discharge_power': 800, 'max_charge_power': 1200, 'minimum_soc': 5}
print(DEVICE_LIMITS[2]) # {'max_discharge_power': 2400, 'max_charge_power': 2400, 'minimum_soc': 5}
Requirements
- Python 3.11+
- aiohttp >= 3.9.0
License
MIT License - see LICENSE file for details
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file indevolt_api-1.4.3.tar.gz.
File metadata
- Download URL: indevolt_api-1.4.3.tar.gz
- Upload date:
- Size: 12.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
87369cdbf7136215cf376d66afb07d25051e9a5d4e4f020052832b69e1d3e36a
|
|
| MD5 |
77d98d29214443841c1f2d165ab9506e
|
|
| BLAKE2b-256 |
3e72806e108724400758a0c024feea47f702dc037c925457fb3c54b2af1be072
|
File details
Details for the file indevolt_api-1.4.3-py3-none-any.whl.
File metadata
- Download URL: indevolt_api-1.4.3-py3-none-any.whl
- Upload date:
- Size: 11.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb1bf5e82266f52c53ce810fc01d1ba0974b6b7448eb1172a0ab9774e3afa573
|
|
| MD5 |
41d651ba33d383aa6c2806848c96a8db
|
|
| BLAKE2b-256 |
bee046b6170790f7216e28fe6b48cc03a9ddac8bbb89cf19f4227c828fd0c95a
|