From 0a11effade0df956c8f53bc5abcc84131c9debb4 Mon Sep 17 00:00:00 2001 From: Raphael Hehl <7577984+RaHehl@users.noreply.github.com> Date: Tue, 10 Nov 2026 18:26:40 +0100 Subject: [PATCH 1/2] Type the characteristic writes as HAP JSON A TypedDict instead of dict[str, Any] for one characteristic of a write, with aid and iid always present and value, ev and r optional. --- pyhap/accessory_driver.py | 5 +++-- pyhap/characteristic.py | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/pyhap/accessory_driver.py b/pyhap/accessory_driver.py index 7f7326f2..c4134feb 100644 --- a/pyhap/accessory_driver.py +++ b/pyhap/accessory_driver.py @@ -42,6 +42,7 @@ PROP_PERMISSIONS, Characteristic, CharacteristicError, + CharacteristicWrite, HAPValue, ) from pyhap.const import ( @@ -1206,7 +1207,7 @@ def _run_characteristic_writes( client_addr: tuple[str, int], pending: list[_PendingWrite], ) -> tuple[dict[int, dict[int, dict[str, Any]]], list[_PendingWrite]]: - queries: list[dict[str, Any]] = chars_query[HAP_REPR_CHARS] + queries: list[CharacteristicWrite] = chars_query[HAP_REPR_CHARS] timed_write = HAP_REPR_PID in chars_query if timed_write and not self._take_prepared_write( @@ -1548,7 +1549,7 @@ def signal_handler(self, _signal: Any, _frame: Any) -> None: raise def _notify( - self, queries: list[dict[str, Any]], client_addr: tuple[str, int] + self, queries: list[CharacteristicWrite], client_addr: tuple[str, int] ) -> set[tuple[int, int]]: """Notify the driver that the client has subscribed or unsubscribed. diff --git a/pyhap/characteristic.py b/pyhap/characteristic.py index 3dd44c9f..292ed42d 100644 --- a/pyhap/characteristic.py +++ b/pyhap/characteristic.py @@ -7,7 +7,7 @@ from collections.abc import Callable import inspect import logging -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, TypedDict from uuid import UUID from .const import ( @@ -50,6 +50,24 @@ def _setter_wants_client_addr(setter: Callable[..., Any]) -> bool: # A characteristic value as HAP JSON carries it. HAPValue = bool | int | float | str | None + +class _CharacteristicWriteTarget(TypedDict): + aid: int + iid: int + + +class CharacteristicWrite(_CharacteristicWriteTarget, total=False): + """One characteristic of a write, as HAP JSON carries it. + + ``value`` is the value to write, ``ev`` subscribes or unsubscribes and + ``r`` asks for a write response. + """ + + value: HAPValue + ev: bool + r: bool + + HAP_FORMAT_BOOL = "bool" HAP_FORMAT_INT = "int" HAP_FORMAT_FLOAT = "float" From 555775acc8011f6695e477d54309113009504384 Mon Sep 17 00:00:00 2001 From: Raphael Hehl <7577984+RaHehl@users.noreply.github.com> Date: Tue, 10 Nov 2026 19:01:27 +0100 Subject: [PATCH 2/2] List authData and remote in CharacteristicWrite --- pyhap/characteristic.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyhap/characteristic.py b/pyhap/characteristic.py index a1823a10..0e757c0f 100644 --- a/pyhap/characteristic.py +++ b/pyhap/characteristic.py @@ -60,12 +60,15 @@ class CharacteristicWrite(_CharacteristicWriteTarget, total=False): """One characteristic of a write, as HAP JSON carries it. ``value`` is the value to write, ``ev`` subscribes or unsubscribes and - ``r`` asks for a write response. + ``r`` asks for a write response. ``authData`` and ``remote`` are part of + the HAP request too, the driver does not read them. """ value: HAPValue ev: bool r: bool + authData: str + remote: bool HAP_FORMAT_BOOL = "bool"