Skip to content

Commit ddcf176

Browse files
committed
config: add support for lastWill and keep alive
By default, MQTT keep-alive is 1200 seconds and AWS broker add a 1.5x factor, so it takes generally 15 min to discover that a device is disconnected (30 min in the worst case) This patch allow a user to configure a last will and change the default timeout (30 seconds will be the minimum authorized by AWS) New config will have for example: "last-will-topic": "things/myDevice/shadow/name/demo-shadow/update", "last-will-message": "{\"state\":{\"reported\":{\"connected\":false}}}", "connect-timeout": 0, "keep-alive": 30,
1 parent cf738c8 commit ddcf176

3 files changed

Lines changed: 76 additions & 2 deletions

File tree

source/SharedCrtResourceManager.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ int SharedCrtResourceManager::establishConnection(const PlainConfig &config)
393393
/*
394394
* This will execute when an mqtt connect has completed or failed.
395395
*/
396-
auto onConnectionCompleted = [this, &connectionCompletedPromise](
396+
auto onConnectionCompleted = [this, &connectionCompletedPromise, config](
397397
const Mqtt::MqttConnection &, int errorCode, Mqtt::ReturnCode returnCode, bool) {
398398
if (errorCode)
399399
{
@@ -412,6 +412,15 @@ int SharedCrtResourceManager::establishConnection(const PlainConfig &config)
412412
{
413413
LOGM_INFO(TAG, "MQTT connection established with return code: %d", returnCode);
414414
connectionCompletedPromise.set_value(0);
415+
416+
if (config.lastWillTopic.has_value() && config.lastWillMessage.has_value()) {
417+
Aws::Crt::ByteBuf payload = Aws::Crt::ByteBufFromCString(config.lastWillMessage->c_str());
418+
if (connection->SetWill(config.lastWillTopic->c_str(), Aws::Crt::Mqtt::QOS::AWS_MQTT_QOS_AT_LEAST_ONCE, false, payload)) {
419+
LOG_INFO(TAG, "MQTT connection set will succeeded");
420+
} else {
421+
LOG_INFO(TAG, "MQTT connection set will failed");
422+
}
423+
}
415424
}
416425
};
417426

@@ -461,7 +470,18 @@ int SharedCrtResourceManager::establishConnection(const PlainConfig &config)
461470
LOG_ERROR(TAG, "Device Client is not able to set reconnection settings. Device Client will retry again.");
462471
return RETRY;
463472
}
464-
if (!connection->Connect(config.thingName->c_str(), false))
473+
474+
int keepAliveTimeSecs = 0;
475+
if (config.connectKeepAlive.has_value()) {
476+
keepAliveTimeSecs = *config.connectKeepAlive;
477+
}
478+
479+
int pingTimeoutMs = 0;
480+
if (config.connectTimeout.has_value()) {
481+
pingTimeoutMs = *config.connectTimeout;
482+
}
483+
484+
if (!connection->Connect(config.thingName->c_str(), false, keepAliveTimeSecs, pingTimeoutMs))
465485
{
466486
LOGM_ERROR(TAG, "MQTT Connection failed with error: %s", ErrorDebugString(connection->LastError()));
467487
return RETRY;

source/config/Config.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ constexpr char PlainConfig::JSON_KEY_FLEET_PROVISIONING[];
6262
constexpr char PlainConfig::JSON_KEY_RUNTIME_CONFIG[];
6363
constexpr char PlainConfig::JSON_KEY_SAMPLES[];
6464
constexpr char PlainConfig::JSON_KEY_PUB_SUB[];
65+
constexpr char PlainConfig::JSON_KEY_LAST_WILL_TOPIC[];
66+
constexpr char PlainConfig::JSON_KEY_LAST_WILL_MESSAGE[];
67+
constexpr char PlainConfig::JSON_KEY_CONNECT_TIMEOUT[];
68+
constexpr char PlainConfig::JSON_KEY_CONNECT_KEEPALIVE[];
6569
constexpr char PlainConfig::JSON_KEY_SAMPLE_SHADOW[];
6670
constexpr char PlainConfig::JSON_KEY_CONFIG_SHADOW[];
6771
constexpr char PlainConfig::JSON_KEY_SECURE_ELEMENT[];
@@ -208,6 +212,30 @@ bool PlainConfig::LoadFromJson(const Crt::JsonView &json)
208212
}
209213
}
210214

