[zephyr] Added support for few GeneralDiagnostics attributes (#13160)
Platform doesn't support a few optional attributes and also
mandatory BootReason event.
* Added support for attributes: UpTime, TotalOperationalHours
* Added support for event: BootReason
diff --git a/config/zephyr/Kconfig b/config/zephyr/Kconfig
index 63b9e72..b3404c5 100644
--- a/config/zephyr/Kconfig
+++ b/config/zephyr/Kconfig
@@ -108,6 +108,16 @@
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
diff --git a/src/platform/Zephyr/ConfigurationManagerImpl.cpp b/src/platform/Zephyr/ConfigurationManagerImpl.cpp
index 7c4f7ab..65f95d9 100644
--- a/src/platform/Zephyr/ConfigurationManagerImpl.cpp
+++ b/src/platform/Zephyr/ConfigurationManagerImpl.cpp
@@ -111,6 +111,22 @@
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);
diff --git a/src/platform/Zephyr/ConfigurationManagerImpl.h b/src/platform/Zephyr/ConfigurationManagerImpl.h
index bcca062..44d66d3 100644
--- a/src/platform/Zephyr/ConfigurationManagerImpl.h
+++ b/src/platform/Zephyr/ConfigurationManagerImpl.h
@@ -38,6 +38,8 @@
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();
diff --git a/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp b/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp
index e627bb5..44fad86 100644
--- a/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp
+++ b/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp
@@ -90,6 +90,37 @@
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));
+
+ uint64_t totalHours = 0;
+ const uint32_t upTimeH = upTimeS / 3600 < UINT32_MAX ? static_cast<uint32_t>(upTimeS / 3600) : UINT32_MAX;
+ const uint64_t deltaTime = upTimeH - PlatformMgrImpl().GetSavedOperationalHoursSinceBoot();
+
+ ReturnErrorOnFailure(ConfigurationMgr().GetTotalOperationalHours(reinterpret_cast<uint32_t &>(totalHours)));
+
+ totalOperationalHours = totalHours + deltaTime < UINT32_MAX ? totalHours + deltaTime : UINT32_MAX;
+
+ return CHIP_NO_ERROR;
+}
+
CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(uint8_t & bootReason)
{
#if CONFIG_HWINFO
diff --git a/src/platform/Zephyr/DiagnosticDataProviderImpl.h b/src/platform/Zephyr/DiagnosticDataProviderImpl.h
index 36eeef6..05687dc 100644
--- a/src/platform/Zephyr/DiagnosticDataProviderImpl.h
+++ b/src/platform/Zephyr/DiagnosticDataProviderImpl.h
@@ -44,6 +44,8 @@
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;
diff --git a/src/platform/Zephyr/PlatformManagerImpl.cpp b/src/platform/Zephyr/PlatformManagerImpl.cpp
index 1efda50..f730e10 100644
--- a/src/platform/Zephyr/PlatformManagerImpl.cpp
+++ b/src/platform/Zephyr/PlatformManagerImpl.cpp
@@ -42,6 +42,8 @@
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)
{
@@ -61,6 +63,37 @@
}
#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;
+ }
+
+ uint64_t totalOperationalHours = 0;
+ const uint32_t upTimeH = upTimeS / 3600 < UINT32_MAX ? static_cast<uint32_t>(upTimeS / 3600) : UINT32_MAX;
+ const uint64_t deltaTime = upTimeH - sInstance.mSavedOperationalHoursSinceBoot;
+
+ if (ConfigurationMgr().GetTotalOperationalHours(reinterpret_cast<uint32_t &>(totalOperationalHours)) == CHIP_NO_ERROR)
+ {
+ ConfigurationMgr().StoreTotalOperationalHours(
+ totalOperationalHours + deltaTime < UINT32_MAX ? totalOperationalHours + deltaTime : UINT32_MAX);
+ sInstance.mSavedOperationalHoursSinceBoot = upTimeH;
+ }
+ else
+ {
+ ChipLogError(DeviceLayer, "Failed to get total operational hours of the node");
+ }
+}
+
CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
{
CHIP_ERROR err;
@@ -86,9 +119,27 @@
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
diff --git a/src/platform/Zephyr/PlatformManagerImpl.h b/src/platform/Zephyr/PlatformManagerImpl.h
index cdc9240..a4bb23f 100644
--- a/src/platform/Zephyr/PlatformManagerImpl.h
+++ b/src/platform/Zephyr/PlatformManagerImpl.h
@@ -29,7 +29,7 @@
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>
{
@@ -46,19 +46,27 @@
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;
@@ -79,7 +87,7 @@
* 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()
{
diff --git a/src/platform/Zephyr/ZephyrConfig.cpp b/src/platform/Zephyr/ZephyrConfig.cpp
index 9bdbccb..395d637 100644
--- a/src/platform/Zephyr/ZephyrConfig.cpp
+++ b/src/platform/Zephyr/ZephyrConfig.cpp
@@ -73,8 +73,9 @@
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 {
diff --git a/src/platform/Zephyr/ZephyrConfig.h b/src/platform/Zephyr/ZephyrConfig.h
index a43d3bf..f6a1b23 100644
--- a/src/platform/Zephyr/ZephyrConfig.h
+++ b/src/platform/Zephyr/ZephyrConfig.h
@@ -65,6 +65,7 @@
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);