Skip to content

Commit

Permalink
Linux tv-casting-app: simplified CastingPlayerDiscovery API
Browse files Browse the repository at this point in the history
  • Loading branch information
sharadb-amazon committed Sep 25, 2023
1 parent 041ba33 commit 365bfd1
Show file tree
Hide file tree
Showing 10 changed files with 499 additions and 11 deletions.
37 changes: 37 additions & 0 deletions examples/tv-casting-app/linux/simple-app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* limitations under the License.
*/

#include "core/CastingPlayer.h"
#include "core/CastingPlayerDiscovery.h"
#include "core/Types.h"

#include <LinuxCommissionableDataProvider.h>
Expand Down Expand Up @@ -76,6 +78,30 @@ CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & prov
options.payload.discriminator.GetLongValue());
}

class DiscoveryDelegateImpl : public DiscoveryDelegate
{
private:
int commissionersCount = 0;

public:
void HandleOnAdded(matter::casting::memory::Strong<CastingPlayer> player) override
{
if (commissionersCount == 0)
{
ChipLogProgress(AppServer, "Select discovered commissioner to request commissioning");

ChipLogProgress(AppServer, "Example: cast request 0");
}
++commissionersCount;
ChipLogProgress(AppServer, "Discovered Commissioners #%d", commissionersCount);
player->LogDetail();
}
void HandleOnUpdated(matter::casting::memory::Strong<CastingPlayer> player) override
{
ChipLogProgress(AppServer, "Updated commissioner with ID: %s", player->GetId());
}
};

/**
* @brief Provides the unique ID that is used by the SDK to generate the Rotating Device ID.
*/
Expand Down Expand Up @@ -148,6 +174,17 @@ int main(int argc, char * argv[])
VerifyOrReturnValue(err == CHIP_NO_ERROR, 0,
ChipLogError(AppServer, "CastingApp::Start failed %" CHIP_ERROR_FORMAT, err.Format()));

DiscoveryDelegateImpl delegate;
CastingPlayerDiscovery::GetInstance()->SetDelegate(&delegate);
VerifyOrReturnValue(err == CHIP_NO_ERROR, 0,
ChipLogError(AppServer, "CastingPlayerDiscovery::SetDelegate failed %" CHIP_ERROR_FORMAT, err.Format()));

// Discover CastingPlayers
const uint64_t kTargetPlayerDeviceType = 35; // 35 represents device type: Matter video players
err = CastingPlayerDiscovery::GetInstance()->StartDiscovery(kTargetPlayerDeviceType);
VerifyOrReturnValue(err == CHIP_NO_ERROR, 0,
ChipLogError(AppServer, "CastingPlayerDiscovery::StartDiscovery failed %" CHIP_ERROR_FORMAT, err.Format()));

chip::DeviceLayer::PlatformMgr().RunEventLoop();

