License changed from AGPL-3.0-or-later to MIT. The LICENSE file now contains the MIT License. pyproject.toml SPDX expression and Trove classifier updated to match. No source-code changes; runtime behavior is unchanged. Downstream consumers should review the new license terms before upgrading.
Development dependencies moved from [project.optional-dependencies] to [dependency-groups] (PEP 735). The dev, test, and docs groups were never user-facing extras; they're for working on the package, not with it. They no longer appear as Provides-Extra: on PyPI. Local install: pip install -e . --group dev --group test --group docs (requires pip ≥ 25.1). CI workflows (test.yml, lint.yml, docs.yml) and CONTRIBUTING.md updated accordingly.
Python ≥ 3.13 required. The minimum supported Python version has been raised from 3.10 to 3.13 to align with Home Assistant Core 2026.5 and to drop the async-timeout dependency (now part of the stdlib as asyncio.timeout).
Relay value semantics fixed.Relay.__init__ previously passed the already-computed value (offset + gain × raw) as the raw value to the parent DataObject.__init__, causing the transform to be applied twice. For controllers with non-trivial offset/gain values this produced incorrect relay state reads. Fixed to pass raw_value so the transform is applied exactly once. Controllers with offset=0, gain=1 (the typical case) are unaffected.
async-timeout dependency removed. Replace any direct use of async_timeout with asyncio.timeout (Python 3.11+ stdlib).
TimeoutException is now actually raised (it was defined but never used in v1.x; ProconipApiException was raised instead). Code that catches ProconipApiException for timeouts will still work, but narrowing to TimeoutException is now possible and recommended.
src/setup.py removed. The package is now built exclusively with hatchling and hatch-vcs.
Top-level from proconip import ... imports: all public classes, functions, and exceptions are now re-exported from proconip.__init__.
proconip.__version__ attribute (derived from git tags via hatch-vcs).
py.typed marker (PEP 561) — the package is now typed.
EXTERNAL_RELAY_ID_OFFSET constant (replaces magic number 8).
GetDmxData.__iter__ — for channel in dmx_data: now works via an explicit iterator.
InvalidPayloadException class — raised by GetStateData and GetDmxData when the controller's payload is empty or truncated.
configurable timeout parameter (timeout: float = 10.0) on all public async functions; the timeout now wraps both the request and response body read.
OO wrappers (GetState, RelaySwitch, DosageControl, DmxControl) now accept a timeout argument in __init__ and on every async method (defaults to 10.0 seconds; the method-level argument, when supplied, overrides the value bound in the constructor).
CHANGELOG.md (this file) — release notes extracted from README.
Documentation site at https://ylabonte.github.io/proconip-pypi/ built with MkDocs Material + mkdocstrings; rebuilds on every main push and release. Source docstrings audited and expanded throughout the public surface.
CLAUDE.md — project memory for AI agents (and humans) capturing tech stack, conventions, and pitfalls.
Relay.__init__ double-applies offset+gain (see Breaking Changes above).
GetStateData.__init__ and GetDmxData.__init__: bounds check before index access in the leading-blank-line skip loop (while line < len(lines) and ... instead of while len(lines[line]...) and line < len(lines)).
GetStateData._parse: _digital_objects renamed to _digital_input_objects — aligns with the class annotation and the digital_input_objects property.
GetStateData.get_dosage_relay return type changed from int (with False fallback) to int | None.
GetStateData.get_ntp_fault_state_as_str: rewritten to handle composite bit-flag values correctly (e.g. value 3 = bits 1+2, returns highest-severity bit's description).
is_dosage_relay: BadRelayException now includes a descriptive message when data_object.category is not a relay category.
async_switch_off docstring said "Switch on" — corrected to "Switch off".
Relay.is_auto_mode docstring said "manual mode" — corrected to "auto mode".
determine_overall_relay_bit_state docstring typo ("relay a bit state" → "relay bit state").
async_get_raw_dmx and DmxControl.async_get_raw_dmx docstrings referenced GetState.csv — corrected to GetDmx.csv.
DmxControl class docstring said "GetDmx class" — corrected to "DmxControl class".
Build system: hatchling + hatch-vcs (git-tag-based versioning). Version no longer hard-coded in source.
Dependencies declared in [project.dependencies] in pyproject.toml (were missing — wheel shipped with no deps).
Runtime dependencies: aiohttp>=3.10,<4 and yarl>=1.9,<2 (ranges compatible with HA Core 2026.5 pins of aiohttp==3.13.5 and yarl==1.23.0).
Exception classes moved to the top of api.py (were at the bottom, referenced before definition).
Exception handling in async_get_raw_data / async_post_usrcfg_cgi: extracted _handle_response helper; BadCredentialsException now propagates correctly instead of being accidentally re-wrapped as BadStatusCodeException.
@dataclasses.dataclass decorator removed from all classes (had no effect since each class defines __init__).
Linting: black replaced by ruff (lint + format); mypy added for type checking.