Skip to content

Commit

Permalink
The sample pub sub feature shows customers how they might leverage the (
Browse files Browse the repository at this point in the history
#129)

shared mqtt connection available in the Device Client to accomplish some
set of business logic

Co-authored-by: lwwilkov <[email protected]>
Co-authored-by: Matthew Paul <[email protected]>
  • Loading branch information
3 people authored Apr 14, 2021
1 parent 91bb420 commit 483b3a9
Show file tree
Hide file tree
Showing 16 changed files with 718 additions and 5 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- SDK logging now configurable via CLI or JSON
- Support for configuring Device Private Key via CLI and JSON for Fleet provisioning using CreateCertificateFromCsr API
- Added [Pub/Sub Sample Feature](source/samples/pubsub/README.md)
- Update job to "In Progress" after receive
- Shared Lib builds in Github Actions
- Add CodeDeploy config for integration test setup
- Doxygen Github Actions

### Changed
- Reademe Makeover
- Address cross-platform compatibility for ANSI color codes

### Removed

### Fixed
- Properly stripping symbols on RELEASE builds
- Updated SDK version to fix shared lib builds
- Broken Doxygen URL in the Readme
- Fix Ubi8 and Al2 Dockerfile Openssl install

## [1.0.X] - 2021-01-21
### Added
Expand Down
20 changes: 19 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ option(EXCLUDE_DD "Builds the device client without the IoT Device Defender Feat
option(EXCLUDE_ST "Builds the device client without the IoT Secure Tunneling Feature." OFF)
option(EXCLUDE_FP "Builds the device client without the IoT Fleet Provisioning Feature." OFF)
option(DISABLE_MQTT "WARNING: This flag is meant for internal use cases and will prevent Device Client features from operating. Builds the device client without MQTT Connection Management." OFF)
option(EXCLUDE_SAMPLES "Builds the device client without any of the IoT Sample Features." OFF)
option(EXCLUDE_PUBSUB "Builds the device client without the IoT Pub Sub Sample Feature." OFF)
option(GIT_VERSION "Updates the version number using the Git commit history" ON)

if (EXCLUDE_JOBS)
Expand All @@ -31,6 +33,14 @@ if (DISABLE_MQTT)
add_definitions(-DDISABLE_MQTT)
endif ()

if (EXCLUDE_SAMPLES)
add_definitions(-DEXCLUDE_SAMPLES)
endif ()

if (EXCLUDE_PUBSUB)
add_definitions(-DEXCLUDE_PUBSUB)
endif ()

list(APPEND CMAKE_MODULE_PATH "./sdk-cpp-workspace/lib/cmake")

file(GLOB CONFIG_SRC "source/config/*.cpp")
Expand All @@ -41,7 +51,8 @@ file(GLOB DC_SRC "source/*.cpp" /
"source/*.c" /
${CONFIG_SRC}
${LOG_SRC}
${UTIL_SRC})
${UTIL_SRC}
${SAMP_SRC})

if (NOT EXCLUDE_DD)
file(GLOB DD_SRC "source/devicedefender/*.cpp")
Expand All @@ -63,6 +74,13 @@ if (NOT EXCLUDE_FP)
list(APPEND DC_SRC ${FP_SRC})
endif ()

if (NOT EXCLUDE_SAMPLES)
if (NOT EXCLUDE_PUBSUB)
file(GLOB PUBSUB_SRC "source/samples/pubsub/*.cpp")
list(APPEND DC_SRC ${PUBSUB_SRC})
endif ()
endif ()

set(DC_PROJECT_NAME aws-iot-device-client)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_FLAGS_DEBUGOPT "")
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* [Fleet Provisioning Feature](source/fleetprovisioning/README.md)
* [Device Defender Feature](source/devicedefender/README.md)
* [Secure Tunneling Feature](source/tunneling/README.md)
* [MQTT Pub/Sub Sample Feature](source/samples/pubsub/README.md)
* [Logging](source/logging/README.md)
* [Doxygen Documentation](docs/README.md)
* [Additional Resources](#additional-resources)
Expand Down Expand Up @@ -109,6 +110,9 @@ cd ../
[Device Defender Feature Readme](source/devicedefender/README.md)
[Secure Tunneling Feature Readme](source/tunneling/README.md)

## AWS IoT Device Client Samples
[MQTT Pub/Sub Sample Feature](source/samples/pubsub/README.md)

## Logging
[Logging Readme](source/logging/README.md)

Expand Down
9 changes: 9 additions & 0 deletions config-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,14 @@
"template-name": "replace_with_template_name",
"csr-file": "replace_with_csr_file_path",
"device-key": "replace_with_device_private_key_file_path"
},
"samples": {
"pub-sub": {
"enabled": false,
"publish-topic": "replace_with_publish_topic",
"publish-file": "replace_with_publish_file",
"subscribe-topic": "replace_with_subscribe_topic",
"subscribe-file": "replace_with_subscribe_file"
}
}
}
2 changes: 2 additions & 0 deletions docs/COMPILATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ Available CMake flags for feature exclusion:
* `EXCLUDE_DD`
* `EXCLUDE_ST`
* `EXCLUDE_FP`
* `EXCLUDE_SAMPLES`
* `EXCLUDE_PUBSUB`

