34
34
#include < app/util/endpoint-config-api.h>
35
35
#include < lib/core/TLVUtilities.h>
36
36
#include < lib/support/CodeUtils.h>
37
+ #include < lib/support/FibonacciUtils.h>
37
38
38
39
namespace chip {
39
40
namespace app {
@@ -324,6 +325,17 @@ void InteractionModelEngine::OnDone(ReadHandler & apReadObj)
324
325
mReportingEngine .ResetReadHandlerTracker (&apReadObj);
325
326
326
327
mReadHandlers .ReleaseObject (&apReadObj);
328
+
329
+ #if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
330
+ if (!mSubscriptionResumptionScheduled && HasSubscriptionsToResume ())
331
+ {
332
+ mSubscriptionResumptionScheduled = true ;
333
+ auto timeTillNextResubscriptionSecs = ComputeTimeSecondsTillNextSubscriptionResumption ();
334
+ mpExchangeMgr->GetSessionManager ()->SystemLayer ()->StartTimer (System::Clock::Seconds32 (timeTillNextResubscriptionSecs),
335
+ ResumeSubscriptionsTimerCallback, this );
336
+ mNumSubscriptionResumptionRetries ++;
337
+ }
338
+ #endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
327
339
}
328
340
329
341
Status InteractionModelEngine::OnInvokeCommandRequest (Messaging::ExchangeContext * apExchangeContext,
@@ -1752,6 +1764,9 @@ CHIP_ERROR InteractionModelEngine::ResumeSubscriptions()
1752
1764
{
1753
1765
#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
1754
1766
ReturnErrorCodeIf (!mpSubscriptionResumptionStorage, CHIP_NO_ERROR);
1767
+ #if CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1768
+ ReturnErrorCodeIf (mSubscriptionResumptionScheduled , CHIP_NO_ERROR);
1769
+ #endif
1755
1770
1756
1771
// To avoid the case of a reboot loop causing rapid traffic generation / power consumption, subscription resumption should make
1757
1772
// use of the persisted min-interval values, and wait before resumption. Ideally, each persisted subscription should wait their
@@ -1776,6 +1791,9 @@ CHIP_ERROR InteractionModelEngine::ResumeSubscriptions()
1776
1791
1777
1792
if (subscriptionsToResume)
1778
1793
{
1794
+ #if CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1795
+ mSubscriptionResumptionScheduled = true ;
1796
+ #endif
1779
1797
ChipLogProgress (InteractionModel, " Resuming %d subscriptions in %u seconds" , subscriptionsToResume, minInterval);
1780
1798
ReturnErrorOnFailure (mpExchangeMgr->GetSessionManager ()->SystemLayer ()->StartTimer (System::Clock::Seconds16 (minInterval),
1781
1799
ResumeSubscriptionsTimerCallback, this ));
@@ -1794,6 +1812,10 @@ void InteractionModelEngine::ResumeSubscriptionsTimerCallback(System::Layer * ap
1794
1812
#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
1795
1813
VerifyOrReturn (apAppState != nullptr );
1796
1814
InteractionModelEngine * imEngine = static_cast <InteractionModelEngine *>(apAppState);
1815
+ #if CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1816
+ imEngine->mSubscriptionResumptionScheduled = false ;
1817
+ bool resumedSubscriptions = false ;
1818
+ #endif // CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1797
1819
SubscriptionResumptionStorage::SubscriptionInfo subscriptionInfo;
1798
1820
auto * iterator = imEngine->mpSubscriptionResumptionStorage ->IterateSubscriptions ();
1799
1821
while (iterator->Next (subscriptionInfo))
@@ -1833,10 +1855,67 @@ void InteractionModelEngine::ResumeSubscriptionsTimerCallback(System::Layer * ap
1833
1855
1834
1856
ChipLogProgress (InteractionModel, " Resuming subscriptionId %" PRIu32, subscriptionInfo.mSubscriptionId );
1835
1857
handler->ResumeSubscription (*imEngine->mpCASESessionMgr , subscriptionInfo);
1858
+ #if CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1859
+ resumedSubscriptions = true ;
1860
+ #endif // CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1836
1861
}
1837
1862
iterator->Release ();
1863
+
1864
+ #if CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1865
+ // If no persisted subscriptions needed resumption then all resumption retries are done
1866
+ if (!resumedSubscriptions)
1867
+ {
1868
+ imEngine->mNumSubscriptionResumptionRetries = 0 ;
1869
+ }
1870
+ #endif // CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1871
+
1838
1872
#endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
1839
1873
}
1840
1874
1875
+ #if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1876
+ uint32_t InteractionModelEngine::ComputeTimeSecondsTillNextSubscriptionResumption ()
1877
+ {
1878
+ if (mNumSubscriptionResumptionRetries > CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION_MAX_FIBONACCI_STEP_INDEX)
1879
+ {
1880
+ return CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION_MAX_RETRY_INTERVAL_SECS;
1881
+ }
1882
+
1883
+ return CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION_MIN_RETRY_INTERVAL_SECS +
1884
+ GetFibonacciForIndex (mNumSubscriptionResumptionRetries ) *
1885
+ CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION_WAIT_TIME_MULTIPLIER_SECS;
1886
+ }
1887
+
1888
+ bool InteractionModelEngine::HasSubscriptionsToResume ()
1889
+ {
1890
+ VerifyOrReturnValue (mpSubscriptionResumptionStorage != nullptr , false );
1891
+
1892
+ // Look through persisted subscriptions and see if any aren't already in mReadHandlers pool
1893
+ SubscriptionResumptionStorage::SubscriptionInfo subscriptionInfo;
1894
+ auto * iterator = mpSubscriptionResumptionStorage->IterateSubscriptions ();
1895
+ bool foundSubscriptionToResume = false ;
1896
+ while (iterator->Next (subscriptionInfo))
1897
+ {
1898
+ if (Loop::Break == mReadHandlers .ForEachActiveObject ([&](ReadHandler * handler) {
1899
+ SubscriptionId subscriptionId;
1900
+ handler->GetSubscriptionId (subscriptionId);
1901
+ if (subscriptionId == subscriptionInfo.mSubscriptionId )
1902
+ {
1903
+ return Loop::Break;
1904
+ }
1905
+ return Loop::Continue;
1906
+ }))
1907
+ {
1908
+ continue ;
1909
+ }
1910
+
1911
+ foundSubscriptionToResume = true ;
1912
+ break ;
1913
+ }
1914
+ iterator->Release ();
1915
+
1916
+ return foundSubscriptionToResume;
1917
+ }
1918
+ #endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1919
+
1841
1920
} // namespace app
1842
1921
} // namespace chip
0 commit comments