@@ -336,6 +336,9 @@ @interface MTRDevice_Concrete ()
336
336
@property (nonatomic ) NSDate * lastDeviceBecameActiveCallbackTime;
337
337
@property (nonatomic ) BOOL throttlingDeviceBecameActiveCallbacks;
338
338
339
+ // Keep track of the last time we received subscription related communication from the device
340
+ @property (nonatomic , nullable ) NSDate * lastSubscriptionActiveTime;
341
+
339
342
/* *
340
343
* If currentReadClient is non-null, that means that we successfully
341
344
* called SendAutoResubscribeRequest on the ReadClient and have not yet gotten
@@ -360,6 +363,7 @@ - (void)unitTestSubscriptionPoolWorkComplete:(MTRDevice *)device;
360
363
- (void )unitTestClusterDataPersisted : (MTRDevice *)device ;
361
364
- (BOOL )unitTestSuppressTimeBasedReachabilityChanges : (MTRDevice *)device ;
362
365
- (void )unitTestSubscriptionCallbackDeleteForDevice : (MTRDevice *)device ;
366
+ - (void )unitTestSubscriptionResetForDevice : (MTRDevice *)device ;
363
367
@end
364
368
#endif
365
369
@@ -2669,6 +2673,14 @@ - (void)_resetSubscription
2669
2673
[self .matterCPPObjectsHolder clearReadClientAndDeleteSubscriptionCallback ];
2670
2674
2671
2675
[self _doHandleSubscriptionError: nil ];
2676
+
2677
+ #ifdef DEBUG
2678
+ [self _callFirstDelegateSynchronouslyWithBlock: ^(id testDelegate) {
2679
+ if ([testDelegate respondsToSelector: @selector (unitTestSubscriptionResetForDevice: )]) {
2680
+ [testDelegate unitTestSubscriptionResetForDevice: self ];
2681
+ }
2682
+ }];
2683
+ #endif
2672
2684
}
2673
2685
2674
2686
#ifdef DEBUG
@@ -2774,6 +2786,10 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason
2774
2786
^(NSArray * value) {
2775
2787
mtr_strongify (self);
2776
2788
VerifyOrReturn (self, MTR_LOG_DEBUG (" _setupSubscriptionWithReason subscription attribute report called back with nil MTRDevice" ));
2789
+ {
2790
+ std::lock_guard lock (self->_lock );
2791
+ self.lastSubscriptionActiveTime = [NSDate now ];
2792
+ }
2777
2793
2778
2794
MTR_LOG (" %@ got attribute report (%p) %@" , self, value, value);
2779
2795
dispatch_async (self.queue , ^{
@@ -2790,6 +2806,10 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason
2790
2806
^(NSArray * value) {
2791
2807
mtr_strongify (self);
2792
2808
VerifyOrReturn (self, MTR_LOG_DEBUG (" _setupSubscriptionWithReason subscription event report called back with nil MTRDevice" ));
2809
+ {
2810
+ std::lock_guard lock (self->_lock );
2811
+ self.lastSubscriptionActiveTime = [NSDate now ];
2812
+ }
2793
2813
2794
2814
MTR_LOG (" %@ got event report %@" , self, value);
2795
2815
dispatch_async (self.queue , ^{
@@ -2822,6 +2842,7 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason
2822
2842
2823
2843
MTR_LOG (" %@ got subscription established" , self);
2824
2844
std::lock_guard lock (self->_lock );
2845
+ self.lastSubscriptionActiveTime = [NSDate now ];
2825
2846
2826
2847
// First synchronously change state
2827
2848
if (HadSubscriptionEstablishedOnce (self->_internalDeviceState )) {
@@ -2866,6 +2887,10 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason
2866
2887
^(void ) {
2867
2888
mtr_strongify (self);
2868
2889
VerifyOrReturn (self, MTR_LOG_DEBUG (" _setupSubscriptionWithReason subscription report begin called back with nil MTRDevice" ));
2890
+ {
2891
+ std::lock_guard lock (self->_lock );
2892
+ self.lastSubscriptionActiveTime = [NSDate now ];
2893
+ }
2869
2894
2870
2895
MTR_LOG (" %@ got report begin" , self);
2871
2896
[self _handleReportBegin ];
@@ -4723,8 +4748,23 @@ - (BOOL)_deviceHasActiveSubscription
4723
4748
return HaveSubscriptionEstablishedRightNow (_internalDeviceState);
4724
4749
}
4725
4750
4751
+ // TODO: make this configurable - for now use 1.5 second
4752
+ #define MTRDEVICE_ACTIVE_COMMUNICATION_THRESHOLD_SECONDS (1.5 )
4753
+
4726
4754
- (void )_deviceMayBeReachable
4727
4755
{
4756
+ // Ignore this call if actively receiving communication from this device
4757
+ {
4758
+ std::lock_guard lock (self->_lock );
4759
+ if (self.lastSubscriptionActiveTime ) {
4760
+ NSTimeInterval intervalSinceDeviceLastActive = -[self .lastSubscriptionActiveTime timeIntervalSinceNow ];
4761
+ if (intervalSinceDeviceLastActive < MTRDEVICE_ACTIVE_COMMUNICATION_THRESHOLD_SECONDS) {
4762
+ MTR_LOG (" %@ _deviceMayBeReachable called and ignored, because last received communication from device %.6lf seconds ago" , self, intervalSinceDeviceLastActive);
4763
+ return ;
4764
+ }
4765
+ }
4766
+ }
4767
+
4728
4768
MTR_LOG (" %@ _deviceMayBeReachable called, resetting subscription" , self);
4729
4769
// TODO: This should only be allowed for thread devices
4730
4770
mtr_weakify (self);
0 commit comments