Skip to content

Commit

Permalink
Topographically Structured Attribute Data
Browse files Browse the repository at this point in the history
The existing format for how attribute reports were returned to callers
of DeviceController.ReadAttribute() made it quite challenging for them
to consume it in an easy enough manner.

Instead of providing them with an effectively raw stream of attribute
data, this commit organizes and structures that data into a series of
nested dictionaries that mirror the topography and composition of the
data in a given Matter device: Endpoints that contain Clusters that in
turn contain Attributes.

The Python data structure equivalent represents these as nested
dictionaries: Dict[EndpointId, Dict[ClusterType, Dict[AttributeType,
AttributeValue]]]

Tests:

- Updated the existing ReadAttribute and Subscription tests to utilize this new format.
- Added new ones.
- Validated using the REPL
  • Loading branch information
mrjerryjohns committed Dec 4, 2021
1 parent ba69e73 commit 923f32d
Show file tree
Hide file tree
Showing 9 changed files with 4,848 additions and 115 deletions.
1 change: 1 addition & 0 deletions src/controller/python/build-chip-wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ def finalize_options(self):
'rich',
'stringcase',
'pyyaml',
'ipdb'
]

if platform.system() == "Darwin":
Expand Down
18 changes: 10 additions & 8 deletions src/controller/python/chip/ChipDeviceCtrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ async def ReadAttribute(self, nodeid: int, attributes: typing.List[typing.Union[
typing.Tuple[int, typing.Type[ClusterObjects.Cluster]],
# Concrete path
typing.Tuple[int, typing.Type[ClusterObjects.ClusterAttributeDescriptor]]
]], reportInterval: typing.Tuple[int, int] = None):
]], returnClusterObject: bool = False, reportInterval: typing.Tuple[int, int] = None):
'''
Read a list of attributes from a target node
Expand Down Expand Up @@ -480,7 +480,6 @@ async def ReadAttribute(self, nodeid: int, attributes: typing.List[typing.Union[
# Wildcard
pass
elif type(v) is not tuple:
print(type(v))
if type(v) is int:
endpoint = v
elif issubclass(v, ClusterObjects.Cluster):
Expand All @@ -501,7 +500,7 @@ async def ReadAttribute(self, nodeid: int, attributes: typing.List[typing.Union[
attrs.append(ClusterAttribute.AttributePath(
EndpointId=endpoint, Cluster=cluster, Attribute=attribute))
res = self._ChipStack.Call(
lambda: ClusterAttribute.ReadAttributes(future, eventLoop, device, self, attrs, ClusterAttribute.SubscriptionParameters(reportInterval[0], reportInterval[1]) if reportInterval else None))
lambda: ClusterAttribute.ReadAttributes(future, eventLoop, device, self, attrs, returnClusterObject, ClusterAttribute.SubscriptionParameters(reportInterval[0], reportInterval[1]) if reportInterval else None))
if res != 0:
raise self._ChipStack.ErrorToException(res)
return await future
Expand Down Expand Up @@ -597,16 +596,19 @@ def ZCLSend(self, cluster, command, nodeid, endpoint, groupid, args, blocking=Fa

def ZCLReadAttribute(self, cluster, attribute, nodeid, endpoint, groupid, blocking=True):
req = None
clusterType = eval(f"GeneratedObjects.{cluster}")

try:
req = eval(f"GeneratedObjects.{cluster}.Attributes.{attribute}")
attributeType = eval(
f"GeneratedObjects.{cluster}.Attributes.{attribute}")
except:
raise UnknownAttribute(cluster, attribute)

result = asyncio.run(self.ReadAttribute(
nodeid, [(endpoint, req)]))['Attributes']
nodeid, [(endpoint, attributeType)]))
path = ClusterAttribute.AttributePath(
EndpointId=endpoint, Attribute=req)
return im.AttributeReadResult(path=im.AttributePath(nodeId=nodeid, endpointId=path.EndpointId, clusterId=path.ClusterId, attributeId=path.AttributeId), status=0, value=result[path].Data.value)
EndpointId=endpoint, Attribute=attributeType)
return im.AttributeReadResult(path=im.AttributePath(nodeId=nodeid, endpointId=path.EndpointId, clusterId=path.ClusterId, attributeId=path.AttributeId), status=0, value=result[endpoint][clusterType][attributeType])

def ZCLWriteAttribute(self, cluster: str, attribute: str, nodeid, endpoint, groupid, value, blocking=True):
req = None
Expand All @@ -624,7 +626,7 @@ def ZCLSubscribeAttribute(self, cluster, attribute, nodeid, endpoint, minInterva
req = eval(f"GeneratedObjects.{cluster}.Attributes.{attribute}")
except:
raise UnknownAttribute(cluster, attribute)
return asyncio.run(self.ReadAttribute(nodeid, [(endpoint, req)], reportInterval=(minInterval, maxInterval)))
return asyncio.run(self.ReadAttribute(nodeid, [(endpoint, req)], False, reportInterval=(minInterval, maxInterval)))

def ZCLShutdownSubscription(self, subscriptionId: int):
res = self._ChipStack.Call(
Expand Down
Loading

0 comments on commit 923f32d

Please sign in to comment.