Skip to content

Commit

Permalink
Commissioning flow
Browse files Browse the repository at this point in the history
  • Loading branch information
sharadb-amazon committed Oct 11, 2023
1 parent 13712ef commit 3e6789e
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 45 deletions.
2 changes: 1 addition & 1 deletion examples/tv-casting-app/linux/simple-app-helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ static CHIP_ERROR CommandHandler(int argc, char ** argv)
VerifyOrReturnValue(0 <= index && index < castingPlayers.size(), CHIP_ERROR_INVALID_ARGUMENT,
ChipLogError(AppServer, "Invalid casting player index provided: %lu", index));
std::shared_ptr<matter::casting::core::CastingPlayer> targetCastingPlayer = castingPlayers.at(index);
targetCastingPlayer->Connect(ConnectionHandler);
targetCastingPlayer->VerifyOrEstablishConnection(ConnectionHandler);
return CHIP_NO_ERROR;
}
if (strcmp(argv[0], "print-bindings") == 0)
Expand Down
90 changes: 84 additions & 6 deletions examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,25 @@ namespace core {

CastingPlayer * CastingPlayer::mTargetCastingPlayer = nullptr;

void CastingPlayer::Connect(ConnectCallback onCompleted, const chip::System::Clock::Seconds16 commissioningWindowTimeout)
void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted,
const chip::System::Clock::Seconds16 commissioningWindowTimeout)
{
chip::Inet::IPAddress * ipAddressToUse = GetIpAddressForUDCRequest();
CHIP_ERROR err = ipAddressToUse != nullptr ? CHIP_NO_ERROR : CHIP_ERROR_INCORRECT_STATE;
ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection called");

chip::Inet::IPAddress * ipAddressToUse = nullptr;

CHIP_ERROR err = CHIP_NO_ERROR;
err = (mConnectionState != CASTING_PLAYER_CONNECTING ? CHIP_NO_ERROR : CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(mConnectionState != CASTING_PLAYER_CONNECTING,
ChipLogError(AppServer,
"CastingPlayer::VerifyOrEstablishConnection called while already connecting to this CastingPlayer"));
mConnectionState = CASTING_PLAYER_CONNECTING;

SuccessOrExit(err = chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(
kCommissioningWindowTimeout));

ipAddressToUse = GetIpAddressForUDCRequest();
err = ipAddressToUse != nullptr ? CHIP_NO_ERROR : CHIP_ERROR_INCORRECT_STATE;
VerifyOrExit(ipAddressToUse != nullptr, ChipLogError(AppServer, "No IP Address found to send UDC request to"));

SuccessOrExit(err = support::ChipDeviceEventHandler::SetUdcStatus(true));
Expand All @@ -38,17 +53,32 @@ void CastingPlayer::Connect(ConnectCallback onCompleted, const chip::System::Clo

SuccessOrExit(err = chip::Server::GetInstance().SendUserDirectedCommissioningRequest(
chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId)));
SuccessOrExit(err = chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow(
kCommissioningWindowTimeout));

exit:
if (err != CHIP_NO_ERROR)
{
support::ChipDeviceEventHandler::SetUdcStatus(false);
ChipLogError(AppServer, "CastingPlayer::Connect failed with %" CHIP_ERROR_FORMAT, err.Format());
mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
ChipLogError(AppServer, "CastingPlayer::VerifyOrEstablishConnection failed with %" CHIP_ERROR_FORMAT, err.Format());
}
}

void CastingPlayer::FindOrEstablishSession(void * clientContext, chip::OnDeviceConnected onDeviceConnected,
chip::OnDeviceConnectionFailure onDeviceConnectionFailure)
{
ChipLogProgress(AppServer, "CastingPlayer.FindOrEstablishSession called on nodeId=0x" ChipLogFormatX64 " fabricIndex=%d",
ChipLogValueX64(mAttributes.nodeId), mAttributes.fabricIndex);
VerifyOrReturn(mAttributes.nodeId != 0 && mAttributes.fabricIndex != 0,
ChipLogError(AppServer, "CastingPlayer.FindOrEstablishSession called on invalid nodeId/fabricIndex"));

ConnectionContext * connectionContext =
new ConnectionContext(clientContext, this, onDeviceConnected, onDeviceConnectionFailure);

chip::Server::GetInstance().GetCASESessionManager()->FindOrEstablishSession(
chip::ScopedNodeId(mAttributes.nodeId, mAttributes.fabricIndex), connectionContext->mOnConnectedCallback,
connectionContext->mOnConnectionFailureCallback);
}

void CastingPlayer::LogDetail() const
{
if (strlen(mAttributes.id) != 0)
Expand Down Expand Up @@ -120,6 +150,54 @@ chip::Inet::IPAddress * CastingPlayer::GetIpAddressForUDCRequest()
return &mAttributes.ipAddresses[ipIndexToUse];
}

ConnectionContext::ConnectionContext(void * clientContext, core::CastingPlayer * targetCastingPlayer,
chip::OnDeviceConnected onDeviceConnectedFn,
chip::OnDeviceConnectionFailure onDeviceConnectionFailureFn)
{
mClientContext = clientContext;
mTargetCastingPlayer = targetCastingPlayer;
mOnDeviceConnectedFn = onDeviceConnectedFn;
mOnDeviceConnectionFailureFn = onDeviceConnectionFailureFn;

mOnConnectedCallback = new chip::Callback::Callback<chip::OnDeviceConnected>(
[](void * context, chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle) {
ChipLogProgress(AppServer, "Device Connection success callback called");
ConnectionContext * connectionContext = static_cast<ConnectionContext *>(context);
VerifyOrReturn(connectionContext != nullptr && connectionContext->mTargetCastingPlayer != nullptr,
ChipLogError(AppServer, "Invalid ConnectionContext received in DeviceConnection success callback"));

connectionContext->mTargetCastingPlayer->mConnectionState = core::CASTING_PLAYER_CONNECTED;
connectionContext->mOnDeviceConnectedFn(context, exchangeMgr, sessionHandle);
delete connectionContext;
},
this);

mOnConnectionFailureCallback = new chip::Callback::Callback<chip::OnDeviceConnectionFailure>(
[](void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR error) {
ChipLogError(AppServer, "Device Connection failure callback called with %" CHIP_ERROR_FORMAT, error.Format());
ConnectionContext * connectionContext = static_cast<ConnectionContext *>(context);
VerifyOrReturn(connectionContext != nullptr && connectionContext->mTargetCastingPlayer != nullptr,
ChipLogError(AppServer, "Invalid ConnectionContext received in DeviceConnection failure callback"));
connectionContext->mTargetCastingPlayer->mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
connectionContext->mOnDeviceConnectionFailureFn(connectionContext->mClientContext, peerId, error);
delete connectionContext;
},
this);
}

ConnectionContext::~ConnectionContext()
{
if (mOnConnectedCallback != nullptr)
{
delete mOnConnectedCallback;
}

if (mOnConnectionFailureCallback != nullptr)
{
delete mOnConnectionFailureCallback;
}
}

}; // namespace core
}; // namespace casting
}; // namespace matter
58 changes: 50 additions & 8 deletions examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ namespace matter {
namespace casting {
namespace core {

class CastingPlayer;
using ConnectCallback = std::function<void(CHIP_ERROR, CastingPlayer *)>;

const int kPortMaxLength = 5; // port is uint16_t
// +1 for the : between the hostname and the port.
const int kIdMaxLength = chip::Dnssd::kHostNameMaxLength + kPortMaxLength + 1;
Expand All @@ -53,8 +50,26 @@ class CastingPlayerAttributes
uint16_t productId;
uint16_t vendorId;
uint32_t deviceType;

chip::NodeId nodeId = 0;
chip::FabricIndex fabricIndex = 0;
};

/**
* @brief Represents CastingPlayer ConnectionState.
*
*/
enum ConnectionState
{
CASTING_PLAYER_NOT_CONNECTED,
CASTING_PLAYER_CONNECTING,
CASTING_PLAYER_CONNECTED,
};

class ConnectionContext;
class CastingPlayer;
using ConnectCallback = std::function<void(CHIP_ERROR, CastingPlayer *)>;

/**
* @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.
Expand All @@ -63,18 +78,22 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
{
private:
// std::vector<memory::Strong<Endpoint>> endpoints;
bool mConnected = false;
ConnectionState mConnectionState = CASTING_PLAYER_NOT_CONNECTED;
CastingPlayerAttributes mAttributes;
static CastingPlayer * mTargetCastingPlayer;
ConnectCallback mOnCompleted;
ConnectCallback mOnCompleted = {};

chip::Inet::IPAddress * GetIpAddressForUDCRequest();

friend class support::ChipDeviceEventHandler;
friend class ConnectionContext;

public:
CastingPlayer(CastingPlayerAttributes playerAttributes) { mAttributes = playerAttributes; }

void FindOrEstablishSession(void * clientContext, chip::OnDeviceConnected onDeviceConnected,
chip::OnDeviceConnectionFailure onDeviceConnectionFailure);

static CastingPlayer * GetTargetCastingPlayer() { return mTargetCastingPlayer; }

const char * GetId() const { return mAttributes.id; }
Expand All @@ -97,6 +116,14 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>

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

chip::NodeId GetNodeId() const { return mAttributes.nodeId; }

chip::FabricIndex GetFabricIndex() const { return mAttributes.fabricIndex; }

void SetNodeId(chip::NodeId nodeId) { mAttributes.nodeId = nodeId; }

void SetFabricIndex(chip::FabricIndex fabricIndex) { mAttributes.fabricIndex = fabricIndex; }

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

// const std::vector<memory::Strong<Endpoint>> GetEndpoints() const { return endpoints; }
Expand All @@ -113,13 +140,28 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
/**
* @return true if this CastingPlayer is connected to the CastingApp
*/
bool IsConnected() const { return mConnected; }
bool IsConnected() const { return mConnectionState == CASTING_PLAYER_CONNECTED; }

void Connect(ConnectCallback onCompleted,
const chip::System::Clock::Seconds16 commissioningWindowTimeout = kCommissioningWindowTimeout);
void VerifyOrEstablishConnection(ConnectCallback onCompleted,
const chip::System::Clock::Seconds16 commissioningWindowTimeout = kCommissioningWindowTimeout);
void LogDetail() const;
};

class ConnectionContext
{
public:
ConnectionContext(void * clientContext, core::CastingPlayer * targetCastingPlayer, chip::OnDeviceConnected onDeviceConnected,
chip::OnDeviceConnectionFailure onDeviceConnectionFailure);
~ConnectionContext();

void * mClientContext = nullptr;
core::CastingPlayer * mTargetCastingPlayer = nullptr;
chip::OnDeviceConnected mOnDeviceConnectedFn = nullptr;
chip::OnDeviceConnectionFailure mOnDeviceConnectionFailureFn = nullptr;
chip::Callback::Callback<chip::OnDeviceConnected> * mOnConnectedCallback = nullptr;
chip::Callback::Callback<chip::OnDeviceConnectionFailure> * mOnConnectionFailureCallback = nullptr;
};

}; // namespace core
}; // namespace casting
}; // namespace matter
Original file line number Diff line number Diff line change
Expand Up @@ -36,36 +36,38 @@ void ChipDeviceEventHandler::Handle(const chip::DeviceLayer::ChipDeviceEvent * e
ChipLogProgress(AppServer, "ChipDeviceEventHandler::Handle called");

bool runPostCommissioning = false;
chip::NodeId targetPeerNodeId = 0;
chip::NodeId targetNodeId = 0;
chip::FabricIndex targetFabricIndex = 0;
if (event->Type == chip::DeviceLayer::DeviceEventType::kBindingsChangedViaCluster &&
CastingPlayer::GetTargetCastingPlayer() != nullptr)
{
HandleBindingsChangedViaCluster(event, arg, runPostCommissioning, targetPeerNodeId, targetFabricIndex);
HandleBindingsChangedViaCluster(event, arg, runPostCommissioning, targetNodeId, targetFabricIndex);
}
else if (event->Type == chip::DeviceLayer::DeviceEventType::kCommissioningComplete)
{
HandleCommissioningComplete(event, arg, runPostCommissioning, targetPeerNodeId, targetFabricIndex);
HandleCommissioningComplete(event, arg, runPostCommissioning, targetNodeId, targetFabricIndex);
}

if (runPostCommissioning)
{
ChipLogProgress(AppServer, "ChipDeviceEventHandler::Handle will connect with nodeId=0x" ChipLogFormatX64 " fabricIndex=%d",
ChipLogValueX64(targetPeerNodeId), targetFabricIndex);
// TODO
/*CHIP_ERROR err = CastingServer::GetInstance()->GetActiveTargetVideoPlayer()->Initialize(
targetPeerNodeId, targetFabricIndex, CastingServer::GetInstance()->mOnConnectionSuccessClientCallback,
CastingServer::GetInstance()->mOnConnectionFailureClientCallback,
CastingServer::GetInstance()->mTargetVideoPlayerVendorId, CastingServer::GetInstance()->mTargetVideoPlayerProductId,
CastingServer::GetInstance()->mTargetVideoPlayerDeviceType, CastingServer::GetInstance()->mTargetVideoPlayerDeviceName,
CastingServer::GetInstance()->mTargetVideoPlayerHostName, CastingServer::GetInstance()->mTargetVideoPlayerNumIPs,
CastingServer::GetInstance()->mTargetVideoPlayerIpAddress);
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "Failed to initialize target video player");
}
CastingPlayer::GetTargetCastingPlayer()->SetNodeId(targetNodeId);
CastingPlayer::GetTargetCastingPlayer()->SetFabricIndex(targetFabricIndex);

CastingPlayer::GetTargetCastingPlayer()->FindOrEstablishSession(
nullptr,
[](void * context, chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle) {
ChipLogProgress(AppServer, "ChipDeviceEventHandler::Handle: Connection to CastingPlayer successful");
VerifyOrReturn(CastingPlayer::GetTargetCastingPlayer()->mOnCompleted);
CastingPlayer::GetTargetCastingPlayer()->mOnCompleted(CHIP_NO_ERROR, CastingPlayer::GetTargetCastingPlayer());
},
[](void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR error) {
ChipLogError(AppServer, "ChipDeviceEventHandler::Handle: Connection to CastingPlayer failed");
VerifyOrReturn(CastingPlayer::GetTargetCastingPlayer()->mOnCompleted);
CastingPlayer::GetTargetCastingPlayer()->mOnCompleted(error, nullptr);
});

// TODO
/*
err = CastingServer::GetInstance()->mPersistenceManager.AddVideoPlayer(
&CastingServer::GetInstance()->mActiveTargetVideoPlayerInfo);
if (err != CHIP_NO_ERROR)
Expand All @@ -81,19 +83,18 @@ void ChipDeviceEventHandler::Handle(const chip::DeviceLayer::ChipDeviceEvent * e
}

void ChipDeviceEventHandler::HandleBindingsChangedViaCluster(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg,
bool & runPostCommissioning, chip::NodeId & targetPeerNodeId,
bool & runPostCommissioning, chip::NodeId & targetNodeId,
chip::FabricIndex & targetFabricIndex)
{
ChipLogProgress(AppServer, "ChipDeviceEventHandler::HandleBindingsChangedViaCluster called");

if (CastingPlayer::GetTargetCastingPlayer()->IsConnected())
{
ChipLogProgress(
AppServer,
"ChipDeviceEventHandler::HandleBindingsChangedViaCluster already connected to video player, reading server clusters");
/* TODO
CastingServer::GetInstance()->ReadServerClustersForNode(
CastingServer::GetInstance()->GetActiveTargetVideoPlayer()->GetNodeId());*/
// re-use existing nodeId and fabricIndex
ChipLogProgress(AppServer, "ChipDeviceEventHandler::HandleBindingsChangedViaCluster already connected to video player");
runPostCommissioning = true;
targetNodeId = CastingPlayer::GetTargetCastingPlayer()->GetNodeId();
targetFabricIndex = CastingPlayer::GetTargetCastingPlayer()->GetFabricIndex();
}
else if (sUdcInProgress)
{
Expand All @@ -104,7 +105,7 @@ void ChipDeviceEventHandler::HandleBindingsChangedViaCluster(const chip::DeviceL
event->BindingsChanged.fabricIndex);
sUdcInProgress = false;

// find targetPeerNodeId from binding table by matching the binding's fabricIndex with the accessing fabricIndex
// find targetNodeId from binding table by matching the binding's fabricIndex with the accessing fabricIndex
// received in BindingsChanged event
for (const auto & binding : chip::BindingTable::GetInstance())
{
Expand All @@ -120,14 +121,14 @@ void ChipDeviceEventHandler::HandleBindingsChangedViaCluster(const chip::DeviceL
"ChipDeviceEventHandler::HandleBindingsChangedViaCluster Matched accessingFabricIndex with "
"nodeId=0x" ChipLogFormatX64,
ChipLogValueX64(binding.nodeId));
targetPeerNodeId = binding.nodeId;
targetNodeId = binding.nodeId;
targetFabricIndex = binding.fabricIndex;
runPostCommissioning = true;
break;
}
}

if (targetPeerNodeId == 0 && runPostCommissioning == false)
if (targetNodeId == 0 && runPostCommissioning == false)
{
ChipLogError(AppServer,
"ChipDeviceEventHandler::HandleBindingsChangedViaCluster accessingFabricIndex: %d did not match bindings",
Expand All @@ -140,12 +141,12 @@ void ChipDeviceEventHandler::HandleBindingsChangedViaCluster(const chip::DeviceL
}

void ChipDeviceEventHandler::HandleCommissioningComplete(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg,
bool & runPostCommissioning, chip::NodeId & targetPeerNodeId,
bool & runPostCommissioning, chip::NodeId & targetNodeId,
chip::FabricIndex & targetFabricIndex)
{
ChipLogProgress(AppServer, "ChipDeviceEventHandler::HandleCommissioningComplete called");
sUdcInProgress = false;
targetPeerNodeId = event->CommissioningComplete.nodeId;
targetNodeId = event->CommissioningComplete.nodeId;
targetFabricIndex = event->CommissioningComplete.fabricIndex;
runPostCommissioning = true;
}
Expand Down

0 comments on commit 3e6789e

Please sign in to comment.