@@ -140,21 +140,34 @@ typedef NS_ENUM(NSUInteger, MTRInternalDeviceState) {
140
140
// InitialSubscriptionEstablished means we have at some point finished setting up a
141
141
// subscription. That subscription may have dropped since then, but if so it's the ReadClient's
142
142
// responsibility to re-establish it.
143
- MTRInternalDeviceStateInitalSubscriptionEstablished = 2 ,
143
+ MTRInternalDeviceStateInitialSubscriptionEstablished = 2 ,
144
+ // Resubscribing means we had established a subscription, but then
145
+ // detected a subscription drop due to not receiving a report on time. This
146
+ // covers all the actions that happen when re-subscribing (discovery, CASE,
147
+ // getting priming reports, etc).
148
+ MTRInternalDeviceStateResubscribing = 3 ,
149
+ // LaterSubscriptionEstablished meant that we had a subscription drop and
150
+ // then re-created a subscription.
151
+ MTRInternalDeviceStateLaterSubscriptionEstablished = 4 ,
144
152
};
145
153
146
154
// Utility methods for working with MTRInternalDeviceState, located near the
147
155
// enum so it's easier to notice that they need to stay in sync.
148
156
namespace {
149
157
bool HadSubscriptionEstablishedOnce (MTRInternalDeviceState state)
150
158
{
151
- return state >= MTRInternalDeviceStateInitalSubscriptionEstablished ;
159
+ return state >= MTRInternalDeviceStateInitialSubscriptionEstablished ;
152
160
}
153
161
154
162
bool NeedToStartSubscriptionSetup (MTRInternalDeviceState state)
155
163
{
156
164
return state <= MTRInternalDeviceStateUnsubscribed;
157
165
}
166
+
167
+ bool HaveSubscriptionEstablishedRightNow (MTRInternalDeviceState state)
168
+ {
169
+ return state == MTRInternalDeviceStateInitialSubscriptionEstablished || state == MTRInternalDeviceStateLaterSubscriptionEstablished;
170
+ }
158
171
} // anonymous namespace
159
172
160
173
typedef NS_ENUM (NSUInteger , MTRDeviceExpectedValueFieldIndex) {
@@ -878,6 +891,16 @@ - (void)_changeState:(MTRDeviceState)state
878
891
}
879
892
}
880
893
894
+ - (void )_changeInternalState : (MTRInternalDeviceState)state
895
+ {
896
+ os_unfair_lock_assert_owner (&self->_lock );
897
+ MTRInternalDeviceState lastState = _internalDeviceState;
898
+ _internalDeviceState = state;
899
+ if (lastState != state) {
900
+ MTR_LOG_DEFAULT (" %@ internal state change %lu => %lu" , self, static_cast <unsigned long >(lastState), static_cast <unsigned long >(state));
901
+ }
902
+ }
903
+
881
904
// First Time Sync happens 2 minutes after reachability (this can be changed in the future)
882
905
#define MTR_DEVICE_TIME_UPDATE_INITIAL_WAIT_TIME_SEC (60 * 2 )
883
906
- (void )_handleSubscriptionEstablished
@@ -886,7 +909,11 @@ - (void)_handleSubscriptionEstablished
886
909
887
910
// reset subscription attempt wait time when subscription succeeds
888
911
_lastSubscriptionAttemptWait = 0 ;
889
- _internalDeviceState = MTRInternalDeviceStateInitalSubscriptionEstablished;
912
+ if (HadSubscriptionEstablishedOnce (_internalDeviceState)) {
913
+ [self _changeInternalState: MTRInternalDeviceStateLaterSubscriptionEstablished];
914
+ } else {
915
+ [self _changeInternalState: MTRInternalDeviceStateInitialSubscriptionEstablished];
916
+ }
890
917
891
918
// As subscription is established, check if the delegate needs to be informed
892
919
if (!_delegateDeviceCachePrimedCalled) {
@@ -913,7 +940,7 @@ - (void)_handleSubscriptionError:(NSError *)error
913
940
{
914
941
std::lock_guard lock (_lock);
915
942
916
- _internalDeviceState = MTRInternalDeviceStateUnsubscribed;
943
+ [ self _changeInternalState: MTRInternalDeviceStateUnsubscribed] ;
917
944
_unreportedEvents = nil ;
918
945
919
946
[self _changeState: MTRDeviceStateUnreachable];
@@ -924,6 +951,7 @@ - (void)_handleResubscriptionNeeded
924
951
std::lock_guard lock (_lock);
925
952
926
953
[self _changeState: MTRDeviceStateUnknown];
954
+ [self _changeInternalState: MTRInternalDeviceStateResubscribing];
927
955
928
956
// If we are here, then the ReadClient either just detected a subscription
929
957
// drop or just tried again and failed. Either way, count it as "tried and
@@ -1044,11 +1072,12 @@ - (void)_handleReportBegin
1044
1072
1045
1073
_receivingReport = YES ;
1046
1074
if (_state != MTRDeviceStateReachable) {
1047
- _receivingPrimingReport = YES ;
1048
1075
[self _changeState: MTRDeviceStateReachable];
1049
- } else {
1050
- _receivingPrimingReport = NO ;
1051
1076
}
1077
+
1078
+ // If we currently don't have an established subscription, this must be a
1079
+ // priming report.
1080
+ _receivingPrimingReport = !HaveSubscriptionEstablishedRightNow (_internalDeviceState);
1052
1081
}
1053
1082
1054
1083
- (NSDictionary <MTRClusterPath *, MTRDeviceClusterData *> *)_clusterDataToPersistSnapshot
@@ -1461,7 +1490,7 @@ - (void)_setupSubscription
1461
1490
return ;
1462
1491
}
1463
1492
1464
- _internalDeviceState = MTRInternalDeviceStateSubscribing;
1493
+ [ self _changeInternalState: MTRInternalDeviceStateSubscribing] ;
1465
1494
1466
1495
// Set up a timer to mark as not reachable if it takes too long to set up a subscription
1467
1496
MTRWeakReference<MTRDevice *> * weakSelf = [MTRWeakReference weakReferenceWithObject: self ];
0 commit comments