Skip to content

Commit e114431

Browse files
authored
[python] Add script interface for node discovery in REPL (#22034)
1 parent 0b43763 commit e114431

10 files changed

+4719
-253
lines changed

docs/guides/repl/.ipynb_checkpoints/Matter - Basic Interactions-checkpoint.ipynb

+4,218
Large diffs are not rendered by default.

docs/guides/repl/Matter - Basic Interactions.ipynb

+134-164
Large diffs are not rendered by default.

src/controller/python/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ shared_library("ChipDeviceCtrl") {
5151
if (chip_controller) {
5252
sources += [
5353
"ChipCommissionableNodeController-ScriptBinding.cpp",
54+
"ChipDeviceController-Discovery.cpp",
5455
"ChipDeviceController-IssueNocChain.cpp",
5556
"ChipDeviceController-ScriptBinding.cpp",
5657
"ChipDeviceController-ScriptDevicePairingDelegate.cpp",
@@ -109,6 +110,7 @@ shared_library("ChipDeviceCtrl") {
109110
public_deps += [
110111
"${chip_root}/src/controller/data_model",
111112
"${chip_root}/src/credentials:file_attestation_trust_store",
113+
"${chip_root}/third_party/jsoncpp",
112114
]
113115
} else {
114116
public_deps += [ "$chip_data_model" ]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/*
2+
*
3+
* Copyright (c) 2022 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/**
20+
* @file
21+
* Implementation of the native methods expected by the Python
22+
* version of Chip Device Manager.
23+
*
24+
*/
25+
26+
#include <controller/CHIPDeviceController.h>
27+
#include <json/json.h>
28+
#include <lib/core/CHIPError.h>
29+
#include <lib/core/CHIPTLV.h>
30+
#include <lib/dnssd/Resolver.h>
31+
32+
using namespace chip;
33+
34+
typedef void (*IterateDiscoveredCommissionableNodesFunct)(const char * deviceInfoJson, size_t deviceInfoLen);
35+
36+
extern "C" {
37+
38+
bool pychip_DeviceController_HasDiscoveredCommissionableNode(Controller::DeviceCommissioner * devCtrl)
39+
{
40+
for (int i = 0; i < devCtrl->GetMaxCommissionableNodesSupported(); ++i)
41+
{
42+
const Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(i);
43+
if (dnsSdInfo == nullptr)
44+
{
45+
continue;
46+
}
47+
return true;
48+
}
49+
return false;
50+
}
51+
52+
ChipError::StorageType pychip_DeviceController_DiscoverCommissionableNodes(Controller::DeviceCommissioner * devCtrl,
53+
const uint8_t filterType, const char * filterParam)
54+
{
55+
Dnssd::DiscoveryFilter filter(static_cast<Dnssd::DiscoveryFilterType>(filterType));
56+
switch (static_cast<Dnssd::DiscoveryFilterType>(filterType))
57+
{
58+
case Dnssd::DiscoveryFilterType::kNone:
59+
break;
60+
case Dnssd::DiscoveryFilterType::kShortDiscriminator:
61+
case Dnssd::DiscoveryFilterType::kLongDiscriminator:
62+
case Dnssd::DiscoveryFilterType::kCompressedFabricId:
63+
case Dnssd::DiscoveryFilterType::kVendorId:
64+
case Dnssd::DiscoveryFilterType::kDeviceType: {
65+
// For any numerical filter, convert the string to a filter value
66+
errno = 0;
67+
unsigned long long int numericalArg = strtoull(filterParam, nullptr, 0);
68+
if ((numericalArg == ULLONG_MAX) && (errno == ERANGE))
69+
{
70+
return CHIP_ERROR_INVALID_ARGUMENT.AsInteger();
71+
}
72+
filter.code = static_cast<uint64_t>(numericalArg);
73+
break;
74+
}
75+
case Dnssd::DiscoveryFilterType::kCommissioningMode:
76+
break;
77+
case Dnssd::DiscoveryFilterType::kCommissioner:
78+
filter.code = 1;
79+
break;
80+
case Dnssd::DiscoveryFilterType::kInstanceName:
81+
filter.code = 0;
82+
filter.instanceName = filterParam;
83+
break;
84+
default:
85+
return CHIP_ERROR_INVALID_ARGUMENT.AsInteger();
86+
}
87+
88+
return devCtrl->DiscoverCommissionableNodes(filter).AsInteger();
89+
}
90+
91+
void pychip_DeviceController_IterateDiscoveredCommissionableNodes(Controller::DeviceCommissioner * devCtrl,
92+
IterateDiscoveredCommissionableNodesFunct cb)
93+
{
94+
VerifyOrReturn(cb != nullptr);
95+
96+
for (int i = 0; i < devCtrl->GetMaxCommissionableNodesSupported(); ++i)
97+
{
98+
const Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(i);
99+
if (dnsSdInfo == nullptr)
100+
{
101+
continue;
102+
}
103+
104+
Json::Value jsonVal;
105+
106+
char rotatingId[Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
107+
Encoding::BytesToUppercaseHexString(dnsSdInfo->commissionData.rotatingId, dnsSdInfo->commissionData.rotatingIdLen,
108+
rotatingId, sizeof(rotatingId));
109+
110+
ChipLogProgress(Discovery, "Commissionable Node %d", i);
111+
jsonVal["instanceName"] = dnsSdInfo->commissionData.instanceName;
112+
jsonVal["hostName"] = dnsSdInfo->resolutionData.hostName;
113+
jsonVal["port"] = dnsSdInfo->resolutionData.port;
114+
jsonVal["longDiscriminator"] = dnsSdInfo->commissionData.longDiscriminator;
115+
jsonVal["vendorId"] = dnsSdInfo->commissionData.vendorId;
116+
jsonVal["productId"] = dnsSdInfo->commissionData.productId;
117+
jsonVal["commissioningMode"] = dnsSdInfo->commissionData.commissioningMode;
118+
jsonVal["deviceType"] = dnsSdInfo->commissionData.deviceType;
119+
jsonVal["deviceName"] = dnsSdInfo->commissionData.deviceName;
120+
jsonVal["pairingInstruction"] = dnsSdInfo->commissionData.pairingInstruction;
121+
jsonVal["pairingHint"] = dnsSdInfo->commissionData.pairingHint;
122+
if (dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().HasValue())
123+
{
124+
jsonVal["mrpRetryIntervalIdle"] = dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().Value().count();
125+
}
126+
if (dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().HasValue())
127+
{
128+
jsonVal["mrpRetryIntervalActive"] = dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().Value().count();
129+
}
130+
jsonVal["supportsTcp"] = dnsSdInfo->resolutionData.supportsTcp;
131+
{
132+
Json::Value addresses;
133+
for (unsigned j = 0; j < dnsSdInfo->resolutionData.numIPs; ++j)
134+
{
135+
char buf[Inet::IPAddress::kMaxStringLength];
136+
dnsSdInfo->resolutionData.ipAddress[j].ToString(buf);
137+
addresses[j] = buf;
138+
}
139+
jsonVal["addresses"] = addresses;
140+
}
141+
142+
{
143+
auto str = jsonVal.toStyledString();
144+
cb(str.c_str(), str.size());
145+
}
146+
}
147+
}
148+
149+
void pychip_DeviceController_PrintDiscoveredDevices(Controller::DeviceCommissioner * devCtrl)
150+
{
151+
for (int i = 0; i < devCtrl->GetMaxCommissionableNodesSupported(); ++i)
152+
{
153+
const Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(i);
154+
if (dnsSdInfo == nullptr)
155+
{
156+
continue;
157+
}
158+
char rotatingId[Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
159+
Encoding::BytesToUppercaseHexString(dnsSdInfo->commissionData.rotatingId, dnsSdInfo->commissionData.rotatingIdLen,
160+
rotatingId, sizeof(rotatingId));
161+
162+
ChipLogProgress(Discovery, "Commissionable Node %d", i);
163+
ChipLogProgress(Discovery, "\tInstance name:\t\t%s", dnsSdInfo->commissionData.instanceName);
164+
ChipLogProgress(Discovery, "\tHost name:\t\t%s", dnsSdInfo->resolutionData.hostName);
165+
ChipLogProgress(Discovery, "\tPort:\t\t\t%u", dnsSdInfo->resolutionData.port);
166+
ChipLogProgress(Discovery, "\tLong discriminator:\t%u", dnsSdInfo->commissionData.longDiscriminator);
167+
ChipLogProgress(Discovery, "\tVendor ID:\t\t%u", dnsSdInfo->commissionData.vendorId);
168+
ChipLogProgress(Discovery, "\tProduct ID:\t\t%u", dnsSdInfo->commissionData.productId);
169+
ChipLogProgress(Discovery, "\tCommissioning Mode\t%u", dnsSdInfo->commissionData.commissioningMode);
170+
ChipLogProgress(Discovery, "\tDevice Type\t\t%u", dnsSdInfo->commissionData.deviceType);
171+
ChipLogProgress(Discovery, "\tDevice Name\t\t%s", dnsSdInfo->commissionData.deviceName);
172+
ChipLogProgress(Discovery, "\tRotating Id\t\t%s", rotatingId);
173+
ChipLogProgress(Discovery, "\tPairing Instruction\t%s", dnsSdInfo->commissionData.pairingInstruction);
174+
ChipLogProgress(Discovery, "\tPairing Hint\t\t%u", dnsSdInfo->commissionData.pairingHint);
175+
if (dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().HasValue())
176+
{
177+
ChipLogProgress(Discovery, "\tMrp Interval idle\t%u",
178+
dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().Value().count());
179+
}
180+
else
181+
{
182+
ChipLogProgress(Discovery, "\tMrp Interval idle\tNot present");
183+
}
184+
if (dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().HasValue())
185+
{
186+
ChipLogProgress(Discovery, "\tMrp Interval active\t%u",
187+
dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().Value().count());
188+
}
189+
else
190+
{
191+
ChipLogProgress(Discovery, "\tMrp Interval active\tNot present");
192+
}
193+
ChipLogProgress(Discovery, "\tSupports TCP\t\t%d", dnsSdInfo->resolutionData.supportsTcp);
194+
for (unsigned j = 0; j < dnsSdInfo->resolutionData.numIPs; ++j)
195+
{
196+
char buf[Inet::IPAddress::kMaxStringLength];
197+
dnsSdInfo->resolutionData.ipAddress[j].ToString(buf);
198+
ChipLogProgress(Discovery, "\tAddress %d:\t\t%s", j, buf);
199+
}
200+
}
201+
}
202+
203+
bool pychip_DeviceController_GetIPForDiscoveredDevice(Controller::DeviceCommissioner * devCtrl, int idx, char * addrStr,
204+
uint32_t len)
205+
{
206+
const Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(idx);
207+
if (dnsSdInfo == nullptr)
208+
{
209+
return false;
210+
}
211+
// TODO(cecille): Select which one we actually want.
212+
if (dnsSdInfo->resolutionData.ipAddress[0].ToString(addrStr, len) == addrStr)
213+
{
214+
return true;
215+
}
216+
return false;
217+
}
218+
}

src/controller/python/ChipDeviceController-ScriptBinding.cpp

+1-70
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
6161
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
6262
#include <inet/IPAddress.h>
63+
#include <lib/core/CHIPTLV.h>
6364
#include <lib/dnssd/Resolver.h>
6465
#include <lib/support/BytesToHex.h>
6566
#include <lib/support/CHIPMem.h>
@@ -551,76 +552,6 @@ ChipError::StorageType pychip_DeviceController_OpenCommissioningWindow(chip::Con
551552
return CHIP_ERROR_INVALID_ARGUMENT.AsInteger();
552553
}
553554

554-
void pychip_DeviceController_PrintDiscoveredDevices(chip::Controller::DeviceCommissioner * devCtrl)
555-
{
556-
for (int i = 0; i < devCtrl->GetMaxCommissionableNodesSupported(); ++i)
557-
{
558-
const chip::Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(i);
559-
if (dnsSdInfo == nullptr)
560-
{
561-
continue;
562-
}
563-
char rotatingId[chip::Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
564-
Encoding::BytesToUppercaseHexString(dnsSdInfo->commissionData.rotatingId, dnsSdInfo->commissionData.rotatingIdLen,
565-
rotatingId, sizeof(rotatingId));
566-
567-
ChipLogProgress(Discovery, "Commissionable Node %d", i);
568-
ChipLogProgress(Discovery, "\tInstance name:\t\t%s", dnsSdInfo->commissionData.instanceName);
569-
ChipLogProgress(Discovery, "\tHost name:\t\t%s", dnsSdInfo->resolutionData.hostName);
570-
ChipLogProgress(Discovery, "\tPort:\t\t\t%u", dnsSdInfo->resolutionData.port);
571-
ChipLogProgress(Discovery, "\tLong discriminator:\t%u", dnsSdInfo->commissionData.longDiscriminator);
572-
ChipLogProgress(Discovery, "\tVendor ID:\t\t%u", dnsSdInfo->commissionData.vendorId);
573-
ChipLogProgress(Discovery, "\tProduct ID:\t\t%u", dnsSdInfo->commissionData.productId);
574-
ChipLogProgress(Discovery, "\tCommissioning Mode\t%u", dnsSdInfo->commissionData.commissioningMode);
575-
ChipLogProgress(Discovery, "\tDevice Type\t\t%u", dnsSdInfo->commissionData.deviceType);
576-
ChipLogProgress(Discovery, "\tDevice Name\t\t%s", dnsSdInfo->commissionData.deviceName);
577-
ChipLogProgress(Discovery, "\tRotating Id\t\t%s", rotatingId);
578-
ChipLogProgress(Discovery, "\tPairing Instruction\t%s", dnsSdInfo->commissionData.pairingInstruction);
579-
ChipLogProgress(Discovery, "\tPairing Hint\t\t%u", dnsSdInfo->commissionData.pairingHint);
580-
if (dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().HasValue())
581-
{
582-
ChipLogProgress(Discovery, "\tMrp Interval idle\t%u",
583-
dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().Value().count());
584-
}
585-
else
586-
{
587-
ChipLogProgress(Discovery, "\tMrp Interval idle\tNot present");
588-
}
589-
if (dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().HasValue())
590-
{
591-
ChipLogProgress(Discovery, "\tMrp Interval active\t%u",
592-
dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().Value().count());
593-
}
594-
else
595-
{
596-
ChipLogProgress(Discovery, "\tMrp Interval active\tNot present");
597-
}
598-
ChipLogProgress(Discovery, "\tSupports TCP\t\t%d", dnsSdInfo->resolutionData.supportsTcp);
599-
for (unsigned j = 0; j < dnsSdInfo->resolutionData.numIPs; ++j)
600-
{
601-
char buf[chip::Inet::IPAddress::kMaxStringLength];
602-
dnsSdInfo->resolutionData.ipAddress[j].ToString(buf);
603-
ChipLogProgress(Discovery, "\tAddress %d:\t\t%s", j, buf);
604-
}
605-
}
606-
}
607-
608-
bool pychip_DeviceController_GetIPForDiscoveredDevice(chip::Controller::DeviceCommissioner * devCtrl, int idx, char * addrStr,
609-
uint32_t len)
610-
{
611-
const chip::Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(idx);
612-
if (dnsSdInfo == nullptr)
613-
{
614-
return false;
615-
}
616-
// TODO(cecille): Select which one we actually want.
617-
if (dnsSdInfo->resolutionData.ipAddress[0].ToString(addrStr, len) == addrStr)
618-
{
619-
return true;
620-
}
621-
return false;
622-
}
623-
624555
ChipError::StorageType
625556
pychip_ScriptDevicePairingDelegate_SetKeyExchangeCallback(chip::Controller::DeviceCommissioner * devCtrl,
626557
chip::Controller::DevicePairingDelegate_OnPairingCompleteFunct callback)

0 commit comments

Comments
 (0)