return 0;
Expand Down
3 changes: 3 additions & 0 deletions examples/tv-casting-app/tv-casting-common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ chip_data_model("tv-casting-common") {
sources += [
"core/CastingApp.cpp",
"core/CastingApp.h",
"core/CastingPlayer.h",
"core/CastingPlayerDiscovery.cpp",
"core/CastingPlayerDiscovery.h",
"core/Types.h",
"support/AppParameters.h",
"support/DataProvider.h",
Expand Down
14 changes: 7 additions & 7 deletions examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ CastingApp * CastingApp::GetInstance()

CHIP_ERROR CastingApp::Initialize(const AppParameters & appParameters)
{
VerifyOrReturnError(mState == UNINITIALIZED, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mState == CASTING_APP_UNINITIALIZED, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(appParameters.GetCommissionableDataProvider() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(appParameters.GetDeviceAttestationCredentialsProvider() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(appParameters.GetServerInitParamsProvider() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
Expand Down Expand Up @@ -74,14 +74,14 @@ CHIP_ERROR CastingApp::Initialize(const AppParameters & appParameters)
}
#endif // CHIP_ENABLE_ROTATING_DEVICE_ID

mState = NOT_RUNNING; // initialization done, set state to NOT_RUNNING
mState = CASTING_APP_NOT_RUNNING; // initialization done, set state to NOT_RUNNING

return CHIP_NO_ERROR;
}

CHIP_ERROR CastingApp::Start()
{
VerifyOrReturnError(mState == NOT_RUNNING, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mState == CASTING_APP_NOT_RUNNING, CHIP_ERROR_INCORRECT_STATE);

// start Matter server
chip::ServerInitParams * serverInitParams = mAppParameters->GetServerInitParamsProvider()->Get();
Expand All @@ -96,7 +96,7 @@ CHIP_ERROR CastingApp::Start()

CHIP_ERROR CastingApp::PostStartRegistrations()
{
VerifyOrReturnError(mState == NOT_RUNNING, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mState == CASTING_APP_NOT_RUNNING, CHIP_ERROR_INCORRECT_STATE);
auto & server = chip::Server::GetInstance();

// TODO: Set CastingApp as AppDelegate
Expand All @@ -112,21 +112,21 @@ CHIP_ERROR CastingApp::PostStartRegistrations()
// TODO: Add DeviceEvent Handler
// ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(DeviceEventCallback, 0));

mState = RUNNING; // CastingApp started successfully, set state to RUNNING
mState = CASTING_APP_RUNNING; // CastingApp started successfully, set state to RUNNING
return CHIP_NO_ERROR;
}

CHIP_ERROR CastingApp::Stop()
{
VerifyOrReturnError(mState == RUNNING, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mState == CASTING_APP_RUNNING, CHIP_ERROR_INCORRECT_STATE);

// TODO: add logic to capture CastingPlayers that we are currently connected to, so we can automatically reconnect with them on
// Start() again

// Shutdown the Matter server
chip::Server::GetInstance().Shutdown();

mState = NOT_RUNNING; // CastingApp stopped successfully, set state to NOT_RUNNING
mState = CASTING_APP_NOT_RUNNING; // CastingApp stopped successfully, set state to NOT_RUNNING

return CHIP_ERROR_NOT_IMPLEMENTED;
}
Expand Down
8 changes: 4 additions & 4 deletions examples/tv-casting-app/tv-casting-common/core/CastingApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ namespace core {
*/
enum CastingAppState
{
UNINITIALIZED, // Before Initialize() success
NOT_RUNNING, // After Initialize() success before Start()ing, OR After stop() success
RUNNING, // After Start() success
CASTING_APP_UNINITIALIZED, // Before Initialize() success
CASTING_APP_NOT_RUNNING, // After Initialize() success before Start()ing, OR After stop() success
CASTING_APP_RUNNING, // After Start() success
};

/**
Expand Down Expand Up @@ -83,7 +83,7 @@ class CastingApp

const matter::casting::support::AppParameters * mAppParameters;

CastingAppState mState = UNINITIALIZED;
CastingAppState mState = CASTING_APP_UNINITIALIZED;
};

}; // namespace core
Expand Down
168 changes: 168 additions & 0 deletions examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include "Types.h"
#include "lib/support/logging/CHIPLogging.h"

#include <inet/IPAddress.h>
#include <inet/InetInterface.h>
#include <string.h>
#include <vector>

namespace matter {
namespace casting {
namespace core {

enum ConnectionError
{
NO_CONNECTION_ERROR = 0,
FAILED_TO_CONNECT = 1
};

using ConnectCallback = std::function<void(ConnectionError)>;
using DisconnectCallback = std::function<void(void)>;

const int kPortMaxLength = 5; // port is uint16_t
const int kIdMaxLength = chip::Dnssd::kHostNameMaxLength + kPortMaxLength;

class Attributes
{
public:
char id[kIdMaxLength] = {};
char deviceName[chip::Dnssd::kMaxDeviceNameLen + 1] = {};
char hostName[chip::Dnssd::kHostNameMaxLength + 1] = {};
char instanceName[chip::Dnssd::kHostNameMaxLength + 1] = {};
unsigned int numIPs; // number of valid IP addresses
chip::Inet::IPAddress ipAddresses[chip::Dnssd::CommonResolutionData::kMaxIPAddresses];
uint16_t port;
uint16_t productId;
uint16_t vendorId;
uint32_t deviceType;
};

/**
* @brief CastingPlayer represents a Matter commissioner that is able to play media to a physical
* output or to a display screen which is part of the device.
*/
class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
{
private:
// std::vector<memory::Strong<Endpoint>> endpoints;
bool mConnected = false;
Attributes mAttributes;

public:
CastingPlayer(Attributes playerAttributes) { mAttributes = playerAttributes; }
const char * GetId() const { return mAttributes.id; }

const char * GetDeviceName() const { return mAttributes.deviceName; }

const char * GetHostName() const { return mAttributes.hostName; }

const char * GetInstanceName() const { return mAttributes.instanceName; }

uint GetNumIPs() const { return mAttributes.numIPs; }

chip::Inet::IPAddress * GetIPAddresses() { return mAttributes.ipAddresses; }

uint16_t GetPort() { return mAttributes.port; }

uint16_t GetProductId() const { return mAttributes.productId; }

uint16_t GetVendorId() const { return mAttributes.vendorId; }

uint32_t GetDeviceType() const { return mAttributes.deviceType; }

// public:
// void RegisterEndpoint(const memory::Strong<Endpoint> endpoint) { endpoints.push_back(endpoint); }

// const std::vector<memory::Strong<Endpoint>> GetEndpoints() const { return endpoints; }

/**
* @brief Compares based on the Id
*/
bool operator==(const CastingPlayer & other) const
{
int compareResult = strcmp(this->mAttributes.id, other.mAttributes.id);
return (compareResult == 0) ? 1 : 0;
}

public:
/**
* @return true if this CastingPlayer is connected to the CastingApp
*/
bool IsConnected() const { return mConnected; }

void Connect(const long timeout, ConnectCallback onCompleted);
void Disconnect(const long timeout, DisconnectCallback onCompleted);

void LogDetail() const
{
if (strlen(mAttributes.id) != 0)
{
ChipLogDetail(Discovery, "\tID: %s", mAttributes.id);
}
if (strlen(mAttributes.deviceName) != 0)
{
ChipLogDetail(Discovery, "\tName: %s", mAttributes.deviceName);
}
if (strlen(mAttributes.hostName) != 0)
{
ChipLogDetail(Discovery, "\tHost Name: %s", mAttributes.hostName);
}
if (strlen(mAttributes.instanceName) != 0)
{
ChipLogDetail(Discovery, "\tInstance Name: %s", mAttributes.instanceName);
}
if (mAttributes.numIPs > 0)
{
ChipLogDetail(Discovery, "\tNumber of IPs: %u", mAttributes.numIPs);
}
char buf[chip::Inet::IPAddress::kMaxStringLength];
if (strlen(mAttributes.ipAddresses[0].ToString(buf)) != 0)
{
for (unsigned j = 0; j < mAttributes.numIPs; j++)
{
char * ipAddressOut = mAttributes.ipAddresses[j].ToString(buf);
ChipLogDetail(AppServer, "\tIP Address #%d: %s", j + 1, ipAddressOut);
}
}
if (mAttributes.port > 0)
{
ChipLogDetail(Discovery, "\tPort: %u", mAttributes.port);
}
if (mAttributes.productId > 0)
{
ChipLogDetail(Discovery, "\tProduct ID: %u", mAttributes.productId);
}
if (mAttributes.vendorId > 0)
{
ChipLogDetail(Discovery, "\tVendor ID: %u", mAttributes.vendorId);
}
if (mAttributes.deviceType > 0)
{
ChipLogDetail(Discovery, "\tDevice Type: %" PRIu32, mAttributes.deviceType);
}
}
};

}; // namespace core
}; // namespace casting
}; // namespace matter
Loading

0 comments on commit 365bfd1

Please sign in to comment.