Skip to content

Commit

Permalink
Adding cmd line args to tv-casting-app for device type of commissione…
Browse files Browse the repository at this point in the history
…rs to be discovered (#9572)

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

* Addressing comments from andy31415, bzbarsky-apple

* Switching logging module to AppServer

* Switching to lib/support/SafeInt.h for Cirque build

* Fixing compiler errors

* Accepting both text and numeric representations of cmd line arg for device type, defaulting to 'all'

* Fixing merge error/typo
  • Loading branch information
sharadb-amazon authored Sep 14, 2021
1 parent e71f2d7 commit cfacfda
Showing 1 changed file with 88 additions and 22 deletions.
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

0 comments on commit cfacfda

Please sign in to comment.