Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Python] Store original PyChipError in ChipStackException #33954

Merged
merged 6 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions src/controller/python/ChipDeviceController-ScriptBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ pychip_ScriptDevicePairingDelegate_SetExpectingPairingComplete(chip::Controller:
// BLE
PyChipError pychip_DeviceCommissioner_CloseBleConnection(chip::Controller::DeviceCommissioner * devCtrl);

const char * pychip_Stack_ErrorToString(ChipError::StorageType err);
const char * pychip_Stack_StatusReportToString(uint32_t profileId, uint16_t statusCode);

PyChipError pychip_GetConnectedDeviceByNodeId(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeId,
Expand Down Expand Up @@ -366,11 +365,6 @@ PyChipError pychip_DeviceController_GetNodeId(chip::Controller::DeviceCommission
return ToPyChipError(CHIP_NO_ERROR);
}

const char * pychip_DeviceController_ErrorToString(ChipError::StorageType err)
{
return chip::ErrorStr(CHIP_ERROR(err));
}

const char * pychip_DeviceController_StatusReportToString(uint32_t profileId, uint16_t statusCode)
{
// return chip::StatusReportStr(profileId, statusCode);
Expand Down Expand Up @@ -769,11 +763,6 @@ pychip_ScriptDevicePairingDelegate_SetExpectingPairingComplete(chip::Controller:
return ToPyChipError(CHIP_NO_ERROR);
}

const char * pychip_Stack_ErrorToString(ChipError::StorageType err)
{
return chip::ErrorStr(CHIP_ERROR(err));
}

const char * pychip_Stack_StatusReportToString(uint32_t profileId, uint16_t statusCode)
{
// return chip::StatusReportStr(profileId, statusCode);
Expand Down
13 changes: 5 additions & 8 deletions src/controller/python/chip/ChipDeviceCtrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1013,12 +1013,8 @@ def GetRemoteSessionParameters(self, nodeid) -> typing.Optional[SessionParameter
sessionParametersStruct = SessionParametersStruct.parse(b'\x00' * SessionParametersStruct.sizeof())
sessionParametersByteArray = SessionParametersStruct.build(sessionParametersStruct)
device = self.GetConnectedDeviceSync(nodeid)
res = self._ChipStack.Call(lambda: self._dmLib.pychip_DeviceProxy_GetRemoteSessionParameters(
device.deviceProxy, ctypes.c_char_p(sessionParametersByteArray)))

# 0 is CHIP_NO_ERROR
if res != 0:
return None
self._ChipStack.Call(lambda: self._dmLib.pychip_DeviceProxy_GetRemoteSessionParameters(
device.deviceProxy, ctypes.c_char_p(sessionParametersByteArray))).raise_on_error()

sessionParametersStruct = SessionParametersStruct.parse(sessionParametersByteArray)
return SessionParameters(
Expand All @@ -1030,8 +1026,6 @@ def GetRemoteSessionParameters(self, nodeid) -> typing.Optional[SessionParameter
specficiationVersion=sessionParametersStruct.SpecificationVersion if sessionParametersStruct.SpecificationVersion != 0 else None,
maxPathsPerInvoke=sessionParametersStruct.MaxPathsPerInvoke)

return res

async def TestOnlySendBatchCommands(self, nodeid: int, commands: typing.List[ClusterCommand.InvokeRequestInfo],
timedRequestTimeoutMs: typing.Optional[int] = None,
interactionTimeoutMs: typing.Optional[int] = None, busyWaitMs: typing.Optional[int] = None,
Expand Down Expand Up @@ -1804,6 +1798,9 @@ def _InitLib(self):

self._dmLib.pychip_CheckInDelegate_SetOnCheckInCompleteCallback(_OnCheckInComplete)

self._dmLib.pychip_DeviceProxy_GetRemoteSessionParameters.restype = PyChipError
self._dmLib.pychip_DeviceProxy_GetRemoteSessionParameters.argtypes = [c_void_p, c_char_p]


class ChipDeviceController(ChipDeviceControllerBase):
''' The ChipDeviceCommissioner binding, named as ChipDeviceController
Expand Down
30 changes: 0 additions & 30 deletions src/controller/python/chip/ChipStack.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import chip.native
from chip.native import PyChipError

from .ChipUtility import ChipUtility
from .clusters import Attribute as ClusterAttribute
from .clusters import Command as ClusterCommand
from .exceptions import ChipStackError, ChipStackException, DeviceError
Expand Down Expand Up @@ -247,33 +246,6 @@ def PostTaskOnChipThread(self, callFunct) -> AsyncCallableHandle:
raise res.to_exception()
return callObj

def ErrorToException(self, err, devStatusPtr=None):
if err == 0x2C and devStatusPtr:
devStatus = devStatusPtr.contents
msg = ChipUtility.CStringToString(
(
self._ChipStackLib.pychip_Stack_StatusReportToString(
devStatus.ProfileId, devStatus.StatusCode
)
)
)
sysErrorCode = (
devStatus.SysErrorCode if (
devStatus.SysErrorCode != 0) else None
)
if sysErrorCode is not None:
msg = msg + " (system err %d)" % (sysErrorCode)
return DeviceError(
devStatus.ProfileId, devStatus.StatusCode, sysErrorCode, msg
)
else:
return ChipStackError(
err,
ChipUtility.CStringToString(
(self._ChipStackLib.pychip_Stack_ErrorToString(err))
),
)

def LocateChipDLL(self):
self._loadLib()
return self._chipDLLPath
Expand Down Expand Up @@ -302,8 +274,6 @@ def _loadLib(self):
c_uint16,
]
self._ChipStackLib.pychip_Stack_StatusReportToString.restype = c_char_p
self._ChipStackLib.pychip_Stack_ErrorToString.argtypes = [c_uint32]
self._ChipStackLib.pychip_Stack_ErrorToString.restype = c_char_p

self._ChipStackLib.pychip_DeviceController_PostTaskOnChipThread.argtypes = [
_ChipThreadTaskRunnerFunct, py_object]
Expand Down
12 changes: 6 additions & 6 deletions src/controller/python/chip/clusters/Attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ def __init__(self, future: Future, eventLoop, devCtrl, returnClusterObject: bool
self._changedPathSet = set()
self._pReadClient = None
self._pReadCallback = None
self._resultError = None
self._resultError: Optional[PyChipError] = None

def SetClientObjPointers(self, pReadClient, pReadCallback):
self._pReadClient = pReadClient
Expand Down Expand Up @@ -718,7 +718,7 @@ def handleEventData(self, header: EventHeader, path: EventPath, data: bytes, sta
logging.exception(ex)

def handleError(self, chipError: PyChipError):
self._resultError = chipError.code
self._resultError = chipError

def _handleSubscriptionEstablished(self, subscriptionId):
if not self._future.done():
Expand Down Expand Up @@ -777,11 +777,11 @@ def _handleDone(self):
# move on, possibly invalidating the provided _event_loop.
#
if not self._future.done():
if self._resultError:
if self._resultError is not None:
if self._subscription_handler:
self._subscription_handler.OnErrorCb(self._resultError, self._subscription_handler)
self._subscription_handler.OnErrorCb(self._resultError.code, self._subscription_handler)
else:
self._future.set_exception(chip.exceptions.ChipStackError(self._resultError))
self._future.set_exception(self._resultError.to_exception())
else:
self._future.set_result(AsyncReadTransaction.ReadResponse(
attributes=self._cache.attributeCache, events=self._events, tlvAttributes=self._cache.attributeTLVCache))
Expand Down Expand Up @@ -809,7 +809,7 @@ def __init__(self, future: Future, eventLoop):
self._event_loop = eventLoop
self._future = future
self._resultData = []
self._resultError = None
self._resultError: Optional[PyChipError] = None

def handleResponse(self, path: AttributePath, status: int):
try:
Expand Down
4 changes: 2 additions & 2 deletions src/controller/python/chip/clusters/Command.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,13 +467,13 @@ def Init():
setter = chip.native.NativeLibraryHandleMethodArguments(handle)

setter.Set('pychip_CommandSender_SendCommand',
PyChipError, [py_object, c_void_p, c_uint16, c_uint32, c_uint32, c_char_p, c_size_t, c_uint16, c_bool])
PyChipError, [py_object, c_void_p, c_uint16, c_uint16, c_uint32, c_uint32, c_char_p, c_size_t, c_uint16, c_uint16, c_bool])
setter.Set('pychip_CommandSender_SendBatchCommands',
PyChipError, [py_object, c_void_p, c_uint16, c_uint16, c_uint16, c_bool, POINTER(PyInvokeRequestData), c_size_t])
setter.Set('pychip_CommandSender_TestOnlySendBatchCommands',
PyChipError, [py_object, c_void_p, c_uint16, c_uint16, c_uint16, c_bool, TestOnlyPyBatchCommandsOverrides, POINTER(PyInvokeRequestData), c_size_t])
setter.Set('pychip_CommandSender_TestOnlySendCommandTimedRequestNoTimedInvoke',
PyChipError, [py_object, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_uint16, c_bool])
PyChipError, [py_object, c_void_p, c_uint16, c_uint32, c_uint32, c_char_p, c_size_t, c_uint16, c_uint16, c_bool])
setter.Set('pychip_CommandSender_SendGroupCommand',
PyChipError, [c_uint16, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_uint16])
setter.Set('pychip_CommandSender_InitCallbacks', None, [
Expand Down
8 changes: 6 additions & 2 deletions src/controller/python/chip/credentials/cert.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ def convert_x509_cert_to_chip_cert(x509Cert: bytes) -> bytes:
"""Converts a x509 certificate to CHIP Certificate."""
output_buffer = (ctypes.c_uint8 * 1024)()
output_size = ctypes.c_size_t(1024)
ptr_type = ctypes.POINTER(ctypes.c_uint8)

_handle().pychip_ConvertX509CertToChipCert(x509Cert, len(x509Cert), output_buffer, ctypes.byref(output_size)).raise_on_error()
_handle().pychip_ConvertX509CertToChipCert(ctypes.cast(x509Cert, ptr_type), len(x509Cert),
ctypes.cast(output_buffer, ptr_type), ctypes.byref(output_size)).raise_on_error()

return bytes(output_buffer)[:output_size.value]

Expand All @@ -45,7 +47,9 @@ def convert_chip_cert_to_x509_cert(chipCert: bytes) -> bytes:
"""Converts a x509 certificate to CHIP Certificate."""
output_buffer = (ctypes.c_byte * 1024)()
output_size = ctypes.c_size_t(1024)
ptr_type = ctypes.POINTER(ctypes.c_uint8)

_handle().pychip_ConvertChipCertToX509Cert(chipCert, len(chipCert), output_buffer, ctypes.byref(output_size)).raise_on_error()
_handle().pychip_ConvertChipCertToX509Cert(ctypes.cast(chipCert, ptr_type), len(chipCert),
ctypes.cast(output_buffer, ptr_type), ctypes.byref(output_size)).raise_on_error()

return bytes(output_buffer)[:output_size.value]
3 changes: 1 addition & 2 deletions src/controller/python/chip/discovery/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,7 @@ def FindAddressAsync(fabricid: int, nodeid: int, callback, timeout_ms=1000):
)

res = _GetDiscoveryLibraryHandle().pychip_discovery_resolve(fabricid, nodeid)
if res != 0:
raise Exception("Failed to start node resolution")
res.raise_on_error()


class _SyncAddressFinder:
Expand Down
25 changes: 22 additions & 3 deletions src/controller/python/chip/exceptions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# limitations under the License.
#

from __future__ import annotations

__all__ = [
"ChipStackException",
"ChipStackError",
Expand All @@ -26,15 +28,32 @@
"UnknownCommand",
]

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from chip.native import PyChipError


class ChipStackException(Exception):
pass


class ChipStackError(ChipStackException):
def __init__(self, err, msg=None):
self.err = err
self.msg = msg if msg else "Chip Stack Error %d" % err
def __init__(self, chip_error: PyChipError, msg=None):
self._chip_error = chip_error
self.msg = msg if msg else "Chip Stack Error %d" % chip_error.code

@classmethod
def from_chip_error(cls, chip_error: PyChipError) -> ChipStackError:
return cls(chip_error, str(chip_error))

@property
def chip_error(self) -> PyChipError | None:
return self._chip_error

@property
def err(self) -> int:
return self._chip_error.code

def __str__(self):
return self.msg
Expand Down
8 changes: 3 additions & 5 deletions src/controller/python/chip/interaction_model/delegate.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ def InitIMDelegate():
setter.Set("pychip_InteractionModelDelegate_SetCommandResponseErrorCallback", None, [
_OnCommandResponseFunct])
setter.Set("pychip_InteractionModel_GetCommandSenderHandle",
c_uint32, [ctypes.POINTER(c_uint64)])
chip.native.PyChipError, [ctypes.POINTER(c_uint64)])
setter.Set("pychip_InteractionModelDelegate_SetOnWriteResponseStatusCallback", None, [
_OnWriteResponseStatusFunct])

Expand Down Expand Up @@ -389,10 +389,8 @@ def WaitCommandIndexStatus(commandHandle: int, commandIndex: int):
def GetCommandSenderHandle() -> int:
handle = chip.native.GetLibraryHandle()
resPointer = c_uint64()
res = handle.pychip_InteractionModel_GetCommandSenderHandle(
ctypes.pointer(resPointer))
if res != 0:
raise chip.exceptions.ChipStackError(res)
handle.pychip_InteractionModel_GetCommandSenderHandle(
ctypes.pointer(resPointer)).raise_on_error()
ClearCommandStatus(resPointer.value)
return resPointer.value

Expand Down
4 changes: 2 additions & 2 deletions src/controller/python/chip/native/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def sdk_code(self) -> int:

def to_exception(self) -> typing.Union[None, chip.exceptions.ChipStackError]:
if not self.is_success:
return chip.exceptions.ChipStackError(self.code, str(self))
return chip.exceptions.ChipStackError.from_chip_error(self)

def __str__(self):
buf = ctypes.create_string_buffer(256)
Expand Down Expand Up @@ -199,7 +199,7 @@ def __init__(self, handle):
def Set(self, methodName: str, resultType, argumentTypes: list):
method = getattr(self.handle, methodName)
method.restype = resultType
method.argtype = argumentTypes
method.argtypes = argumentTypes


@dataclass
Expand Down
38 changes: 14 additions & 24 deletions src/controller/python/chip/setup_payload/setup_payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@
# limitations under the License.
#

from ctypes import CFUNCTYPE, c_char_p, c_int32, c_uint8, c_uint16, c_uint32
from ctypes import CFUNCTYPE, c_char_p, c_uint8, c_uint16, c_uint32
from typing import Optional

from chip.exceptions import ChipStackError
from chip.native import GetLibraryHandle, NativeLibraryHandleMethodArguments
from chip.native import GetLibraryHandle, NativeLibraryHandleMethodArguments, PyChipError


class SetupPayload:
Expand Down Expand Up @@ -46,34 +45,25 @@ def AddVendorAttribute(tag, value):

def ParseQrCode(self, qrCode: str):
self.Clear()
err = self.chipLib.pychip_SetupPayload_ParseQrCode(qrCode.upper().encode(),
self.attribute_visitor,
self.vendor_attribute_visitor)

if err != 0:
raise ChipStackError(err)
self.chipLib.pychip_SetupPayload_ParseQrCode(qrCode.upper().encode(),
self.attribute_visitor,
self.vendor_attribute_visitor).raise_on_error()

return self

def ParseManualPairingCode(self, manualPairingCode: str):
self.Clear()
err = self.chipLib.pychip_SetupPayload_ParseManualPairingCode(manualPairingCode.encode(),
self.attribute_visitor,
self.vendor_attribute_visitor)

if err != 0:
raise ChipStackError(err)
self.chipLib.pychip_SetupPayload_ParseManualPairingCode(manualPairingCode.encode(),
self.attribute_visitor,
self.vendor_attribute_visitor).raise_on_error()

return self

# DEPRECATED
def PrintOnboardingCodes(self, passcode, vendorId, productId, discriminator, customFlow, capabilities, version):
self.Clear()
err = self.chipLib.pychip_SetupPayload_PrintOnboardingCodes(
passcode, vendorId, productId, discriminator, customFlow, capabilities, version)

if err != 0:
raise ChipStackError(err)
self.chipLib.pychip_SetupPayload_PrintOnboardingCodes(
passcode, vendorId, productId, discriminator, customFlow, capabilities, version).raise_on_error()

# DEPRECATED
def Print(self):
Expand Down Expand Up @@ -106,17 +96,17 @@ def __DecorateValue(self, name, value):
return None

def __InitNativeFunctions(self, chipLib):
if chipLib.pychip_SetupPayload_ParseQrCode is not None:
if chipLib.pychip_SetupPayload_ParseQrCode.argtypes is not None:
return
setter = NativeLibraryHandleMethodArguments(chipLib)
setter.Set("pychip_SetupPayload_ParseQrCode",
c_int32,
PyChipError,
[c_char_p, SetupPayload.AttributeVisitor, SetupPayload.VendorAttributeVisitor])
setter.Set("pychip_SetupPayload_ParseManualPairingCode",
c_int32,
PyChipError,
[c_char_p, SetupPayload.AttributeVisitor, SetupPayload.VendorAttributeVisitor])
setter.Set("pychip_SetupPayload_PrintOnboardingCodes",
c_int32,
PyChipError,
[c_uint32, c_uint16, c_uint16, c_uint16, c_uint8, c_uint8, c_uint8])

# Getters from parsed contents.
Expand Down
Loading