Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AccountLogin Login/Logout command support #34162

Merged
merged 74 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
8f98caf
AccountLogin Login/Logout command support
mthiesc Jun 28, 2024
2b99f24
HandleLogin in ContentAppPlatform::ManageClientAccess
mthiesc Jul 4, 2024
5c1bb91
Cache rotating ID in OnUserDirectedCommissioningRequest
mthiesc Jul 6, 2024
33fad6d
Restyled by google-java-format
restyled-commits Jul 6, 2024
2713b60
Restyled by clang-format
restyled-commits Jul 6, 2024
cb826a5
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 10, 2024
2029347
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
473c3ab
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
d7747b0
Update content app
lazarkov Jul 11, 2024
d5915a3
Restyled by whitespace
restyled-commits Jul 11, 2024
c4489c4
Restyled by clang-format
restyled-commits Jul 11, 2024
343f1bf
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
b86f8ba
Update response
lazarkov Jul 11, 2024
fe52e9b
Update method name
lazarkov Jul 11, 2024
3f9ba8c
Restyled by google-java-format
restyled-commits Jul 11, 2024
4b8d323
Update src/app/app-platform/ContentApp.h
lazarkov Jul 11, 2024
d995175
Update content app platform validation
lazarkov Jul 11, 2024
9067357
Update validation logic
lazarkov Jul 11, 2024
8957b1f
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
7289e08
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
b6b2927
Update logic
lazarkov Jul 11, 2024
5cb6dd6
Update responses
lazarkov Jul 11, 2024
471d838
Restyled by clang-format
restyled-commits Jul 11, 2024
968adfe
Simplify logic
lazarkov Jul 11, 2024
45a3f12
Restyled by whitespace
restyled-commits Jul 11, 2024
8836681
clean up
lazarkov Jul 11, 2024
e1cb367
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
15c904f
Update code
lazarkov Jul 12, 2024
0e910fe
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 12, 2024
af9d528
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 12, 2024
d422046
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 13, 2024
57894e4
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 15, 2024
ee443e3
Update content app with dynamic pin code
lazarkov Jul 15, 2024
8fa8ae2
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 15, 2024
8ec3d2a
Restyled by google-java-format
restyled-commits Jul 15, 2024
dde2830
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 16, 2024
82dab86
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 16, 2024
9d68f73
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 16, 2024
b208c46
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 17, 2024
35155b7
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 17, 2024
1d28980
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 17, 2024
580605d
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 17, 2024
5c76617
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 18, 2024
5356da2
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 19, 2024
2ca28f6
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 19, 2024
cb9feba
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 19, 2024
46cb529
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 19, 2024
0d9dc71
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 20, 2024
04726e4
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 20, 2024
538425c
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 22, 2024
5d27aba
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 22, 2024
fee0b92
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 22, 2024
40057a0
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 23, 2024
e765019
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 24, 2024
fb33ae2
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 24, 2024
092cdb2
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 24, 2024
cebfe2e
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 25, 2024
768f608
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 25, 2024
a9d1067
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 26, 2024
9ce6830
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 26, 2024
7feb6ef
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 26, 2024
0cc3860
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 26, 2024
6f598e9
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 26, 2024
43c87e8
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 29, 2024
1da644e
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 29, 2024
3929ab6
Merge branch 'master' into accountlogin-login-logout-support
mthiesc Aug 2, 2024
d48832c
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Aug 2, 2024
c863bae
Merge branch 'master' into accountlogin-login-logout-support
mthiesc Aug 5, 2024
9c9e036
Remove getRotatingIdSpan class methods
mthiesc Aug 19, 2024
9dd0a50
Merge branch 'master' into accountlogin-login-logout-support
mthiesc Aug 19, 2024
ac49ea3
Restyled by clang-format
restyled-commits Aug 19, 2024
3b70d26
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Aug 21, 2024
9632993
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Aug 22, 2024
f187308
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Aug 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ private CommandResponseHolder() {
Clusters.AccountLogin.Id,
Clusters.AccountLogin.Commands.GetSetupPIN.ID,
"{\"0\":\"20202021\"}");
setResponseValue(
Clusters.AccountLogin.Id,
Clusters.AccountLogin.Commands.Login.ID,
"0");
setResponseValue(
Clusters.AccountLogin.Id,
Clusters.AccountLogin.Commands.Logout.ID,
"0");
};

