Async Python interface for Kermi heat pumps via Modbus and HTTP
Project description
Kermi x-center Python Interface
Async Python interface for Kermi heat pumps via x-center module. Supports both HTTP API (recommended) and Modbus TCP/RTU.
Transport Options
| Feature | HTTP API | Modbus |
|---|---|---|
| API Status | Unofficial/Undocumented | Official (Kermi docs) |
| Setup Required | None | Kermi support activation |
| Datapoints | 250+ (all available) | ~90 (documented subset) |
| Efficiency | 2 API calls for all data | ~30 register reads |
| Device Discovery | Automatic | Manual configuration |
| Alarms | Current + History | Not available |
| IFM Access | Full (SmartGrid, I/O, S0) | Not available |
Recommendation: Use HTTP for most use cases. Use Modbus only if HTTP is unavailable or you need real-time polling at high frequency.
Requirements
Hardware Compatibility
This library is tested with:
- x-center IFM: Firmware version 1.6.3.42
- Heat pump: x-change dynamic pro ac 6 AW E (air/water heat pump)
- Buffer system: x-buffer combi pro (Puffersystemmodul)
Other Kermi heat pump models with x-center module should also work.
Modbus Activation (Modbus only)
IMPORTANT: Modbus must be activated on your x-center module before use.
Contact Kermi support to enable Modbus communication. For technical details, see docs/Kermi.Modbus.TCP_RTU_Quick.Guide_DE.pdf.
Features
- Async/await support - Modern async Python using
asyncio - Two transports - HTTP API (recommended) or Modbus TCP/RTU
- Four device types - IFM, Heat Pump, Storage System, and Universal Module
- Fully typed - Complete type hints for better IDE support
- Type-safe enums - Status and mode values as Python enums
- Auto-conversion - Automatic data type conversions
- Validation - Input validation with range checks
- Device discovery - Automatic detection of connected devices (HTTP)
Installation
pip install kermi-xcenter
For development:
pip install -e ".[dev]"
Quick Start
HTTP API (Recommended)
import asyncio
from kermi_xcenter import KermiHttpClient
async def main():
# Connect to x-center (password optional on some devices)
client = KermiHttpClient(host="192.168.1.100", password="1234")
async with client:
# Devices are auto-discovered
print(f"Found {len(client.devices)} devices")
for device in client.devices:
print(f" - {device.display_name} (Unit {device.unit_id})")
# Get all values efficiently (2 API calls)
values = await client.get_all_values(unit_id=40) # Heat Pump
print(f"Outdoor: {values.get('outdoor_temperature')}°C")
print(f"COP: {values.get('cop_total')}")
print(f"Power: {values.get('power_total')} kW")
# Get device info
info = await client.get_device_info(unit_id=40)
print(f"Model: {info.model}")
print(f"Serial: {info.serial_number}")
print(f"Firmware: {info.software_version}")
# Read IFM (x-center gateway) data
ifm_values = await client.get_all_values(unit_id=0)
print(f"SmartGrid State: {ifm_values.get('ifm_smartgrid_state')}")
print(f"S0 Power: {ifm_values.get('ifm_s0_power')} W")
# Check alarms
alarms = await client.get_current_alarms()
if alarms:
for alarm in alarms:
print(f"Alarm: {alarm.message}")
asyncio.run(main())
Modbus (Alternative)
import asyncio
from kermi_xcenter import KermiModbusClient, HeatPump
async def main():
client = KermiModbusClient(host="192.168.1.100", port=502)
heat_pump = HeatPump(client)
async with client:
outdoor_temp = await heat_pump.get_outdoor_temperature()
cop = await heat_pump.get_cop_total()
status = await heat_pump.get_heat_pump_status()
print(f"Outdoor: {outdoor_temp}°C")
print(f"COP: {cop}")
print(f"Status: {status.name}")
asyncio.run(main())
Supported Devices
IFM - x-center Interface Module (Unit 0, HTTP only)
The x-center gateway device itself:
- System info (serial, firmware, OS version)
- Network status (LAN states, IP, remote connection)
- SmartGrid/EVU signals (EVU, SGReady2, SmartGrid state)
- Digital I/O (LED1, LED2, Output1, Output2)
- S0 energy meter (power, pulse counter)
# HTTP only
values = await client.get_all_values(unit_id=0)
smartgrid = values.get('ifm_smartgrid_state') # 0-4
evu_active = values.get('ifm_evu_signal') # True/False
s0_power = values.get('ifm_s0_power') # Watts
Heat Pump (Unit 40)
Main heat pump control:
- Energy source temperatures
- Heat pump circuit (supply, return, flow rate)
- COP values (total, heating, hot water, cooling)
- Power measurements (thermal and electrical)
- Operating hours (fan, compressor, pumps)
- Status and alarms
- PV modulation controls
# HTTP
values = await client.get_all_values(unit_id=40)
cop = values.get('cop_total')
# Modbus
from kermi_xcenter import HeatPump
heat_pump = HeatPump(client, unit_id=40)
cop = await heat_pump.get_cop_total()
Storage System (Units 50/51)
Heating storage (50) and hot water storage (51):
- Storage temperatures (heating, cooling, hot water)
- Heating circuit control
- Operating modes and energy settings
- External heat generator control
# HTTP
heating_values = await client.get_all_values(unit_id=50)
hot_water_values = await client.get_all_values(unit_id=51)
# Modbus
from kermi_xcenter import StorageSystem
heating_storage = StorageSystem(client, unit_id=50)
hot_water_storage = StorageSystem(client, unit_id=51)
Universal Module (Unit 30, Modbus only)
Additional heating circuits:
- Heating circuit control and status
- Operating modes and energy settings
from kermi_xcenter import UniversalModule
universal = UniversalModule(client, unit_id=30)
Writing Values
HTTP
# Set hot water boost
await client.set_value("hot_water_boost_active", True, unit_id=51)
await client.set_value("hot_water_boost_setpoint", 55.0, unit_id=51)
# Control IFM outputs
await client.set_value("ifm_led1", True, unit_id=0)
await client.set_value("ifm_output1", False, unit_id=0)
Modbus
await heat_pump.set_pv_modulation_power(2000) # 2000W
await storage.set_hot_water_setpoint_constant(50.0)
await storage.set_heating_circuit_energy_mode(EnergyMode.ECO)
Connection Types
HTTP
client = KermiHttpClient(
host="192.168.1.100",
password="1234", # Optional on some devices
port=80, # Default HTTP port
timeout=10.0
)
Modbus TCP
client = KermiModbusClient(
host="192.168.1.100",
port=502,
timeout=3.0,
retries=3
)
Modbus RTU
client = KermiModbusClient(
port="/dev/ttyUSB0",
baudrate=9600,
use_rtu=True,
timeout=3.0
)
Examples
See the examples/ directory:
http_monitoring.py- HTTP client with device discovery and bulk readsbasic_monitoring.py- Modbus: Read temperatures, COP, power, and statuspv_modulation.py- Modbus: Control PV modulation for solar integrationstorage_control.py- Modbus: Control heating and hot water storagecontinuous_monitoring.py- Modbus: Continuous monitoring with periodic updates
Run an example:
python examples/http_monitoring.py --host 192.168.1.100 --password 1234
python examples/basic_monitoring.py
Data Types and Enums
from kermi_xcenter import (
HeatPumpStatus, # STANDBY, ALARM, HOT_WATER, COOLING, HEATING, etc.
HeatingCircuitStatus, # OFF, HEATING, COOLING, DEW_POINT, etc.
OperatingMode, # OFF, HEATING, COOLING
OperatingType, # AUTO, HEATING
EnergyMode, # OFF, ECO, NORMAL, COMFORT, CUSTOM
SeasonSelection, # AUTO, HEATING, COOLING, OFF
ExternalHeatGeneratorMode, # AUTO, HEAT_PUMP_ONLY, BOTH, SECONDARY_ONLY
)
Error Handling
from kermi_xcenter import (
KermiModbusError, # Base exception
ConnectionError, # Connection failed
RegisterReadError, # Read operation failed
RegisterWriteError, # Write operation failed
ValidationError, # Value out of range
HttpError, # HTTP API error
AuthenticationError, # HTTP authentication failed
DatapointNotWritableError, # Attempted write to read-only datapoint
)
try:
values = await client.get_all_values(unit_id=40)
except HttpError as e:
print(f"HTTP API error: {e}")
except AuthenticationError as e:
print(f"Authentication failed: {e}")
Architecture
kermi_xcenter/
├── client.py # Async Modbus client (TCP/RTU)
├── http/
│ ├── client.py # Async HTTP client
│ ├── session.py # HTTP session management
│ ├── mapping.py # WellKnownName to attribute mapping
│ └── models.py # HTTP data models
├── registers.py # Modbus register definitions
├── types.py # Enums and type aliases
├── exceptions.py # Custom exceptions
└── models/
├── base.py # Base device class
├── heat_pump.py # Heat pump (unit 40)
├── storage_system.py # Storage system (units 50/51)
└── universal_module.py # Universal module (unit 30)
Documentation
- HTTP API Specification - HTTP endpoints and datapoints
- OpenAPI Specification - Machine-readable API spec
- Modbus Specification - Complete register maps
- Project Plan - Architecture and design decisions
Development
Setup
python -m venv venv
source venv/bin/activate
pip install -e ".[dev]"
pre-commit install
Code Quality
black src/ tests/ examples/
ruff check src/ tests/ examples/
mypy src/
pytest
Requirements
- Python 3.12+
- pymodbus >= 3.6.0
- aiohttp >= 3.9.0
License
Apache License 2.0 - see LICENSE file for details.
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Ensure code passes linting and type checking
- Submit a pull request
Credits
This library is not affiliated with or endorsed by Kermi GmbH.
Support
For issues and questions:
- Create an issue on GitHub
- Check existing documentation in
docs/ - Review examples in
examples/
Changelog
0.3.0 (2026-01-06)
- Added HTTP API client (
KermiHttpClient) as recommended transport - Added IFM device support (SmartGrid, I/O, S0 meter)
- Added automatic device discovery
- Added efficient bulk reads (all datapoints in 2 API calls)
- Added alarm management (current and history)
- Added 40+ IFM datapoint mappings
- Added 180+ Heat Pump and Storage datapoint mappings
- Added HTTP API documentation and OpenAPI spec
- Tested with x-center IFM firmware 1.6.3.42
0.2.2 (2025-12-01)
- Fixed power and COP scaling (10x correction)
0.2.1 (2025-11-27)
- Added Codecov integration
- Fixed cleanup errors from malformed frames
0.2.0 (2025-11-27)
- Return None for unavailable registers (Pythonic API)
- Added resilient error handling for device firmware variations
0.1.0 (2025-11-27)
- Initial release
- Async/await support for all operations
- Support for three device types (Heat Pump, Storage System, Universal Module)
- Complete register definitions with English names
- Type-safe enums for all status and mode values
- Automatic data conversions
- TCP and RTU connection support
Disclaimer
This software is provided "as-is" without any warranty of any kind, express or implied.
-
The HTTP API implementation interfaces with an unofficial, undocumented API of the Kermi x-center. This API may change without notice in firmware updates, potentially breaking functionality.
-
The Modbus implementation is based on Kermi's official Modbus documentation.
-
This library is not affiliated with, endorsed by, or supported by Kermi GmbH.
-
Use at your own risk. The authors are not responsible for any damage to your equipment, loss of warranty, or other issues that may arise from using this software.
-
Always ensure you have appropriate backups and understand the implications before writing values to your heat pump system.
Project details
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 kermi_xcenter-0.3.1.tar.gz.
File metadata
- Download URL: kermi_xcenter-0.3.1.tar.gz
- Upload date:
- Size: 58.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c971150652ceea20199ea5fcd052e6a1cdd214ae00642692c32ad6e10ec0d7c
|
|
| MD5 |
ebfa790add915519051508f6ab28c54e
|
|
| BLAKE2b-256 |
3222c80374b7ddf6f74453a97781fb8dbe6754d2a1acf914a1d709d8a03d8285
|
Provenance
The following attestation bundles were made for kermi_xcenter-0.3.1.tar.gz:
Publisher:
release.yml on jr42/py-kermi-xcenter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kermi_xcenter-0.3.1.tar.gz -
Subject digest:
3c971150652ceea20199ea5fcd052e6a1cdd214ae00642692c32ad6e10ec0d7c - Sigstore transparency entry: 801763397
- Sigstore integration time:
-
Permalink:
jr42/py-kermi-xcenter@61bb7d9f330da962e4f7ba9784f97b796fa836d1 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/jr42
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@61bb7d9f330da962e4f7ba9784f97b796fa836d1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file kermi_xcenter-0.3.1-py3-none-any.whl.
File metadata
- Download URL: kermi_xcenter-0.3.1-py3-none-any.whl
- Upload date:
- Size: 51.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e14bb84ef88566377af83d791feb6bc8ce6a1885a31600ebea9826d3cb69c980
|
|
| MD5 |
6e85a5f872ad3d3dbe0278ba030366e0
|
|
| BLAKE2b-256 |
6268a2b290649e53c13334326a911daf0a26dc586e2aed1b49fa7e675a2732e6
|
Provenance
The following attestation bundles were made for kermi_xcenter-0.3.1-py3-none-any.whl:
Publisher:
release.yml on jr42/py-kermi-xcenter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kermi_xcenter-0.3.1-py3-none-any.whl -
Subject digest:
e14bb84ef88566377af83d791feb6bc8ce6a1885a31600ebea9826d3cb69c980 - Sigstore transparency entry: 801763429
- Sigstore integration time:
-
Permalink:
jr42/py-kermi-xcenter@61bb7d9f330da962e4f7ba9784f97b796fa836d1 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/jr42
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@61bb7d9f330da962e4f7ba9784f97b796fa836d1 -
Trigger Event:
release
-
Statement type: