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
99 changes: 77 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,70 @@
#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;
constexpr int kVideoPlayerDeviceType = 35;
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(Mdns::DiscoveryFilterType::kDeviceType, kVideoPlayerDeviceType);
sharadb-amazon marked this conversation as resolved.
Show resolved Hide resolved

bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue)
{
switch (aIdentifier)
{
case kOptionDeviceType:
if (strcasecmp(aValue, "all") == 0)
{
gDiscoveryFilter = Mdns::DiscoveryFilter();
return true;
}
else
{
long deviceType = strtol(aValue, nullptr, 10);
if (CanCastTo<uint16_t>(deviceType))
{
gDiscoveryFilter = Mdns::DiscoveryFilter(Mdns::DiscoveryFilterType::kDeviceType, static_cast<uint16_t>(deviceType));
return true;
}
}
return false;
default:
ChipLogError(AppServer, "%s: INTERNAL ERROR: Unhandled option: %s\n", 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 "
"'all' to allow all commissioner device types or the device type as a decimal integer. Defaults to 35 (Video Player)\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 @@ -43,7 +93,7 @@ void PrepareForCommissioning(const Mdns::DiscoveredNodeData * selectedCommission
{
// Enter commissioning mode, open commissioning window
InitServer();
ReturnOnFailure(OpenBasicCommissioningWindow(ResetFabrics::kYes, commissioningWindowTimeoutInSec));
ReturnOnFailure(OpenBasicCommissioningWindow(ResetFabrics::kYes, kCommissioningWindowTimeoutInSec));

// Display onboarding payload
chip::DeviceLayer::ConfigurationMgr().LogDeviceConfig();
Expand Down Expand Up @@ -73,11 +123,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 @@ -88,48 +138,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 @@ -138,7 +193,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