Skip to content

Commit

Permalink
add observer logic between ICDManager and ICDManagementServer
Browse files Browse the repository at this point in the history
  • Loading branch information
mkardous-silabs authored and pull[bot] committed Jan 19, 2024
1 parent e569eb1 commit 1120300
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ class IcdManagementFabricDelegate : public chip::FabricTable::Delegate
ICDMonitoringTable table(Server::GetInstance().GetPersistentStorage(), fabricIndex, supported_clients,
Server::GetInstance().GetSessionKeystore());
table.RemoveAll();
ICDManagementServer::GetInstance().TableIsEmptyForFabric();
}
};

Expand Down
1 change: 1 addition & 0 deletions src/app/icd/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ source_set("cluster") {
]

public_deps = [
":notifier",
"${chip_root}/src/lib/core",
"${chip_root}/src/platform:platform",
"${chip_root}/src/protocols:im_status",
Expand Down
23 changes: 23 additions & 0 deletions src/app/icd/ICDManagementServer.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ICDManagementServer.h"
#include <app/icd/ICDNotifier.h>

using namespace chip;
using namespace chip::Protocols;
Expand All @@ -11,6 +12,7 @@ Status ICDManagementServer::RegisterClient(PersistentStorageDelegate & storage,
uint64_t monitored_subject, chip::ByteSpan key,
Optional<chip::ByteSpan> verification_key, bool is_admin)
{
bool isFirstEntryForFabric = false;
ICDMonitoringTable table(storage, fabric_index, GetClientsSupportedPerFabric(), mSymmetricKeystore);

// Get current entry, if exists
Expand All @@ -29,6 +31,9 @@ Status ICDManagementServer::RegisterClient(PersistentStorageDelegate & storage,
{
// New entry
VerifyOrReturnError(entry.index < table.Limit(), InteractionModel::Status::ResourceExhausted);

// Check if it's going to be the first entry for fabric
isFirstEntryForFabric = table.IsEmpty();
}
else
{
Expand Down Expand Up @@ -58,6 +63,12 @@ Status ICDManagementServer::RegisterClient(PersistentStorageDelegate & storage,
VerifyOrReturnError(CHIP_ERROR_INVALID_ARGUMENT != err, InteractionModel::Status::ConstraintError);
VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure);

if (isFirstEntryForFabric)
{
// Notify subscribers that the first entry for the fabric was successfully added
app::ICDNotifier::GetInstance().BroadcastICDManagementEvent(app::ICDListener::ICDManagementEvents::kTableUpdated);
}

return InteractionModel::Status::Success;
}

Expand All @@ -82,13 +93,25 @@ Status ICDManagementServer::UnregisterClient(PersistentStorageDelegate & storage
err = table.Remove(entry.index);
VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure);

if (table.IsEmpty())
{
TableIsEmptyForFabric();
}

return InteractionModel::Status::Success;
}

Status ICDManagementServer::StayActiveRequest(FabricIndex fabric_index)
{
// TODO: Implementent stay awake logic for end device
// https://github.com/project-chip/connectedhomeip/issues/24259
app::ICDNotifier::GetInstance().BroadcastICDManagementEvent(app::ICDListener::ICDManagementEvents::kStayActiveRequestReceived);
return InteractionModel::Status::UnsupportedCommand;
}

void ICDManagementServer::TableIsEmptyForFabric()
{
app::ICDNotifier::GetInstance().BroadcastICDManagementEvent(app::ICDListener::ICDManagementEvents::kTableUpdated);
}

} // namespace chip
4 changes: 4 additions & 0 deletions src/app/icd/ICDManagementServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class ICDManagementServer
Status UnregisterClient(PersistentStorageDelegate & storage, FabricIndex fabric_index, chip::NodeId node_id,
Optional<chip::ByteSpan> verificationKey, bool is_admin);

void TableIsEmptyForFabric();

Status StayActiveRequest(FabricIndex fabric_index);

static ICDManagementServer & GetInstance() { return mInstance; }
Expand All @@ -75,6 +77,8 @@ class ICDManagementServer

uint16_t mActiveThreshold_ms = CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS;

// TODO : Implement ICD counter
// https://github.com/project-chip/connectedhomeip/issues/29184
uint32_t mICDCounter = 0;

static_assert((CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC) >= 1,
Expand Down
38 changes: 31 additions & 7 deletions src/app/icd/ICDManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricT
VerifyOrDieWithMsg((supportLIT == false) || SupportsFeature(Feature::kUserActiveModeTrigger), AppServer,
"The user ActiveMode trigger feature is required for LIT support");

// Disabling check until LIT support is compelte
// VerifyOrDieWithMsg((supportLIT == false) && (GetSlowPollingInterval() <= GetSITPollingThreshold()) , AppServer,
// "LIT support is required for slow polling intervals superior to 15 seconds");

mStorage = storage;
mFabricTable = fabricTable;
mStateObserver = stateObserver;
Expand Down Expand Up @@ -90,13 +94,16 @@ void ICDManager::Shutdown()

bool ICDManager::SupportsFeature(Feature feature)
{
bool success = false;
uint32_t featureMap = 0;
// Can't use attribute accessors/Attributes::FeatureMap::Get in unit tests
#ifndef CONFIG_BUILD_FOR_HOST_UNIT_TEST
success = (Attributes::FeatureMap::Get(kRootEndpointId, &featureMap) == EMBER_ZCL_STATUS_SUCCESS);
#endif
bool success = false;
uint32_t featureMap = 0;
success = (Attributes::FeatureMap::Get(kRootEndpointId, &featureMap) == EMBER_ZCL_STATUS_SUCCESS);

return success ? ((featureMap & to_underlying(feature)) != 0) : false;
#else
return ((mFeatureMap & to_underlying(feature)) != 0);
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
}

void ICDManager::UpdateICDMode()
Expand All @@ -105,9 +112,8 @@ void ICDManager::UpdateICDMode()

ICDMode tempMode = ICDMode::SIT;

// The Check In Protocol Feature is required and the slow polling interval shall also be greater than 15 seconds
// to run an ICD in LIT mode.
if (GetSlowPollingInterval() > GetSITPollingThreshold() && SupportsFeature(Feature::kLongIdleTimeSupport))
// Device can only switch to the LIT operating mode if LIT support is present
if (SupportsFeature(Feature::kLongIdleTimeSupport))
{
VerifyOrDie(mStorage != nullptr);
VerifyOrDie(mFabricTable != nullptr);
Expand Down Expand Up @@ -315,5 +321,23 @@ void ICDManager::OnNetworkActivity()
{
this->UpdateOperationState(OperationalState::ActiveMode);
}

void ICDManager::OnICDManagementServerEvent(ICDManagementEvents event)
{
switch (event)
{
case ICDManagementEvents::kTableUpdated:
this->UpdateICDMode();
break;

case ICDManagementEvents::kStayActiveRequestReceived:
// TODO : Implement the StayActiveRequest
// https://github.com/project-chip/connectedhomeip/issues/24259
break;
default:
break;
}
}

} // namespace app
} // namespace chip
10 changes: 10 additions & 0 deletions src/app/icd/ICDManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,16 @@ class ICDManager : public ICDListener
static System::Clock::Milliseconds32 GetSlowPollingInterval() { return kSlowPollingInterval; }
static System::Clock::Milliseconds32 GetFastPollingInterval() { return kFastPollingInterval; }

#ifdef CONFIG_BUILD_FOR_HOST_UNIT_TEST
void SetTestFeatureMapValue(uint32_t featureMap) { mFeatureMap = featureMap; };
#endif

// Implementation of ICDListener functions.
// Callers must origin from the chip task context or be holding the ChipStack lock.
void OnNetworkActivity() override;
void OnKeepActiveRequest(KeepActiveFlags request) override;
void OnActiveRequestWithdrawal(KeepActiveFlags request) override;
void OnICDManagementServerEvent(ICDManagementEvents event) override;

protected:
friend class TestICDManager;
Expand Down Expand Up @@ -108,6 +113,11 @@ class ICDManager : public ICDListener
ICDStateObserver * mStateObserver = nullptr;
bool mTransitionToIdleCalled = false;
Crypto::SymmetricKeystore * mSymmetricKeystore = nullptr;

#ifdef CONFIG_BUILD_FOR_HOST_UNIT_TEST
// feature map that can be changed at runtime for testing purposes
uint32_t mFeatureMap = 0;
#endif
};

} // namespace app
Expand Down
11 changes: 11 additions & 0 deletions src/app/icd/ICDNotifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,16 @@ void ICDNotifier::BroadcastActiveRequestWithdrawal(ICDListener::KeepActiveFlags
}
}

