Skip to content

Commit

Permalink
Send ContentLauncher commands from tv-casting-app to tv-app (#12913)
Browse files Browse the repository at this point in the history
* Switched to client for Media cluster

* Send ContentLauncher.LaunchURL command from the tv-casting-app to tv-app

Merged from master and resolved merge conflicts

Using InvokeCommand instead of the callback api to LaunchURL

Calling GetPeerIdForNode instead of GetPeerID

* Added usage/deprecation comment for OperationalDeviceProxy.SetConnectedSession
  • Loading branch information
sharadb-amazon authored and pull[bot] committed Jul 11, 2023
1 parent 4066d50 commit 1130941
Show file tree
Hide file tree
Showing 16 changed files with 3,397 additions and 397 deletions.
76 changes: 75 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,7 @@
* limitations under the License.
*/

#include <app/OperationalDeviceProxy.h>
#include <app/server/Dnssd.h>
#include <app/server/Server.h>
#include <controller/CHIPCommissionableNodeController.h>
Expand All @@ -27,8 +28,10 @@
#include <lib/support/SafeInt.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/ConfigurationManager.h>
#include <platform/DeviceControlServer.h>
#include <system/SystemLayer.h>
#include <transport/raw/PeerAddress.h>
#include <zap-generated/CHIPClusters.h>

#include <list>
#include <string>
Expand All @@ -39,6 +42,7 @@ 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 @@ -52,10 +56,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 @@ -188,6 +199,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::DeviceControlServer::DeviceControlSvr().GetPeerNodeId();
chip::FabricIndex peerFabricIndex = chip::DeviceLayer::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 @@ -218,7 +291,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
1 change: 1 addition & 0 deletions examples/tv-casting-app/tv-casting-common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ chip_data_model("tv-casting-common") {
zap_pregenerated_dir =
"${chip_root}/zzz_generated/tv-casting-app/zap-generated"
is_server = true
use_default_client_callbacks = true
}
43 changes: 22 additions & 21 deletions examples/tv-casting-app/tv-casting-common/tv-casting-app.zap
Original file line number Diff line number Diff line change
Expand Up @@ -11854,7 +11854,7 @@
"mfgCode": null,
"define": "CHANNEL_CLUSTER",
"side": "client",
"enabled": 0,
"enabled": 1,
"commands": [
{
"name": "ChangeChannel",
Expand Down Expand Up @@ -11905,7 +11905,7 @@
"mfgCode": null,
"define": "CHANNEL_CLUSTER",
"side": "server",
"enabled": 1,
"enabled": 0,
"commands": [
{
"name": "ChangeChannelResponse",
Expand Down Expand Up @@ -11985,7 +11985,7 @@
"mfgCode": null,
"define": "TARGET_NAVIGATOR_CLUSTER",
"side": "client",
"enabled": 0,
"enabled": 1,
"commands": [
{
"name": "NavigateTarget",
Expand Down Expand Up @@ -12020,7 +12020,7 @@
"mfgCode": null,
"define": "TARGET_NAVIGATOR_CLUSTER",
"side": "server",
"enabled": 1,
"enabled": 0,
"commands": [
{
"name": "NavigateTargetResponse",
Expand Down Expand Up @@ -12070,7 +12070,7 @@
"mfgCode": null,
"define": "MEDIA_PLAYBACK_CLUSTER",
"side": "client",
"enabled": 0,
"enabled": 1,
"commands": [
{
"name": "MediaPlay",
Expand Down Expand Up @@ -12185,7 +12185,7 @@
"mfgCode": null,
"define": "MEDIA_PLAYBACK_CLUSTER",
"side": "server",
"enabled": 1,
"enabled": 0,
"commands": [
{
"name": "MediaPlayResponse",
Expand Down Expand Up @@ -12292,7 +12292,7 @@
"mfgCode": null,
"define": "MEDIA_INPUT_CLUSTER",
"side": "client",
"enabled": 0,
"enabled": 1,
"commands": [
{
"name": "SelectInput",
Expand Down Expand Up @@ -12351,7 +12351,7 @@
"mfgCode": null,
"define": "MEDIA_INPUT_CLUSTER",
"side": "server",
"enabled": 1,
"enabled": 0,
"commands": [],
"attributes": [
{
Expand Down Expand Up @@ -12392,7 +12392,7 @@
"mfgCode": null,
"define": "KEYPAD_INPUT_CLUSTER",
"side": "client",
"enabled": 0,
"enabled": 1,
"commands": [
{
"name": "SendKey",
Expand Down Expand Up @@ -12427,7 +12427,7 @@
"mfgCode": null,
"define": "KEYPAD_INPUT_CLUSTER",
"side": "server",
"enabled": 1,
"enabled": 0,
"commands": [
{
"name": "SendKeyResponse",
Expand Down Expand Up @@ -12462,7 +12462,7 @@
"mfgCode": null,
"define": "CONTENT_LAUNCH_CLUSTER",
"side": "client",
"enabled": 0,
"enabled": 1,
"commands": [
{
"name": "LaunchContent",
Expand Down Expand Up @@ -12505,7 +12505,7 @@
"mfgCode": null,
"define": "CONTENT_LAUNCH_CLUSTER",
"side": "server",
"enabled": 1,
"enabled": 0,
"commands": [
{
"name": "LaunchContentResponse",
Expand Down Expand Up @@ -12578,7 +12578,7 @@
"mfgCode": null,
"define": "AUDIO_OUTPUT_CLUSTER",
"side": "client",
"enabled": 0,
"enabled": 1,
"commands": [
{
"name": "SelectOutput",
Expand Down Expand Up @@ -12621,7 +12621,7 @@
"mfgCode": null,
"define": "AUDIO_OUTPUT_CLUSTER",
"side": "server",
"enabled": 1,
"enabled": 0,
"commands": [],
"attributes": [
{
Expand Down Expand Up @@ -12662,7 +12662,7 @@
"mfgCode": null,
"define": "APPLICATION_LAUNCHER_CLUSTER",
"side": "client",
"enabled": 0,
"enabled": 1,
"commands": [
{
"name": "LaunchApp",
Expand Down Expand Up @@ -12697,7 +12697,7 @@
"mfgCode": null,
"define": "APPLICATION_LAUNCHER_CLUSTER",
"side": "server",
"enabled": 1,
"enabled": 0,
"commands": [
{
"name": "LaunchAppResponse",
Expand Down Expand Up @@ -12747,7 +12747,7 @@
"mfgCode": null,
"define": "APPLICATION_BASIC_CLUSTER",
"side": "client",
"enabled": 0,
"enabled": 1,
"commands": [],
"attributes": [
{
Expand All @@ -12773,7 +12773,7 @@
"mfgCode": null,
"define": "APPLICATION_BASIC_CLUSTER",
"side": "server",
"enabled": 1,
"enabled": 0,
"commands": [],
"attributes": [
{
Expand Down Expand Up @@ -12889,7 +12889,7 @@
"mfgCode": null,
"define": "ACCOUNT_LOGIN_CLUSTER",
"side": "client",
"enabled": 0,
"enabled": 1,
"commands": [
{
"name": "GetSetupPIN",
Expand Down Expand Up @@ -12932,7 +12932,7 @@
"mfgCode": null,
"define": "ACCOUNT_LOGIN_CLUSTER",
"side": "server",
"enabled": 1,
"enabled": 0,
"commands": [
{
"name": "GetSetupPINResponse",
Expand Down Expand Up @@ -16286,5 +16286,6 @@
"endpointVersion": 1,
"deviceIdentifier": 22
}
]
],
"log": []
}
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
9 changes: 9 additions & 0 deletions src/app/OperationalDeviceProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,15 @@ class DLL_EXPORT OperationalDeviceProxy : public DeviceProxy, SessionReleaseDele
*/
CHIP_ERROR Disconnect() override;

/**
* Use SetConnectedSession if 'this' object is a newly allocated device proxy.
* It will take an existing session, such as the one established
* during commissioning, and use it for this device proxy.
*
* Note: Avoid using this function generally as it is Deprecated
*/
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::DeviceControlServer::DeviceControlSvr().SetFabricIndex(handle.GetFabricIndex());
DeviceLayer::DeviceControlServer::DeviceControlSvr().SetPeerNodeId(handle.GetPeerNodeId());

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

Expand Down
7 changes: 7 additions & 0 deletions src/include/platform/DeviceControlServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ 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; }
void SetSwitchDelegate(SwitchDeviceControlDelegate * delegate) { mSwitchDelegate = delegate; }
SwitchDeviceControlDelegate * GetSwitchDelegate() const { return mSwitchDelegate; }

Expand All @@ -116,6 +120,9 @@ class DeviceControlServer final
DeviceControlServer(const DeviceControlServer &) = delete;
DeviceControlServer(const DeviceControlServer &&) = delete;
DeviceControlServer & operator=(const DeviceControlServer &) = delete;

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

} // namespace DeviceLayer
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
Loading

0 comments on commit 1130941

Please sign in to comment.