Skip to content

Commit

Permalink
Send ContentLauncher.LaunchURL command from the tv-casting-app to tv-app
Browse files Browse the repository at this point in the history
Merged from master and resolved merge conflicts

Using InvokeCommand instead of the callback api to LaunchURL

Calling GetPeerIdForNode instead of GetPeerID
  • Loading branch information
sharadb-amazon committed Dec 15, 2021
1 parent 66fcad3 commit d461885
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 1 deletion.
78 changes: 77 additions & 1 deletion examples/tv-casting-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* limitations under the License.
*/

#include <app-common/zap-generated/cluster-objects.h>
#include <app/OperationalDeviceProxy.h>
#include <app/server/Dnssd.h>
#include <app/server/Server.h>
#include <controller/CHIPCommissionableNodeController.h>
Expand All @@ -27,15 +29,19 @@
#include <lib/support/SafeInt.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/ConfigurationManager.h>
#include <platform/internal/DeviceControlServer.h>
#include <system/SystemLayer.h>
#include <transport/raw/PeerAddress.h>
#include <zap-generated/CHIPClientCallbacks.h>
#include <zap-generated/CHIPClusters.h>

using namespace chip;
using namespace chip::Controller;
using namespace chip::Credentials;
using chip::ArgParser::HelpOptions;
using chip::ArgParser::OptionDef;
using chip::ArgParser::OptionSet;
using namespace chip::app::Clusters::ContentLauncher::Commands;

struct TVExampleDeviceType
{
Expand All @@ -49,10 +55,17 @@ constexpr uint16_t kOptionDeviceType = 't';
constexpr uint16_t kCommissioningWindowTimeoutInSec = 3 * 60;
constexpr uint32_t kCommissionerDiscoveryTimeoutInMs = 5 * 1000;

// TODO: Accept these values over CLI
const char * kContentUrl = "https://www.test.com/videoid";
const char * kContentDisplayStr = "Test video";
constexpr EndpointId kTvEndpoint = 1;

CommissionableNodeController gCommissionableNodeController;
chip::System::SocketWatchToken gToken;
Dnssd::DiscoveryFilter gDiscoveryFilter = Dnssd::DiscoveryFilter();

CASEClientPool<CHIP_CONFIG_DEVICE_MAX_ACTIVE_CASE_CLIENTS> gCASEClientPool;

bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue)
{
switch (aIdentifier)
Expand Down Expand Up @@ -185,6 +198,68 @@ void InitCommissioningFlow(intptr_t commandArg)
}
}

void OnContentLauncherSuccessResponse(void * context, const LaunchURLResponse::DecodableType & response)
{
ChipLogProgress(AppServer, "ContentLauncher: Default Success Response");
}

void OnContentLauncherFailureResponse(void * context, EmberAfStatus status)
{
ChipLogError(AppServer, "ContentLauncher: Default Failure Response: %" PRIu8, status);
}

void DeviceEventCallback(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
{
if (event->Type == DeviceLayer::DeviceEventType::kCommissioningComplete)
{
chip::NodeId tvNodeId = chip::DeviceLayer::Internal::DeviceControlServer::DeviceControlSvr().GetPeerNodeId();
chip::FabricIndex peerFabricIndex = chip::DeviceLayer::Internal::DeviceControlServer::DeviceControlSvr().GetFabricIndex();

Server * server = &(chip::Server::GetInstance());
chip::FabricInfo * fabric = server->GetFabricTable().FindFabricWithIndex(peerFabricIndex);
if (fabric == nullptr)
{
ChipLogError(AppServer, "Did not find fabric for index %d", peerFabricIndex);
return;
}

chip::DeviceProxyInitParams initParams = {
.sessionManager = &(server->GetSecureSessionManager()),
.exchangeMgr = &(server->GetExchangeManager()),
.idAllocator = &(server->GetSessionIDAllocator()),
.fabricTable = &(server->GetFabricTable()),
.clientPool = &gCASEClientPool,
.imDelegate = chip::Platform::New<chip::Controller::DeviceControllerInteractionModelDelegate>(),
};

PeerId peerID = fabric->GetPeerIdForNode(tvNodeId);
chip::OperationalDeviceProxy * operationalDeviceProxy =
chip::Platform::New<chip::OperationalDeviceProxy>(initParams, peerID);
if (operationalDeviceProxy == nullptr)
{
ChipLogError(AppServer, "Failed in creating an instance of OperationalDeviceProxy");
return;
}

SessionHandle handle = server->GetSecureSessionManager().FindSecureSessionForNode(tvNodeId);
operationalDeviceProxy->SetConnectedSession(handle);

ContentLauncherCluster cluster;
CHIP_ERROR err = cluster.Associate(operationalDeviceProxy, kTvEndpoint);
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "Associate() failed: %" CHIP_ERROR_FORMAT, err.Format());
return;
}
LaunchURL::Type request;
request.contentURL = chip::CharSpan(kContentUrl, strlen(kContentUrl));
request.displayString = chip::CharSpan(kContentDisplayStr, strlen(kContentDisplayStr));
request.brandingInformation = chip::app::DataModel::List<
const chip::app::Clusters::ContentLauncher::Structs::ContentLaunchBrandingInformation::Type>();
cluster.InvokeCommand(request, nullptr, OnContentLauncherSuccessResponse, OnContentLauncherFailureResponse);
}
}