Example CMake command to exclude only the Device Defender feature from the build:

Expand Down
1 change: 1 addition & 0 deletions docs/PERMISSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ CSR File | 600 | **Yes**
Log File | 600 | **Yes**
Job Handler | 700 | **Yes**
Config File | 644 | **Recommended**
Pub/Sub Files | 600 | **yes**


#### Recommended and Required permissions on directories storing respective files
Expand Down
27 changes: 27 additions & 0 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,24 @@ if [ "$BUILD_CONFIG" = "y" ]; then
FP_ENABLED="false"
fi

### PUBSUB Config ###
printf ${PMPT} "Enable Pub Sub sample feature? y/n"
PUBSUB_ENABLED=""
read -r ENABLE_PUBSUB
if [ "$ENABLE_PUBSUB" = "y" ]; then
PUBSUB_ENABLED="true"
printf ${PMPT} "Specify a topic for the feature to publish to:"
read -r PUB_TOPIC
printf ${PMPT} "Specify the path of a file for the feature to publish (Leaving this blank will publish 'Hello World!'):"
read -r PUB_FILE
printf ${PMPT} "Specify a topic for the feature to subscribe to:"
read -r SUB_TOPIC
printf ${PMPT} "Specify the path of a file for the feature to write to (Optional):"
read -r SUB_FILE
else
PUBSUB_ENABLED="false"
fi

CONFIG_OUTPUT="
{
\"endpoint\": \"$ENDPOINT\",
Expand Down Expand Up @@ -165,6 +183,15 @@ if [ "$BUILD_CONFIG" = "y" ]; then
\"template-name\": \"$FP_TEMPLATE_NAME\",
\"csr-file\": \"$FP_CSR_FILE\",
\"device-key\": \"$FP_DEVICE_KEY\"
},
\"samples\": {
\"pub-sub\": {
\"enabled\": $PUBSUB_ENABLED,
\"publish-topic\": \"$PUB_TOPIC\",
\"publish-file\": \"$PUB_FILE\",
\"subscribe-topic\": \"$SUB_TOPIC\",
\"subscribe-file\": \"$SUB_FILE\"
}
}
}"

Expand Down
152 changes: 148 additions & 4 deletions source/config/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ constexpr char PlainConfig::JSON_KEY_TUNNELING[];
constexpr char PlainConfig::JSON_KEY_DEVICE_DEFENDER[];
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 int Permissions::KEY_DIR;
constexpr int Permissions::ROOT_CA_DIR;
Expand All @@ -64,6 +66,7 @@ constexpr int Permissions::LOG_FILE;
constexpr int Permissions::CONFIG_FILE;
constexpr int Permissions::RUNTIME_CONFIG_FILE;
constexpr int Permissions::JOB_HANDLER;
constexpr int Permissions::PUB_SUB_FILES;

bool PlainConfig::LoadFromJson(const Crt::JsonView &json)
{
Expand Down Expand Up @@ -166,6 +169,18 @@ bool PlainConfig::LoadFromJson(const Crt::JsonView &json)
logConfig = temp;
}

jsonKey = JSON_KEY_SAMPLES;
if (json.ValueExists(jsonKey))
{
const char *jsonKeyTwo = JSON_KEY_PUB_SUB;
if (json.ValueExists(jsonKey))
{
PubSub temp;
temp.LoadFromJson(json.GetJsonObject(jsonKey).GetJsonObject(jsonKeyTwo));
pubSub = temp;
}
}

return true;
}

Expand Down Expand Up @@ -193,14 +208,15 @@ bool PlainConfig::LoadFromCliArgs(const CliArgs &cliArgs)
}

return logConfig.LoadFromCliArgs(cliArgs) && jobs.LoadFromCliArgs(cliArgs) && tunneling.LoadFromCliArgs(cliArgs) &&
deviceDefender.LoadFromCliArgs(cliArgs) && fleetProvisioning.LoadFromCliArgs(cliArgs);
deviceDefender.LoadFromCliArgs(cliArgs) && fleetProvisioning.LoadFromCliArgs(cliArgs) &&
pubSub.LoadFromCliArgs(cliArgs);
}

