Skip to content

Commit

Permalink
implement unpairdevice API for python CHIP controller (#25961)
Browse files Browse the repository at this point in the history
* implement unpairdevice API for python chip controller

* Restyled by clang-format

* Restyled by autopep8

* pep8 formatting

* autopep8

* fix leak on error return from RemoveCurrentFabric

* delete fabric remover on error

* autopep8

* clean up callbacks as well on RemoveCurrentFabric error

---------

Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: Andrei Litvin <andy314@gmail.com>
  • Loading branch information
3 people authored and pull[bot] committed Oct 2, 2023
1 parent 0f80d81 commit b9109ea
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
44 changes: 44 additions & 0 deletions src/controller/python/ChipDeviceController-ScriptBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include <controller/CHIPDeviceControllerFactory.h>
#include <controller/CommissioningDelegate.h>
#include <controller/CommissioningWindowOpener.h>
#include <controller/CurrentFabricRemover.h>
#include <controller/ExampleOperationalCredentialsIssuer.h>

#include <controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h>
Expand Down Expand Up @@ -89,6 +90,7 @@ typedef void (*ConstructBytesArrayFunct)(const uint8_t * dataBuf, uint32_t dataL
typedef void (*LogMessageFunct)(uint64_t time, uint64_t timeUS, const char * moduleName, uint8_t category, const char * msg);
typedef void (*DeviceAvailableFunc)(DeviceProxy * device, PyChipError err);
typedef void (*ChipThreadTaskRunnerFunct)(intptr_t context);
typedef void (*DeviceUnpairingCompleteFunct)(uint64_t nodeId, PyChipError error);
}

namespace {
Expand Down Expand Up @@ -131,6 +133,8 @@ PyChipError pychip_DeviceController_ConnectIP(chip::Controller::DeviceCommission
uint32_t setupPINCode, chip::NodeId nodeid);
PyChipError pychip_DeviceController_ConnectWithCode(chip::Controller::DeviceCommissioner * devCtrl, const char * onboardingPayload,
chip::NodeId nodeid);
PyChipError pychip_DeviceController_UnpairDevice(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId remoteDeviceId,
DeviceUnpairingCompleteFunct callback);
PyChipError pychip_DeviceController_SetThreadOperationalDataset(const char * threadOperationalDataset, uint32_t size);
PyChipError pychip_DeviceController_SetWiFiCredentials(const char * ssid, const char * credentials);
PyChipError pychip_DeviceController_CloseSession(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeid);
Expand Down Expand Up @@ -386,6 +390,46 @@ PyChipError pychip_DeviceController_ConnectWithCode(chip::Controller::DeviceComm
return ToPyChipError(devCtrl->PairDevice(nodeid, onboardingPayload, sCommissioningParameters));
}

namespace {
struct UnpairDeviceCallback
{
UnpairDeviceCallback(DeviceUnpairingCompleteFunct callback, chip::Controller::CurrentFabricRemover * remover) :
mOnCurrentFabricRemove(OnCurrentFabricRemoveFn, this), mCallback(callback), mRemover(remover)
{}

static void OnCurrentFabricRemoveFn(void * context, chip::NodeId nodeId, CHIP_ERROR error)
{
auto * self = static_cast<UnpairDeviceCallback *>(context);
self->mCallback(nodeId, ToPyChipError(error));
delete self->mRemover;
delete self;
}

Callback::Callback<OnCurrentFabricRemove> mOnCurrentFabricRemove;
DeviceUnpairingCompleteFunct mCallback;
chip::Controller::CurrentFabricRemover * mRemover;
};
} // anonymous namespace

PyChipError pychip_DeviceController_UnpairDevice(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeid,
DeviceUnpairingCompleteFunct callback)
{
// Create a new CurrentFabricRemover instance
auto * fabricRemover = new chip::Controller::CurrentFabricRemover(devCtrl);

auto * callbacks = new UnpairDeviceCallback(callback, fabricRemover);

// Pass the callback and nodeid to the RemoveCurrentFabric function
CHIP_ERROR err = fabricRemover->RemoveCurrentFabric(nodeid, &callbacks->mOnCurrentFabricRemove);
if (err != CHIP_NO_ERROR)
{
delete fabricRemover;
delete callbacks;
}
// Else will clean up when the callback is called.
return ToPyChipError(err);
}

PyChipError pychip_DeviceController_OnNetworkCommission(chip::Controller::DeviceCommissioner * devCtrl, uint64_t nodeId,
uint32_t setupPasscode, const uint8_t filterType, const char * filterParam)
{
Expand Down
25 changes: 24 additions & 1 deletion src/controller/python/chip/ChipDeviceCtrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
__all__ = ["ChipDeviceController"]

_DevicePairingDelegate_OnPairingCompleteFunct = CFUNCTYPE(None, PyChipError)
_DeviceUnpairingCompleteFunct = CFUNCTYPE(None, c_uint64, PyChipError)
_DevicePairingDelegate_OnCommissioningCompleteFunct = CFUNCTYPE(
None, c_uint64, PyChipError)
_DevicePairingDelegate_OnOpenWindowCompleteFunct = CFUNCTYPE(
Expand Down Expand Up @@ -248,6 +249,15 @@ def HandleOpenWindowComplete(nodeid: int, setupPinCode: int, setupCode: str, err
self._ChipStack.callbackRes = err
self._ChipStack.completeEvent.set()

def HandleUnpairDeviceComplete(nodeid: int, err: PyChipError):
if err.is_success:
print("Succesfully unpaired device with nodeid {}".format(nodeid))
else:
print("Failed to unpair device: {}".format(err))

self._ChipStack.callbackRes = err
self._ChipStack.completeEvent.set()

def HandlePASEEstablishmentComplete(err: PyChipError):
if not err.is_success:
print("Failed to establish secure session to device: {}".format(err))
Expand Down Expand Up @@ -284,9 +294,10 @@ def HandlePASEEstablishmentComplete(err: PyChipError):
self._dmLib.pychip_ScriptDevicePairingDelegate_SetOpenWindowCompleteCallback(
self.devCtrl, self.cbHandleOpenWindowCompleteFunct)

self.cbHandleDeviceUnpairCompleteFunct = _DeviceUnpairingCompleteFunct(HandleUnpairDeviceComplete)

self.state = DCState.IDLE
self._isActive = True

# Validate FabricID/NodeID followed from NOC Chain
self._fabricId = self.GetFabricIdInternal()
self._nodeId = self.GetNodeIdInternal()
Expand Down Expand Up @@ -386,6 +397,14 @@ def ConnectBLE(self, discriminator, setupPinCode, nodeid):
return False
return self._ChipStack.commissioningEventRes.is_success

def UnpairDevice(self, nodeid: int):
self.CheckIsActive()

return self._ChipStack.CallAsync(
lambda: self._dmLib.pychip_DeviceController_UnpairDevice(
self.devCtrl, nodeid, self.cbHandleDeviceUnpairCompleteFunct)
).raise_on_error()

def CloseBLEConnection(self):
self.CheckIsActive()

Expand Down Expand Up @@ -1274,6 +1293,10 @@ def _InitLib(self):
c_void_p, c_char_p, c_uint64]
self._dmLib.pychip_DeviceController_ConnectWithCode.restype = PyChipError

self._dmLib.pychip_DeviceController_UnpairDevice.argtypes = [
c_void_p, c_uint64, _DeviceUnpairingCompleteFunct]
self._dmLib.pychip_DeviceController_UnpairDevice.restype = PyChipError

self._dmLib.pychip_DeviceController_CloseSession.argtypes = [
c_void_p, c_uint64]
self._dmLib.pychip_DeviceController_CloseSession.restype = PyChipError
Expand Down

0 comments on commit b9109ea

Please sign in to comment.