void ICDNotifier::BroadcastICDManagementEvent(ICDListener::ICDManagementEvents event)
{
for (auto subscriber : mSubscribers)
{
if (subscriber != nullptr)
{
subscriber->OnICDManagementServerEvent(event);
}
}
}

} // namespace app
} // namespace chip
15 changes: 15 additions & 0 deletions src/app/icd/ICDNotifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ class ICDListener
kExchangeContextOpen = 0x03,
};

enum class ICDManagementEvents : uint8_t
{
kTableUpdated = 0x01,
kStayActiveRequestReceived = 0x02,
};

virtual ~ICDListener() {}

/**
Expand All @@ -68,6 +74,14 @@ class ICDListener
* @param request : The request source
*/
virtual void OnActiveRequestWithdrawal(KeepActiveFlags request) = 0;

/**
* @brief This function is called for all subscribers of the ICDNotifier when it calls BroadcastICDManagementEvent
* It informs the subscriber that an ICD Management action has happened and needs to be processed
*
* @param event : The event type
*/
virtual void OnICDManagementServerEvent(ICDManagementEvents event){};
};

class ICDNotifier
Expand All @@ -85,6 +99,7 @@ class ICDNotifier
void BroadcastNetworkActivityNotification();
void BroadcastActiveRequestNotification(ICDListener::KeepActiveFlags request);
void BroadcastActiveRequestWithdrawal(ICDListener::KeepActiveFlags request);
void BroadcastICDManagementEvent(ICDListener::ICDManagementEvents event);

static ICDNotifier & GetInstance() { return sICDNotifier; }

Expand Down
Loading

0 comments on commit 1120300

Please sign in to comment.