Async Python client for the Duco ventilation API
Project description
python-duco-client
Async Python client for the DUCO ventilation box local REST API.
The client uses the unauthenticated Connectivity Board API surface. On some
firmware versions this means optional fields like node temperature,
reported_api_version, endpoint inventory details, and extended diagnostics
may be unavailable.
Installation
pip install python-duco-client
Quick start
import asyncio
import aiohttp
from duco import DucoClient
async def main():
async with aiohttp.ClientSession() as session:
client = DucoClient(session=session, host="192.168.1.100")
board = await client.async_get_board_info()
print(f"Box: {board.box_name} ({board.box_sub_type_name})")
nodes = await client.async_get_nodes()
for node in nodes:
print(f"Node {node.node_id}: {node.general.node_type}")
if node.sensor and node.sensor.co2 is not None:
print(f" CO2: {node.sensor.co2} ppm")
await client.async_set_ventilation_state(1, "MAN2")
asyncio.run(main())
CLI
duco --host 192.168.1.100 info
duco --host 192.168.1.100 nodes
duco --host 192.168.1.100 set 1 MAN2
Documentation
See the docs/ folder for the full documentation:
License
MIT. See LICENSE for details.
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
0.6.1 - 2026-05-09
Documentation
- Add
ACKNOWLEDGEMENTS.mdand link it fromREADME.mdto document the historical attribution for the removed API key generation implementation.
0.6.0 - 2026-05-08
Removed
- Remove API key generation and authenticated request support from
DucoClient. The library now uses the unauthenticated Connectivity Board API subset only. - Remove
DucoAuthenticationErrorfrom the public exception surface.
Changed
- Document that some firmware versions return a reduced unauthenticated
dataset. In practice this can affect optional node temperature values,
extended diagnostics,
reported_api_version, and endpoint inventory data.
0.5.0 - 2026-05-08
Added
async_detect_board_family(host, session, ssl_context, timeout)— standalone async helper that detects the board family of a Duco box without requiring aDucoClientinstance. Probes HTTPS first (/info?module=General&submodule=Board) and falls back to HTTP (/nodeinfoget?node=1) when HTTPS fails with a transport or protocol error.BoardFamilyStrEnum (CONNECTIVITY_BOARD,COMMUNICATION_PRINT) returned by the detection helper. Both are exported from the top-levelducopackage.- Both symbols are documented in
docs/api-reference.md.
Changed
- When the HTTPS probe returns any HTTP response (including 404), the host is
considered reachable. A subsequent HTTP transport failure in that case now
raises
DucoErrorinstead ofDucoConnectionError, so callers can correctly distinguish "host unreachable" from "host reachable but board type unrecognised".
0.4.2 - 2026-05-07
Added
DucoClientnow enforces a per-request timeout via a newrequest_timeoutconstructor parameter (default10.0seconds). A request that exceeds the timeout is raised asDucoConnectionError, consistent with other connection failures. Callers no longer need to wrap individual calls in their ownasyncio.timeout().
0.4.1 - 2026-05-07
Fixed
- Add
WI(Wi-Fi) toNetworkTypeenum so Duco nodes connected over Wi-Fi no longer raiseValueError: 'WI' is not a valid NetworkType. Any future unrecognised network type values now fall back toNetworkType.UNKNOWNinstead of crashing.
0.4.0 - 2026-05-04
Added
- Expose typed API metadata via
ApiEndpointInfoand the expandedApiInfomodel./apiresponses now includepublic_api_version, optionalreported_api_version, and typed endpoint inventory data.
Enhanced
- Extend
BoardInfowith optionalpublic_api_versionandsoftware_versionfields. - Parse optional version metadata defensively so older and newer firmware variants remain compatible.
- Expand unit and focused live integration coverage for API and board metadata.
- Update the published package description so PyPI includes both
README.mdandCHANGELOG.md.
0.3.10 - 2026-05-03
Fixed
_ensure_api_key:DucoConnectionErroris no longer wrapped asDucoAuthenticationError. Previously, a connection failure during API key generation was caught by the genericexcept DucoErrorhandler and re-raised asDucoAuthenticationError, bypassing callers that correctly handleDucoConnectionError. The exception is now re-raised unchanged; only genuine API failures are wrapped asDucoAuthenticationError.
Enhanced
- Fixed ruff code quality warnings across
src/andtests/: sorted__all__(RUF022), removed unusednoqadirective (RUF100), combinedelifbranches (SIM114), replaced EN dashes with hyphens in docstrings/comments (RUF002, RUF003), usednext(iter(...))instead of list slice (RUF015), combined nestedwithstatements (SIM117). - Fixed ruff docstring style (D413, COM812) across
src/duco/. Added per-file-ignore for T201 incli.py—print()is intentional CLI output.
0.3.9 - 2026-04-26
Added
build_ssl_context()is now part of the public API (exported fromduco).DucoClient.__init__accepts an optionalssl_contextparameter. When provided the caller controls when the context is built (e.g. in an executor so blocking I/O stays off the asyncio event loop). When omitted the behaviour is identical to previous releases.build_ssl_context()now caches its result so repeated calls are free of blocking I/O.
0.3.8 - 2026-04-26
Changed
DucoClient.__init__: defaultschemechanged from"http"to"https". All Duco Connectivity Board 2.0 boxes use HTTPS, and since v0.3.7 the client automatically constructs a valid SSL context using the bundled Duco CA certificate chain. Callers that need plain HTTP must now passscheme="http"explicitly.
Breaking change
Code that instantiates DucoClient without a scheme= argument and expects
HTTP behaviour must now pass scheme="http" explicitly.
0.3.7 - 2026-04-25
Added
- Bundle the Duco device CA certificate chain so HTTPS connections are verified
without requiring
verify_ssl=Falsein callers. The bundled chain contains ServerDeviceCert + Duco Intermediate COM CA + Duco Root CA. build_ssl_context()helper induco._sslbuilds a ready-to-usessl.SSLContextwith certificate verification enabled and hostname verification disabled (device cert SAN contains factory IP192.168.4.1, not the user-assigned IP).DucoClientautomatically uses the SSL context for HTTPS connections and passesssl=True(default behaviour) for plain HTTP connections.- CLI: add
--httpsflag (andDUCO_HTTPS=1env var) to select HTTPS; addtempandRHcolumns tonodesoutput; require--host(removed hardcoded default IP).
Fixed
- Fix missing
if __name__ == "__main__":guard incli.py.
Internal
- Add
tests/test_ssl.pywith 7 unit tests covering SSL context construction and wiring inDucoClient.
0.3.6 - 2026-04-25
Added
- Add temperature reading support for room nodes (
NodeTemperatureData). - New
DucoClient.get_node_temperature()method.
0.3.5 - 2026-04-21
Added
- Initial release with basic node info retrieval and action control.
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 python_duco_client-0.6.1.tar.gz.
File metadata
- Download URL: python_duco_client-0.6.1.tar.gz
- Upload date:
- Size: 33.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63e2ef4211f677d320c242a0a4bf548ecf023e6b1209d60fc79cef892a0289eb
|
|
| MD5 |
0cc054eaaf39fa1a22e5f000a8c69c4b
|
|
| BLAKE2b-256 |
ec9bf4dd132a7a0ec371faf29f0182c4fed5dd2c229cc21f146c3f280d11dc71
|
Provenance
The following attestation bundles were made for python_duco_client-0.6.1.tar.gz:
Publisher:
ci.yml on ronaldvdmeer/python-duco-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
python_duco_client-0.6.1.tar.gz -
Subject digest:
63e2ef4211f677d320c242a0a4bf548ecf023e6b1209d60fc79cef892a0289eb - Sigstore transparency entry: 1479710642
- Sigstore integration time:
-
Permalink:
ronaldvdmeer/python-duco-client@8b092b28de2d62e411180daf6c03ceb2470b58fa -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/ronaldvdmeer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@8b092b28de2d62e411180daf6c03ceb2470b58fa -
Trigger Event:
push
-
Statement type:
File details
Details for the file python_duco_client-0.6.1-py3-none-any.whl.
File metadata
- Download URL: python_duco_client-0.6.1-py3-none-any.whl
- Upload date:
- Size: 23.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00a50f40aad717392773cc1b8edba7597240772cd2d0bfa1e535f04218204aaf
|
|
| MD5 |
3c83b993004ce5377d74bc8ce134775e
|
|
| BLAKE2b-256 |
58b1468f9ef55012dd4ee1b35f365caedbdb85076bf5b8444d3c728e8609ace4
|
Provenance
The following attestation bundles were made for python_duco_client-0.6.1-py3-none-any.whl:
Publisher:
ci.yml on ronaldvdmeer/python-duco-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
python_duco_client-0.6.1-py3-none-any.whl -
Subject digest:
00a50f40aad717392773cc1b8edba7597240772cd2d0bfa1e535f04218204aaf - Sigstore transparency entry: 1479713630
- Sigstore integration time:
-
Permalink:
ronaldvdmeer/python-duco-client@8b092b28de2d62e411180daf6c03ceb2470b58fa -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/ronaldvdmeer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@8b092b28de2d62e411180daf6c03ceb2470b58fa -
Trigger Event:
push
-
Statement type: