Skip to content

Commit

Permalink
Merge pull request #68 from home-assistant-libs/add-untyped-attribute…
Browse files Browse the repository at this point in the history
…-callback

Add untyped attribute callback support
  • Loading branch information
agners committed May 23, 2024
2 parents 8bcb974 + c094b4e commit ed9b9d3
Showing 1 changed file with 106 additions and 0 deletions.
106 changes: 106 additions & 0 deletions 0006-Python-Add-raw-attribute-callback.patch
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

0 comments on commit ed9b9d3

Please sign in to comment.