bool PlainConfig::LoadFromEnvironment()
{
return logConfig.LoadFromEnvironment() && jobs.LoadFromEnvironment() && tunneling.LoadFromEnvironment() &&
deviceDefender.LoadFromEnvironment() && fleetProvisioning.LoadFromEnvironment() &&
fleetProvisioningRuntimeConfig.LoadFromEnvironment();
fleetProvisioningRuntimeConfig.LoadFromEnvironment() && pubSub.LoadFromEnvironment();
}

bool PlainConfig::Validate() const
Expand Down Expand Up @@ -259,6 +275,12 @@ bool PlainConfig::Validate() const
{
return false;
}
#endif
#if !defined(EXCLUDE_PUBSUB)
if (!pubSub.Validate())
{
return false;
}
#endif
return true;
}
Expand Down Expand Up @@ -904,6 +926,118 @@ bool PlainConfig::FleetProvisioningRuntimeConfig::Validate() const
!thingName->empty();
}

constexpr char PlainConfig::PubSub::CLI_ENABLE_PUB_SUB[];
constexpr char PlainConfig::PubSub::CLI_PUB_SUB_PUBLISH_TOPIC[];
constexpr char PlainConfig::PubSub::CLI_PUB_SUB_PUBLISH_FILE[];
constexpr char PlainConfig::PubSub::CLI_PUB_SUB_SUBSCRIBE_TOPIC[];
constexpr char PlainConfig::PubSub::CLI_PUB_SUB_SUBSCRIBE_FILE[];

constexpr char PlainConfig::PubSub::JSON_ENABLE_PUB_SUB[];
constexpr char PlainConfig::PubSub::JSON_PUB_SUB_PUBLISH_TOPIC[];
constexpr char PlainConfig::PubSub::JSON_PUB_SUB_PUBLISH_FILE[];
constexpr char PlainConfig::PubSub::JSON_PUB_SUB_SUBSCRIBE_TOPIC[];
constexpr char PlainConfig::PubSub::JSON_PUB_SUB_SUBSCRIBE_FILE[];

bool PlainConfig::PubSub::LoadFromJson(const Crt::JsonView &json)
{
const char *jsonKey = JSON_ENABLE_PUB_SUB;
if (json.ValueExists(jsonKey))
{
enabled = json.GetBool(jsonKey);
}

jsonKey = JSON_PUB_SUB_PUBLISH_TOPIC;
if (json.ValueExists(jsonKey))
{
publishTopic = FileUtils::ExtractExpandedPath(json.GetString(jsonKey).c_str());
}

jsonKey = JSON_PUB_SUB_PUBLISH_FILE;
if (json.ValueExists(jsonKey))
{
publishFile = FileUtils::ExtractExpandedPath(json.GetString(jsonKey).c_str());
}

jsonKey = JSON_PUB_SUB_SUBSCRIBE_TOPIC;
if (json.ValueExists(jsonKey))
{
subscribeTopic = FileUtils::ExtractExpandedPath(json.GetString(jsonKey).c_str());
}

jsonKey = JSON_PUB_SUB_SUBSCRIBE_FILE;
if (json.ValueExists(jsonKey))
{
subscribeFile = FileUtils::ExtractExpandedPath(json.GetString(jsonKey).c_str());
}

return true;
}

bool PlainConfig::PubSub::LoadFromCliArgs(const CliArgs &cliArgs)
{
if (cliArgs.count(PlainConfig::PubSub::CLI_ENABLE_PUB_SUB))
{
enabled = cliArgs.at(CLI_ENABLE_PUB_SUB).compare("true") == 0;
}
if (cliArgs.count(PlainConfig::PubSub::CLI_PUB_SUB_PUBLISH_TOPIC))
{
publishTopic = cliArgs.at(PlainConfig::PubSub::CLI_PUB_SUB_PUBLISH_TOPIC);
}
if (cliArgs.count(PlainConfig::PubSub::CLI_PUB_SUB_PUBLISH_FILE))
{
subscribeTopic = cliArgs.at(PlainConfig::PubSub::CLI_PUB_SUB_SUBSCRIBE_TOPIC);
}
if (cliArgs.count(PlainConfig::PubSub::CLI_PUB_SUB_SUBSCRIBE_TOPIC))
{
subscribeTopic = cliArgs.at(PlainConfig::PubSub::CLI_PUB_SUB_SUBSCRIBE_TOPIC);
}
if (cliArgs.count(PlainConfig::PubSub::CLI_PUB_SUB_SUBSCRIBE_FILE))
{
subscribeFile = FileUtils::ExtractExpandedPath(cliArgs.at(PlainConfig::PubSub::CLI_PUB_SUB_SUBSCRIBE_FILE));
}
return true;
}

