Skip to content

Commit 3d78493

Browse files
Fix python Wi-Fi/Thread setup with manual code (#33933)
* Fix python Wi-Fi/Thread setup with manual code - Plumbing was missing to pass down the short discriminator - Passing `--manual-code 1234-567-8901` which only has short discriminator, would always fail to find device over BLE Fixes #26907 This PR: - Adds plumbing to detect short discriminator in Python controller - Improves code-based setup in CHIPDeviceController to honor the SetupDiscriminator value, including whether short/long. Testing done: - Ran `python3 src/python_testing/TC_SC_3_6.py --commissioning-method ble-wifi --wifi-ssid MySsid --wifi-passphrase Secret123 --manual-code 2168-374-4904 --storage-path kvs1` - Before fix, discriminator always mismatched. - After fix, commissioning succeeds. - Unit tests and other integration tests still pass * Restyled by clang-format * Restyled by autopep8 * Add warning about GetDiscriminator * Improve unit test * Fix tests * Address review comments * Restyled by clang-format --------- Co-authored-by: Restyled.io <commits@restyled.io>
1 parent d5e92e8 commit 3d78493

File tree

8 files changed

+103
-39
lines changed

8 files changed

+103
-39
lines changed

src/controller/CHIPDeviceController.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -793,10 +793,9 @@ CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, Re
793793
// for later.
794794
mRendezvousParametersForDeviceDiscoveredOverBle = params;
795795

796-
SetupDiscriminator discriminator;
797-
discriminator.SetLongValue(params.GetDiscriminator());
798-
SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByDiscriminator(
799-
discriminator, this, OnDiscoveredDeviceOverBleSuccess, OnDiscoveredDeviceOverBleError));
796+
SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByDiscriminator(params.GetSetupDiscriminator().value(),
797+
this, OnDiscoveredDeviceOverBleSuccess,
798+
OnDiscoveredDeviceOverBleError));
800799
ExitNow(CHIP_NO_ERROR);
801800
}
802801
else

src/controller/python/ChipDeviceController-ScriptBinding.cpp

+15-3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
#include <lib/support/CodeUtils.h>
7777
#include <lib/support/DLLUtil.h>
7878
#include <lib/support/ScopedBuffer.h>
79+
#include <lib/support/SetupDiscriminator.h>
7980
#include <platform/CHIPDeviceLayer.h>
8081
#include <setup_payload/QRCodeSetupPayloadParser.h>
8182
#include <system/SystemClock.h>
@@ -140,7 +141,7 @@ PyChipError pychip_DeviceController_GetNodeId(chip::Controller::DeviceCommission
140141

141142
// Rendezvous
142143
PyChipError pychip_DeviceController_ConnectBLE(chip::Controller::DeviceCommissioner * devCtrl, uint16_t discriminator,
143-
uint32_t setupPINCode, chip::NodeId nodeid);
144+
bool isShortDiscriminator, uint32_t setupPINCode, chip::NodeId nodeid);
144145
PyChipError pychip_DeviceController_ConnectIP(chip::Controller::DeviceCommissioner * devCtrl, const char * peerAddrStr,
145146
uint32_t setupPINCode, chip::NodeId nodeid);
146147
PyChipError pychip_DeviceController_ConnectWithCode(chip::Controller::DeviceCommissioner * devCtrl, const char * onboardingPayload,
@@ -377,13 +378,24 @@ const char * pychip_DeviceController_StatusReportToString(uint32_t profileId, ui
377378
}
378379

379380
PyChipError pychip_DeviceController_ConnectBLE(chip::Controller::DeviceCommissioner * devCtrl, uint16_t discriminator,
380-
uint32_t setupPINCode, chip::NodeId nodeid)
381+
bool isShortDiscriminator, uint32_t setupPINCode, chip::NodeId nodeid)
381382
{
383+
SetupDiscriminator setupDiscriminator;
384+
385+
if (isShortDiscriminator)
386+
{
387+
setupDiscriminator.SetShortValue(discriminator & 0xFu);
388+
}
389+
else
390+
{
391+
setupDiscriminator.SetLongValue(discriminator);
392+
}
393+
382394
return ToPyChipError(devCtrl->PairDevice(nodeid,
383395
chip::RendezvousParameters()
384396
.SetPeerAddress(Transport::PeerAddress(Transport::Type::kBle))
385397
.SetSetupPINCode(setupPINCode)
386-
.SetDiscriminator(discriminator),
398+
.SetSetupDiscriminator(setupDiscriminator),
387399
sCommissioningParameters));
388400
}
389401

src/controller/python/chip/ChipDeviceCtrl.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ def IsConnected(self):
533533
self.devCtrl)
534534
)
535535