int main(int argc, char * argv[])
{
CHIP_ERROR err = CHIP_NO_ERROR;
Expand Down Expand Up @@ -215,7 +290,8 @@ int main(int argc, char * argv[])
chip::System::Clock::Milliseconds32(kCommissionerDiscoveryTimeoutInMs),
[](System::Layer *, void *) { chip::DeviceLayer::PlatformMgr().ScheduleWork(InitCommissioningFlow); }, nullptr);

// TBD: Content casting commands
// Add callback to send Content casting commands after commissioning completes
chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(DeviceEventCallback, 0);

DeviceLayer::PlatformMgr().RunEventLoop();
exit:
Expand Down
6 changes: 6 additions & 0 deletions src/app/OperationalDeviceProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,12 @@ CHIP_ERROR OperationalDeviceProxy::Disconnect()
return CHIP_NO_ERROR;
}

void OperationalDeviceProxy::SetConnectedSession(SessionHandle handle)
{
mSecureSession.Grab(handle);
mState = State::SecureConnected;
}

void OperationalDeviceProxy::Clear()
{
if (mCASEClient)
Expand Down
6 changes: 6 additions & 0 deletions src/app/OperationalDeviceProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ class DLL_EXPORT OperationalDeviceProxy : public DeviceProxy, SessionReleaseDele
*/
CHIP_ERROR Disconnect() override;

/**
* Grab the SessionHolder and set state of this OperationalDeviceProxy
* to SecureConnected
*/
void SetConnectedSession(SessionHandle handle);

NodeId GetDeviceId() const override { return mPeerId.GetNodeId(); }

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,19 @@ bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler *
return true;
}

/**
* Pass fabric and nodeId of commissioner to DeviceControlSvr.
* This allows device to send messages back to commissioner.
* Once bindings are implemented, this may no longer be needed.
*/
bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback(
app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
const Commands::CommissioningComplete::DecodableType & commandData)
{
SessionHandle handle = commandObj->GetExchangeContext()->GetSessionHandle();
DeviceLayer::Internal::DeviceControlServer::DeviceControlSvr().SetFabricIndex(handle.GetFabricIndex());
DeviceLayer::Internal::DeviceControlServer::DeviceControlSvr().SetPeerNodeId(handle.GetPeerNodeId());

CHIP_ERROR err = DeviceLayer::Internal::DeviceControlServer::DeviceControlSvr().CommissioningComplete();
emberAfSendImmediateDefaultResponse(err == CHIP_NO_ERROR ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE);

Expand Down
8 changes: 8 additions & 0 deletions src/include/platform/internal/DeviceControlServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ class DeviceControlServer final

CHIP_ERROR ConnectNetworkForOperational(ByteSpan networkID);

inline FabricIndex GetFabricIndex() { return mFabric; }
inline void SetFabricIndex(FabricIndex fabricId) { mFabric = fabricId; }
inline NodeId GetPeerNodeId() { return mPeerNodeId; }
inline void SetPeerNodeId(NodeId peerNodeId) { mPeerNodeId = peerNodeId; }

static DeviceControlServer & DeviceControlSvr();

private:
Expand All @@ -58,6 +63,9 @@ class DeviceControlServer final
DeviceControlServer(const DeviceControlServer &) = delete;
DeviceControlServer(const DeviceControlServer &&) = delete;
DeviceControlServer & operator=(const DeviceControlServer &) = delete;

NodeId mPeerNodeId = 0;
FabricIndex mFabric = 0;
};

} // namespace Internal
Expand Down
1 change: 1 addition & 0 deletions src/transport/SessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ class DLL_EXPORT SessionManager : public TransportMgrDelegate
}

// TODO: this is a temporary solution for legacy tests which use nodeId to send packets
// and tv-casting-app that uses the TV's node ID to find the associated secure session
SessionHandle FindSecureSessionForNode(NodeId peerNodeId);

private:
Expand Down

0 comments on commit d461885

Please sign in to comment.