From 0f5f7084727be885c15e08391316f5eeb250157a Mon Sep 17 00:00:00 2001 From: C Freeman Date: Mon, 6 Nov 2023 10:43:42 -0500 Subject: [PATCH] Python: Add more API documentation (#30220) --- src/controller/python/chip/ChipDeviceCtrl.py | 91 +++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/src/controller/python/chip/ChipDeviceCtrl.py b/src/controller/python/chip/ChipDeviceCtrl.py index 22ae11cda65a78..f30cc711b9a7cb 100644 --- a/src/controller/python/chip/ChipDeviceCtrl.py +++ b/src/controller/python/chip/ChipDeviceCtrl.py @@ -684,6 +684,19 @@ def DiscoverAllCommissioning(self): def OpenCommissioningWindow(self, nodeid: int, timeout: int, iteration: int, discriminator: int, option: int) -> CommissioningParameters: + ''' Opens a commissioning window on the device with the given nodeid. + nodeid: Node id of the device + timeout: Command timeout + iteration: The PAKE iteration count associated with the PAKE Passcode ID and ephemeral + PAKE passcode verifier to be used for this commissioning. Valid range: 1000 - 100000 + Ignored if option == 0 + discriminator: The long discriminator for the DNS-SD advertisement. Valid range: 0-4095 + Ignored if option == 0 + option: 0 = kOriginalSetupCode + 1 = kTokenWithRandomPIN + + Returns CommissioningParameters + ''' self.CheckIsActive() self._ChipStack.CallAsync( lambda: self._dmLib.pychip_DeviceController_OpenCommissioningWindow( @@ -825,6 +838,11 @@ async def SendCommand(self, nodeid: int, endpoint: int, payload: ClusterObjects. timedWriteTimeoutMs: Timeout for a timed invoke request. Omit or set to 'None' to indicate a non-timed request. interactionTimeoutMs: Overall timeout for the interaction. Omit or set to 'None' to have the SDK automatically compute the right timeout value based on transport characteristics as well as the responsiveness of the target. + + Returns: + - command respone. The type of the response is defined by the command. + Raises: + - InteractionModelError on error ''' self.CheckIsActive() @@ -845,6 +863,10 @@ def SendGroupCommand(self, groupid: int, payload: ClusterObjects.ClusterCommand, ''' Send a group cluster-object encapsulated command to a group_id and get returned a future that can be awaited upon to get confirmation command was sent. + Returns: + - None: responses are not sent to group commands + Raises: + - InteractionModelError on error ''' self.CheckIsActive() @@ -870,6 +892,9 @@ async def WriteAttribute(self, nodeid: int, E.g (1, Clusters.UnitTesting.Attributes.XYZAttribute('hello')) -- Write 'hello' to the XYZ attribute on the test cluster to endpoint 1 + + Returns: + - PyChipError ''' self.CheckIsActive() @@ -1091,6 +1116,13 @@ async def Read(self, nodeid: int, attributes: typing.List[typing.Union[ reportInterval: A tuple of two int-s for (MinIntervalFloor, MaxIntervalCeiling). Used by establishing subscriptions. When not provided, a read request will be sent. + + Returns: + - AsyncReadTransaction.ReadResponse. Please see ReadAttribute and ReadEvent for examples of how to access data. + + Raises: + - InteractionModelError (chip.interaction_model) on error + ''' self.CheckIsActive() @@ -1153,6 +1185,26 @@ async def ReadAttribute(self, nodeid: int, attributes: typing.List[typing.Union[ reportInterval: A tuple of two int-s for (MinIntervalFloor, MaxIntervalCeiling). Used by establishing subscriptions. When not provided, a read request will be sent. + + Returns: + - subscription request: ClusterAttribute.SubscriptionTransaction + To get notified on attribute change use SetAttributeUpdateCallback on the returned + SubscriptionTransaction. This is used to set a callback function, which is a callable of + type Callable[[TypedAttributePath, SubscriptionTransaction], None] + Get the attribute value from the change path using GetAttribute on the SubscriptionTransasction + You can await changes in the main loop using a trigger mechanism from the callback. + ex. queue.SimpleQueue + + - read request: AsyncReadTransation.ReadResponse.attributes. + This is of type AttributeCache.attributeCache (Attribute.py), + which is a dict mapping endpoints to a list of Cluster (ClusterObjects.py) classes + (dict[int], List[Cluster]) + Access as ret[endpoint_id][][] + Ex. To access the OnTime attribute from the OnOff cluster on EP 0 + ret[0][Clusters.OnOff][Clusters.OnOff.Attributes.OnTime] + + Raises: + - InteractionModelError (chip.interaction_model) on error ''' res = await self.Read(nodeid, attributes=attributes, @@ -1209,6 +1261,19 @@ async def ReadEvent(self, nodeid: int, events: typing.List[typing.Union[ eventNumberFilter: Optional minimum event number filter. reportInterval: A tuple of two int-s for (MinIntervalFloor, MaxIntervalCeiling). Used by establishing subscriptions. When not provided, a read request will be sent. + + Returns: + - subscription request: ClusterAttribute.SubscriptionTransaction + To get notified on event subscriptions, use the SetEventUpdateCallback function on the + returned SubscriptionTransaction. This is a callable of type + Callable[[EventReadResult, SubscriptionTransaction], None] + You can await events using a trigger mechanism in the callback. ex. queue.SimpleQueue + + - read request: AsyncReadTransation.ReadResponse.events. + This is a List[ClusterEvent]. + + Raises: + - InteractionModelError (chip.interaction_model) on error ''' res = await self.Read(nodeid=nodeid, events=events, eventNumberFilter=eventNumberFilter, fabricFiltered=fabricFiltered, reportInterval=reportInterval, keepSubscriptions=keepSubscriptions, @@ -1219,6 +1284,9 @@ async def ReadEvent(self, nodeid: int, events: typing.List[typing.Union[ return res.events def ZCLSend(self, cluster, command, nodeid, endpoint, groupid, args, blocking=False): + ''' Wrapper over SendCommand that catches the exceptions + Returns a tuple of (errorCode, CommandResponse) + ''' self.CheckIsActive() req = None @@ -1235,6 +1303,9 @@ def ZCLSend(self, cluster, command, nodeid, endpoint, groupid, args, blocking=Fa return (int(ex.status), None) def ZCLReadAttribute(self, cluster, attribute, nodeid, endpoint, groupid, blocking=True): + ''' Wrapper over ReadAttribute for a single attribute + Returns an AttributeReadResult + ''' self.CheckIsActive() clusterType = getattr(GeneratedObjects, cluster) @@ -1253,6 +1324,9 @@ def ZCLReadAttribute(self, cluster, attribute, nodeid, endpoint, groupid, blocki status=0, value=result[endpoint][clusterType][attributeType], dataVersion=result[endpoint][clusterType][ClusterAttribute.DataVersion]) def ZCLWriteAttribute(self, cluster: str, attribute: str, nodeid, endpoint, groupid, value, dataVersion=0, blocking=True): + ''' Wrapper over WriteAttribute for a single attribute + return PyChipError + ''' req = None try: req = eval( @@ -1263,6 +1337,9 @@ def ZCLWriteAttribute(self, cluster: str, attribute: str, nodeid, endpoint, grou return asyncio.run(self.WriteAttribute(nodeid, [(endpoint, req, dataVersion)])) def ZCLSubscribeAttribute(self, cluster, attribute, nodeid, endpoint, minInterval, maxInterval, blocking=True): + ''' Wrapper over ReadAttribute for a single attribute + Returns a SubscriptionTransaction. See ReadAttribute for more information. + ''' self.CheckIsActive() req = None @@ -1627,12 +1704,13 @@ def CommissionThread(self, discriminator, setupPinCode, nodeId, threadOperationa return self.ConnectBLE(discriminator, setupPinCode, nodeId) def CommissionWiFi(self, discriminator, setupPinCode, nodeId, ssid: str, credentials: str) -> PyChipError: - ''' Commissions a WiFi device over BLE + ''' Commissions a Wi-Fi device over BLE. ''' self.SetWiFiCredentials(ssid, credentials) return self.ConnectBLE(discriminator, setupPinCode, nodeId) def SetWiFiCredentials(self, ssid: str, credentials: str): + ''' Set the Wi-Fi credentials to set during commissioning.''' self.CheckIsActive() self._ChipStack.Call( @@ -1641,6 +1719,7 @@ def SetWiFiCredentials(self, ssid: str, credentials: str): ).raise_on_error() def SetThreadOperationalDataset(self, threadOperationalDataset): + ''' Set the Thread operational dataset to set during commissioning.''' self.CheckIsActive() self._ChipStack.Call( @@ -1649,42 +1728,49 @@ def SetThreadOperationalDataset(self, threadOperationalDataset): ).raise_on_error() def ResetCommissioningParameters(self): + ''' Sets the commissioning parameters back to the default values.''' self.CheckIsActive() self._ChipStack.Call( lambda: self._dmLib.pychip_DeviceController_ResetCommissioningParameters() ).raise_on_error() def SetTimeZone(self, offset: int, validAt: int): + ''' Set the time zone to set during commissioning. Currently only one time zone entry is supported''' self.CheckIsActive() self._ChipStack.Call( lambda: self._dmLib.pychip_DeviceController_SetTimeZone(offset, validAt) ).raise_on_error() def SetDSTOffset(self, offset: int, validStarting: int, validUntil: int): + ''' Set the DST offset to set during commissioning. Currently only one DST entry is supported''' self.CheckIsActive() self._ChipStack.Call( lambda: self._dmLib.pychip_DeviceController_SetDSTOffset(offset, validStarting, validUntil) ).raise_on_error() def SetDefaultNTP(self, defaultNTP: str): + ''' Set the DefaultNTP to set during commissioning''' self.CheckIsActive() self._ChipStack.Call( lambda: self._dmLib.pychip_DeviceController_SetDefaultNtp(defaultNTP.encode("utf-8")) ).raise_on_error() def SetTrustedTimeSource(self, nodeId: int, endpoint: int): + ''' Set the trusetd time source nodeId to set during commissioning. This must be a node on the commissioner fabric.''' self.CheckIsActive() self._ChipStack.Call( lambda: self._dmLib.pychip_DeviceController_SetTrustedTimeSource(nodeId, endpoint) ).raise_on_error() def SetCheckMatchingFabric(self, check: bool): + ''' Instructs the auto-commissioner to perform a matching fabric check before commissioning.''' self.CheckIsActive() self._ChipStack.Call( lambda: self._dmLib.pychip_DeviceController_SetCheckMatchingFabric(check) ).raise_on_error() def GetFabricCheckResult(self) -> int: + ''' Returns the fabric check result if SetCheckMatchingFabric was used.''' return self.fabricCheckNodeId def CommissionOnNetwork(self, nodeId: int, setupPinCode: int, @@ -1727,6 +1813,9 @@ def CommissionOnNetwork(self, nodeId: int, setupPinCode: int, return self._ChipStack.commissioningEventRes def CommissionWithCode(self, setupPayload: str, nodeid: int) -> PyChipError: + ''' Commission with the given nodeid from the setupPayload. + setupPayload may be a QR or manual code. + ''' self.CheckIsActive() setupPayload = setupPayload.encode() + b'\0'