@@ -100,15 +100,18 @@ void DeviceSubscription::OnReportEnd()
100
100
#if defined(PW_RPC_ENABLED)
101
101
AdminCommissioningAttributeChanged (mCurrentAdministratorCommissioningAttributes );
102
102
#else
103
- ChipLogError (NotSpecified, " Cannot synchronize device with fabric bridge: RPC not enabled" );
103
+ ChipLogError (NotSpecified, " Cannot forward Administrator Commissioning Attribute to fabric bridge: RPC not enabled" );
104
104
#endif
105
105
mChangeDetected = false ;
106
106
}
107
107
}
108
108
109
109
void DeviceSubscription::OnDone (ReadClient * apReadClient)
110
110
{
111
- // TODO(#35077) In follow up PR we will indicate to a manager DeviceSubscription is terminal.
111
+ // After calling mOnDoneCallback we are indicating that `this` is deleted and we shouldn't do anything else with
112
+ // DeviceSubscription.
113
+ MoveToState (State::AwaitingDestruction);
114
+ mOnDoneCallback (mCurrentAdministratorCommissioningAttributes .node_id );
112
115
}
113
116
114
117
void DeviceSubscription::OnError (CHIP_ERROR error)
@@ -118,6 +121,15 @@ void DeviceSubscription::OnError(CHIP_ERROR error)
118
121
119
122
void DeviceSubscription::OnDeviceConnected (Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle)
120
123
{
124
+ if (mState == State::Stopping)
125
+ {
126
+ // After calling mOnDoneCallback we are indicating that `this` is deleted and we shouldn't do anything else with
127
+ // DeviceSubscription.
128
+ MoveToState (State::AwaitingDestruction);
129
+ mOnDoneCallback (mCurrentAdministratorCommissioningAttributes .node_id );
130
+ return ;
131
+ }
132
+ VerifyOrDie (mState == State::Connecting);
121
133
mClient = std::make_unique<ReadClient>(app::InteractionModelEngine::GetInstance (), &exchangeMgr /* echangeMgr */ ,
122
134
*this /* callback */ , ReadClient::InteractionType::Subscribe);
123
135
VerifyOrDie (mClient );
@@ -136,25 +148,95 @@ void DeviceSubscription::OnDeviceConnected(Messaging::ExchangeManager & exchange
136
148
if (err != CHIP_NO_ERROR)
137
149
{
138
150
ChipLogError (NotSpecified, " Failed to issue subscription to AdministratorCommissioning data" );
139
- // TODO(#35077) In follow up PR we will indicate to a manager DeviceSubscription is terminal.
151
+ // After calling mOnDoneCallback we are indicating that `this` is deleted and we shouldn't do anything else with
152
+ // DeviceSubscription.
153
+ MoveToState (State::AwaitingDestruction);
154
+ mOnDoneCallback (mCurrentAdministratorCommissioningAttributes .node_id );
155
+ return ;
140
156
}
157
+ MoveToState (State::SubscriptionStarted);
158
+ }
159
+
160
+ void DeviceSubscription::MoveToState (const State aTargetState)
161
+ {
162
+ mState = aTargetState;
163
+ ChipLogDetail (NotSpecified, " DeviceSubscription moving to [%10.10s]" , GetStateStr ());
164
+ }
165
+
166
+ const char * DeviceSubscription::GetStateStr () const
167
+ {
168
+ switch (mState )
169
+ {
170
+ case State::Idle:
171
+ return " Idle" ;
172
+
173
+ case State::Connecting:
174
+ return " Connecting" ;
175
+
176
+ case State::Stopping:
177
+ return " Stopping" ;
178
+
179
+ case State::SubscriptionStarted:
180
+ return " SubscriptionStarted" ;
181
+
182
+ case State::AwaitingDestruction:
183
+ return " AwaitingDestruction" ;
184
+ }
185
+ return " N/A" ;
141
186
}
142
187
143
188
void DeviceSubscription::OnDeviceConnectionFailure (const ScopedNodeId & peerId, CHIP_ERROR error)
144
189
{
145
- ChipLogError (NotSpecified, " Device Sync failed to connect to " ChipLogFormatX64, ChipLogValueX64 (peerId.GetNodeId ()));
146
- // TODO(#35077) In follow up PR we will indicate to a manager DeviceSubscription is terminal.
190
+ VerifyOrDie (mState == State::Connecting || mState == State::Stopping);
191
+ ChipLogError (NotSpecified, " DeviceSubscription failed to connect to " ChipLogFormatX64, ChipLogValueX64 (peerId.GetNodeId ()));
192
+ // TODO(#35333) Figure out how we should recover if we fail to connect and mState == State::Connecting.
193
+
194
+ // After calling mOnDoneCallback we are indicating that `this` is deleted and we shouldn't do anything else with
195
+ // DeviceSubscription.
196
+ MoveToState (State::AwaitingDestruction);
197
+ mOnDoneCallback (mCurrentAdministratorCommissioningAttributes .node_id );
147
198
}
148
199
149
- void DeviceSubscription::StartSubscription (Controller::DeviceController & controller, NodeId nodeId)
200
+ CHIP_ERROR DeviceSubscription::StartSubscription (OnDoneCallback onDoneCallback, Controller::DeviceController & controller,
201
+ NodeId nodeId)
150
202
{
151
- VerifyOrDie (!mSubscriptionStarted );
203
+ assertChipStackLockedByCurrentThread ();
204
+ VerifyOrDie (mState == State::Idle);
152
205
153
206
mCurrentAdministratorCommissioningAttributes = chip_rpc_AdministratorCommissioningChanged_init_default;
154
207
mCurrentAdministratorCommissioningAttributes .node_id = nodeId;
155
208
mCurrentAdministratorCommissioningAttributes .window_status =
156
209
static_cast <uint32_t >(Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen );
157
- mSubscriptionStarted = true ;
210
+ mState = State::Connecting;
211
+ mOnDoneCallback = onDoneCallback;
212
+
213
+ return controller.GetConnectedDevice (nodeId, &mOnDeviceConnectedCallback , &mOnDeviceConnectionFailureCallback );
214
+ }
215
+
216
+ void DeviceSubscription::StopSubscription ()
217
+ {
218
+ assertChipStackLockedByCurrentThread ();
219
+ VerifyOrDie (mState != State::Idle);
220
+ // Something is seriously wrong if we die on the line below
221
+ VerifyOrDie (mState != State::AwaitingDestruction);
222
+
223
+ if (mState == State::Stopping)
224
+ {
225
+ // Stop is called again while we are still waiting on connected callbacks
226
+ return ;
227
+ }
228
+
229
+ if (mState == State::Connecting)
230
+ {
231
+ MoveToState (State::Stopping);
232
+ return ;
233
+ }
158
234
159
- controller.GetConnectedDevice (nodeId, &mOnDeviceConnectedCallback , &mOnDeviceConnectionFailureCallback );
235
+ // By calling reset on our ReadClient we terminate the subscription.
236
+ VerifyOrDie (mClient );
237
+ mClient .reset ();
238
+ // After calling mOnDoneCallback we are indicating that `this` is deleted and we shouldn't do anything else with
239
+ // DeviceSubscription.
240
+ MoveToState (State::AwaitingDestruction);
241
+ mOnDoneCallback (mCurrentAdministratorCommissioningAttributes .node_id );
160
242
}
0 commit comments