bool PlainConfig::PubSub::Validate() const
{
if (!enabled)
{
return true;
}
if (!publishTopic.has_value() || publishTopic->empty())
{
LOGM_ERROR(
Config::TAG,
"*** %s: Publish Topic field must be specified if Pub-Sub sample feature is enabled ***",
DeviceClient::DC_FATAL_ERROR);
return false;
}
if (!subscribeTopic.has_value() || subscribeTopic->empty())
{
LOGM_ERROR(
Config::TAG,
"*** %s: Subscribe Topic field must be specified if Pub-Sub sample feature is enabled ***",
DeviceClient::DC_FATAL_ERROR);
return false;
}
if (publishFile.has_value() && !publishFile->empty())
{
if (!FileUtils::ValidateFilePermissions(publishFile.value(), Permissions::PUB_SUB_FILES, true))
{
return false;
}
}
if (subscribeFile.has_value() && !subscribeFile->empty())
{
if (!FileUtils::ValidateFilePermissions(subscribeFile.value(), Permissions::PUB_SUB_FILES, true))
{
return false;
}
}

return true;
}

constexpr char Config::TAG[];
constexpr char Config::DEFAULT_CONFIG_DIR[];
constexpr char Config::DEFAULT_KEY_DIR[];
Expand Down Expand Up @@ -1175,6 +1309,7 @@ void Config::PrintHelpMessage()
"%s [true|false]:\t\t\t\t\tEnables/Disables Tunneling feature\n"
"%s [true|false]:\t\t\t\t\tEnables/Disables Device Defender feature\n"
"%s [true|false]:\t\t\t\tEnables/Disables Fleet Provisioning feature\n"
"%s [true|false]:\t\t\t\t\t\tEnables/Disables Pub/Sub Sample feature\n"
"%s <endpoint-value>:\t\t\t\t\t\tUse Specified Endpoint\n"
"%s <Cert-Location>:\t\t\t\t\t\t\tUse Specified Cert file\n"
"%s <Key-Location>:\t\t\t\t\t\t\tUse Specified Key file\n"
Expand All @@ -1192,7 +1327,11 @@ void Config::PrintHelpMessage()
"%s <device-key-path>:\t\t\t\t\t\tUse specified device key to connect to IoT core after provisioning using csr "
"file is completed. If the CSR file is specified without also specifying a device private key, the Device "
"Client will use Claim Certificate and Private key to generate new Certificate and Private Key while "
"provisioning the device\n";
"provisioning the device\n"
"%s <publish-topic>:\t\t\t\t\tThe topic the Pub/Sub sample feature will publish to\n"
"%s <path/to/publish/file>:\t\t\t\t\tThe file the Pub/Sub sample feature will read from when publishing\n"
"%s <subscribe-topic>:\t\t\t\t\tThe topic the Pub/Sub sample feature will receive messages on\n"
"%s <path/to/sub/file>:\t\t\t\t\tThe file the Pub/Sub sample feature will write received messaged to\n";

cout << FormatMessage(
helpMessageTemplate,
Expand All @@ -1209,6 +1348,7 @@ void Config::PrintHelpMessage()
PlainConfig::Tunneling::CLI_ENABLE_TUNNELING,
PlainConfig::DeviceDefender::CLI_ENABLE_DEVICE_DEFENDER,
PlainConfig::FleetProvisioning::CLI_ENABLE_FLEET_PROVISIONING,
PlainConfig::PubSub::CLI_ENABLE_PUB_SUB,
PlainConfig::CLI_ENDPOINT,
PlainConfig::CLI_CERT,
PlainConfig::CLI_KEY,
Expand All @@ -1221,7 +1361,11 @@ void Config::PrintHelpMessage()
PlainConfig::DeviceDefender::CLI_DEVICE_DEFENDER_INTERVAL,
PlainConfig::FleetProvisioning::CLI_FLEET_PROVISIONING_TEMPLATE_NAME,
PlainConfig::FleetProvisioning::CLI_FLEET_PROVISIONING_CSR_FILE,
PlainConfig::FleetProvisioning::CLI_FLEET_PROVISIONING_DEVICE_KEY);
PlainConfig::FleetProvisioning::CLI_FLEET_PROVISIONING_DEVICE_KEY,
PlainConfig::PubSub::CLI_PUB_SUB_PUBLISH_TOPIC,
PlainConfig::PubSub::CLI_PUB_SUB_PUBLISH_FILE,
PlainConfig::PubSub::CLI_PUB_SUB_SUBSCRIBE_TOPIC,
PlainConfig::PubSub::CLI_PUB_SUB_SUBSCRIBE_FILE);
}

bool Config::ExportDefaultSetting(const string &file)
Expand Down
Loading

0 comments on commit 483b3a9

Please sign in to comment.