diff --git a/src/include/platform/internal/GenericPlatformManagerImpl.cpp b/src/include/platform/internal/GenericPlatformManagerImpl.cpp index 7b33ba61a09fd5..6272f169ff0ab7 100644 --- a/src/include/platform/internal/GenericPlatformManagerImpl.cpp +++ b/src/include/platform/internal/GenericPlatformManagerImpl.cpp @@ -123,10 +123,7 @@ CHIP_ERROR GenericPlatformManagerImpl::_InitChipStack() // TODO Initialize the Software Update Manager object. - // TODO: Attempt to diagnose Darwin CI, REMOVE ONCE FIXED -#if !CHIP_DEVICE_LAYER_TARGET_DARWIN _ScheduleWork(HandleDeviceRebooted, 0); -#endif exit: return err; diff --git a/src/platform/Darwin/ConfigurationManagerImpl.cpp b/src/platform/Darwin/ConfigurationManagerImpl.cpp index 7aa55b39bf5270..c4b5aa5b556a91 100644 --- a/src/platform/Darwin/ConfigurationManagerImpl.cpp +++ b/src/platform/Darwin/ConfigurationManagerImpl.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -137,14 +138,44 @@ ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance() CHIP_ERROR ConfigurationManagerImpl::Init() { - CHIP_ERROR err; - // Initialize the generic implementation base class. - err = Internal::GenericConfigurationManagerImpl::Init(); - SuccessOrExit(err); + ReturnErrorOnFailure(Internal::GenericConfigurationManagerImpl::Init()); -exit: - return err; + uint32_t rebootCount; + if (!PosixConfig::ConfigValueExists(PosixConfig::kCounterKey_RebootCount)) + { + // The first boot after factory reset of the Node. + ReturnErrorOnFailure(StoreRebootCount(1)); + } + else + { + ReturnErrorOnFailure(GetRebootCount(rebootCount)); + ReturnErrorOnFailure(StoreRebootCount(rebootCount + 1)); + } + + if (!PosixConfig::ConfigValueExists(PosixConfig::kCounterKey_TotalOperationalHours)) + { + ReturnErrorOnFailure(StoreTotalOperationalHours(0)); + } + + if (!PosixConfig::ConfigValueExists(PosixConfig::kCounterKey_BootReason)) + { + ReturnErrorOnFailure(StoreBootReason(DiagnosticDataProvider::BootReasonType::Unspecified)); + } + + if (!PosixConfig::ConfigValueExists(PosixConfig::kConfigKey_RegulatoryLocation)) + { + uint32_t location = to_underlying(chip::app::Clusters::GeneralCommissioning::RegulatoryLocationType::kIndoor); + ReturnErrorOnFailure(WriteConfigValue(PosixConfig::kConfigKey_RegulatoryLocation, location)); + } + + if (!PosixConfig::ConfigValueExists(PosixConfig::kConfigKey_LocationCapability)) + { + uint32_t location = to_underlying(chip::app::Clusters::GeneralCommissioning::RegulatoryLocationType::kIndoor); + ReturnErrorOnFailure(WriteConfigValue(PosixConfig::kConfigKey_LocationCapability, location)); + } + + return CHIP_NO_ERROR; } CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf) @@ -176,6 +207,66 @@ void ConfigurationManagerImpl::InitiateFactoryReset() ChipLogError(DeviceLayer, "InitiateFactoryReset not implemented"); } +CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount) +{ + return ReadConfigValue(PosixConfig::kCounterKey_RebootCount, rebootCount); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreRebootCount(uint32_t rebootCount) +{ + return WriteConfigValue(PosixConfig::kCounterKey_RebootCount, rebootCount); +} + +CHIP_ERROR ConfigurationManagerImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours) +{ + return ReadConfigValue(PosixConfig::kCounterKey_TotalOperationalHours, totalOperationalHours); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreTotalOperationalHours(uint32_t totalOperationalHours) +{ + return WriteConfigValue(PosixConfig::kCounterKey_TotalOperationalHours, totalOperationalHours); +} + +CHIP_ERROR ConfigurationManagerImpl::GetBootReason(uint32_t & bootReason) +{ + return ReadConfigValue(PosixConfig::kCounterKey_BootReason, bootReason); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreBootReason(uint32_t bootReason) +{ + return WriteConfigValue(PosixConfig::kCounterKey_BootReason, bootReason); +} + +CHIP_ERROR ConfigurationManagerImpl::GetRegulatoryLocation(uint8_t & location) +{ + uint32_t value = 0; + + CHIP_ERROR err = ReadConfigValue(PosixConfig::kConfigKey_RegulatoryLocation, value); + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(value <= UINT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + location = static_cast(value); + } + + return err; +} + +CHIP_ERROR ConfigurationManagerImpl::GetLocationCapability(uint8_t & location) +{ + uint32_t value = 0; + + CHIP_ERROR err = ReadConfigValue(PosixConfig::kConfigKey_LocationCapability, value); + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(value <= UINT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + location = static_cast(value); + } + + return err; +} + CHIP_ERROR ConfigurationManagerImpl::ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value) { PosixConfig::Key configKey{ PosixConfig::kConfigNamespace_ChipCounters, key }; diff --git a/src/platform/Darwin/ConfigurationManagerImpl.h b/src/platform/Darwin/ConfigurationManagerImpl.h index 23848ff0bd3cca..86728c4e2c6e8f 100644 --- a/src/platform/Darwin/ConfigurationManagerImpl.h +++ b/src/platform/Darwin/ConfigurationManagerImpl.h @@ -48,6 +48,14 @@ class ConfigurationManagerImpl : public Internal::GenericConfigurationManagerImp CHIP_ERROR GetPrimaryWiFiMACAddress(uint8_t * buf) override; bool CanFactoryReset(void) override; void InitiateFactoryReset(void) override; + 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; + CHIP_ERROR GetBootReason(uint32_t & bootReason) override; + CHIP_ERROR StoreBootReason(uint32_t bootReason) override; + CHIP_ERROR GetRegulatoryLocation(uint8_t & location) override; + CHIP_ERROR GetLocationCapability(uint8_t & location) override; CHIP_ERROR ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value) override; CHIP_ERROR WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) override; diff --git a/src/platform/Darwin/DiagnosticDataProviderImpl.cpp b/src/platform/Darwin/DiagnosticDataProviderImpl.cpp index e62a7a397cc003..e0cb4364cfa4c1 100644 --- a/src/platform/Darwin/DiagnosticDataProviderImpl.cpp +++ b/src/platform/Darwin/DiagnosticDataProviderImpl.cpp @@ -36,5 +36,37 @@ DiagnosticDataProviderImpl & DiagnosticDataProviderImpl::GetDefaultInstance() return sInstance; } +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(currentTime - startTime).count(); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_INVALID_TIME; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours) +{ + uint64_t upTime = 0; + + if (GetUpTime(upTime) == CHIP_NO_ERROR) + { + uint32_t totalHours = 0; + if (ConfigurationMgr().GetTotalOperationalHours(totalHours) == CHIP_NO_ERROR) + { + VerifyOrReturnError(upTime / 3600 <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE); + totalOperationalHours = totalHours + static_cast(upTime / 3600); + return CHIP_NO_ERROR; + } + } + + return CHIP_ERROR_INVALID_TIME; +} + } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Darwin/DiagnosticDataProviderImpl.h b/src/platform/Darwin/DiagnosticDataProviderImpl.h index 731f445fec8671..1651779c2ccd61 100644 --- a/src/platform/Darwin/DiagnosticDataProviderImpl.h +++ b/src/platform/Darwin/DiagnosticDataProviderImpl.h @@ -34,6 +34,10 @@ class DiagnosticDataProviderImpl : public DiagnosticDataProvider { public: static DiagnosticDataProviderImpl & GetDefaultInstance(); + + // ===== Methods that implement the PlatformManager abstract interface. + CHIP_ERROR GetUpTime(uint64_t & upTime) override; + CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override; }; } // namespace DeviceLayer diff --git a/src/platform/Darwin/KeyValueStoreManagerImpl.mm b/src/platform/Darwin/KeyValueStoreManagerImpl.mm index b7005aa4c1bf36..00519e0adacd60 100644 --- a/src/platform/Darwin/KeyValueStoreManagerImpl.mm +++ b/src/platform/Darwin/KeyValueStoreManagerImpl.mm @@ -201,6 +201,7 @@ - (instancetype)initWithContext:(nonnull NSManagedObjectContext *)context key:(n // create Managed Object context gContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; + [gContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy]; [gContext setPersistentStoreCoordinator:coordinator]; mInitialized = true; diff --git a/src/platform/Darwin/PlatformManagerImpl.cpp b/src/platform/Darwin/PlatformManagerImpl.cpp index 1a162727b90f72..631ed38f63bf86 100644 --- a/src/platform/Darwin/PlatformManagerImpl.cpp +++ b/src/platform/Darwin/PlatformManagerImpl.cpp @@ -49,11 +49,16 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack() mRunLoopSem = dispatch_semaphore_create(0); + // Ensure there is a dispatch queue available + GetWorkQueue(); + // Call _InitChipStack() on the generic implementation base class // to finish the initialization process. err = Internal::GenericPlatformManagerImpl::_InitChipStack(); SuccessOrExit(err); + mStartTime = System::SystemClock().GetMonotonicTimestamp(); + static_cast(DeviceLayer::SystemLayer()).SetDispatchQueue(GetWorkQueue()); exit: @@ -119,6 +124,11 @@ CHIP_ERROR PlatformManagerImpl::_Shutdown() CHIP_ERROR PlatformManagerImpl::_PostEvent(const ChipDeviceEvent * event) { + if (mWorkQueue == nullptr) + { + return CHIP_ERROR_INCORRECT_STATE; + } + const ChipDeviceEvent eventCopy = *event; dispatch_async(mWorkQueue, ^{ Impl()->DispatchEvent(&eventCopy); diff --git a/src/platform/Darwin/PlatformManagerImpl.h b/src/platform/Darwin/PlatformManagerImpl.h index ec2d32590dbd56..fcac77a86535fe 100644 --- a/src/platform/Darwin/PlatformManagerImpl.h +++ b/src/platform/Darwin/PlatformManagerImpl.h @@ -53,6 +53,8 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener return mWorkQueue; } + System::Clock::Timestamp GetStartTime() { return mStartTime; } + private: // ===== Methods that implement the PlatformManager abstract interface. CHIP_ERROR _InitChipStack(); @@ -86,6 +88,8 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener static PlatformManagerImpl sInstance; + System::Clock::Timestamp mStartTime = System::Clock::kZero; + dispatch_queue_t mWorkQueue = nullptr; // Semaphore used to implement blocking behavior in _RunEventLoop. dispatch_semaphore_t mRunLoopSem;