Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding cmd line args to tv-casting-app for device type of commissioners to be discovered #9572

Merged
merged 9 commits into from
Sep 14, 2021
110 changes: 88 additions & 22 deletions examples/tv-casting-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,81 @@
#include <app/server/Mdns.h>
#include <app/server/Server.h>
#include <controller/CHIPCommissionableNodeController.h>
#include <lib/support/CHIPArgParser.hpp>
#include <lib/support/SafeInt.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/ConfigurationManager.h>
#include <system/SystemLayer.h>
#include <transport/raw/PeerAddress.h>

using namespace chip;
using namespace chip::Controller;
using chip::ArgParser::HelpOptions;
using chip::ArgParser::OptionDef;
using chip::ArgParser::OptionSet;

constexpr int kTvDeviceType = 35;
constexpr uint16_t commissioningWindowTimeoutInSec = 3 * 60;
constexpr uint32_t commissionerDiscoveryTimeoutInMs = 5 * 1000;
struct DeviceType
{
const char * name;
uint16_t id;
};

constexpr DeviceType kKnownDeviceTypes[] = { { "video-player", 35 }, { "dimmable-light", 257 } };
constexpr int kKnownDeviceTypesCount = sizeof kKnownDeviceTypes / sizeof *kKnownDeviceTypes;
constexpr uint16_t kOptionDeviceType = 't';
constexpr uint16_t kCommissioningWindowTimeoutInSec = 3 * 60;
constexpr uint32_t kCommissionerDiscoveryTimeoutInMs = 5 * 1000;

CommissionableNodeController commissionableNodeController;
chip::System::SocketWatchToken token;
CommissionableNodeController gCommissionableNodeController;
chip::System::SocketWatchToken gToken;
Mdns::DiscoveryFilter gDiscoveryFilter = Mdns::DiscoveryFilter();

bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue)
{
switch (aIdentifier)
{
case kOptionDeviceType: {
char * endPtr;
long deviceType = strtol(aValue, &endPtr, 10);
if (*endPtr == '\0' && deviceType > 0 && CanCastTo<uint16_t>(deviceType))
{
gDiscoveryFilter = Mdns::DiscoveryFilter(Mdns::DiscoveryFilterType::kDeviceType, static_cast<uint16_t>(deviceType));
return true;
}
else
{
for (int i = 0; i < kKnownDeviceTypesCount; i++)
{
if (strcasecmp(aValue, kKnownDeviceTypes[i].name) == 0)
{
gDiscoveryFilter = Mdns::DiscoveryFilter(Mdns::DiscoveryFilterType::kDeviceType, kKnownDeviceTypes[i].id);
return true;
}
}
}
ChipLogError(AppServer, "%s: INTERNAL ERROR: Unhandled option value: %s %s", aProgram, aName, aValue);
return false;
}
default:
ChipLogError(AppServer, "%s: INTERNAL ERROR: Unhandled option: %s", aProgram, aName);
return false;
}
}

OptionDef cmdLineOptionsDef[] = {
{ "device-type", chip::ArgParser::kArgumentRequired, kOptionDeviceType },
{},
};

OptionSet cmdLineOptions = { HandleOptions, cmdLineOptionsDef, "PROGRAM OPTIONS",
" -t <commissioner device type>\n"
" --device-type <commissioner device type>\n"
" Device type of the commissioner to discover and request commissioning from. Specify value as "
"a decimal integer or a known text representation. Defaults to all device types\n" };

HelpOptions helpOptions("tv-casting-app", "Usage: tv-casting-app [options]", "1.0");

OptionSet * allOptions[] = { &cmdLineOptions, &helpOptions, nullptr };

