-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #68 from home-assistant-libs/add-untyped-attribute…
…-callback Add untyped attribute callback support
- Loading branch information
Showing
1 changed file
with
106 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
From 9bc05af1e1ef2ec93336dc0eecba16b6802b6fb1 Mon Sep 17 00:00:00 2001 | ||
Message-ID: <9bc05af1e1ef2ec93336dc0eecba16b6802b6fb1.1716466458.git.stefan@agner.ch> | ||
From: Stefan Agner <stefan@agner.ch> | ||
Date: Thu, 23 May 2024 12:48:54 +0200 | ||
Subject: [PATCH] [Python] Add raw attribute callback | ||
|
||
Add new subscription callback which uses raw AttributePath as paths | ||
of changed attributes. This allows to subscribe to custom clusters, | ||
where no Cluster/Attribute types are part of the Python library. | ||
|
||
Also allow to get the raw Python values (in tagged dict format) | ||
directly from the subscription transaction. | ||
--- | ||
.../python/chip/clusters/Attribute.py | 48 +++++++++++++++---- | ||
1 file changed, 38 insertions(+), 10 deletions(-) | ||
|
||
diff --git a/src/controller/python/chip/clusters/Attribute.py b/src/controller/python/chip/clusters/Attribute.py | ||
index 9e46eed469..ce522bf452 100644 | ||
--- a/src/controller/python/chip/clusters/Attribute.py | ||
+++ b/src/controller/python/chip/clusters/Attribute.py | ||
@@ -466,6 +466,7 @@ class SubscriptionTransaction: | ||
def __init__(self, transaction: AsyncReadTransaction, subscriptionId, devCtrl): | ||
self._onResubscriptionAttemptedCb = DefaultResubscriptionAttemptedCallback | ||
self._onAttributeChangeCb = DefaultAttributeChangeCallback | ||
+ self._onRawAttributeChangeCb = None | ||
self._onEventChangeCb = DefaultEventChangeCallback | ||
self._onErrorCb = DefaultErrorCallback | ||
self._readTransaction = transaction | ||
@@ -491,6 +492,18 @@ class SubscriptionTransaction: | ||
else: | ||
return data[path.Path.EndpointId][path.ClusterType][path.AttributeType] | ||
|
||
+ def GetTLVAttributes(self) -> Dict[int, Dict[int, Dict[int, Any]]]: | ||
+ '''Returns the attributes value cache in raw/tag dict value tracking | ||
+ the latest state on the publisher. | ||
+ ''' | ||
+ return self._readTransaction._cache.attributeTLVCache | ||
+ | ||
+ | ||
+ def GetTLVAttribute(self, path: AttributePath) -> bytes: | ||
+ '''Returns a specific attribute given a AttributePath. | ||
+ ''' | ||
+ return self._readTransaction._cache.attributeTLVCache[path.EndpointId][path.ClusterId][path.AttributeId] | ||
+ | ||
def GetEvents(self): | ||
return self._readTransaction.GetAllEventValues() | ||
|
||
@@ -564,8 +577,14 @@ class SubscriptionTransaction: | ||
Sets the callback function for the attribute value change event, | ||
accepts a Callable accepts an attribute path and the cached data. | ||
''' | ||
- if callback is not None: | ||
- self._onAttributeChangeCb = callback | ||
+ self._onAttributeChangeCb = callback | ||
+ | ||
+ def SetRawAttributeUpdateCallback(self, callback: Callable[[AttributePath, SubscriptionTransaction], None]): | ||
+ ''' | ||
+ Sets the callback function for raw attribute value change event, | ||
+ accepts a Callable which accepts an attribute path and the cached data. | ||
+ ''' | ||
+ self._onRawAttributeChangeCb = callback | ||
|
||
def SetEventUpdateCallback(self, callback: Callable[[EventReadResult, SubscriptionTransaction], None]): | ||
if callback is not None: | ||
@@ -583,6 +602,10 @@ class SubscriptionTransaction: | ||
def OnAttributeChangeCb(self) -> Callable[[TypedAttributePath, SubscriptionTransaction], None]: | ||
return self._onAttributeChangeCb | ||
|
||
+ @property | ||
+ def OnRawAttributeChangeCb(self) -> Callable[[TypedAttributePath, SubscriptionTransaction], None]: | ||
+ return self._onRawAttributeChangeCb | ||
+ | ||
@property | ||
def OnEventChangeCb(self) -> Callable[[EventReadResult, SubscriptionTransaction], None]: | ||
return self._onEventChangeCb | ||
@@ -785,14 +808,19 @@ class AsyncReadTransaction: | ||
|
||
if (self._subscription_handler is not None): | ||
for change in self._changedPathSet: | ||
- try: | ||
- attribute_path = TypedAttributePath(Path=change) | ||
- except (KeyError, ValueError) as err: | ||
- # path could not be resolved into a TypedAttributePath | ||
- logging.getLogger(__name__).exception(err) | ||
- continue | ||
- self._subscription_handler.OnAttributeChangeCb( | ||
- attribute_path, self._subscription_handler) | ||
+ if self._subscription_handler.OnAttributeChangeCb: | ||
+ try: | ||
+ attribute_path = TypedAttributePath(Path=change) | ||
+ except (KeyError, ValueError) as err: | ||
+ # path could not be resolved into a TypedAttributePath | ||
+ logging.getLogger(__name__).exception(err) | ||
+ continue | ||
+ self._subscription_handler.OnAttributeChangeCb( | ||
+ attribute_path, self._subscription_handler) | ||
+ | ||
+ if self._subscription_handler.OnRawAttributeChangeCb: | ||
+ self._subscription_handler.OnRawAttributeChangeCb( | ||
+ change, self._subscription_handler) | ||
|
||
# Clear it out once we've notified of all changes in this transaction. | ||
self._changedPathSet = set() | ||
-- | ||
2.45.1 | ||
|