Skip to content

Commit

Permalink
Add DeviceController::PairDevice(NodeId remoteId, const char * setupC…
Browse files Browse the repository at this point in the history
…ode) API that looks for the device over supported networks resolves #9343 (#9847)

* Add DeviceDiscoveryDelegate and use it in chip-tool

* [ChipTool] Add chip-tool commands to connect to a device using mdns, and possibly specifying subtypes

* Add SetUpCodePairer::PairDevice to handle scanning from a setup code
  • Loading branch information
vivien-apple authored Oct 4, 2021
1 parent 257d179 commit 02d8900
Show file tree
Hide file tree
Showing 16 changed files with 579 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,41 +23,34 @@ using namespace ::chip;

CHIP_ERROR DiscoverCommissionablesCommand::Run()
{
mCommissioner = GetExecContext()->commissioner;
GetExecContext()->commissioner->RegisterDeviceDiscoveryDelegate(this);

Mdns::DiscoveryFilter filter(Mdns::DiscoveryFilterType::kNone, (uint64_t) 0);
return mCommissioner->DiscoverCommissionableNodes(filter);
return GetExecContext()->commissioner->DiscoverCommissionableNodes(filter);
}

void DiscoverCommissionablesCommand::Shutdown()
void DiscoverCommissionablesCommand::OnDiscoveredDevice(const chip::Mdns::DiscoveredNodeData & nodeData)
{
for (int i = 0; i < mCommissioner->GetMaxCommissionableNodesSupported(); ++i)
{
const chip::Mdns::DiscoveredNodeData * dnsSdInfo = mCommissioner->GetDiscoveredDevice(i);
if (dnsSdInfo == nullptr)
{
continue;
}
char rotatingId[chip::Mdns::kMaxRotatingIdLen * 2 + 1] = "";
Encoding::BytesToUppercaseHexString(nodeData.rotatingId, nodeData.rotatingIdLen, rotatingId, sizeof(rotatingId));

char rotatingId[chip::Mdns::kMaxRotatingIdLen * 2 + 1] = "";
Encoding::BytesToUppercaseHexString(dnsSdInfo->rotatingId, dnsSdInfo->rotatingIdLen, rotatingId, sizeof(rotatingId));
ChipLogProgress(Discovery, "Discovered Node: ");
ChipLogProgress(Discovery, "\tHost name:\t\t%s", nodeData.hostName);
ChipLogProgress(Discovery, "\tPort:\t\t\t%u", nodeData.port);
ChipLogProgress(Discovery, "\tLong discriminator:\t%u", nodeData.longDiscriminator);
ChipLogProgress(Discovery, "\tVendor ID:\t\t%u", nodeData.vendorId);
ChipLogProgress(Discovery, "\tProduct ID:\t\t%u", nodeData.productId);
ChipLogProgress(Discovery, "\tCommissioning Mode\t%u", nodeData.commissioningMode);
ChipLogProgress(Discovery, "\tDevice Type\t\t%u", nodeData.deviceType);
ChipLogProgress(Discovery, "\tDevice Name\t\t%s", nodeData.deviceName);
ChipLogProgress(Discovery, "\tRotating Id\t\t%s", rotatingId);
ChipLogProgress(Discovery, "\tPairing Instruction\t%s", nodeData.pairingInstruction);
ChipLogProgress(Discovery, "\tPairing Hint\t\t0x%x", nodeData.pairingHint);
for (int i = 0; i < nodeData.numIPs; i++)
{
char buf[chip::Inet::kMaxIPAddressStringLength];
nodeData.ipAddress[i].ToString(buf);

ChipLogProgress(Discovery, "Commissionable Node %d", i);
ChipLogProgress(Discovery, "\tHost name:\t\t%s", dnsSdInfo->hostName);
ChipLogProgress(Discovery, "\tPort:\t\t\t%u", dnsSdInfo->port);
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, "\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);
}
ChipLogProgress(Discovery, "\tAddress %d:\t\t%s", i, buf);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@

#include "../common/Command.h"

class DiscoverCommissionablesCommand : public Command
class DiscoverCommissionablesCommand : public Command, public chip::Controller::DeviceDiscoveryDelegate
{
public:
DiscoverCommissionablesCommand() : Command("commissionables") {}
CHIP_ERROR Run() override;
uint16_t GetWaitDurationInSeconds() const override { return 3; }
void Shutdown() override;

private:
ChipDeviceCommissioner * mCommissioner;
/////////// DeviceDiscoveryDelegate Interface /////////
void OnDiscoveredDevice(const chip::Mdns::DiscoveredNodeData & nodeData) override;

/////////// Command Interface /////////
CHIP_ERROR Run() override;
uint16_t GetWaitDurationInSeconds() const override { return 30; }
};
93 changes: 88 additions & 5 deletions examples/chip-tool/commands/pairing/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,76 @@ class PairOnNetwork : public PairingCommand
PairOnNetwork() : PairingCommand("onnetwork", PairingMode::OnNetwork, PairingNetworkType::None) {}
};

class PairOnNetworkShort : public PairingCommand
{
public:
PairOnNetworkShort() :
PairingCommand("onnetwork-short", PairingMode::OnNetwork, PairingNetworkType::None, chip::Mdns::DiscoveryFilterType::kShort)
{}
};

class PairOnNetworkLong : public PairingCommand
{
public:
PairOnNetworkLong() :
PairingCommand("onnetwork-long", PairingMode::OnNetwork, PairingNetworkType::None, chip::Mdns::DiscoveryFilterType::kLong)
{}
};

class PairOnNetworkVendor : public PairingCommand
{
public:
PairOnNetworkVendor() :
PairingCommand("onnetwork-vendor", PairingMode::OnNetwork, PairingNetworkType::None,
chip::Mdns::DiscoveryFilterType::kVendor)
{}
};

class PairOnNetworkFabric : public PairingCommand
{
public:
PairOnNetworkFabric() :
PairingCommand("onnetwork-fabric", PairingMode::OnNetwork, PairingNetworkType::None,
chip::Mdns::DiscoveryFilterType::kCompressedFabricId)
{}
};

class PairOnNetworkCommissioningMode : public PairingCommand
{
public:
PairOnNetworkCommissioningMode() :
PairingCommand("onnetwork-commissioning-mode", PairingMode::OnNetwork, PairingNetworkType::None,
chip::Mdns::DiscoveryFilterType::kCommissioningMode)
{}
};

class PairOnNetworkCommissioner : public PairingCommand
{
public:
PairOnNetworkCommissioner() :
PairingCommand("onnetwork-commissioner", PairingMode::OnNetwork, PairingNetworkType::None,
chip::Mdns::DiscoveryFilterType::kCommissioner)
{}
};

class PairOnNetworkDeviceType : public PairingCommand
{
public:
PairOnNetworkDeviceType() :
PairingCommand("onnetwork-device-type", PairingMode::OnNetwork, PairingNetworkType::None,
chip::Mdns::DiscoveryFilterType::kDeviceType)
{}
};

class PairOnNetworkInstanceName : public PairingCommand
{
public:
PairOnNetworkInstanceName() :
PairingCommand("onnetwork-instance-name", PairingMode::OnNetwork, PairingNetworkType::None,
chip::Mdns::DiscoveryFilterType::kInstanceName)
{}
};

class PairBleWiFi : public PairingCommand
{
public:
Expand Down Expand Up @@ -87,11 +157,24 @@ void registerCommandsPairing(Commands & commands)
const char * clusterName = "Pairing";

commands_list clusterCommands = {
make_unique<Unpair>(), make_unique<PairBypass>(),
make_unique<PairQRCode>(), make_unique<PairManualCode>(),
make_unique<PairBleWiFi>(), make_unique<PairBleThread>(),
make_unique<PairSoftAP>(), make_unique<Ethernet>(),
make_unique<PairOnNetwork>(), make_unique<OpenCommissioningWindow>(),
make_unique<Unpair>(),
make_unique<PairBypass>(),
make_unique<PairQRCode>(),
make_unique<PairManualCode>(),
make_unique<PairBleWiFi>(),
make_unique<PairBleThread>(),
make_unique<PairSoftAP>(),
make_unique<Ethernet>(),
make_unique<PairOnNetwork>(),
make_unique<PairOnNetworkShort>(),
make_unique<PairOnNetworkLong>(),
make_unique<PairOnNetworkVendor>(),
make_unique<PairOnNetworkCommissioningMode>(),
make_unique<PairOnNetworkCommissioner>(),
make_unique<PairOnNetworkDeviceType>(),
make_unique<PairOnNetworkDeviceType>(),
make_unique<PairOnNetworkInstanceName>(),
make_unique<OpenCommissioningWindow>(),
};

commands.Register(clusterName, clusterCommands);
Expand Down
70 changes: 51 additions & 19 deletions examples/chip-tool/commands/pairing/PairingCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ CHIP_ERROR PairingCommand::RunInternal(NodeId remoteId)
err = Pair(remoteId, PeerAddress::BLE());
break;
case PairingMode::OnNetwork:
err = PairWithMdns(remoteId);
break;
case PairingMode::SoftAP:
err = Pair(remoteId, PeerAddress::UDP(mRemoteAddr.address, mRemotePort));
break;
Expand Down Expand Up @@ -129,38 +131,49 @@ void PairingCommand::OnDeviceConnectionFailureFn(void * context, NodeId deviceId

CHIP_ERROR PairingCommand::PairWithQRCode(NodeId remoteId)
{
SetupPayload payload;
ReturnErrorOnFailure(QRCodeSetupPayloadParser(mOnboardingPayload).populatePayload(payload));

chip::RendezvousInformationFlags rendezvousInformation = payload.rendezvousInformation;
ReturnErrorCodeIf(rendezvousInformation != RendezvousInformationFlag::kBLE, CHIP_ERROR_INVALID_ARGUMENT);

return PairWithCode(remoteId, payload);
return GetExecContext()->commissioner->PairDevice(remoteId, mOnboardingPayload);
}

CHIP_ERROR PairingCommand::PairWithManualCode(NodeId remoteId)
{
SetupPayload payload;
ReturnErrorOnFailure(ManualSetupPayloadParser(mOnboardingPayload).populatePayload(payload));
return PairWithCode(remoteId, payload);
return GetExecContext()->commissioner->PairDevice(remoteId, mOnboardingPayload);
}

CHIP_ERROR PairingCommand::PairWithCode(NodeId remoteId, SetupPayload payload)
CHIP_ERROR PairingCommand::Pair(NodeId remoteId, PeerAddress address)
{
RendezvousParameters params = RendezvousParameters()
.SetSetupPINCode(payload.setUpPINCode)
.SetDiscriminator(payload.discriminator)
.SetPeerAddress(PeerAddress::BLE());
RendezvousParameters params =
RendezvousParameters().SetSetupPINCode(mSetupPINCode).SetDiscriminator(mDiscriminator).SetPeerAddress(address);

return GetExecContext()->commissioner->PairDevice(remoteId, params);
}

CHIP_ERROR PairingCommand::Pair(NodeId remoteId, PeerAddress address)
CHIP_ERROR PairingCommand::PairWithMdns(NodeId remoteId)
{
RendezvousParameters params =
RendezvousParameters().SetSetupPINCode(mSetupPINCode).SetDiscriminator(mDiscriminator).SetPeerAddress(address);
Mdns::DiscoveryFilter filter(mFilterType);
switch (mFilterType)
{
case chip::Mdns::DiscoveryFilterType::kNone:
break;
case chip::Mdns::DiscoveryFilterType::kShort:
case chip::Mdns::DiscoveryFilterType::kLong:
case chip::Mdns::DiscoveryFilterType::kCompressedFabricId:
case chip::Mdns::DiscoveryFilterType::kVendor:
case chip::Mdns::DiscoveryFilterType::kDeviceType:
filter.code = mDiscoveryFilterCode;
break;
case chip::Mdns::DiscoveryFilterType::kCommissioningMode:
break;
case chip::Mdns::DiscoveryFilterType::kCommissioner:
filter.code = 1;
break;
case chip::Mdns::DiscoveryFilterType::kInstanceName:
filter.code = 0;
filter.instanceName = mDiscoveryFilterInstanceName;
break;
}

return GetExecContext()->commissioner->PairDevice(remoteId, params);
GetExecContext()->commissioner->RegisterDeviceDiscoveryDelegate(this);
return GetExecContext()->commissioner->DiscoverCommissionableNodes(filter);
}

CHIP_ERROR PairingCommand::PairWithoutSecurity(NodeId remoteId, PeerAddress address)
Expand Down Expand Up @@ -439,3 +452,22 @@ void PairingCommand::OnAddressUpdateComplete(NodeId nodeId, CHIP_ERROR err)
SetCommandExitStatus(err);
}
}

void PairingCommand::OnDiscoveredDevice(const chip::Mdns::DiscoveredNodeData & nodeData)
{
const uint16_t port = nodeData.port;
char buf[chip::Inet::kMaxIPAddressStringLength];
nodeData.ipAddress[0].ToString(buf);
ChipLogProgress(chipTool, "Discovered Device: %s:%u", buf, port);

// Stop Mdns discovery. Is it the right method ?
GetExecContext()->commissioner->RegisterDeviceDiscoveryDelegate(nullptr);

Inet::InterfaceId interfaceId = nodeData.ipAddress[0].IsIPv6LinkLocal() ? nodeData.interfaceId[0] : INET_NULL_INTERFACEID;
PeerAddress peerAddress = PeerAddress::UDP(nodeData.ipAddress[0], port, interfaceId);
CHIP_ERROR err = Pair(mRemoteId, peerAddress);
if (CHIP_NO_ERROR != err)
{
SetCommandExitStatus(err);
}
}
47 changes: 43 additions & 4 deletions examples/chip-tool/commands/pairing/PairingCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,15 @@ enum class PairingNetworkType

class PairingCommand : public Command,
public chip::Controller::DevicePairingDelegate,
public chip::Controller::DeviceAddressUpdateDelegate
public chip::Controller::DeviceAddressUpdateDelegate,
public chip::Controller::DeviceDiscoveryDelegate
{
public:
PairingCommand(const char * commandName, PairingMode mode, PairingNetworkType networkType) :
Command(commandName), mPairingMode(mode), mNetworkType(networkType), mRemoteAddr{ IPAddress::Any, INET_NULL_INTERFACEID },
PairingCommand(const char * commandName, PairingMode mode, PairingNetworkType networkType,
chip::Mdns::DiscoveryFilterType filterType = chip::Mdns::DiscoveryFilterType::kNone) :
Command(commandName),
mPairingMode(mode), mNetworkType(networkType),
mFilterType(filterType), mRemoteAddr{ IPAddress::Any, INET_NULL_INTERFACEID },
mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
{
switch (networkType)
Expand All @@ -82,7 +86,6 @@ class PairingCommand : public Command,
break;
case PairingMode::QRCode:
case PairingMode::ManualCode:
AddArgument("fabric-id", 0, UINT64_MAX, &mFabricId);
AddArgument("payload", &mOnboardingPayload);
break;
case PairingMode::Ble:
Expand All @@ -91,6 +94,8 @@ class PairingCommand : public Command,
AddArgument("discriminator", 0, 4096, &mDiscriminator);
break;
case PairingMode::OnNetwork:
AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode);
break;
case PairingMode::SoftAP:
AddArgument("fabric-id", 0, UINT64_MAX, &mFabricId);
AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode);
Expand All @@ -111,6 +116,33 @@ class PairingCommand : public Command,
AddArgument("discriminator", 0, 4096, &mDiscriminator);
break;
}