/**
* Enters commissioning mode, opens commissioning window, logs onboarding payload.
Expand All @@ -44,7 +105,7 @@ void PrepareForCommissioning(const Mdns::DiscoveredNodeData * selectedCommission
// Enter commissioning mode, open commissioning window
Server::GetInstance().Init();
ReturnOnFailure(Server::GetInstance().GetCommissionManager().OpenBasicCommissioningWindow(ResetFabrics::kYes,
commissioningWindowTimeoutInSec));
kCommissioningWindowTimeoutInSec));

// Display onboarding payload
chip::DeviceLayer::ConfigurationMgr().LogDeviceConfig();
Expand Down Expand Up @@ -74,11 +135,11 @@ void RequestUserDirectedCommissioning(System::SocketEvents events, intptr_t data
int selectedCommissionerNumber = CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES;
scanf("%d", &selectedCommissionerNumber);
printf("%d\n", selectedCommissionerNumber);
chip::DeviceLayer::SystemLayerSockets().StopWatchingSocket(&token);
chip::DeviceLayer::SystemLayerSockets().StopWatchingSocket(&gToken);

const Mdns::DiscoveredNodeData * selectedCommissioner =
commissionableNodeController.GetDiscoveredCommissioner(selectedCommissionerNumber - 1);
VerifyOrReturn(selectedCommissioner != nullptr, ChipLogError(Zcl, "No such commissioner!"));
gCommissionableNodeController.GetDiscoveredCommissioner(selectedCommissionerNumber - 1);
VerifyOrReturn(selectedCommissioner != nullptr, ChipLogError(AppServer, "No such commissioner!"));
PrepareForCommissioning(selectedCommissioner);
}

Expand All @@ -89,48 +150,53 @@ void InitCommissioningFlow(intptr_t commandArg)
// Display discovered commissioner TVs to ask user to select one
for (int i = 0; i < CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES; i++)
{
const Mdns::DiscoveredNodeData * commissioner = commissionableNodeController.GetDiscoveredCommissioner(i);
const Mdns::DiscoveredNodeData * commissioner = gCommissionableNodeController.GetDiscoveredCommissioner(i);
if (commissioner != nullptr)
{
ChipLogProgress(Zcl, "Discovered Commissioner #%d", ++commissionerCount);
ChipLogProgress(AppServer, "Discovered Commissioner #%d", ++commissionerCount);
commissioner->LogDetail();
}
}

if (commissionerCount > 0)
{
ChipLogProgress(
Zcl, "%d commissioner(s) discovered. Select one (by number# above) to request commissioning from: ", commissionerCount);
ChipLogProgress(AppServer, "%d commissioner(s) discovered. Select one (by number# above) to request commissioning from: ",
commissionerCount);

// Setup for async/non-blocking user input from stdin
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
VerifyOrReturn(fcntl(0, F_SETFL, flags | O_NONBLOCK) == 0,
ChipLogError(Zcl, "Could not set non-blocking mode for user input!"));
ReturnOnFailure(chip::DeviceLayer::SystemLayerSockets().StartWatchingSocket(STDIN_FILENO, &token));
ChipLogError(AppServer, "Could not set non-blocking mode for user input!"));
ReturnOnFailure(chip::DeviceLayer::SystemLayerSockets().StartWatchingSocket(STDIN_FILENO, &gToken));
ReturnOnFailure(
chip::DeviceLayer::SystemLayerSockets().SetCallback(token, RequestUserDirectedCommissioning, (intptr_t) NULL));
ReturnOnFailure(chip::DeviceLayer::SystemLayerSockets().RequestCallbackOnPendingRead(token));
chip::DeviceLayer::SystemLayerSockets().SetCallback(gToken, RequestUserDirectedCommissioning, (intptr_t) NULL));
ReturnOnFailure(chip::DeviceLayer::SystemLayerSockets().RequestCallbackOnPendingRead(gToken));
}
else
{
ChipLogError(Zcl, "No commissioner discovered, commissioning must be initiated manually!");
ChipLogError(AppServer, "No commissioner discovered, commissioning must be initiated manually!");
PrepareForCommissioning();
}
}

int main(int argc, char * argv[])
{
CHIP_ERROR err = CHIP_NO_ERROR;

SuccessOrExit(err = chip::Platform::MemoryInit());
SuccessOrExit(err = chip::DeviceLayer::PlatformMgr().InitChipStack());

if (!chip::ArgParser::ParseArgs(argv[0], argc, argv, allOptions))
{
return 1;
}

// Send discover commissioners request
SuccessOrExit(err = commissionableNodeController.DiscoverCommissioners(
Mdns::DiscoveryFilter(Mdns::DiscoveryFilterType::kDeviceType, kTvDeviceType)));
SuccessOrExit(err = gCommissionableNodeController.DiscoverCommissioners(gDiscoveryFilter));

// Give commissioners some time to respond and then ScheduleWork to initiate commissioning
DeviceLayer::SystemLayer().StartTimer(
commissionerDiscoveryTimeoutInMs,
kCommissionerDiscoveryTimeoutInMs,
[](System::Layer *, void *) { chip::DeviceLayer::PlatformMgr().ScheduleWork(InitCommissioningFlow); }, nullptr);

// TBD: Content casting commands
Expand All @@ -139,7 +205,7 @@ int main(int argc, char * argv[])
exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "Failed to run TV Casting App: %s", ErrorStr(err));
ChipLogError(AppServer, "Failed to run TV Casting App: %s", ErrorStr(err));
// End the program with non zero error code to indicate an error.
return 1;
}
Expand Down