536-
def ConnectBLE(self, discriminator, setupPinCode, nodeid) -> PyChipError:
536+
def ConnectBLE(self, discriminator: int, setupPinCode: int, nodeid: int, isShortDiscriminator: bool = False) -> PyChipError:
537537
self.CheckIsActive()
538538

539539
self._commissioning_complete_future = concurrent.futures.Future()
@@ -542,7 +542,7 @@ def ConnectBLE(self, discriminator, setupPinCode, nodeid) -> PyChipError:
542542
self._enablePairingCompeleteCallback(True)
543543
self._ChipStack.Call(
544544
lambda: self._dmLib.pychip_DeviceController_ConnectBLE(
545-
self.devCtrl, discriminator, setupPinCode, nodeid)
545+
self.devCtrl, discriminator, isShortDiscriminator, setupPinCode, nodeid)
546546
).raise_on_error()
547547

548548
# TODO: Change return None. Only returning on success is not useful.
@@ -1590,7 +1590,7 @@ def _InitLib(self):
15901590
self._dmLib.pychip_DeviceController_DeleteDeviceController.restype = PyChipError
15911591

15921592
self._dmLib.pychip_DeviceController_ConnectBLE.argtypes = [
1593-
c_void_p, c_uint16, c_uint32, c_uint64]
1593+
c_void_p, c_uint16, c_bool, c_uint32, c_uint64]
15941594
self._dmLib.pychip_DeviceController_ConnectBLE.restype = PyChipError
15951595

15961596
self._dmLib.pychip_DeviceController_SetThreadOperationalDataset.argtypes = [
@@ -1882,17 +1882,17 @@ def Commission(self, nodeid) -> PyChipError:
18821882
finally:
18831883
self._commissioning_complete_future = None
18841884

1885-
def CommissionThread(self, discriminator, setupPinCode, nodeId, threadOperationalDataset: bytes) -> PyChipError:
1885+
def CommissionThread(self, discriminator, setupPinCode, nodeId, threadOperationalDataset: bytes, isShortDiscriminator: bool = False) -> PyChipError:
18861886
''' Commissions a Thread device over BLE
18871887
'''
18881888
self.SetThreadOperationalDataset(threadOperationalDataset)
1889-
return self.ConnectBLE(discriminator, setupPinCode, nodeId)
1889+
return self.ConnectBLE(discriminator, setupPinCode, nodeId, isShortDiscriminator)
18901890

1891-
def CommissionWiFi(self, discriminator, setupPinCode, nodeId, ssid: str, credentials: str) -> PyChipError:
1891+
def CommissionWiFi(self, discriminator, setupPinCode, nodeId, ssid: str, credentials: str, isShortDiscriminator: bool = False) -> PyChipError:
18921892
''' Commissions a Wi-Fi device over BLE.
18931893
'''
18941894
self.SetWiFiCredentials(ssid, credentials)
1895-
return self.ConnectBLE(discriminator, setupPinCode, nodeId)
1895+
return self.ConnectBLE(discriminator, setupPinCode, nodeId, isShortDiscriminator)
18961896

18971897
def SetWiFiCredentials(self, ssid: str, credentials: str):
18981898
''' Set the Wi-Fi credentials to set during commissioning.'''

src/lib/support/SetupDiscriminator.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@
2323

2424
#pragma once
2525

26-
#include <lib/support/CodeUtils.h>
27-
2826
#include <cstdint>
2927

28+
#include <lib/support/CodeUtils.h>
29+
3030
namespace chip {
3131

3232
class SetupDiscriminator
3333
{
3434
public:
35-
constexpr SetupDiscriminator() : mDiscriminator(0), mIsShortDiscriminator(0) {}
35+
constexpr SetupDiscriminator() : mDiscriminator(0), mIsShortDiscriminator(false) {}
3636

3737
// See section 5.1.2. QR Code in the Matter specification
3838
static constexpr int kLongBits = 12;
@@ -104,8 +104,8 @@ class SetupDiscriminator
104104
// discriminator).
105105
static_assert(kLongBits == 12, "Unexpected field length");
106106
static_assert(kShortBits <= kLongBits, "Unexpected field length");
107-
uint16_t mDiscriminator : 12;
108-
uint16_t mIsShortDiscriminator : 1;
107+
uint16_t mDiscriminator;
108+
bool mIsShortDiscriminator;
109109
};
110110

111111
} // namespace chip

src/protocols/secure_channel/RendezvousParameters.h

+53-6
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717

1818
#pragma once
1919

20+
#include <optional>
21+
2022
#include <transport/raw/Base.h>
2123
#include <transport/raw/PeerAddress.h>
2224
#if CONFIG_NETWORK_LAYER_BLE
2325
#include <ble/Ble.h>
2426
#endif // CONFIG_NETWORK_LAYER_BLE
2527

2628
#include <crypto/CHIPCryptoPAL.h>
29+
#include <lib/support/SetupDiscriminator.h>
2730
#include <lib/support/logging/CHIPLogging.h>
2831
#include <messaging/ReliableMessageProtocolConfig.h>
2932
#include <protocols/secure_channel/PASESession.h>
@@ -59,11 +62,55 @@ class RendezvousParameters
5962

6063
// Discriminators in RendezvousParameters are always long (12-bit)
6164
// discriminators.
62-
bool HasDiscriminator() const { return mDiscriminator <= kMaxRendezvousDiscriminatorValue; }
63-
uint16_t GetDiscriminator() const { return mDiscriminator; }
65+
bool HasDiscriminator() const { return mSetupDiscriminator.has_value(); }
66+
67+
// Obtains the long version of the discriminator, or 0 if short.
68+
// WARNING: This is lossy and a bad idea to use. The correct method to use
69+
// is GetSetupDiscriminator(). This method exists for public
70+
// API backwards compatibility.
71+
uint16_t GetDiscriminator() const
72+
{
73+
if (!mSetupDiscriminator.has_value())
74+
{
75+
ChipLogError(Discovery,
76+
"Get RendezvousParameters::GetDiscriminator() called without discriminator in params (inconsistent). "
77+
"Using value 0 to avoid crash! Ensure discriminator is set!");
78+
return 0;
79+
}
80+
81+
if (mSetupDiscriminator.value().IsShortDiscriminator())
82+
{
83+
ChipLogError(Discovery,
84+
"Get RendezvousParameters::GetDiscriminator() called with SHORT discriminator (inconsistent). Using value "
85+
"0 to avoid crash! Call GetSetupDiscriminator() to avoid loss.");
86+
return 0;
87+
}
88+
89+
return mSetupDiscriminator.value().GetLongValue();
90+
}
91+
92+
std::optional<SetupDiscriminator> GetSetupDiscriminator() const
93+
{
94+
if (!mSetupDiscriminator.has_value())
95+
{
96+
ChipLogError(
97+
Discovery,
98+
"Get RendezvousParameters::GetSetupDiscriminator() called without discriminator in params (inconsistent).");
99+
}
100+
return mSetupDiscriminator;
101+
}
102+
103+
RendezvousParameters & SetSetupDiscriminator(SetupDiscriminator discriminator)
104+
{
105+
mSetupDiscriminator = discriminator;
106+
return *this;
107+
}
108+
64109
RendezvousParameters & SetDiscriminator(uint16_t discriminator)
65110
{
66-
mDiscriminator = discriminator;
111+
SetupDiscriminator tempDiscriminator;
112+
tempDiscriminator.SetLongValue(discriminator);
113+
mSetupDiscriminator = tempDiscriminator;
67114
return *this;
68115
}
69116

@@ -128,9 +175,9 @@ class RendezvousParameters
128175
}
129176

