Skip to content

Commit f15b7d7

Browse files
committed
Replace checkCloudConnection and associated functions with an easier to read state machine
1 parent b6a1257 commit f15b7d7

File tree

2 files changed

+77
-82
lines changed

2 files changed

+77
-82
lines changed

src/ArduinoIoTCloudTCP.cpp

Lines changed: 62 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ extern "C" unsigned long getTime()
7474
******************************************************************************/
7575

7676
ArduinoIoTCloudTCP::ArduinoIoTCloudTCP()
77-
: _lastSyncRequestTickTime{0}
77+
: _state{State::ConnectMqttBroker}
78+
, _lastSyncRequestTickTime{0}
7879
, _mqtt_data_buf{0}
7980
, _mqtt_data_len{0}
8081
, _mqtt_data_request_retransmit{false}
@@ -186,7 +187,18 @@ void ArduinoIoTCloudTCP::update()
186187
#endif /* OTA_ENABLED */
187188

188189
if(checkPhyConnection() != NetworkConnectionState::CONNECTED) return;
189-
if(checkCloudConnection() != ArduinoIoTConnectionStatus::CONNECTED) return;
190+
191+
State next_state = _state;
192+
switch (_state)
193+
{
194+
case State::ConnectMqttBroker: next_state = handle_ConnectMqttBroker(); break;
195+
case State::SubscribeMqttTopics: next_state = handle_SubscribeMqttTopics(); break;
196+
case State::Connected: next_state = handle_Connected(); break;
197+
}
198+
_state = next_state;
199+
200+
/* For now exit here if we are not connected. */
201+
if (_state != State::Connected) return;
190202

191203
/* Check if a primitive property wrapper is locally changed.
192204
* This function requires an existing time service which in
@@ -250,44 +262,71 @@ void ArduinoIoTCloudTCP::setOTAStorage(OTAStorage & ota_storage)
250262
}
251263
#endif /* OTA_ENABLED */
252264

253-
int ArduinoIoTCloudTCP::reconnect()
254-
{
255-
if (_mqttClient.connected()) {
256-
_mqttClient.stop();
257-
}
258-
return connect();
259-
}
260-
261265
/******************************************************************************
262-
* PROTECTED MEMBER FUNCTIONS
266+
* PRIVATE MEMBER FUNCTIONS
263267
******************************************************************************/
264268

265-
int ArduinoIoTCloudTCP::connect()
269+
ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker()
266270
{
267-
if (!_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) return CONNECT_FAILURE;
268-
if (_mqttClient.subscribe(_stdinTopic) == 0) return CONNECT_FAILURE_SUBSCRIBE;
269-
if (_mqttClient.subscribe(_dataTopicIn) == 0) return CONNECT_FAILURE_SUBSCRIBE;
270-
if (_mqttClient.subscribe(_ota_topic_in) == 0) return CONNECT_FAILURE_SUBSCRIBE;
271+
if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort))
272+
return State::SubscribeMqttTopics;
273+
274+
DBG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort);
275+
return State::ConnectMqttBroker;
276+
}
277+
278+
ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics()
279+
{
280+
if (!_mqttClient.subscribe(_stdinTopic))
281+
{
282+
DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _stdinTopic.c_str());
283+
return State::SubscribeMqttTopics;
284+
}
285+
286+
if (!_mqttClient.subscribe(_dataTopicIn))
287+
{
288+
DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str());
289+
return State::SubscribeMqttTopics;
290+
}
291+
292+
if (!_mqttClient.subscribe(_ota_topic_in))
293+
{
294+
DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _ota_topic_in.c_str());
295+
return State::SubscribeMqttTopics;
296+
}
271297

272298
if (_shadowTopicIn != "")
273299
{
274-
if (_mqttClient.subscribe(_shadowTopicIn) == 0) return CONNECT_FAILURE_SUBSCRIBE;
300+
if (!_mqttClient.subscribe(_shadowTopicIn))
301+
{
302+
DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _ota_topic_in.c_str());
303+
return State::SubscribeMqttTopics;
304+
}
275305
_syncStatus = ArduinoIoTSynchronizationStatus::SYNC_STATUS_WAIT_FOR_CLOUD_VALUES;
276306
_lastSyncRequestTickTime = 0;
277307
}
278308

279-
return CONNECT_SUCCESS;
309+
DBG_VERBOSE("Connected to Arduino IoT Cloud");
310+
execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT);
311+
return State::Connected;
280312
}
281313

282-
void ArduinoIoTCloudTCP::disconnect()
314+
ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected()
283315
{
316+
if (_mqttClient.connected())
317+
return State::Connected;
318+
319+
/* The last message was definitely lost, trigger a retransmit. */
320+
_mqtt_data_request_retransmit = true;
321+
322+
/* We are not connected anymore, trigger the callback for a disconnected event. */
323+
execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT);
324+
325+
/* Forcefully disconnect MQTT client and trigger a reconnection. */
284326
_mqttClient.stop();
327+
return State::ConnectMqttBroker;
285328
}
286329

