Skip to content

Commit

Permalink
[zephyr] Added support for few GeneralDiagnostics attributes
Browse files Browse the repository at this point in the history
Platform doesn't support a few optional attributes and also
mandatory BootReason event.

* Added support for attributes: UpTime, TotalOperationalHours
* Added support for event: BootReason
  • Loading branch information
kkasperczyk-no committed Dec 20, 2021
1 parent 3a28cd7 commit 3b16dd5
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 5 deletions.
10 changes: 10 additions & 0 deletions config/zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ config CHIP_OTA_REQUESTOR
Device Firmware Upgrade by quering and downloading a new firmware image
from an external OTA Provider node.

config CHIP_OPERATIONAL_TIME_SAVE_INTERVAL
int "Interval of saving node operation time to flash in hours unit"
default 10
range 1 4294967295
help
Interval in hours with which the node operation time is saved to the flash
memory. Selected value is a trade off between performing frequent saves to know
precisely operation time in case of device reboot and maximizing flash memory
lifetime.

config APP_LINK_WITH_CHIP
bool "Link 'app' with Connected Home over IP"
default y
Expand Down
16 changes: 16 additions & 0 deletions src/platform/Zephyr/ConfigurationManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,22 @@ CHIP_ERROR ConfigurationManagerImpl::StoreRebootCount(uint32_t rebootCount)
return WriteConfigValue(ZephyrConfig::kCounterKey_RebootCount, rebootCount);
}

CHIP_ERROR ConfigurationManagerImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours)
{
if (!ZephyrConfig::ConfigValueExists(ZephyrConfig::kCounterKey_TotalOperationalHours))
{
totalOperationalHours = 0;
return CHIP_NO_ERROR;
}

return ZephyrConfig::ReadConfigValue(ZephyrConfig::kCounterKey_TotalOperationalHours, totalOperationalHours);
}

CHIP_ERROR ConfigurationManagerImpl::StoreTotalOperationalHours(uint32_t totalOperationalHours)
{
return ZephyrConfig::WriteConfigValue(ZephyrConfig::kCounterKey_TotalOperationalHours, totalOperationalHours);
}