130177
private:
131-
Transport::PeerAddress mPeerAddress; ///< the peer node address
132-
uint32_t mSetupPINCode = 0; ///< the target peripheral setup PIN Code
133-
uint16_t mDiscriminator = UINT16_MAX; ///< the target peripheral discriminator
178+
Transport::PeerAddress mPeerAddress; ///< the peer node address
179+
uint32_t mSetupPINCode = 0; ///< the target peripheral setup PIN Code
180+
std::optional<SetupDiscriminator> mSetupDiscriminator;
134181

135182
Crypto::Spake2pVerifier mPASEVerifier;
136183
bool mHasPASEVerifier = false;

src/python_testing/matter_testing_support.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1554,14 +1554,16 @@ def _commission_device(self, i) -> bool:
15541554
info.passcode,
15551555
conf.dut_node_ids[i],
15561556
conf.wifi_ssid,
1557-
conf.wifi_passphrase
1557+
conf.wifi_passphrase,
1558+
isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR)
15581559
)
15591560
elif conf.commissioning_method == "ble-thread":
15601561
return dev_ctrl.CommissionThread(
15611562
info.filter_value,
15621563
info.passcode,
15631564
conf.dut_node_ids[i],
1564-
conf.thread_operational_dataset
1565+
conf.thread_operational_dataset,
1566+
isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR)
15651567
)
15661568
elif conf.commissioning_method == "on-network-ip":
15671569
logging.warning("==== USING A DIRECT IP COMMISSIONING METHOD NOT SUPPORTED IN THE LONG TERM ====")