287-
/******************************************************************************
288-
* PRIVATE MEMBER FUNCTIONS
289-
******************************************************************************/
290-
291330
void ArduinoIoTCloudTCP::onMessage(int length)
292331
{
293332
ArduinoCloud.handleMessage(length);
@@ -345,62 +384,6 @@ void ArduinoIoTCloudTCP::requestLastValue()
345384
write(_shadowTopicOut, CBOR_REQUEST_LAST_VALUE_MSG, sizeof(CBOR_REQUEST_LAST_VALUE_MSG));
346385
}
347386

348-
ArduinoIoTConnectionStatus ArduinoIoTCloudTCP::checkCloudConnection()
349-
{
350-
ArduinoIoTConnectionStatus next_iot_status = _iot_status;
351-
352-
switch (_iot_status)
353-
{
354-
case ArduinoIoTConnectionStatus::IDLE: next_iot_status = ArduinoIoTConnectionStatus::CONNECTING; break;
355-
case ArduinoIoTConnectionStatus::ERROR: next_iot_status = ArduinoIoTConnectionStatus::RECONNECTING; break;
356-
case ArduinoIoTConnectionStatus::DISCONNECTED: next_iot_status = ArduinoIoTConnectionStatus::RECONNECTING; break;
357-
case ArduinoIoTConnectionStatus::CONNECTING:
358-
{
359-
DBG_INFO("Arduino IoT Cloud connecting ...");
360-
int const ret = connect();
361-
if (ret == CONNECT_SUCCESS)
362-
{
363-
next_iot_status = ArduinoIoTConnectionStatus::CONNECTED;
364-
}
365-
else if (ret == CONNECT_FAILURE_SUBSCRIBE)
366-
{
367-
DBG_ERROR("ERROR - Please verify your THING ID");
368-
}
369-
}
370-
break;
371-
372-
case ArduinoIoTConnectionStatus::RECONNECTING:
373-
{
374-
DBG_INFO("Arduino IoT Cloud reconnecting ...");
375-
if (reconnect() == CONNECT_SUCCESS)
376-
{
377-
next_iot_status = ArduinoIoTConnectionStatus::CONNECTED;
378-
}
379-
}
380-
break;
381-
382-
case ArduinoIoTConnectionStatus::CONNECTED:
383-
{
384-
if (!_mqttClient.connected())
385-
{
386-
next_iot_status = ArduinoIoTConnectionStatus::DISCONNECTED;
387-
_mqtt_data_request_retransmit = true;
388-
}
389-
}
390-
break;
391-
}
392-
393-
if(next_iot_status != _iot_status)
394-
{
395-
printConnectionStatus(next_iot_status);
396-
if (next_iot_status == ArduinoIoTConnectionStatus::DISCONNECTED) execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT);
397-
else if(next_iot_status == ArduinoIoTConnectionStatus::CONNECTED) execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT);
398-
_iot_status = next_iot_status;
399-
}
400-
401-
return _iot_status;
402-
}
403-
404387
int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const length)
405388
{
406389
if (_mqttClient.beginMessage(topic, length, false, 0)) {

src/ArduinoIoTCloudTCP.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,22 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
8989

9090
protected:
9191

92-
virtual int connect () override;
93-
virtual void disconnect () override;
92+
virtual int connect () override { }
93+
virtual void disconnect () override { }
9494

9595

9696
private:
9797
static const int MQTT_TRANSMIT_BUFFER_SIZE = 256;
9898

99+
enum class State
100+
{
101+
ConnectMqttBroker,
102+
SubscribeMqttTopics,
103+
Connected,
104+
};
105+
106+
State _state;
107+
99108
int _lastSyncRequestTickTime;
100109
String _brokerAddress;
101110
uint16_t _brokerPort;
@@ -138,11 +147,14 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
138147
inline String getTopic_datain () { return ( getThingId().length() == 0) ? String("/a/d/" + getDeviceId() + "/e/i") : String("/a/t/" + getThingId() + "/e/i"); }
139148
inline String getTopic_ota_in () { return String("/a/d/" + getDeviceId() + "/ota/i"); }
140149

150+
State handle_ConnectMqttBroker();
151+
State handle_SubscribeMqttTopics();
152+
State handle_Connected();
153+
141154
static void onMessage(int length);
142155
void handleMessage(int length);
143156
void sendPropertiesToCloud();
144157
void requestLastValue();
145-
ArduinoIoTConnectionStatus checkCloudConnection();
146158
int write(String const topic, byte const data[], int const length);
147159

148160
};

0 commit comments

Comments
 (0)