public static CommandResponseHolder getInstance() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,34 @@
#include <lib/core/DataModelTypes.h>

using namespace std;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::AccountLogin;
using Status = chip::Protocols::InteractionModel::Status;

namespace {

const auto loginTempAccountIdentifierFieldId = to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kTempAccountIdentifier));
const auto loginSetupPINFieldId = to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kSetupPIN));
const auto loginNodeFieldId = to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kNode));
const auto logoutNodeFieldId = to_string(chip::to_underlying(AccountLogin::Commands::Logout::Fields::kNode));

string charSpanToString(const CharSpan& charSpan) {
return { charSpan.data(), charSpan.size() };
}

std::string serializeLoginCommand(AccountLogin::Commands::Login::Type cmd) {
return
R"({")" + loginTempAccountIdentifierFieldId + R"(":")" + charSpanToString(cmd.tempAccountIdentifier) + R"(",)" +
R"(")" + loginSetupPINFieldId + R"(":")" + charSpanToString(cmd.setupPIN) + R"(",)" +
R"(")" + loginNodeFieldId + R"(":")" + to_string(cmd.node.Value()) + R"("})";
}

std::string serializeLogoutCommand(AccountLogin::Commands::Logout::Type cmd) {
return R"({")" + logoutNodeFieldId + R"(":")" + to_string(cmd.node.Value()) + R"("})";
}

}

