Skip to content

Commit

Permalink
Adding python bindings and platform implementation for Commissioner d…
Browse files Browse the repository at this point in the history
…iscovery
  • Loading branch information
sharadb-amazon committed Jun 26, 2021
1 parent b9dad95 commit 87e5328
Show file tree
Hide file tree
Showing 12 changed files with 318 additions and 57 deletions.
3 changes: 3 additions & 0 deletions src/controller/python/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ shared_library("ChipDeviceCtrl") {
include_dirs = [ "." ]

sources = [
"ChipCommissionableNodeController-ScriptBinding.cpp",
"ChipDeviceController-ScriptBinding.cpp",
"ChipDeviceController-ScriptDeviceAddressUpdateDelegate.cpp",
"ChipDeviceController-ScriptDeviceAddressUpdateDelegate.h",
Expand Down Expand Up @@ -71,6 +72,7 @@ shared_library("ChipDeviceCtrl") {

public_deps = [
"${chip_root}/src/app",
"${chip_root}/src/app/server",
"${chip_root}/src/controller/data_model",
"${chip_root}/src/lib",
"${chip_root}/src/lib/core",
Expand All @@ -95,6 +97,7 @@ pw_python_action("python") {
"chip/ChipBleBase.py",
"chip/ChipBleUtility.py",
"chip/ChipBluezMgr.py",
"chip/ChipCommissionableNodeCtrl.py",
"chip/ChipCoreBluetoothMgr.py",
"chip/ChipDeviceCtrl.py",
"chip/ChipStack.py",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
*
* Copyright (c) 2020-2021 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @file
* Implementation of the native methods expected by the Python
* version of CHIPCommissionableNodeController.
*
*/

#include <controller/CHIPCommissionableNodeController.h>
#include <inet/IPAddress.h>
#include <support/BytesToHex.h>
#include <support/logging/CHIPLogging.h>

using namespace chip;
using namespace chip::Controller;

extern "C" {
CHIP_ERROR
pychip_CommissionableNodeController_NewController(chip::Controller::CommissionableNodeController ** outCommissionableNodeCtrl);
CHIP_ERROR
pychip_CommissionableNodeController_DeleteController(chip::Controller::CommissionableNodeController * commissionableNodeCtrl);

CHIP_ERROR
pychip_CommissionableNodeController_DiscoverCommissioners(chip::Controller::CommissionableNodeController * commissionableNodeCtrl);
void pychip_CommissionableNodeController_PrintDiscoveredCommissioners(
chip::Controller::CommissionableNodeController * commissionableNodeCtrl);
}

CHIP_ERROR
pychip_CommissionableNodeController_NewController(chip::Controller::CommissionableNodeController ** outCommissionableNodeCtrl)
{
CHIP_ERROR err = CHIP_NO_ERROR;
*outCommissionableNodeCtrl = new chip::Controller::CommissionableNodeController();
VerifyOrExit(*outCommissionableNodeCtrl != NULL, err = CHIP_ERROR_NO_MEMORY);
exit:
return err;
}

CHIP_ERROR
pychip_CommissionableNodeController_DeleteController(chip::Controller::CommissionableNodeController * commissionableNodeCtrl)
{
if (commissionableNodeCtrl != NULL)
{
delete commissionableNodeCtrl;
}

return CHIP_NO_ERROR;
}

CHIP_ERROR
pychip_CommissionableNodeController_DiscoverCommissioners(chip::Controller::CommissionableNodeController * commissionableNodeCtrl)
{
return commissionableNodeCtrl->DiscoverCommissioners();
}

void pychip_CommissionableNodeController_PrintDiscoveredCommissioners(
chip::Controller::CommissionableNodeController * commissionableNodeCtrl)
{
for (int i = 0; i < CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES; ++i)
{
const chip::Mdns::DiscoveredNodeData * dnsSdInfo = commissionableNodeCtrl->GetDiscoveredCommissioner(i);
if (dnsSdInfo == nullptr)
{
continue;
}
char rotatingId[chip::Mdns::kMaxRotatingIdLen * 2 + 1] = "";
Encoding::BytesToUppercaseHexString(dnsSdInfo->rotatingId, dnsSdInfo->rotatingIdLen, rotatingId, sizeof(rotatingId));

ChipLogProgress(Discovery, "Commissioner %d", i);
ChipLogProgress(Discovery, "\tHost name:\t\t%s", dnsSdInfo->hostName);
ChipLogProgress(Discovery, "\tLong discriminator:\t%u", dnsSdInfo->longDiscriminator);
ChipLogProgress(Discovery, "\tVendor ID:\t\t%u", dnsSdInfo->vendorId);
ChipLogProgress(Discovery, "\tProduct ID:\t\t%u", dnsSdInfo->productId);
ChipLogProgress(Discovery, "\tAdditional Pairing\t%u", dnsSdInfo->additionalPairing);
ChipLogProgress(Discovery, "\tCommissioning Mode\t%u", dnsSdInfo->commissioningMode);
ChipLogProgress(Discovery, "\tDevice Type\t\t%u", dnsSdInfo->deviceType);
ChipLogProgress(Discovery, "\tDevice Name\t\t%s", dnsSdInfo->deviceName);
ChipLogProgress(Discovery, "\tRotating Id\t\t%s", rotatingId);
ChipLogProgress(Discovery, "\tPairing Instruction\t%s", dnsSdInfo->pairingInstruction);
ChipLogProgress(Discovery, "\tPairing Hint\t\t0x%x", dnsSdInfo->pairingHint);
for (int j = 0; j < dnsSdInfo->numIPs; ++j)
{
char buf[chip::Inet::kMaxIPAddressStringLength];
dnsSdInfo->ipAddress[j].ToString(buf);
ChipLogProgress(Discovery, "\tAddress %d:\t\t%s", j, buf);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ void pychip_DeviceController_PrintDiscoveredDevices(chip::Controller::DeviceComm
char rotatingId[chip::Mdns::kMaxRotatingIdLen * 2 + 1] = "";
Encoding::BytesToUppercaseHexString(dnsSdInfo->rotatingId, dnsSdInfo->rotatingIdLen, rotatingId, sizeof(rotatingId));

ChipLogProgress(Discovery, "Device %d", i);
ChipLogProgress(Discovery, "Commissionable Node %d", i);
ChipLogProgress(Discovery, "\tHost name:\t\t%s", dnsSdInfo->hostName);
ChipLogProgress(Discovery, "\tLong discriminator:\t%u", dnsSdInfo->longDiscriminator);
ChipLogProgress(Discovery, "\tVendor ID:\t\t%u", dnsSdInfo->vendorId);
Expand Down
22 changes: 14 additions & 8 deletions src/controller/python/chip-device-ctrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from __future__ import absolute_import
from __future__ import print_function
from chip import ChipDeviceCtrl
from chip import ChipCommissionableNodeCtrl
from chip import exceptions
import argparse
import ctypes
Expand Down Expand Up @@ -156,6 +157,8 @@ def __init__(self, rendezvousAddr=None, controllerNodeId=0, bluetoothAdapter=Non
self.devCtrl = ChipDeviceCtrl.ChipDeviceController(
controllerNodeId=controllerNodeId, bluetoothAdapter=bluetoothAdapter)

self.commissionableNodeCtrl = ChipCommissionableNodeCtrl.ChipCommissionableNodeController()

# If we are on Linux and user selects non-default bluetooth adapter.
if sys.platform.startswith("linux") and (bluetoothAdapter is not None):
try:
Expand Down Expand Up @@ -562,16 +565,19 @@ def do_discover(self, line):
return
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-all', help='discover all commissionable nodes', action='store_true')
group.add_argument('-qr', help='discover devices matching provided QR code', type=str)
group.add_argument('-l', help='discover devices with given long discriminator', type=int)
group.add_argument('-s', help='discover devices with given short discriminator', type=int)
group.add_argument('-v', help='discover devices wtih given vendor ID', type=int)
group.add_argument('-t', help='discover devices with given device type', type=int)
group.add_argument('-c', help='discover devices with given commissioning mode', type=int)
group.add_argument('-a', help='discover devices put in commissioning mode from command', action='store_true')
group.add_argument('-all', help='discover all commissionable nodes and commissioners', action='store_true')
group.add_argument('-qr', help='discover commissionable nodes matching provided QR code', type=str)
group.add_argument('-l', help='discover commissionable nodes with given long discriminator', type=int)
group.add_argument('-s', help='discover commissionable nodes with given short discriminator', type=int)
group.add_argument('-v', help='discover commissionable nodes wtih given vendor ID', type=int)
group.add_argument('-t', help='discover commissionable nodes with given device type', type=int)
group.add_argument('-c', help='discover commissionable nodes with given commissioning mode', type=int)
group.add_argument('-a', help='discover commissionable nodes put in commissioning mode from command', action='store_true')
args=parser.parse_args(arglist)
if args.all:
self.commissionableNodeCtrl.DiscoverCommissioners()
self.wait_for_many_discovered_devices()
self.commissionableNodeCtrl.PrintDiscoveredCommissioners()
self.devCtrl.DiscoverAllCommissioning()
self.wait_for_many_discovered_devices()
elif args.qr is not None:
Expand Down
96 changes: 96 additions & 0 deletions src/controller/python/chip/ChipCommissionableNodeCtrl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#
# Copyright (c) 2020-2021 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

#
# @file
# Python interface for ChipCommissionableNodeController
#

"""Chip Commissionable Node Controller interface
"""

from __future__ import absolute_import
from __future__ import print_function
import time
from threading import Thread
from ctypes import *
from .ChipStack import *
from .exceptions import *

__all__ = ["ChipCommissionableNodeController"]

def _singleton(cls):
instance = [None]

def wrapper(*args, **kwargs):
if instance[0] is None:
instance[0] = cls(*args, **kwargs)
return instance[0]

return wrapper

@_singleton
class ChipCommissionableNodeController(object):
def __init__(self, startNetworkThread=True):
self.commissionableNodeCtrl = None
self._ChipStack = ChipStack()
self._dmLib = None

self._InitLib()

commissionableNodeCtrl = c_void_p(None)
res = self._dmLib.pychip_CommissionableNodeController_NewController(
pointer(commissionableNodeCtrl))
if res != 0:
raise self._ChipStack.ErrorToException(res)

self.commissionableNodeCtrl = commissionableNodeCtrl
self._ChipStack.commissionableNodeCtrl = commissionableNodeCtrl

def __del__(self):
if self.commissionableNodeCtrl != None:
self._dmLib.pychip_CommissionableNodeController_DeleteController(
self.commissionableNodeCtrl)
self.commissionableNodeCtrl = None

def PrintDiscoveredCommissioners(self):
return self._ChipStack.Call(
lambda: self._dmLib.pychip_CommissionableNodeController_PrintDiscoveredCommissioners(self.commissionableNodeCtrl)
)

def DiscoverCommissioners(self):
return self._ChipStack.Call(
lambda: self._dmLib.pychip_CommissionableNodeController_DiscoverCommissioners(self.commissionableNodeCtrl)
)

# ----- Private Members -----
def _InitLib(self):
if self._dmLib is None:
self._dmLib = CDLL(self._ChipStack.LocateChipDLL())

self._dmLib.pychip_CommissionableNodeController_NewController.argtypes = [
POINTER(c_void_p)]
self._dmLib.pychip_CommissionableNodeController_NewController.restype = c_uint32

self._dmLib.pychip_CommissionableNodeController_DeleteController.argtypes = [
c_void_p]
self._dmLib.pychip_CommissionableNodeController_DeleteController.restype = c_uint32

self._dmLib.pychip_CommissionableNodeController_DiscoverCommissioners.argtypes = [c_void_p]
self._dmLib.pychip_CommissionableNodeController_DiscoverCommissioners.restype = c_uint32

self._dmLib.pychip_CommissionableNodeController_PrintDiscoveredCommissioners.argtypes = [c_void_p]
22 changes: 15 additions & 7 deletions src/lib/mdns/Discovery_ImplPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,6 @@ CHIP_ERROR DiscoveryImplPlatform::StopPublishDevice()

CHIP_ERROR DiscoveryImplPlatform::SetResolverDelegate(ResolverDelegate * delegate)
{
VerifyOrReturnError(delegate == nullptr || mResolverDelegate == nullptr, CHIP_ERROR_INCORRECT_STATE);
mResolverDelegate = delegate;
return CHIP_NO_ERROR;
}
Expand All @@ -432,16 +431,15 @@ CHIP_ERROR DiscoveryImplPlatform::ResolveNodeId(const PeerId & peerId, Inet::IPA
return ChipMdnsResolve(&service, INET_NULL_INTERFACEID, HandleNodeIdResolve, this);
}

void DiscoveryImplPlatform::HandleCommissionableNodeBrowse(void * context, MdnsService * services, size_t servicesSize,
CHIP_ERROR error)
void DiscoveryImplPlatform::HandleNodeBrowse(void * context, MdnsService * services, size_t servicesSize, CHIP_ERROR error)
{
for (size_t i = 0; i < servicesSize; ++i)
{
ChipMdnsResolve(&services[i], INET_NULL_INTERFACEID, HandleCommissionableNodeResolve, context);
ChipMdnsResolve(&services[i], INET_NULL_INTERFACEID, HandleNodeResolve, context);
}
}

void DiscoveryImplPlatform::HandleCommissionableNodeResolve(void * context, MdnsService * result, CHIP_ERROR error)
void DiscoveryImplPlatform::HandleNodeResolve(void * context, MdnsService * result, CHIP_ERROR error)
{
if (error != CHIP_NO_ERROR)
{
Expand Down Expand Up @@ -469,10 +467,20 @@ CHIP_ERROR DiscoveryImplPlatform::FindCommissionableNodes(DiscoveryFilter filter
{
ReturnErrorOnFailure(Init());
char serviceName[kMaxCommisisonableServiceNameSize];
ReturnErrorOnFailure(MakeCommissionableNodeServiceTypeName(serviceName, sizeof(serviceName), filter));
ReturnErrorOnFailure(MakeServiceTypeName(serviceName, sizeof(serviceName), filter, DiscoveryType::kCommissionableNode));

return ChipMdnsBrowse(serviceName, MdnsServiceProtocol::kMdnsProtocolUdp, Inet::kIPAddressType_Any, INET_NULL_INTERFACEID,
HandleCommissionableNodeBrowse, this);
HandleNodeBrowse, this);
}

CHIP_ERROR DiscoveryImplPlatform::FindCommissioners(DiscoveryFilter filter)
{
ReturnErrorOnFailure(Init());
char serviceName[kMaxCommisisonerServiceNameSize];
ReturnErrorOnFailure(MakeServiceTypeName(serviceName, sizeof(serviceName), filter, DiscoveryType::kCommissionerNode));

return ChipMdnsBrowse(serviceName, MdnsServiceProtocol::kMdnsProtocolUdp, Inet::kIPAddressType_Any, INET_NULL_INTERFACEID,
HandleNodeBrowse, this);
}

void DiscoveryImplPlatform::HandleNodeIdResolve(void * context, MdnsService * result, CHIP_ERROR error)
Expand Down
6 changes: 3 additions & 3 deletions src/lib/mdns/Discovery_ImplPlatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class DiscoveryImplPlatform : public ServiceAdvertiser, public Resolver

CHIP_ERROR FindCommissionableNodes(DiscoveryFilter filter = DiscoveryFilter()) override;

CHIP_ERROR FindCommissioners(DiscoveryFilter filter = DiscoveryFilter()) override { return CHIP_ERROR_NOT_IMPLEMENTED; }
CHIP_ERROR FindCommissioners(DiscoveryFilter filter = DiscoveryFilter()) override;

static DiscoveryImplPlatform & GetInstance();

Expand All @@ -72,8 +72,8 @@ class DiscoveryImplPlatform : public ServiceAdvertiser, public Resolver
static void HandleNodeIdResolve(void * context, MdnsService * result, CHIP_ERROR error);
static void HandleMdnsInit(void * context, CHIP_ERROR initError);
static void HandleMdnsError(void * context, CHIP_ERROR initError);
static void HandleCommissionableNodeBrowse(void * context, MdnsService * services, size_t servicesSize, CHIP_ERROR error);
static void HandleCommissionableNodeResolve(void * context, MdnsService * result, CHIP_ERROR error);
static void HandleNodeBrowse(void * context, MdnsService * services, size_t servicesSize, CHIP_ERROR error);
static void HandleNodeResolve(void * context, MdnsService * result, CHIP_ERROR error);
static CHIP_ERROR GenerateRotatingDeviceId(char rotatingDeviceIdHexBuffer[], size_t & rotatingDeviceIdHexBufferSize);
#ifdef DETAIL_LOGGING
static void PrintEntries(const MdnsService * service);
Expand Down
7 changes: 7 additions & 0 deletions src/lib/mdns/Resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ struct DiscoveryFilter
DiscoveryFilter() : type(DiscoveryFilterType::kNone), code(0) {}
DiscoveryFilter(DiscoveryFilterType newType, uint16_t newCode) : type(newType), code(newCode) {}
};
enum class DiscoveryType
{
kUnknown,
kOperational,
kCommissionableNode,
kCommissionerNode
};
/// Groups callbacks for CHIP service resolution requests
class ResolverDelegate
{
Expand Down
9 changes: 0 additions & 9 deletions src/lib/mdns/Resolver_ImplMinimalMdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,6 @@ namespace chip {
namespace Mdns {
namespace {

enum class DiscoveryType
{
kUnknown,
kOperational,
kCommissionableNode,
kCommissionerNode
};

class TxtRecordDelegateImpl : public mdns::Minimal::TxtRecordDelegate
{
public:
Expand Down Expand Up @@ -386,7 +378,6 @@ CHIP_ERROR MinMdnsResolver::SetResolverDelegate(ResolverDelegate * delegate)

CHIP_ERROR MinMdnsResolver::SendQuery(mdns::Minimal::FullQName qname, mdns::Minimal::QType type)
{

System::PacketBufferHandle buffer = System::PacketBufferHandle::New(kMdnsMaxPacketSize);
ReturnErrorCodeIf(buffer.IsNull(), CHIP_ERROR_NO_MEMORY);

Expand Down
Loading

0 comments on commit 87e5328

Please sign in to comment.