-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create new ICD Manager in fabric-admin to service KeepActive Command (#…
…34894) --------- Co-authored-by: Restyled.io <[email protected]> Co-authored-by: yunhanw <[email protected]>
- Loading branch information
Showing
9 changed files
with
377 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* Copyright (c) 2024 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. | ||
* | ||
*/ | ||
|
||
#include "IcdManager.h" | ||
|
||
IcdManager IcdManager::sInstance; | ||
|
||
IcdManager & IcdManager::Instance() | ||
{ | ||
return sInstance; | ||
} | ||
|
||
void IcdManager::OnCheckInComplete(const chip::app::ICDClientInfo & clientInfo) | ||
{ | ||
DefaultCheckInDelegate::OnCheckInComplete(clientInfo); | ||
if (mDelegate) | ||
{ | ||
mDelegate->OnCheckInCompleted(clientInfo); | ||
} | ||
} | ||
|
||
void IcdManager::SetDelegate(Delegate * delegate) | ||
{ | ||
// To keep IcdManager simple, there is an assumption that there is only ever | ||
// one delegate set and it's lifetime is identical to IcdManager. In the | ||
// future this assumption can change should there be a need, but that will | ||
// require code changes to IcdManager. For now we will crash if someone tries | ||
// to call SetDelegate for a second time or if delegate is non-null. | ||
VerifyOrDie(delegate); | ||
VerifyOrDie(!mDelegate); | ||
mDelegate = delegate; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright (c) 2024 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 <app/icd/client/DefaultCheckInDelegate.h> | ||
|
||
/** | ||
* @brief Manages check-ins from ICD devices. | ||
* | ||
* Intended to be used as a thin CheckInDelegate. This allows a delegate register | ||
* themselves so they can be aware when ICD device checks-in allowing the | ||
* delegate to interact with the ICD device during the short window that it is | ||
* awake. | ||
*/ | ||
class IcdManager : public chip::app::DefaultCheckInDelegate | ||
{ | ||
public: | ||
class Delegate | ||
{ | ||
public: | ||
virtual ~Delegate() = default; | ||
virtual void OnCheckInCompleted(const chip::app::ICDClientInfo & clientInfo) = 0; | ||
}; | ||
|
||
static IcdManager & Instance(); | ||
void OnCheckInComplete(const chip::app::ICDClientInfo & clientInfo) override; | ||
|
||
// There is an assumption delegate assigned only happens once and that it lives | ||
// for the entirety of the lifetime of fabric admin. | ||
void SetDelegate(Delegate * delegate); | ||
|
||
private: | ||
static IcdManager sInstance; | ||
Delegate * mDelegate = nullptr; | ||
}; |
99 changes: 99 additions & 0 deletions
99
examples/fabric-admin/commands/common/StayActiveSender.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
* Copyright (c) 2024 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. | ||
*/ | ||
|
||
#include "StayActiveSender.h" | ||
|
||
#include <app-common/zap-generated/cluster-objects.h> | ||
#include <app/ConcreteCommandPath.h> | ||
#include <controller/InvokeInteraction.h> | ||
#include <support/CHIPMem.h> | ||
|
||
CHIP_ERROR StayActiveSender::SendStayActiveCommand(uint32_t stayActiveDurationMs, const chip::ScopedNodeId & peerNode, | ||
chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone) | ||
{ | ||
ConstructorOnlyInternallyCallable internal; | ||
auto stayActiveSender = chip::Platform::New<StayActiveSender>(internal, stayActiveDurationMs, peerNode, | ||
chip::app::InteractionModelEngine::GetInstance(), onDone); | ||
VerifyOrReturnError(stayActiveSender != nullptr, CHIP_ERROR_NO_MEMORY); | ||
CHIP_ERROR err = stayActiveSender->EstablishSessionToPeer(); | ||
if (CHIP_NO_ERROR != err) | ||
{ | ||
chip::Platform::Delete(stayActiveSender); | ||
} | ||
return err; | ||
} | ||
|
||
StayActiveSender::StayActiveSender(const ConstructorOnlyInternallyCallable & _, uint32_t stayActiveDurationMs, | ||
const chip::ScopedNodeId & peerNode, chip::app::InteractionModelEngine * engine, | ||
OnDoneCallbackType onDone) : | ||
mStayActiveDurationMs(stayActiveDurationMs), | ||
mPeerNode(peerNode), mpImEngine(engine), mOnDone(onDone), mOnConnectedCallback(HandleDeviceConnected, this), | ||
mOnConnectionFailureCallback(HandleDeviceConnectionFailure, this) | ||
{} | ||
|
||
CHIP_ERROR StayActiveSender::SendStayActiveCommand(chip::Messaging::ExchangeManager & exchangeMgr, | ||
const chip::SessionHandle & sessionHandle) | ||
{ | ||
auto onSuccess = [&](const chip::app::ConcreteCommandPath & commandPath, const chip::app::StatusIB & status, | ||
const auto & dataResponse) { | ||
uint32_t promisedActiveDurationMs = dataResponse.promisedActiveDuration; | ||
ChipLogProgress(ICD, "StayActive command succeeded with promised duration %u", promisedActiveDurationMs); | ||
mOnDone(promisedActiveDurationMs); | ||
chip::Platform::Delete(this); | ||
}; | ||
|
||
auto onFailure = [&](CHIP_ERROR error) { | ||
ChipLogError(ICD, "StayActive command failed: %" CHIP_ERROR_FORMAT, error.Format()); | ||
chip::Platform::Delete(this); | ||
}; | ||
|
||
chip::EndpointId endpointId = 0; | ||
chip::app::Clusters::IcdManagement::Commands::StayActiveRequest::Type request; | ||
request.stayActiveDuration = mStayActiveDurationMs; | ||
return chip::Controller::InvokeCommandRequest(&exchangeMgr, sessionHandle, endpointId, request, onSuccess, onFailure); | ||
} | ||
|
||
CHIP_ERROR StayActiveSender::EstablishSessionToPeer() | ||
{ | ||
ChipLogProgress(ICD, "Trying to establish a CASE session to extend the active period for lit icd device"); | ||
auto * caseSessionManager = mpImEngine->GetCASESessionManager(); | ||
VerifyOrReturnError(caseSessionManager != nullptr, CHIP_ERROR_INVALID_CASE_PARAMETER); | ||
caseSessionManager->FindOrEstablishSession(mPeerNode, &mOnConnectedCallback, &mOnConnectionFailureCallback); | ||
return CHIP_NO_ERROR; | ||
} | ||
|
||
void StayActiveSender::HandleDeviceConnected(void * context, chip::Messaging::ExchangeManager & exchangeMgr, | ||
const chip::SessionHandle & sessionHandle) | ||
{ | ||
StayActiveSender * const _this = static_cast<StayActiveSender *>(context); | ||
VerifyOrDie(_this != nullptr); | ||
|
||
CHIP_ERROR err = _this->SendStayActiveCommand(exchangeMgr, sessionHandle); | ||
if (CHIP_NO_ERROR != err) | ||
{ | ||
ChipLogError(ICD, "Failed to send stay active command"); | ||
chip::Platform::Delete(_this); | ||
} | ||
} | ||
|
||
void StayActiveSender::HandleDeviceConnectionFailure(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR err) | ||
{ | ||
StayActiveSender * const _this = static_cast<StayActiveSender *>(context); | ||
VerifyOrDie(_this != nullptr); | ||
ChipLogError(ICD, "Failed to establish CASE for stay active command with error '%" CHIP_ERROR_FORMAT "'", err.Format()); | ||
chip::Platform::Delete(_this); | ||
} |
107 changes: 107 additions & 0 deletions
107
examples/fabric-admin/commands/common/StayActiveSender.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* | ||
* | ||
* Copyright (c) 2024 Project CHIP Authors | ||
* | ||
* 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 <stddef.h> | ||
|
||
#include <app/InteractionModelEngine.h> | ||
#include <lib/core/ScopedNodeId.h> | ||
#include <messaging/ExchangeMgr.h> | ||
|
||
/** | ||
* @brief StayActiveSender contains all the data and methods needed for active period extension of an ICD client. | ||
* | ||
* Lifetime of instance of StayActiveSender is entirely self managed. | ||
*/ | ||
class StayActiveSender | ||
{ | ||
private: | ||
// Ideally StayActiveSender would be a private constructor, unfortunately that is not possible as Platform::New | ||
// does not have access to private constructors. As a workaround we have defined this private struct that can | ||
// be forwarded by Platform::New that allows us to enforce that the only way StayActiveSender is constructed is | ||
// if SendStayActiveCommand is called. | ||
struct ConstructorOnlyInternallyCallable | ||
{ | ||
}; | ||
|
||
public: | ||
using OnDoneCallbackType = std::function<void(uint32_t promisedActiveDurationMs)>; | ||
|
||
/** | ||
* @brief Attempts to send a StayActiveRequest command | ||
* | ||
* @param[in] stayActiveDurationMs StayActiveRequest command parameter. | ||
* @param[in] peerNode Peer node we sending StayActiveRequest command to | ||
* @param[in] engine Interaction Model Engine instance for sending command. | ||
* @param[in] onDone Upon this function returning success, it is expected that onDone will be called after we | ||
* have successfully recieved a response | ||
* | ||
* @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code. | ||
*/ | ||
static CHIP_ERROR SendStayActiveCommand(uint32_t stayActiveDurationMs, const chip::ScopedNodeId & peerNode, | ||
chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone); | ||
|
||
// Ideally this would be a private constructor, unfortunately that is not possible as Platform::New does not | ||
// have access to private constructors. As a workaround we have defined a private struct that can be forwarded | ||
// by Platform::New that allows us to enforce that the only way this is constructed is if SendStayActiveCommand | ||
// is called. | ||
StayActiveSender(const ConstructorOnlyInternallyCallable & _, uint32_t stayActiveDurationMs, | ||
const chip::ScopedNodeId & peerNode, chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone); | ||
|
||
private: | ||
/** | ||
* @brief Sets up a CASE session with the peer to extend the client's active period with that peer. | ||
* Returns error if we did not even manage to kick off a CASE attempt. | ||
*/ | ||
CHIP_ERROR EstablishSessionToPeer(); | ||
|
||
// CASE session callbacks | ||
/** | ||
*@brief Callback received on successfully establishing a CASE session in order to keep the 'lit icd device' active | ||
* | ||
* @param[in] context - context of the client establishing the CASE session | ||
* @param[in] exchangeMgr - exchange manager to use for the re-registration | ||
* @param[in] sessionHandle - session handle to use for the re-registration | ||
*/ | ||
static void HandleDeviceConnected(void * context, chip::Messaging::ExchangeManager & exchangeMgr, | ||
const chip::SessionHandle & sessionHandle); | ||
/** | ||
* @brief Callback received on failure to establish a CASE session | ||
* | ||
* @param[in] context - context of the client establishing the CASE session | ||
* @param[in] peerId - Scoped Node ID of the peer node | ||
* @param[in] err - failure reason | ||
*/ | ||
static void HandleDeviceConnectionFailure(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR err); | ||
|
||
/** | ||
* @brief Used to send a stayActive command to the peer | ||
* | ||
* @param[in] exchangeMgr - exchange manager to use for the re-registration | ||
* @param[in] sessionHandle - session handle to use for the re-registration | ||
*/ | ||
CHIP_ERROR SendStayActiveCommand(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); | ||
|
||
uint32_t mStayActiveDurationMs = 0; | ||
chip::ScopedNodeId mPeerNode; | ||
chip::app::InteractionModelEngine * mpImEngine = nullptr; | ||
OnDoneCallbackType mOnDone; | ||
|
||
chip::Callback::Callback<chip::OnDeviceConnected> mOnConnectedCallback; | ||
chip::Callback::Callback<chip::OnDeviceConnectionFailure> mOnConnectionFailureCallback; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.