AccountLoginManager::AccountLoginManager(ContentAppCommandDelegate * commandDelegate, const char * setupPin) :
mCommandDelegate(commandDelegate)
{
Expand All @@ -37,25 +62,61 @@ bool AccountLoginManager::HandleLogin(const CharSpan & tempAccountIdentifier, co
const chip::Optional<chip::NodeId> & nodeId)
{
ChipLogProgress(DeviceLayer, "AccountLoginManager::HandleLogin called for endpoint %d", mEndpointId);
string tempAccountIdentifierString(tempAccountIdentifier.data(), tempAccountIdentifier.size());
string setupPinString(setupPin.data(), setupPin.size());

if (strcmp(mSetupPin, setupPinString.c_str()) == 0)
if (mCommandDelegate == nullptr)
{
ChipLogProgress(Zcl, "AccountLoginManager::HandleLogin success");
return true;
ChipLogError(Zcl, "CommandDelegate not found");
return false;
}
else
{
ChipLogProgress(Zcl, "AccountLoginManager::HandleLogin failed expected pin %s", mSetupPin);

if (tempAccountIdentifier.empty() || setupPIN.empty() || !nodeId.HasValue()) {
ChipLogError(Zcl, "Invalid parameters");
return false;
}

Json::Value response;
bool commandHandled = true;
AccountLogin::Commands::Login::Type cmd = { tempAccountIdentifier, setupPin, nodeId };

// Deliberately ignore returned status
mCommandDelegate->InvokeCommand(mEndpointId, AccountLogin::Id,
AccountLogin::Commands::Login::Id,
serializeLoginCommand(cmd), commandHandled, response);

Status status = mCommandDelegate->FormatStatusResponse(response);
ChipLogProgress(Zcl, "AccountLoginManager::HandleLogin command returned with status: %d", chip::to_underlying(status));

return status == chip::Protocols::InteractionModel::Status::Success;
}

bool AccountLoginManager::HandleLogout(const chip::Optional<chip::NodeId> & nodeId)
{
// TODO: Insert your code here to send logout request
return true;
ChipLogProgress(DeviceLayer, "AccountLoginManager::HandleLogout called for endpoint %d", mEndpointId);

if (mCommandDelegate == nullptr)
{
ChipLogError(Zcl, "CommandDelegate not found");
return false;
}

if (!nodeId.HasValue()) {
ChipLogError(Zcl, "Invalid parameters");
return false;
}

Json::Value response;
bool commandHandled = true;
AccountLogin::Commands::Logout::Type cmd = { nodeId };

// Deliberately ignore returned status
mCommandDelegate->InvokeCommand(mEndpointId, AccountLogin::Id,
AccountLogin::Commands::Logout::Id,
serializeLogoutCommand(cmd), commandHandled, response);

Status status = mCommandDelegate->FormatStatusResponse(response);
ChipLogProgress(Zcl, "AccountLoginManager::HandleLogout command returned with status: %d", chip::to_underlying(status));

return status == chip::Protocols::InteractionModel::Status::Success;
}

void AccountLoginManager::HandleGetSetupPin(CommandResponseHelper<GetSetupPINResponse> & helper,
Expand Down
58 changes: 37 additions & 21 deletions examples/tv-app/android/java/ContentAppCommandDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,6 @@
namespace chip {
namespace AppPlatform {

using CommandHandlerInterface = chip::app::CommandHandlerInterface;
using LaunchResponseType = chip::app::Clusters::ContentLauncher::Commands::LauncherResponse::Type;
using PlaybackResponseType = chip::app::Clusters::MediaPlayback::Commands::PlaybackResponse::Type;
using NavigateTargetResponseType = chip::app::Clusters::TargetNavigator::Commands::NavigateTargetResponse::Type;
using GetSetupPINResponseType = chip::app::Clusters::AccountLogin::Commands::GetSetupPINResponse::Type;
using Status = chip::Protocols::InteractionModel::Status;

const std::string FAILURE_KEY = "PlatformError";
const std::string FAILURE_STATUS_KEY = "Status";

Expand Down Expand Up @@ -107,6 +100,7 @@ void ContentAppCommandDelegate::InvokeCommand(CommandHandlerInterface::HandlerCo
Status ContentAppCommandDelegate::InvokeCommand(EndpointId epId, ClusterId clusterId, CommandId commandId, std::string payload,
bool & commandHandled, Json::Value & value)
{
// Q1: It seems like this InvokeCommand *never* returns success status.
if (epId >= FIXED_ENDPOINT_COUNT)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
Expand Down Expand Up @@ -153,6 +147,7 @@ Status ContentAppCommandDelegate::InvokeCommand(EndpointId epId, ClusterId clust
return chip::Protocols::InteractionModel::Status::Failure;
}

// Q: It would seem that this is the successfull return case (?)
return chip::Protocols::InteractionModel::Status::UnsupportedEndpoint;
}
else
Expand Down Expand Up @@ -231,20 +226,30 @@ void ContentAppCommandDelegate::FormatResponseData(CommandHandlerInterface::Hand
}

case app::Clusters::AccountLogin::Id: {
if (app::Clusters::AccountLogin::Commands::GetSetupPIN::Id != handlerContext.mRequestPath.mCommandId)
{
// No response for other commands in this cluster
break;
}
Status status;
GetSetupPINResponseType getSetupPINresponse = FormatGetSetupPINResponse(value, status);
if (status != chip::Protocols::InteractionModel::Status::Success)
{
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
}
else
{
handlerContext.mCommandHandler.AddResponse(handlerContext.mRequestPath, getSetupPINresponse);
switch (handlerContext.mRequestPath.mCommandId) {
case app::Clusters::AccountLogin::Commands::GetSetupPIN::Id: {
Status status;
GetSetupPINResponseType getSetupPINresponse = FormatGetSetupPINResponse(value, status);
if (status != chip::Protocols::InteractionModel::Status::Success)
{
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
}
else
{
handlerContext.mCommandHandler.AddResponse(handlerContext.mRequestPath, getSetupPINresponse);
}
break;
}
case app::Clusters::AccountLogin::Commands::Login::Id: {
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, FormatStatusResponse(value));
break;
}
case app::Clusters::AccountLogin::Commands::Logout::Id: {
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, FormatStatusResponse(value));
break;
}
default:
break;
}
break;
}
Expand Down Expand Up @@ -342,5 +347,16 @@ GetSetupPINResponseType ContentAppCommandDelegate::FormatGetSetupPINResponse(Jso
return getSetupPINresponse;
}

Status ContentAppCommandDelegate::FormatStatusResponse(Json::Value value)
{
if (value.isUInt()) {
return static_cast<Protocols::InteractionModel::Status>(value.asUInt());
}
else
{
return chip::Protocols::InteractionModel::Status::Failure;
}
}

} // namespace AppPlatform
} // namespace chip
2 changes: 2 additions & 0 deletions examples/tv-app/android/java/ContentAppCommandDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <json/json.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/JniReferences.h>
#include <protocols/interaction_model/StatusCode.h>

#include <string>

Expand Down Expand Up @@ -75,6 +76,7 @@ class ContentAppCommandDelegate : public CommandHandlerInterface
LaunchResponseType FormatContentLauncherResponse(Json::Value value, Status & status);
NavigateTargetResponseType FormatNavigateTargetResponse(Json::Value value, Status & status);
PlaybackResponseType FormatMediaPlaybackResponse(Json::Value value, Status & status);
Status FormatStatusResponse(Json::Value value);

private:
void InitializeJNIObjects(jobject manager)
Expand Down
26 changes: 26 additions & 0 deletions src/controller/CommissionerDiscoveryController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <controller/CommissionerDiscoveryController.h>
#include <platform/CHIPDeviceLayer.h>
#include <setup_payload/AdditionalDataPayloadGenerator.h>
#include <app/app-platform/ContentAppPlatform.h>

#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY

Expand Down Expand Up @@ -405,6 +406,7 @@ void CommissionerDiscoveryController::InternalHandleContentAppPasscodeResponse()
ValidateSession();
uint32_t passcode = mPasscode;

// Q: Seems like getting rotating ID is done twice - once here and once in InternalOk. Is this necessary or could it be cached?
if (mUdcServer == nullptr)
{
ChipLogError(AppServer, "UX Ok - HandleContentAppPasscodeResponse: no udc server");
Expand Down Expand Up @@ -440,6 +442,9 @@ void CommissionerDiscoveryController::InternalHandleContentAppPasscodeResponse()
}
CharSpan rotatingIdSpan(rotatingIdBuffer, 2 * rotatingIdLength);

// Store rotating ID as tempAccountIdentifier to use in AccountLogin::Login payload later.
mTempAccountIdentifier = rotatingIdSpan;

// first step of commissioner passcode
ChipLogError(AppServer, "UX Ok: commissioner passcode, sending CDC");
// generate a passcode
Expand All @@ -455,6 +460,10 @@ void CommissionerDiscoveryController::InternalHandleContentAppPasscodeResponse()
cd, Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort()));
return;
}
// Store commissioner passcode as setup PIN (string/charspan).
// If this PIN is not empty it signals that user prompt was shown to enter PIN and AccountLogin::Login command has to be sent.
mCommissionerSetupPin = CharSpan::fromCharString(std::to_string(passcode));

