Skip to main content

Python client for Kospel C.MI electric heater HTTP API

Project description

kospel-cmi-lib

Python client for the Kospel C.MI electric heater HTTP API.

This library provides a Python client for controlling Kospel C.MI electric heaters via their HTTP API. It is designed for integration with Home Assistant and other automation systems, and supports device discovery, register-based control, and offline development with a YAML simulator.

Features

  • Async-first: Built on asyncio and aiohttp for non-blocking I/O
  • Type-safe: Strict type hinting throughout
  • Device-specific API: Explicit properties and async setters on EkcoM3
  • Simulator-capable: Full simulator for offline development and testing (no hardware required)
  • Protocol-based: Decoder/encoder interfaces via Python Protocol types
  • Device discovery: probe_device() and discover_devices() to find Kospel devices on the network (no device_id required)

Implemented Features

  • Heater mode control (OFF, SUMMER, WINTER, PARTY, VACATION, MANUAL)
  • CWU (water) mode and temperatures (economy, comfort)
  • Manual heating temperature
  • Device discovery (CLI kospel-discover + Python API)
  • Register scanner and live scanner tools (kospel-scan-registers, kospel-scan-live)
  • YAML backend for offline testing (no hardware required)

Installation

# With uv (recommended)
uv add kospel-cmi-lib

# With pip
pip install kospel-cmi-lib

Quick Start

  1. Install: uv add kospel-cmi-lib or pip install kospel-cmi-lib
  2. Discover device: Run kospel-discover or use probe_device(session, "192.168.x.x") to get api_base_url
  3. Connect and read: Create EkcoM3 with HttpRegisterBackend(session, api_base_url) and call refresh()

Usage

Create a register backend (HTTP or YAML) and pass it to EkcoM3. When using HttpRegisterBackend, call aclose() or use the controller as an async context manager to release the HTTP session when done.

Recommended: async context manager (resources released automatically):

import asyncio
import aiohttp
from kospel_cmi.controller.device import EkcoM3
from kospel_cmi.kospel.backend import HttpRegisterBackend, YamlRegisterBackend
from kospel_cmi.registers.enums import HeaterMode


async def main() -> None:
    api_base_url = "http://192.168.1.1/api/dev/65"  # Replace with your heater URL
    async with aiohttp.ClientSession() as session:
        backend = HttpRegisterBackend(session, api_base_url)
        async with EkcoM3(backend=backend) as controller:
            await controller.refresh()
            print(controller.heater_mode)  # Read property
            await controller.set_heater_mode(HeaterMode.MANUAL)  # Write immediately
    # Session and controller resources released here


asyncio.run(main())

Alternative: explicit aclose() (for long-lived integrations):

controller = EkcoM3(backend=HttpRegisterBackend(session, api_base_url))
try:
    await controller.refresh()
    # ... use controller ...
finally:
    await controller.aclose()

For offline development or tests, use the YAML backend (no HTTP, no close needed):

backend = YamlRegisterBackend(state_file="/path/to/state.yaml")
controller = EkcoM3(backend=backend)
await controller.refresh()

Device Discovery

CLI — scan network and list devices (no config needed):

kospel-discover                    # Scans common subnets
kospel-discover 192.168.101.0/24  # Scan specific subnet

Python API:

import aiohttp
from kospel_cmi import probe_device, discover_devices

async with aiohttp.ClientSession() as session:
    info = await probe_device(session, "192.168.101.49")
    if info:
        print(f"Found: {info.serial_number}, {info.api_base_url}")

    found = await discover_devices(session, "192.168.101.0/24")
    for device in found:
        print(device.host, device.serial_number, device.api_base_url)

Setting Heater Mode

import asyncio
import aiohttp
from kospel_cmi.controller.device import EkcoM3
from kospel_cmi.kospel.backend import HttpRegisterBackend
from kospel_cmi.registers.enums import CwuMode, HeaterMode

async def main():
    async with aiohttp.ClientSession() as session:
        backend = HttpRegisterBackend(session, "http://192.168.1.1/api/dev/65")
        async with EkcoM3(backend=backend) as controller:
            await controller.refresh()

            # Manual heating: mode + temperature in one call (recommended)
            await controller.set_manual_heating(22.0)

            # Or use individual setters (each writes immediately)
            await controller.set_heater_mode(HeaterMode.WINTER)
            await controller.set_manual_temperature(22.0)

            # Water: set mode and temperature separately
            await controller.set_water_mode(CwuMode.COMFORT)
            await controller.set_water_comfort_temperature(38.0)
            await controller.set_water_economy_temperature(35.0)

asyncio.run(main())

Documentation

Module Documentation

Module-specific documentation is co-located with the code (GitHub automatically displays these when browsing directories):

  • kospel/ - HTTP API endpoints and protocol
  • registers/ - Register encoding, decoding, and mappings
  • controller/ - EkcoM3 device class
  • tools/ - Register scanner and live scanner for reverse-engineering

Project Documentation

Known Limitations

  • No authentication (assumes local network access)
  • HTTP only (no HTTPS)
  • Single device config (kospel_cmi_standard) — more variants planned for v2

Roadmap

v1.0.0 Engine & Explorer

  1. Local control - basic device functions can be operated using the library
  2. Robust interface - an interface for 3rd party tools (i.e., Home Assistant integration)
  3. Reverse-engineering toolset - kospel-scan-registers and kospel-scan-live for exploring registers

v2.0.0 Plug & Play for Kospel ecosystem

  1. Support multiple device types
  2. Device discovery
  3. Advanced state management (error and warning flags, fault detection, debug)

References

This library was reverse-engineered from JavaScript code used in the heater's web interface. Key findings:

  • Register encoding uses little-endian byte order
  • Flag bits are used for boolean settings within registers
  • Temperature and pressure values are scaled for precision
  • Read-Modify-Write pattern is required for setting flag bits

License

Apache License 2.0

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

kospel_cmi_lib-1.1.0.tar.gz (35.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kospel_cmi_lib-1.1.0-py3-none-any.whl (47.8 kB view details)

Uploaded Python 3

File details

Details for the file kospel_cmi_lib-1.1.0.tar.gz.

File metadata

  • Download URL: kospel_cmi_lib-1.1.0.tar.gz
  • Upload date:
  • Size: 35.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for kospel_cmi_lib-1.1.0.tar.gz
Algorithm Hash digest
SHA256 916e1f66da5fed7aa8d2a240d5ff18f45a1add4079b2b0f679622adc04101643
MD5 c6e510a51fd245e8c6b8447b2a8435d5
BLAKE2b-256 8d3214718c94a8018af01238948438917e05bf10c15e46de1bbc64eeaee334f3

See more details on using hashes here.

Provenance

The following attestation bundles were made for kospel_cmi_lib-1.1.0.tar.gz:

Publisher: release-pypi.yml on JanKrl/kospel-cmi-lib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kospel_cmi_lib-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: kospel_cmi_lib-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 47.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for kospel_cmi_lib-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5ff1b184b0a8a2c1c5d65b8c995d4e87af95cdcf0fbd03a6c1de40114f46f387
MD5 3a038f7a285974b488310de8bd63b53e
BLAKE2b-256 e389812468e8b95c657d3d3cedd6cbe83cafdf06e1bf3e58ccb55ca76d9ef910

See more details on using hashes here.

Provenance

The following attestation bundles were made for kospel_cmi_lib-1.1.0-py3-none-any.whl:

Publisher: release-pypi.yml on JanKrl/kospel-cmi-lib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page