Skip to main content

python-duco-connectivity

Async Python client for the local Duco HTTP API.

python-duco-connectivity is a small async client for the unauthenticated local Duco HTTP endpoints that were validated during initial development. The library keeps its public models close to the API payload shape and is intended to stay reusable outside Home Assistant.

Installation

Until the first PyPI release is published, install directly from GitHub:

pip install git+https://github.com/ronaldvdmeer/python-duco-connectivity.git

After the package is published on PyPI, install it with:

pip install python-duco-connectivity

The package also installs a duco-probe CLI and supports module execution for quick function probes against a local Duco box. When you are not running inside an activated virtual environment, use the explicit .venv/bin/... paths shown in the development examples below.

Current scope

  • HTTP only
  • asynchronous communication via aiohttp
  • typed stable config families for the documented /config branches
  • typed helpers for stable /info fields such as heat recovery filter time
  • natural empty results for optional capability discovery and explicit errors for strict capability access
  • typed models that stay close to the API response shape
  • preserved raw_payload data on typed response models for forward compatibility

Error handling

Discovery-style helpers use their natural empty result when a Duco box reports an optional capability as unsupported: filter time returns None, ventilation temperatures return an empty VentilationTemperatureInfo, and bulk bypass targets return {}. Malformed responses and operational failures remain exceptions. The strict parameter-specific bypass helper raises DucoUnsupportedCapabilityError for an unsupported target; this DucoResponseError subclass preserves the HTTP status, path, and response body. The bypass-target helpers only return models with complete and coherent value, minimum, increment, and maximum metadata. Bulk reads omit an invalid individual zone without suppressing valid zones. Parameter-specific reads and write responses raise DucoError when the requested target is missing, incomplete, or inconsistent. BypassSupplyTemperatureTarget.validate_value() checks a Celsius value against the target-specific range and step, while normalize_value() rounds converted values to the nearest supported step. Pass the target to async_set_bypass_supply_temperature_target(..., target=target) to validate a write without an additional read.

Diagnostic subsystem reads expose known status values as normalized DiagStatus members (ok, disabled, or error). Each DiagComponent also keeps the exact API value in raw_status; an unrecognized future value produces status=None without discarding the raw value. Subsystem names remain unfiltered so future components are available to downstream consumers. Direct construction using a pre-0.13 raw status string remains compatible and derives raw_status automatically; callers using a normalized DiagStatus must provide raw_status explicitly.

Getting started

import asyncio

import aiohttp

from duco_connectivity import DucoClient


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        client = DucoClient(session, "192.168.1.10")
        api_info = await client.async_get_api_info()
        nodes = await client.async_get_nodes_overview()

        print(api_info.public_api_version)
        print([node.node_id for node in nodes])


if __name__ == "__main__":
    asyncio.run(main())

Documentation map

Start with docs/api-reference.md when you want a compact inventory of the public client methods, exports, compatibility aliases, and construction rules.

  • docs/api-reference.md for the central public API inventory
  • docs/cli.md for the function probe CLI and shell examples
  • docs/config.md for system, node, and zone config reads and writes
  • docs/live-testing.md for local opt-in tests against a real Duco device
  • docs/replay-testing.md for local sample validation against ignored raw API captures
  • docs/actions.md for action discovery and execution
  • docs/nodes.md for node models and node information readers
  • docs/public-api-boundaries.md for the typed-model contract and raw escape hatch boundaries
  • docs/zones.md for zone and group info and config readers
  • docs/ventilation-states.md for ventilation enum values and compatibility members
  • docs/payload-preservation.md for raw payload preservation and raw endpoint access

The public surface keeps a deliberate split between stable typed readers and broader raw escape hatches. Use the typed methods when the model already matches the data you need, and use the raw helpers when you need endpoint coverage, selector flexibility, or payload fields that have not been typed yet. See docs/public-api-boundaries.md for the full contract.

Testing strategy

The repository uses three automated test layers:

  • Synthetic unit tests cover focused parser and client behavior with mocked HTTP responses.
  • Local sample-validation tests can replay a small set of typed client methods against your own ignored raw API captures.
  • Live tests validate read paths, safe writes, and latency probes against your own Duco device.

