Skip to content

Commit

Permalink
config: add support for lastWill and keep alive
Browse files Browse the repository at this point in the history
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,
  • Loading branch information
AmarOk1412 committed Sep 24, 2024
1 parent cf738c8 commit 8dff9d9
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 1 deletion.
18 changes: 17 additions & 1 deletion source/SharedCrtResourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,13 +455,29 @@ int SharedCrtResourceManager::establishConnection(const PlainConfig &config)
connection->OnConnectionInterrupted = move(OnConnectionInterrupted);
connection->OnConnectionResumed = move(OnConnectionResumed);

if (config.lastWillTopic.has_value() && config.lastWillMessage.has_value()) {
Aws::Crt::ByteBuf payload = Aws::Crt::ByteBufFromCString(config.lastWillMessage->c_str());
connection->SetWill(config.lastWillTopic->c_str(), Aws::Crt::Mqtt::QOS::AWS_MQTT_QOS_AT_LEAST_ONCE, false, payload);
}

LOGM_INFO(TAG, "Establishing MQTT connection with client id %s...", config.thingName->c_str());
if (!connection->SetReconnectTimeout(15, 240))
{
LOG_ERROR(TAG, "Device Client is not able to set reconnection settings. Device Client will retry again.");
return RETRY;
}
if (!connection->Connect(config.thingName->c_str(), false))

int keepAliveTimeSecs = 0;
if (config.connectKeepAlive.has_value()) {
keepAliveTimeSecs = *config.connectKeepAlive;
}

int pingTimeoutMs = 0;
if (config.connectTimeout.has_value()) {
pingTimeoutMs = *config.connectTimeout;
}

if (!connection->Connect(config.thingName->c_str(), false, keepAliveTimeSecs, pingTimeoutMs))
{
LOGM_ERROR(TAG, "MQTT Connection failed with error: %s", ErrorDebugString(connection->LastError()));
return RETRY;
Expand Down
44 changes: 44 additions & 0 deletions source/config/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ constexpr char PlainConfig::JSON_KEY_FLEET_PROVISIONING[];
constexpr char PlainConfig::JSON_KEY_RUNTIME_CONFIG[];
constexpr char PlainConfig::JSON_KEY_SAMPLES[];
constexpr char PlainConfig::JSON_KEY_PUB_SUB[];
constexpr char PlainConfig::JSON_KEY_LAST_WILL_TOPIC[];
constexpr char PlainConfig::JSON_KEY_LAST_WILL_MESSAGE[];
constexpr char PlainConfig::JSON_KEY_CONNECT_TIMEOUT[];
constexpr char PlainConfig::JSON_KEY_CONNECT_KEEPALIVE[];
constexpr char PlainConfig::JSON_KEY_SAMPLE_SHADOW[];
constexpr char PlainConfig::JSON_KEY_CONFIG_SHADOW[];
constexpr char PlainConfig::JSON_KEY_SECURE_ELEMENT[];
Expand Down Expand Up @@ -208,6 +212,30 @@ bool PlainConfig::LoadFromJson(const Crt::JsonView &json)
}
}

jsonKey = JSON_KEY_LAST_WILL_TOPIC;
if (json.ValueExists(jsonKey))
{
lastWillTopic = json.GetString(jsonKey).c_str();
}

jsonKey = JSON_KEY_LAST_WILL_MESSAGE;
if (json.ValueExists(jsonKey))
{
lastWillMessage = json.GetString(jsonKey).c_str();
}

jsonKey = JSON_KEY_CONNECT_TIMEOUT;
if (json.ValueExists(jsonKey))
{
connectTimeout = json.GetInteger(jsonKey);
}

jsonKey = JSON_KEY_CONNECT_KEEPALIVE;
if (json.ValueExists(jsonKey))
{
connectKeepAlive = json.GetInteger(jsonKey);
}

jsonKey = JSON_KEY_SAMPLE_SHADOW;
if (json.ValueExists(jsonKey))
{
Expand Down Expand Up @@ -436,6 +464,22 @@ void PlainConfig::SerializeToObject(Crt::JsonObject &object) const
{
object.WithString(JSON_KEY_THING_NAME, thingName->c_str());
}
if (lastWillTopic.has_value() && lastWillTopic->c_str())
{
object.WithString(JSON_KEY_LAST_WILL_TOPIC, lastWillTopic->c_str());
}
if (lastWillMessage.has_value() && lastWillMessage->c_str())
{
object.WithString(JSON_KEY_LAST_WILL_MESSAGE, lastWillMessage->c_str());
}
if (connectTimeout.has_value() && connectTimeout)
{
object.WithInteger(JSON_KEY_CONNECT_TIMEOUT, *connectTimeout);
}
if (connectKeepAlive.has_value() && connectKeepAlive)
{
object.WithInteger(JSON_KEY_CONNECT_KEEPALIVE, *connectKeepAlive);
}

Crt::JsonObject loggingObject;
logConfig.SerializeToObject(loggingObject);
Expand Down
10 changes: 10 additions & 0 deletions source/config/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ namespace Aws
static constexpr char JSON_KEY_SAMPLES[] = "samples";
static constexpr char JSON_KEY_PUB_SUB[] = "pub-sub";

static constexpr char JSON_KEY_LAST_WILL_TOPIC[] = "last-will-topic";
static constexpr char JSON_KEY_LAST_WILL_MESSAGE[] = "last-will-message";

static constexpr char JSON_KEY_CONNECT_TIMEOUT[] = "connect-timeout";
static constexpr char JSON_KEY_CONNECT_KEEPALIVE[] = "keep-alive";

static constexpr char JSON_KEY_SAMPLE_SHADOW[] = "sample-shadow";
static constexpr char JSON_KEY_CONFIG_SHADOW[] = "config-shadow";
static constexpr char JSON_KEY_SENSOR_PUBLISH[] = "sensor-publish";
Expand All @@ -107,6 +113,10 @@ namespace Aws
Aws::Crt::Optional<std::string> key;
Aws::Crt::Optional<std::string> rootCa;
Aws::Crt::Optional<std::string> thingName;
Aws::Crt::Optional<std::string> lastWillTopic;
Aws::Crt::Optional<std::string> lastWillMessage;
Aws::Crt::Optional<int> connectTimeout;
Aws::Crt::Optional<int> connectKeepAlive;

std::string lockFilePath{DEFAULT_LOCK_FILE_PATH};

Expand Down

0 comments on commit 8dff9d9

Please sign in to comment.