switch (filterType)
{
case chip::Mdns::DiscoveryFilterType::kNone:
break;
case chip::Mdns::DiscoveryFilterType::kShort:
AddArgument("discriminator", 0, 15, &mDiscoveryFilterCode);
break;
case chip::Mdns::DiscoveryFilterType::kLong:
AddArgument("discriminator", 0, 4096, &mDiscoveryFilterCode);
break;
case chip::Mdns::DiscoveryFilterType::kVendor:
AddArgument("vendor-id", 0, UINT16_MAX, &mDiscoveryFilterCode);
break;
case chip::Mdns::DiscoveryFilterType::kCompressedFabricId:
AddArgument("fabric-id", 0, UINT64_MAX, &mDiscoveryFilterCode);
break;
case chip::Mdns::DiscoveryFilterType::kCommissioningMode:
case chip::Mdns::DiscoveryFilterType::kCommissioner:
break;
case chip::Mdns::DiscoveryFilterType::kDeviceType:
AddArgument("device-type", 0, UINT16_MAX, &mDiscoveryFilterCode);
break;
case chip::Mdns::DiscoveryFilterType::kInstanceName:
AddArgument("name", &mDiscoveryFilterInstanceName);
break;
}
}

/////////// Command Interface /////////
Expand All @@ -124,6 +156,9 @@ class PairingCommand : public Command,
void OnPairingDeleted(CHIP_ERROR error) override;
void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error) override;

