blob: eda6bf0b46308a1b1259b5a05fbaebfba74ef7a8 [file] [log] [blame]
Song GUOe1144312022-08-31 05:20:32 +08001/*
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>
Song GUOb9d32ec2022-10-24 14:40:11 +080027#include <controller/python/chip/native/PyChipError.h>
Song GUOe1144312022-08-31 05:20:32 +080028#include <json/json.h>
29#include <lib/core/CHIPError.h>
Martin Turon82bfcd52023-01-09 13:30:38 -080030#include <lib/core/TLV.h>
Song GUOe1144312022-08-31 05:20:32 +080031#include <lib/dnssd/Resolver.h>
32
33using namespace chip;
34
35typedef void (*IterateDiscoveredCommissionableNodesFunct)(const char * deviceInfoJson, size_t deviceInfoLen);
36
37extern "C" {
38
39bool pychip_DeviceController_HasDiscoveredCommissionableNode(Controller::DeviceCommissioner * devCtrl)
40{
41 for (int i = 0; i < devCtrl->GetMaxCommissionableNodesSupported(); ++i)
42 {
43 const Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(i);
44 if (dnsSdInfo == nullptr)
45 {
46 continue;
47 }
48 return true;
49 }
50 return false;
51}
52
Song GUOb9d32ec2022-10-24 14:40:11 +080053PyChipError pychip_DeviceController_DiscoverCommissionableNodes(Controller::DeviceCommissioner * devCtrl, const uint8_t filterType,
54 const char * filterParam)
Song GUOe1144312022-08-31 05:20:32 +080055{
56 Dnssd::DiscoveryFilter filter(static_cast<Dnssd::DiscoveryFilterType>(filterType));
57 switch (static_cast<Dnssd::DiscoveryFilterType>(filterType))
58 {
59 case Dnssd::DiscoveryFilterType::kNone:
60 break;
61 case Dnssd::DiscoveryFilterType::kShortDiscriminator:
62 case Dnssd::DiscoveryFilterType::kLongDiscriminator:
63 case Dnssd::DiscoveryFilterType::kCompressedFabricId:
64 case Dnssd::DiscoveryFilterType::kVendorId:
65 case Dnssd::DiscoveryFilterType::kDeviceType: {
66 // For any numerical filter, convert the string to a filter value
67 errno = 0;
68 unsigned long long int numericalArg = strtoull(filterParam, nullptr, 0);
69 if ((numericalArg == ULLONG_MAX) && (errno == ERANGE))
70 {
Song GUOb9d32ec2022-10-24 14:40:11 +080071 return ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT);
Song GUOe1144312022-08-31 05:20:32 +080072 }
73 filter.code = static_cast<uint64_t>(numericalArg);
74 break;
75 }
76 case Dnssd::DiscoveryFilterType::kCommissioningMode:
77 break;
78 case Dnssd::DiscoveryFilterType::kCommissioner:
79 filter.code = 1;
80 break;
81 case Dnssd::DiscoveryFilterType::kInstanceName:
82 filter.code = 0;
83 filter.instanceName = filterParam;
84 break;
85 default:
Song GUOb9d32ec2022-10-24 14:40:11 +080086 return ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT);
Song GUOe1144312022-08-31 05:20:32 +080087 }
88
Song GUOb9d32ec2022-10-24 14:40:11 +080089 return ToPyChipError(devCtrl->DiscoverCommissionableNodes(filter));
Song GUOe1144312022-08-31 05:20:32 +080090}
91
92void pychip_DeviceController_IterateDiscoveredCommissionableNodes(Controller::DeviceCommissioner * devCtrl,
93 IterateDiscoveredCommissionableNodesFunct cb)
94{
95 VerifyOrReturn(cb != nullptr);
96
97 for (int i = 0; i < devCtrl->GetMaxCommissionableNodesSupported(); ++i)
98 {
99 const Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(i);
100 if (dnsSdInfo == nullptr)
101 {
102 continue;
103 }
104
105 Json::Value jsonVal;
106
107 char rotatingId[Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
108 Encoding::BytesToUppercaseHexString(dnsSdInfo->commissionData.rotatingId, dnsSdInfo->commissionData.rotatingIdLen,
109 rotatingId, sizeof(rotatingId));
110
111 ChipLogProgress(Discovery, "Commissionable Node %d", i);
112 jsonVal["instanceName"] = dnsSdInfo->commissionData.instanceName;
113 jsonVal["hostName"] = dnsSdInfo->resolutionData.hostName;
114 jsonVal["port"] = dnsSdInfo->resolutionData.port;
115 jsonVal["longDiscriminator"] = dnsSdInfo->commissionData.longDiscriminator;
116 jsonVal["vendorId"] = dnsSdInfo->commissionData.vendorId;
117 jsonVal["productId"] = dnsSdInfo->commissionData.productId;
118 jsonVal["commissioningMode"] = dnsSdInfo->commissionData.commissioningMode;
119 jsonVal["deviceType"] = dnsSdInfo->commissionData.deviceType;
120 jsonVal["deviceName"] = dnsSdInfo->commissionData.deviceName;
121 jsonVal["pairingInstruction"] = dnsSdInfo->commissionData.pairingInstruction;
122 jsonVal["pairingHint"] = dnsSdInfo->commissionData.pairingHint;
123 if (dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().HasValue())
124 {
125 jsonVal["mrpRetryIntervalIdle"] = dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().Value().count();
126 }
127 if (dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().HasValue())
128 {
129 jsonVal["mrpRetryIntervalActive"] = dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().Value().count();
130 }
131 jsonVal["supportsTcp"] = dnsSdInfo->resolutionData.supportsTcp;
132 {
133 Json::Value addresses;
134 for (unsigned j = 0; j < dnsSdInfo->resolutionData.numIPs; ++j)
135 {
136 char buf[Inet::IPAddress::kMaxStringLength];
137 dnsSdInfo->resolutionData.ipAddress[j].ToString(buf);
138 addresses[j] = buf;
139 }
140 jsonVal["addresses"] = addresses;
141 }
Andrei Litvine5842df2023-02-06 14:30:29 -0500142 if (dnsSdInfo->commissionData.rotatingIdLen > 0)
143 {
tianfeng-yang3de75bb2023-07-15 04:19:26 +0800144 jsonVal["rotatingId"] = rotatingId;
Andrei Litvine5842df2023-02-06 14:30:29 -0500145 }
Song GUOe1144312022-08-31 05:20:32 +0800146
147 {
148 auto str = jsonVal.toStyledString();
149 cb(str.c_str(), str.size());
150 }
151 }
152}
153
154void pychip_DeviceController_PrintDiscoveredDevices(Controller::DeviceCommissioner * devCtrl)
155{
156 for (int i = 0; i < devCtrl->GetMaxCommissionableNodesSupported(); ++i)
157 {
158 const Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(i);
159 if (dnsSdInfo == nullptr)
160 {
161 continue;
162 }
163 char rotatingId[Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
164 Encoding::BytesToUppercaseHexString(dnsSdInfo->commissionData.rotatingId, dnsSdInfo->commissionData.rotatingIdLen,
165 rotatingId, sizeof(rotatingId));
166
167 ChipLogProgress(Discovery, "Commissionable Node %d", i);
168 ChipLogProgress(Discovery, "\tInstance name:\t\t%s", dnsSdInfo->commissionData.instanceName);
169 ChipLogProgress(Discovery, "\tHost name:\t\t%s", dnsSdInfo->resolutionData.hostName);
170 ChipLogProgress(Discovery, "\tPort:\t\t\t%u", dnsSdInfo->resolutionData.port);
171 ChipLogProgress(Discovery, "\tLong discriminator:\t%u", dnsSdInfo->commissionData.longDiscriminator);
172 ChipLogProgress(Discovery, "\tVendor ID:\t\t%u", dnsSdInfo->commissionData.vendorId);
173 ChipLogProgress(Discovery, "\tProduct ID:\t\t%u", dnsSdInfo->commissionData.productId);
174 ChipLogProgress(Discovery, "\tCommissioning Mode\t%u", dnsSdInfo->commissionData.commissioningMode);
175 ChipLogProgress(Discovery, "\tDevice Type\t\t%u", dnsSdInfo->commissionData.deviceType);
176 ChipLogProgress(Discovery, "\tDevice Name\t\t%s", dnsSdInfo->commissionData.deviceName);
177 ChipLogProgress(Discovery, "\tRotating Id\t\t%s", rotatingId);
178 ChipLogProgress(Discovery, "\tPairing Instruction\t%s", dnsSdInfo->commissionData.pairingInstruction);
179 ChipLogProgress(Discovery, "\tPairing Hint\t\t%u", dnsSdInfo->commissionData.pairingHint);
180 if (dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().HasValue())
181 {
182 ChipLogProgress(Discovery, "\tMrp Interval idle\t%u",
183 dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().Value().count());
184 }
185 else
186 {
187 ChipLogProgress(Discovery, "\tMrp Interval idle\tNot present");
188 }
189 if (dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().HasValue())
190 {
191 ChipLogProgress(Discovery, "\tMrp Interval active\t%u",
192 dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().Value().count());
193 }
194 else
195 {
196 ChipLogProgress(Discovery, "\tMrp Interval active\tNot present");
197 }
198 ChipLogProgress(Discovery, "\tSupports TCP\t\t%d", dnsSdInfo->resolutionData.supportsTcp);
199 for (unsigned j = 0; j < dnsSdInfo->resolutionData.numIPs; ++j)
200 {
201 char buf[Inet::IPAddress::kMaxStringLength];
202 dnsSdInfo->resolutionData.ipAddress[j].ToString(buf);
203 ChipLogProgress(Discovery, "\tAddress %d:\t\t%s", j, buf);
204 }
205 }
206}
207
208bool pychip_DeviceController_GetIPForDiscoveredDevice(Controller::DeviceCommissioner * devCtrl, int idx, char * addrStr,
209 uint32_t len)
210{
211 const Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(idx);
212 if (dnsSdInfo == nullptr)
213 {
214 return false;
215 }
216 // TODO(cecille): Select which one we actually want.
217 if (dnsSdInfo->resolutionData.ipAddress[0].ToString(addrStr, len) == addrStr)
218 {
219 return true;
220 }
221 return false;
222}
223}