client->SetCachedCommissionerPasscode(passcode);
client->SetUDCClientProcessingState(UDCClientProcessingState::kWaitingForCommissionerPasscodeReady);

Expand Down Expand Up @@ -606,6 +615,23 @@ void CommissionerDiscoveryController::CommissioningSucceeded(uint16_t vendorId,
mVendorId = vendorId;
mProductId = productId;
mNodeId = nodeId;

// Send AccountLogin::Login command if user was prompted to enter setup PIN manually.
// Q: Is this the correct place to have this logic?
// Q: Is there an easier way call AccountLoginDelegate from here?
if (!mCommissionerSetupPIN.empty()) {
ChipLogProgress(AppServer, "UX ComissioningSucceeded with setupPIN prompt flow");
auto app = ContentAppPlatform::GetInstance().LoadContentAppByClient(vendorId, productId);
if (app == nullptr) {
ChipLogError(AppServer, "UX ComissioningSucceeded with setupPIN prompt flow: Failed to get ContentApp");
// Q: Any action to take?
} else {
auto status = app->GetAccountLoginDelegate()->HandleLogin(mTempAccountIdentifier, mCommissionerSetupPin, {mNodeId});
ChipLogProgress(AppServer, "UX ComissioningSucceeded with setupPIN prompt flow: HandleLogin response status: %d", status);
// Q: Any action to take here if status is true/false?
}
}

if (mPostCommissioningListener != nullptr)
{
ChipLogDetail(Controller, "CommissionerDiscoveryController calling listener");
Expand Down
3 changes: 3 additions & 0 deletions src/controller/CommissionerDiscoveryController.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY

using chip::CharSpan;
using chip::NodeId;
using chip::OperationalSessionSetup;
using chip::Protocols::UserDirectedCommissioning::UDCClientState;
Expand Down Expand Up @@ -451,6 +452,8 @@ class CommissionerDiscoveryController : public chip::Protocols::UserDirectedComm
uint16_t mProductId = 0;
NodeId mNodeId = 0;
uint32_t mPasscode = 0;
CharSpan mTempAccountIdentifier;
CharSpan mCommissionerSetupPin;

UserDirectedCommissioningServer * mUdcServer = nullptr;
UserPrompter * mUserPrompter = nullptr;
Expand Down
Loading