215+
jsonKey = JSON_KEY_LAST_WILL_TOPIC;
216+
if (json.ValueExists(jsonKey))
217+
{
218+
lastWillTopic = json.GetString(jsonKey).c_str();
219+
}
220+
221+
jsonKey = JSON_KEY_LAST_WILL_MESSAGE;
222+
if (json.ValueExists(jsonKey))
223+
{
224+
lastWillMessage = json.GetString(jsonKey).c_str();
225+
}
226+
227+
jsonKey = JSON_KEY_CONNECT_TIMEOUT;
228+
if (json.ValueExists(jsonKey))
229+
{
230+
connectTimeout = json.GetInteger(jsonKey);
231+
}
232+
233+
jsonKey = JSON_KEY_CONNECT_KEEPALIVE;
234+
if (json.ValueExists(jsonKey))
235+
{
236+
connectKeepAlive = json.GetInteger(jsonKey);
237+
}
238+
211239
jsonKey = JSON_KEY_SAMPLE_SHADOW;
212240
if (json.ValueExists(jsonKey))
213241
{
@@ -436,6 +464,22 @@ void PlainConfig::SerializeToObject(Crt::JsonObject &object) const
436464
{
437465
object.WithString(JSON_KEY_THING_NAME, thingName->c_str());
438466
}
467+
if (lastWillTopic.has_value() && lastWillTopic->c_str())
468+
{
469+
object.WithString(JSON_KEY_LAST_WILL_TOPIC, lastWillTopic->c_str());
470+
}
471+
if (lastWillMessage.has_value() && lastWillMessage->c_str())
472+
{
473+
object.WithString(JSON_KEY_LAST_WILL_MESSAGE, lastWillMessage->c_str());
474+
}
475+
if (connectTimeout.has_value() && connectTimeout)
476+
{
477+
object.WithInteger(JSON_KEY_CONNECT_TIMEOUT, *connectTimeout);
478+
}
479+
if (connectKeepAlive.has_value() && connectKeepAlive)
480+
{
481+
object.WithInteger(JSON_KEY_CONNECT_KEEPALIVE, *connectKeepAlive);
482+
}
439483

440484
Crt::JsonObject loggingObject;
441485
logConfig.SerializeToObject(loggingObject);

source/config/Config.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ namespace Aws
9494
static constexpr char JSON_KEY_SAMPLES[] = "samples";
9595
static constexpr char JSON_KEY_PUB_SUB[] = "pub-sub";
9696

97+
static constexpr char JSON_KEY_LAST_WILL_TOPIC[] = "last-will-topic";
98+
static constexpr char JSON_KEY_LAST_WILL_MESSAGE[] = "last-will-message";
99+
100+
static constexpr char JSON_KEY_CONNECT_TIMEOUT[] = "connect-timeout";
101+
static constexpr char JSON_KEY_CONNECT_KEEPALIVE[] = "keep-alive";
102+
97103
static constexpr char JSON_KEY_SAMPLE_SHADOW[] = "sample-shadow";
98104
static constexpr char JSON_KEY_CONFIG_SHADOW[] = "config-shadow";
99105
static constexpr char JSON_KEY_SENSOR_PUBLISH[] = "sensor-publish";
@@ -107,6 +113,10 @@ namespace Aws
107113
Aws::Crt::Optional<std::string> key;
108114
Aws::Crt::Optional<std::string> rootCa;
109115
Aws::Crt::Optional<std::string> thingName;
116+
Aws::Crt::Optional<std::string> lastWillTopic;
117+
Aws::Crt::Optional<std::string> lastWillMessage;
118+
Aws::Crt::Optional<int> connectTimeout;
119+
Aws::Crt::Optional<int> connectKeepAlive;
110120

111121
std::string lockFilePath{DEFAULT_LOCK_FILE_PATH};
112122

0 commit comments

Comments
 (0)