Skip to content

Commit ed9b9d3

Browse files
authored
Merge pull request home-assistant-libs#68 from home-assistant-libs/add-untyped-attribute-callback
Add untyped attribute callback support
2 parents 8bcb974 + c094b4e commit ed9b9d3

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
From 9bc05af1e1ef2ec93336dc0eecba16b6802b6fb1 Mon Sep 17 00:00:00 2001
2+
Message-ID: <9bc05af1e1ef2ec93336dc0eecba16b6802b6fb1.1716466458.git.stefan@agner.ch>
3+
From: Stefan Agner <stefan@agner.ch>
4+
Date: Thu, 23 May 2024 12:48:54 +0200
5+
Subject: [PATCH] [Python] Add raw attribute callback
6+
7+
Add new subscription callback which uses raw AttributePath as paths
8+
of changed attributes. This allows to subscribe to custom clusters,
9+
where no Cluster/Attribute types are part of the Python library.
10+
11+
Also allow to get the raw Python values (in tagged dict format)
12+
directly from the subscription transaction.
13+
---
14+
.../python/chip/clusters/Attribute.py | 48 +++++++++++++++----
15+
1 file changed, 38 insertions(+), 10 deletions(-)
16+
17+
diff --git a/src/controller/python/chip/clusters/Attribute.py b/src/controller/python/chip/clusters/Attribute.py
18+
index 9e46eed469..ce522bf452 100644
19+
--- a/src/controller/python/chip/clusters/Attribute.py
20+
+++ b/src/controller/python/chip/clusters/Attribute.py
21+
@@ -466,6 +466,7 @@ class SubscriptionTransaction:
22+
def __init__(self, transaction: AsyncReadTransaction, subscriptionId, devCtrl):
23+
self._onResubscriptionAttemptedCb = DefaultResubscriptionAttemptedCallback
24+
self._onAttributeChangeCb = DefaultAttributeChangeCallback
25+
+ self._onRawAttributeChangeCb = None
26+
self._onEventChangeCb = DefaultEventChangeCallback
27+
self._onErrorCb = DefaultErrorCallback
28+
self._readTransaction = transaction
29+
@@ -491,6 +492,18 @@ class SubscriptionTransaction:
30+
else:
31+
return data[path.Path.EndpointId][path.ClusterType][path.AttributeType]
32+
33+
+ def GetTLVAttributes(self) -> Dict[int, Dict[int, Dict[int, Any]]]:
34+
+ '''Returns the attributes value cache in raw/tag dict value tracking
35+
+ the latest state on the publisher.
36+
+ '''
37+
+ return self._readTransaction._cache.attributeTLVCache
38+
+
39+
+
40+
+ def GetTLVAttribute(self, path: AttributePath) -> bytes:
41+
+ '''Returns a specific attribute given a AttributePath.
42+
+ '''
43+
+ return self._readTransaction._cache.attributeTLVCache[path.EndpointId][path.ClusterId][path.AttributeId]
44+
+
45+
def GetEvents(self):
46+
return self._readTransaction.GetAllEventValues()
47+
48+
@@ -564,8 +577,14 @@ class SubscriptionTransaction:
49+
Sets the callback function for the attribute value change event,
50+
accepts a Callable accepts an attribute path and the cached data.
51+
'''
52+
- if callback is not None:
53+
- self._onAttributeChangeCb = callback
54+
+ self._onAttributeChangeCb = callback
55+
+
56+
+ def SetRawAttributeUpdateCallback(self, callback: Callable[[AttributePath, SubscriptionTransaction], None]):
57+
+ '''
58+
+ Sets the callback function for raw attribute value change event,
59+
+ accepts a Callable which accepts an attribute path and the cached data.
60+
+ '''
61+
+ self._onRawAttributeChangeCb = callback
62+
63+
def SetEventUpdateCallback(self, callback: Callable[[EventReadResult, SubscriptionTransaction], None]):
64+
if callback is not None:
65+
@@ -583,6 +602,10 @@ class SubscriptionTransaction:
66+
def OnAttributeChangeCb(self) -> Callable[[TypedAttributePath, SubscriptionTransaction], None]:
67+
return self._onAttributeChangeCb
68+
69+
+ @property
70+
+ def OnRawAttributeChangeCb(self) -> Callable[[TypedAttributePath, SubscriptionTransaction], None]:
71+
+ return self._onRawAttributeChangeCb
72+
+
73+
@property
74+
def OnEventChangeCb(self) -> Callable[[EventReadResult, SubscriptionTransaction], None]:
75+
return self._onEventChangeCb
76+
@@ -785,14 +808,19 @@ class AsyncReadTransaction:
77+
78+
if (self._subscription_handler is not None):
79+
for change in self._changedPathSet:
80+
- try:
81+
- attribute_path = TypedAttributePath(Path=change)
82+
- except (KeyError, ValueError) as err:
83+
- # path could not be resolved into a TypedAttributePath
84+
- logging.getLogger(__name__).exception(err)
85+
- continue
86+
- self._subscription_handler.OnAttributeChangeCb(
87+
- attribute_path, self._subscription_handler)
88+
+ if self._subscription_handler.OnAttributeChangeCb:
89+
+ try:
90+
+ attribute_path = TypedAttributePath(Path=change)
91+
+ except (KeyError, ValueError) as err:
92+
+ # path could not be resolved into a TypedAttributePath
93+
+ logging.getLogger(__name__).exception(err)
94+
+ continue
95+
+ self._subscription_handler.OnAttributeChangeCb(
96+
+ attribute_path, self._subscription_handler)
97+
+
98+
+ if self._subscription_handler.OnRawAttributeChangeCb:
99+
+ self._subscription_handler.OnRawAttributeChangeCb(
100+
+ change, self._subscription_handler)
101+
102+
# Clear it out once we've notified of all changes in this transaction.
103+
self._changedPathSet = set()
104+
--
105+
2.45.1
106+

0 commit comments

Comments
 (0)