src/setup_payload/SetupPayload.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ struct PayloadContents
126126
// payload parsed from a QR code would always have a value for
127127
// rendezvousInformation.
128128
Optional<RendezvousInformationFlags> rendezvousInformation;
129-
SetupDiscriminator discriminator;
129+
SetupDiscriminator discriminator{};
130130
uint32_t setUpPINCode = 0;
131131

132132
enum class ValidationMode : uint8_t

src/setup_payload/tests/TestManualCode.cpp

+15-11
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <stdio.h>
2727

2828
#include <lib/core/StringBuilderAdapters.h>
29+
#include <lib/support/logging/CHIPLogging.h>
2930
#include <lib/support/verhoeff/Verhoeff.h>
3031
#include <setup_payload/ManualSetupPayloadGenerator.h>
3132
#include <setup_payload/ManualSetupPayloadParser.h>
@@ -397,11 +398,14 @@ TEST(TestManualCode, TestLongCodeReadWrite)
397398
EXPECT_TRUE(inPayload == outPayload);
398399
}
399400

400-
void assertEmptyPayloadWithError(CHIP_ERROR actualError, CHIP_ERROR expectedError, const SetupPayload & payload)
401+
void assertEmptyPayloadWithError(CHIP_ERROR actualError, CHIP_ERROR expectedError, const SetupPayload & payload, int line)
401402
{
403+
ChipLogProgress(Test, "Current check line: %d", line);
402404
EXPECT_EQ(actualError, expectedError);
403-
EXPECT_TRUE(payload.setUpPINCode == 0 && payload.discriminator.GetLongValue() == 0 && payload.productID == 0 &&
404-
payload.vendorID == 0);
405+
EXPECT_EQ(payload.setUpPINCode, 0u);
406+
EXPECT_EQ(payload.discriminator.GetLongValue(), 0u);
407+
EXPECT_EQ(payload.productID, 0u);
408+
EXPECT_EQ(payload.vendorID, 0u);
405409
}
406410

407411
TEST(TestManualCode, TestPayloadParser_InvalidEntry)
@@ -413,46 +417,46 @@ TEST(TestManualCode, TestPayloadParser_InvalidEntry)
413417
decimalString = "";
414418
decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str());
415419
assertEmptyPayloadWithError(ManualSetupPayloadParser(decimalString).populatePayload(payload), CHIP_ERROR_INVALID_STRING_LENGTH,
416-
payload);
420+
payload, __LINE__);
417421

418422
// Invalid character
419423
decimalString = "24184.2196";
420424
decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str());
421425
assertEmptyPayloadWithError(ManualSetupPayloadParser(decimalString).populatePayload(payload), CHIP_ERROR_INVALID_INTEGER_VALUE,
422-
payload);
426+
payload, __LINE__);
423427

424428
// too short
425429
decimalString = "2456";
426430
decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str());
427431
assertEmptyPayloadWithError(ManualSetupPayloadParser(decimalString).populatePayload(payload), CHIP_ERROR_INVALID_STRING_LENGTH,
428-
payload);
432+
payload, __LINE__);
429433

430434
// too long for long code
431435
decimalString = "123456789123456785671";
432436
decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str());
433437
assertEmptyPayloadWithError(ManualSetupPayloadParser(decimalString).populatePayload(payload), CHIP_ERROR_INVALID_STRING_LENGTH,
434-
payload);
438+
payload, __LINE__);
435439

436440
// too long for short code
437441
decimalString = "12749875380";
438442
decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str());
439443
assertEmptyPayloadWithError(ManualSetupPayloadParser(decimalString).populatePayload(payload), CHIP_ERROR_INVALID_STRING_LENGTH,
440-
payload);
444+
payload, __LINE__);
441445

442446
// bit to indicate short code but long code length
443447
decimalString = "23456789123456785610";
444448
decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str());
445449
assertEmptyPayloadWithError(ManualSetupPayloadParser(decimalString).populatePayload(payload), CHIP_ERROR_INVALID_STRING_LENGTH,
446-
payload);
450+
payload, __LINE__);
447451
// no pin code (= 0)
448452
decimalString = "2327680000";
449453
decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str());
450454
assertEmptyPayloadWithError(ManualSetupPayloadParser(decimalString).populatePayload(payload), CHIP_ERROR_INVALID_ARGUMENT,
451-
payload);
455+
payload, __LINE__);
452456
// wrong check digit
453457
decimalString = "02684354589";
454458
assertEmptyPayloadWithError(ManualSetupPayloadParser(decimalString).populatePayload(payload), CHIP_ERROR_INTEGRITY_CHECK_FAILED,
455-
payload);
459+
payload, __LINE__);
456460
}
457461

458462
TEST(TestManualCode, TestCheckDecimalStringValidity)

0 commit comments

Comments
 (0)