That split matters for Duco support. Synthetic tests keep day-to-day iteration fast. Local sample validation lets you check real captures without committing them or maintaining a sanitization workflow. Live tests confirm that the client still behaves correctly against actual hardware.

Public API maintenance

The compact API reference is generated from the published exports and public async client methods. Regenerate it after public surface changes with:

python tools/api_reference.py write

Development

From the repository root, use any activated virtual environment you prefer. The commands below use a local .venv so they stay copy-pasteable from a clean checkout. Create it first if needed, then install the development dependencies and run the same checks as CI:

python -m venv .venv
.venv/bin/python -m pip install -e ".[dev]"
.venv/bin/pytest
.venv/bin/ruff check src tests
.venv/bin/ruff format --check src tests
.venv/bin/mypy src
.venv/bin/bandit -r src -ll
.venv/bin/pip-audit --desc on

For local function probes without activating the environment first:

.venv/bin/python -m duco_connectivity --host 192.168.1.10 call async_get_board_info
.venv/bin/duco-probe --host 192.168.1.10 call async_get_board_info
.venv/bin/duco-probe --host 192.168.1.10 call async_get_ventilation_temperature_info
.venv/bin/duco-probe --host 192.168.1.10 call async_get_bypass_supply_temperature_targets
.venv/bin/duco-probe --host 192.168.1.10 call async_get_bypass_supply_temperature_target --kwargs '{"zone_id": 1}'

For local real-device validation against your own Duco box, use the opt-in workflow documented in docs/live-testing.md.

For local sample validation against ignored raw captures, use docs/replay-testing.md.

If you want to validate raw API captures locally, follow the layout guidance in docs/replay-testing.md and the fixture-specific notes in tests/fixtures/replay/README.md.

Validation

The current API surface was validated against a real Duco box during the first development pass, covering:

  • GET /api
  • GET /info with generic module, submodule, and parameter queries
  • GET /config with generic module, submodule, and parameter queries
  • PATCH /config with a no-op TimeZone write against the current value
  • GET /info?module=General&submodule=Board
  • GET /info?module=General&submodule=Lan
  • GET /info?module=Ventilation
  • GET /info?module=HeatRecovery
  • GET /info/nodes
  • GET /info?module=General&submodule=PublicApi
  • GET /config?module=HeatRecovery&submodule=Bypass&parameter=TempSupTgtZone1
  • PATCH /config?module=HeatRecovery&submodule=Bypass&parameter=TempSupTgtZone1 with a no-op write against the current value
  • POST /action/nodes/{node} with a no-op SetVentilationState

The repository now also includes opt-in local live tests so the same read and safe-write checks can be repeated against your own device without changing the default mock-only test workflow.

Metadata

Release files for python-duco-connectivity 0.15.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for python-duco-connectivity 0.15.0
File Size Uploaded
python_duco_connectivity-0.15.0.tar.gz 72.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for python-duco-connectivity 0.15.0
File Interpreter ABI Platform
python_duco_connectivity-0.15.0-py3-none-any.whl Python 3 none any Details

Total release size: 107.2 kB

Release files / python_duco_connectivity-0.15.0.tar.gz

Download URL python_duco_connectivity-0.15.0.tar.gz
Size 72.9 kB
Tags Source
SHA-256 checksum
How to use checksums
4bbb4ecef68d91ada3ec85babc9419d33e5382ae89fe3a311ca8d91c669a9562
BLAKE2b-256 checksum
How to use checksums
de7578dba15c7097cca3fa5e7bcf8fed728b17ff23378be3237d3c44d9e6f0ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.

Transparency log

Release files / python_duco_connectivity-0.15.0-py3-none-any.whl

Download URL python_duco_connectivity-0.15.0-py3-none-any.whl
Size 34.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7f95e7b6f83313e929655cf449278dccb0b48a26c61f32cb8fccc5b271ba665d
BLAKE2b-256 checksum
How to use checksums
fecca3c0ae0fec3f89351d6d4b5f25399b3589b0faaec53a7587adfa1bab2a90
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.

Transparency log

Release history Release notifications | RSS feed

0.18.0

2 release files

0.17.0

2 release files

0.16.0

2 release files

This release

0.15.0 This release

2 release files

0.14.0

2 release files

0.13.1

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page