python-duco-client
This project is deprecated. Future development moved to python-duco-connectivity. This repository remains available for historical reference and will receive no further development.
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.2 - 2026-05-10
Deprecated
- Mark
python-duco-clientas deprecated and inactive. - Move future development to
python-duco-connectivity. - Keep this repository available for historical reference as the final release line before archival.
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.
Metadata
Release files for python-duco-client 0.6.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| python_duco_client-0.6.2.tar.gz | 33.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| python_duco_client-0.6.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 57.5 kB
Release files / python_duco_client-0.6.2.tar.gz
| Download URL | python_duco_client-0.6.2.tar.gz |
|---|---|
| Size | 33.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e8a2feed477f92cd061e11b52e161f05c46fd095354b1dd54c9402ff1c1066e5
|
|
BLAKE2b-256 checksum How to use checksums |
9390e38a3b8ee6eeb47a5586589017e6f714c86f894f9668044e14e37e586309
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 10, 2026.
Transparency logRelease files / python_duco_client-0.6.2-py3-none-any.whl
| Download URL | python_duco_client-0.6.2-py3-none-any.whl |
|---|---|
| Size | 23.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1b1df03bcc39f32148ea7d5e749b3cb206b09e3151a493013e8d43ea59225176
|
|
BLAKE2b-256 checksum How to use checksums |
feb0ec91fc6c1c56625a5f41ea88c16a277819e518a78d703c0982cf307a7faa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 10, 2026.
Transparency log