/////////// DeviceDiscoveryDelegate Interface /////////
void OnDiscoveredDevice(const chip::Mdns::DiscoveredNodeData & nodeData) override;

/////////// DeviceAddressUpdateDelegate Interface /////////
void OnAddressUpdateComplete(NodeId nodeId, CHIP_ERROR error) override;

Expand All @@ -135,6 +170,7 @@ class PairingCommand : public Command,
private:
CHIP_ERROR RunInternal(NodeId remoteId);
CHIP_ERROR Pair(NodeId remoteId, PeerAddress address);
CHIP_ERROR PairWithMdns(NodeId remoteId);
CHIP_ERROR PairWithQRCode(NodeId remoteId);
CHIP_ERROR PairWithManualCode(NodeId remoteId);
CHIP_ERROR PairWithCode(NodeId remoteId, chip::SetupPayload payload);
Expand All @@ -154,6 +190,7 @@ class PairingCommand : public Command,

const PairingMode mPairingMode;
const PairingNetworkType mNetworkType;
const chip::Mdns::DiscoveryFilterType mFilterType;
Command::AddressWithInterface mRemoteAddr;
NodeId mRemoteId;
uint16_t mRemotePort;
Expand All @@ -168,6 +205,8 @@ class PairingCommand : public Command,
chip::ByteSpan mSSID;
chip::ByteSpan mPassword;
char * mOnboardingPayload;
uint64_t mDiscoveryFilterCode;
char * mDiscoveryFilterInstanceName;

chip::Callback::Callback<NetworkCommissioningClusterAddThreadNetworkResponseCallback> * mOnAddThreadNetworkCallback = nullptr;
chip::Callback::Callback<NetworkCommissioningClusterAddWiFiNetworkResponseCallback> * mOnAddWiFiNetworkCallback = nullptr;
Expand Down
Loading

0 comments on commit 02d8900

Please sign in to comment.