void ConfigurationManagerImpl::InitiateFactoryReset()
{
PlatformMgr().ScheduleWork(DoFactoryReset);
Expand Down
2 changes: 2 additions & 0 deletions src/platform/Zephyr/ConfigurationManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class ConfigurationManagerImpl : public Internal::GenericConfigurationManagerImp
public:
CHIP_ERROR GetRebootCount(uint32_t & rebootCount) override;
CHIP_ERROR StoreRebootCount(uint32_t rebootCount) override;
CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override;
CHIP_ERROR StoreTotalOperationalHours(uint32_t totalOperationalHours) override;
// This returns an instance of this class.
static ConfigurationManagerImpl & GetDefaultInstance();

Expand Down
31 changes: 31 additions & 0 deletions src/platform/Zephyr/DiagnosticDataProviderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,37 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetRebootCount(uint16_t & rebootCount)
return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetUpTime(uint64_t & upTime)
{
System::Clock::Timestamp currentTime = System::SystemClock().GetMonotonicTimestamp();
System::Clock::Timestamp startTime = PlatformMgrImpl().GetStartTime();

if (currentTime >= startTime)
{
upTime = std::chrono::duration_cast<System::Clock::Seconds64>(currentTime - startTime).count();
return CHIP_NO_ERROR;
}

return CHIP_ERROR_INVALID_TIME;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours)
{
uint64_t upTimeS;

ReturnErrorOnFailure(GetUpTime(upTimeS));

uint32_t totalHours = 0;
const uint32_t upTimeH = upTimeS / 3600 < UINT32_MAX ? static_cast<uint32_t>(upTimeS / 3600) : UINT32_MAX;
const uint32_t deltaTime = upTimeH - PlatformMgrImpl().GetSavedOperationalHoursSinceBoot();

ReturnErrorOnFailure(ConfigurationMgr().GetTotalOperationalHours(totalHours));

totalOperationalHours = totalHours + deltaTime < UINT32_MAX ? totalHours + deltaTime : UINT32_MAX;

return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(uint8_t & bootReason)
{
#if CONFIG_HWINFO
Expand Down
2 changes: 2 additions & 0 deletions src/platform/Zephyr/DiagnosticDataProviderImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class DiagnosticDataProviderImpl : public DiagnosticDataProvider
CHIP_ERROR GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) override;

CHIP_ERROR GetRebootCount(uint16_t & rebootCount) override;
CHIP_ERROR GetUpTime(uint64_t & upTime) override;
CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override;
CHIP_ERROR GetBootReason(uint8_t & bootReason) override;
CHIP_ERROR GetNetworkInterfaces(NetworkInterface ** netifpp) override;
void ReleaseNetworkInterfaces(NetworkInterface * netifp) override;
Expand Down
50 changes: 50 additions & 0 deletions src/platform/Zephyr/PlatformManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ static K_THREAD_STACK_DEFINE(sChipThreadStack, CHIP_DEVICE_CONFIG_CHIP_TASK_STAC

PlatformManagerImpl PlatformManagerImpl::sInstance{ sChipThreadStack };

static k_timer sOperationalHoursSavingTimer;

#if !CONFIG_NORDIC_SECURITY_BACKEND
static int app_entropy_source(void * data, unsigned char * output, size_t len, size_t * olen)
{
Expand All @@ -61,6 +63,36 @@ static int app_entropy_source(void * data, unsigned char * output, size_t len, s
}
#endif // !CONFIG_NORDIC_SECURITY_BACKEND

void PlatformManagerImpl::OperationalHoursSavingTimerEventHandler(k_timer * timer)
{
PlatformMgr().ScheduleWork(UpdateOperationalHours);
}

void PlatformManagerImpl::UpdateOperationalHours(intptr_t arg)
{
uint64_t upTimeS;

if (GetDiagnosticDataProvider().GetUpTime(upTimeS) != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Failed to get up time of the node");
return;
}

uint32_t totalOperationalHours = 0;
const uint32_t upTimeH = upTimeS / 3600 < UINT32_MAX ? static_cast<uint32_t>(upTimeS / 3600) : UINT32_MAX;
const uint32_t deltaTime = upTimeH - sInstance.mSavedOperationalHoursSinceBoot;

if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR)
{
ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + deltaTime);
sInstance.mSavedOperationalHoursSinceBoot = upTimeH;
}
else
{
ChipLogError(DeviceLayer, "Failed to get total operational hours of the node");
}
}

CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
{
CHIP_ERROR err;
Expand All @@ -86,9 +118,27 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
err = Internal::GenericPlatformManagerImpl_Zephyr<PlatformManagerImpl>::_InitChipStack();
SuccessOrExit(err);

// Start the timer to periodically save node operational hours.
k_timer_init(&sOperationalHoursSavingTimer, &PlatformManagerImpl::OperationalHoursSavingTimerEventHandler, nullptr);
k_timer_user_data_set(&sOperationalHoursSavingTimer, this);
k_timer_start(&sOperationalHoursSavingTimer, K_HOURS(CONFIG_CHIP_OPERATIONAL_TIME_SAVE_INTERVAL),
K_HOURS(CONFIG_CHIP_OPERATIONAL_TIME_SAVE_INTERVAL));

ScheduleWork(OnDeviceBoot, 0);

exit:
return err;
}

void PlatformManagerImpl::OnDeviceBoot(intptr_t arg)
{
GeneralDiagnosticsDelegate * generalDiagnosticsDelegate = GetDiagnosticDataProvider().GetGeneralDiagnosticsDelegate();

if (generalDiagnosticsDelegate)
{
generalDiagnosticsDelegate->OnDeviceRebooted();
}
}

} // namespace DeviceLayer
} // namespace chip
14 changes: 11 additions & 3 deletions src/platform/Zephyr/PlatformManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace chip {
namespace DeviceLayer {

/**
* Concrete implementation of the PlatformManager singleton object for the nRF Connect SDK platforms.
* Concrete implementation of the PlatformManager singleton object for the Zephyr platforms.
*/
class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl_Zephyr<PlatformManagerImpl>
{
Expand All @@ -46,19 +46,27 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener
public:
// ===== Platform-specific members that may be accessed directly by the application.

/* none so far */
System::Clock::Timestamp GetStartTime() { return mStartTime; }
uint32_t GetSavedOperationalHoursSinceBoot() { return mSavedOperationalHoursSinceBoot; }

private:
// ===== Methods that implement the PlatformManager abstract interface.

CHIP_ERROR _InitChipStack(void);

static void OperationalHoursSavingTimerEventHandler(k_timer * timer);
static void UpdateOperationalHours(intptr_t arg);
static void OnDeviceBoot(intptr_t arg);

// ===== Members for internal use by the following friends.

friend PlatformManager & PlatformMgr(void);
friend PlatformManagerImpl & PlatformMgrImpl(void);
friend class Internal::BLEManagerImpl;

System::Clock::Timestamp mStartTime = System::Clock::kZero;
uint32_t mSavedOperationalHoursSinceBoot = 0;

explicit PlatformManagerImpl(ThreadStack & stack) : Internal::GenericPlatformManagerImpl_Zephyr<PlatformManagerImpl>(stack) {}

static PlatformManagerImpl sInstance;
Expand All @@ -79,7 +87,7 @@ inline PlatformManager & PlatformMgr(void)
* Returns the platform-specific implementation of the PlatformManager singleton object.
*
* chip applications can use this to gain access to features of the PlatformManager
* that are specific to the ESP32 platform.
* that are specific to the Zephyr platform.
*/
inline PlatformManagerImpl & PlatformMgrImpl()
{
Expand Down
5 changes: 3 additions & 2 deletions src/platform/Zephyr/ZephyrConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ const ZephyrConfig::Key ZephyrConfig::kConfigKey_CountryCode = CONFIG_KEY
const ZephyrConfig::Key ZephyrConfig::kConfigKey_Breadcrumb = CONFIG_KEY(NAMESPACE_CONFIG "breadcrumb");

// Keys stored in the counters namespace
const ZephyrConfig::Key ZephyrConfig::kCounterKey_RebootCount = CONFIG_KEY(NAMESPACE_COUNTERS "reboot-count");
const ZephyrConfig::Key ZephyrConfig::kCounterKey_BootReason = CONFIG_KEY(NAMESPACE_COUNTERS "boot-reason");
const ZephyrConfig::Key ZephyrConfig::kCounterKey_RebootCount = CONFIG_KEY(NAMESPACE_COUNTERS "reboot-count");
const ZephyrConfig::Key ZephyrConfig::kCounterKey_BootReason = CONFIG_KEY(NAMESPACE_COUNTERS "boot-reason");
const ZephyrConfig::Key ZephyrConfig::kCounterKey_TotalOperationalHours = CONFIG_KEY(NAMESPACE_COUNTERS "total-operational-hours");

namespace {

Expand Down
1 change: 1 addition & 0 deletions src/platform/Zephyr/ZephyrConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class ZephyrConfig
static const Key kConfigKey_Breadcrumb;
static const Key kCounterKey_RebootCount;
static const Key kCounterKey_BootReason;
static const Key kCounterKey_TotalOperationalHours;

static CHIP_ERROR Init(void);

Expand Down

0 comments on commit 3b16dd5

Please sign in to comment.