From 359a7937ac578489f2e82daa51a0a78f8f714d26 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 16 Sep 2024 16:59:14 -0700 Subject: [PATCH 01/33] Checkpoint --- crt/aws-crt-cpp | 2 +- .../include/aws/iotshadow/IotShadowClientv2.h | 61 ++++++++++ shadow/source/IotShadowClientv2.cpp | 111 ++++++++++++++++++ 3 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 shadow/include/aws/iotshadow/IotShadowClientv2.h create mode 100644 shadow/source/IotShadowClientv2.cpp diff --git a/crt/aws-crt-cpp b/crt/aws-crt-cpp index 17e30acb7..5f2268cd7 160000 --- a/crt/aws-crt-cpp +++ b/crt/aws-crt-cpp @@ -1 +1 @@ -Subproject commit 17e30acb7d6338a7b180c0cd522de0b4c51ceadd +Subproject commit 5f2268cd7c0d5b08b169a60094ff4cc66214d4eb diff --git a/shadow/include/aws/iotshadow/IotShadowClientv2.h b/shadow/include/aws/iotshadow/IotShadowClientv2.h new file mode 100644 index 000000000..fca0e0766 --- /dev/null +++ b/shadow/include/aws/iotshadow/IotShadowClientv2.h @@ -0,0 +1,61 @@ +#pragma once + +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ + +#include + +#include +#include + + +#include + +namespace Aws +{ + namespace Crt { + namespace Mqtt { + class MqttConnection; + } + namespace Mqtt5 { + class Mqtt5Client; + } + } + + template class Error { + public: + + private: + Aws::Crt::Variant rawError; + }; + + namespace Iotshadow + { + class ErrorResponse; + class GetNamedShadowRequest; + class GetNamedShadowResponse; + + using GetNamedShadowResult = Aws::Iot::RequestResponse::Result>; + + class AWS_IOTSHADOW_API IClientv2 + { + public: + + virtual ~IClientv2() = 0; + + static std::shared_ptr newFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + Aws::Iot::RequestResponse::RequestResponseClientOptions &&options, + Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); + + static std::shared_ptr newFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, + Aws::Iot::RequestResponse::RequestResponseClientOptions &&options, + Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); + + virtual bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) = 0; + + }; + } +} \ No newline at end of file diff --git a/shadow/source/IotShadowClientv2.cpp b/shadow/source/IotShadowClientv2.cpp new file mode 100644 index 000000000..82e55bd67 --- /dev/null +++ b/shadow/source/IotShadowClientv2.cpp @@ -0,0 +1,111 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +* SPDX-License-Identifier: Apache-2.0. +* +* This file is generated +*/ + +#include + +#include +#include + +namespace Aws +{ + namespace Iotshadow + { + + class Clientv2 : public IClientv2 { + public: + + Clientv2(Aws::Crt::Allocator *allocator, Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient); + virtual ~Clientv2(); + + virtual bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, std::function &&handler); + + private: + + Aws::Crt::ScopedResource m_bindingClient; + }; + + Clientv2::Clientv2(Aws::Crt::Allocator *allocator, Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient) : + m_bindingClient(bindingClient, [allocator](Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient) { Aws::Crt::Delete(bindingClient, allocator); }) + { + } + + Clientv2::~Clientv2() { + } + + bool Clientv2::GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) { + Aws::Crt::StringStream publishTopic; + publishTopic << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get"; + + Aws::Crt::StringStream subscriptionTopic; + subscriptionTopic << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/+"; + + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic.str()) + }; + + Aws::Crt::StringStream responsePathTopic1; + responsePathTopic1 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/accepted"; + + Aws::Crt::StringStream responsePathTopic2; + responsePathTopic2 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/rejected"; + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopic1.str()); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopic2.str()); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + auto uuid = Aws::Crt::UUID().ToString(); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic.str()); + options.serialized_request = Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [](Aws::Iot::RequestResponse::UnmodeledResult &&result){ + + }; + + int submitResult = m_bindingClient->submitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + std::shared_ptr IClientv2::newFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + Aws::Iot::RequestResponse::RequestResponseClientOptions &&options, + Aws::Crt::Allocator *allocator) { + + Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient = Aws::Iot::RequestResponse::IMqttRequestResponseClient::newFrom5(protocolClient, std::move(options), allocator); + if (!bindingClient) { + return nullptr; + } + + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + } + + std::shared_ptr IClientv2::newFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, + Aws::Iot::RequestResponse::RequestResponseClientOptions &&options, + Aws::Crt::Allocator *allocator) { + + Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient = Aws::Iot::RequestResponse::IMqttRequestResponseClient::newFrom311(protocolClient, std::move(options), allocator); + if (!bindingClient) { + return nullptr; + } + + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + } + + } +} \ No newline at end of file From aa12ba8e9c402aea406118378d93312b32b48b9f Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Wed, 18 Sep 2024 14:43:53 -0700 Subject: [PATCH 02/33] Checkpoint --- crt/aws-crt-cpp | 2 +- samples/shadow/v2/CMakeLists.txt | 28 ++ samples/shadow/v2/README.md | 127 +++++++ samples/shadow/v2/main.cpp | 311 +++++++++++++++ .../include/aws/iotshadow/IotShadowClientv2.h | 81 +++- shadow/source/IotShadowClientv2.cpp | 354 ++++++++++++++++-- 6 files changed, 860 insertions(+), 43 deletions(-) create mode 100644 samples/shadow/v2/CMakeLists.txt create mode 100644 samples/shadow/v2/README.md create mode 100644 samples/shadow/v2/main.cpp diff --git a/crt/aws-crt-cpp b/crt/aws-crt-cpp index 5f2268cd7..806b0694f 160000 --- a/crt/aws-crt-cpp +++ b/crt/aws-crt-cpp @@ -1 +1 @@ -Subproject commit 5f2268cd7c0d5b08b169a60094ff4cc66214d4eb +Subproject commit 806b0694f6cf4a354872f41fb64070f428e0844b diff --git a/samples/shadow/v2/CMakeLists.txt b/samples/shadow/v2/CMakeLists.txt new file mode 100644 index 000000000..d42494ffb --- /dev/null +++ b/samples/shadow/v2/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.1) +# note: cxx-17 requires cmake 3.8, cxx-20 requires cmake 3.12 +project(shadowv2 CXX) + +file(GLOB SRC_FILES + "*.cpp" + "../../utils/CommandLineUtils.cpp" + "../../utils/CommandLineUtils.h" +) + +add_executable(${PROJECT_NAME} ${SRC_FILES}) + +set_target_properties(${PROJECT_NAME} PROPERTIES + CXX_STANDARD 14) + +#set warnings +if (MSVC) + target_compile_options(${PROJECT_NAME} PRIVATE /W4 /WX) +else () + target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wno-long-long -pedantic -Werror) +endif () + +find_package(aws-crt-cpp REQUIRED) +find_package(IotShadow-cpp REQUIRED) + +install(TARGETS ${PROJECT_NAME} DESTINATION bin) + +target_link_libraries(${PROJECT_NAME} PRIVATE AWS::aws-crt-cpp AWS::IotShadow-cpp) diff --git a/samples/shadow/v2/README.md b/samples/shadow/v2/README.md new file mode 100644 index 000000000..0c614a9e5 --- /dev/null +++ b/samples/shadow/v2/README.md @@ -0,0 +1,127 @@ +# Shadow + +[**Return to main sample list**](../../README.md) + +This sample uses the AWS IoT [Device Shadow](https://docs.aws.amazon.com/iot/latest/developerguide/iot-device-shadows.html) Service to keep a property in sync between device and server. Imagine a light whose color may be changed through an app, or set by a local user. + +Once connected, type a value in the terminal and press Enter to update the property's "reported" value. The sample also responds when the "desired" value changes on the server. To observe this, edit the Shadow document in the AWS Console and set a new "desired" value. + +On startup, the sample requests the shadow document to learn the property's initial state. The sample also subscribes to "delta" events from the server, which are sent when a property's "desired" value differs from its "reported" value. When the sample learns of a new desired value, that value is changed on the device and an update is sent to the server with the new "reported" value. + +Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect, subscribe, publish, and receive. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. + +
+Sample Policy +
+{
+  "Version": "2012-10-17",
+  "Statement": [
+    {
+      "Effect": "Allow",
+      "Action": [
+        "iot:Publish"
+      ],
+      "Resource": [
+        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/get",
+        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update"
+      ]
+    },
+    {
+      "Effect": "Allow",
+      "Action": [
+        "iot:Receive"
+      ],
+      "Resource": [
+        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/get/accepted",
+        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/get/rejected",
+        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update/accepted",
+        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update/rejected",
+        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update/delta"
+      ]
+    },
+    {
+      "Effect": "Allow",
+      "Action": [
+        "iot:Subscribe"
+      ],
+      "Resource": [
+        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/get/accepted",
+        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/get/rejected",
+        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/update/accepted",
+        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/update/rejected",
+        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/update/delta"
+      ]
+    },
+    {
+      "Effect": "Allow",
+      "Action": "iot:Connect",
+      "Resource": "arn:aws:iot:region:account:client/test-*"
+    }
+  ]
+}
+
+ +Replace with the following with the data from your AWS account: +* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. +* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. +* ``: The name of your AWS IoT Core thing you want the device connection to be associated with + +Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. + +
+ +## How to run + +To run the Shadow sample use the following command: + +``` sh +./mqtt5-shadow-sync --endpoint --cert --key --thing_name --shadow_property +``` + +You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: + +``` sh +./mqtt5-shadow-sync --endpoint --cert --key --thing_name --shadow_property --ca_file +``` + + +## Service Client Notes +### Difference between MQTT5 and MQTT311 IotShadowClient +The IotShadowClient with Mqtt5 client is identical to Mqtt3 one. We wrapped the Mqtt5Client into MqttClientConnection so that we could keep the same interface for IotShadowClient. +The only difference is that you would need setup up a Mqtt5 Client for the IotShadowClient. For how to setup a Mqtt5 Client, please refer to [MQTT5 UserGuide](../../../documents/MQTT5_Userguide.md) and [MQTT5 PubSub Sample](../../mqtt5/mqtt5_pubsub/) + + + + + + + + + + +
Create a IotShadowClient with Mqtt5Create a IotShadowClient with Mqtt311
+ +```Cpp + // Build Mqtt5Client + std::shared_ptr client = builder->Build(); + + // Create shadow client with mqtt5 client + Aws::Iotshadow::IotShadowClient shadowClient(client); +``` + + + +```Cpp + // Create mqtt311 connection + Aws::Iot::MqttClient client = Aws::Iot::MqttClient(); + auto connection = client.NewConnection(clientConfig); + + // Create shadow client with mqtt311 connection + Aws::Iotshadow::IotShadowClient shadowClient(connection); + +``` + +
+ +### Mqtt::QOS v.s. Mqtt5::QOS +As the service client interface is unchanged for Mqtt3 Connection and Mqtt5 Client,the IotShadowClient will use Mqtt::QOS instead of Mqtt5::QOS even with a Mqtt5 Client. diff --git a/samples/shadow/v2/main.cpp b/samples/shadow/v2/main.cpp new file mode 100644 index 000000000..47e3178cf --- /dev/null +++ b/samples/shadow/v2/main.cpp @@ -0,0 +1,311 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../../utils/CommandLineUtils.h" + +using namespace Aws::Crt; +using namespace Aws::Iotshadow; + +static void s_onConnectionSuccess(const Mqtt5::OnConnectionSuccessEventData &eventData) { + fprintf( + stdout, + "Mqtt5 Client connection succeeded!\n"); +} + +static void s_onConnectionFailure(const Mqtt5::OnConnectionFailureEventData &eventData) { + fprintf(stdout, "Mqtt5 client connection attempt failed with error: %s.\n", aws_error_debug_str(eventData.errorCode)); +} + +static void s_onStopped(const Mqtt5::OnStoppedEventData &event) { + fprintf(stdout, "Protocol client stopped.\n"); +} + + +static Aws::Crt::String s_nibbleNextToken(Aws::Crt::String &input) { + Aws::Crt::String token; + Aws::Crt::String remaining; + auto delimPosition = input.find(' '); + if (delimPosition != Aws::Crt::String::npos) { + token = input.substr(0, delimPosition); + + auto untrimmedRemaining = input.substr(delimPosition, Aws::Crt::String::npos); + auto firstNonSpacePosition = untrimmedRemaining.find_first_not_of(' '); + if (firstNonSpacePosition != Aws::Crt::String::npos) { + remaining = untrimmedRemaining.substr(firstNonSpacePosition, Aws::Crt::String::npos); + } else { + remaining = ""; + } + } else { + token = input; + remaining = ""; + } + + input = remaining; + return token; +} + +static void s_printHelp() { + fprintf(stdout, "\nShadow sandbox:\n\n"); + fprintf(stdout, " quit -- quits the program\n"); + fprintf(stdout, " start -- starts the protocol client\n"); + fprintf(stdout, " stop -- stops the protocol client\n"); + fprintf(stdout, " get -- gets the state of a named shadow belonging to the specified thing\n"); + fprintf(stdout, " delete -- deletes a named shadow belonging to the specified thing\n"); + fprintf(stdout, " update-desired -- updates the desired state of a named shadow belonging to the specified thing\n"); + fprintf(stdout, " update-reported -- updates the reported state a named shadow belonging to the specified thing\n"); +} + +static void s_onServiceError(const Aws::Iotshadow::ServiceErrorV2 &serviceError, Aws::Crt::String operationName) { + fprintf(stdout, "%s failed with error code: %s\n", operationName.c_str(), aws_error_debug_str(serviceError.getErrorCode())); + if (serviceError.hasModeledError()) { + const auto &modeledError = serviceError.getModeledError(); + + Aws::Crt::JsonObject jsonObject; + modeledError.SerializeToObject(jsonObject); + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + fprintf(stdout, "modeled error: %s\n", outgoingJson.c_str()); + } +} + +static void s_onGetShadowResult(GetShadowResult &&result) { + if (result.isSuccess()) { + const auto &response = result.getResponse(); + + Aws::Crt::JsonObject jsonObject; + response.SerializeToObject(jsonObject); + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + fprintf(stdout, "get result: %s\n", outgoingJson.c_str()); + } else { + s_onServiceError(result.getError(), "get"); + } +} + +static void s_handleGetNamedShadow(const Aws::Crt::String params, const std::shared_ptr &shadowClient) { + Aws::Crt::String remaining = params; + Aws::Crt::String thing = s_nibbleNextToken(remaining); + Aws::Crt::String shadow = s_nibbleNextToken(remaining); + + if (thing.length() == 0 || shadow.length() == 0) { + fprintf(stdout, "Invalid arguments to get command!\n\n"); + s_printHelp(); + return; + } + + Aws::Iotshadow::GetNamedShadowRequest request; + request.ThingName = thing; + request.ShadowName = shadow; + + shadowClient->GetNamedShadow(request, [](GetShadowResult &&result){ + s_onGetShadowResult(std::move(result)); + }); +} + +static void s_onDeleteShadowResult(DeleteShadowResult &&result) { + if (result.isSuccess()) { + const auto &response = result.getResponse(); + + Aws::Crt::JsonObject jsonObject; + response.SerializeToObject(jsonObject); + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + fprintf(stdout, "delete result: %s\n", outgoingJson.c_str()); + } else { + s_onServiceError(result.getError(), "delete"); + } +} + +static void s_handleDeleteNamedShadow(const Aws::Crt::String params, const std::shared_ptr &shadowClient) { + Aws::Crt::String remaining = params; + Aws::Crt::String thing = s_nibbleNextToken(remaining); + Aws::Crt::String shadow = s_nibbleNextToken(remaining); + + if (thing.length() == 0 || shadow.length() == 0) { + fprintf(stdout, "Invalid arguments to delete command!\n\n"); + s_printHelp(); + return; + } + + Aws::Iotshadow::DeleteNamedShadowRequest request; + request.ThingName = thing; + request.ShadowName = shadow; + + shadowClient->DeleteNamedShadow(request, [](DeleteShadowResult &&result){ + s_onDeleteShadowResult(std::move(result)); + }); +} + +static void s_onUpdateShadowResult(UpdateShadowResult &&result, Aws::Crt::String operationName) { + if (result.isSuccess()) { + const auto &response = result.getResponse(); + + Aws::Crt::JsonObject jsonObject; + response.SerializeToObject(jsonObject); + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + fprintf(stdout, "%s result: %s\n", operationName.c_str(), outgoingJson.c_str()); + } else { + s_onServiceError(result.getError(), operationName); + } +} + +static void s_handleUpdateDesiredNamedShadow(const Aws::Crt::String params, const std::shared_ptr &shadowClient) { + Aws::Crt::String remaining = params; + Aws::Crt::String thing = s_nibbleNextToken(remaining); + Aws::Crt::String shadow = s_nibbleNextToken(remaining); + + if (thing.length() == 0 || shadow.length() == 0) { + fprintf(stdout, "Invalid arguments to update-desired command!\n\n"); + s_printHelp(); + return; + } + + Aws::Crt::JsonObject stateAsJson(remaining); + if (!stateAsJson.WasParseSuccessful()) { + fprintf(stdout, "desired state was not valid JSON!\n\n"); + s_printHelp(); + return; + } + + Aws::Iotshadow::UpdateNamedShadowRequest request; + request.ThingName = thing; + request.ShadowName = shadow; + request.State = Aws::Iotshadow::ShadowState(); + request.State.value().Desired = stateAsJson; + + shadowClient->UpdateNamedShadow(request, [](UpdateShadowResult &&result){ + s_onUpdateShadowResult(std::move(result), "update-desired"); + }); +} + +static void s_handleUpdateReportedNamedShadow(const Aws::Crt::String params, const std::shared_ptr &shadowClient) { + Aws::Crt::String remaining = params; + Aws::Crt::String thing = s_nibbleNextToken(remaining); + Aws::Crt::String shadow = s_nibbleNextToken(remaining); + + if (thing.length() == 0 || shadow.length() == 0) { + fprintf(stdout, "Invalid arguments to update-reported command!\n\n"); + s_printHelp(); + return; + } + + Aws::Crt::JsonObject stateAsJson(remaining); + if (!stateAsJson.WasParseSuccessful()) { + fprintf(stdout, "reported state was not valid JSON!\n\n"); + s_printHelp(); + return; + } + + Aws::Iotshadow::UpdateNamedShadowRequest request; + request.ThingName = thing; + request.ShadowName = shadow; + request.State = Aws::Iotshadow::ShadowState(); + request.State.value().Reported = stateAsJson; + + shadowClient->UpdateNamedShadow(request, [](UpdateShadowResult &&result){ + s_onUpdateShadowResult(std::move(result), "update-reported"); + }); +} + +static bool s_handleInput(const Aws::Crt::String &input, const std::shared_ptr &protocolClient, const std::shared_ptr &shadowClient) { + Aws::Crt::String remaining = input; + Aws::Crt::String command = s_nibbleNextToken(remaining); + + if (command == "quit") { + fprintf(stdout, "Quitting!\n"); + return true; + } else if (command == "start") { + fprintf(stdout, "Starting protocol client!\n"); + protocolClient->Start(); + } else if (command == "stop") { + fprintf(stdout, "Stopping protocol client!\n"); + protocolClient->Stop(); + } else if (command == "get") { + s_handleGetNamedShadow(remaining, shadowClient); + } else if (command == "delete") { + s_handleDeleteNamedShadow(remaining, shadowClient); + } else if (command == "update-desired") { + s_handleUpdateDesiredNamedShadow(remaining, shadowClient); + } else if (command == "update-reported") { + s_handleUpdateReportedNamedShadow(remaining, shadowClient); + } else { + s_printHelp(); + } + + return false; +} + +int main(int argc, char *argv[]) +{ + /************************ Setup ****************************/ + + // Do the global initialization for the API. + ApiHandle apiHandle; + + Utils::cmdData cmdData = Utils::parseSampleInputBasicConnect(argc, argv, &apiHandle); + + // Create the MQTT5 builder and populate it with data from cmdData. + auto builder = std::unique_ptr( + Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithMtlsFromPath( + cmdData.input_endpoint, cmdData.input_cert.c_str(), cmdData.input_key.c_str())); + // Check if the builder setup correctly. + if (builder == nullptr) + { + printf( + "Failed to setup mqtt5 client builder with error code %d: %s", LastError(), ErrorDebugString(LastError())); + return -1; + } + + if (cmdData.input_port != 0) + { + builder->WithPort(static_cast(cmdData.input_port)); + } + + // Setup lifecycle callbacks + builder->WithClientConnectionSuccessCallback(s_onConnectionSuccess); + builder->WithClientConnectionFailureCallback(s_onConnectionFailure); + builder->WithClientStoppedCallback(s_onStopped); + + // Create Mqtt5Client + std::shared_ptr client = builder->Build(); + + Aws::Iot::RequestResponse::RequestResponseClientOptions requestResponseOptions; + requestResponseOptions.maxRequestResponseSubscriptions = 4; + requestResponseOptions.maxStreamingSubscriptions = 10; + requestResponseOptions.operationTimeoutInSeconds = 30; + + std::shared_ptr shadowClient = Aws::Iotshadow::IClientV2::newFrom5(*client, requestResponseOptions); + + while (true) + { + fprintf(stdout, "\nEnter command:\n"); + + String input; + std::getline(std::cin, input); + + if (s_handleInput(input, client, shadowClient)) + { + fprintf(stdout, "Exiting..."); + break; + } + } + + return 0; +} diff --git a/shadow/include/aws/iotshadow/IotShadowClientv2.h b/shadow/include/aws/iotshadow/IotShadowClientv2.h index fca0e0766..6850ddd8c 100644 --- a/shadow/include/aws/iotshadow/IotShadowClientv2.h +++ b/shadow/include/aws/iotshadow/IotShadowClientv2.h @@ -25,36 +25,81 @@ namespace Aws } } - template class Error { - public: - - private: - Aws::Crt::Variant rawError; - }; - namespace Iotshadow { - class ErrorResponse; - class GetNamedShadowRequest; - class GetNamedShadowResponse; + template class ServiceErrorV2 + { + public: + ServiceErrorV2() = delete; + ServiceErrorV2(const ServiceErrorV2 &rhs) = default; + ServiceErrorV2(ServiceErrorV2 &&rhs) = default; + + explicit ServiceErrorV2(int errorCode) : + m_errorCode(errorCode), + m_modeledError() + {} + + ServiceErrorV2(int errorCode, E &&modeledError) : + m_errorCode(errorCode), + m_modeledError(std::move(modeledError)) + {} + + ~ServiceErrorV2() = default; + + ServiceErrorV2 &operator =(const ServiceErrorV2 &rhs) = default; + ServiceErrorV2 &operator =(ServiceErrorV2 &&rhs) = default; + + int getErrorCode() const { return m_errorCode; } - using GetNamedShadowResult = Aws::Iot::RequestResponse::Result>; + bool hasModeledError() const { return m_modeledError.has_value(); } + const E &getModeledError() const { return m_modeledError.value(); } - class AWS_IOTSHADOW_API IClientv2 + private: + + int m_errorCode; + + Aws::Crt::Optional m_modeledError; + }; + + class ErrorResponse; + class DeleteNamedShadowRequest; + class DeleteShadowResponse; + class GetNamedShadowRequest; + class GetShadowResponse; + class NamedShadowDeltaUpdatedSubscriptionRequest; + class NamedShadowUpdatedSubscriptionRequest; + class ShadowDeltaUpdatedEvent; + class ShadowUpdatedEvent; + class UpdateNamedShadowRequest; + class UpdateShadowResponse; + + using DeleteShadowResult = Aws::Iot::RequestResponse::Result>; + using GetShadowResult = Aws::Iot::RequestResponse::Result>; + using UpdateShadowResult = Aws::Iot::RequestResponse::Result>; + + class AWS_IOTSHADOW_API IClientV2 { public: - virtual ~IClientv2() = 0; + virtual ~IClientV2() = default; - static std::shared_ptr newFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, - Aws::Iot::RequestResponse::RequestResponseClientOptions &&options, + static std::shared_ptr newFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); - static std::shared_ptr newFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, - Aws::Iot::RequestResponse::RequestResponseClientOptions &&options, + static std::shared_ptr newFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); - virtual bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) = 0; + virtual bool DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler) = 0; + + virtual bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) = 0; + + virtual bool UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler) = 0; + + virtual std::shared_ptr createNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler) = 0; + + virtual std::shared_ptr createNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler) = 0; }; } diff --git a/shadow/source/IotShadowClientv2.cpp b/shadow/source/IotShadowClientv2.cpp index 82e55bd67..ccf693d8c 100644 --- a/shadow/source/IotShadowClientv2.cpp +++ b/shadow/source/IotShadowClientv2.cpp @@ -7,61 +7,213 @@ #include #include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include namespace Aws { + namespace Iotshadow { - class Clientv2 : public IClientv2 { + class Clientv2 : public IClientV2 + { public: Clientv2(Aws::Crt::Allocator *allocator, Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient); - virtual ~Clientv2(); + virtual ~Clientv2() = default; + + virtual bool DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler); + + virtual bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler); - virtual bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, std::function &&handler); + virtual bool UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler); + + virtual std::shared_ptr createNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler); + + virtual std::shared_ptr createNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler); private: + Aws::Crt::Allocator *m_allocator; + Aws::Crt::ScopedResource m_bindingClient; }; Clientv2::Clientv2(Aws::Crt::Allocator *allocator, Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient) : + m_allocator(allocator), m_bindingClient(bindingClient, [allocator](Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient) { Aws::Crt::Delete(bindingClient, allocator); }) { } - Clientv2::~Clientv2() { + static void s_applyUnmodeledErrorToDeleteNamedShadowHandler(const std::function &handler, int errorCode) { + ServiceErrorV2 error(errorCode); + Aws::Iotshadow::DeleteShadowResult finalResult(std::move(error)); + handler(std::move(finalResult)); + } + + static void s_DeleteNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { + if (!result.isSuccess()) { + s_applyUnmodeledErrorToDeleteNamedShadowHandler(handler, result.getError()); + return; + } + + auto response = result.getResponse(); + Aws::Crt::String objectStr(reinterpret_cast(response.payload.ptr), response.payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + s_applyUnmodeledErrorToDeleteNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure + return; + } + + auto responseTopic = Aws::Crt::String((const char *)response.topic.ptr, response.topic.len); + if (responseTopic == successPathTopic) { + Aws::Iotshadow::DeleteShadowResponse modeledResponse(jsonObject); + Aws::Iotshadow::DeleteShadowResult finalResult(std::move(modeledResponse)); + handler(std::move(finalResult)); + } else if (responseTopic == failurePathTopic) { + Aws::Iotshadow::ErrorResponse modeledResponse(jsonObject); + + Aws::Iotshadow::ServiceErrorV2 modeledError(AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR, std::move(modeledResponse)); // TBI: MQTT Service error + Aws::Iotshadow::DeleteShadowResult finalResult(std::move(modeledError)); + handler(std::move(finalResult)); + } else { + s_applyUnmodeledErrorToDeleteNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path + } } - bool Clientv2::GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) { - Aws::Crt::StringStream publishTopic; - publishTopic << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get"; + bool Clientv2::DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler) { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/delete"; + Aws::Crt::String publishTopic = publishTopicStream.str(); - Aws::Crt::StringStream subscriptionTopic; - subscriptionTopic << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/+"; + Aws::Crt::StringStream subscriptionTopicStream; + subscriptionTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/delete/+"; + Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); struct aws_byte_cursor subscriptionTopicFilters[1] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic.str()) + Aws::Crt::ByteCursorFromString(subscriptionTopic) }; - Aws::Crt::StringStream responsePathTopic1; - responsePathTopic1 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/accepted"; + Aws::Crt::StringStream responsePathTopic1Stream; + responsePathTopic1Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/delete/accepted"; + Aws::Crt::String responsePathTopic1 = responsePathTopic1Stream.str(); - Aws::Crt::StringStream responsePathTopic2; - responsePathTopic2 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/rejected"; + Aws::Crt::StringStream responsePathTopic2Stream; + responsePathTopic2Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/delete/rejected"; + Aws::Crt::String responsePathTopic2 = responsePathTopic2Stream.str(); struct aws_mqtt_request_operation_response_path responsePaths[2]; - responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopic1.str()); + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopic1); responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopic2.str()); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopic2); responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopic1, responsePathTopic2](Aws::Iot::RequestResponse::UnmodeledResult &&result){ + s_DeleteNamedShadowResponseHandler(std::move(result), handler, responsePathTopic1, responsePathTopic2); + }; + + int submitResult = m_bindingClient->submitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + static void s_applyUnmodeledErrorToGetNamedShadowHandler(const std::function &handler, int errorCode) { + ServiceErrorV2 error(errorCode); + Aws::Iotshadow::GetShadowResult finalResult(std::move(error)); + handler(std::move(finalResult)); + } + + static void s_GetNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { + if (!result.isSuccess()) { + s_applyUnmodeledErrorToGetNamedShadowHandler(handler, result.getError()); + return; + } + + auto response = result.getResponse(); + Aws::Crt::String objectStr(reinterpret_cast(response.payload.ptr), response.payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + s_applyUnmodeledErrorToGetNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure + return; + } + + auto responseTopic = Aws::Crt::String((const char *)response.topic.ptr, response.topic.len); + if (responseTopic == successPathTopic) { + Aws::Iotshadow::GetShadowResponse modeledResponse(jsonObject); + Aws::Iotshadow::GetShadowResult finalResult(std::move(modeledResponse)); + handler(std::move(finalResult)); + } else if (responseTopic == failurePathTopic) { + Aws::Iotshadow::ErrorResponse modeledResponse(jsonObject); + + Aws::Iotshadow::ServiceErrorV2 modeledError(AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR, std::move(modeledResponse)); // TBI: MQTT Service error + Aws::Iotshadow::GetShadowResult finalResult(std::move(modeledError)); + handler(std::move(finalResult)); + } else { + s_applyUnmodeledErrorToGetNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path + } + } + + bool Clientv2::GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream; + subscriptionTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/+"; + Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); + + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic) + }; + + Aws::Crt::StringStream responsePathTopic1Stream; + responsePathTopic1Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/accepted"; + Aws::Crt::String responsePathTopic1 = responsePathTopic1Stream.str(); + + Aws::Crt::StringStream responsePathTopic2Stream; + responsePathTopic2Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/rejected"; + Aws::Crt::String responsePathTopic2 = responsePathTopic2Stream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopic1); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopic2); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); struct aws_mqtt_request_operation_options options; @@ -70,12 +222,107 @@ namespace Aws options.subscription_topic_filter_count = 1; options.response_paths = responsePaths; options.response_path_count = 2; - options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic.str()); + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); options.serialized_request = Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); - auto resultHandler = [](Aws::Iot::RequestResponse::UnmodeledResult &&result){ + auto resultHandler = [handler, responsePathTopic1, responsePathTopic2](Aws::Iot::RequestResponse::UnmodeledResult &&result){ + s_GetNamedShadowResponseHandler(std::move(result), handler, responsePathTopic1, responsePathTopic2); + }; + + int submitResult = m_bindingClient->submitRequest(options, std::move(resultHandler)); + return submitResult == AWS_OP_SUCCESS; + } + + static void s_applyUnmodeledErrorToUpdateNamedShadowHandler(const std::function &handler, int errorCode) { + ServiceErrorV2 error(errorCode); + Aws::Iotshadow::UpdateShadowResult finalResult(std::move(error)); + handler(std::move(finalResult)); + } + + static void s_UpdateNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { + if (!result.isSuccess()) { + s_applyUnmodeledErrorToUpdateNamedShadowHandler(handler, result.getError()); + return; + } + + auto response = result.getResponse(); + Aws::Crt::String objectStr(reinterpret_cast(response.payload.ptr), response.payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + s_applyUnmodeledErrorToUpdateNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure + return; + } + + auto responseTopic = Aws::Crt::String((const char *)response.topic.ptr, response.topic.len); + if (responseTopic == successPathTopic) { + Aws::Iotshadow::UpdateShadowResponse modeledResponse(jsonObject); + Aws::Iotshadow::UpdateShadowResult finalResult(std::move(modeledResponse)); + handler(std::move(finalResult)); + } else if (responseTopic == failurePathTopic) { + Aws::Iotshadow::ErrorResponse modeledResponse(jsonObject); + + Aws::Iotshadow::ServiceErrorV2 modeledError(AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR, std::move(modeledResponse)); // TBI: MQTT Service error + Aws::Iotshadow::UpdateShadowResult finalResult(std::move(modeledError)); + handler(std::move(finalResult)); + } else { + s_applyUnmodeledErrorToUpdateNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path + } + } + + bool Clientv2::UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler) { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopic1Stream; + subscriptionTopic1Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/accepted"; + Aws::Crt::String subscriptionTopic1 = subscriptionTopic1Stream.str(); + + Aws::Crt::StringStream subscriptionTopic2Stream; + subscriptionTopic2Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/rejected"; + Aws::Crt::String subscriptionTopic2 = subscriptionTopic2Stream.str(); + + struct aws_byte_cursor subscriptionTopicFilters[2] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic1), + Aws::Crt::ByteCursorFromString(subscriptionTopic2) + }; + + Aws::Crt::StringStream responsePathTopic1Stream; + responsePathTopic1Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/accepted"; + Aws::Crt::String responsePathTopic1 = responsePathTopic1Stream.str(); + + Aws::Crt::StringStream responsePathTopic2Stream; + responsePathTopic2Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/rejected"; + Aws::Crt::String responsePathTopic2 = responsePathTopic2Stream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopic1); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopic2); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 2; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopic1, responsePathTopic2](Aws::Iot::RequestResponse::UnmodeledResult &&result){ + s_UpdateNamedShadowResponseHandler(std::move(result), handler, responsePathTopic1, responsePathTopic2); }; int submitResult = m_bindingClient->submitRequest(options, std::move(resultHandler)); @@ -83,11 +330,70 @@ namespace Aws return submitResult == AWS_OP_SUCCESS; } - std::shared_ptr IClientv2::newFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, - Aws::Iot::RequestResponse::RequestResponseClientOptions &&options, + template class ShadowStreamingOperation : public Aws::Iot::RequestResponse::IStreamingOperation { + public: + + explicit ShadowStreamingOperation(std::shared_ptr stream) : + m_stream(std::move(stream)) + { + } + + static std::shared_ptr create(Aws::Crt::Allocator *allocator, Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient, const Aws::Crt::String &subscriptionTopicFilter, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler) { + + std::function unmodeledHandler = [handler](Aws::Iot::RequestResponse::IncomingPublishEvent &&event){ + Aws::Crt::String objectStr(reinterpret_cast(event.payload.ptr), event.payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + return; + } + + T modeledEvent(jsonObject); + handler(std::move(modeledEvent)); + }; + + Aws::Iot::RequestResponse::StreamingOperationOptionsInternal internalOptions; + internalOptions.subscriptionTopicFilter = Aws::Crt::ByteCursorFromString(subscriptionTopicFilter); + internalOptions.subscriptionStatusEventHandler = options.subscriptionStatusEventHandler; + internalOptions.incomingPublishEventHandler = unmodeledHandler; + + auto unmodeledStream = bindingClient->createStream(internalOptions); + if (!unmodeledStream) { + return nullptr; + } + + return Aws::Crt::MakeShared(allocator, unmodeledStream); + } + + virtual void activate() { + m_stream->activate(); + } + + private: + + std::shared_ptr m_stream; + }; + + std::shared_ptr Clientv2::createNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler) { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/delta"; + Aws::Crt::String topic = topicStream.str(); + + return ShadowStreamingOperation::create(m_allocator, m_bindingClient.get(), topic, options, handler); + } + + std::shared_ptr Clientv2::createNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler) { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/documents"; + Aws::Crt::String topic = topicStream.str(); + + return ShadowStreamingOperation::create(m_allocator, m_bindingClient.get(), topic, options, handler); + } + + std::shared_ptr IClientV2::newFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, Aws::Crt::Allocator *allocator) { - Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient = Aws::Iot::RequestResponse::IMqttRequestResponseClient::newFrom5(protocolClient, std::move(options), allocator); + Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient = Aws::Iot::RequestResponse::IMqttRequestResponseClient::newFrom5(protocolClient, options, allocator); if (!bindingClient) { return nullptr; } @@ -95,11 +401,11 @@ namespace Aws return Aws::Crt::MakeShared(allocator, allocator, bindingClient); } - std::shared_ptr IClientv2::newFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, - Aws::Iot::RequestResponse::RequestResponseClientOptions &&options, + std::shared_ptr IClientV2::newFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, Aws::Crt::Allocator *allocator) { - Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient = Aws::Iot::RequestResponse::IMqttRequestResponseClient::newFrom311(protocolClient, std::move(options), allocator); + Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient = Aws::Iot::RequestResponse::IMqttRequestResponseClient::newFrom311(protocolClient, options, allocator); if (!bindingClient) { return nullptr; } From 0327dcfe6fcf4ebbaff12ca1798cf99beda993af Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Thu, 19 Sep 2024 12:50:31 -0700 Subject: [PATCH 03/33] Updates --- crt/aws-crt-cpp | 2 +- samples/shadow/v2/main.cpp | 222 +++++++++++++++--- ...otShadowClientv2.h => IotShadowClientV2.h} | 29 +-- ...adowClientv2.cpp => IotShadowClientV2.cpp} | 201 ++++++++-------- 4 files changed, 298 insertions(+), 156 deletions(-) rename shadow/include/aws/iotshadow/{IotShadowClientv2.h => IotShadowClientV2.h} (71%) rename shadow/source/{IotShadowClientv2.cpp => IotShadowClientV2.cpp} (64%) diff --git a/crt/aws-crt-cpp b/crt/aws-crt-cpp index 806b0694f..dfdd59a78 160000 --- a/crt/aws-crt-cpp +++ b/crt/aws-crt-cpp @@ -1 +1 @@ -Subproject commit 806b0694f6cf4a354872f41fb64070f428e0844b +Subproject commit dfdd59a7896ccab047d630cd6f38a588857fbcae diff --git a/samples/shadow/v2/main.cpp b/samples/shadow/v2/main.cpp index 47e3178cf..575ded785 100644 --- a/samples/shadow/v2/main.cpp +++ b/samples/shadow/v2/main.cpp @@ -7,18 +7,22 @@ #include #include -#include +#include #include #include #include #include +#include +#include +#include +#include #include #include #include #include +#include #include -#include #include #include "../../utils/CommandLineUtils.h" @@ -26,6 +30,28 @@ using namespace Aws::Crt; using namespace Aws::Iotshadow; +struct StreamingOperationWrapper { + Aws::Crt::String m_thingName; + + Aws::Crt::String m_shadowName; + + Aws::Crt::String m_type; + + std::shared_ptr m_stream; +}; + +struct ApplicationContext { + + std::shared_ptr m_protocolClient; + + std::shared_ptr m_shadowClient; + + uint64_t m_nextStreamId; + + std::unordered_map m_streams; +}; + + static void s_onConnectionSuccess(const Mqtt5::OnConnectionSuccessEventData &eventData) { fprintf( stdout, @@ -40,7 +66,6 @@ static void s_onStopped(const Mqtt5::OnStoppedEventData &event) { fprintf(stdout, "Protocol client stopped.\n"); } - static Aws::Crt::String s_nibbleNextToken(Aws::Crt::String &input) { Aws::Crt::String token; Aws::Crt::String remaining; @@ -68,17 +93,21 @@ static void s_printHelp() { fprintf(stdout, "\nShadow sandbox:\n\n"); fprintf(stdout, " quit -- quits the program\n"); fprintf(stdout, " start -- starts the protocol client\n"); - fprintf(stdout, " stop -- stops the protocol client\n"); + fprintf(stdout, " stop -- stops the protocol client\n\n"); fprintf(stdout, " get -- gets the state of a named shadow belonging to the specified thing\n"); fprintf(stdout, " delete -- deletes a named shadow belonging to the specified thing\n"); fprintf(stdout, " update-desired -- updates the desired state of a named shadow belonging to the specified thing\n"); - fprintf(stdout, " update-reported -- updates the reported state a named shadow belonging to the specified thing\n"); + fprintf(stdout, " update-reported -- updates the reported state a named shadow belonging to the specified thing\n\n"); + fprintf(stdout, " list-streams -- lists all open streaming operations\n"); + fprintf(stdout, " open-delta-stream -- opens a new streaming operation that receives delta events about changes to a particular shadow belonging to a thing\n"); + fprintf(stdout, " open-document-stream -- opens a new streaming operation that receives document events about changes to a particular shadow belonging to a thing\n"); + fprintf(stdout, " close-stream -- closes a streaming operation\n"); } static void s_onServiceError(const Aws::Iotshadow::ServiceErrorV2 &serviceError, Aws::Crt::String operationName) { - fprintf(stdout, "%s failed with error code: %s\n", operationName.c_str(), aws_error_debug_str(serviceError.getErrorCode())); - if (serviceError.hasModeledError()) { - const auto &modeledError = serviceError.getModeledError(); + fprintf(stdout, "%s failed with error code: %s\n", operationName.c_str(), aws_error_debug_str(serviceError.GetErrorCode())); + if (serviceError.HasModeledError()) { + const auto &modeledError = serviceError.GetModeledError(); Aws::Crt::JsonObject jsonObject; modeledError.SerializeToObject(jsonObject); @@ -88,15 +117,15 @@ static void s_onServiceError(const Aws::Iotshadow::ServiceErrorV2 &protocolClient, const std::shared_ptr &shadowClient) { +static void s_handleListStreams(const ApplicationContext &context) { + fprintf(stdout, "Streams:\n"); + for (const auto &iter : context.m_streams) { + uint64_t streamId = iter.first; + const StreamingOperationWrapper &wrapper = iter.second; + fprintf(stdout, " %" PRIu64": type '%s', thing '%s', shadow '%s'\n", streamId, wrapper.m_type.c_str(), wrapper.m_thingName.c_str(), wrapper.m_shadowName.c_str()); + } +} + +static void s_handleCloseStream(const Aws::Crt::String params, ApplicationContext &context) { + Aws::Crt::String remaining = params; + Aws::Crt::String streamId = s_nibbleNextToken(remaining); + + if (streamId.length() == 0) { + fprintf(stdout, "Invalid arguments to close-stream command!\n\n"); + s_printHelp(); + return; + } + + uint64_t id = std::stoull(streamId.c_str()); + fprintf(stdout, "Closing stream %" PRIu64 "\n", id); + context.m_streams.erase(id); +} + +static void s_registerStream(ApplicationContext &context, uint64_t id, std::shared_ptr operation, Aws::Crt::String type, Aws::Crt::String thing, Aws::Crt::String shadow) { + StreamingOperationWrapper wrapper; + wrapper.m_stream = operation; + wrapper.m_type = type; + wrapper.m_thingName = thing; + wrapper.m_shadowName = shadow; + + context.m_streams[id] = wrapper; + + operation->Open(); +} + +static void s_onSubscriptionStatusEvent(uint64_t id, Aws::Iot::RequestResponse::SubscriptionStatusEvent &&event) { + fprintf(stdout, "Stream %" PRIu64 ": subscription status event with type %d and error %s\n", id, event.GetErrorCode(), Aws::Crt::ErrorDebugString(event.GetErrorCode())); +} + +static void s_onShadowDeltaUpdatedEvent(uint64_t id, Aws::Iotshadow::ShadowDeltaUpdatedEvent &&event) { + fprintf(stdout, "Stream %" PRIu64 ": received shadow delta updated event:\n", id); + + Aws::Crt::JsonObject jsonObject; + event.SerializeToObject(jsonObject); + Aws::Crt::String json = jsonObject.View().WriteCompact(true); + fprintf(stdout, " %s\n", json.c_str()); +} + +static void s_handleOpenDeltaStream(const Aws::Crt::String params, ApplicationContext &context) { + Aws::Crt::String remaining = params; + Aws::Crt::String thing = s_nibbleNextToken(remaining); + Aws::Crt::String shadow = s_nibbleNextToken(remaining); + + if (thing.length() == 0 || shadow.length() == 0) { + fprintf(stdout, "Invalid arguments to open-delta-stream command!\n\n"); + s_printHelp(); + return; + } + + uint64_t streamId = context.m_nextStreamId++; + + Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest request; + request.ThingName = thing; + request.ShadowName = shadow; + + Aws::Iot::RequestResponse::StreamingOperationOptions options; + options.WithSubscriptionStatusEventHandler([streamId](Aws::Iot::RequestResponse::SubscriptionStatusEvent &&event) { + s_onSubscriptionStatusEvent(streamId, std::move(event)); + }); + options.WithStreamHandler([streamId](Aws::Iotshadow::ShadowDeltaUpdatedEvent &&event) { + s_onShadowDeltaUpdatedEvent(streamId, std::move(event)); + }); + + auto operation = context.m_shadowClient->CreateNamedShadowDeltaUpdatedStream(request, options); + s_registerStream(context, streamId, operation, "Delta", thing, shadow); +} + +static void s_onShadowUpdatedEvent(uint64_t id, Aws::Iotshadow::ShadowUpdatedEvent &&event) { + fprintf(stdout, "Stream %" PRIu64 ": received shadow updated event:\n", id); + + Aws::Crt::JsonObject jsonObject; + event.SerializeToObject(jsonObject); + Aws::Crt::String json = jsonObject.View().WriteCompact(true); + fprintf(stdout, " %s\n", json.c_str()); +} + +static void s_handleOpenDocumentStream(const Aws::Crt::String params, ApplicationContext &context) { + Aws::Crt::String remaining = params; + Aws::Crt::String thing = s_nibbleNextToken(remaining); + Aws::Crt::String shadow = s_nibbleNextToken(remaining); + + if (thing.length() == 0 || shadow.length() == 0) { + fprintf(stdout, "Invalid arguments to open-document-stream command!\n\n"); + s_printHelp(); + return; + } + + uint64_t streamId = context.m_nextStreamId++; + + Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest request; + request.ThingName = thing; + request.ShadowName = shadow; + + Aws::Iot::RequestResponse::StreamingOperationOptions options; + options.WithSubscriptionStatusEventHandler([streamId](Aws::Iot::RequestResponse::SubscriptionStatusEvent &&event) { + s_onSubscriptionStatusEvent(streamId, std::move(event)); + }); + options.WithStreamHandler([streamId](Aws::Iotshadow::ShadowUpdatedEvent &&event) { + s_onShadowUpdatedEvent(streamId, std::move(event)); + }); + + auto operation = context.m_shadowClient->CreateNamedShadowUpdatedStream(request, options); + s_registerStream(context, streamId, operation, "Document", thing, shadow); +} + +static bool s_handleInput(const Aws::Crt::String &input, ApplicationContext &context) { Aws::Crt::String remaining = input; Aws::Crt::String command = s_nibbleNextToken(remaining); @@ -233,18 +378,26 @@ static bool s_handleInput(const Aws::Crt::String &input, const std::shared_ptrStart(); + context.m_protocolClient->Start(); } else if (command == "stop") { fprintf(stdout, "Stopping protocol client!\n"); - protocolClient->Stop(); + context.m_protocolClient->Stop(); } else if (command == "get") { - s_handleGetNamedShadow(remaining, shadowClient); + s_handleGetNamedShadow(remaining, context.m_shadowClient); } else if (command == "delete") { - s_handleDeleteNamedShadow(remaining, shadowClient); + s_handleDeleteNamedShadow(remaining, context.m_shadowClient); } else if (command == "update-desired") { - s_handleUpdateDesiredNamedShadow(remaining, shadowClient); + s_handleUpdateDesiredNamedShadow(remaining, context.m_shadowClient); } else if (command == "update-reported") { - s_handleUpdateReportedNamedShadow(remaining, shadowClient); + s_handleUpdateReportedNamedShadow(remaining, context.m_shadowClient); + } else if (command == "list-streams") { + s_handleListStreams(context); + } else if (command == "open-delta-stream") { + s_handleOpenDeltaStream(remaining, context); + } else if (command == "open-document-stream") { + s_handleOpenDocumentStream(remaining, context); + } else if (command == "close-stream") { + s_handleCloseStream(remaining, context); } else { s_printHelp(); } @@ -273,25 +426,20 @@ int main(int argc, char *argv[]) return -1; } - if (cmdData.input_port != 0) - { - builder->WithPort(static_cast(cmdData.input_port)); - } - // Setup lifecycle callbacks builder->WithClientConnectionSuccessCallback(s_onConnectionSuccess); builder->WithClientConnectionFailureCallback(s_onConnectionFailure); builder->WithClientStoppedCallback(s_onStopped); - // Create Mqtt5Client - std::shared_ptr client = builder->Build(); - Aws::Iot::RequestResponse::RequestResponseClientOptions requestResponseOptions; - requestResponseOptions.maxRequestResponseSubscriptions = 4; - requestResponseOptions.maxStreamingSubscriptions = 10; - requestResponseOptions.operationTimeoutInSeconds = 30; + requestResponseOptions.WithMaxRequestResponseSubscriptions(4); + requestResponseOptions.WithMaxStreamingSubscriptions(10); + requestResponseOptions.WithOperationTimeoutInSeconds(30); - std::shared_ptr shadowClient = Aws::Iotshadow::IClientV2::newFrom5(*client, requestResponseOptions); + ApplicationContext context; + context.m_protocolClient = builder->Build();; + context.m_shadowClient = Aws::Iotshadow::NewClientFrom5(*context.m_protocolClient, requestResponseOptions); + context.m_nextStreamId = 1; while (true) { @@ -300,7 +448,7 @@ int main(int argc, char *argv[]) String input; std::getline(std::cin, input); - if (s_handleInput(input, client, shadowClient)) + if (s_handleInput(input, context)) { fprintf(stdout, "Exiting..."); break; diff --git a/shadow/include/aws/iotshadow/IotShadowClientv2.h b/shadow/include/aws/iotshadow/IotShadowClientV2.h similarity index 71% rename from shadow/include/aws/iotshadow/IotShadowClientv2.h rename to shadow/include/aws/iotshadow/IotShadowClientV2.h index 6850ddd8c..46d61e2f9 100644 --- a/shadow/include/aws/iotshadow/IotShadowClientv2.h +++ b/shadow/include/aws/iotshadow/IotShadowClientV2.h @@ -10,8 +10,6 @@ #include #include - - #include namespace Aws @@ -49,10 +47,10 @@ namespace Aws ServiceErrorV2 &operator =(const ServiceErrorV2 &rhs) = default; ServiceErrorV2 &operator =(ServiceErrorV2 &&rhs) = default; - int getErrorCode() const { return m_errorCode; } + int GetErrorCode() const { return m_errorCode; } - bool hasModeledError() const { return m_modeledError.has_value(); } - const E &getModeledError() const { return m_modeledError.value(); } + bool HasModeledError() const { return m_modeledError.has_value(); } + const E &GetModeledError() const { return m_modeledError.value(); } private: @@ -83,24 +81,23 @@ namespace Aws virtual ~IClientV2() = default; - static std::shared_ptr newFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, - const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, - Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); - - static std::shared_ptr newFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, - const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, - Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); - virtual bool DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler) = 0; virtual bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) = 0; virtual bool UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler) = 0; - virtual std::shared_ptr createNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler) = 0; - - virtual std::shared_ptr createNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler) = 0; + virtual std::shared_ptr CreateNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + virtual std::shared_ptr CreateNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; }; + + AWS_IOTSHADOW_API std::shared_ptr NewClientFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); + + AWS_IOTSHADOW_API std::shared_ptr NewClientFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); } } \ No newline at end of file diff --git a/shadow/source/IotShadowClientv2.cpp b/shadow/source/IotShadowClientV2.cpp similarity index 64% rename from shadow/source/IotShadowClientv2.cpp rename to shadow/source/IotShadowClientV2.cpp index ccf693d8c..1e722d1de 100644 --- a/shadow/source/IotShadowClientv2.cpp +++ b/shadow/source/IotShadowClientV2.cpp @@ -4,7 +4,7 @@ * This file is generated */ -#include +#include #include #include @@ -25,91 +25,100 @@ namespace Aws namespace Iotshadow { - class Clientv2 : public IClientV2 + class ClientV2 : public IClientV2 { public: + ClientV2(Aws::Crt::Allocator *allocator, std::shared_ptr bindingClient); + virtual ~ClientV2() = default; - Clientv2(Aws::Crt::Allocator *allocator, Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient); - virtual ~Clientv2() = default; + bool DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler) override; - virtual bool DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler); + bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) override; - virtual bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler); + bool UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler) override; - virtual bool UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler); + std::shared_ptr CreateNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; - virtual std::shared_ptr createNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler); - - virtual std::shared_ptr createNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler); + std::shared_ptr CreateNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; private: Aws::Crt::Allocator *m_allocator; - Aws::Crt::ScopedResource m_bindingClient; + std::shared_ptr m_bindingClient; }; - Clientv2::Clientv2(Aws::Crt::Allocator *allocator, Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient) : + ClientV2::ClientV2(Aws::Crt::Allocator *allocator, std::shared_ptr bindingClient) : m_allocator(allocator), - m_bindingClient(bindingClient, [allocator](Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient) { Aws::Crt::Delete(bindingClient, allocator); }) + m_bindingClient(std::move(bindingClient)) { } - static void s_applyUnmodeledErrorToDeleteNamedShadowHandler(const std::function &handler, int errorCode) { + template + static void s_applyUnmodeledErrorToHandler(const std::function &handler, int errorCode) { ServiceErrorV2 error(errorCode); - Aws::Iotshadow::DeleteShadowResult finalResult(std::move(error)); + R finalResult(std::move(error)); + handler(std::move(finalResult)); + } + + template + static void s_applyModeledErrorToHandler(const std::function &handler, ErrorResponse &&modeledError) { + ServiceErrorV2 error(AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR, std::move(modeledError)); // TBI: MQTT Service error + R finalResult(std::move(error)); handler(std::move(finalResult)); } static void s_DeleteNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - if (!result.isSuccess()) { - s_applyUnmodeledErrorToDeleteNamedShadowHandler(handler, result.getError()); + if (!result.IsSuccess()) { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); return; } - auto response = result.getResponse(); - Aws::Crt::String objectStr(reinterpret_cast(response.payload.ptr), response.payload.len); + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); Aws::Crt::JsonObject jsonObject(objectStr); if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToDeleteNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure return; } - auto responseTopic = Aws::Crt::String((const char *)response.topic.ptr, response.topic.len); + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); if (responseTopic == successPathTopic) { Aws::Iotshadow::DeleteShadowResponse modeledResponse(jsonObject); Aws::Iotshadow::DeleteShadowResult finalResult(std::move(modeledResponse)); handler(std::move(finalResult)); } else if (responseTopic == failurePathTopic) { - Aws::Iotshadow::ErrorResponse modeledResponse(jsonObject); - - Aws::Iotshadow::ServiceErrorV2 modeledError(AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR, std::move(modeledResponse)); // TBI: MQTT Service error - Aws::Iotshadow::DeleteShadowResult finalResult(std::move(modeledError)); - handler(std::move(finalResult)); + Aws::Iotshadow::ErrorResponse modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else { - s_applyUnmodeledErrorToDeleteNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path } } - bool Clientv2::DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler) { + bool ClientV2::DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler) + { Aws::Crt::StringStream publishTopicStream; - publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/delete"; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/delete"; Aws::Crt::String publishTopic = publishTopicStream.str(); Aws::Crt::StringStream subscriptionTopicStream; - subscriptionTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/delete/+"; + subscriptionTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/delete/+"; Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); - struct aws_byte_cursor subscriptionTopicFilters[1] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic) - }; + struct aws_byte_cursor subscriptionTopicFilters[1] = {Aws::Crt::ByteCursorFromString(subscriptionTopic),}; Aws::Crt::StringStream responsePathTopic1Stream; - responsePathTopic1Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/delete/accepted"; + responsePathTopic1Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/delete/accepted"; Aws::Crt::String responsePathTopic1 = responsePathTopic1Stream.str(); Aws::Crt::StringStream responsePathTopic2Stream; - responsePathTopic2Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/delete/rejected"; + responsePathTopic2Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/delete/rejected"; Aws::Crt::String responsePathTopic2 = responsePathTopic2Stream.str(); struct aws_mqtt_request_operation_response_path responsePaths[2]; @@ -133,55 +142,49 @@ namespace Aws options.response_paths = responsePaths; options.response_path_count = 2; options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); - options.serialized_request = Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); - auto resultHandler = [handler, responsePathTopic1, responsePathTopic2](Aws::Iot::RequestResponse::UnmodeledResult &&result){ - s_DeleteNamedShadowResponseHandler(std::move(result), handler, responsePathTopic1, responsePathTopic2); - }; + auto resultHandler = + [handler, responsePathTopic1, responsePathTopic2](Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_DeleteNamedShadowResponseHandler(std::move(result), handler, responsePathTopic1, responsePathTopic2); }; - int submitResult = m_bindingClient->submitRequest(options, std::move(resultHandler)); + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); return submitResult == AWS_OP_SUCCESS; } - static void s_applyUnmodeledErrorToGetNamedShadowHandler(const std::function &handler, int errorCode) { - ServiceErrorV2 error(errorCode); - Aws::Iotshadow::GetShadowResult finalResult(std::move(error)); - handler(std::move(finalResult)); - } - static void s_GetNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - if (!result.isSuccess()) { - s_applyUnmodeledErrorToGetNamedShadowHandler(handler, result.getError()); + if (!result.IsSuccess()) { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); return; } - auto response = result.getResponse(); - Aws::Crt::String objectStr(reinterpret_cast(response.payload.ptr), response.payload.len); + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); Aws::Crt::JsonObject jsonObject(objectStr); if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToGetNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure return; } - auto responseTopic = Aws::Crt::String((const char *)response.topic.ptr, response.topic.len); + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); if (responseTopic == successPathTopic) { Aws::Iotshadow::GetShadowResponse modeledResponse(jsonObject); Aws::Iotshadow::GetShadowResult finalResult(std::move(modeledResponse)); handler(std::move(finalResult)); } else if (responseTopic == failurePathTopic) { - Aws::Iotshadow::ErrorResponse modeledResponse(jsonObject); - - Aws::Iotshadow::ServiceErrorV2 modeledError(AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR, std::move(modeledResponse)); // TBI: MQTT Service error - Aws::Iotshadow::GetShadowResult finalResult(std::move(modeledError)); - handler(std::move(finalResult)); + Aws::Iotshadow::ErrorResponse modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else { - s_applyUnmodeledErrorToGetNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path } } - bool Clientv2::GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) { + bool ClientV2::GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) { Aws::Crt::StringStream publishTopicStream; publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get"; Aws::Crt::String publishTopic = publishTopicStream.str(); @@ -191,7 +194,7 @@ namespace Aws Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); struct aws_byte_cursor subscriptionTopicFilters[1] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic) + Aws::Crt::ByteCursorFromString(subscriptionTopic), }; Aws::Crt::StringStream responsePathTopic1Stream; @@ -230,48 +233,41 @@ namespace Aws s_GetNamedShadowResponseHandler(std::move(result), handler, responsePathTopic1, responsePathTopic2); }; - int submitResult = m_bindingClient->submitRequest(options, std::move(resultHandler)); + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); return submitResult == AWS_OP_SUCCESS; } - static void s_applyUnmodeledErrorToUpdateNamedShadowHandler(const std::function &handler, int errorCode) { - ServiceErrorV2 error(errorCode); - Aws::Iotshadow::UpdateShadowResult finalResult(std::move(error)); - handler(std::move(finalResult)); - } - static void s_UpdateNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - if (!result.isSuccess()) { - s_applyUnmodeledErrorToUpdateNamedShadowHandler(handler, result.getError()); + if (!result.IsSuccess()) { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); return; } - auto response = result.getResponse(); - Aws::Crt::String objectStr(reinterpret_cast(response.payload.ptr), response.payload.len); + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); Aws::Crt::JsonObject jsonObject(objectStr); if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToUpdateNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure return; } - auto responseTopic = Aws::Crt::String((const char *)response.topic.ptr, response.topic.len); + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); if (responseTopic == successPathTopic) { Aws::Iotshadow::UpdateShadowResponse modeledResponse(jsonObject); Aws::Iotshadow::UpdateShadowResult finalResult(std::move(modeledResponse)); handler(std::move(finalResult)); } else if (responseTopic == failurePathTopic) { - Aws::Iotshadow::ErrorResponse modeledResponse(jsonObject); - - Aws::Iotshadow::ServiceErrorV2 modeledError(AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR, std::move(modeledResponse)); // TBI: MQTT Service error - Aws::Iotshadow::UpdateShadowResult finalResult(std::move(modeledError)); - handler(std::move(finalResult)); + Aws::Iotshadow::ErrorResponse modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else { - s_applyUnmodeledErrorToUpdateNamedShadowHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path } } - bool Clientv2::UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler) { + bool ClientV2::UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler) { Aws::Crt::StringStream publishTopicStream; publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update"; Aws::Crt::String publishTopic = publishTopicStream.str(); @@ -286,7 +282,7 @@ namespace Aws struct aws_byte_cursor subscriptionTopicFilters[2] = { Aws::Crt::ByteCursorFromString(subscriptionTopic1), - Aws::Crt::ByteCursorFromString(subscriptionTopic2) + Aws::Crt::ByteCursorFromString(subscriptionTopic2), }; Aws::Crt::StringStream responsePathTopic1Stream; @@ -325,7 +321,7 @@ namespace Aws s_UpdateNamedShadowResponseHandler(std::move(result), handler, responsePathTopic1, responsePathTopic2); }; - int submitResult = m_bindingClient->submitRequest(options, std::move(resultHandler)); + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); return submitResult == AWS_OP_SUCCESS; } @@ -338,25 +334,26 @@ namespace Aws { } - static std::shared_ptr create(Aws::Crt::Allocator *allocator, Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient, const Aws::Crt::String &subscriptionTopicFilter, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler) { + static std::shared_ptr Create(Aws::Crt::Allocator *allocator, const std::shared_ptr &bindingClient, const Aws::Crt::String &subscriptionTopicFilter, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { - std::function unmodeledHandler = [handler](Aws::Iot::RequestResponse::IncomingPublishEvent &&event){ - Aws::Crt::String objectStr(reinterpret_cast(event.payload.ptr), event.payload.len); + std::function unmodeledHandler = [options](Aws::Iot::RequestResponse::IncomingPublishEvent &&event){ + const auto &payload = event.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); Aws::Crt::JsonObject jsonObject(objectStr); if (!jsonObject.WasParseSuccessful()) { return; } T modeledEvent(jsonObject); - handler(std::move(modeledEvent)); + options.GetStreamHandler()(std::move(modeledEvent)); }; Aws::Iot::RequestResponse::StreamingOperationOptionsInternal internalOptions; internalOptions.subscriptionTopicFilter = Aws::Crt::ByteCursorFromString(subscriptionTopicFilter); - internalOptions.subscriptionStatusEventHandler = options.subscriptionStatusEventHandler; + internalOptions.subscriptionStatusEventHandler = options.GetSubscriptionStatusEventHandler(); internalOptions.incomingPublishEventHandler = unmodeledHandler; - auto unmodeledStream = bindingClient->createStream(internalOptions); + auto unmodeledStream = bindingClient->CreateStream(internalOptions); if (!unmodeledStream) { return nullptr; } @@ -364,8 +361,8 @@ namespace Aws return Aws::Crt::MakeShared(allocator, unmodeledStream); } - virtual void activate() { - m_stream->activate(); + void Open() override { + m_stream->Open(); } private: @@ -373,44 +370,44 @@ namespace Aws std::shared_ptr m_stream; }; - std::shared_ptr Clientv2::createNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler) { + std::shared_ptr ClientV2::CreateNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { Aws::Crt::StringStream topicStream; topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/delta"; Aws::Crt::String topic = topicStream.str(); - return ShadowStreamingOperation::create(m_allocator, m_bindingClient.get(), topic, options, handler); + return ShadowStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); } - std::shared_ptr Clientv2::createNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options, const std::function &handler) { + std::shared_ptr ClientV2::CreateNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { Aws::Crt::StringStream topicStream; topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/documents"; Aws::Crt::String topic = topicStream.str(); - return ShadowStreamingOperation::create(m_allocator, m_bindingClient.get(), topic, options, handler); + return ShadowStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); } - std::shared_ptr IClientV2::newFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + std::shared_ptr NewClientFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, Aws::Crt::Allocator *allocator) { - Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient = Aws::Iot::RequestResponse::IMqttRequestResponseClient::newFrom5(protocolClient, options, allocator); - if (!bindingClient) { + std::shared_ptr bindingClient = Aws::Iot::RequestResponse::NewClientFrom5(protocolClient, options, allocator); + if (nullptr == bindingClient) { return nullptr; } - return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); } - std::shared_ptr IClientV2::newFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, + std::shared_ptr NewClientFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, Aws::Crt::Allocator *allocator) { - Aws::Iot::RequestResponse::IMqttRequestResponseClient *bindingClient = Aws::Iot::RequestResponse::IMqttRequestResponseClient::newFrom311(protocolClient, options, allocator); - if (!bindingClient) { + std::shared_ptr bindingClient = Aws::Iot::RequestResponse::NewClientFrom311(protocolClient, options, allocator); + if (nullptr == bindingClient) { return nullptr; } - return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); } } From f8567cd872a7c69d757f6ee3cd0ba0ddd7e2f04d Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Wed, 16 Oct 2024 09:12:40 -0700 Subject: [PATCH 04/33] Checkpoint pre gen diff --- .../include/aws/iotshadow/IotShadowClientV2.h | 260 ++++- shadow/source/IotShadowClientV2.cpp | 968 ++++++++++++------ 2 files changed, 875 insertions(+), 353 deletions(-) diff --git a/shadow/include/aws/iotshadow/IotShadowClientV2.h b/shadow/include/aws/iotshadow/IotShadowClientV2.h index 46d61e2f9..d125e870d 100644 --- a/shadow/include/aws/iotshadow/IotShadowClientV2.h +++ b/shadow/include/aws/iotshadow/IotShadowClientV2.h @@ -12,19 +12,28 @@ #include #include +#include + namespace Aws { - namespace Crt { - namespace Mqtt { + namespace Crt + { + namespace Mqtt + { class MqttConnection; } - namespace Mqtt5 { + namespace Mqtt5 + { class Mqtt5Client; } - } + } // namespace Crt +} // namespace Aws +namespace Aws +{ namespace Iotshadow { + template class ServiceErrorV2 { public: @@ -32,20 +41,17 @@ namespace Aws ServiceErrorV2(const ServiceErrorV2 &rhs) = default; ServiceErrorV2(ServiceErrorV2 &&rhs) = default; - explicit ServiceErrorV2(int errorCode) : - m_errorCode(errorCode), - m_modeledError() - {} + explicit ServiceErrorV2(int errorCode) : m_errorCode(errorCode), m_modeledError() {} - ServiceErrorV2(int errorCode, E &&modeledError) : - m_errorCode(errorCode), - m_modeledError(std::move(modeledError)) - {} + ServiceErrorV2(int errorCode, E &&modeledError) + : m_errorCode(errorCode), m_modeledError(std::move(modeledError)) + { + } ~ServiceErrorV2() = default; - ServiceErrorV2 &operator =(const ServiceErrorV2 &rhs) = default; - ServiceErrorV2 &operator =(ServiceErrorV2 &&rhs) = default; + ServiceErrorV2 &operator=(const ServiceErrorV2 &rhs) = default; + ServiceErrorV2 &operator=(ServiceErrorV2 &&rhs) = default; int GetErrorCode() const { return m_errorCode; } @@ -53,51 +59,239 @@ namespace Aws const E &GetModeledError() const { return m_modeledError.value(); } private: - int m_errorCode; Aws::Crt::Optional m_modeledError; }; - class ErrorResponse; class DeleteNamedShadowRequest; + class DeleteShadowRequest; class DeleteShadowResponse; class GetNamedShadowRequest; + class GetShadowRequest; class GetShadowResponse; class NamedShadowDeltaUpdatedSubscriptionRequest; class NamedShadowUpdatedSubscriptionRequest; class ShadowDeltaUpdatedEvent; + class ShadowDeltaUpdatedSubscriptionRequest; class ShadowUpdatedEvent; + class ShadowUpdatedSubscriptionRequest; class UpdateNamedShadowRequest; + class UpdateShadowRequest; class UpdateShadowResponse; - using DeleteShadowResult = Aws::Iot::RequestResponse::Result>; - using GetShadowResult = Aws::Iot::RequestResponse::Result>; - using UpdateShadowResult = Aws::Iot::RequestResponse::Result>; + using DeleteNamedShadowResultHandler = std::function> &&)>; + using DeleteShadowResultHandler = std::function> &&)>; + using GetNamedShadowResultHandler = std::function> &&)>; + using GetShadowResultHandler = std::function> &&)>; + using UpdateNamedShadowResultHandler = std::function> &&)>; + using UpdateShadowResultHandler = std::function> &&)>; + /** + * The AWS IoT Device Shadow service adds shadows to AWS IoT thing objects. Shadows are a simple data store for + * device properties and state. Shadows can make a device’s state available to apps and other services whether + * the device is connected to AWS IoT or not. + * + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html + * + */ class AWS_IOTSHADOW_API IClientV2 { public: - virtual ~IClientV2() = default; - virtual bool DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler) = 0; + /** + * Deletes a named shadow for an AWS IoT thing. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html#delete-pub-sub-topic + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool DeleteNamedShadow( + const DeleteNamedShadowRequest &request, + const DeleteNamedShadowResultHandler &handler) = 0; + + /** + * Deletes the (classic) shadow for an AWS IoT thing. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html#delete-pub-sub-topic + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool DeleteShadow(const DeleteShadowRequest &request, const DeleteShadowResultHandler &handler) = 0; + + /** + * Gets a named shadow for an AWS IoT thing. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html#get-pub-sub-topic + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool GetNamedShadow( + const GetNamedShadowRequest &request, + const GetNamedShadowResultHandler &handler) = 0; + + /** + * Gets the (classic) shadow for an AWS IoT thing. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html#get-pub-sub-topic + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool GetShadow(const GetShadowRequest &request, const GetShadowResultHandler &handler) = 0; - virtual bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) = 0; + /** + * Update a named shadow for a device. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html#update-pub-sub-topic + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool UpdateNamedShadow( + const UpdateNamedShadowRequest &request, + const UpdateNamedShadowResultHandler &handler) = 0; - virtual bool UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler) = 0; + /** + * Update a device's (classic) shadow. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html#update-pub-sub-topic + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool UpdateShadow(const UpdateShadowRequest &request, const UpdateShadowResultHandler &handler) = 0; - virtual std::shared_ptr CreateNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + /** + * Create a stream for NamedShadowDelta events for a named shadow of an AWS IoT thing. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html#update-delta-pub-sub-topic + * + * @param request modeled streaming operation subscription configuration + * @param options + * + * @returns a streaming operation which will emit a modeled event every time a message is received on the + * associated MQTT topic + */ + virtual std::shared_ptr CreateNamedShadowDeltaUpdatedStream( + const NamedShadowDeltaUpdatedSubscriptionRequest &request, + const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; - virtual std::shared_ptr CreateNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + /** + * Create a stream for ShadowUpdated events for a named shadow of an AWS IoT thing. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html#update-documents-pub-sub-topic + * + * @param request modeled streaming operation subscription configuration + * @param options + * + * @returns a streaming operation which will emit a modeled event every time a message is received on the + * associated MQTT topic + */ + virtual std::shared_ptr CreateNamedShadowUpdatedStream( + const NamedShadowUpdatedSubscriptionRequest &request, + const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + + /** + * Create a stream for ShadowDelta events for the (classic) shadow of an AWS IoT thing. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html#update-delta-pub-sub-topic + * + * @param request modeled streaming operation subscription configuration + * @param options + * + * @returns a streaming operation which will emit a modeled event every time a message is received on the + * associated MQTT topic + */ + virtual std::shared_ptr CreateShadowDeltaUpdatedStream( + const ShadowDeltaUpdatedSubscriptionRequest &request, + const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + + /** + * Create a stream for ShadowUpdated events for the (classic) shadow of an AWS IoT thing. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-mqtt.html#update-documents-pub-sub-topic + * + * @param request modeled streaming operation subscription configuration + * @param options + * + * @returns a streaming operation which will emit a modeled event every time a message is received on the + * associated MQTT topic + */ + virtual std::shared_ptr CreateShadowUpdatedStream( + const ShadowUpdatedSubscriptionRequest &request, + const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; }; - AWS_IOTSHADOW_API std::shared_ptr NewClientFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, - const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, - Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); + /** + * Creates a new service client that uses an SDK MQTT5 client for transport. + * + * @param protocolClient MQTT client to use as transport + * @param options request-response MQTT client configuration options + * @param allocator memory allocator to use for all client functionality + * + * @return a new service client + */ + AWS_IOTSHADOW_API std::shared_ptr NewClientFrom5( + const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); + + /** + * Creates a new service client that uses an SDK MQTT311 client for transport. + * + * @param protocolClient MQTT client to use as transport + * @param options request-response MQTT client configuration options + * @param allocator memory allocator to use for all client functionality + * + * @return a new service client + */ + AWS_IOTSHADOW_API std::shared_ptr NewClientFrom311( + const Aws::Crt::Mqtt::MqttConnection &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); - AWS_IOTSHADOW_API std::shared_ptr NewClientFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, - const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, - Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); - } -} \ No newline at end of file + } // namespace Iotshadow +} // namespace Aws diff --git a/shadow/source/IotShadowClientV2.cpp b/shadow/source/IotShadowClientV2.cpp index 1e722d1de..433f2c517 100644 --- a/shadow/source/IotShadowClientV2.cpp +++ b/shadow/source/IotShadowClientV2.cpp @@ -1,414 +1,742 @@ /* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -* SPDX-License-Identifier: Apache-2.0. -* -* This file is generated -*/ - + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ #include #include + #include +#include #include -#include #include +#include #include #include #include #include +#include #include +#include #include +#include #include namespace Aws { +namespace Iotshadow +{ - namespace Iotshadow - { +class ClientV2 : public IClientV2 +{ + public: + ClientV2(Aws::Crt::Allocator *allocator, std::shared_ptr bindingClient); + virtual ~ClientV2() = default; - class ClientV2 : public IClientV2 - { - public: - ClientV2(Aws::Crt::Allocator *allocator, std::shared_ptr bindingClient); - virtual ~ClientV2() = default; + bool DeleteNamedShadow(const DeleteNamedShadowRequest &request, const DeleteNamedShadowResultHandler &handler) override; - bool DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler) override; + bool DeleteShadow(const DeleteShadowRequest &request, const DeleteShadowResultHandler &handler) override; - bool GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) override; + bool GetNamedShadow(const GetNamedShadowRequest &request, const GetNamedShadowResultHandler &handler) override; - bool UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler) override; + bool GetShadow(const GetShadowRequest &request, const GetShadowResultHandler &handler) override; - std::shared_ptr CreateNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; + bool UpdateNamedShadow(const UpdateNamedShadowRequest &request, const UpdateNamedShadowResultHandler &handler) override; - std::shared_ptr CreateNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; + bool UpdateShadow(const UpdateShadowRequest &request, const UpdateShadowResultHandler &handler) override; - private: - Aws::Crt::Allocator *m_allocator; + std::shared_ptr CreateNamedShadowDeltaUpdatedStream(const NamedShadowDeltaUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; - std::shared_ptr m_bindingClient; - }; + std::shared_ptr CreateNamedShadowUpdatedStream(const NamedShadowUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; - ClientV2::ClientV2(Aws::Crt::Allocator *allocator, std::shared_ptr bindingClient) : - m_allocator(allocator), - m_bindingClient(std::move(bindingClient)) - { - } + std::shared_ptr CreateShadowDeltaUpdatedStream(const ShadowDeltaUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; - template - static void s_applyUnmodeledErrorToHandler(const std::function &handler, int errorCode) { - ServiceErrorV2 error(errorCode); - R finalResult(std::move(error)); - handler(std::move(finalResult)); - } + std::shared_ptr CreateShadowUpdatedStream(const ShadowUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; - template - static void s_applyModeledErrorToHandler(const std::function &handler, ErrorResponse &&modeledError) { - ServiceErrorV2 error(AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR, std::move(modeledError)); // TBI: MQTT Service error - R finalResult(std::move(error)); - handler(std::move(finalResult)); - } - static void s_DeleteNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - if (!result.IsSuccess()) { - s_applyUnmodeledErrorToHandler(handler, result.GetError()); - return; - } + private: - auto response = result.GetResponse(); - const auto &payload = response.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure - return; - } + Aws::Crt::Allocator *m_allocator; - const auto &topic = response.GetTopic(); - auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); - if (responseTopic == successPathTopic) { - Aws::Iotshadow::DeleteShadowResponse modeledResponse(jsonObject); - Aws::Iotshadow::DeleteShadowResult finalResult(std::move(modeledResponse)); - handler(std::move(finalResult)); - } else if (responseTopic == failurePathTopic) { - Aws::Iotshadow::ErrorResponse modeledError(jsonObject); - s_applyModeledErrorToHandler(handler, std::move(modeledError)); - } else { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path - } - } + std::shared_ptr m_bindingClient; +}; - bool ClientV2::DeleteNamedShadow(const Aws::Iotshadow::DeleteNamedShadowRequest &request, const std::function &handler) - { - Aws::Crt::StringStream publishTopicStream; - publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName - << "/delete"; - Aws::Crt::String publishTopic = publishTopicStream.str(); - - Aws::Crt::StringStream subscriptionTopicStream; - subscriptionTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName - << "/delete/+"; - Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); - - struct aws_byte_cursor subscriptionTopicFilters[1] = {Aws::Crt::ByteCursorFromString(subscriptionTopic),}; - - Aws::Crt::StringStream responsePathTopic1Stream; - responsePathTopic1Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName - << "/delete/accepted"; - Aws::Crt::String responsePathTopic1 = responsePathTopic1Stream.str(); - - Aws::Crt::StringStream responsePathTopic2Stream; - responsePathTopic2Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName - << "/delete/rejected"; - Aws::Crt::String responsePathTopic2 = responsePathTopic2Stream.str(); - - struct aws_mqtt_request_operation_response_path responsePaths[2]; - responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopic1); - responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopic2); - responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - - Aws::Crt::JsonObject jsonObject; - request.SerializeToObject(jsonObject); - - auto uuid = Aws::Crt::UUID().ToString(); - jsonObject.WithString("clientToken", uuid); - - Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); - - struct aws_mqtt_request_operation_options options; - AWS_ZERO_STRUCT(options); - options.subscription_topic_filters = subscriptionTopicFilters; - options.subscription_topic_filter_count = 1; - options.response_paths = responsePaths; - options.response_path_count = 2; - options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); - options.serialized_request = - Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); - options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); - - auto resultHandler = - [handler, responsePathTopic1, responsePathTopic2](Aws::Iot::RequestResponse::UnmodeledResult &&result) - { s_DeleteNamedShadowResponseHandler(std::move(result), handler, responsePathTopic1, responsePathTopic2); }; - - int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); - - return submitResult == AWS_OP_SUCCESS; - } +ClientV2::ClientV2(Aws::Crt::Allocator *allocator, std::shared_ptr bindingClient) : + m_allocator(allocator), + m_bindingClient(std::move(bindingClient)) +{ +} - static void s_GetNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - if (!result.IsSuccess()) { - s_applyUnmodeledErrorToHandler(handler, result.GetError()); - return; - } +template +static void s_applyUnmodeledErrorToHandler(const std::function &handler, int errorCode) { + ServiceErrorV2 error(errorCode); + R finalResult(std::move(error)); + handler(std::move(finalResult)); +} - auto response = result.GetResponse(); - const auto &payload = response.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure - return; - } +template +static void s_applyModeledErrorToHandler(const std::function &handler, E &&modeledError) { + ServiceErrorV2 error(AWS_ERROR_MQTT_REQUEST_RESPONSE_MODELED_SERVICE_ERROR, std::move(modeledError)); + R finalResult(std::move(error)); + handler(std::move(finalResult)); +} - const auto &topic = response.GetTopic(); - auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); - if (responseTopic == successPathTopic) { - Aws::Iotshadow::GetShadowResponse modeledResponse(jsonObject); - Aws::Iotshadow::GetShadowResult finalResult(std::move(modeledResponse)); - handler(std::move(finalResult)); - } else if (responseTopic == failurePathTopic) { - Aws::Iotshadow::ErrorResponse modeledError(jsonObject); - s_applyModeledErrorToHandler(handler, std::move(modeledError)); - } else { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path - } - } - bool ClientV2::GetNamedShadow(const Aws::Iotshadow::GetNamedShadowRequest &request, const std::function &handler) { - Aws::Crt::StringStream publishTopicStream; - publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get"; - Aws::Crt::String publishTopic = publishTopicStream.str(); - Aws::Crt::StringStream subscriptionTopicStream; - subscriptionTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/+"; - Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); +static void s_DeleteNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; - struct aws_byte_cursor subscriptionTopicFilters[1] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic), - }; + if (!result.IsSuccess()) { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } - Aws::Crt::StringStream responsePathTopic1Stream; - responsePathTopic1Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/accepted"; - Aws::Crt::String responsePathTopic1 = responsePathTopic1Stream.str(); + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } - Aws::Crt::StringStream responsePathTopic2Stream; - responsePathTopic2Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get/rejected"; - Aws::Crt::String responsePathTopic2 = responsePathTopic2Stream.str(); + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) { + DeleteShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); + handler(std::move(finalResult)); + } else if (responseTopic == failurePathTopic) { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } else { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } +} - struct aws_mqtt_request_operation_response_path responsePaths[2]; - responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopic1); - responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopic2); - responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); +bool ClientV2::DeleteNamedShadow(const DeleteNamedShadowRequest &request, const DeleteNamedShadowResultHandler &handler) { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/delete"; + Aws::Crt::String publishTopic = publishTopicStream.str(); - Aws::Crt::JsonObject jsonObject; - request.SerializeToObject(jsonObject); + Aws::Crt::StringStream subscriptionTopicStream; + subscriptionTopicStream << publishTopic << "/+"; + Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); - auto uuid = Aws::Crt::UUID().ToString(); - jsonObject.WithString("clientToken", uuid); - Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic) + }; - struct aws_mqtt_request_operation_options options; - AWS_ZERO_STRUCT(options); - options.subscription_topic_filters = subscriptionTopicFilters; - options.subscription_topic_filter_count = 1; - options.response_paths = responsePaths; - options.response_path_count = 2; - options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); - options.serialized_request = Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); - options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); - auto resultHandler = [handler, responsePathTopic1, responsePathTopic2](Aws::Iot::RequestResponse::UnmodeledResult &&result){ - s_GetNamedShadowResponseHandler(std::move(result), handler, responsePathTopic1, responsePathTopic2); - }; + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); - int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - return submitResult == AWS_OP_SUCCESS; - } + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); - static void s_UpdateNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - if (!result.IsSuccess()) { - s_applyUnmodeledErrorToHandler(handler, result.GetError()); - return; - } + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); - auto response = result.GetResponse(); - const auto &payload = response.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: Payload Parse failure - return; - } + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); - const auto &topic = response.GetTopic(); - auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); - if (responseTopic == successPathTopic) { - Aws::Iotshadow::UpdateShadowResponse modeledResponse(jsonObject); - Aws::Iotshadow::UpdateShadowResult finalResult(std::move(modeledResponse)); - handler(std::move(finalResult)); - } else if (responseTopic == failurePathTopic) { - Aws::Iotshadow::ErrorResponse modeledError(jsonObject); - s_applyModeledErrorToHandler(handler, std::move(modeledError)); - } else { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INTERNAL_ERROR); // TBI: invalid response path - } - } + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); - bool ClientV2::UpdateNamedShadow(const Aws::Iotshadow::UpdateNamedShadowRequest &request, const std::function &handler) { - Aws::Crt::StringStream publishTopicStream; - publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update"; - Aws::Crt::String publishTopic = publishTopicStream.str(); + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); - Aws::Crt::StringStream subscriptionTopic1Stream; - subscriptionTopic1Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/accepted"; - Aws::Crt::String subscriptionTopic1 = subscriptionTopic1Stream.str(); + auto resultHandler = + [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_DeleteNamedShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; - Aws::Crt::StringStream subscriptionTopic2Stream; - subscriptionTopic2Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/rejected"; - Aws::Crt::String subscriptionTopic2 = subscriptionTopic2Stream.str(); + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); - struct aws_byte_cursor subscriptionTopicFilters[2] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic1), - Aws::Crt::ByteCursorFromString(subscriptionTopic2), - }; + return submitResult == AWS_OP_SUCCESS; +} - Aws::Crt::StringStream responsePathTopic1Stream; - responsePathTopic1Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/accepted"; - Aws::Crt::String responsePathTopic1 = responsePathTopic1Stream.str(); - Aws::Crt::StringStream responsePathTopic2Stream; - responsePathTopic2Stream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/rejected"; - Aws::Crt::String responsePathTopic2 = responsePathTopic2Stream.str(); +static void s_DeleteShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; - struct aws_mqtt_request_operation_response_path responsePaths[2]; - responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopic1); - responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopic2); - responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + if (!result.IsSuccess()) { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } - Aws::Crt::JsonObject jsonObject; - request.SerializeToObject(jsonObject); + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } - auto uuid = Aws::Crt::UUID().ToString(); - jsonObject.WithString("clientToken", uuid); + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) { + DeleteShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); + handler(std::move(finalResult)); + } else if (responseTopic == failurePathTopic) { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } else { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } +} - Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); +bool ClientV2::DeleteShadow(const DeleteShadowRequest &request, const DeleteShadowResultHandler &handler) { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/delete"; + Aws::Crt::String publishTopic = publishTopicStream.str(); - struct aws_mqtt_request_operation_options options; - AWS_ZERO_STRUCT(options); - options.subscription_topic_filters = subscriptionTopicFilters; - options.subscription_topic_filter_count = 2; - options.response_paths = responsePaths; - options.response_path_count = 2; - options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); - options.serialized_request = Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); - options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + Aws::Crt::StringStream subscriptionTopicStream; + subscriptionTopicStream << publishTopic << "/+"; + Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); - auto resultHandler = [handler, responsePathTopic1, responsePathTopic2](Aws::Iot::RequestResponse::UnmodeledResult &&result){ - s_UpdateNamedShadowResponseHandler(std::move(result), handler, responsePathTopic1, responsePathTopic2); - }; - int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic) + }; - return submitResult == AWS_OP_SUCCESS; - } + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); - template class ShadowStreamingOperation : public Aws::Iot::RequestResponse::IStreamingOperation { - public: + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); - explicit ShadowStreamingOperation(std::shared_ptr stream) : - m_stream(std::move(stream)) - { - } + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - static std::shared_ptr Create(Aws::Crt::Allocator *allocator, const std::shared_ptr &bindingClient, const Aws::Crt::String &subscriptionTopicFilter, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); - std::function unmodeledHandler = [options](Aws::Iot::RequestResponse::IncomingPublishEvent &&event){ - const auto &payload = event.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - return; - } + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); - T modeledEvent(jsonObject); - options.GetStreamHandler()(std::move(modeledEvent)); - }; + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); - Aws::Iot::RequestResponse::StreamingOperationOptionsInternal internalOptions; - internalOptions.subscriptionTopicFilter = Aws::Crt::ByteCursorFromString(subscriptionTopicFilter); - internalOptions.subscriptionStatusEventHandler = options.GetSubscriptionStatusEventHandler(); - internalOptions.incomingPublishEventHandler = unmodeledHandler; + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); - auto unmodeledStream = bindingClient->CreateStream(internalOptions); - if (!unmodeledStream) { - return nullptr; - } + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); - return Aws::Crt::MakeShared(allocator, unmodeledStream); - } + auto resultHandler = + [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_DeleteShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; - void Open() override { - m_stream->Open(); - } + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); - private: + return submitResult == AWS_OP_SUCCESS; +} - std::shared_ptr m_stream; - }; - std::shared_ptr ClientV2::CreateNamedShadowDeltaUpdatedStream(const Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { - Aws::Crt::StringStream topicStream; - topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/delta"; - Aws::Crt::String topic = topicStream.str(); +static void s_GetNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; - return ShadowStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); - } + if (!result.IsSuccess()) { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } - std::shared_ptr ClientV2::CreateNamedShadowUpdatedStream(const Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest &request, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { - Aws::Crt::StringStream topicStream; - topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/documents"; - Aws::Crt::String topic = topicStream.str(); + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } - return ShadowStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); - } + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) { + GetShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); + handler(std::move(finalResult)); + } else if (responseTopic == failurePathTopic) { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } else { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } +} - std::shared_ptr NewClientFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, - const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, - Aws::Crt::Allocator *allocator) { +bool ClientV2::GetNamedShadow(const GetNamedShadowRequest &request, const GetNamedShadowResultHandler &handler) { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get"; + Aws::Crt::String publishTopic = publishTopicStream.str(); - std::shared_ptr bindingClient = Aws::Iot::RequestResponse::NewClientFrom5(protocolClient, options, allocator); - if (nullptr == bindingClient) { - return nullptr; - } + Aws::Crt::StringStream subscriptionTopicStream; + subscriptionTopicStream << publishTopic << "/+"; + Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); + + + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic) + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = + [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_GetNamedShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; +} + + +static void s_GetShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) { + GetShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); + handler(std::move(finalResult)); + } else if (responseTopic == failurePathTopic) { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } else { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } +} + +bool ClientV2::GetShadow(const GetShadowRequest &request, const GetShadowResultHandler &handler) { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/get"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream; + subscriptionTopicStream << publishTopic << "/+"; + Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); + + + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic) + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = + [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_GetShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; - return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; +} + + +static void s_UpdateNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) { + UpdateShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); + handler(std::move(finalResult)); + } else if (responseTopic == failurePathTopic) { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } else { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } +} + +bool ClientV2::UpdateNamedShadow(const UpdateNamedShadowRequest &request, const UpdateNamedShadowResultHandler &handler) { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + Aws::Crt::StringStream subscriptionTopicStream1; + subscriptionTopicStream1 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update"; + Aws::Crt::String subscriptionTopic1 = subscriptionTopicStream1.str(); + + + struct aws_byte_cursor subscriptionTopicFilters[2] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + Aws::Crt::ByteCursorFromString(subscriptionTopic1), + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 2; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = + [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_UpdateNamedShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; +} + + +static void s_UpdateShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) { + UpdateShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); + handler(std::move(finalResult)); + } else if (responseTopic == failurePathTopic) { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } else { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } +} + +bool ClientV2::UpdateShadow(const UpdateShadowRequest &request, const UpdateShadowResultHandler &handler) { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/update"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/shadow/update"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + Aws::Crt::StringStream subscriptionTopicStream1; + subscriptionTopicStream1 << "$aws/things/" << *request.ThingName << "/shadow/update"; + Aws::Crt::String subscriptionTopic1 = subscriptionTopicStream1.str(); + + + struct aws_byte_cursor subscriptionTopicFilters[2] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + Aws::Crt::ByteCursorFromString(subscriptionTopic1), + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 2; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = + [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_UpdateShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; +} + + + +template class ServiceStreamingOperation : public Aws::Iot::RequestResponse::IStreamingOperation { + public: + + explicit ShadowStreamingOperation(std::shared_ptr stream) : + m_stream(std::move(stream)) + { } - std::shared_ptr NewClientFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, - const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, - Aws::Crt::Allocator *allocator) { + static std::shared_ptr Create(Aws::Crt::Allocator *allocator, const std::shared_ptr &bindingClient, const Aws::Crt::String &subscriptionTopicFilter, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { + + std::function unmodeledHandler = [options](Aws::Iot::RequestResponse::IncomingPublishEvent &&event){ + const auto &payload = event.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) { + return; + } + + T modeledEvent(jsonObject); + options.GetStreamHandler()(std::move(modeledEvent)); + }; - std::shared_ptr bindingClient = Aws::Iot::RequestResponse::NewClientFrom311(protocolClient, options, allocator); - if (nullptr == bindingClient) { + Aws::Iot::RequestResponse::StreamingOperationOptionsInternal internalOptions; + internalOptions.subscriptionTopicFilter = Aws::Crt::ByteCursorFromString(subscriptionTopicFilter); + internalOptions.subscriptionStatusEventHandler = options.GetSubscriptionStatusEventHandler(); + internalOptions.incomingPublishEventHandler = unmodeledHandler; + + auto unmodeledStream = bindingClient->CreateStream(internalOptions); + if (!unmodeledStream) { return nullptr; } - return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + return Aws::Crt::MakeShared(allocator, unmodeledStream); + } + + void Open() override { + m_stream->Open(); } + private: + + std::shared_ptr m_stream; +}; + +std::shared_ptr ClientV2::CreateNamedShadowDeltaUpdatedStream(const NamedShadowDeltaUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/delta"; + Aws::Crt::String topic = topicStream.str(); + + return ServiceStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); +} + +std::shared_ptr ClientV2::CreateNamedShadowUpdatedStream(const NamedShadowUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/documents"; + Aws::Crt::String topic = topicStream.str(); + + return ServiceStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); +} + +std::shared_ptr ClientV2::CreateShadowDeltaUpdatedStream(const ShadowDeltaUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/shadow/update/delta"; + Aws::Crt::String topic = topicStream.str(); + + return ServiceStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); +} + +std::shared_ptr ClientV2::CreateShadowUpdatedStream(const ShadowUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/shadow/update/documents"; + Aws::Crt::String topic = topicStream.str(); + + return ServiceStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); +} + + + +std::shared_ptr NewClientFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator) { + + std::shared_ptr bindingClient = Aws::Iot::RequestResponse::NewClientFrom5(protocolClient, options, allocator); + if (nullptr == bindingClient) { + return nullptr; + } + + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); +} + +std::shared_ptr NewClientFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator) { + + std::shared_ptr bindingClient = Aws::Iot::RequestResponse::NewClientFrom311(protocolClient, options, allocator); + if (nullptr == bindingClient) { + return nullptr; } -} \ No newline at end of file + + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); +} + +} +} From 8f357e181336b85129f0c6cace638579b436c710 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Wed, 16 Oct 2024 19:25:11 -0700 Subject: [PATCH 05/33] V2 Codegen Building --- crt/aws-crt-cpp | 2 +- .../aws/iotidentity/IotIdentityClientV2.h | 177 ++ .../include/aws/iotidentity/V2ServiceError.h | 55 + .../CreateKeysAndCertificateRequest.cpp | 5 +- identity/source/ErrorResponse.cpp | 5 +- identity/source/IotIdentityClient.cpp | 205 +-- identity/source/IotIdentityClientV2.cpp | 470 ++++++ identity/source/RegisterThingRequest.cpp | 5 +- identity/source/RegisterThingResponse.cpp | 5 +- .../RegisterThingSubscriptionRequest.cpp | 5 +- identity/source/V2ServiceError.cpp | 66 + jobs/include/aws/iotjobs/IotJobsClientV2.h | 232 +++ jobs/include/aws/iotjobs/JobStatus.h | 2 +- jobs/include/aws/iotjobs/RejectedErrorCode.h | 2 +- jobs/include/aws/iotjobs/V2ServiceError.h | 72 + jobs/source/IotJobsClient.cpp | 322 ++-- jobs/source/IotJobsClientV2.cpp | 630 ++++++++ jobs/source/JobExecutionData.cpp | 5 +- jobs/source/JobExecutionState.cpp | 5 +- jobs/source/JobExecutionSummary.cpp | 5 +- jobs/source/JobExecutionsChangedEvent.cpp | 5 +- jobs/source/JobStatus.cpp | 2 +- jobs/source/RejectedError.cpp | 5 +- jobs/source/RejectedErrorCode.cpp | 2 +- jobs/source/UpdateJobExecutionRequest.cpp | 5 +- jobs/source/UpdateJobExecutionResponse.cpp | 5 +- jobs/source/V2ServiceError.cpp | 88 + .../include/aws/iotshadow/IotShadowClientV2.h | 9 +- shadow/include/aws/iotshadow/V2ServiceError.h | 64 + shadow/source/DeleteNamedShadowRequest.cpp | 5 +- shadow/source/DeleteShadowRequest.cpp | 5 +- shadow/source/DeleteShadowResponse.cpp | 5 +- .../DeleteShadowSubscriptionRequest.cpp | 5 +- shadow/source/ErrorResponse.cpp | 5 +- shadow/source/GetNamedShadowRequest.cpp | 5 +- .../GetNamedShadowSubscriptionRequest.cpp | 5 +- shadow/source/GetShadowRequest.cpp | 5 +- shadow/source/GetShadowResponse.cpp | 5 +- .../source/GetShadowSubscriptionRequest.cpp | 5 +- shadow/source/IotShadowClient.cpp | 541 +++---- shadow/source/IotShadowClientV2.cpp | 1440 +++++++++-------- shadow/source/ShadowDeltaUpdatedEvent.cpp | 5 +- shadow/source/ShadowMetadata.cpp | 5 +- shadow/source/ShadowState.cpp | 5 +- shadow/source/ShadowStateWithDelta.cpp | 5 +- shadow/source/ShadowUpdatedEvent.cpp | 5 +- shadow/source/ShadowUpdatedSnapshot.cpp | 5 +- .../ShadowUpdatedSubscriptionRequest.cpp | 5 +- shadow/source/UpdateNamedShadowRequest.cpp | 5 +- shadow/source/UpdateShadowRequest.cpp | 5 +- shadow/source/UpdateShadowResponse.cpp | 5 +- .../UpdateShadowSubscriptionRequest.cpp | 5 +- shadow/source/V2ServiceError.cpp | 76 + 53 files changed, 3260 insertions(+), 1362 deletions(-) create mode 100644 identity/include/aws/iotidentity/IotIdentityClientV2.h create mode 100644 identity/include/aws/iotidentity/V2ServiceError.h create mode 100644 identity/source/IotIdentityClientV2.cpp create mode 100644 identity/source/V2ServiceError.cpp create mode 100644 jobs/include/aws/iotjobs/IotJobsClientV2.h create mode 100644 jobs/include/aws/iotjobs/V2ServiceError.h create mode 100644 jobs/source/IotJobsClientV2.cpp create mode 100644 jobs/source/V2ServiceError.cpp create mode 100644 shadow/include/aws/iotshadow/V2ServiceError.h create mode 100644 shadow/source/V2ServiceError.cpp diff --git a/crt/aws-crt-cpp b/crt/aws-crt-cpp index dfdd59a78..6ff68c5fa 160000 --- a/crt/aws-crt-cpp +++ b/crt/aws-crt-cpp @@ -1 +1 @@ -Subproject commit dfdd59a7896ccab047d630cd6f38a588857fbcae +Subproject commit 6ff68c5fa0f151cb59a781227f3c66770046487a diff --git a/identity/include/aws/iotidentity/IotIdentityClientV2.h b/identity/include/aws/iotidentity/IotIdentityClientV2.h new file mode 100644 index 000000000..1a75ff97e --- /dev/null +++ b/identity/include/aws/iotidentity/IotIdentityClientV2.h @@ -0,0 +1,177 @@ +#pragma once + +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ + +#include + +#include +#include +#include + +#include + +namespace Aws +{ + namespace Crt + { + namespace Mqtt + { + class MqttConnection; + } + namespace Mqtt5 + { + class Mqtt5Client; + } + } // namespace Crt +} // namespace Aws + +namespace Aws +{ + namespace Iotidentity + { + + template class ServiceErrorV2 + { + public: + ServiceErrorV2() = delete; + ServiceErrorV2(const ServiceErrorV2 &rhs) = default; + ServiceErrorV2(ServiceErrorV2 &&rhs) = default; + + explicit ServiceErrorV2(int errorCode) : m_errorCode(errorCode), m_modeledError() {} + + ServiceErrorV2(int errorCode, E &&modeledError) + : m_errorCode(errorCode), m_modeledError(std::move(modeledError)) + { + } + + ~ServiceErrorV2() = default; + + ServiceErrorV2 &operator=(const ServiceErrorV2 &rhs) = default; + ServiceErrorV2 &operator=(ServiceErrorV2 &&rhs) = default; + + int GetErrorCode() const { return m_errorCode; } + + bool HasModeledError() const { return m_modeledError.has_value(); } + const E &GetModeledError() const { return m_modeledError.value(); } + + private: + int m_errorCode; + + Aws::Crt::Optional m_modeledError; + }; + + class CreateCertificateFromCsrRequest; + class CreateCertificateFromCsrResponse; + class CreateKeysAndCertificateRequest; + class CreateKeysAndCertificateResponse; + class RegisterThingRequest; + class RegisterThingResponse; + class V2ServiceError; + + using CreateCertificateFromCsrResultHandler = std::function> &&)>; + using CreateKeysAndCertificateResultHandler = std::function> &&)>; + using RegisterThingResultHandler = std::function> &&)>; + + /** + * An AWS IoT service that assists with provisioning a device and installing unique client certificates on it + * + * https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html + * + */ + class AWS_IOTIDENTITY_API IClientV2 + { + public: + virtual ~IClientV2() = default; + + /** + * Creates a certificate from a certificate signing request (CSR). AWS IoT provides client certificates that + * are signed by the Amazon Root certificate authority (CA). The new certificate has a PENDING_ACTIVATION + * status. When you call RegisterThing to provision a thing with this certificate, the certificate status + * changes to ACTIVE or INACTIVE as described in the template. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html#fleet-provision-api + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool CreateCertificateFromCsr( + const CreateCertificateFromCsrRequest &request, + const CreateCertificateFromCsrResultHandler &handler) = 0; + + /** + * Creates new keys and a certificate. AWS IoT provides client certificates that are signed by the Amazon + * Root certificate authority (CA). The new certificate has a PENDING_ACTIVATION status. When you call + * RegisterThing to provision a thing with this certificate, the certificate status changes to ACTIVE or + * INACTIVE as described in the template. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html#fleet-provision-api + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool CreateKeysAndCertificate( + const CreateKeysAndCertificateRequest &request, + const CreateKeysAndCertificateResultHandler &handler) = 0; + + /** + * Provisions an AWS IoT thing using a pre-defined template. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html#fleet-provision-api + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool RegisterThing( + const RegisterThingRequest &request, + const RegisterThingResultHandler &handler) = 0; + }; + + /** + * Creates a new service client that uses an SDK MQTT5 client for transport. + * + * @param protocolClient MQTT client to use as transport + * @param options request-response MQTT client configuration options + * @param allocator memory allocator to use for all client functionality + * + * @return a new service client + */ + AWS_IOTIDENTITY_API std::shared_ptr NewClientFrom5( + const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); + + /** + * Creates a new service client that uses an SDK MQTT311 client for transport. + * + * @param protocolClient MQTT client to use as transport + * @param options request-response MQTT client configuration options + * @param allocator memory allocator to use for all client functionality + * + * @return a new service client + */ + AWS_IOTIDENTITY_API std::shared_ptr NewClientFrom311( + const Aws::Crt::Mqtt::MqttConnection &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); + + } // namespace Iotidentity +} // namespace Aws diff --git a/identity/include/aws/iotidentity/V2ServiceError.h b/identity/include/aws/iotidentity/V2ServiceError.h new file mode 100644 index 000000000..c4b0b9a9b --- /dev/null +++ b/identity/include/aws/iotidentity/V2ServiceError.h @@ -0,0 +1,55 @@ +#pragma once + +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ + +#include + +#include +#include + +namespace Aws +{ + namespace Iotidentity + { + + /** + * Response document containing details about a failed request. + * + */ + class AWS_IOTIDENTITY_API V2ServiceError final + { + public: + V2ServiceError() = default; + + V2ServiceError(const Crt::JsonView &doc); + V2ServiceError &operator=(const Crt::JsonView &doc); + + void SerializeToObject(Crt::JsonObject &doc) const; + + /** + * Response status code + * + */ + Aws::Crt::Optional StatusCode; + + /** + * Response error code + * + */ + Aws::Crt::Optional ErrorCode; + + /** + * Response error message + * + */ + Aws::Crt::Optional ErrorMessage; + + private: + static void LoadFromObject(V2ServiceError &obj, const Crt::JsonView &doc); + }; + } // namespace Iotidentity +} // namespace Aws diff --git a/identity/source/CreateKeysAndCertificateRequest.cpp b/identity/source/CreateKeysAndCertificateRequest.cpp index 6761a1f29..fa29f2d2b 100644 --- a/identity/source/CreateKeysAndCertificateRequest.cpp +++ b/identity/source/CreateKeysAndCertificateRequest.cpp @@ -18,7 +18,10 @@ namespace Aws (void)doc; } - void CreateKeysAndCertificateRequest::SerializeToObject(Aws::Crt::JsonObject &object) const { (void)object; } + void CreateKeysAndCertificateRequest::SerializeToObject(Aws::Crt::JsonObject &object) const + { + (void)object; + } CreateKeysAndCertificateRequest::CreateKeysAndCertificateRequest(const Crt::JsonView &doc) { diff --git a/identity/source/ErrorResponse.cpp b/identity/source/ErrorResponse.cpp index ac8d83742..f835e0555 100644 --- a/identity/source/ErrorResponse.cpp +++ b/identity/source/ErrorResponse.cpp @@ -51,7 +51,10 @@ namespace Aws } } - ErrorResponse::ErrorResponse(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + ErrorResponse::ErrorResponse(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } ErrorResponse &ErrorResponse::operator=(const Crt::JsonView &doc) { diff --git a/identity/source/IotIdentityClient.cpp b/identity/source/IotIdentityClient.cpp index 2b25fba33..93d3f0f2c 100644 --- a/identity/source/IotIdentityClient.cpp +++ b/identity/source/IotIdentityClient.cpp @@ -31,9 +31,15 @@ namespace Aws m_connection = Aws::Crt::Mqtt::MqttConnection::NewConnectionFromMqtt5Client(mqtt5Client); } - IotIdentityClient::operator bool() const noexcept { return m_connection && *m_connection; } + IotIdentityClient::operator bool() const noexcept + { + return m_connection && *m_connection; + } - int IotIdentityClient::GetLastError() const noexcept { return aws_last_error(); } + int IotIdentityClient::GetLastError() const noexcept + { + return aws_last_error(); + } bool IotIdentityClient::SubscribeToCreateCertificateFromCsrAccepted( const Aws::Iotidentity::CreateCertificateFromCsrSubscriptionRequest &request, @@ -47,7 +53,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -61,24 +68,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotidentity::CreateCertificateFromCsrResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotidentity::CreateCertificateFromCsrResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "certificates" - << "/" - << "create-from-csr" - << "/" - << "json" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/certificates/create-from-csr/json/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -99,7 +98,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -113,24 +113,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotidentity::ErrorResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotidentity::ErrorResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "certificates" - << "/" - << "create-from-csr" - << "/" - << "json" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/certificates/create-from-csr/json/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -151,7 +143,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -165,24 +158,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotidentity::CreateKeysAndCertificateResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotidentity::CreateKeysAndCertificateResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "certificates" - << "/" - << "create" - << "/" - << "json" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/certificates/create/json/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -203,7 +188,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -217,24 +203,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotidentity::ErrorResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotidentity::ErrorResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "certificates" - << "/" - << "create" - << "/" - << "json" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/certificates/create/json/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -255,7 +233,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -269,24 +248,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotidentity::RegisterThingResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotidentity::RegisterThingResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "provisioning-templates" - << "/" << *request.TemplateName << "/" - << "provision" - << "/" - << "json" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/provisioning-templates/" << *request.TemplateName << "/provision/json/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -307,7 +278,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -321,24 +293,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotidentity::ErrorResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotidentity::ErrorResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "provisioning-templates" - << "/" << *request.TemplateName << "/" - << "provision" - << "/" - << "json" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/provisioning-templates/" << *request.TemplateName << "/provision/json/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -353,13 +317,7 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "certificates" - << "/" - << "create-from-csr" - << "/" - << "json"; + publishTopicSStr << "$aws/certificates/create-from-csr/json"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -367,7 +325,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; @@ -382,13 +341,7 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "certificates" - << "/" - << "create" - << "/" - << "json"; + publishTopicSStr << "$aws/certificates/create/json"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -396,7 +349,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; @@ -411,13 +365,7 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "provisioning-templates" - << "/" << *request.TemplateName << "/" - << "provision" - << "/" - << "json"; + publishTopicSStr << "$aws/provisioning-templates/" << *request.TemplateName << "/provision/json"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -425,7 +373,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; diff --git a/identity/source/IotIdentityClientV2.cpp b/identity/source/IotIdentityClientV2.cpp new file mode 100644 index 000000000..726121bbc --- /dev/null +++ b/identity/source/IotIdentityClientV2.cpp @@ -0,0 +1,470 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Aws +{ + namespace Iotidentity + { + + class ClientV2 : public IClientV2 + { + public: + ClientV2( + Aws::Crt::Allocator *allocator, + std::shared_ptr bindingClient); + virtual ~ClientV2() = default; + + bool CreateCertificateFromCsr( + const CreateCertificateFromCsrRequest &request, + const CreateCertificateFromCsrResultHandler &handler) override; + + bool CreateKeysAndCertificate( + const CreateKeysAndCertificateRequest &request, + const CreateKeysAndCertificateResultHandler &handler) override; + + bool RegisterThing(const RegisterThingRequest &request, const RegisterThingResultHandler &handler) override; + + private: + Aws::Crt::Allocator *m_allocator; + + std::shared_ptr m_bindingClient; + }; + + ClientV2::ClientV2( + Aws::Crt::Allocator *allocator, + std::shared_ptr bindingClient) + : m_allocator(allocator), m_bindingClient(std::move(bindingClient)) + { + // It's simpler to do this than branch the codegen based on the presence of streaming operations + (void)m_allocator; + } + + template + static void s_applyUnmodeledErrorToHandler(const std::function &handler, int errorCode) + { + ServiceErrorV2 error(errorCode); + R finalResult(std::move(error)); + handler(std::move(finalResult)); + } + + template + static void s_applyModeledErrorToHandler(const std::function &handler, E &&modeledError) + { + ServiceErrorV2 error(AWS_ERROR_MQTT_REQUEST_RESPONSE_MODELED_SERVICE_ERROR, std::move(modeledError)); + R finalResult(std::move(error)); + handler(std::move(finalResult)); + } + + static void s_CreateCertificateFromCsrResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const CreateCertificateFromCsrResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + CreateCertificateFromCsrResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } + + bool ClientV2::CreateCertificateFromCsr( + const CreateCertificateFromCsrRequest &request, + const CreateCertificateFromCsrResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/certificates/create-from-csr/json"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/certificates/create-from-csr/json/accepted"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + Aws::Crt::StringStream subscriptionTopicStream1; + subscriptionTopicStream1 << "$aws/certificates/create-from-csr/json/rejected"; + Aws::Crt::String subscriptionTopic1 = subscriptionTopicStream1.str(); + + struct aws_byte_cursor subscriptionTopicFilters[2] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + Aws::Crt::ByteCursorFromString(subscriptionTopic1), + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 2; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_CreateCertificateFromCsrResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + static void s_CreateKeysAndCertificateResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const CreateKeysAndCertificateResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + CreateKeysAndCertificateResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } + + bool ClientV2::CreateKeysAndCertificate( + const CreateKeysAndCertificateRequest &request, + const CreateKeysAndCertificateResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/certificates/create/json"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/certificates/create/json/accepted"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + Aws::Crt::StringStream subscriptionTopicStream1; + subscriptionTopicStream1 << "$aws/certificates/create/json/rejected"; + Aws::Crt::String subscriptionTopic1 = subscriptionTopicStream1.str(); + + struct aws_byte_cursor subscriptionTopicFilters[2] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + Aws::Crt::ByteCursorFromString(subscriptionTopic1), + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 2; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_CreateKeysAndCertificateResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + static void s_RegisterThingResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const RegisterThingResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + RegisterThingResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } + + bool ClientV2::RegisterThing(const RegisterThingRequest &request, const RegisterThingResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/provisioning-templates/" << *request.TemplateName << "/provision/json"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/provisioning-templates/" << *request.TemplateName + << "/provision/json/accepted"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + Aws::Crt::StringStream subscriptionTopicStream1; + subscriptionTopicStream1 << "$aws/provisioning-templates/" << *request.TemplateName + << "/provision/json/rejected"; + Aws::Crt::String subscriptionTopic1 = subscriptionTopicStream1.str(); + + struct aws_byte_cursor subscriptionTopicFilters[2] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + Aws::Crt::ByteCursorFromString(subscriptionTopic1), + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 2; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_RegisterThingResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + template class ServiceStreamingOperation : public Aws::Iot::RequestResponse::IStreamingOperation + { + public: + explicit ServiceStreamingOperation(std::shared_ptr stream) + : m_stream(std::move(stream)) + { + } + + static std::shared_ptr Create( + Aws::Crt::Allocator *allocator, + const std::shared_ptr &bindingClient, + const Aws::Crt::String &subscriptionTopicFilter, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + { + + std::function unmodeledHandler = + [options](Aws::Iot::RequestResponse::IncomingPublishEvent &&event) + { + const auto &payload = event.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + return; + } + + T modeledEvent(jsonObject); + options.GetStreamHandler()(std::move(modeledEvent)); + }; + + Aws::Iot::RequestResponse::StreamingOperationOptionsInternal internalOptions; + internalOptions.subscriptionTopicFilter = Aws::Crt::ByteCursorFromString(subscriptionTopicFilter); + internalOptions.subscriptionStatusEventHandler = options.GetSubscriptionStatusEventHandler(); + internalOptions.incomingPublishEventHandler = unmodeledHandler; + + auto unmodeledStream = bindingClient->CreateStream(internalOptions); + if (!unmodeledStream) + { + return nullptr; + } + + return Aws::Crt::MakeShared>(allocator, unmodeledStream); + } + + void Open() override { m_stream->Open(); } + + private: + std::shared_ptr m_stream; + }; + + std::shared_ptr NewClientFrom5( + const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator) + { + + std::shared_ptr bindingClient = + Aws::Iot::RequestResponse::NewClientFrom5(protocolClient, options, allocator); + if (nullptr == bindingClient) + { + return nullptr; + } + + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + } + + std::shared_ptr NewClientFrom311( + const Aws::Crt::Mqtt::MqttConnection &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator) + { + + std::shared_ptr bindingClient = + Aws::Iot::RequestResponse::NewClientFrom311(protocolClient, options, allocator); + if (nullptr == bindingClient) + { + return nullptr; + } + + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + } + + } // namespace Iotidentity +} // namespace Aws diff --git a/identity/source/RegisterThingRequest.cpp b/identity/source/RegisterThingRequest.cpp index 981aa7550..130b823ce 100644 --- a/identity/source/RegisterThingRequest.cpp +++ b/identity/source/RegisterThingRequest.cpp @@ -55,7 +55,10 @@ namespace Aws } } - RegisterThingRequest::RegisterThingRequest(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + RegisterThingRequest::RegisterThingRequest(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } RegisterThingRequest &RegisterThingRequest::operator=(const Crt::JsonView &doc) { diff --git a/identity/source/RegisterThingResponse.cpp b/identity/source/RegisterThingResponse.cpp index 180d5d92d..ca7ebbb61 100644 --- a/identity/source/RegisterThingResponse.cpp +++ b/identity/source/RegisterThingResponse.cpp @@ -57,7 +57,10 @@ namespace Aws } } - RegisterThingResponse::RegisterThingResponse(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + RegisterThingResponse::RegisterThingResponse(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } RegisterThingResponse &RegisterThingResponse::operator=(const Crt::JsonView &doc) { diff --git a/identity/source/RegisterThingSubscriptionRequest.cpp b/identity/source/RegisterThingSubscriptionRequest.cpp index 67f10f152..21d601ea0 100644 --- a/identity/source/RegisterThingSubscriptionRequest.cpp +++ b/identity/source/RegisterThingSubscriptionRequest.cpp @@ -18,7 +18,10 @@ namespace Aws (void)doc; } - void RegisterThingSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const { (void)object; } + void RegisterThingSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const + { + (void)object; + } RegisterThingSubscriptionRequest::RegisterThingSubscriptionRequest(const Crt::JsonView &doc) { diff --git a/identity/source/V2ServiceError.cpp b/identity/source/V2ServiceError.cpp new file mode 100644 index 000000000..1d2d7d668 --- /dev/null +++ b/identity/source/V2ServiceError.cpp @@ -0,0 +1,66 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ +#include + +namespace Aws +{ + namespace Iotidentity + { + + void V2ServiceError::LoadFromObject(V2ServiceError &val, const Aws::Crt::JsonView &doc) + { + (void)val; + (void)doc; + + if (doc.ValueExists("statusCode")) + { + val.StatusCode = doc.GetInteger("statusCode"); + } + + if (doc.ValueExists("errorCode")) + { + val.ErrorCode = doc.GetString("errorCode"); + } + + if (doc.ValueExists("errorMessage")) + { + val.ErrorMessage = doc.GetString("errorMessage"); + } + } + + void V2ServiceError::SerializeToObject(Aws::Crt::JsonObject &object) const + { + (void)object; + + if (StatusCode) + { + object.WithInteger("statusCode", *StatusCode); + } + + if (ErrorCode) + { + object.WithString("errorCode", *ErrorCode); + } + + if (ErrorMessage) + { + object.WithString("errorMessage", *ErrorMessage); + } + } + + V2ServiceError::V2ServiceError(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } + + V2ServiceError &V2ServiceError::operator=(const Crt::JsonView &doc) + { + *this = V2ServiceError(doc); + return *this; + } + + } // namespace Iotidentity +} // namespace Aws diff --git a/jobs/include/aws/iotjobs/IotJobsClientV2.h b/jobs/include/aws/iotjobs/IotJobsClientV2.h new file mode 100644 index 000000000..ab9944810 --- /dev/null +++ b/jobs/include/aws/iotjobs/IotJobsClientV2.h @@ -0,0 +1,232 @@ +#pragma once + +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ + +#include + +#include +#include +#include + +#include + +namespace Aws +{ + namespace Crt + { + namespace Mqtt + { + class MqttConnection; + } + namespace Mqtt5 + { + class Mqtt5Client; + } + } // namespace Crt +} // namespace Aws + +namespace Aws +{ + namespace Iotjobs + { + + template class ServiceErrorV2 + { + public: + ServiceErrorV2() = delete; + ServiceErrorV2(const ServiceErrorV2 &rhs) = default; + ServiceErrorV2(ServiceErrorV2 &&rhs) = default; + + explicit ServiceErrorV2(int errorCode) : m_errorCode(errorCode), m_modeledError() {} + + ServiceErrorV2(int errorCode, E &&modeledError) + : m_errorCode(errorCode), m_modeledError(std::move(modeledError)) + { + } + + ~ServiceErrorV2() = default; + + ServiceErrorV2 &operator=(const ServiceErrorV2 &rhs) = default; + ServiceErrorV2 &operator=(ServiceErrorV2 &&rhs) = default; + + int GetErrorCode() const { return m_errorCode; } + + bool HasModeledError() const { return m_modeledError.has_value(); } + const E &GetModeledError() const { return m_modeledError.value(); } + + private: + int m_errorCode; + + Aws::Crt::Optional m_modeledError; + }; + + class DescribeJobExecutionRequest; + class DescribeJobExecutionResponse; + class GetPendingJobExecutionsRequest; + class GetPendingJobExecutionsResponse; + class JobExecutionsChangedEvent; + class JobExecutionsChangedSubscriptionRequest; + class NextJobExecutionChangedEvent; + class NextJobExecutionChangedSubscriptionRequest; + class StartNextJobExecutionResponse; + class StartNextPendingJobExecutionRequest; + class UpdateJobExecutionRequest; + class UpdateJobExecutionResponse; + class V2ServiceError; + + using DescribeJobExecutionResultHandler = std::function> &&)>; + using GetPendingJobExecutionsResultHandler = std::function> &&)>; + using StartNextPendingJobExecutionResultHandler = std::function> &&)>; + using UpdateJobExecutionResultHandler = std::function> &&)>; + + /** + * The AWS IoT jobs service can be used to define a set of remote operations that are sent to and executed on + * one or more devices connected to AWS IoT. + * + * https://docs.aws.amazon.com/iot/latest/developerguide/jobs-api.html#jobs-mqtt-api + * + */ + class AWS_IOTJOBS_API IClientV2 + { + public: + virtual ~IClientV2() = default; + + /** + * Gets detailed information about a job execution. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/jobs-api.html#mqtt-describejobexecution + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool DescribeJobExecution( + const DescribeJobExecutionRequest &request, + const DescribeJobExecutionResultHandler &handler) = 0; + + /** + * Gets the list of all jobs for a thing that are not in a terminal state. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/jobs-api.html#mqtt-getpendingjobexecutions + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool GetPendingJobExecutions( + const GetPendingJobExecutionsRequest &request, + const GetPendingJobExecutionsResultHandler &handler) = 0; + + /** + * Gets and starts the next pending job execution for a thing (status IN_PROGRESS or QUEUED). + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/jobs-api.html#mqtt-startnextpendingjobexecution + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool StartNextPendingJobExecution( + const StartNextPendingJobExecutionRequest &request, + const StartNextPendingJobExecutionResultHandler &handler) = 0; + + /** + * Updates the status of a job execution. You can optionally create a step timer by setting a value for the + * stepTimeoutInMinutes property. If you don't update the value of this property by running + * UpdateJobExecution again, the job execution times out when the step timer expires. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/jobs-api.html#mqtt-updatejobexecution + * + * @param request operation to perform + * @param handler function object to invoke upon operation completion + * + * @returns success/failure + */ + virtual bool UpdateJobExecution( + const UpdateJobExecutionRequest &request, + const UpdateJobExecutionResultHandler &handler) = 0; + + /** + * Creates a stream of JobExecutionsChanged notifications for a given IoT thing. + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/jobs-api.html#mqtt-jobexecutionschanged + * + * @param request modeled streaming operation subscription configuration + * @param options + * + * @returns a streaming operation which will emit a modeled event every time a message is received on the + * associated MQTT topic + */ + virtual std::shared_ptr CreateJobExecutionsChangedStream( + const JobExecutionsChangedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + + /** + * + * + * + * AWS documentation: + * https://docs.aws.amazon.com/iot/latest/developerguide/jobs-api.html#mqtt-nextjobexecutionchanged + * + * @param request modeled streaming operation subscription configuration + * @param options + * + * @returns a streaming operation which will emit a modeled event every time a message is received on the + * associated MQTT topic + */ + virtual std::shared_ptr CreateNextJobExecutionChangedStream( + const NextJobExecutionChangedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + }; + + /** + * Creates a new service client that uses an SDK MQTT5 client for transport. + * + * @param protocolClient MQTT client to use as transport + * @param options request-response MQTT client configuration options + * @param allocator memory allocator to use for all client functionality + * + * @return a new service client + */ + AWS_IOTJOBS_API std::shared_ptr NewClientFrom5( + const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); + + /** + * Creates a new service client that uses an SDK MQTT311 client for transport. + * + * @param protocolClient MQTT client to use as transport + * @param options request-response MQTT client configuration options + * @param allocator memory allocator to use for all client functionality + * + * @return a new service client + */ + AWS_IOTJOBS_API std::shared_ptr NewClientFrom311( + const Aws::Crt::Mqtt::MqttConnection &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator = Aws::Crt::ApiAllocator()); + + } // namespace Iotjobs +} // namespace Aws diff --git a/jobs/include/aws/iotjobs/JobStatus.h b/jobs/include/aws/iotjobs/JobStatus.h index 7655b5f30..0fa69859e 100644 --- a/jobs/include/aws/iotjobs/JobStatus.h +++ b/jobs/include/aws/iotjobs/JobStatus.h @@ -61,5 +61,5 @@ namespace Aws AWS_IOTJOBS_API const char *ToString(JobStatus val); AWS_IOTJOBS_API JobStatus FromString(const Aws::Crt::String &val); } // namespace JobStatusMarshaller - } // namespace Iotjobs + } // namespace Iotjobs } // namespace Aws diff --git a/jobs/include/aws/iotjobs/RejectedErrorCode.h b/jobs/include/aws/iotjobs/RejectedErrorCode.h index 83228c402..1fc115c76 100644 --- a/jobs/include/aws/iotjobs/RejectedErrorCode.h +++ b/jobs/include/aws/iotjobs/RejectedErrorCode.h @@ -76,5 +76,5 @@ namespace Aws AWS_IOTJOBS_API const char *ToString(RejectedErrorCode val); AWS_IOTJOBS_API RejectedErrorCode FromString(const Aws::Crt::String &val); } // namespace RejectedErrorCodeMarshaller - } // namespace Iotjobs + } // namespace Iotjobs } // namespace Aws diff --git a/jobs/include/aws/iotjobs/V2ServiceError.h b/jobs/include/aws/iotjobs/V2ServiceError.h new file mode 100644 index 000000000..27702c3e8 --- /dev/null +++ b/jobs/include/aws/iotjobs/V2ServiceError.h @@ -0,0 +1,72 @@ +#pragma once + +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ + +#include +#include +#include + +#include + +#include +#include + +namespace Aws +{ + namespace Iotjobs + { + + /** + * Response document containing details about a failed request. + * + */ + class AWS_IOTJOBS_API V2ServiceError final + { + public: + V2ServiceError() = default; + + V2ServiceError(const Crt::JsonView &doc); + V2ServiceError &operator=(const Crt::JsonView &doc); + + void SerializeToObject(Crt::JsonObject &doc) const; + + /** + * Opaque token that can correlate this response to the original request. + * + */ + Aws::Crt::Optional ClientToken; + + /** + * Indicates the type of error. + * + */ + Aws::Crt::Optional Code; + + /** + * A text message that provides additional information. + * + */ + Aws::Crt::Optional Message; + + /** + * The date and time the response was generated by AWS IoT. + * + */ + Aws::Crt::Optional Timestamp; + + /** + * A JobExecutionState object. This field is included only when the code field has the value + * InvalidStateTransition or VersionMismatch. + * + */ + Aws::Crt::Optional ExecutionState; + + private: + static void LoadFromObject(V2ServiceError &obj, const Crt::JsonView &doc); + }; + } // namespace Iotjobs +} // namespace Aws diff --git a/jobs/source/IotJobsClient.cpp b/jobs/source/IotJobsClient.cpp index c0cb1cf0c..0f3189bfa 100644 --- a/jobs/source/IotJobsClient.cpp +++ b/jobs/source/IotJobsClient.cpp @@ -38,9 +38,15 @@ namespace Aws m_connection = Aws::Crt::Mqtt::MqttConnection::NewConnectionFromMqtt5Client(mqtt5Client); } - IotJobsClient::operator bool() const noexcept { return m_connection && *m_connection; } + IotJobsClient::operator bool() const noexcept + { + return m_connection && *m_connection; + } - int IotJobsClient::GetLastError() const noexcept { return aws_last_error(); } + int IotJobsClient::GetLastError() const noexcept + { + return aws_last_error(); + } bool IotJobsClient::SubscribeToDescribeJobExecutionAccepted( const Aws::Iotjobs::DescribeJobExecutionSubscriptionRequest &request, @@ -54,7 +60,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -68,24 +75,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotjobs::DescribeJobExecutionResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotjobs::DescribeJobExecutionResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" << *request.JobId << "/" - << "get" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/" << *request.JobId << "/get/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -106,7 +105,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -120,24 +120,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotjobs::RejectedError response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotjobs::RejectedError response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" << *request.JobId << "/" - << "get" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/" << *request.JobId << "/get/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -158,7 +150,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -172,24 +165,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotjobs::GetPendingJobExecutionsResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotjobs::GetPendingJobExecutionsResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" - << "get" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/get/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -210,7 +195,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -224,24 +210,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotjobs::RejectedError response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotjobs::RejectedError response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" - << "get" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/get/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -262,7 +240,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -276,22 +255,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotjobs::JobExecutionsChangedEvent response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotjobs::JobExecutionsChangedEvent response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" - << "notify"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/notify"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -312,7 +285,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -326,22 +300,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotjobs::NextJobExecutionChangedEvent response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotjobs::NextJobExecutionChangedEvent response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" - << "notify-next"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/notify-next"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -362,7 +330,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -376,24 +345,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotjobs::StartNextJobExecutionResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotjobs::StartNextJobExecutionResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" - << "start-next" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/start-next/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -414,7 +375,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -428,24 +390,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotjobs::RejectedError response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotjobs::RejectedError response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" - << "start-next" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/start-next/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -466,7 +420,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -480,24 +435,17 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotjobs::UpdateJobExecutionResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotjobs::UpdateJobExecutionResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" << *request.JobId << "/" - << "update" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/" << *request.JobId + << "/update/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -518,7 +466,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -532,24 +481,17 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotjobs::RejectedError response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotjobs::RejectedError response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" << *request.JobId << "/" - << "update" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/" << *request.JobId + << "/update/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -564,13 +506,7 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" << *request.JobId << "/" - << "get"; + publishTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/" << *request.JobId << "/get"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -578,7 +514,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; @@ -593,13 +530,7 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" - << "get"; + publishTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/get"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -607,7 +538,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; @@ -622,13 +554,7 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" - << "start-next"; + publishTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/start-next"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -636,7 +562,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; @@ -651,13 +578,7 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "jobs" - << "/" << *request.JobId << "/" - << "update"; + publishTopicSStr << "$aws/things/" << *request.ThingName << "/jobs/" << *request.JobId << "/update"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -665,7 +586,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; diff --git a/jobs/source/IotJobsClientV2.cpp b/jobs/source/IotJobsClientV2.cpp new file mode 100644 index 000000000..0185e4938 --- /dev/null +++ b/jobs/source/IotJobsClientV2.cpp @@ -0,0 +1,630 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Aws +{ + namespace Iotjobs + { + + class ClientV2 : public IClientV2 + { + public: + ClientV2( + Aws::Crt::Allocator *allocator, + std::shared_ptr bindingClient); + virtual ~ClientV2() = default; + + bool DescribeJobExecution( + const DescribeJobExecutionRequest &request, + const DescribeJobExecutionResultHandler &handler) override; + + bool GetPendingJobExecutions( + const GetPendingJobExecutionsRequest &request, + const GetPendingJobExecutionsResultHandler &handler) override; + + bool StartNextPendingJobExecution( + const StartNextPendingJobExecutionRequest &request, + const StartNextPendingJobExecutionResultHandler &handler) override; + + bool UpdateJobExecution( + const UpdateJobExecutionRequest &request, + const UpdateJobExecutionResultHandler &handler) override; + + std::shared_ptr CreateJobExecutionsChangedStream( + const JobExecutionsChangedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + override; + + std::shared_ptr CreateNextJobExecutionChangedStream( + const NextJobExecutionChangedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + override; + + private: + Aws::Crt::Allocator *m_allocator; + + std::shared_ptr m_bindingClient; + }; + + ClientV2::ClientV2( + Aws::Crt::Allocator *allocator, + std::shared_ptr bindingClient) + : m_allocator(allocator), m_bindingClient(std::move(bindingClient)) + { + // It's simpler to do this than branch the codegen based on the presence of streaming operations + (void)m_allocator; + } + + template + static void s_applyUnmodeledErrorToHandler(const std::function &handler, int errorCode) + { + ServiceErrorV2 error(errorCode); + R finalResult(std::move(error)); + handler(std::move(finalResult)); + } + + template + static void s_applyModeledErrorToHandler(const std::function &handler, E &&modeledError) + { + ServiceErrorV2 error(AWS_ERROR_MQTT_REQUEST_RESPONSE_MODELED_SERVICE_ERROR, std::move(modeledError)); + R finalResult(std::move(error)); + handler(std::move(finalResult)); + } + + static void s_DescribeJobExecutionResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const DescribeJobExecutionResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + DescribeJobExecutionResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } + + bool ClientV2::DescribeJobExecution( + const DescribeJobExecutionRequest &request, + const DescribeJobExecutionResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/jobs/" << *request.JobId << "/get"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/jobs/" << *request.JobId << "/get/+"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_DescribeJobExecutionResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + static void s_GetPendingJobExecutionsResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const GetPendingJobExecutionsResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + GetPendingJobExecutionsResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } + + bool ClientV2::GetPendingJobExecutions( + const GetPendingJobExecutionsRequest &request, + const GetPendingJobExecutionsResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/jobs/get"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/jobs/get/+"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_GetPendingJobExecutionsResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + static void s_StartNextPendingJobExecutionResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const StartNextPendingJobExecutionResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + StartNextJobExecutionResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } + + bool ClientV2::StartNextPendingJobExecution( + const StartNextPendingJobExecutionRequest &request, + const StartNextPendingJobExecutionResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/jobs/start-next"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/jobs/start-next/+"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_StartNextPendingJobExecutionResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + static void s_UpdateJobExecutionResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const UpdateJobExecutionResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + UpdateJobExecutionResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } + + bool ClientV2::UpdateJobExecution( + const UpdateJobExecutionRequest &request, + const UpdateJobExecutionResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/jobs/" << *request.JobId << "/update"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/jobs/" << *request.JobId + << "/update/+"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_UpdateJobExecutionResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + template class ServiceStreamingOperation : public Aws::Iot::RequestResponse::IStreamingOperation + { + public: + explicit ServiceStreamingOperation(std::shared_ptr stream) + : m_stream(std::move(stream)) + { + } + + static std::shared_ptr Create( + Aws::Crt::Allocator *allocator, + const std::shared_ptr &bindingClient, + const Aws::Crt::String &subscriptionTopicFilter, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + { + + std::function unmodeledHandler = + [options](Aws::Iot::RequestResponse::IncomingPublishEvent &&event) + { + const auto &payload = event.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + return; + } + + T modeledEvent(jsonObject); + options.GetStreamHandler()(std::move(modeledEvent)); + }; + + Aws::Iot::RequestResponse::StreamingOperationOptionsInternal internalOptions; + internalOptions.subscriptionTopicFilter = Aws::Crt::ByteCursorFromString(subscriptionTopicFilter); + internalOptions.subscriptionStatusEventHandler = options.GetSubscriptionStatusEventHandler(); + internalOptions.incomingPublishEventHandler = unmodeledHandler; + + auto unmodeledStream = bindingClient->CreateStream(internalOptions); + if (!unmodeledStream) + { + return nullptr; + } + + return Aws::Crt::MakeShared>(allocator, unmodeledStream); + } + + void Open() override { m_stream->Open(); } + + private: + std::shared_ptr m_stream; + }; + + std::shared_ptr ClientV2::CreateJobExecutionsChangedStream( + const JobExecutionsChangedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/jobs/notify"; + Aws::Crt::String topic = topicStream.str(); + + return ServiceStreamingOperation::Create( + m_allocator, m_bindingClient, topic, options); + } + + std::shared_ptr ClientV2::CreateNextJobExecutionChangedStream( + const NextJobExecutionChangedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/jobs/notify-next"; + Aws::Crt::String topic = topicStream.str(); + + return ServiceStreamingOperation::Create( + m_allocator, m_bindingClient, topic, options); + } + + std::shared_ptr NewClientFrom5( + const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator) + { + + std::shared_ptr bindingClient = + Aws::Iot::RequestResponse::NewClientFrom5(protocolClient, options, allocator); + if (nullptr == bindingClient) + { + return nullptr; + } + + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + } + + std::shared_ptr NewClientFrom311( + const Aws::Crt::Mqtt::MqttConnection &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator) + { + + std::shared_ptr bindingClient = + Aws::Iot::RequestResponse::NewClientFrom311(protocolClient, options, allocator); + if (nullptr == bindingClient) + { + return nullptr; + } + + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + } + + } // namespace Iotjobs +} // namespace Aws diff --git a/jobs/source/JobExecutionData.cpp b/jobs/source/JobExecutionData.cpp index 9e39e0f14..4dba0a662 100644 --- a/jobs/source/JobExecutionData.cpp +++ b/jobs/source/JobExecutionData.cpp @@ -132,7 +132,10 @@ namespace Aws } } - JobExecutionData::JobExecutionData(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + JobExecutionData::JobExecutionData(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } JobExecutionData &JobExecutionData::operator=(const Crt::JsonView &doc) { diff --git a/jobs/source/JobExecutionState.cpp b/jobs/source/JobExecutionState.cpp index 3a25e08c8..641244c98 100644 --- a/jobs/source/JobExecutionState.cpp +++ b/jobs/source/JobExecutionState.cpp @@ -65,7 +65,10 @@ namespace Aws } } - JobExecutionState::JobExecutionState(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + JobExecutionState::JobExecutionState(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } JobExecutionState &JobExecutionState::operator=(const Crt::JsonView &doc) { diff --git a/jobs/source/JobExecutionSummary.cpp b/jobs/source/JobExecutionSummary.cpp index 1f7936e69..4181e9c4e 100644 --- a/jobs/source/JobExecutionSummary.cpp +++ b/jobs/source/JobExecutionSummary.cpp @@ -81,7 +81,10 @@ namespace Aws } } - JobExecutionSummary::JobExecutionSummary(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + JobExecutionSummary::JobExecutionSummary(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } JobExecutionSummary &JobExecutionSummary::operator=(const Crt::JsonView &doc) { diff --git a/jobs/source/JobExecutionsChangedEvent.cpp b/jobs/source/JobExecutionsChangedEvent.cpp index d8e1f0684..0b82e095d 100644 --- a/jobs/source/JobExecutionsChangedEvent.cpp +++ b/jobs/source/JobExecutionsChangedEvent.cpp @@ -73,7 +73,10 @@ namespace Aws } } - JobExecutionsChangedEvent::JobExecutionsChangedEvent(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + JobExecutionsChangedEvent::JobExecutionsChangedEvent(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } JobExecutionsChangedEvent &JobExecutionsChangedEvent::operator=(const Crt::JsonView &doc) { diff --git a/jobs/source/JobStatus.cpp b/jobs/source/JobStatus.cpp index 06169d17f..1b7603bb2 100644 --- a/jobs/source/JobStatus.cpp +++ b/jobs/source/JobStatus.cpp @@ -100,5 +100,5 @@ namespace Aws return static_cast(-1); } } // namespace JobStatusMarshaller - } // namespace Iotjobs + } // namespace Iotjobs } // namespace Aws diff --git a/jobs/source/RejectedError.cpp b/jobs/source/RejectedError.cpp index 00c2cd188..a487d7f35 100644 --- a/jobs/source/RejectedError.cpp +++ b/jobs/source/RejectedError.cpp @@ -73,7 +73,10 @@ namespace Aws } } - RejectedError::RejectedError(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + RejectedError::RejectedError(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } RejectedError &RejectedError::operator=(const Crt::JsonView &doc) { diff --git a/jobs/source/RejectedErrorCode.cpp b/jobs/source/RejectedErrorCode.cpp index 4e792a57c..d1fe072bc 100644 --- a/jobs/source/RejectedErrorCode.cpp +++ b/jobs/source/RejectedErrorCode.cpp @@ -108,5 +108,5 @@ namespace Aws return static_cast(-1); } } // namespace RejectedErrorCodeMarshaller - } // namespace Iotjobs + } // namespace Iotjobs } // namespace Aws diff --git a/jobs/source/UpdateJobExecutionRequest.cpp b/jobs/source/UpdateJobExecutionRequest.cpp index 8ac18844d..19f250897 100644 --- a/jobs/source/UpdateJobExecutionRequest.cpp +++ b/jobs/source/UpdateJobExecutionRequest.cpp @@ -115,7 +115,10 @@ namespace Aws } } - UpdateJobExecutionRequest::UpdateJobExecutionRequest(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + UpdateJobExecutionRequest::UpdateJobExecutionRequest(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } UpdateJobExecutionRequest &UpdateJobExecutionRequest::operator=(const Crt::JsonView &doc) { diff --git a/jobs/source/UpdateJobExecutionResponse.cpp b/jobs/source/UpdateJobExecutionResponse.cpp index d6a919924..43b66ec6d 100644 --- a/jobs/source/UpdateJobExecutionResponse.cpp +++ b/jobs/source/UpdateJobExecutionResponse.cpp @@ -63,7 +63,10 @@ namespace Aws } } - UpdateJobExecutionResponse::UpdateJobExecutionResponse(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + UpdateJobExecutionResponse::UpdateJobExecutionResponse(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } UpdateJobExecutionResponse &UpdateJobExecutionResponse::operator=(const Crt::JsonView &doc) { diff --git a/jobs/source/V2ServiceError.cpp b/jobs/source/V2ServiceError.cpp new file mode 100644 index 000000000..3e2bb5444 --- /dev/null +++ b/jobs/source/V2ServiceError.cpp @@ -0,0 +1,88 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ +#include + +namespace Aws +{ + namespace Iotjobs + { + + void V2ServiceError::LoadFromObject(V2ServiceError &val, const Aws::Crt::JsonView &doc) + { + (void)val; + (void)doc; + + if (doc.ValueExists("clientToken")) + { + val.ClientToken = doc.GetString("clientToken"); + } + + if (doc.ValueExists("code")) + { + val.Code = RejectedErrorCodeMarshaller::FromString(doc.GetString("code")); + } + + if (doc.ValueExists("message")) + { + val.Message = doc.GetString("message"); + } + + if (doc.ValueExists("timestamp")) + { + val.Timestamp = doc.GetDouble("timestamp"); + } + + if (doc.ValueExists("executionState")) + { + val.ExecutionState = doc.GetJsonObject("executionState"); + } + } + + void V2ServiceError::SerializeToObject(Aws::Crt::JsonObject &object) const + { + (void)object; + + if (ClientToken) + { + object.WithString("clientToken", *ClientToken); + } + + if (Code) + { + object.WithString("code", RejectedErrorCodeMarshaller::ToString(*Code)); + } + + if (Message) + { + object.WithString("message", *Message); + } + + if (Timestamp) + { + object.WithDouble("timestamp", Timestamp->SecondsWithMSPrecision()); + } + + if (ExecutionState) + { + Aws::Crt::JsonObject jsonObject; + ExecutionState->SerializeToObject(jsonObject); + object.WithObject("executionState", std::move(jsonObject)); + } + } + + V2ServiceError::V2ServiceError(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } + + V2ServiceError &V2ServiceError::operator=(const Crt::JsonView &doc) + { + *this = V2ServiceError(doc); + return *this; + } + + } // namespace Iotjobs +} // namespace Aws diff --git a/shadow/include/aws/iotshadow/IotShadowClientV2.h b/shadow/include/aws/iotshadow/IotShadowClientV2.h index d125e870d..2ce41b594 100644 --- a/shadow/include/aws/iotshadow/IotShadowClientV2.h +++ b/shadow/include/aws/iotshadow/IotShadowClientV2.h @@ -79,6 +79,7 @@ namespace Aws class UpdateNamedShadowRequest; class UpdateShadowRequest; class UpdateShadowResponse; + class V2ServiceError; using DeleteNamedShadowResultHandler = std::function> &&)>; @@ -211,7 +212,7 @@ namespace Aws */ virtual std::shared_ptr CreateNamedShadowDeltaUpdatedStream( const NamedShadowDeltaUpdatedSubscriptionRequest &request, - const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; /** * Create a stream for ShadowUpdated events for a named shadow of an AWS IoT thing. @@ -228,7 +229,7 @@ namespace Aws */ virtual std::shared_ptr CreateNamedShadowUpdatedStream( const NamedShadowUpdatedSubscriptionRequest &request, - const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; /** * Create a stream for ShadowDelta events for the (classic) shadow of an AWS IoT thing. @@ -245,7 +246,7 @@ namespace Aws */ virtual std::shared_ptr CreateShadowDeltaUpdatedStream( const ShadowDeltaUpdatedSubscriptionRequest &request, - const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; /** * Create a stream for ShadowUpdated events for the (classic) shadow of an AWS IoT thing. @@ -262,7 +263,7 @@ namespace Aws */ virtual std::shared_ptr CreateShadowUpdatedStream( const ShadowUpdatedSubscriptionRequest &request, - const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) = 0; }; /** diff --git a/shadow/include/aws/iotshadow/V2ServiceError.h b/shadow/include/aws/iotshadow/V2ServiceError.h new file mode 100644 index 000000000..8e013a9b8 --- /dev/null +++ b/shadow/include/aws/iotshadow/V2ServiceError.h @@ -0,0 +1,64 @@ +#pragma once + +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ + +#include + +#include + +#include +#include + +namespace Aws +{ + namespace Iotshadow + { + + /** + * Response document containing details about a failed request. + * + */ + class AWS_IOTSHADOW_API V2ServiceError final + { + public: + V2ServiceError() = default; + + V2ServiceError(const Crt::JsonView &doc); + V2ServiceError &operator=(const Crt::JsonView &doc); + + void SerializeToObject(Crt::JsonObject &doc) const; + + /** + * Opaque request-response correlation data. Present only if a client token was used in the request. + * + */ + Aws::Crt::Optional ClientToken; + + /** + * An HTTP response code that indicates the type of error. + * + */ + Aws::Crt::Optional Code; + + /** + * A text message that provides additional information. + * + */ + Aws::Crt::Optional Message; + + /** + * The date and time the response was generated by AWS IoT. This property is not present in all error + * response documents. + * + */ + Aws::Crt::Optional Timestamp; + + private: + static void LoadFromObject(V2ServiceError &obj, const Crt::JsonView &doc); + }; + } // namespace Iotshadow +} // namespace Aws diff --git a/shadow/source/DeleteNamedShadowRequest.cpp b/shadow/source/DeleteNamedShadowRequest.cpp index e663bb16d..16da220b0 100644 --- a/shadow/source/DeleteNamedShadowRequest.cpp +++ b/shadow/source/DeleteNamedShadowRequest.cpp @@ -31,7 +31,10 @@ namespace Aws } } - DeleteNamedShadowRequest::DeleteNamedShadowRequest(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + DeleteNamedShadowRequest::DeleteNamedShadowRequest(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } DeleteNamedShadowRequest &DeleteNamedShadowRequest::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/DeleteShadowRequest.cpp b/shadow/source/DeleteShadowRequest.cpp index a5f7fa74c..f602bb78a 100644 --- a/shadow/source/DeleteShadowRequest.cpp +++ b/shadow/source/DeleteShadowRequest.cpp @@ -31,7 +31,10 @@ namespace Aws } } - DeleteShadowRequest::DeleteShadowRequest(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + DeleteShadowRequest::DeleteShadowRequest(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } DeleteShadowRequest &DeleteShadowRequest::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/DeleteShadowResponse.cpp b/shadow/source/DeleteShadowResponse.cpp index 6e46fd6e2..5aa22864e 100644 --- a/shadow/source/DeleteShadowResponse.cpp +++ b/shadow/source/DeleteShadowResponse.cpp @@ -51,7 +51,10 @@ namespace Aws } } - DeleteShadowResponse::DeleteShadowResponse(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + DeleteShadowResponse::DeleteShadowResponse(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } DeleteShadowResponse &DeleteShadowResponse::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/DeleteShadowSubscriptionRequest.cpp b/shadow/source/DeleteShadowSubscriptionRequest.cpp index 59dc03eb3..3f91cb255 100644 --- a/shadow/source/DeleteShadowSubscriptionRequest.cpp +++ b/shadow/source/DeleteShadowSubscriptionRequest.cpp @@ -18,7 +18,10 @@ namespace Aws (void)doc; } - void DeleteShadowSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const { (void)object; } + void DeleteShadowSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const + { + (void)object; + } DeleteShadowSubscriptionRequest::DeleteShadowSubscriptionRequest(const Crt::JsonView &doc) { diff --git a/shadow/source/ErrorResponse.cpp b/shadow/source/ErrorResponse.cpp index c501b2b22..bf782bb69 100644 --- a/shadow/source/ErrorResponse.cpp +++ b/shadow/source/ErrorResponse.cpp @@ -61,7 +61,10 @@ namespace Aws } } - ErrorResponse::ErrorResponse(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + ErrorResponse::ErrorResponse(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } ErrorResponse &ErrorResponse::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/GetNamedShadowRequest.cpp b/shadow/source/GetNamedShadowRequest.cpp index b3c87a3d0..3a9383768 100644 --- a/shadow/source/GetNamedShadowRequest.cpp +++ b/shadow/source/GetNamedShadowRequest.cpp @@ -31,7 +31,10 @@ namespace Aws } } - GetNamedShadowRequest::GetNamedShadowRequest(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + GetNamedShadowRequest::GetNamedShadowRequest(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } GetNamedShadowRequest &GetNamedShadowRequest::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/GetNamedShadowSubscriptionRequest.cpp b/shadow/source/GetNamedShadowSubscriptionRequest.cpp index 19c80b2cd..38f7c3689 100644 --- a/shadow/source/GetNamedShadowSubscriptionRequest.cpp +++ b/shadow/source/GetNamedShadowSubscriptionRequest.cpp @@ -18,7 +18,10 @@ namespace Aws (void)doc; } - void GetNamedShadowSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const { (void)object; } + void GetNamedShadowSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const + { + (void)object; + } GetNamedShadowSubscriptionRequest::GetNamedShadowSubscriptionRequest(const Crt::JsonView &doc) { diff --git a/shadow/source/GetShadowRequest.cpp b/shadow/source/GetShadowRequest.cpp index 021666594..0250b1b8d 100644 --- a/shadow/source/GetShadowRequest.cpp +++ b/shadow/source/GetShadowRequest.cpp @@ -31,7 +31,10 @@ namespace Aws } } - GetShadowRequest::GetShadowRequest(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + GetShadowRequest::GetShadowRequest(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } GetShadowRequest &GetShadowRequest::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/GetShadowResponse.cpp b/shadow/source/GetShadowResponse.cpp index 17330d27a..2275c1e81 100644 --- a/shadow/source/GetShadowResponse.cpp +++ b/shadow/source/GetShadowResponse.cpp @@ -75,7 +75,10 @@ namespace Aws } } - GetShadowResponse::GetShadowResponse(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + GetShadowResponse::GetShadowResponse(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } GetShadowResponse &GetShadowResponse::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/GetShadowSubscriptionRequest.cpp b/shadow/source/GetShadowSubscriptionRequest.cpp index 50398d135..2007e3b00 100644 --- a/shadow/source/GetShadowSubscriptionRequest.cpp +++ b/shadow/source/GetShadowSubscriptionRequest.cpp @@ -18,7 +18,10 @@ namespace Aws (void)doc; } - void GetShadowSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const { (void)object; } + void GetShadowSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const + { + (void)object; + } GetShadowSubscriptionRequest::GetShadowSubscriptionRequest(const Crt::JsonView &doc) { diff --git a/shadow/source/IotShadowClient.cpp b/shadow/source/IotShadowClient.cpp index b9bac21a9..a72e28c0d 100644 --- a/shadow/source/IotShadowClient.cpp +++ b/shadow/source/IotShadowClient.cpp @@ -43,9 +43,15 @@ namespace Aws m_connection = Aws::Crt::Mqtt::MqttConnection::NewConnectionFromMqtt5Client(mqtt5Client); } - IotShadowClient::operator bool() const noexcept { return m_connection && *m_connection; } + IotShadowClient::operator bool() const noexcept + { + return m_connection && *m_connection; + } - int IotShadowClient::GetLastError() const noexcept { return aws_last_error(); } + int IotShadowClient::GetLastError() const noexcept + { + return aws_last_error(); + } bool IotShadowClient::SubscribeToDeleteNamedShadowAccepted( const Aws::Iotshadow::DeleteNamedShadowSubscriptionRequest &request, @@ -59,7 +65,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -73,26 +80,17 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::DeleteShadowResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::DeleteShadowResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "delete" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/delete/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -113,7 +111,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -127,26 +126,17 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::ErrorResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::ErrorResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "delete" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/delete/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -167,7 +157,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -181,24 +172,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::DeleteShadowResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::DeleteShadowResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "delete" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/delete/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -219,7 +202,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -233,24 +217,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::ErrorResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::ErrorResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "delete" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/delete/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -271,7 +247,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -285,26 +262,17 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::GetShadowResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::GetShadowResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "get" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/get/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -325,7 +293,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -339,26 +308,17 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::ErrorResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::ErrorResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "get" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/get/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -379,7 +339,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -393,24 +354,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::GetShadowResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::GetShadowResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "get" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/get/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -431,7 +384,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -445,24 +399,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::ErrorResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::ErrorResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "get" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/get/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -483,7 +429,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -497,26 +444,17 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::ShadowDeltaUpdatedEvent response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::ShadowDeltaUpdatedEvent response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "update" - << "/" - << "delta"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/update/delta"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -537,7 +475,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -551,26 +490,17 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::ShadowUpdatedEvent response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::ShadowUpdatedEvent response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "update" - << "/" - << "documents"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/update/documents"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -591,7 +521,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -605,24 +536,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::ShadowDeltaUpdatedEvent response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::ShadowDeltaUpdatedEvent response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "update" - << "/" - << "delta"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/update/delta"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -643,7 +566,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -657,24 +581,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::ShadowUpdatedEvent response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::ShadowUpdatedEvent response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "update" - << "/" - << "documents"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/update/documents"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -695,7 +611,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -709,26 +626,17 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::UpdateShadowResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::UpdateShadowResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "update" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/update/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -749,7 +657,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -763,26 +672,17 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::ErrorResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::ErrorResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "update" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/update/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -803,7 +703,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -817,24 +718,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::UpdateShadowResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::UpdateShadowResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "update" - << "/" - << "accepted"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/update/accepted"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -855,7 +748,8 @@ namespace Aws uint16_t, const Aws::Crt::String &topic, Aws::Crt::Mqtt::QOS, - int errorCode) { + int errorCode) + { (void)topic; if (errorCode) { @@ -869,24 +763,16 @@ namespace Aws }; auto onSubscribePublish = - [handler]( - Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) { - Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - Aws::Iotshadow::ErrorResponse response(jsonObject); - handler(&response, AWS_ERROR_SUCCESS); - }; + [handler](Aws::Crt::Mqtt::MqttConnection &, const Aws::Crt::String &, const Aws::Crt::ByteBuf &payload) + { + Aws::Crt::String objectStr(reinterpret_cast(payload.buffer), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + Aws::Iotshadow::ErrorResponse response(jsonObject); + handler(&response, AWS_ERROR_SUCCESS); + }; Aws::Crt::StringStream subscribeTopicSStr; - subscribeTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "update" - << "/" - << "rejected"; + subscribeTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/update/rejected"; return m_connection->Subscribe( subscribeTopicSStr.str().c_str(), @@ -901,15 +787,8 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "delete"; + publishTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/delete"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -917,7 +796,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; @@ -932,13 +812,7 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "delete"; + publishTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/delete"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -946,7 +820,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; @@ -961,15 +836,8 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "get"; + publishTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/get"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -977,7 +845,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; @@ -992,13 +861,7 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "get"; + publishTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/get"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -1006,7 +869,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; @@ -1021,15 +885,8 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "name" - << "/" << *request.ShadowName << "/" - << "update"; + publishTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/update"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -1037,7 +894,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; @@ -1052,13 +910,7 @@ namespace Aws const OnPublishComplete &onPubAck) { Aws::Crt::StringStream publishTopicSStr; - publishTopicSStr << "$aws" - << "/" - << "things" - << "/" << *request.ThingName << "/" - << "shadow" - << "/" - << "update"; + publishTopicSStr << "$aws/things/" << *request.ThingName << "/shadow/update"; Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -1066,7 +918,8 @@ namespace Aws Aws::Crt::ByteBuf buf = Aws::Crt::ByteBufNewCopy( Aws::Crt::g_allocator, reinterpret_cast(outgoingJson.data()), outgoingJson.length()); - auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) { + auto onPublishComplete = [buf, onPubAck](Aws::Crt::Mqtt::MqttConnection &, uint16_t, int errorCode) + { onPubAck(errorCode); Aws::Crt::ByteBufDelete(const_cast(buf)); }; diff --git a/shadow/source/IotShadowClientV2.cpp b/shadow/source/IotShadowClientV2.cpp index 433f2c517..48a6163b8 100644 --- a/shadow/source/IotShadowClientV2.cpp +++ b/shadow/source/IotShadowClientV2.cpp @@ -22,721 +22,865 @@ #include #include #include +#include namespace Aws { -namespace Iotshadow -{ + namespace Iotshadow + { -class ClientV2 : public IClientV2 -{ - public: - ClientV2(Aws::Crt::Allocator *allocator, std::shared_ptr bindingClient); - virtual ~ClientV2() = default; + class ClientV2 : public IClientV2 + { + public: + ClientV2( + Aws::Crt::Allocator *allocator, + std::shared_ptr bindingClient); + virtual ~ClientV2() = default; - bool DeleteNamedShadow(const DeleteNamedShadowRequest &request, const DeleteNamedShadowResultHandler &handler) override; + bool DeleteNamedShadow( + const DeleteNamedShadowRequest &request, + const DeleteNamedShadowResultHandler &handler) override; - bool DeleteShadow(const DeleteShadowRequest &request, const DeleteShadowResultHandler &handler) override; + bool DeleteShadow(const DeleteShadowRequest &request, const DeleteShadowResultHandler &handler) override; - bool GetNamedShadow(const GetNamedShadowRequest &request, const GetNamedShadowResultHandler &handler) override; + bool GetNamedShadow(const GetNamedShadowRequest &request, const GetNamedShadowResultHandler &handler) + override; - bool GetShadow(const GetShadowRequest &request, const GetShadowResultHandler &handler) override; + bool GetShadow(const GetShadowRequest &request, const GetShadowResultHandler &handler) override; - bool UpdateNamedShadow(const UpdateNamedShadowRequest &request, const UpdateNamedShadowResultHandler &handler) override; + bool UpdateNamedShadow( + const UpdateNamedShadowRequest &request, + const UpdateNamedShadowResultHandler &handler) override; - bool UpdateShadow(const UpdateShadowRequest &request, const UpdateShadowResultHandler &handler) override; + bool UpdateShadow(const UpdateShadowRequest &request, const UpdateShadowResultHandler &handler) override; + std::shared_ptr CreateNamedShadowDeltaUpdatedStream( + const NamedShadowDeltaUpdatedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; - std::shared_ptr CreateNamedShadowDeltaUpdatedStream(const NamedShadowDeltaUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; + std::shared_ptr CreateNamedShadowUpdatedStream( + const NamedShadowUpdatedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; - std::shared_ptr CreateNamedShadowUpdatedStream(const NamedShadowUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; + std::shared_ptr CreateShadowDeltaUpdatedStream( + const ShadowDeltaUpdatedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; - std::shared_ptr CreateShadowDeltaUpdatedStream(const ShadowDeltaUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; + std::shared_ptr CreateShadowUpdatedStream( + const ShadowUpdatedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; - std::shared_ptr CreateShadowUpdatedStream(const ShadowUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) override; + private: + Aws::Crt::Allocator *m_allocator; + std::shared_ptr m_bindingClient; + }; - private: + ClientV2::ClientV2( + Aws::Crt::Allocator *allocator, + std::shared_ptr bindingClient) + : m_allocator(allocator), m_bindingClient(std::move(bindingClient)) + { + // It's simpler to do this than branch the codegen based on the presence of streaming operations + (void)m_allocator; + } - Aws::Crt::Allocator *m_allocator; + template + static void s_applyUnmodeledErrorToHandler(const std::function &handler, int errorCode) + { + ServiceErrorV2 error(errorCode); + R finalResult(std::move(error)); + handler(std::move(finalResult)); + } - std::shared_ptr m_bindingClient; -}; + template + static void s_applyModeledErrorToHandler(const std::function &handler, E &&modeledError) + { + ServiceErrorV2 error(AWS_ERROR_MQTT_REQUEST_RESPONSE_MODELED_SERVICE_ERROR, std::move(modeledError)); + R finalResult(std::move(error)); + handler(std::move(finalResult)); + } -ClientV2::ClientV2(Aws::Crt::Allocator *allocator, std::shared_ptr bindingClient) : - m_allocator(allocator), - m_bindingClient(std::move(bindingClient)) -{ -} - -template -static void s_applyUnmodeledErrorToHandler(const std::function &handler, int errorCode) { - ServiceErrorV2 error(errorCode); - R finalResult(std::move(error)); - handler(std::move(finalResult)); -} - -template -static void s_applyModeledErrorToHandler(const std::function &handler, E &&modeledError) { - ServiceErrorV2 error(AWS_ERROR_MQTT_REQUEST_RESPONSE_MODELED_SERVICE_ERROR, std::move(modeledError)); - R finalResult(std::move(error)); - handler(std::move(finalResult)); -} - - - -static void s_DeleteNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; - using R = Aws::Iot::RequestResponse::Result>; - - if (!result.IsSuccess()) { - s_applyUnmodeledErrorToHandler(handler, result.GetError()); - return; - } - - auto response = result.GetResponse(); - const auto &payload = response.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); - return; - } - - const auto &topic = response.GetTopic(); - auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); - if (responseTopic == successPathTopic) { - DeleteShadowResponse modeledResponse(jsonObject); - Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); - handler(std::move(finalResult)); - } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); - s_applyModeledErrorToHandler(handler, std::move(modeledError)); - } else { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); - } -} - -bool ClientV2::DeleteNamedShadow(const DeleteNamedShadowRequest &request, const DeleteNamedShadowResultHandler &handler) { - Aws::Crt::StringStream publishTopicStream; - publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/delete"; - Aws::Crt::String publishTopic = publishTopicStream.str(); - - Aws::Crt::StringStream subscriptionTopicStream; - subscriptionTopicStream << publishTopic << "/+"; - Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); - - - struct aws_byte_cursor subscriptionTopicFilters[1] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic) - }; - - Aws::Crt::StringStream responsePathTopicAcceptedStream; - responsePathTopicAcceptedStream << publishTopic << "/accepted"; - Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); - - Aws::Crt::StringStream responsePathTopicRejectedStream; - responsePathTopicRejectedStream << publishTopic << "/rejected"; - Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); - - struct aws_mqtt_request_operation_response_path responsePaths[2]; - responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); - responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); - responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - - Aws::Crt::JsonObject jsonObject; - request.SerializeToObject(jsonObject); - - auto uuid = Aws::Crt::UUID().ToString(); - jsonObject.WithString("clientToken", uuid); - - Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); - - struct aws_mqtt_request_operation_options options; - AWS_ZERO_STRUCT(options); - options.subscription_topic_filters = subscriptionTopicFilters; - options.subscription_topic_filter_count = 1; - options.response_paths = responsePaths; - options.response_path_count = 2; - options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); - options.serialized_request = - Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); - - options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); - - auto resultHandler = - [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) - { s_DeleteNamedShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; - - int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); - - return submitResult == AWS_OP_SUCCESS; -} - - -static void s_DeleteShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; - using R = Aws::Iot::RequestResponse::Result>; - - if (!result.IsSuccess()) { - s_applyUnmodeledErrorToHandler(handler, result.GetError()); - return; - } - - auto response = result.GetResponse(); - const auto &payload = response.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); - return; - } - - const auto &topic = response.GetTopic(); - auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); - if (responseTopic == successPathTopic) { - DeleteShadowResponse modeledResponse(jsonObject); - Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); - handler(std::move(finalResult)); - } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); - s_applyModeledErrorToHandler(handler, std::move(modeledError)); - } else { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); - } -} - -bool ClientV2::DeleteShadow(const DeleteShadowRequest &request, const DeleteShadowResultHandler &handler) { - Aws::Crt::StringStream publishTopicStream; - publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/delete"; - Aws::Crt::String publishTopic = publishTopicStream.str(); - - Aws::Crt::StringStream subscriptionTopicStream; - subscriptionTopicStream << publishTopic << "/+"; - Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); - - - struct aws_byte_cursor subscriptionTopicFilters[1] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic) - }; - - Aws::Crt::StringStream responsePathTopicAcceptedStream; - responsePathTopicAcceptedStream << publishTopic << "/accepted"; - Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); - - Aws::Crt::StringStream responsePathTopicRejectedStream; - responsePathTopicRejectedStream << publishTopic << "/rejected"; - Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); - - struct aws_mqtt_request_operation_response_path responsePaths[2]; - responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); - responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); - responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - - Aws::Crt::JsonObject jsonObject; - request.SerializeToObject(jsonObject); - - auto uuid = Aws::Crt::UUID().ToString(); - jsonObject.WithString("clientToken", uuid); - - Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); - - struct aws_mqtt_request_operation_options options; - AWS_ZERO_STRUCT(options); - options.subscription_topic_filters = subscriptionTopicFilters; - options.subscription_topic_filter_count = 1; - options.response_paths = responsePaths; - options.response_path_count = 2; - options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); - options.serialized_request = - Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); - - options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); - - auto resultHandler = - [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) - { s_DeleteShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; - - int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); - - return submitResult == AWS_OP_SUCCESS; -} - - -static void s_GetNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; - using R = Aws::Iot::RequestResponse::Result>; - - if (!result.IsSuccess()) { - s_applyUnmodeledErrorToHandler(handler, result.GetError()); - return; - } - - auto response = result.GetResponse(); - const auto &payload = response.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); - return; - } - - const auto &topic = response.GetTopic(); - auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); - if (responseTopic == successPathTopic) { - GetShadowResponse modeledResponse(jsonObject); - Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); - handler(std::move(finalResult)); - } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); - s_applyModeledErrorToHandler(handler, std::move(modeledError)); - } else { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); - } -} - -bool ClientV2::GetNamedShadow(const GetNamedShadowRequest &request, const GetNamedShadowResultHandler &handler) { - Aws::Crt::StringStream publishTopicStream; - publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/get"; - Aws::Crt::String publishTopic = publishTopicStream.str(); - - Aws::Crt::StringStream subscriptionTopicStream; - subscriptionTopicStream << publishTopic << "/+"; - Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); - - - struct aws_byte_cursor subscriptionTopicFilters[1] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic) - }; - - Aws::Crt::StringStream responsePathTopicAcceptedStream; - responsePathTopicAcceptedStream << publishTopic << "/accepted"; - Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); - - Aws::Crt::StringStream responsePathTopicRejectedStream; - responsePathTopicRejectedStream << publishTopic << "/rejected"; - Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); - - struct aws_mqtt_request_operation_response_path responsePaths[2]; - responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); - responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); - responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - - Aws::Crt::JsonObject jsonObject; - request.SerializeToObject(jsonObject); - - auto uuid = Aws::Crt::UUID().ToString(); - jsonObject.WithString("clientToken", uuid); - - Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); - - struct aws_mqtt_request_operation_options options; - AWS_ZERO_STRUCT(options); - options.subscription_topic_filters = subscriptionTopicFilters; - options.subscription_topic_filter_count = 1; - options.response_paths = responsePaths; - options.response_path_count = 2; - options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); - options.serialized_request = - Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); - - options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); - - auto resultHandler = - [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) - { s_GetNamedShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; - - int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); - - return submitResult == AWS_OP_SUCCESS; -} - - -static void s_GetShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; - using R = Aws::Iot::RequestResponse::Result>; - - if (!result.IsSuccess()) { - s_applyUnmodeledErrorToHandler(handler, result.GetError()); - return; - } - - auto response = result.GetResponse(); - const auto &payload = response.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); - return; - } - - const auto &topic = response.GetTopic(); - auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); - if (responseTopic == successPathTopic) { - GetShadowResponse modeledResponse(jsonObject); - Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); - handler(std::move(finalResult)); - } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); - s_applyModeledErrorToHandler(handler, std::move(modeledError)); - } else { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); - } -} - -bool ClientV2::GetShadow(const GetShadowRequest &request, const GetShadowResultHandler &handler) { - Aws::Crt::StringStream publishTopicStream; - publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/get"; - Aws::Crt::String publishTopic = publishTopicStream.str(); - - Aws::Crt::StringStream subscriptionTopicStream; - subscriptionTopicStream << publishTopic << "/+"; - Aws::Crt::String subscriptionTopic = subscriptionTopicStream.str(); - - - struct aws_byte_cursor subscriptionTopicFilters[1] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic) - }; - - Aws::Crt::StringStream responsePathTopicAcceptedStream; - responsePathTopicAcceptedStream << publishTopic << "/accepted"; - Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); - - Aws::Crt::StringStream responsePathTopicRejectedStream; - responsePathTopicRejectedStream << publishTopic << "/rejected"; - Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); - - struct aws_mqtt_request_operation_response_path responsePaths[2]; - responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); - responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); - responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - - Aws::Crt::JsonObject jsonObject; - request.SerializeToObject(jsonObject); - - auto uuid = Aws::Crt::UUID().ToString(); - jsonObject.WithString("clientToken", uuid); - - Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); - - struct aws_mqtt_request_operation_options options; - AWS_ZERO_STRUCT(options); - options.subscription_topic_filters = subscriptionTopicFilters; - options.subscription_topic_filter_count = 1; - options.response_paths = responsePaths; - options.response_path_count = 2; - options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); - options.serialized_request = - Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); - - options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); - - auto resultHandler = - [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) - { s_GetShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; - - int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); - - return submitResult == AWS_OP_SUCCESS; -} - - -static void s_UpdateNamedShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; - using R = Aws::Iot::RequestResponse::Result>; - - if (!result.IsSuccess()) { - s_applyUnmodeledErrorToHandler(handler, result.GetError()); - return; - } - - auto response = result.GetResponse(); - const auto &payload = response.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); - return; - } - - const auto &topic = response.GetTopic(); - auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); - if (responseTopic == successPathTopic) { - UpdateShadowResponse modeledResponse(jsonObject); - Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); - handler(std::move(finalResult)); - } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); - s_applyModeledErrorToHandler(handler, std::move(modeledError)); - } else { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); - } -} - -bool ClientV2::UpdateNamedShadow(const UpdateNamedShadowRequest &request, const UpdateNamedShadowResultHandler &handler) { - Aws::Crt::StringStream publishTopicStream; - publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update"; - Aws::Crt::String publishTopic = publishTopicStream.str(); - - Aws::Crt::StringStream subscriptionTopicStream0; - subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update"; - Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); - - Aws::Crt::StringStream subscriptionTopicStream1; - subscriptionTopicStream1 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update"; - Aws::Crt::String subscriptionTopic1 = subscriptionTopicStream1.str(); - - - struct aws_byte_cursor subscriptionTopicFilters[2] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic0), - Aws::Crt::ByteCursorFromString(subscriptionTopic1), - }; - - Aws::Crt::StringStream responsePathTopicAcceptedStream; - responsePathTopicAcceptedStream << publishTopic << "/accepted"; - Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); - - Aws::Crt::StringStream responsePathTopicRejectedStream; - responsePathTopicRejectedStream << publishTopic << "/rejected"; - Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); - - struct aws_mqtt_request_operation_response_path responsePaths[2]; - responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); - responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); - responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - - Aws::Crt::JsonObject jsonObject; - request.SerializeToObject(jsonObject); - - auto uuid = Aws::Crt::UUID().ToString(); - jsonObject.WithString("clientToken", uuid); - - Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); - - struct aws_mqtt_request_operation_options options; - AWS_ZERO_STRUCT(options); - options.subscription_topic_filters = subscriptionTopicFilters; - options.subscription_topic_filter_count = 2; - options.response_paths = responsePaths; - options.response_path_count = 2; - options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); - options.serialized_request = - Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); - - options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); - - auto resultHandler = - [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) - { s_UpdateNamedShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; - - int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); - - return submitResult == AWS_OP_SUCCESS; -} - - -static void s_UpdateShadowResponseHandler(Aws::Iot::RequestResponse::UnmodeledResult &&result, const std::function &handler, const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; - using R = Aws::Iot::RequestResponse::Result>; - - if (!result.IsSuccess()) { - s_applyUnmodeledErrorToHandler(handler, result.GetError()); - return; - } - - auto response = result.GetResponse(); - const auto &payload = response.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); - return; - } - - const auto &topic = response.GetTopic(); - auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); - if (responseTopic == successPathTopic) { - UpdateShadowResponse modeledResponse(jsonObject); - Aws::Iot::RequestResponse::Result> finalResult(std::move(modeledResponse)); - handler(std::move(finalResult)); - } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); - s_applyModeledErrorToHandler(handler, std::move(modeledError)); - } else { - s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); - } -} - -bool ClientV2::UpdateShadow(const UpdateShadowRequest &request, const UpdateShadowResultHandler &handler) { - Aws::Crt::StringStream publishTopicStream; - publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/update"; - Aws::Crt::String publishTopic = publishTopicStream.str(); + static void s_DeleteNamedShadowResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const DeleteNamedShadowResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; - Aws::Crt::StringStream subscriptionTopicStream0; - subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/shadow/update"; - Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } - Aws::Crt::StringStream subscriptionTopicStream1; - subscriptionTopicStream1 << "$aws/things/" << *request.ThingName << "/shadow/update"; - Aws::Crt::String subscriptionTopic1 = subscriptionTopicStream1.str(); + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + DeleteShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } - struct aws_byte_cursor subscriptionTopicFilters[2] = { - Aws::Crt::ByteCursorFromString(subscriptionTopic0), - Aws::Crt::ByteCursorFromString(subscriptionTopic1), - }; + bool ClientV2::DeleteNamedShadow( + const DeleteNamedShadowRequest &request, + const DeleteNamedShadowResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/delete"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/delete/+"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + }; - Aws::Crt::StringStream responsePathTopicAcceptedStream; - responsePathTopicAcceptedStream << publishTopic << "/accepted"; - Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_DeleteNamedShadowResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; - Aws::Crt::StringStream responsePathTopicRejectedStream; - responsePathTopicRejectedStream << publishTopic << "/rejected"; - Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); - struct aws_mqtt_request_operation_response_path responsePaths[2]; - responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); - responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); - responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); - - Aws::Crt::JsonObject jsonObject; - request.SerializeToObject(jsonObject); + return submitResult == AWS_OP_SUCCESS; + } - auto uuid = Aws::Crt::UUID().ToString(); - jsonObject.WithString("clientToken", uuid); + static void s_DeleteShadowResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const DeleteShadowResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; - Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } - struct aws_mqtt_request_operation_options options; - AWS_ZERO_STRUCT(options); - options.subscription_topic_filters = subscriptionTopicFilters; - options.subscription_topic_filter_count = 2; - options.response_paths = responsePaths; - options.response_path_count = 2; - options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); - options.serialized_request = - Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } - options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + DeleteShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } - auto resultHandler = - [handler, responsePathTopicAccepted, responsePathTopicRejected](Aws::Iot::RequestResponse::UnmodeledResult &&result) - { s_UpdateShadowResponseHandler(std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; + bool ClientV2::DeleteShadow(const DeleteShadowRequest &request, const DeleteShadowResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/delete"; + Aws::Crt::String publishTopic = publishTopicStream.str(); - int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/shadow/delete/+"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); - return submitResult == AWS_OP_SUCCESS; -} + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + }; + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_DeleteShadowResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); -template class ServiceStreamingOperation : public Aws::Iot::RequestResponse::IStreamingOperation { - public: + return submitResult == AWS_OP_SUCCESS; + } - explicit ShadowStreamingOperation(std::shared_ptr stream) : - m_stream(std::move(stream)) + static void s_GetNamedShadowResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const GetNamedShadowResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + GetShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } } - static std::shared_ptr Create(Aws::Crt::Allocator *allocator, const std::shared_ptr &bindingClient, const Aws::Crt::String &subscriptionTopicFilter, const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { + bool ClientV2::GetNamedShadow(const GetNamedShadowRequest &request, const GetNamedShadowResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/get"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/get/+"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + }; - std::function unmodeledHandler = [options](Aws::Iot::RequestResponse::IncomingPublishEvent &&event){ - const auto &payload = event.GetPayload(); - Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); - Aws::Crt::JsonObject jsonObject(objectStr); - if (!jsonObject.WasParseSuccessful()) { - return; - } + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_GetNamedShadowResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + static void s_GetShadowResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const GetShadowResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } + + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + GetShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } + + bool ClientV2::GetShadow(const GetShadowRequest &request, const GetShadowResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/get"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/shadow/get/+"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); - T modeledEvent(jsonObject); - options.GetStreamHandler()(std::move(modeledEvent)); + struct aws_byte_cursor subscriptionTopicFilters[1] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), }; - Aws::Iot::RequestResponse::StreamingOperationOptionsInternal internalOptions; - internalOptions.subscriptionTopicFilter = Aws::Crt::ByteCursorFromString(subscriptionTopicFilter); - internalOptions.subscriptionStatusEventHandler = options.GetSubscriptionStatusEventHandler(); - internalOptions.incomingPublishEventHandler = unmodeledHandler; + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 1; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_GetShadowResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; - auto unmodeledStream = bindingClient->CreateStream(internalOptions); - if (!unmodeledStream) { - return nullptr; + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; + } + + static void s_UpdateNamedShadowResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const UpdateNamedShadowResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; + + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } + + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; } - return Aws::Crt::MakeShared(allocator, unmodeledStream); + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + UpdateShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } } - void Open() override { - m_stream->Open(); + bool ClientV2::UpdateNamedShadow( + const UpdateNamedShadowRequest &request, + const UpdateNamedShadowResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/update"; + Aws::Crt::String publishTopic = publishTopicStream.str(); + + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/update/accepted"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); + + Aws::Crt::StringStream subscriptionTopicStream1; + subscriptionTopicStream1 << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/update/rejected"; + Aws::Crt::String subscriptionTopic1 = subscriptionTopicStream1.str(); + + struct aws_byte_cursor subscriptionTopicFilters[2] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + Aws::Crt::ByteCursorFromString(subscriptionTopic1), + }; + + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 2; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_UpdateNamedShadowResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; + + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + + return submitResult == AWS_OP_SUCCESS; } - private: + static void s_UpdateShadowResponseHandler( + Aws::Iot::RequestResponse::UnmodeledResult &&result, + const UpdateShadowResultHandler &handler, + const Aws::Crt::String &successPathTopic, + const Aws::Crt::String &failurePathTopic) + { + using E = V2ServiceError; + using R = Aws::Iot::RequestResponse::Result>; - std::shared_ptr m_stream; -}; + if (!result.IsSuccess()) + { + s_applyUnmodeledErrorToHandler(handler, result.GetError()); + return; + } -std::shared_ptr ClientV2::CreateNamedShadowDeltaUpdatedStream(const NamedShadowDeltaUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { - Aws::Crt::StringStream topicStream; - topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/delta"; - Aws::Crt::String topic = topicStream.str(); + auto response = result.GetResponse(); + const auto &payload = response.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_PAYLOAD_PARSE_ERROR); + return; + } - return ServiceStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); -} + const auto &topic = response.GetTopic(); + auto responseTopic = Aws::Crt::String((const char *)topic.ptr, topic.len); + if (responseTopic == successPathTopic) + { + UpdateShadowResponse modeledResponse(jsonObject); + Aws::Iot::RequestResponse::Result> finalResult( + std::move(modeledResponse)); + handler(std::move(finalResult)); + } + else if (responseTopic == failurePathTopic) + { + V2ServiceError modeledError(jsonObject); + s_applyModeledErrorToHandler(handler, std::move(modeledError)); + } + else + { + s_applyUnmodeledErrorToHandler(handler, AWS_ERROR_MQTT_REQUEST_RESPONSE_INVALID_RESPONSE_PATH); + } + } -std::shared_ptr ClientV2::CreateNamedShadowUpdatedStream(const NamedShadowUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { - Aws::Crt::StringStream topicStream; - topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName << "/update/documents"; - Aws::Crt::String topic = topicStream.str(); + bool ClientV2::UpdateShadow(const UpdateShadowRequest &request, const UpdateShadowResultHandler &handler) + { + Aws::Crt::StringStream publishTopicStream; + publishTopicStream << "$aws/things/" << *request.ThingName << "/shadow/update"; + Aws::Crt::String publishTopic = publishTopicStream.str(); - return ServiceStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); -} + Aws::Crt::StringStream subscriptionTopicStream0; + subscriptionTopicStream0 << "$aws/things/" << *request.ThingName << "/shadow/update/accepted"; + Aws::Crt::String subscriptionTopic0 = subscriptionTopicStream0.str(); -std::shared_ptr ClientV2::CreateShadowDeltaUpdatedStream(const ShadowDeltaUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { - Aws::Crt::StringStream topicStream; - topicStream << "$aws/things/" << *request.ThingName << "/shadow/update/delta"; - Aws::Crt::String topic = topicStream.str(); + Aws::Crt::StringStream subscriptionTopicStream1; + subscriptionTopicStream1 << "$aws/things/" << *request.ThingName << "/shadow/update/rejected"; + Aws::Crt::String subscriptionTopic1 = subscriptionTopicStream1.str(); - return ServiceStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); -} + struct aws_byte_cursor subscriptionTopicFilters[2] = { + Aws::Crt::ByteCursorFromString(subscriptionTopic0), + Aws::Crt::ByteCursorFromString(subscriptionTopic1), + }; -std::shared_ptr ClientV2::CreateShadowUpdatedStream(const ShadowUpdatedSubscriptionRequest &request, const const Aws::Iot::RequestResponse::StreamingOperationOptions &options) { - Aws::Crt::StringStream topicStream; - topicStream << "$aws/things/" << *request.ThingName << "/shadow/update/documents"; - Aws::Crt::String topic = topicStream.str(); + Aws::Crt::StringStream responsePathTopicAcceptedStream; + responsePathTopicAcceptedStream << publishTopic << "/accepted"; + Aws::Crt::String responsePathTopicAccepted = responsePathTopicAcceptedStream.str(); + + Aws::Crt::StringStream responsePathTopicRejectedStream; + responsePathTopicRejectedStream << publishTopic << "/rejected"; + Aws::Crt::String responsePathTopicRejected = responsePathTopicRejectedStream.str(); + + struct aws_mqtt_request_operation_response_path responsePaths[2]; + responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); + responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + responsePaths[0].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + responsePaths[1].correlation_token_json_path = Aws::Crt::ByteCursorFromCString("clientToken"); + + Aws::Crt::JsonObject jsonObject; + request.SerializeToObject(jsonObject); + + auto uuid = Aws::Crt::UUID().ToString(); + jsonObject.WithString("clientToken", uuid); + + Aws::Crt::String outgoingJson = jsonObject.View().WriteCompact(true); + + struct aws_mqtt_request_operation_options options; + AWS_ZERO_STRUCT(options); + options.subscription_topic_filters = subscriptionTopicFilters; + options.subscription_topic_filter_count = 2; + options.response_paths = responsePaths; + options.response_path_count = 2; + options.publish_topic = Aws::Crt::ByteCursorFromString(publishTopic); + options.serialized_request = + Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); + + options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); + + auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { + s_UpdateShadowResponseHandler( + std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); + }; - return ServiceStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); -} + int submitResult = m_bindingClient->SubmitRequest(options, std::move(resultHandler)); + return submitResult == AWS_OP_SUCCESS; + } + template class ServiceStreamingOperation : public Aws::Iot::RequestResponse::IStreamingOperation + { + public: + explicit ServiceStreamingOperation(std::shared_ptr stream) + : m_stream(std::move(stream)) + { + } -std::shared_ptr NewClientFrom5(const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, - const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, - Aws::Crt::Allocator *allocator) { + static std::shared_ptr Create( + Aws::Crt::Allocator *allocator, + const std::shared_ptr &bindingClient, + const Aws::Crt::String &subscriptionTopicFilter, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + { + + std::function unmodeledHandler = + [options](Aws::Iot::RequestResponse::IncomingPublishEvent &&event) + { + const auto &payload = event.GetPayload(); + Aws::Crt::String objectStr(reinterpret_cast(payload.ptr), payload.len); + Aws::Crt::JsonObject jsonObject(objectStr); + if (!jsonObject.WasParseSuccessful()) + { + return; + } + + T modeledEvent(jsonObject); + options.GetStreamHandler()(std::move(modeledEvent)); + }; + + Aws::Iot::RequestResponse::StreamingOperationOptionsInternal internalOptions; + internalOptions.subscriptionTopicFilter = Aws::Crt::ByteCursorFromString(subscriptionTopicFilter); + internalOptions.subscriptionStatusEventHandler = options.GetSubscriptionStatusEventHandler(); + internalOptions.incomingPublishEventHandler = unmodeledHandler; + + auto unmodeledStream = bindingClient->CreateStream(internalOptions); + if (!unmodeledStream) + { + return nullptr; + } + + return Aws::Crt::MakeShared>(allocator, unmodeledStream); + } + + void Open() override { m_stream->Open(); } + + private: + std::shared_ptr m_stream; + }; + + std::shared_ptr ClientV2::CreateNamedShadowDeltaUpdatedStream( + const NamedShadowDeltaUpdatedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/update/delta"; + Aws::Crt::String topic = topicStream.str(); + + return ServiceStreamingOperation::Create( + m_allocator, m_bindingClient, topic, options); + } + + std::shared_ptr ClientV2::CreateNamedShadowUpdatedStream( + const NamedShadowUpdatedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/shadow/name/" << *request.ShadowName + << "/update/documents"; + Aws::Crt::String topic = topicStream.str(); + + return ServiceStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); + } + + std::shared_ptr ClientV2::CreateShadowDeltaUpdatedStream( + const ShadowDeltaUpdatedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/shadow/update/delta"; + Aws::Crt::String topic = topicStream.str(); - std::shared_ptr bindingClient = Aws::Iot::RequestResponse::NewClientFrom5(protocolClient, options, allocator); - if (nullptr == bindingClient) { - return nullptr; - } + return ServiceStreamingOperation::Create( + m_allocator, m_bindingClient, topic, options); + } + + std::shared_ptr ClientV2::CreateShadowUpdatedStream( + const ShadowUpdatedSubscriptionRequest &request, + const Aws::Iot::RequestResponse::StreamingOperationOptions &options) + { + Aws::Crt::StringStream topicStream; + topicStream << "$aws/things/" << *request.ThingName << "/shadow/update/documents"; + Aws::Crt::String topic = topicStream.str(); - return Aws::Crt::MakeShared(allocator, allocator, bindingClient); -} + return ServiceStreamingOperation::Create(m_allocator, m_bindingClient, topic, options); + } -std::shared_ptr NewClientFrom311(const Aws::Crt::Mqtt::MqttConnection &protocolClient, - const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, - Aws::Crt::Allocator *allocator) { + std::shared_ptr NewClientFrom5( + const Aws::Crt::Mqtt5::Mqtt5Client &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator) + { - std::shared_ptr bindingClient = Aws::Iot::RequestResponse::NewClientFrom311(protocolClient, options, allocator); - if (nullptr == bindingClient) { - return nullptr; - } + std::shared_ptr bindingClient = + Aws::Iot::RequestResponse::NewClientFrom5(protocolClient, options, allocator); + if (nullptr == bindingClient) + { + return nullptr; + } - return Aws::Crt::MakeShared(allocator, allocator, bindingClient); -} + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + } + + std::shared_ptr NewClientFrom311( + const Aws::Crt::Mqtt::MqttConnection &protocolClient, + const Aws::Iot::RequestResponse::RequestResponseClientOptions &options, + Aws::Crt::Allocator *allocator) + { + + std::shared_ptr bindingClient = + Aws::Iot::RequestResponse::NewClientFrom311(protocolClient, options, allocator); + if (nullptr == bindingClient) + { + return nullptr; + } + + return Aws::Crt::MakeShared(allocator, allocator, bindingClient); + } -} -} + } // namespace Iotshadow +} // namespace Aws diff --git a/shadow/source/ShadowDeltaUpdatedEvent.cpp b/shadow/source/ShadowDeltaUpdatedEvent.cpp index 0585bfce5..fef4415f1 100644 --- a/shadow/source/ShadowDeltaUpdatedEvent.cpp +++ b/shadow/source/ShadowDeltaUpdatedEvent.cpp @@ -71,7 +71,10 @@ namespace Aws } } - ShadowDeltaUpdatedEvent::ShadowDeltaUpdatedEvent(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + ShadowDeltaUpdatedEvent::ShadowDeltaUpdatedEvent(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } ShadowDeltaUpdatedEvent &ShadowDeltaUpdatedEvent::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/ShadowMetadata.cpp b/shadow/source/ShadowMetadata.cpp index 31e3bba32..8909ec834 100644 --- a/shadow/source/ShadowMetadata.cpp +++ b/shadow/source/ShadowMetadata.cpp @@ -41,7 +41,10 @@ namespace Aws } } - ShadowMetadata::ShadowMetadata(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + ShadowMetadata::ShadowMetadata(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } ShadowMetadata &ShadowMetadata::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/ShadowState.cpp b/shadow/source/ShadowState.cpp index f32d829f9..e7c94ca1b 100644 --- a/shadow/source/ShadowState.cpp +++ b/shadow/source/ShadowState.cpp @@ -41,7 +41,10 @@ namespace Aws } } - ShadowState::ShadowState(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + ShadowState::ShadowState(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } ShadowState &ShadowState::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/ShadowStateWithDelta.cpp b/shadow/source/ShadowStateWithDelta.cpp index 42ec67a4d..df9c31f4f 100644 --- a/shadow/source/ShadowStateWithDelta.cpp +++ b/shadow/source/ShadowStateWithDelta.cpp @@ -51,7 +51,10 @@ namespace Aws } } - ShadowStateWithDelta::ShadowStateWithDelta(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + ShadowStateWithDelta::ShadowStateWithDelta(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } ShadowStateWithDelta &ShadowStateWithDelta::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/ShadowUpdatedEvent.cpp b/shadow/source/ShadowUpdatedEvent.cpp index 550674d7c..d8054c914 100644 --- a/shadow/source/ShadowUpdatedEvent.cpp +++ b/shadow/source/ShadowUpdatedEvent.cpp @@ -55,7 +55,10 @@ namespace Aws } } - ShadowUpdatedEvent::ShadowUpdatedEvent(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + ShadowUpdatedEvent::ShadowUpdatedEvent(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } ShadowUpdatedEvent &ShadowUpdatedEvent::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/ShadowUpdatedSnapshot.cpp b/shadow/source/ShadowUpdatedSnapshot.cpp index 493baa1f5..4c774e70a 100644 --- a/shadow/source/ShadowUpdatedSnapshot.cpp +++ b/shadow/source/ShadowUpdatedSnapshot.cpp @@ -55,7 +55,10 @@ namespace Aws } } - ShadowUpdatedSnapshot::ShadowUpdatedSnapshot(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + ShadowUpdatedSnapshot::ShadowUpdatedSnapshot(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } ShadowUpdatedSnapshot &ShadowUpdatedSnapshot::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/ShadowUpdatedSubscriptionRequest.cpp b/shadow/source/ShadowUpdatedSubscriptionRequest.cpp index d026f1037..4042363cb 100644 --- a/shadow/source/ShadowUpdatedSubscriptionRequest.cpp +++ b/shadow/source/ShadowUpdatedSubscriptionRequest.cpp @@ -18,7 +18,10 @@ namespace Aws (void)doc; } - void ShadowUpdatedSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const { (void)object; } + void ShadowUpdatedSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const + { + (void)object; + } ShadowUpdatedSubscriptionRequest::ShadowUpdatedSubscriptionRequest(const Crt::JsonView &doc) { diff --git a/shadow/source/UpdateNamedShadowRequest.cpp b/shadow/source/UpdateNamedShadowRequest.cpp index 81c2a005d..540420064 100644 --- a/shadow/source/UpdateNamedShadowRequest.cpp +++ b/shadow/source/UpdateNamedShadowRequest.cpp @@ -53,7 +53,10 @@ namespace Aws } } - UpdateNamedShadowRequest::UpdateNamedShadowRequest(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + UpdateNamedShadowRequest::UpdateNamedShadowRequest(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } UpdateNamedShadowRequest &UpdateNamedShadowRequest::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/UpdateShadowRequest.cpp b/shadow/source/UpdateShadowRequest.cpp index c1746bdc0..8230a0c50 100644 --- a/shadow/source/UpdateShadowRequest.cpp +++ b/shadow/source/UpdateShadowRequest.cpp @@ -53,7 +53,10 @@ namespace Aws } } - UpdateShadowRequest::UpdateShadowRequest(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + UpdateShadowRequest::UpdateShadowRequest(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } UpdateShadowRequest &UpdateShadowRequest::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/UpdateShadowResponse.cpp b/shadow/source/UpdateShadowResponse.cpp index cd0703f77..3df213d1f 100644 --- a/shadow/source/UpdateShadowResponse.cpp +++ b/shadow/source/UpdateShadowResponse.cpp @@ -75,7 +75,10 @@ namespace Aws } } - UpdateShadowResponse::UpdateShadowResponse(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } + UpdateShadowResponse::UpdateShadowResponse(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } UpdateShadowResponse &UpdateShadowResponse::operator=(const Crt::JsonView &doc) { diff --git a/shadow/source/UpdateShadowSubscriptionRequest.cpp b/shadow/source/UpdateShadowSubscriptionRequest.cpp index 7c4cee2ac..a2af81d2a 100644 --- a/shadow/source/UpdateShadowSubscriptionRequest.cpp +++ b/shadow/source/UpdateShadowSubscriptionRequest.cpp @@ -18,7 +18,10 @@ namespace Aws (void)doc; } - void UpdateShadowSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const { (void)object; } + void UpdateShadowSubscriptionRequest::SerializeToObject(Aws::Crt::JsonObject &object) const + { + (void)object; + } UpdateShadowSubscriptionRequest::UpdateShadowSubscriptionRequest(const Crt::JsonView &doc) { diff --git a/shadow/source/V2ServiceError.cpp b/shadow/source/V2ServiceError.cpp new file mode 100644 index 000000000..84d32553c --- /dev/null +++ b/shadow/source/V2ServiceError.cpp @@ -0,0 +1,76 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated + */ +#include + +namespace Aws +{ + namespace Iotshadow + { + + void V2ServiceError::LoadFromObject(V2ServiceError &val, const Aws::Crt::JsonView &doc) + { + (void)val; + (void)doc; + + if (doc.ValueExists("clientToken")) + { + val.ClientToken = doc.GetString("clientToken"); + } + + if (doc.ValueExists("code")) + { + val.Code = doc.GetInteger("code"); + } + + if (doc.ValueExists("message")) + { + val.Message = doc.GetString("message"); + } + + if (doc.ValueExists("timestamp")) + { + val.Timestamp = doc.GetDouble("timestamp"); + } + } + + void V2ServiceError::SerializeToObject(Aws::Crt::JsonObject &object) const + { + (void)object; + + if (ClientToken) + { + object.WithString("clientToken", *ClientToken); + } + + if (Code) + { + object.WithInteger("code", *Code); + } + + if (Message) + { + object.WithString("message", *Message); + } + + if (Timestamp) + { + object.WithDouble("timestamp", Timestamp->SecondsWithMSPrecision()); + } + } + + V2ServiceError::V2ServiceError(const Crt::JsonView &doc) + { + LoadFromObject(*this, doc); + } + + V2ServiceError &V2ServiceError::operator=(const Crt::JsonView &doc) + { + *this = V2ServiceError(doc); + return *this; + } + + } // namespace Iotshadow +} // namespace Aws From 4632528dc08df45bb7e2bce8e5d7627007cae6a2 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Fri, 18 Oct 2024 12:48:49 -0700 Subject: [PATCH 06/33] Shadow tests --- shadow/CMakeLists.txt | 6 + .../include/aws/iotshadow/IotShadowClientV2.h | 29 +- shadow/tests/CMakeLists.txt | 32 ++ shadow/tests/v2ClientTests.cpp | 538 ++++++++++++++++++ 4 files changed, 593 insertions(+), 12 deletions(-) create mode 100644 shadow/tests/CMakeLists.txt create mode 100644 shadow/tests/v2ClientTests.cpp diff --git a/shadow/CMakeLists.txt b/shadow/CMakeLists.txt index 771a462a8..5a1426959 100644 --- a/shadow/CMakeLists.txt +++ b/shadow/CMakeLists.txt @@ -131,3 +131,9 @@ configure_file("cmake/iotshadow-cpp-config.cmake" install(FILES "${CMAKE_CURRENT_BINARY_DIR}/iotshadow-cpp-config.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/IotShadow-cpp/cmake/" COMPONENT Development) + +if(NOT CMAKE_CROSSCOMPILING) + if (BUILD_TESTING) + add_subdirectory(tests) + endif() +endif() diff --git a/shadow/include/aws/iotshadow/IotShadowClientV2.h b/shadow/include/aws/iotshadow/IotShadowClientV2.h index 2ce41b594..b00509b53 100644 --- a/shadow/include/aws/iotshadow/IotShadowClientV2.h +++ b/shadow/include/aws/iotshadow/IotShadowClientV2.h @@ -81,18 +81,23 @@ namespace Aws class UpdateShadowResponse; class V2ServiceError; - using DeleteNamedShadowResultHandler = std::function> &&)>; - using DeleteShadowResultHandler = std::function> &&)>; - using GetNamedShadowResultHandler = std::function> &&)>; - using GetShadowResultHandler = std::function> &&)>; - using UpdateNamedShadowResultHandler = std::function> &&)>; - using UpdateShadowResultHandler = std::function> &&)>; + using DeleteNamedShadowResult = + Aws::Iot::RequestResponse::Result>; + using DeleteNamedShadowResultHandler = std::function; + using DeleteShadowResult = + Aws::Iot::RequestResponse::Result>; + using DeleteShadowResultHandler = std::function; + using GetNamedShadowResult = + Aws::Iot::RequestResponse::Result>; + using GetNamedShadowResultHandler = std::function; + using GetShadowResult = Aws::Iot::RequestResponse::Result>; + using GetShadowResultHandler = std::function; + using UpdateNamedShadowResult = + Aws::Iot::RequestResponse::Result>; + using UpdateNamedShadowResultHandler = std::function; + using UpdateShadowResult = + Aws::Iot::RequestResponse::Result>; + using UpdateShadowResultHandler = std::function; /** * The AWS IoT Device Shadow service adds shadows to AWS IoT thing objects. Shadows are a simple data store for diff --git a/shadow/tests/CMakeLists.txt b/shadow/tests/CMakeLists.txt new file mode 100644 index 000000000..bbc19e2a5 --- /dev/null +++ b/shadow/tests/CMakeLists.txt @@ -0,0 +1,32 @@ +include(AwsTestHarness) +enable_testing() +include(CTest) + +file(GLOB TEST_SRC "*.cpp") +file(GLOB TEST_HDRS "*.h") +file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) + +set(TEST_BINARY_NAME ${PROJECT_NAME}-tests) + +add_net_test_case(ShadowV2ClientCreateDestroy5) +add_net_test_case(ShadowV2ClientCreateDestroy311) +add_net_test_case(ShadowV2ClientGetNonExistentNamedShadow5) +add_net_test_case(ShadowV2ClientGetNonExistentNamedShadow311) +add_net_test_case(ShadowV2ClientCreateDestroyNamedShadow5) +add_net_test_case(ShadowV2ClientCreateDestroyNamedShadow311) +add_net_test_case(ShadowV2ClientDeltaUpdateNamedShadow5) +add_net_test_case(ShadowV2ClientDeltaUpdateNamedShadow311) + +generate_cpp_test_driver(${TEST_BINARY_NAME}) + +aws_add_sanitizers(${TEST_BINARY_NAME}) + + # set extra warning flags +if(AWS_WARNINGS_ARE_ERRORS) + if(MSVC) + target_compile_options(${TEST_BINARY_NAME} PRIVATE /W4 /WX /wd4068) + else() + target_compile_options(${TEST_BINARY_NAME} PRIVATE -Wall -Wno-long-long -Werror) + endif() +endif() + diff --git a/shadow/tests/v2ClientTests.cpp b/shadow/tests/v2ClientTests.cpp new file mode 100644 index 000000000..1a293eea9 --- /dev/null +++ b/shadow/tests/v2ClientTests.cpp @@ -0,0 +1,538 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Aws +{ + namespace Iot + { + namespace ServiceTesting + { + + AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableHost, "AWS_TEST_MQTT5_IOT_CORE_HOST"); + AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableCertificatePath, "AWS_TEST_MQTT5_IOT_CORE_RSA_CERT"); + AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariablePrivateKeyPath, "AWS_TEST_MQTT5_IOT_CORE_RSA_KEY"); + + inline std::shared_ptr createProtocolClient5(Aws::Crt::Allocator *allocator) + { + std::shared_ptr client = nullptr; + + struct aws_string *host = NULL; + struct aws_string *certificatePath = NULL; + struct aws_string *privateKeyPath = NULL; + + if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || + certificatePath == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || + privateKeyPath == nullptr) + { + goto done; + } + + { + std::mutex lock; + std::condition_variable signal; + bool connected = false; + + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( + aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); + Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); + + Aws::Crt::Mqtt5::Mqtt5ClientOptions mqtt5Options(allocator); + mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); + mqtt5Options.WithPort(8883); + mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); + + mqtt5Options.WithClientConnectionSuccessCallback([&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &){ + { + std::lock_guard guard(lock); + connected = true; + } + signal.notify_all(); + }); + + client = Aws::Crt::Mqtt5::Mqtt5Client::NewMqtt5Client(mqtt5Options, allocator); + client->Start(); + + std::unique_lock waitLock(lock); + signal.wait(waitLock, [&connected](){ return connected; }); + } + + done: + + aws_string_destroy(host); + aws_string_destroy(certificatePath); + aws_string_destroy(privateKeyPath); + + return client; + } + + inline std::shared_ptr createProtocolClient311( + Aws::Crt::Allocator *allocator) + { + std::shared_ptr connection = nullptr; + + struct aws_string *host = NULL; + struct aws_string *certificatePath = NULL; + struct aws_string *privateKeyPath = NULL; + + if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || + certificatePath == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || + privateKeyPath == nullptr) + { + goto done; + } + + { + std::mutex lock; + std::condition_variable signal; + bool connected = false; + + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( + aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); + Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); + + Aws::Crt::Io::SocketOptions socketOptions; + socketOptions.SetConnectTimeoutMs(3000); + + Aws::Crt::Mqtt::MqttClient client; + connection = client.NewConnection(aws_string_c_str(host), 8883, socketOptions, tlsContext, false); + + connection->OnConnectionSuccess = [&connected, &lock, &signal](Aws::Crt::Mqtt::MqttConnection &connection, Aws::Crt::Mqtt::OnConnectionSuccessData *callbackData) { + { + std::lock_guard guard(lock); + connected = true; + } + signal.notify_all(); + }; + + auto uuid = Aws::Crt::UUID().ToString(); + connection->Connect(uuid.c_str(), true, 30, 15000, 5000); + + std::unique_lock waitLock(lock); + signal.wait(waitLock, [&connected](){ return connected; }); + } + + done: + + aws_string_destroy(host); + aws_string_destroy(certificatePath); + aws_string_destroy(privateKeyPath); + + return connection; + } + + template class ResultWaiter + { + public: + ResultWaiter() = default; + + void ApplyResult(R &&result) + { + { + std::lock_guard guard(m_lock); + + if (m_result.has_value()) + { + return; + } + + m_result = std::move(result); + } + + m_signal.notify_all(); + } + + const R &GetResult() + { + { + std::unique_lock guard(m_lock); + m_signal.wait(guard, [this]() { return this->m_result.has_value(); }); + } + + return m_result.value(); + } + + private: + std::mutex m_lock; + std::condition_variable m_signal; + + Aws::Crt::Optional m_result; + }; + } // namespace ServiceTesting + } // namespace Iot +} // namespace Aws + +static std::shared_ptr s_createShadowClient5(Aws::Crt::Allocator *allocator) +{ + auto protocolClient = Aws::Iot::ServiceTesting::createProtocolClient5(allocator); + if (!protocolClient) + { + return nullptr; + } + + Aws::Iot::RequestResponse::RequestResponseClientOptions serviceClientOptions; + + serviceClientOptions.WithMaxRequestResponseSubscriptions(4); + serviceClientOptions.WithMaxStreamingSubscriptions(2); + serviceClientOptions.WithOperationTimeoutInSeconds(5); + + return Aws::Iotshadow::NewClientFrom5(*protocolClient, serviceClientOptions, allocator); +} + +static std::shared_ptr s_createShadowClient311(Aws::Crt::Allocator *allocator) +{ + auto protocolClient = Aws::Iot::ServiceTesting::createProtocolClient311(allocator); + if (!protocolClient) + { + return nullptr; + } + + Aws::Iot::RequestResponse::RequestResponseClientOptions serviceClientOptions; + + serviceClientOptions.WithMaxRequestResponseSubscriptions(4); + serviceClientOptions.WithMaxStreamingSubscriptions(2); + serviceClientOptions.WithOperationTimeoutInSeconds(5); + + return Aws::Iotshadow::NewClientFrom311(*protocolClient, serviceClientOptions, allocator); +} + +static int s_ShadowV2ClientCreateDestroy5(Aws::Crt::Allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle handle; + + auto shadowClient = s_createShadowClient5(allocator); + if (!shadowClient) + { + return AWS_OP_SKIP; + } + } + + return AWS_OP_SUCCESS; +} +AWS_TEST_CASE(ShadowV2ClientCreateDestroy5, s_ShadowV2ClientCreateDestroy5) + +static int s_ShadowV2ClientCreateDestroy311(Aws::Crt::Allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle handle; + + auto shadowClient = s_createShadowClient311(allocator); + if (!shadowClient) + { + return AWS_OP_SKIP; + } + } + + return AWS_OP_SUCCESS; +} +AWS_TEST_CASE(ShadowV2ClientCreateDestroy311, s_ShadowV2ClientCreateDestroy311) + +static int s_doGetNonexistentShadowTest(std::shared_ptr shadowClient) +{ + if (!shadowClient) + { + return AWS_OP_SKIP; + } + + Aws::Iot::ServiceTesting::ResultWaiter getResult; + + Aws::Iotshadow::GetNamedShadowRequest request; + request.ShadowName = Aws::Crt::UUID().ToString(); + request.ThingName = Aws::Crt::UUID().ToString(); + + shadowClient->GetNamedShadow(request, [&getResult](Aws::Iotshadow::GetNamedShadowResult &&result){ + getResult.ApplyResult(std::move(result)); + }); + + const auto &result = getResult.GetResult(); + ASSERT_FALSE(result.IsSuccess()); + + const auto &error = result.GetError(); + ASSERT_INT_EQUALS(AWS_ERROR_MQTT_REQUEST_RESPONSE_MODELED_SERVICE_ERROR, error.GetErrorCode()); + + const auto &modeledError = error.GetModeledError(); + + ASSERT_INT_EQUALS(404, modeledError.Code.value()); + + return AWS_OP_SUCCESS; +} + +static int s_ShadowV2ClientGetNonExistentNamedShadow5(Aws::Crt::Allocator *allocator, void *) +{ + Aws::Crt::ApiHandle handle; + return s_doGetNonexistentShadowTest(s_createShadowClient5(allocator)); +} +AWS_TEST_CASE(ShadowV2ClientGetNonExistentNamedShadow5, s_ShadowV2ClientGetNonExistentNamedShadow5) + +static int s_ShadowV2ClientGetNonExistentNamedShadow311(Aws::Crt::Allocator *allocator, void *) +{ + Aws::Crt::ApiHandle handle; + return s_doGetNonexistentShadowTest(s_createShadowClient5(allocator)); +} +AWS_TEST_CASE(ShadowV2ClientGetNonExistentNamedShadow311, s_ShadowV2ClientGetNonExistentNamedShadow311) + +static int s_doCreateDestroyNamedShadowTest(std::shared_ptr shadowClient) { + if (!shadowClient) + { + return AWS_OP_SKIP; + } + + auto shadowName = Aws::Crt::UUID().ToString();; + auto thingName = Aws::Crt::UUID().ToString(); + + // 1. Create the Shadow + Aws::Iot::ServiceTesting::ResultWaiter updateResultWaiter; + + Aws::Crt::JsonObject desired; + desired.WithString("color", "green"); + + Aws::Iotshadow::ShadowState state; + state.Desired = desired; + + Aws::Iotshadow::UpdateNamedShadowRequest updateRequest; + updateRequest.ShadowName = shadowName; + updateRequest.ThingName = thingName; + updateRequest.State = state; + + shadowClient->UpdateNamedShadow(updateRequest, [&updateResultWaiter](Aws::Iotshadow::UpdateNamedShadowResult &&result){ + updateResultWaiter.ApplyResult(std::move(result)); + }); + + const auto &updateResult = updateResultWaiter.GetResult(); + ASSERT_TRUE(updateResult.IsSuccess()); + + const auto &updateResponse = updateResult.GetResponse(); + const auto &updateState = updateResponse.State.value(); + + auto desiredColor = updateState.Desired.value().View().GetString("color"); + ASSERT_TRUE(desiredColor == "green"); + + // 2. Delete the shadow + Aws::Iot::ServiceTesting::ResultWaiter deleteResultWaiter; + + Aws::Iotshadow::DeleteNamedShadowRequest deleteRequest; + deleteRequest.ShadowName = shadowName; + deleteRequest.ThingName = thingName; + + shadowClient->DeleteNamedShadow(deleteRequest, [&deleteResultWaiter](Aws::Iotshadow::DeleteNamedShadowResult &&result){ + deleteResultWaiter.ApplyResult(std::move(result)); + }); + + const auto &deleteResult = deleteResultWaiter.GetResult(); + ASSERT_TRUE(deleteResult.IsSuccess()); + + return AWS_OP_SUCCESS; +} + +static int s_ShadowV2ClientCreateDestroyNamedShadow5(Aws::Crt::Allocator *allocator, void *) +{ + Aws::Crt::ApiHandle handle; + return s_doCreateDestroyNamedShadowTest(s_createShadowClient5(allocator)); +} +AWS_TEST_CASE(ShadowV2ClientCreateDestroyNamedShadow5, s_ShadowV2ClientCreateDestroyNamedShadow5) + +static int s_ShadowV2ClientCreateDestroyNamedShadow311(Aws::Crt::Allocator *allocator, void *) +{ + Aws::Crt::ApiHandle handle; + return s_doCreateDestroyNamedShadowTest(s_createShadowClient5(allocator)); +} +AWS_TEST_CASE(ShadowV2ClientCreateDestroyNamedShadow311, s_ShadowV2ClientCreateDestroyNamedShadow311) + +static std::shared_ptr s_createNamedShadowUpdatedStream(std::shared_ptr shadowClient, Aws::Iot::ServiceTesting::ResultWaiter &eventWaiter, const Aws::Crt::String &thingName, const Aws::Crt::String &shadowName) { + Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest updateStreamRequest; + updateStreamRequest.ThingName = thingName; + updateStreamRequest.ShadowName = shadowName; + + Aws::Iot::ServiceTesting::ResultWaiter subscribeWaiter; + + Aws::Iot::RequestResponse::StreamingOperationOptions updateStreamOptions; + updateStreamOptions.WithStreamHandler([&eventWaiter](Aws::Iotshadow::ShadowUpdatedEvent &&event){ + eventWaiter.ApplyResult(std::move(event)); + }); + updateStreamOptions.WithSubscriptionStatusEventHandler([&subscribeWaiter](Aws::Iot::RequestResponse::SubscriptionStatusEvent &&event) { + if (event.GetType() == Aws::Iot::RequestResponse::SubscriptionStatusEventType::SubscriptionEstablished) { + subscribeWaiter.ApplyResult(std::move(event)); + } + }); + + auto updateStream = shadowClient->CreateNamedShadowUpdatedStream(updateStreamRequest, updateStreamOptions); + updateStream->Open(); + + subscribeWaiter.GetResult(); + + return updateStream; +} + +static std::shared_ptr s_createNamedShadowDeltaUpdatedStream(std::shared_ptr shadowClient, Aws::Iot::ServiceTesting::ResultWaiter &eventWaiter, const Aws::Crt::String &thingName, const Aws::Crt::String &shadowName) { + Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest deltaUpdateStreamRequest; + deltaUpdateStreamRequest.ThingName = thingName; + deltaUpdateStreamRequest.ShadowName = shadowName; + + Aws::Iot::ServiceTesting::ResultWaiter subscribeWaiter; + + Aws::Iot::RequestResponse::StreamingOperationOptions deltaUpdateStreamOptions; + deltaUpdateStreamOptions.WithStreamHandler([&eventWaiter](Aws::Iotshadow::ShadowDeltaUpdatedEvent &&event){ + eventWaiter.ApplyResult(std::move(event)); + }); + deltaUpdateStreamOptions.WithSubscriptionStatusEventHandler([&subscribeWaiter](Aws::Iot::RequestResponse::SubscriptionStatusEvent &&event) { + if (event.GetType() == Aws::Iot::RequestResponse::SubscriptionStatusEventType::SubscriptionEstablished) { + subscribeWaiter.ApplyResult(std::move(event)); + } + }); + + auto deltaUpdateStream = shadowClient->CreateNamedShadowDeltaUpdatedStream(deltaUpdateStreamRequest, deltaUpdateStreamOptions); + deltaUpdateStream->Open(); + + subscribeWaiter.GetResult(); + + return deltaUpdateStream; +} + +static int s_doDeltaUpdateNamedShadowTest(std::shared_ptr shadowClient) { + if (!shadowClient) + { + return AWS_OP_SKIP; + } + + // 1. create the shadow with a specific desired state + auto shadowName = Aws::Crt::UUID().ToString();; + auto thingName = Aws::Crt::UUID().ToString(); + + Aws::Iot::ServiceTesting::ResultWaiter createResultWaiter; + + Aws::Crt::JsonObject createDocument; + createDocument.WithString("color", "green"); + + Aws::Iotshadow::ShadowState createState; + createState.Desired = createDocument; + createState.Reported = createDocument; + + Aws::Iotshadow::UpdateNamedShadowRequest createRequest; + createRequest.ShadowName = shadowName; + createRequest.ThingName = thingName; + createRequest.State = createState; + + shadowClient->UpdateNamedShadow(createRequest, [&createResultWaiter](Aws::Iotshadow::UpdateNamedShadowResult &&result){ + createResultWaiter.ApplyResult(std::move(result)); + }); + + ASSERT_TRUE(createResultWaiter.GetResult().IsSuccess()); + + // 2. Create both kinds of streaming operations + + // Result waiters can work as one-shot notifiers for streams too + Aws::Iot::ServiceTesting::ResultWaiter updateStreamFirstEventWaiter; + auto updateStream = s_createNamedShadowUpdatedStream(shadowClient, updateStreamFirstEventWaiter, thingName, shadowName); + + Aws::Iot::ServiceTesting::ResultWaiter deltaUpdateStreamFirstEventWaiter; + auto updateDeltaStream = s_createNamedShadowDeltaUpdatedStream(shadowClient, deltaUpdateStreamFirstEventWaiter, thingName, shadowName); + + // 3. Update the desired state of the shadow to a different color + Aws::Iot::ServiceTesting::ResultWaiter updateResultWaiter; + + Aws::Crt::JsonObject updateDocument; + updateDocument.WithString("color", "blue"); + + Aws::Iotshadow::ShadowState updateState; + updateState.Desired = updateDocument; + + Aws::Iotshadow::UpdateNamedShadowRequest updateRequest; + updateRequest.ShadowName = shadowName; + updateRequest.ThingName = thingName; + updateRequest.State = updateState; + + shadowClient->UpdateNamedShadow(updateRequest, [&updateResultWaiter](Aws::Iotshadow::UpdateNamedShadowResult &&result){ + updateResultWaiter.ApplyResult(std::move(result)); + }); + + ASSERT_TRUE(updateResultWaiter.GetResult().IsSuccess()); + + // 4. Verify both streaming operations got an appropriate update + const auto &oldDesiredState = updateStreamFirstEventWaiter.GetResult().Previous.value().State.value().Desired.value(); + auto oldColor = oldDesiredState.View().GetString("color"); + ASSERT_TRUE(oldColor == "green"); + + const auto ¤tDesiredState = updateStreamFirstEventWaiter.GetResult().Current.value().State.value().Desired.value(); + auto currentColor = currentDesiredState.View().GetString("color"); + ASSERT_TRUE(currentColor == "blue"); + + const auto &deltaState = deltaUpdateStreamFirstEventWaiter.GetResult().State.value(); + auto deltaColor = deltaState.View().GetString("color"); + ASSERT_TRUE(deltaColor == "blue"); + + // 5. Delete the shadow + Aws::Iot::ServiceTesting::ResultWaiter deleteResultWaiter; + + Aws::Iotshadow::DeleteNamedShadowRequest deleteRequest; + deleteRequest.ShadowName = shadowName; + deleteRequest.ThingName = thingName; + + shadowClient->DeleteNamedShadow(deleteRequest, [&deleteResultWaiter](Aws::Iotshadow::DeleteNamedShadowResult &&result){ + deleteResultWaiter.ApplyResult(std::move(result)); + }); + + const auto &deleteResult = deleteResultWaiter.GetResult(); + ASSERT_TRUE(deleteResult.IsSuccess()); + + return AWS_OP_SUCCESS; +} + +static int s_ShadowV2ClientDeltaUpdateNamedShadow5(Aws::Crt::Allocator *allocator, void *) +{ + Aws::Crt::ApiHandle handle; + return s_doDeltaUpdateNamedShadowTest(s_createShadowClient5(allocator)); +} +AWS_TEST_CASE(ShadowV2ClientDeltaUpdateNamedShadow5, s_ShadowV2ClientDeltaUpdateNamedShadow5) + +static int s_ShadowV2ClientDeltaUpdateNamedShadow311(Aws::Crt::Allocator *allocator, void *) +{ + Aws::Crt::ApiHandle handle; + return s_doDeltaUpdateNamedShadowTest(s_createShadowClient5(allocator)); +} +AWS_TEST_CASE(ShadowV2ClientDeltaUpdateNamedShadow311, s_ShadowV2ClientDeltaUpdateNamedShadow311) \ No newline at end of file From 1548624742546490cbb178dbfb72c689bc4ea633 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Fri, 18 Oct 2024 14:19:00 -0700 Subject: [PATCH 07/33] Fix and refactor tests --- shadow/tests/v2ClientTests.cpp | 516 +++++++++++++++++++-------------- 1 file changed, 301 insertions(+), 215 deletions(-) diff --git a/shadow/tests/v2ClientTests.cpp b/shadow/tests/v2ClientTests.cpp index 1a293eea9..a526c2947 100644 --- a/shadow/tests/v2ClientTests.cpp +++ b/shadow/tests/v2ClientTests.cpp @@ -12,13 +12,13 @@ #include #include -#include #include #include #include #include -#include +#include #include +#include #include #include #include @@ -27,189 +27,184 @@ #include -namespace Aws +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableHost, "AWS_TEST_MQTT5_IOT_CORE_HOST"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableCertificatePath, "AWS_TEST_MQTT5_IOT_CORE_RSA_CERT"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariablePrivateKeyPath, "AWS_TEST_MQTT5_IOT_CORE_RSA_KEY"); + +static std::shared_ptr s_createProtocolClient5(Aws::Crt::Allocator *allocator) { - namespace Iot + std::shared_ptr client = nullptr; + + struct aws_string *host = NULL; + struct aws_string *certificatePath = NULL; + struct aws_string *privateKeyPath = NULL; + + if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) { - namespace ServiceTesting - { + goto done; + } - AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableHost, "AWS_TEST_MQTT5_IOT_CORE_HOST"); - AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableCertificatePath, "AWS_TEST_MQTT5_IOT_CORE_RSA_CERT"); - AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariablePrivateKeyPath, "AWS_TEST_MQTT5_IOT_CORE_RSA_KEY"); + if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || + certificatePath == nullptr) + { + goto done; + } - inline std::shared_ptr createProtocolClient5(Aws::Crt::Allocator *allocator) - { - std::shared_ptr client = nullptr; + if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || + privateKeyPath == nullptr) + { + goto done; + } - struct aws_string *host = NULL; - struct aws_string *certificatePath = NULL; - struct aws_string *privateKeyPath = NULL; + { + std::mutex lock; + std::condition_variable signal; + bool connected = false; - if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) - { - goto done; - } + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( + aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); + Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); - if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || - certificatePath == nullptr) - { - goto done; - } + Aws::Crt::Mqtt5::Mqtt5ClientOptions mqtt5Options(allocator); + mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); + mqtt5Options.WithPort(8883); + mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); - if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || - privateKeyPath == nullptr) + mqtt5Options.WithClientConnectionSuccessCallback( + [&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &) + { { - goto done; + std::lock_guard guard(lock); + connected = true; } + signal.notify_all(); + }); - { - std::mutex lock; - std::condition_variable signal; - bool connected = false; - - Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( - aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); - Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); - - Aws::Crt::Mqtt5::Mqtt5ClientOptions mqtt5Options(allocator); - mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); - mqtt5Options.WithPort(8883); - mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); - - mqtt5Options.WithClientConnectionSuccessCallback([&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &){ - { - std::lock_guard guard(lock); - connected = true; - } - signal.notify_all(); - }); - - client = Aws::Crt::Mqtt5::Mqtt5Client::NewMqtt5Client(mqtt5Options, allocator); - client->Start(); - - std::unique_lock waitLock(lock); - signal.wait(waitLock, [&connected](){ return connected; }); - } + client = Aws::Crt::Mqtt5::Mqtt5Client::NewMqtt5Client(mqtt5Options, allocator); + client->Start(); - done: + std::unique_lock waitLock(lock); + signal.wait(waitLock, [&connected]() { return connected; }); + } - aws_string_destroy(host); - aws_string_destroy(certificatePath); - aws_string_destroy(privateKeyPath); +done: - return client; - } + aws_string_destroy(host); + aws_string_destroy(certificatePath); + aws_string_destroy(privateKeyPath); - inline std::shared_ptr createProtocolClient311( - Aws::Crt::Allocator *allocator) - { - std::shared_ptr connection = nullptr; + return client; +} - struct aws_string *host = NULL; - struct aws_string *certificatePath = NULL; - struct aws_string *privateKeyPath = NULL; +static std::shared_ptr s_createProtocolClient311(Aws::Crt::Allocator *allocator) +{ + std::shared_ptr connection = nullptr; - if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) - { - goto done; - } + struct aws_string *host = NULL; + struct aws_string *certificatePath = NULL; + struct aws_string *privateKeyPath = NULL; - if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || - certificatePath == nullptr) - { - goto done; - } + if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) + { + goto done; + } - if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || - privateKeyPath == nullptr) - { - goto done; - } + if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || + certificatePath == nullptr) + { + goto done; + } - { - std::mutex lock; - std::condition_variable signal; - bool connected = false; + if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || + privateKeyPath == nullptr) + { + goto done; + } - Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( - aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); - Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); + { + std::mutex lock; + std::condition_variable signal; + bool connected = false; - Aws::Crt::Io::SocketOptions socketOptions; - socketOptions.SetConnectTimeoutMs(3000); + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( + aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); + Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); - Aws::Crt::Mqtt::MqttClient client; - connection = client.NewConnection(aws_string_c_str(host), 8883, socketOptions, tlsContext, false); + Aws::Crt::Io::SocketOptions socketOptions; + socketOptions.SetConnectTimeoutMs(3000); - connection->OnConnectionSuccess = [&connected, &lock, &signal](Aws::Crt::Mqtt::MqttConnection &connection, Aws::Crt::Mqtt::OnConnectionSuccessData *callbackData) { - { - std::lock_guard guard(lock); - connected = true; - } - signal.notify_all(); - }; + Aws::Crt::Mqtt::MqttClient client; + connection = client.NewConnection(aws_string_c_str(host), 8883, socketOptions, tlsContext, false); - auto uuid = Aws::Crt::UUID().ToString(); - connection->Connect(uuid.c_str(), true, 30, 15000, 5000); + connection->OnConnectionSuccess = + [&connected, &lock, &signal]( + Aws::Crt::Mqtt::MqttConnection &connection, Aws::Crt::Mqtt::OnConnectionSuccessData *callbackData) + { + { + std::lock_guard guard(lock); + connected = true; + } + signal.notify_all(); + }; - std::unique_lock waitLock(lock); - signal.wait(waitLock, [&connected](){ return connected; }); - } + auto uuid = Aws::Crt::UUID().ToString(); + connection->Connect(uuid.c_str(), true, 30, 15000, 5000); - done: + std::unique_lock waitLock(lock); + signal.wait(waitLock, [&connected]() { return connected; }); + } - aws_string_destroy(host); - aws_string_destroy(certificatePath); - aws_string_destroy(privateKeyPath); +done: - return connection; - } + aws_string_destroy(host); + aws_string_destroy(certificatePath); + aws_string_destroy(privateKeyPath); - template class ResultWaiter - { - public: - ResultWaiter() = default; + return connection; +} - void ApplyResult(R &&result) - { - { - std::lock_guard guard(m_lock); +template class ResultWaiter +{ + public: + ResultWaiter() = default; + + void ApplyResult(R &&result) + { + { + std::lock_guard guard(m_lock); - if (m_result.has_value()) - { - return; - } + if (m_result.has_value()) + { + return; + } - m_result = std::move(result); - } + m_result = std::move(result); + } - m_signal.notify_all(); - } + m_signal.notify_all(); + } - const R &GetResult() - { - { - std::unique_lock guard(m_lock); - m_signal.wait(guard, [this]() { return this->m_result.has_value(); }); - } + const R &GetResult() + { + { + std::unique_lock guard(m_lock); + m_signal.wait(guard, [this]() { return this->m_result.has_value(); }); + } - return m_result.value(); - } + return m_result.value(); + } - private: - std::mutex m_lock; - std::condition_variable m_signal; + private: + std::mutex m_lock; + std::condition_variable m_signal; - Aws::Crt::Optional m_result; - }; - } // namespace ServiceTesting - } // namespace Iot -} // namespace Aws + Aws::Crt::Optional m_result; +}; -static std::shared_ptr s_createShadowClient5(Aws::Crt::Allocator *allocator) +static std::shared_ptr s_createShadowClient5( + std::shared_ptr protocolClient, + Aws::Crt::Allocator *allocator) { - auto protocolClient = Aws::Iot::ServiceTesting::createProtocolClient5(allocator); if (!protocolClient) { return nullptr; @@ -224,9 +219,10 @@ static std::shared_ptr s_createShadowClient5(Aws::Crt return Aws::Iotshadow::NewClientFrom5(*protocolClient, serviceClientOptions, allocator); } -static std::shared_ptr s_createShadowClient311(Aws::Crt::Allocator *allocator) +static std::shared_ptr s_createShadowClient311( + std::shared_ptr protocolClient, + Aws::Crt::Allocator *allocator) { - auto protocolClient = Aws::Iot::ServiceTesting::createProtocolClient311(allocator); if (!protocolClient) { return nullptr; @@ -246,7 +242,8 @@ static int s_ShadowV2ClientCreateDestroy5(Aws::Crt::Allocator *allocator, void * { Aws::Crt::ApiHandle handle; - auto shadowClient = s_createShadowClient5(allocator); + auto protocolClient = s_createProtocolClient5(allocator); + auto shadowClient = s_createShadowClient5(protocolClient, allocator); if (!shadowClient) { return AWS_OP_SKIP; @@ -262,7 +259,8 @@ static int s_ShadowV2ClientCreateDestroy311(Aws::Crt::Allocator *allocator, void { Aws::Crt::ApiHandle handle; - auto shadowClient = s_createShadowClient311(allocator); + auto protocolClient = s_createProtocolClient311(allocator); + auto shadowClient = s_createShadowClient311(protocolClient, allocator); if (!shadowClient) { return AWS_OP_SKIP; @@ -280,15 +278,15 @@ static int s_doGetNonexistentShadowTest(std::shared_ptr getResult; + ResultWaiter getResult; Aws::Iotshadow::GetNamedShadowRequest request; request.ShadowName = Aws::Crt::UUID().ToString(); request.ThingName = Aws::Crt::UUID().ToString(); - shadowClient->GetNamedShadow(request, [&getResult](Aws::Iotshadow::GetNamedShadowResult &&result){ - getResult.ApplyResult(std::move(result)); - }); + shadowClient->GetNamedShadow( + request, + [&getResult](Aws::Iotshadow::GetNamedShadowResult &&result) { getResult.ApplyResult(std::move(result)); }); const auto &result = getResult.GetResult(); ASSERT_FALSE(result.IsSuccess()); @@ -306,28 +304,50 @@ static int s_doGetNonexistentShadowTest(std::shared_ptr shadowClient) { +static void s_deleteNamedShadow( + std::shared_ptr shadowClient, + const Aws::Crt::String &thingName, + const Aws::Crt::String &shadowName) +{ + ResultWaiter deleteResultWaiter; + + Aws::Iotshadow::DeleteNamedShadowRequest deleteRequest; + deleteRequest.ShadowName = shadowName; + deleteRequest.ThingName = thingName; + + shadowClient->DeleteNamedShadow( + deleteRequest, + [&deleteResultWaiter](Aws::Iotshadow::DeleteNamedShadowResult &&result) + { deleteResultWaiter.ApplyResult(std::move(result)); }); + + deleteResultWaiter.GetResult(); +} + +static int s_doCreateDestroyNamedShadowTest( + std::shared_ptr shadowClient, + const Aws::Crt::String &thingName, + const Aws::Crt::String &shadowName) +{ if (!shadowClient) { return AWS_OP_SKIP; } - auto shadowName = Aws::Crt::UUID().ToString();; - auto thingName = Aws::Crt::UUID().ToString(); - // 1. Create the Shadow - Aws::Iot::ServiceTesting::ResultWaiter updateResultWaiter; + ResultWaiter updateResultWaiter; Aws::Crt::JsonObject desired; desired.WithString("color", "green"); @@ -340,9 +360,10 @@ static int s_doCreateDestroyNamedShadowTest(std::shared_ptrUpdateNamedShadow(updateRequest, [&updateResultWaiter](Aws::Iotshadow::UpdateNamedShadowResult &&result){ - updateResultWaiter.ApplyResult(std::move(result)); - }); + shadowClient->UpdateNamedShadow( + updateRequest, + [&updateResultWaiter](Aws::Iotshadow::UpdateNamedShadowResult &&result) + { updateResultWaiter.ApplyResult(std::move(result)); }); const auto &updateResult = updateResultWaiter.GetResult(); ASSERT_TRUE(updateResult.IsSuccess()); @@ -354,15 +375,16 @@ static int s_doCreateDestroyNamedShadowTest(std::shared_ptr deleteResultWaiter; + ResultWaiter deleteResultWaiter; Aws::Iotshadow::DeleteNamedShadowRequest deleteRequest; deleteRequest.ShadowName = shadowName; deleteRequest.ThingName = thingName; - shadowClient->DeleteNamedShadow(deleteRequest, [&deleteResultWaiter](Aws::Iotshadow::DeleteNamedShadowResult &&result){ - deleteResultWaiter.ApplyResult(std::move(result)); - }); + shadowClient->DeleteNamedShadow( + deleteRequest, + [&deleteResultWaiter](Aws::Iotshadow::DeleteNamedShadowResult &&result) + { deleteResultWaiter.ApplyResult(std::move(result)); }); const auto &deleteResult = deleteResultWaiter.GetResult(); ASSERT_TRUE(deleteResult.IsSuccess()); @@ -373,33 +395,60 @@ static int s_doCreateDestroyNamedShadowTest(std::shared_ptr s_createNamedShadowUpdatedStream(std::shared_ptr shadowClient, Aws::Iot::ServiceTesting::ResultWaiter &eventWaiter, const Aws::Crt::String &thingName, const Aws::Crt::String &shadowName) { +static std::shared_ptr s_createNamedShadowUpdatedStream( + std::shared_ptr shadowClient, + ResultWaiter &eventWaiter, + const Aws::Crt::String &thingName, + const Aws::Crt::String &shadowName) +{ Aws::Iotshadow::NamedShadowUpdatedSubscriptionRequest updateStreamRequest; updateStreamRequest.ThingName = thingName; updateStreamRequest.ShadowName = shadowName; - Aws::Iot::ServiceTesting::ResultWaiter subscribeWaiter; + ResultWaiter subscribeWaiter; Aws::Iot::RequestResponse::StreamingOperationOptions updateStreamOptions; - updateStreamOptions.WithStreamHandler([&eventWaiter](Aws::Iotshadow::ShadowUpdatedEvent &&event){ - eventWaiter.ApplyResult(std::move(event)); - }); - updateStreamOptions.WithSubscriptionStatusEventHandler([&subscribeWaiter](Aws::Iot::RequestResponse::SubscriptionStatusEvent &&event) { - if (event.GetType() == Aws::Iot::RequestResponse::SubscriptionStatusEventType::SubscriptionEstablished) { - subscribeWaiter.ApplyResult(std::move(event)); - } - }); + updateStreamOptions.WithStreamHandler([&eventWaiter](Aws::Iotshadow::ShadowUpdatedEvent &&event) + { eventWaiter.ApplyResult(std::move(event)); }); + updateStreamOptions.WithSubscriptionStatusEventHandler( + [&subscribeWaiter](Aws::Iot::RequestResponse::SubscriptionStatusEvent &&event) + { + if (event.GetType() == Aws::Iot::RequestResponse::SubscriptionStatusEventType::SubscriptionEstablished) + { + subscribeWaiter.ApplyResult(std::move(event)); + } + }); auto updateStream = shadowClient->CreateNamedShadowUpdatedStream(updateStreamRequest, updateStreamOptions); updateStream->Open(); @@ -409,24 +458,33 @@ static std::shared_ptr s_createN return updateStream; } -static std::shared_ptr s_createNamedShadowDeltaUpdatedStream(std::shared_ptr shadowClient, Aws::Iot::ServiceTesting::ResultWaiter &eventWaiter, const Aws::Crt::String &thingName, const Aws::Crt::String &shadowName) { +static std::shared_ptr s_createNamedShadowDeltaUpdatedStream( + std::shared_ptr shadowClient, + ResultWaiter &eventWaiter, + const Aws::Crt::String &thingName, + const Aws::Crt::String &shadowName) +{ Aws::Iotshadow::NamedShadowDeltaUpdatedSubscriptionRequest deltaUpdateStreamRequest; deltaUpdateStreamRequest.ThingName = thingName; deltaUpdateStreamRequest.ShadowName = shadowName; - Aws::Iot::ServiceTesting::ResultWaiter subscribeWaiter; + ResultWaiter subscribeWaiter; - Aws::Iot::RequestResponse::StreamingOperationOptions deltaUpdateStreamOptions; - deltaUpdateStreamOptions.WithStreamHandler([&eventWaiter](Aws::Iotshadow::ShadowDeltaUpdatedEvent &&event){ - eventWaiter.ApplyResult(std::move(event)); - }); - deltaUpdateStreamOptions.WithSubscriptionStatusEventHandler([&subscribeWaiter](Aws::Iot::RequestResponse::SubscriptionStatusEvent &&event) { - if (event.GetType() == Aws::Iot::RequestResponse::SubscriptionStatusEventType::SubscriptionEstablished) { - subscribeWaiter.ApplyResult(std::move(event)); - } - }); + Aws::Iot::RequestResponse::StreamingOperationOptions + deltaUpdateStreamOptions; + deltaUpdateStreamOptions.WithStreamHandler([&eventWaiter](Aws::Iotshadow::ShadowDeltaUpdatedEvent &&event) + { eventWaiter.ApplyResult(std::move(event)); }); + deltaUpdateStreamOptions.WithSubscriptionStatusEventHandler( + [&subscribeWaiter](Aws::Iot::RequestResponse::SubscriptionStatusEvent &&event) + { + if (event.GetType() == Aws::Iot::RequestResponse::SubscriptionStatusEventType::SubscriptionEstablished) + { + subscribeWaiter.ApplyResult(std::move(event)); + } + }); - auto deltaUpdateStream = shadowClient->CreateNamedShadowDeltaUpdatedStream(deltaUpdateStreamRequest, deltaUpdateStreamOptions); + auto deltaUpdateStream = + shadowClient->CreateNamedShadowDeltaUpdatedStream(deltaUpdateStreamRequest, deltaUpdateStreamOptions); deltaUpdateStream->Open(); subscribeWaiter.GetResult(); @@ -434,17 +492,18 @@ static std::shared_ptr s_createN return deltaUpdateStream; } -static int s_doDeltaUpdateNamedShadowTest(std::shared_ptr shadowClient) { +static int s_doDeltaUpdateNamedShadowTest( + std::shared_ptr shadowClient, + const Aws::Crt::String &thingName, + const Aws::Crt::String &shadowName) +{ if (!shadowClient) { return AWS_OP_SKIP; } // 1. create the shadow with a specific desired state - auto shadowName = Aws::Crt::UUID().ToString();; - auto thingName = Aws::Crt::UUID().ToString(); - - Aws::Iot::ServiceTesting::ResultWaiter createResultWaiter; + ResultWaiter createResultWaiter; Aws::Crt::JsonObject createDocument; createDocument.WithString("color", "green"); @@ -458,23 +517,26 @@ static int s_doDeltaUpdateNamedShadowTest(std::shared_ptrUpdateNamedShadow(createRequest, [&createResultWaiter](Aws::Iotshadow::UpdateNamedShadowResult &&result){ - createResultWaiter.ApplyResult(std::move(result)); - }); + shadowClient->UpdateNamedShadow( + createRequest, + [&createResultWaiter](Aws::Iotshadow::UpdateNamedShadowResult &&result) + { createResultWaiter.ApplyResult(std::move(result)); }); ASSERT_TRUE(createResultWaiter.GetResult().IsSuccess()); // 2. Create both kinds of streaming operations // Result waiters can work as one-shot notifiers for streams too - Aws::Iot::ServiceTesting::ResultWaiter updateStreamFirstEventWaiter; - auto updateStream = s_createNamedShadowUpdatedStream(shadowClient, updateStreamFirstEventWaiter, thingName, shadowName); + ResultWaiter updateStreamFirstEventWaiter; + auto updateStream = + s_createNamedShadowUpdatedStream(shadowClient, updateStreamFirstEventWaiter, thingName, shadowName); - Aws::Iot::ServiceTesting::ResultWaiter deltaUpdateStreamFirstEventWaiter; - auto updateDeltaStream = s_createNamedShadowDeltaUpdatedStream(shadowClient, deltaUpdateStreamFirstEventWaiter, thingName, shadowName); + ResultWaiter deltaUpdateStreamFirstEventWaiter; + auto updateDeltaStream = + s_createNamedShadowDeltaUpdatedStream(shadowClient, deltaUpdateStreamFirstEventWaiter, thingName, shadowName); // 3. Update the desired state of the shadow to a different color - Aws::Iot::ServiceTesting::ResultWaiter updateResultWaiter; + ResultWaiter updateResultWaiter; Aws::Crt::JsonObject updateDocument; updateDocument.WithString("color", "blue"); @@ -487,18 +549,21 @@ static int s_doDeltaUpdateNamedShadowTest(std::shared_ptrUpdateNamedShadow(updateRequest, [&updateResultWaiter](Aws::Iotshadow::UpdateNamedShadowResult &&result){ - updateResultWaiter.ApplyResult(std::move(result)); - }); + shadowClient->UpdateNamedShadow( + updateRequest, + [&updateResultWaiter](Aws::Iotshadow::UpdateNamedShadowResult &&result) + { updateResultWaiter.ApplyResult(std::move(result)); }); ASSERT_TRUE(updateResultWaiter.GetResult().IsSuccess()); // 4. Verify both streaming operations got an appropriate update - const auto &oldDesiredState = updateStreamFirstEventWaiter.GetResult().Previous.value().State.value().Desired.value(); + const auto &oldDesiredState = + updateStreamFirstEventWaiter.GetResult().Previous.value().State.value().Desired.value(); auto oldColor = oldDesiredState.View().GetString("color"); ASSERT_TRUE(oldColor == "green"); - const auto ¤tDesiredState = updateStreamFirstEventWaiter.GetResult().Current.value().State.value().Desired.value(); + const auto ¤tDesiredState = + updateStreamFirstEventWaiter.GetResult().Current.value().State.value().Desired.value(); auto currentColor = currentDesiredState.View().GetString("color"); ASSERT_TRUE(currentColor == "blue"); @@ -507,15 +572,16 @@ static int s_doDeltaUpdateNamedShadowTest(std::shared_ptr deleteResultWaiter; + ResultWaiter deleteResultWaiter; Aws::Iotshadow::DeleteNamedShadowRequest deleteRequest; deleteRequest.ShadowName = shadowName; deleteRequest.ThingName = thingName; - shadowClient->DeleteNamedShadow(deleteRequest, [&deleteResultWaiter](Aws::Iotshadow::DeleteNamedShadowResult &&result){ - deleteResultWaiter.ApplyResult(std::move(result)); - }); + shadowClient->DeleteNamedShadow( + deleteRequest, + [&deleteResultWaiter](Aws::Iotshadow::DeleteNamedShadowResult &&result) + { deleteResultWaiter.ApplyResult(std::move(result)); }); const auto &deleteResult = deleteResultWaiter.GetResult(); ASSERT_TRUE(deleteResult.IsSuccess()); @@ -526,13 +592,33 @@ static int s_doDeltaUpdateNamedShadowTest(std::shared_ptr Date: Mon, 21 Oct 2024 08:20:41 -0700 Subject: [PATCH 08/33] Checkpoint --- identity/CMakeLists.txt | 6 + .../aws/iotidentity/IotIdentityClientV2.h | 15 +- identity/tests/CMakeLists.txt | 26 ++ identity/tests/v2ClientTests.cpp | 261 ++++++++++++++++++ jobs/CMakeLists.txt | 6 + jobs/include/aws/iotjobs/IotJobsClientV2.h | 20 +- jobs/tests/CMakeLists.txt | 26 ++ jobs/tests/v2ClientTests.cpp | 261 ++++++++++++++++++ 8 files changed, 607 insertions(+), 14 deletions(-) create mode 100644 identity/tests/CMakeLists.txt create mode 100644 identity/tests/v2ClientTests.cpp create mode 100644 jobs/tests/CMakeLists.txt create mode 100644 jobs/tests/v2ClientTests.cpp diff --git a/identity/CMakeLists.txt b/identity/CMakeLists.txt index e843c0ff5..8568d46a1 100644 --- a/identity/CMakeLists.txt +++ b/identity/CMakeLists.txt @@ -131,3 +131,9 @@ configure_file("cmake/iotidentity-cpp-config.cmake" install(FILES "${CMAKE_CURRENT_BINARY_DIR}/iotidentity-cpp-config.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/IotIdentity-cpp/cmake/" COMPONENT Development) + +if(NOT CMAKE_CROSSCOMPILING) + if (BUILD_TESTING) + add_subdirectory(tests) + endif() +endif() diff --git a/identity/include/aws/iotidentity/IotIdentityClientV2.h b/identity/include/aws/iotidentity/IotIdentityClientV2.h index 1a75ff97e..6d63c0fe3 100644 --- a/identity/include/aws/iotidentity/IotIdentityClientV2.h +++ b/identity/include/aws/iotidentity/IotIdentityClientV2.h @@ -72,12 +72,15 @@ namespace Aws class RegisterThingResponse; class V2ServiceError; - using CreateCertificateFromCsrResultHandler = std::function> &&)>; - using CreateKeysAndCertificateResultHandler = std::function> &&)>; - using RegisterThingResultHandler = std::function> &&)>; + using CreateCertificateFromCsrResult = + Aws::Iot::RequestResponse::Result>; + using CreateCertificateFromCsrResultHandler = std::function; + using CreateKeysAndCertificateResult = + Aws::Iot::RequestResponse::Result>; + using CreateKeysAndCertificateResultHandler = std::function; + using RegisterThingResult = + Aws::Iot::RequestResponse::Result>; + using RegisterThingResultHandler = std::function; /** * An AWS IoT service that assists with provisioning a device and installing unique client certificates on it diff --git a/identity/tests/CMakeLists.txt b/identity/tests/CMakeLists.txt new file mode 100644 index 000000000..dfbcd6a9a --- /dev/null +++ b/identity/tests/CMakeLists.txt @@ -0,0 +1,26 @@ +include(AwsTestHarness) +enable_testing() +include(CTest) + +file(GLOB TEST_SRC "*.cpp") +file(GLOB TEST_HDRS "*.h") +file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) + +set(TEST_BINARY_NAME ${PROJECT_NAME}-tests) + +add_net_test_case(IdentityV2ClientCreateDestroy5) +add_net_test_case(IdentityV2ClientCreateDestroy311) + +generate_cpp_test_driver(${TEST_BINARY_NAME}) + +aws_add_sanitizers(${TEST_BINARY_NAME}) + + # set extra warning flags +if(AWS_WARNINGS_ARE_ERRORS) + if(MSVC) + target_compile_options(${TEST_BINARY_NAME} PRIVATE /W4 /WX /wd4068) + else() + target_compile_options(${TEST_BINARY_NAME} PRIVATE -Wall -Wno-long-long -Werror) + endif() +endif() + diff --git a/identity/tests/v2ClientTests.cpp b/identity/tests/v2ClientTests.cpp new file mode 100644 index 000000000..c1b52f0d1 --- /dev/null +++ b/identity/tests/v2ClientTests.cpp @@ -0,0 +1,261 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableHost, "AWS_TEST_MQTT5_IOT_CORE_HOST"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableCertificatePath, "AWS_TEST_MQTT5_IOT_CORE_RSA_CERT"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariablePrivateKeyPath, "AWS_TEST_MQTT5_IOT_CORE_RSA_KEY"); + +static std::shared_ptr s_createProtocolClient5(Aws::Crt::Allocator *allocator) +{ + std::shared_ptr client = nullptr; + + struct aws_string *host = NULL; + struct aws_string *certificatePath = NULL; + struct aws_string *privateKeyPath = NULL; + + if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || + certificatePath == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || + privateKeyPath == nullptr) + { + goto done; + } + + { + std::mutex lock; + std::condition_variable signal; + bool connected = false; + + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( + aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); + Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); + + Aws::Crt::Mqtt5::Mqtt5ClientOptions mqtt5Options(allocator); + mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); + mqtt5Options.WithPort(8883); + mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); + + mqtt5Options.WithClientConnectionSuccessCallback( + [&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &) + { + { + std::lock_guard guard(lock); + connected = true; + } + signal.notify_all(); + }); + + client = Aws::Crt::Mqtt5::Mqtt5Client::NewMqtt5Client(mqtt5Options, allocator); + client->Start(); + + std::unique_lock waitLock(lock); + signal.wait(waitLock, [&connected]() { return connected; }); + } + +done: + + aws_string_destroy(host); + aws_string_destroy(certificatePath); + aws_string_destroy(privateKeyPath); + + return client; +} + +static std::shared_ptr s_createProtocolClient311(Aws::Crt::Allocator *allocator) +{ + std::shared_ptr connection = nullptr; + + struct aws_string *host = NULL; + struct aws_string *certificatePath = NULL; + struct aws_string *privateKeyPath = NULL; + + if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || + certificatePath == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || + privateKeyPath == nullptr) + { + goto done; + } + + { + std::mutex lock; + std::condition_variable signal; + bool connected = false; + + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( + aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); + Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); + + Aws::Crt::Io::SocketOptions socketOptions; + socketOptions.SetConnectTimeoutMs(3000); + + Aws::Crt::Mqtt::MqttClient client; + connection = client.NewConnection(aws_string_c_str(host), 8883, socketOptions, tlsContext, false); + + connection->OnConnectionSuccess = + [&connected, &lock, &signal]( + Aws::Crt::Mqtt::MqttConnection &connection, Aws::Crt::Mqtt::OnConnectionSuccessData *callbackData) + { + { + std::lock_guard guard(lock); + connected = true; + } + signal.notify_all(); + }; + + auto uuid = Aws::Crt::UUID().ToString(); + connection->Connect(uuid.c_str(), true, 30, 15000, 5000); + + std::unique_lock waitLock(lock); + signal.wait(waitLock, [&connected]() { return connected; }); + } + +done: + + aws_string_destroy(host); + aws_string_destroy(certificatePath); + aws_string_destroy(privateKeyPath); + + return connection; +} + +template class ResultWaiter +{ + public: + ResultWaiter() = default; + + void ApplyResult(R &&result) + { + { + std::lock_guard guard(m_lock); + + if (m_result.has_value()) + { + return; + } + + m_result = std::move(result); + } + + m_signal.notify_all(); + } + + const R &GetResult() + { + { + std::unique_lock guard(m_lock); + m_signal.wait(guard, [this]() { return this->m_result.has_value(); }); + } + + return m_result.value(); + } + + private: + std::mutex m_lock; + std::condition_variable m_signal; + + Aws::Crt::Optional m_result; +}; + +static std::shared_ptr s_createIdentityClient5( + std::shared_ptr protocolClient, + Aws::Crt::Allocator *allocator) +{ + if (!protocolClient) + { + return nullptr; + } + + Aws::Iot::RequestResponse::RequestResponseClientOptions serviceClientOptions; + + serviceClientOptions.WithMaxRequestResponseSubscriptions(4); + serviceClientOptions.WithMaxStreamingSubscriptions(2); + serviceClientOptions.WithOperationTimeoutInSeconds(5); + + return Aws::Iotidentity::NewClientFrom5(*protocolClient, serviceClientOptions, allocator); +} + +static std::shared_ptr s_createShadowClient311( + std::shared_ptr protocolClient, + Aws::Crt::Allocator *allocator) +{ + if (!protocolClient) + { + return nullptr; + } + + Aws::Iot::RequestResponse::RequestResponseClientOptions serviceClientOptions; + + serviceClientOptions.WithMaxRequestResponseSubscriptions(4); + serviceClientOptions.WithMaxStreamingSubscriptions(2); + serviceClientOptions.WithOperationTimeoutInSeconds(5); + + return Aws::Iotidentity::NewClientFrom311(*protocolClient, serviceClientOptions, allocator); +} + +static int s_IdentityV2ClientCreateDestroy5(Aws::Crt::Allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle handle; + + auto protocolClient = s_createProtocolClient5(allocator); + auto shadowClient = s_createIdentityClient5(protocolClient, allocator); + if (!shadowClient) + { + return AWS_OP_SKIP; + } + } + + return AWS_OP_SUCCESS; +} +AWS_TEST_CASE(IdentityV2ClientCreateDestroy5, s_IdentityV2ClientCreateDestroy5) + +static int s_IdentityV2ClientCreateDestroy311(Aws::Crt::Allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle handle; + + auto protocolClient = s_createProtocolClient311(allocator); + auto shadowClient = s_createShadowClient311(protocolClient, allocator); + if (!shadowClient) + { + return AWS_OP_SKIP; + } + } + + return AWS_OP_SUCCESS; +} +AWS_TEST_CASE(IdentityV2ClientCreateDestroy311, s_IdentityV2ClientCreateDestroy311) diff --git a/jobs/CMakeLists.txt b/jobs/CMakeLists.txt index b1d054924..1ef33a18f 100644 --- a/jobs/CMakeLists.txt +++ b/jobs/CMakeLists.txt @@ -131,3 +131,9 @@ configure_file("cmake/iotjobs-cpp-config.cmake" install(FILES "${CMAKE_CURRENT_BINARY_DIR}/iotjobs-cpp-config.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/IotJobs-cpp/cmake/" COMPONENT Development) + +if(NOT CMAKE_CROSSCOMPILING) + if (BUILD_TESTING) + add_subdirectory(tests) + endif() +endif() diff --git a/jobs/include/aws/iotjobs/IotJobsClientV2.h b/jobs/include/aws/iotjobs/IotJobsClientV2.h index ab9944810..25d48b2f9 100644 --- a/jobs/include/aws/iotjobs/IotJobsClientV2.h +++ b/jobs/include/aws/iotjobs/IotJobsClientV2.h @@ -78,14 +78,18 @@ namespace Aws class UpdateJobExecutionResponse; class V2ServiceError; - using DescribeJobExecutionResultHandler = std::function> &&)>; - using GetPendingJobExecutionsResultHandler = std::function> &&)>; - using StartNextPendingJobExecutionResultHandler = std::function> &&)>; - using UpdateJobExecutionResultHandler = std::function> &&)>; + using DescribeJobExecutionResult = + Aws::Iot::RequestResponse::Result>; + using DescribeJobExecutionResultHandler = std::function; + using GetPendingJobExecutionsResult = + Aws::Iot::RequestResponse::Result>; + using GetPendingJobExecutionsResultHandler = std::function; + using StartNextPendingJobExecutionResult = + Aws::Iot::RequestResponse::Result>; + using StartNextPendingJobExecutionResultHandler = std::function; + using UpdateJobExecutionResult = + Aws::Iot::RequestResponse::Result>; + using UpdateJobExecutionResultHandler = std::function; /** * The AWS IoT jobs service can be used to define a set of remote operations that are sent to and executed on diff --git a/jobs/tests/CMakeLists.txt b/jobs/tests/CMakeLists.txt new file mode 100644 index 000000000..e1013f3e9 --- /dev/null +++ b/jobs/tests/CMakeLists.txt @@ -0,0 +1,26 @@ +include(AwsTestHarness) +enable_testing() +include(CTest) + +file(GLOB TEST_SRC "*.cpp") +file(GLOB TEST_HDRS "*.h") +file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) + +set(TEST_BINARY_NAME ${PROJECT_NAME}-tests) + +add_net_test_case(JobsV2ClientCreateDestroy5) +add_net_test_case(JobsV2ClientCreateDestroy311) + +generate_cpp_test_driver(${TEST_BINARY_NAME}) + +aws_add_sanitizers(${TEST_BINARY_NAME}) + + # set extra warning flags +if(AWS_WARNINGS_ARE_ERRORS) + if(MSVC) + target_compile_options(${TEST_BINARY_NAME} PRIVATE /W4 /WX /wd4068) + else() + target_compile_options(${TEST_BINARY_NAME} PRIVATE -Wall -Wno-long-long -Werror) + endif() +endif() + diff --git a/jobs/tests/v2ClientTests.cpp b/jobs/tests/v2ClientTests.cpp new file mode 100644 index 000000000..7906c2e89 --- /dev/null +++ b/jobs/tests/v2ClientTests.cpp @@ -0,0 +1,261 @@ +/** +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +* SPDX-License-Identifier: Apache-2.0. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableHost, "AWS_TEST_MQTT5_IOT_CORE_HOST"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableCertificatePath, "AWS_TEST_MQTT5_IOT_CORE_RSA_CERT"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariablePrivateKeyPath, "AWS_TEST_MQTT5_IOT_CORE_RSA_KEY"); + +static std::shared_ptr s_createProtocolClient5(Aws::Crt::Allocator *allocator) +{ + std::shared_ptr client = nullptr; + + struct aws_string *host = NULL; + struct aws_string *certificatePath = NULL; + struct aws_string *privateKeyPath = NULL; + + if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || + certificatePath == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || + privateKeyPath == nullptr) + { + goto done; + } + + { + std::mutex lock; + std::condition_variable signal; + bool connected = false; + + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( + aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); + Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); + + Aws::Crt::Mqtt5::Mqtt5ClientOptions mqtt5Options(allocator); + mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); + mqtt5Options.WithPort(8883); + mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); + + mqtt5Options.WithClientConnectionSuccessCallback( + [&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &) + { + { + std::lock_guard guard(lock); + connected = true; + } + signal.notify_all(); + }); + + client = Aws::Crt::Mqtt5::Mqtt5Client::NewMqtt5Client(mqtt5Options, allocator); + client->Start(); + + std::unique_lock waitLock(lock); + signal.wait(waitLock, [&connected]() { return connected; }); + } + +done: + + aws_string_destroy(host); + aws_string_destroy(certificatePath); + aws_string_destroy(privateKeyPath); + + return client; +} + +static std::shared_ptr s_createProtocolClient311(Aws::Crt::Allocator *allocator) +{ + std::shared_ptr connection = nullptr; + + struct aws_string *host = NULL; + struct aws_string *certificatePath = NULL; + struct aws_string *privateKeyPath = NULL; + + if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || + certificatePath == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || + privateKeyPath == nullptr) + { + goto done; + } + + { + std::mutex lock; + std::condition_variable signal; + bool connected = false; + + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( + aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); + Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); + + Aws::Crt::Io::SocketOptions socketOptions; + socketOptions.SetConnectTimeoutMs(3000); + + Aws::Crt::Mqtt::MqttClient client; + connection = client.NewConnection(aws_string_c_str(host), 8883, socketOptions, tlsContext, false); + + connection->OnConnectionSuccess = + [&connected, &lock, &signal]( + Aws::Crt::Mqtt::MqttConnection &connection, Aws::Crt::Mqtt::OnConnectionSuccessData *callbackData) + { + { + std::lock_guard guard(lock); + connected = true; + } + signal.notify_all(); + }; + + auto uuid = Aws::Crt::UUID().ToString(); + connection->Connect(uuid.c_str(), true, 30, 15000, 5000); + + std::unique_lock waitLock(lock); + signal.wait(waitLock, [&connected]() { return connected; }); + } + +done: + + aws_string_destroy(host); + aws_string_destroy(certificatePath); + aws_string_destroy(privateKeyPath); + + return connection; +} + +template class ResultWaiter +{ + public: + ResultWaiter() = default; + + void ApplyResult(R &&result) + { + { + std::lock_guard guard(m_lock); + + if (m_result.has_value()) + { + return; + } + + m_result = std::move(result); + } + + m_signal.notify_all(); + } + + const R &GetResult() + { + { + std::unique_lock guard(m_lock); + m_signal.wait(guard, [this]() { return this->m_result.has_value(); }); + } + + return m_result.value(); + } + + private: + std::mutex m_lock; + std::condition_variable m_signal; + + Aws::Crt::Optional m_result; +}; + +static std::shared_ptr s_createIdentityClient5( + std::shared_ptr protocolClient, + Aws::Crt::Allocator *allocator) +{ + if (!protocolClient) + { + return nullptr; + } + + Aws::Iot::RequestResponse::RequestResponseClientOptions serviceClientOptions; + + serviceClientOptions.WithMaxRequestResponseSubscriptions(4); + serviceClientOptions.WithMaxStreamingSubscriptions(2); + serviceClientOptions.WithOperationTimeoutInSeconds(5); + + return Aws::Iotjobs::NewClientFrom5(*protocolClient, serviceClientOptions, allocator); +} + +static std::shared_ptr s_createShadowClient311( + std::shared_ptr protocolClient, + Aws::Crt::Allocator *allocator) +{ + if (!protocolClient) + { + return nullptr; + } + + Aws::Iot::RequestResponse::RequestResponseClientOptions serviceClientOptions; + + serviceClientOptions.WithMaxRequestResponseSubscriptions(4); + serviceClientOptions.WithMaxStreamingSubscriptions(2); + serviceClientOptions.WithOperationTimeoutInSeconds(5); + + return Aws::Iotjobs::NewClientFrom311(*protocolClient, serviceClientOptions, allocator); +} + +static int s_JobsV2ClientCreateDestroy5(Aws::Crt::Allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle handle; + + auto protocolClient = s_createProtocolClient5(allocator); + auto shadowClient = s_createIdentityClient5(protocolClient, allocator); + if (!shadowClient) + { + return AWS_OP_SKIP; + } + } + + return AWS_OP_SUCCESS; +} +AWS_TEST_CASE(JobsV2ClientCreateDestroy5, s_JobsV2ClientCreateDestroy5) + +static int s_JobsV2ClientCreateDestroy311(Aws::Crt::Allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle handle; + + auto protocolClient = s_createProtocolClient311(allocator); + auto shadowClient = s_createShadowClient311(protocolClient, allocator); + if (!shadowClient) + { + return AWS_OP_SKIP; + } + } + + return AWS_OP_SUCCESS; +} +AWS_TEST_CASE(JobsV2ClientCreateDestroy311, s_JobsV2ClientCreateDestroy311) From b6276dd8d5c1d56551e3ccdc01c10b353065a05b Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 21 Oct 2024 10:56:07 -0700 Subject: [PATCH 09/33] Regen --- .../aws/iotidentity/IotIdentityClientV2.h | 2 + identity/source/IotIdentityClientV2.cpp | 6 + jobs/include/aws/iotjobs/IotJobsClientV2.h | 3 + jobs/tests/v2ClientTests.cpp | 382 +++++++++--------- .../include/aws/iotshadow/IotShadowClientV2.h | 5 + 5 files changed, 207 insertions(+), 191 deletions(-) diff --git a/identity/include/aws/iotidentity/IotIdentityClientV2.h b/identity/include/aws/iotidentity/IotIdentityClientV2.h index 6d63c0fe3..ca79cf3fd 100644 --- a/identity/include/aws/iotidentity/IotIdentityClientV2.h +++ b/identity/include/aws/iotidentity/IotIdentityClientV2.h @@ -75,9 +75,11 @@ namespace Aws using CreateCertificateFromCsrResult = Aws::Iot::RequestResponse::Result>; using CreateCertificateFromCsrResultHandler = std::function; + using CreateKeysAndCertificateResult = Aws::Iot::RequestResponse::Result>; using CreateKeysAndCertificateResultHandler = std::function; + using RegisterThingResult = Aws::Iot::RequestResponse::Result>; using RegisterThingResultHandler = std::function; diff --git a/identity/source/IotIdentityClientV2.cpp b/identity/source/IotIdentityClientV2.cpp index 726121bbc..b4a8c15f5 100644 --- a/identity/source/IotIdentityClientV2.cpp +++ b/identity/source/IotIdentityClientV2.cpp @@ -146,6 +146,8 @@ namespace Aws struct aws_mqtt_request_operation_response_path responsePaths[2]; responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + AWS_ZERO_STRUCT(responsePaths[0].correlation_token_json_path); + AWS_ZERO_STRUCT(responsePaths[1].correlation_token_json_path); Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -251,6 +253,8 @@ namespace Aws struct aws_mqtt_request_operation_response_path responsePaths[2]; responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + AWS_ZERO_STRUCT(responsePaths[0].correlation_token_json_path); + AWS_ZERO_STRUCT(responsePaths[1].correlation_token_json_path); Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); @@ -356,6 +360,8 @@ namespace Aws struct aws_mqtt_request_operation_response_path responsePaths[2]; responsePaths[0].topic = Aws::Crt::ByteCursorFromString(responsePathTopicAccepted); responsePaths[1].topic = Aws::Crt::ByteCursorFromString(responsePathTopicRejected); + AWS_ZERO_STRUCT(responsePaths[0].correlation_token_json_path); + AWS_ZERO_STRUCT(responsePaths[1].correlation_token_json_path); Aws::Crt::JsonObject jsonObject; request.SerializeToObject(jsonObject); diff --git a/jobs/include/aws/iotjobs/IotJobsClientV2.h b/jobs/include/aws/iotjobs/IotJobsClientV2.h index 25d48b2f9..41a1e591b 100644 --- a/jobs/include/aws/iotjobs/IotJobsClientV2.h +++ b/jobs/include/aws/iotjobs/IotJobsClientV2.h @@ -81,12 +81,15 @@ namespace Aws using DescribeJobExecutionResult = Aws::Iot::RequestResponse::Result>; using DescribeJobExecutionResultHandler = std::function; + using GetPendingJobExecutionsResult = Aws::Iot::RequestResponse::Result>; using GetPendingJobExecutionsResultHandler = std::function; + using StartNextPendingJobExecutionResult = Aws::Iot::RequestResponse::Result>; using StartNextPendingJobExecutionResultHandler = std::function; + using UpdateJobExecutionResult = Aws::Iot::RequestResponse::Result>; using UpdateJobExecutionResultHandler = std::function; diff --git a/jobs/tests/v2ClientTests.cpp b/jobs/tests/v2ClientTests.cpp index 7906c2e89..9a3007529 100644 --- a/jobs/tests/v2ClientTests.cpp +++ b/jobs/tests/v2ClientTests.cpp @@ -1,7 +1,7 @@ /** -* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -* SPDX-License-Identifier: Apache-2.0. -*/ + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ #include #include @@ -22,240 +22,240 @@ AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariablePrivateKeyPath, "AWS_TEST_MQTT5_IO static std::shared_ptr s_createProtocolClient5(Aws::Crt::Allocator *allocator) { - std::shared_ptr client = nullptr; - - struct aws_string *host = NULL; - struct aws_string *certificatePath = NULL; - struct aws_string *privateKeyPath = NULL; - - if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) - { - goto done; - } - - if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || - certificatePath == nullptr) - { - goto done; - } - - if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || - privateKeyPath == nullptr) - { - goto done; - } - - { - std::mutex lock; - std::condition_variable signal; - bool connected = false; - - Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( - aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); - Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); - - Aws::Crt::Mqtt5::Mqtt5ClientOptions mqtt5Options(allocator); - mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); - mqtt5Options.WithPort(8883); - mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); - - mqtt5Options.WithClientConnectionSuccessCallback( - [&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &) - { - { - std::lock_guard guard(lock); - connected = true; - } - signal.notify_all(); - }); - - client = Aws::Crt::Mqtt5::Mqtt5Client::NewMqtt5Client(mqtt5Options, allocator); - client->Start(); - - std::unique_lock waitLock(lock); - signal.wait(waitLock, [&connected]() { return connected; }); - } + std::shared_ptr client = nullptr; + + struct aws_string *host = NULL; + struct aws_string *certificatePath = NULL; + struct aws_string *privateKeyPath = NULL; + + if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || + certificatePath == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || + privateKeyPath == nullptr) + { + goto done; + } + + { + std::mutex lock; + std::condition_variable signal; + bool connected = false; + + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( + aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); + Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); + + Aws::Crt::Mqtt5::Mqtt5ClientOptions mqtt5Options(allocator); + mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); + mqtt5Options.WithPort(8883); + mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); + + mqtt5Options.WithClientConnectionSuccessCallback( + [&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &) + { + { + std::lock_guard guard(lock); + connected = true; + } + signal.notify_all(); + }); + + client = Aws::Crt::Mqtt5::Mqtt5Client::NewMqtt5Client(mqtt5Options, allocator); + client->Start(); + + std::unique_lock waitLock(lock); + signal.wait(waitLock, [&connected]() { return connected; }); + } done: - aws_string_destroy(host); - aws_string_destroy(certificatePath); - aws_string_destroy(privateKeyPath); + aws_string_destroy(host); + aws_string_destroy(certificatePath); + aws_string_destroy(privateKeyPath); - return client; + return client; } static std::shared_ptr s_createProtocolClient311(Aws::Crt::Allocator *allocator) { - std::shared_ptr connection = nullptr; - - struct aws_string *host = NULL; - struct aws_string *certificatePath = NULL; - struct aws_string *privateKeyPath = NULL; - - if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) - { - goto done; - } - - if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || - certificatePath == nullptr) - { - goto done; - } - - if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || - privateKeyPath == nullptr) - { - goto done; - } - - { - std::mutex lock; - std::condition_variable signal; - bool connected = false; - - Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( - aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); - Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); - - Aws::Crt::Io::SocketOptions socketOptions; - socketOptions.SetConnectTimeoutMs(3000); - - Aws::Crt::Mqtt::MqttClient client; - connection = client.NewConnection(aws_string_c_str(host), 8883, socketOptions, tlsContext, false); - - connection->OnConnectionSuccess = - [&connected, &lock, &signal]( - Aws::Crt::Mqtt::MqttConnection &connection, Aws::Crt::Mqtt::OnConnectionSuccessData *callbackData) - { - { - std::lock_guard guard(lock); - connected = true; - } - signal.notify_all(); - }; - - auto uuid = Aws::Crt::UUID().ToString(); - connection->Connect(uuid.c_str(), true, 30, 15000, 5000); - - std::unique_lock waitLock(lock); - signal.wait(waitLock, [&connected]() { return connected; }); - } + std::shared_ptr connection = nullptr; + + struct aws_string *host = NULL; + struct aws_string *certificatePath = NULL; + struct aws_string *privateKeyPath = NULL; + + if (aws_get_environment_value(allocator, s_rrEnvVariableHost, &host) || host == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariableCertificatePath, &certificatePath) || + certificatePath == nullptr) + { + goto done; + } + + if (aws_get_environment_value(allocator, s_rrEnvVariablePrivateKeyPath, &privateKeyPath) || + privateKeyPath == nullptr) + { + goto done; + } + + { + std::mutex lock; + std::condition_variable signal; + bool connected = false; + + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitClientWithMtls( + aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); + Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); + + Aws::Crt::Io::SocketOptions socketOptions; + socketOptions.SetConnectTimeoutMs(3000); + + Aws::Crt::Mqtt::MqttClient client; + connection = client.NewConnection(aws_string_c_str(host), 8883, socketOptions, tlsContext, false); + + connection->OnConnectionSuccess = + [&connected, &lock, &signal]( + Aws::Crt::Mqtt::MqttConnection &connection, Aws::Crt::Mqtt::OnConnectionSuccessData *callbackData) + { + { + std::lock_guard guard(lock); + connected = true; + } + signal.notify_all(); + }; + + auto uuid = Aws::Crt::UUID().ToString(); + connection->Connect(uuid.c_str(), true, 30, 15000, 5000); + + std::unique_lock waitLock(lock); + signal.wait(waitLock, [&connected]() { return connected; }); + } done: - aws_string_destroy(host); - aws_string_destroy(certificatePath); - aws_string_destroy(privateKeyPath); + aws_string_destroy(host); + aws_string_destroy(certificatePath); + aws_string_destroy(privateKeyPath); - return connection; + return connection; } template class ResultWaiter { - public: - ResultWaiter() = default; + public: + ResultWaiter() = default; - void ApplyResult(R &&result) - { - { - std::lock_guard guard(m_lock); + void ApplyResult(R &&result) + { + { + std::lock_guard guard(m_lock); - if (m_result.has_value()) - { - return; - } + if (m_result.has_value()) + { + return; + } - m_result = std::move(result); - } + m_result = std::move(result); + } - m_signal.notify_all(); - } + m_signal.notify_all(); + } - const R &GetResult() - { - { - std::unique_lock guard(m_lock); - m_signal.wait(guard, [this]() { return this->m_result.has_value(); }); - } + const R &GetResult() + { + { + std::unique_lock guard(m_lock); + m_signal.wait(guard, [this]() { return this->m_result.has_value(); }); + } - return m_result.value(); - } + return m_result.value(); + } - private: - std::mutex m_lock; - std::condition_variable m_signal; + private: + std::mutex m_lock; + std::condition_variable m_signal; - Aws::Crt::Optional m_result; + Aws::Crt::Optional m_result; }; static std::shared_ptr s_createIdentityClient5( - std::shared_ptr protocolClient, - Aws::Crt::Allocator *allocator) + std::shared_ptr protocolClient, + Aws::Crt::Allocator *allocator) { - if (!protocolClient) - { - return nullptr; - } + if (!protocolClient) + { + return nullptr; + } - Aws::Iot::RequestResponse::RequestResponseClientOptions serviceClientOptions; + Aws::Iot::RequestResponse::RequestResponseClientOptions serviceClientOptions; - serviceClientOptions.WithMaxRequestResponseSubscriptions(4); - serviceClientOptions.WithMaxStreamingSubscriptions(2); - serviceClientOptions.WithOperationTimeoutInSeconds(5); + serviceClientOptions.WithMaxRequestResponseSubscriptions(4); + serviceClientOptions.WithMaxStreamingSubscriptions(2); + serviceClientOptions.WithOperationTimeoutInSeconds(5); - return Aws::Iotjobs::NewClientFrom5(*protocolClient, serviceClientOptions, allocator); + return Aws::Iotjobs::NewClientFrom5(*protocolClient, serviceClientOptions, allocator); } static std::shared_ptr s_createShadowClient311( - std::shared_ptr protocolClient, - Aws::Crt::Allocator *allocator) + std::shared_ptr protocolClient, + Aws::Crt::Allocator *allocator) { - if (!protocolClient) - { - return nullptr; - } + if (!protocolClient) + { + return nullptr; + } - Aws::Iot::RequestResponse::RequestResponseClientOptions serviceClientOptions; + Aws::Iot::RequestResponse::RequestResponseClientOptions serviceClientOptions; - serviceClientOptions.WithMaxRequestResponseSubscriptions(4); - serviceClientOptions.WithMaxStreamingSubscriptions(2); - serviceClientOptions.WithOperationTimeoutInSeconds(5); + serviceClientOptions.WithMaxRequestResponseSubscriptions(4); + serviceClientOptions.WithMaxStreamingSubscriptions(2); + serviceClientOptions.WithOperationTimeoutInSeconds(5); - return Aws::Iotjobs::NewClientFrom311(*protocolClient, serviceClientOptions, allocator); + return Aws::Iotjobs::NewClientFrom311(*protocolClient, serviceClientOptions, allocator); } static int s_JobsV2ClientCreateDestroy5(Aws::Crt::Allocator *allocator, void *) { - { - Aws::Crt::ApiHandle handle; - - auto protocolClient = s_createProtocolClient5(allocator); - auto shadowClient = s_createIdentityClient5(protocolClient, allocator); - if (!shadowClient) - { - return AWS_OP_SKIP; - } - } - - return AWS_OP_SUCCESS; + { + Aws::Crt::ApiHandle handle; + + auto protocolClient = s_createProtocolClient5(allocator); + auto shadowClient = s_createIdentityClient5(protocolClient, allocator); + if (!shadowClient) + { + return AWS_OP_SKIP; + } + } + + return AWS_OP_SUCCESS; } AWS_TEST_CASE(JobsV2ClientCreateDestroy5, s_JobsV2ClientCreateDestroy5) static int s_JobsV2ClientCreateDestroy311(Aws::Crt::Allocator *allocator, void *) { - { - Aws::Crt::ApiHandle handle; - - auto protocolClient = s_createProtocolClient311(allocator); - auto shadowClient = s_createShadowClient311(protocolClient, allocator); - if (!shadowClient) - { - return AWS_OP_SKIP; - } - } - - return AWS_OP_SUCCESS; + { + Aws::Crt::ApiHandle handle; + + auto protocolClient = s_createProtocolClient311(allocator); + auto shadowClient = s_createShadowClient311(protocolClient, allocator); + if (!shadowClient) + { + return AWS_OP_SKIP; + } + } + + return AWS_OP_SUCCESS; } AWS_TEST_CASE(JobsV2ClientCreateDestroy311, s_JobsV2ClientCreateDestroy311) diff --git a/shadow/include/aws/iotshadow/IotShadowClientV2.h b/shadow/include/aws/iotshadow/IotShadowClientV2.h index b00509b53..285b85759 100644 --- a/shadow/include/aws/iotshadow/IotShadowClientV2.h +++ b/shadow/include/aws/iotshadow/IotShadowClientV2.h @@ -84,17 +84,22 @@ namespace Aws using DeleteNamedShadowResult = Aws::Iot::RequestResponse::Result>; using DeleteNamedShadowResultHandler = std::function; + using DeleteShadowResult = Aws::Iot::RequestResponse::Result>; using DeleteShadowResultHandler = std::function; + using GetNamedShadowResult = Aws::Iot::RequestResponse::Result>; using GetNamedShadowResultHandler = std::function; + using GetShadowResult = Aws::Iot::RequestResponse::Result>; using GetShadowResultHandler = std::function; + using UpdateNamedShadowResult = Aws::Iot::RequestResponse::Result>; using UpdateNamedShadowResultHandler = std::function; + using UpdateShadowResult = Aws::Iot::RequestResponse::Result>; using UpdateShadowResultHandler = std::function; From 7f8dac8bfacc7306ab2b1a4e574a38a6865bd683 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 21 Oct 2024 12:31:17 -0700 Subject: [PATCH 10/33] Identity tests --- identity/source/IotIdentityClientV2.cpp | 3 +- identity/tests/CMakeLists.txt | 4 + identity/tests/v2ClientTests.cpp | 251 +++++++++++++++++++++++- shadow/source/IotShadowClientV2.cpp | 12 +- 4 files changed, 250 insertions(+), 20 deletions(-) diff --git a/identity/source/IotIdentityClientV2.cpp b/identity/source/IotIdentityClientV2.cpp index b4a8c15f5..6ac2e4ebf 100644 --- a/identity/source/IotIdentityClientV2.cpp +++ b/identity/source/IotIdentityClientV2.cpp @@ -379,8 +379,7 @@ namespace Aws Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( - Aws::Iot::RequestResponse::UnmodeledResult &&result) - { + Aws::Iot::RequestResponse::UnmodeledResult &&result) { s_RegisterThingResponseHandler( std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; diff --git a/identity/tests/CMakeLists.txt b/identity/tests/CMakeLists.txt index dfbcd6a9a..33d324e7d 100644 --- a/identity/tests/CMakeLists.txt +++ b/identity/tests/CMakeLists.txt @@ -10,6 +10,10 @@ set(TEST_BINARY_NAME ${PROJECT_NAME}-tests) add_net_test_case(IdentityV2ClientCreateDestroy5) add_net_test_case(IdentityV2ClientCreateDestroy311) +add_net_test_case(IdentityV2ClientProvisionWithCertAndKey5) +add_net_test_case(IdentityV2ClientProvisionWithCertAndKey311) +add_net_test_case(IdentityV2ClientProvisionWithCSR5) +add_net_test_case(IdentityV2ClientProvisionWithCSR311) generate_cpp_test_driver(${TEST_BINARY_NAME}) diff --git a/identity/tests/v2ClientTests.cpp b/identity/tests/v2ClientTests.cpp index c1b52f0d1..bd0bb493d 100644 --- a/identity/tests/v2ClientTests.cpp +++ b/identity/tests/v2ClientTests.cpp @@ -10,15 +10,24 @@ #include #include #include -#include - +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include -AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableHost, "AWS_TEST_MQTT5_IOT_CORE_HOST"); -AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableCertificatePath, "AWS_TEST_MQTT5_IOT_CORE_RSA_CERT"); -AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariablePrivateKeyPath, "AWS_TEST_MQTT5_IOT_CORE_RSA_KEY"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableHost, "AWS_TEST_IOT_CORE_PROVISIONING_HOST"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableCertificatePath, "AWS_TEST_IOT_CORE_PROVISIONING_CERTIFICATE_PATH"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariablePrivateKeyPath, "AWS_TEST_IOT_CORE_PROVISIONING_KEY_PATH"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableProvisioningTemplateName, "AWS_TEST_IOT_CORE_PROVISIONING_TEMPLATE_NAME"); +AWS_STATIC_STRING_FROM_LITERAL(s_rrEnvVariableProvisioningCsrPath, "AWS_TEST_IOT_CORE_PROVISIONING_CSR_PATH"); static std::shared_ptr s_createProtocolClient5(Aws::Crt::Allocator *allocator) { @@ -54,10 +63,15 @@ static std::shared_ptr s_createProtocolClient5(Aws aws_string_c_str(certificatePath), aws_string_c_str(privateKeyPath), allocator); Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator); + Aws::Crt::String clientId = Aws::Crt::String("test-") + Aws::Crt::UUID().ToString(); + auto connectOptions = Aws::Crt::MakeShared(allocator); + connectOptions->WithClientId(clientId); + Aws::Crt::Mqtt5::Mqtt5ClientOptions mqtt5Options(allocator); mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); mqtt5Options.WithPort(8883); mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); + mqtt5Options.WithConnectOptions(connectOptions); mqtt5Options.WithClientConnectionSuccessCallback( [&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &) @@ -208,7 +222,7 @@ static std::shared_ptr s_createIdentityClient5( return Aws::Iotidentity::NewClientFrom5(*protocolClient, serviceClientOptions, allocator); } -static std::shared_ptr s_createShadowClient311( +static std::shared_ptr s_createIdentityClient311( std::shared_ptr protocolClient, Aws::Crt::Allocator *allocator) { @@ -232,8 +246,8 @@ static int s_IdentityV2ClientCreateDestroy5(Aws::Crt::Allocator *allocator, void Aws::Crt::ApiHandle handle; auto protocolClient = s_createProtocolClient5(allocator); - auto shadowClient = s_createIdentityClient5(protocolClient, allocator); - if (!shadowClient) + auto identityClient = s_createIdentityClient5(protocolClient, allocator); + if (!identityClient) { return AWS_OP_SKIP; } @@ -249,8 +263,8 @@ static int s_IdentityV2ClientCreateDestroy311(Aws::Crt::Allocator *allocator, vo Aws::Crt::ApiHandle handle; auto protocolClient = s_createProtocolClient311(allocator); - auto shadowClient = s_createShadowClient311(protocolClient, allocator); - if (!shadowClient) + auto identityClient = s_createIdentityClient311(protocolClient, allocator); + if (!identityClient) { return AWS_OP_SKIP; } @@ -259,3 +273,220 @@ static int s_IdentityV2ClientCreateDestroy311(Aws::Crt::Allocator *allocator, vo return AWS_OP_SUCCESS; } AWS_TEST_CASE(IdentityV2ClientCreateDestroy311, s_IdentityV2ClientCreateDestroy311) + +static int s_doProvisionCertKeyTest( + std::shared_ptr client, + const Aws::Crt::String &templateName) +{ + + ResultWaiter createResult; + Aws::Iotidentity::CreateKeysAndCertificateRequest createKeysRequest; + + client->CreateKeysAndCertificate( + createKeysRequest, + [&createResult](Aws::Iotidentity::CreateKeysAndCertificateResult &&result) + { createResult.ApplyResult(std::move(result)); }); + + const auto &result = createResult.GetResult(); + ASSERT_TRUE(result.IsSuccess()); + + const auto &response = result.GetResponse(); + ASSERT_TRUE(response.CertificateId.has_value()); + ASSERT_TRUE(response.CertificatePem.has_value()); + ASSERT_TRUE(response.PrivateKey.has_value()); + ASSERT_TRUE(response.CertificateOwnershipToken.has_value()); + + ResultWaiter registerResult; + Aws::Crt::Map params; + params.emplace(Aws::Crt::String("SerialNumber"), Aws::Crt::UUID().ToString()); + + Aws::Iotidentity::RegisterThingRequest registerRequest; + registerRequest.CertificateOwnershipToken = response.CertificateOwnershipToken.value(); + registerRequest.TemplateName = templateName; + registerRequest.Parameters = params; + + client->RegisterThing( + registerRequest, + [®isterResult](Aws::Iotidentity::RegisterThingResult &&result) + { registerResult.ApplyResult(std::move(result)); }); + + ASSERT_TRUE(registerResult.GetResult().IsSuccess()); + + return AWS_OP_SUCCESS; +} + +static int s_IdentityV2ClientProvisionWithCertAndKey5(Aws::Crt::Allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle handle; + + struct aws_string *template_name = NULL; + if (aws_get_environment_value(allocator, s_rrEnvVariableProvisioningTemplateName, &template_name) || + template_name == nullptr) + { + return AWS_OP_SKIP; + } + + Aws::Crt::String templateName(aws_string_c_str(template_name)); + aws_string_destroy(template_name); + + auto protocolClient = s_createProtocolClient5(allocator); + auto identityClient = s_createIdentityClient5(protocolClient, allocator); + if (!identityClient) + { + return AWS_OP_SKIP; + } + + return s_doProvisionCertKeyTest(identityClient, templateName); + } +} +AWS_TEST_CASE(IdentityV2ClientProvisionWithCertAndKey5, s_IdentityV2ClientProvisionWithCertAndKey5) + +static int s_IdentityV2ClientProvisionWithCertAndKey311(Aws::Crt::Allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle handle; + + struct aws_string *template_name = NULL; + if (aws_get_environment_value(allocator, s_rrEnvVariableProvisioningTemplateName, &template_name) || + template_name == nullptr) + { + return AWS_OP_SKIP; + } + + Aws::Crt::String templateName(aws_string_c_str(template_name)); + aws_string_destroy(template_name); + + auto protocolClient = s_createProtocolClient5(allocator); + auto identityClient = s_createIdentityClient5(protocolClient, allocator); + if (!identityClient) + { + return AWS_OP_SKIP; + } + + return s_doProvisionCertKeyTest(identityClient, templateName); + } +} +AWS_TEST_CASE(IdentityV2ClientProvisionWithCertAndKey311, s_IdentityV2ClientProvisionWithCertAndKey311) + +static int s_doProvisionCsrTest( + std::shared_ptr client, + const Aws::Crt::String &templateName, + const Aws::Crt::String &csr) +{ + + ResultWaiter createResult; + Aws::Iotidentity::CreateCertificateFromCsrRequest createCsrRequest; + createCsrRequest.CertificateSigningRequest = csr; + + client->CreateCertificateFromCsr( + createCsrRequest, + [&createResult](Aws::Iotidentity::CreateCertificateFromCsrResult &&result) + { createResult.ApplyResult(std::move(result)); }); + + const auto &result = createResult.GetResult(); + ASSERT_TRUE(result.IsSuccess()); + + const auto &response = result.GetResponse(); + ASSERT_TRUE(response.CertificateId.has_value()); + ASSERT_TRUE(response.CertificatePem.has_value()); + ASSERT_TRUE(response.CertificateOwnershipToken.has_value()); + + ResultWaiter registerResult; + Aws::Crt::Map params; + params.emplace(Aws::Crt::String("SerialNumber"), Aws::Crt::UUID().ToString()); + + Aws::Iotidentity::RegisterThingRequest registerRequest; + registerRequest.CertificateOwnershipToken = response.CertificateOwnershipToken.value(); + registerRequest.TemplateName = templateName; + registerRequest.Parameters = params; + + client->RegisterThing( + registerRequest, + [®isterResult](Aws::Iotidentity::RegisterThingResult &&result) + { registerResult.ApplyResult(std::move(result)); }); + + ASSERT_TRUE(registerResult.GetResult().IsSuccess()); + + return AWS_OP_SUCCESS; +} + +static int s_IdentityV2ClientProvisionWithCSR5(Aws::Crt::Allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle handle; + + struct aws_string *template_name = NULL; + if (aws_get_environment_value(allocator, s_rrEnvVariableProvisioningTemplateName, &template_name) || + template_name == nullptr) + { + return AWS_OP_SKIP; + } + + Aws::Crt::String templateName(aws_string_c_str(template_name)); + aws_string_destroy(template_name); + + struct aws_string *csr_path = NULL; + if (aws_get_environment_value(allocator, s_rrEnvVariableProvisioningCsrPath, &csr_path) || csr_path == nullptr) + { + return AWS_OP_SKIP; + } + + Aws::Crt::String csrPath(aws_string_c_str(csr_path)); + aws_string_destroy(csr_path); + + std::ifstream ifs(csrPath.c_str()); + std::string csr; + getline(ifs, csr, (char)ifs.eof()); + + auto protocolClient = s_createProtocolClient5(allocator); + auto identityClient = s_createIdentityClient5(protocolClient, allocator); + if (!identityClient) + { + return AWS_OP_SKIP; + } + + return s_doProvisionCsrTest(identityClient, templateName, csr.c_str()); + } +} +AWS_TEST_CASE(IdentityV2ClientProvisionWithCSR5, s_IdentityV2ClientProvisionWithCSR5) + +static int s_IdentityV2ClientProvisionWithCSR311(Aws::Crt::Allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle handle; + + struct aws_string *template_name = NULL; + if (aws_get_environment_value(allocator, s_rrEnvVariableProvisioningTemplateName, &template_name) || + template_name == nullptr) + { + return AWS_OP_SKIP; + } + + Aws::Crt::String templateName(aws_string_c_str(template_name)); + aws_string_destroy(template_name); + + struct aws_string *csr_path = NULL; + if (aws_get_environment_value(allocator, s_rrEnvVariableProvisioningCsrPath, &csr_path) || csr_path == nullptr) + { + return AWS_OP_SKIP; + } + + Aws::Crt::String csrPath(aws_string_c_str(csr_path)); + aws_string_destroy(csr_path); + + std::ifstream ifs(csrPath.c_str()); + std::string csr; + getline(ifs, csr, (char)ifs.eof()); + + auto protocolClient = s_createProtocolClient311(allocator); + auto identityClient = s_createIdentityClient311(protocolClient, allocator); + if (!identityClient) + { + return AWS_OP_SKIP; + } + + return s_doProvisionCsrTest(identityClient, templateName, csr.c_str()); + } +} +AWS_TEST_CASE(IdentityV2ClientProvisionWithCSR311, s_IdentityV2ClientProvisionWithCSR311) diff --git a/shadow/source/IotShadowClientV2.cpp b/shadow/source/IotShadowClientV2.cpp index 48a6163b8..e0e0d7c88 100644 --- a/shadow/source/IotShadowClientV2.cpp +++ b/shadow/source/IotShadowClientV2.cpp @@ -304,8 +304,7 @@ namespace Aws options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( - Aws::Iot::RequestResponse::UnmodeledResult &&result) - { + Aws::Iot::RequestResponse::UnmodeledResult &&result) { s_DeleteShadowResponseHandler( std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; @@ -411,8 +410,7 @@ namespace Aws options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( - Aws::Iot::RequestResponse::UnmodeledResult &&result) - { + Aws::Iot::RequestResponse::UnmodeledResult &&result) { s_GetNamedShadowResponseHandler( std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; @@ -516,8 +514,7 @@ namespace Aws options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( - Aws::Iot::RequestResponse::UnmodeledResult &&result) - { + Aws::Iot::RequestResponse::UnmodeledResult &&result) { s_GetShadowResponseHandler( std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; @@ -741,8 +738,7 @@ namespace Aws options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( - Aws::Iot::RequestResponse::UnmodeledResult &&result) - { + Aws::Iot::RequestResponse::UnmodeledResult &&result) { s_UpdateShadowResponseHandler( std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; From ba0ef19d9ae5666e78fa5d94df18a02c56bc30e8 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Tue, 29 Oct 2024 14:42:01 -0700 Subject: [PATCH 11/33] Codegen and format updates --- identity/include/aws/iotidentity/Config.h.in | 5 +++-- identity/source/IotIdentityClientV2.cpp | 3 ++- jobs/include/aws/iotjobs/Config.h.in | 5 +++-- shadow/include/aws/iotshadow/Config.h.in | 5 +++-- shadow/source/IotShadowClientV2.cpp | 12 ++++++++---- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/identity/include/aws/iotidentity/Config.h.in b/identity/include/aws/iotidentity/Config.h.in index b3f4cfb13..eebcaab25 100644 --- a/identity/include/aws/iotidentity/Config.h.in +++ b/identity/include/aws/iotidentity/Config.h.in @@ -1,7 +1,8 @@ #pragma once -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated */ #define AWS_IOT_DEVICE_SDK_CPP_V2_IOTIDENTITY_VERSION "@FULL_VERSION@" diff --git a/identity/source/IotIdentityClientV2.cpp b/identity/source/IotIdentityClientV2.cpp index 6ac2e4ebf..b4a8c15f5 100644 --- a/identity/source/IotIdentityClientV2.cpp +++ b/identity/source/IotIdentityClientV2.cpp @@ -379,7 +379,8 @@ namespace Aws Aws::Crt::ByteCursorFromArray((uint8_t *)outgoingJson.data(), outgoingJson.length()); auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( - Aws::Iot::RequestResponse::UnmodeledResult &&result) { + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_RegisterThingResponseHandler( std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; diff --git a/jobs/include/aws/iotjobs/Config.h.in b/jobs/include/aws/iotjobs/Config.h.in index 747f13316..891200098 100644 --- a/jobs/include/aws/iotjobs/Config.h.in +++ b/jobs/include/aws/iotjobs/Config.h.in @@ -1,7 +1,8 @@ #pragma once -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated */ #define AWS_IOT_DEVICE_SDK_CPP_V2_IOTJOBS_VERSION "@FULL_VERSION@" diff --git a/shadow/include/aws/iotshadow/Config.h.in b/shadow/include/aws/iotshadow/Config.h.in index 66d133a2c..c4ae17957 100644 --- a/shadow/include/aws/iotshadow/Config.h.in +++ b/shadow/include/aws/iotshadow/Config.h.in @@ -1,7 +1,8 @@ #pragma once -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. + * + * This file is generated */ #define AWS_IOT_DEVICE_SDK_CPP_V2_IOTSHADOW_VERSION "@FULL_VERSION@" diff --git a/shadow/source/IotShadowClientV2.cpp b/shadow/source/IotShadowClientV2.cpp index e0e0d7c88..48a6163b8 100644 --- a/shadow/source/IotShadowClientV2.cpp +++ b/shadow/source/IotShadowClientV2.cpp @@ -304,7 +304,8 @@ namespace Aws options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( - Aws::Iot::RequestResponse::UnmodeledResult &&result) { + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_DeleteShadowResponseHandler( std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; @@ -410,7 +411,8 @@ namespace Aws options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( - Aws::Iot::RequestResponse::UnmodeledResult &&result) { + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_GetNamedShadowResponseHandler( std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; @@ -514,7 +516,8 @@ namespace Aws options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( - Aws::Iot::RequestResponse::UnmodeledResult &&result) { + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_GetShadowResponseHandler( std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; @@ -738,7 +741,8 @@ namespace Aws options.correlation_token = Aws::Crt::ByteCursorFromString(uuid); auto resultHandler = [handler, responsePathTopicAccepted, responsePathTopicRejected]( - Aws::Iot::RequestResponse::UnmodeledResult &&result) { + Aws::Iot::RequestResponse::UnmodeledResult &&result) + { s_UpdateShadowResponseHandler( std::move(result), handler, responsePathTopicAccepted, responsePathTopicRejected); }; From e519763a6191602f2f180baf9a1c45e5834ce585 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 09:23:32 -0800 Subject: [PATCH 12/33] V2ServiceError -> V2ErrorResponse --- .../aws/iotidentity/IotIdentityClientV2.h | 8 +++--- .../{V2ServiceError.h => V2ErrorResponse.h} | 10 +++---- identity/source/IotIdentityClientV2.cpp | 14 +++++----- ...V2ServiceError.cpp => V2ErrorResponse.cpp} | 12 ++++----- identity/tests/v2ClientTests.cpp | 2 +- jobs/include/aws/iotjobs/IotJobsClientV2.h | 10 +++---- .../{V2ServiceError.h => V2ErrorResponse.h} | 10 +++---- jobs/source/IotJobsClientV2.cpp | 18 ++++++------- ...V2ServiceError.cpp => V2ErrorResponse.cpp} | 12 ++++----- .../include/aws/iotshadow/IotShadowClientV2.h | 14 +++++----- .../{V2ServiceError.h => V2ErrorResponse.h} | 10 +++---- shadow/source/IotShadowClientV2.cpp | 26 +++++++++---------- ...V2ServiceError.cpp => V2ErrorResponse.cpp} | 12 ++++----- shadow/tests/v2ClientTests.cpp | 2 +- 14 files changed, 80 insertions(+), 80 deletions(-) rename identity/include/aws/iotidentity/{V2ServiceError.h => V2ErrorResponse.h} (76%) rename identity/source/{V2ServiceError.cpp => V2ErrorResponse.cpp} (75%) rename jobs/include/aws/iotjobs/{V2ServiceError.h => V2ErrorResponse.h} (84%) rename jobs/source/{V2ServiceError.cpp => V2ErrorResponse.cpp} (82%) rename shadow/include/aws/iotshadow/{V2ServiceError.h => V2ErrorResponse.h} (82%) rename shadow/source/{V2ServiceError.cpp => V2ErrorResponse.cpp} (78%) diff --git a/identity/include/aws/iotidentity/IotIdentityClientV2.h b/identity/include/aws/iotidentity/IotIdentityClientV2.h index ca79cf3fd..936f5f1bf 100644 --- a/identity/include/aws/iotidentity/IotIdentityClientV2.h +++ b/identity/include/aws/iotidentity/IotIdentityClientV2.h @@ -70,18 +70,18 @@ namespace Aws class CreateKeysAndCertificateResponse; class RegisterThingRequest; class RegisterThingResponse; - class V2ServiceError; + class V2ErrorResponse; using CreateCertificateFromCsrResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using CreateCertificateFromCsrResultHandler = std::function; using CreateKeysAndCertificateResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using CreateKeysAndCertificateResultHandler = std::function; using RegisterThingResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using RegisterThingResultHandler = std::function; /** diff --git a/identity/include/aws/iotidentity/V2ServiceError.h b/identity/include/aws/iotidentity/V2ErrorResponse.h similarity index 76% rename from identity/include/aws/iotidentity/V2ServiceError.h rename to identity/include/aws/iotidentity/V2ErrorResponse.h index c4b0b9a9b..1eba965de 100644 --- a/identity/include/aws/iotidentity/V2ServiceError.h +++ b/identity/include/aws/iotidentity/V2ErrorResponse.h @@ -20,13 +20,13 @@ namespace Aws * Response document containing details about a failed request. * */ - class AWS_IOTIDENTITY_API V2ServiceError final + class AWS_IOTIDENTITY_API V2ErrorResponse final { public: - V2ServiceError() = default; + V2ErrorResponse() = default; - V2ServiceError(const Crt::JsonView &doc); - V2ServiceError &operator=(const Crt::JsonView &doc); + V2ErrorResponse(const Crt::JsonView &doc); + V2ErrorResponse &operator=(const Crt::JsonView &doc); void SerializeToObject(Crt::JsonObject &doc) const; @@ -49,7 +49,7 @@ namespace Aws Aws::Crt::Optional ErrorMessage; private: - static void LoadFromObject(V2ServiceError &obj, const Crt::JsonView &doc); + static void LoadFromObject(V2ErrorResponse &obj, const Crt::JsonView &doc); }; } // namespace Iotidentity } // namespace Aws diff --git a/identity/source/IotIdentityClientV2.cpp b/identity/source/IotIdentityClientV2.cpp index b4a8c15f5..4a502ee3b 100644 --- a/identity/source/IotIdentityClientV2.cpp +++ b/identity/source/IotIdentityClientV2.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace Aws { @@ -75,7 +75,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -105,7 +105,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else @@ -182,7 +182,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -212,7 +212,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else @@ -289,7 +289,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -319,7 +319,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else diff --git a/identity/source/V2ServiceError.cpp b/identity/source/V2ErrorResponse.cpp similarity index 75% rename from identity/source/V2ServiceError.cpp rename to identity/source/V2ErrorResponse.cpp index 1d2d7d668..af4a02371 100644 --- a/identity/source/V2ServiceError.cpp +++ b/identity/source/V2ErrorResponse.cpp @@ -3,14 +3,14 @@ * * This file is generated */ -#include +#include namespace Aws { namespace Iotidentity { - void V2ServiceError::LoadFromObject(V2ServiceError &val, const Aws::Crt::JsonView &doc) + void V2ErrorResponse::LoadFromObject(V2ErrorResponse &val, const Aws::Crt::JsonView &doc) { (void)val; (void)doc; @@ -31,7 +31,7 @@ namespace Aws } } - void V2ServiceError::SerializeToObject(Aws::Crt::JsonObject &object) const + void V2ErrorResponse::SerializeToObject(Aws::Crt::JsonObject &object) const { (void)object; @@ -51,14 +51,14 @@ namespace Aws } } - V2ServiceError::V2ServiceError(const Crt::JsonView &doc) + V2ErrorResponse::V2ErrorResponse(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } - V2ServiceError &V2ServiceError::operator=(const Crt::JsonView &doc) + V2ErrorResponse &V2ErrorResponse::operator=(const Crt::JsonView &doc) { - *this = V2ServiceError(doc); + *this = V2ErrorResponse(doc); return *this; } diff --git a/identity/tests/v2ClientTests.cpp b/identity/tests/v2ClientTests.cpp index bd0bb493d..1cf525301 100644 --- a/identity/tests/v2ClientTests.cpp +++ b/identity/tests/v2ClientTests.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include diff --git a/jobs/include/aws/iotjobs/IotJobsClientV2.h b/jobs/include/aws/iotjobs/IotJobsClientV2.h index 41a1e591b..a5acfd57b 100644 --- a/jobs/include/aws/iotjobs/IotJobsClientV2.h +++ b/jobs/include/aws/iotjobs/IotJobsClientV2.h @@ -76,22 +76,22 @@ namespace Aws class StartNextPendingJobExecutionRequest; class UpdateJobExecutionRequest; class UpdateJobExecutionResponse; - class V2ServiceError; + class V2ErrorResponse; using DescribeJobExecutionResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using DescribeJobExecutionResultHandler = std::function; using GetPendingJobExecutionsResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using GetPendingJobExecutionsResultHandler = std::function; using StartNextPendingJobExecutionResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using StartNextPendingJobExecutionResultHandler = std::function; using UpdateJobExecutionResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using UpdateJobExecutionResultHandler = std::function; /** diff --git a/jobs/include/aws/iotjobs/V2ServiceError.h b/jobs/include/aws/iotjobs/V2ErrorResponse.h similarity index 84% rename from jobs/include/aws/iotjobs/V2ServiceError.h rename to jobs/include/aws/iotjobs/V2ErrorResponse.h index 27702c3e8..36b2a63c3 100644 --- a/jobs/include/aws/iotjobs/V2ServiceError.h +++ b/jobs/include/aws/iotjobs/V2ErrorResponse.h @@ -24,13 +24,13 @@ namespace Aws * Response document containing details about a failed request. * */ - class AWS_IOTJOBS_API V2ServiceError final + class AWS_IOTJOBS_API V2ErrorResponse final { public: - V2ServiceError() = default; + V2ErrorResponse() = default; - V2ServiceError(const Crt::JsonView &doc); - V2ServiceError &operator=(const Crt::JsonView &doc); + V2ErrorResponse(const Crt::JsonView &doc); + V2ErrorResponse &operator=(const Crt::JsonView &doc); void SerializeToObject(Crt::JsonObject &doc) const; @@ -66,7 +66,7 @@ namespace Aws Aws::Crt::Optional ExecutionState; private: - static void LoadFromObject(V2ServiceError &obj, const Crt::JsonView &doc); + static void LoadFromObject(V2ErrorResponse &obj, const Crt::JsonView &doc); }; } // namespace Iotjobs } // namespace Aws diff --git a/jobs/source/IotJobsClientV2.cpp b/jobs/source/IotJobsClientV2.cpp index 0185e4938..83d37f872 100644 --- a/jobs/source/IotJobsClientV2.cpp +++ b/jobs/source/IotJobsClientV2.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include namespace Aws { @@ -97,7 +97,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -127,7 +127,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else @@ -204,7 +204,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -234,7 +234,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else @@ -311,7 +311,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -341,7 +341,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else @@ -418,7 +418,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -448,7 +448,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else diff --git a/jobs/source/V2ServiceError.cpp b/jobs/source/V2ErrorResponse.cpp similarity index 82% rename from jobs/source/V2ServiceError.cpp rename to jobs/source/V2ErrorResponse.cpp index 3e2bb5444..515bd4d88 100644 --- a/jobs/source/V2ServiceError.cpp +++ b/jobs/source/V2ErrorResponse.cpp @@ -3,14 +3,14 @@ * * This file is generated */ -#include +#include namespace Aws { namespace Iotjobs { - void V2ServiceError::LoadFromObject(V2ServiceError &val, const Aws::Crt::JsonView &doc) + void V2ErrorResponse::LoadFromObject(V2ErrorResponse &val, const Aws::Crt::JsonView &doc) { (void)val; (void)doc; @@ -41,7 +41,7 @@ namespace Aws } } - void V2ServiceError::SerializeToObject(Aws::Crt::JsonObject &object) const + void V2ErrorResponse::SerializeToObject(Aws::Crt::JsonObject &object) const { (void)object; @@ -73,14 +73,14 @@ namespace Aws } } - V2ServiceError::V2ServiceError(const Crt::JsonView &doc) + V2ErrorResponse::V2ErrorResponse(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } - V2ServiceError &V2ServiceError::operator=(const Crt::JsonView &doc) + V2ErrorResponse &V2ErrorResponse::operator=(const Crt::JsonView &doc) { - *this = V2ServiceError(doc); + *this = V2ErrorResponse(doc); return *this; } diff --git a/shadow/include/aws/iotshadow/IotShadowClientV2.h b/shadow/include/aws/iotshadow/IotShadowClientV2.h index 285b85759..2f5a05de8 100644 --- a/shadow/include/aws/iotshadow/IotShadowClientV2.h +++ b/shadow/include/aws/iotshadow/IotShadowClientV2.h @@ -79,29 +79,29 @@ namespace Aws class UpdateNamedShadowRequest; class UpdateShadowRequest; class UpdateShadowResponse; - class V2ServiceError; + class V2ErrorResponse; using DeleteNamedShadowResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using DeleteNamedShadowResultHandler = std::function; using DeleteShadowResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using DeleteShadowResultHandler = std::function; using GetNamedShadowResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using GetNamedShadowResultHandler = std::function; - using GetShadowResult = Aws::Iot::RequestResponse::Result>; + using GetShadowResult = Aws::Iot::RequestResponse::Result>; using GetShadowResultHandler = std::function; using UpdateNamedShadowResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using UpdateNamedShadowResultHandler = std::function; using UpdateShadowResult = - Aws::Iot::RequestResponse::Result>; + Aws::Iot::RequestResponse::Result>; using UpdateShadowResultHandler = std::function; /** diff --git a/shadow/include/aws/iotshadow/V2ServiceError.h b/shadow/include/aws/iotshadow/V2ErrorResponse.h similarity index 82% rename from shadow/include/aws/iotshadow/V2ServiceError.h rename to shadow/include/aws/iotshadow/V2ErrorResponse.h index 8e013a9b8..3a1da7dac 100644 --- a/shadow/include/aws/iotshadow/V2ServiceError.h +++ b/shadow/include/aws/iotshadow/V2ErrorResponse.h @@ -22,13 +22,13 @@ namespace Aws * Response document containing details about a failed request. * */ - class AWS_IOTSHADOW_API V2ServiceError final + class AWS_IOTSHADOW_API V2ErrorResponse final { public: - V2ServiceError() = default; + V2ErrorResponse() = default; - V2ServiceError(const Crt::JsonView &doc); - V2ServiceError &operator=(const Crt::JsonView &doc); + V2ErrorResponse(const Crt::JsonView &doc); + V2ErrorResponse &operator=(const Crt::JsonView &doc); void SerializeToObject(Crt::JsonObject &doc) const; @@ -58,7 +58,7 @@ namespace Aws Aws::Crt::Optional Timestamp; private: - static void LoadFromObject(V2ServiceError &obj, const Crt::JsonView &doc); + static void LoadFromObject(V2ErrorResponse &obj, const Crt::JsonView &doc); }; } // namespace Iotshadow } // namespace Aws diff --git a/shadow/source/IotShadowClientV2.cpp b/shadow/source/IotShadowClientV2.cpp index 48a6163b8..02068cc59 100644 --- a/shadow/source/IotShadowClientV2.cpp +++ b/shadow/source/IotShadowClientV2.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include namespace Aws { @@ -107,7 +107,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -137,7 +137,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else @@ -216,7 +216,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -246,7 +246,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else @@ -321,7 +321,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -351,7 +351,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else @@ -428,7 +428,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -458,7 +458,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else @@ -533,7 +533,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -563,7 +563,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else @@ -648,7 +648,7 @@ namespace Aws const Aws::Crt::String &successPathTopic, const Aws::Crt::String &failurePathTopic) { - using E = V2ServiceError; + using E = V2ErrorResponse; using R = Aws::Iot::RequestResponse::Result>; if (!result.IsSuccess()) @@ -678,7 +678,7 @@ namespace Aws } else if (responseTopic == failurePathTopic) { - V2ServiceError modeledError(jsonObject); + V2ErrorResponse modeledError(jsonObject); s_applyModeledErrorToHandler(handler, std::move(modeledError)); } else diff --git a/shadow/source/V2ServiceError.cpp b/shadow/source/V2ErrorResponse.cpp similarity index 78% rename from shadow/source/V2ServiceError.cpp rename to shadow/source/V2ErrorResponse.cpp index 84d32553c..26656db7c 100644 --- a/shadow/source/V2ServiceError.cpp +++ b/shadow/source/V2ErrorResponse.cpp @@ -3,14 +3,14 @@ * * This file is generated */ -#include +#include namespace Aws { namespace Iotshadow { - void V2ServiceError::LoadFromObject(V2ServiceError &val, const Aws::Crt::JsonView &doc) + void V2ErrorResponse::LoadFromObject(V2ErrorResponse &val, const Aws::Crt::JsonView &doc) { (void)val; (void)doc; @@ -36,7 +36,7 @@ namespace Aws } } - void V2ServiceError::SerializeToObject(Aws::Crt::JsonObject &object) const + void V2ErrorResponse::SerializeToObject(Aws::Crt::JsonObject &object) const { (void)object; @@ -61,14 +61,14 @@ namespace Aws } } - V2ServiceError::V2ServiceError(const Crt::JsonView &doc) + V2ErrorResponse::V2ErrorResponse(const Crt::JsonView &doc) { LoadFromObject(*this, doc); } - V2ServiceError &V2ServiceError::operator=(const Crt::JsonView &doc) + V2ErrorResponse &V2ErrorResponse::operator=(const Crt::JsonView &doc) { - *this = V2ServiceError(doc); + *this = V2ErrorResponse(doc); return *this; } diff --git a/shadow/tests/v2ClientTests.cpp b/shadow/tests/v2ClientTests.cpp index a526c2947..5a2814014 100644 --- a/shadow/tests/v2ClientTests.cpp +++ b/shadow/tests/v2ClientTests.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include From 88889a564843762f4cedaf69190568e7943a1a73 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 09:37:06 -0800 Subject: [PATCH 13/33] unreferenced params --- identity/tests/v2ClientTests.cpp | 2 +- jobs/tests/v2ClientTests.cpp | 2 +- shadow/tests/v2ClientTests.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/identity/tests/v2ClientTests.cpp b/identity/tests/v2ClientTests.cpp index 1cf525301..4326aa608 100644 --- a/identity/tests/v2ClientTests.cpp +++ b/identity/tests/v2ClientTests.cpp @@ -141,7 +141,7 @@ static std::shared_ptr s_createProtocolClient311 connection->OnConnectionSuccess = [&connected, &lock, &signal]( - Aws::Crt::Mqtt::MqttConnection &connection, Aws::Crt::Mqtt::OnConnectionSuccessData *callbackData) + Aws::Crt::Mqtt::MqttConnection &, Aws::Crt::Mqtt::OnConnectionSuccessData *) { { std::lock_guard guard(lock); diff --git a/jobs/tests/v2ClientTests.cpp b/jobs/tests/v2ClientTests.cpp index 9a3007529..f893fb2c6 100644 --- a/jobs/tests/v2ClientTests.cpp +++ b/jobs/tests/v2ClientTests.cpp @@ -127,7 +127,7 @@ static std::shared_ptr s_createProtocolClient311 connection->OnConnectionSuccess = [&connected, &lock, &signal]( - Aws::Crt::Mqtt::MqttConnection &connection, Aws::Crt::Mqtt::OnConnectionSuccessData *callbackData) + Aws::Crt::Mqtt::MqttConnection &, Aws::Crt::Mqtt::OnConnectionSuccessData *) { { std::lock_guard guard(lock); diff --git a/shadow/tests/v2ClientTests.cpp b/shadow/tests/v2ClientTests.cpp index 5a2814014..f0092b07b 100644 --- a/shadow/tests/v2ClientTests.cpp +++ b/shadow/tests/v2ClientTests.cpp @@ -138,7 +138,7 @@ static std::shared_ptr s_createProtocolClient311 connection->OnConnectionSuccess = [&connected, &lock, &signal]( - Aws::Crt::Mqtt::MqttConnection &connection, Aws::Crt::Mqtt::OnConnectionSuccessData *callbackData) + Aws::Crt::Mqtt::MqttConnection &, Aws::Crt::Mqtt::OnConnectionSuccessData *) { { std::lock_guard guard(lock); From be267e3c475c121dd0e2fe9a14e05aa13166a6df Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 10:45:13 -0800 Subject: [PATCH 14/33] Trivial change to invoke fresh CI --- jobs/tests/v2ClientTests.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/jobs/tests/v2ClientTests.cpp b/jobs/tests/v2ClientTests.cpp index f893fb2c6..ffefca7da 100644 --- a/jobs/tests/v2ClientTests.cpp +++ b/jobs/tests/v2ClientTests.cpp @@ -58,7 +58,6 @@ static std::shared_ptr s_createProtocolClient5(Aws mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); mqtt5Options.WithPort(8883); mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); - mqtt5Options.WithClientConnectionSuccessCallback( [&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &) { From 20a9fe265a67cbe49d52257cb426f127dccf8e68 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 11:19:44 -0800 Subject: [PATCH 15/33] Will this setup the env variables? --- .builder/actions/sdk-ci-prep.py | 8 ++++++++ builder.json | 1 + 2 files changed, 9 insertions(+) create mode 100644 .builder/actions/sdk-ci-prep.py diff --git a/.builder/actions/sdk-ci-prep.py b/.builder/actions/sdk-ci-prep.py new file mode 100644 index 000000000..86dfac564 --- /dev/null +++ b/.builder/actions/sdk-ci-prep.py @@ -0,0 +1,8 @@ +import Builder + +class SdkCiPrep(Builder.Action): + def run(self, env): + actions = [ + Builder.SetupCrossCICrtEnvironment() + ] + return Builder.Script(actions, name='sdk-ci-prep') diff --git a/builder.json b/builder.json index 293a06351..2a62b48f2 100644 --- a/builder.json +++ b/builder.json @@ -20,6 +20,7 @@ }, "_comment": "See .builder/actions/build_samples.py for definition of 'build-samples'", "build_steps": [ + "sdk-ci-prep", "build", "build-samples" ], From 634aea85e37dac0930c98501191962990a03e406 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 11:31:26 -0800 Subject: [PATCH 16/33] Manual test invoke of cli --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed420b850..7cbd50375 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,6 +118,7 @@ jobs: # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages - name: Build ${{ env.PACKAGE_NAME }} run: | + aws s3 ls aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --compiler=${{ matrix.compiler }} byo-crypto: From ec5fb72be357ba58dcccb82098189a6a8972e044 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 11:32:01 -0800 Subject: [PATCH 17/33] Revert "Manual test invoke of cli" This reverts commit 634aea85e37dac0930c98501191962990a03e406. --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7cbd50375..ed420b850 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,7 +118,6 @@ jobs: # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages - name: Build ${{ env.PACKAGE_NAME }} run: | - aws s3 ls aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --compiler=${{ matrix.compiler }} byo-crypto: From 421baabf0fa17033095554188d74b8412ea031dd Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 11:39:56 -0800 Subject: [PATCH 18/33] Does the build have credentials injected? --- .builder/actions/sdk-ci-prep.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.builder/actions/sdk-ci-prep.py b/.builder/actions/sdk-ci-prep.py index 86dfac564..3dc014505 100644 --- a/.builder/actions/sdk-ci-prep.py +++ b/.builder/actions/sdk-ci-prep.py @@ -1,7 +1,12 @@ import Builder +import os class SdkCiPrep(Builder.Action): def run(self, env): + if os.environ.get('AWS_ACCESS_KEY_ID') != None: + print(f"Local credentials exist") + else: + print(f"No Local credentials") actions = [ Builder.SetupCrossCICrtEnvironment() ] From f04dfd6f6abcf2cd4a1365405223bd3167167ff2 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 11:50:39 -0800 Subject: [PATCH 19/33] Check for session --- .builder/actions/sdk-ci-prep.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.builder/actions/sdk-ci-prep.py b/.builder/actions/sdk-ci-prep.py index 3dc014505..8a0998c85 100644 --- a/.builder/actions/sdk-ci-prep.py +++ b/.builder/actions/sdk-ci-prep.py @@ -5,8 +5,12 @@ class SdkCiPrep(Builder.Action): def run(self, env): if os.environ.get('AWS_ACCESS_KEY_ID') != None: print(f"Local credentials exist") + if os.environ.get('AWS_SESSION_TOKEN') != None: + print(f"Local credentials are session based") else: print(f"No Local credentials") + + actions = [ Builder.SetupCrossCICrtEnvironment() ] From d799ec9115a80d32aa05f21dcb0f6d5f0fea643f Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 12:02:26 -0800 Subject: [PATCH 20/33] non-change to trigger CI --- jobs/tests/v2ClientTests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/jobs/tests/v2ClientTests.cpp b/jobs/tests/v2ClientTests.cpp index ffefca7da..0da16b5c3 100644 --- a/jobs/tests/v2ClientTests.cpp +++ b/jobs/tests/v2ClientTests.cpp @@ -58,6 +58,7 @@ static std::shared_ptr s_createProtocolClient5(Aws mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); mqtt5Options.WithPort(8883); mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); + mqtt5Options.WithClientConnectionSuccessCallback( [&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &) { From bd03d8ac81d95690f20091ab08f26408b34fd9eb Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 12:26:47 -0800 Subject: [PATCH 21/33] Updated builder to a version that passes session credentials to the container --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed420b850..a40592d6d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: - 'docs' env: - BUILDER_VERSION: v0.9.56 + BUILDER_VERSION: v0.9.70 BUILDER_SOURCE: releases BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net PACKAGE_NAME: aws-iot-device-sdk-cpp-v2 From 3fd689254e1cc3a60269cb93994ee941fc42a61b Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 12:41:20 -0800 Subject: [PATCH 22/33] Non-change --- jobs/tests/v2ClientTests.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/jobs/tests/v2ClientTests.cpp b/jobs/tests/v2ClientTests.cpp index 0da16b5c3..ffefca7da 100644 --- a/jobs/tests/v2ClientTests.cpp +++ b/jobs/tests/v2ClientTests.cpp @@ -58,7 +58,6 @@ static std::shared_ptr s_createProtocolClient5(Aws mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); mqtt5Options.WithPort(8883); mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); - mqtt5Options.WithClientConnectionSuccessCallback( [&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &) { From 1799c1ad8addb2dad793fa33f323a75a8638dee1 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 12:53:20 -0800 Subject: [PATCH 23/33] Non change --- jobs/tests/v2ClientTests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/jobs/tests/v2ClientTests.cpp b/jobs/tests/v2ClientTests.cpp index ffefca7da..0da16b5c3 100644 --- a/jobs/tests/v2ClientTests.cpp +++ b/jobs/tests/v2ClientTests.cpp @@ -58,6 +58,7 @@ static std::shared_ptr s_createProtocolClient5(Aws mqtt5Options.WithHostName(Aws::Crt::String(aws_string_c_str(host))); mqtt5Options.WithPort(8883); mqtt5Options.WithTlsConnectionOptions(tlsContext.NewConnectionOptions()); + mqtt5Options.WithClientConnectionSuccessCallback( [&lock, &signal, &connected](const Aws::Crt::Mqtt5::OnConnectionSuccessEventData &) { From 5fa7606b969ad8aa6f145b54428ed296d7b26d6a Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Mon, 11 Nov 2024 13:10:16 -0800 Subject: [PATCH 24/33] Update CI jobs with CI-test credentials --- .github/workflows/ci.yml | 73 +++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a40592d6d..d80afcf86 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -155,6 +155,11 @@ jobs: permissions: id-token: write # This is required for requesting the JWT steps: + - name: configure AWS credentials (containers) + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ env.CI_IOT_CONTAINERS }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | md ${{ env.CI_FOLDER }} @@ -204,6 +209,11 @@ jobs: permissions: id-token: write # This is required for requesting the JWT steps: + - name: configure AWS credentials (containers) + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ env.CI_IOT_CONTAINERS }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | md ${{ env.CI_FOLDER }} @@ -249,6 +259,11 @@ jobs: permissions: id-token: write # This is required for requesting the JWT steps: + - name: configure AWS credentials (containers) + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ env.CI_IOT_CONTAINERS }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | md ${{ env.CI_FOLDER }} @@ -294,30 +309,40 @@ jobs: permissions: id-token: write # This is required for requesting the JWT steps: - - name: Build ${{ env.PACKAGE_NAME }} + consumers - run: | - md ${{ env.CI_FOLDER }} - cd ${{ env.CI_FOLDER }} - python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz', 'builder.pyz')" - python builder.pyz build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-DUSE_CPU_EXTENSIONS=OFF - - name: Running samples in CI setup - run: | - python -m pip install boto3 - - name: configure AWS credentials (CyclePubSub) - uses: aws-actions/configure-aws-credentials@v2 - with: - role-to-assume: ${{ env.CI_CYCLEPUBSUB_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: Run and check AppVerifier - run: | - cd ${{ env.CI_FOLDER }} - echo "Starting to run AppVerifier with cycle pub-sub sample" - python ${{ env.CI_UTILS_FOLDER }}/appverifier_launch_sample.py --sample_file ".\aws-iot-device-sdk-cpp-v2\build\samples\pub_sub\cycle_pub_sub\RelWithDebInfo\cycle-pub-sub.exe" --sample_secret_endpoint 'ci/endpoint' --sample_secret_certificate 'ci/CyclePubSub/cert' --sample_secret_private_key 'ci/CyclePubSub/key' + - name: configure AWS credentials (containers) + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ env.CI_IOT_CONTAINERS }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + - name: Build ${{ env.PACKAGE_NAME }} + consumers + run: | + md ${{ env.CI_FOLDER }} + cd ${{ env.CI_FOLDER }} + python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz', 'builder.pyz')" + python builder.pyz build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-DUSE_CPU_EXTENSIONS=OFF + - name: Running samples in CI setup + run: | + python -m pip install boto3 + - name: configure AWS credentials (CyclePubSub) + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ env.CI_CYCLEPUBSUB_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + - name: Run and check AppVerifier + run: | + cd ${{ env.CI_FOLDER }} + echo "Starting to run AppVerifier with cycle pub-sub sample" + python ${{ env.CI_UTILS_FOLDER }}/appverifier_launch_sample.py --sample_file ".\aws-iot-device-sdk-cpp-v2\build\samples\pub_sub\cycle_pub_sub\RelWithDebInfo\cycle-pub-sub.exe" --sample_secret_endpoint 'ci/endpoint' --sample_secret_certificate 'ci/CyclePubSub/cert' --sample_secret_private_key 'ci/CyclePubSub/key' windows-shared-lib: runs-on: windows-latest permissions: id-token: write # This is required for requesting the JWT steps: + - name: configure AWS credentials (containers) + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ env.CI_IOT_CONTAINERS }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | md ${{ env.CI_FOLDER }} @@ -336,6 +361,11 @@ jobs: id-token: write # This is required for requesting the JWT security-events: write # This is required for pkcs12 sample to sign the key steps: + - name: configure AWS credentials (containers) + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ env.CI_IOT_CONTAINERS }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz', 'builder')" @@ -400,6 +430,11 @@ jobs: permissions: id-token: write # This is required for requesting the JWT steps: + - name: configure AWS credentials (containers) + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ env.CI_IOT_CONTAINERS }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" From c57dec71dcdc7f2b71da1537866e79acac523a2b Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Tue, 12 Nov 2024 11:18:49 -0800 Subject: [PATCH 25/33] Basic CI Prep --- .github/workflows/ci.yml | 2 +- builder.json | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d80afcf86..948822c15 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: - 'docs' env: - BUILDER_VERSION: v0.9.70 + BUILDER_VERSION: v0.9.71 BUILDER_SOURCE: releases BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net PACKAGE_NAME: aws-iot-device-sdk-cpp-v2 diff --git a/builder.json b/builder.json index 2a62b48f2..6d2f47eac 100644 --- a/builder.json +++ b/builder.json @@ -20,10 +20,13 @@ }, "_comment": "See .builder/actions/build_samples.py for definition of 'build-samples'", "build_steps": [ - "sdk-ci-prep", "build", "build-samples" ], + "test_steps": [ + "sdk-ci-prep", + "test" + ], "variants" : { "skip_sample": { "!build_steps": [ From bc9273ef50e988db5fad4e86d610815eaba716c3 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Tue, 12 Nov 2024 13:00:35 -0800 Subject: [PATCH 26/33] Skip service tests on macs where keychain access/code-signing is necessary. Skip tests on BYO_CRYPTO --- builder.json | 7 +++++++ identity/tests/CMakeLists.txt | 14 ++++++++------ jobs/tests/CMakeLists.txt | 6 ++++-- jobs/tests/v2ClientTests.cpp | 8 ++++---- shadow/tests/CMakeLists.txt | 18 ++++++++++-------- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/builder.json b/builder.json index 6d2f47eac..6f673e9a1 100644 --- a/builder.json +++ b/builder.json @@ -39,5 +39,12 @@ "build-gg-samples" ] } + }, + "targets" : { + "macos" : { + "!test_steps": [ + "test" + ] + } } } diff --git a/identity/tests/CMakeLists.txt b/identity/tests/CMakeLists.txt index 33d324e7d..d6a51e011 100644 --- a/identity/tests/CMakeLists.txt +++ b/identity/tests/CMakeLists.txt @@ -8,12 +8,14 @@ file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) set(TEST_BINARY_NAME ${PROJECT_NAME}-tests) -add_net_test_case(IdentityV2ClientCreateDestroy5) -add_net_test_case(IdentityV2ClientCreateDestroy311) -add_net_test_case(IdentityV2ClientProvisionWithCertAndKey5) -add_net_test_case(IdentityV2ClientProvisionWithCertAndKey311) -add_net_test_case(IdentityV2ClientProvisionWithCSR5) -add_net_test_case(IdentityV2ClientProvisionWithCSR311) +if(NOT BYO_CRYPTO) + add_net_test_case(IdentityV2ClientCreateDestroy5) + add_net_test_case(IdentityV2ClientCreateDestroy311) + add_net_test_case(IdentityV2ClientProvisionWithCertAndKey5) + add_net_test_case(IdentityV2ClientProvisionWithCertAndKey311) + add_net_test_case(IdentityV2ClientProvisionWithCSR5) + add_net_test_case(IdentityV2ClientProvisionWithCSR311) +endif() generate_cpp_test_driver(${TEST_BINARY_NAME}) diff --git a/jobs/tests/CMakeLists.txt b/jobs/tests/CMakeLists.txt index e1013f3e9..1980b3006 100644 --- a/jobs/tests/CMakeLists.txt +++ b/jobs/tests/CMakeLists.txt @@ -8,8 +8,10 @@ file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) set(TEST_BINARY_NAME ${PROJECT_NAME}-tests) -add_net_test_case(JobsV2ClientCreateDestroy5) -add_net_test_case(JobsV2ClientCreateDestroy311) +if(NOT BYO_CRYPTO) + add_net_test_case(JobsV2ClientCreateDestroy5) + add_net_test_case(JobsV2ClientCreateDestroy311) +endif() generate_cpp_test_driver(${TEST_BINARY_NAME}) diff --git a/jobs/tests/v2ClientTests.cpp b/jobs/tests/v2ClientTests.cpp index 0da16b5c3..93bc9f779 100644 --- a/jobs/tests/v2ClientTests.cpp +++ b/jobs/tests/v2ClientTests.cpp @@ -190,7 +190,7 @@ template class ResultWaiter Aws::Crt::Optional m_result; }; -static std::shared_ptr s_createIdentityClient5( +static std::shared_ptr s_createJobsClient5( std::shared_ptr protocolClient, Aws::Crt::Allocator *allocator) { @@ -208,7 +208,7 @@ static std::shared_ptr s_createIdentityClient5( return Aws::Iotjobs::NewClientFrom5(*protocolClient, serviceClientOptions, allocator); } -static std::shared_ptr s_createShadowClient311( +static std::shared_ptr s_createJobsClient311( std::shared_ptr protocolClient, Aws::Crt::Allocator *allocator) { @@ -232,7 +232,7 @@ static int s_JobsV2ClientCreateDestroy5(Aws::Crt::Allocator *allocator, void *) Aws::Crt::ApiHandle handle; auto protocolClient = s_createProtocolClient5(allocator); - auto shadowClient = s_createIdentityClient5(protocolClient, allocator); + auto shadowClient = s_createJobsClient5(protocolClient, allocator); if (!shadowClient) { return AWS_OP_SKIP; @@ -249,7 +249,7 @@ static int s_JobsV2ClientCreateDestroy311(Aws::Crt::Allocator *allocator, void * Aws::Crt::ApiHandle handle; auto protocolClient = s_createProtocolClient311(allocator); - auto shadowClient = s_createShadowClient311(protocolClient, allocator); + auto shadowClient = s_createJobsClient311(protocolClient, allocator); if (!shadowClient) { return AWS_OP_SKIP; diff --git a/shadow/tests/CMakeLists.txt b/shadow/tests/CMakeLists.txt index bbc19e2a5..a316539ee 100644 --- a/shadow/tests/CMakeLists.txt +++ b/shadow/tests/CMakeLists.txt @@ -8,14 +8,16 @@ file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) set(TEST_BINARY_NAME ${PROJECT_NAME}-tests) -add_net_test_case(ShadowV2ClientCreateDestroy5) -add_net_test_case(ShadowV2ClientCreateDestroy311) -add_net_test_case(ShadowV2ClientGetNonExistentNamedShadow5) -add_net_test_case(ShadowV2ClientGetNonExistentNamedShadow311) -add_net_test_case(ShadowV2ClientCreateDestroyNamedShadow5) -add_net_test_case(ShadowV2ClientCreateDestroyNamedShadow311) -add_net_test_case(ShadowV2ClientDeltaUpdateNamedShadow5) -add_net_test_case(ShadowV2ClientDeltaUpdateNamedShadow311) +if(NOT BYO_CRYPTO) + add_net_test_case(ShadowV2ClientCreateDestroy5) + add_net_test_case(ShadowV2ClientCreateDestroy311) + add_net_test_case(ShadowV2ClientGetNonExistentNamedShadow5) + add_net_test_case(ShadowV2ClientGetNonExistentNamedShadow311) + add_net_test_case(ShadowV2ClientCreateDestroyNamedShadow5) + add_net_test_case(ShadowV2ClientCreateDestroyNamedShadow311) + add_net_test_case(ShadowV2ClientDeltaUpdateNamedShadow5) + add_net_test_case(ShadowV2ClientDeltaUpdateNamedShadow311) +endif() generate_cpp_test_driver(${TEST_BINARY_NAME}) From 2fb685f4b45ca24137246ca237b89bd4ed8c3b15 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Tue, 12 Nov 2024 13:15:57 -0800 Subject: [PATCH 27/33] Can't have empty test exe --- identity/CMakeLists.txt | 2 +- identity/tests/CMakeLists.txt | 14 ++++++-------- jobs/CMakeLists.txt | 2 +- jobs/tests/CMakeLists.txt | 6 ++---- shadow/CMakeLists.txt | 2 +- shadow/tests/CMakeLists.txt | 18 ++++++++---------- 6 files changed, 19 insertions(+), 25 deletions(-) diff --git a/identity/CMakeLists.txt b/identity/CMakeLists.txt index bfd7a6c8a..16ffe1856 100644 --- a/identity/CMakeLists.txt +++ b/identity/CMakeLists.txt @@ -135,7 +135,7 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/iotidentity-cpp-config.cmake" COMPONENT Development) if(NOT CMAKE_CROSSCOMPILING) - if (BUILD_TESTING) + if (BUILD_TESTING AND NOT BYO_CRYPTO) add_subdirectory(tests) endif() endif() diff --git a/identity/tests/CMakeLists.txt b/identity/tests/CMakeLists.txt index d6a51e011..33d324e7d 100644 --- a/identity/tests/CMakeLists.txt +++ b/identity/tests/CMakeLists.txt @@ -8,14 +8,12 @@ file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) set(TEST_BINARY_NAME ${PROJECT_NAME}-tests) -if(NOT BYO_CRYPTO) - add_net_test_case(IdentityV2ClientCreateDestroy5) - add_net_test_case(IdentityV2ClientCreateDestroy311) - add_net_test_case(IdentityV2ClientProvisionWithCertAndKey5) - add_net_test_case(IdentityV2ClientProvisionWithCertAndKey311) - add_net_test_case(IdentityV2ClientProvisionWithCSR5) - add_net_test_case(IdentityV2ClientProvisionWithCSR311) -endif() +add_net_test_case(IdentityV2ClientCreateDestroy5) +add_net_test_case(IdentityV2ClientCreateDestroy311) +add_net_test_case(IdentityV2ClientProvisionWithCertAndKey5) +add_net_test_case(IdentityV2ClientProvisionWithCertAndKey311) +add_net_test_case(IdentityV2ClientProvisionWithCSR5) +add_net_test_case(IdentityV2ClientProvisionWithCSR311) generate_cpp_test_driver(${TEST_BINARY_NAME}) diff --git a/jobs/CMakeLists.txt b/jobs/CMakeLists.txt index c538a5872..0f7d59068 100644 --- a/jobs/CMakeLists.txt +++ b/jobs/CMakeLists.txt @@ -135,7 +135,7 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/iotjobs-cpp-config.cmake" COMPONENT Development) if(NOT CMAKE_CROSSCOMPILING) - if (BUILD_TESTING) + if (BUILD_TESTING AND NOT BYO_CRYPTO) add_subdirectory(tests) endif() endif() diff --git a/jobs/tests/CMakeLists.txt b/jobs/tests/CMakeLists.txt index 1980b3006..e1013f3e9 100644 --- a/jobs/tests/CMakeLists.txt +++ b/jobs/tests/CMakeLists.txt @@ -8,10 +8,8 @@ file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) set(TEST_BINARY_NAME ${PROJECT_NAME}-tests) -if(NOT BYO_CRYPTO) - add_net_test_case(JobsV2ClientCreateDestroy5) - add_net_test_case(JobsV2ClientCreateDestroy311) -endif() +add_net_test_case(JobsV2ClientCreateDestroy5) +add_net_test_case(JobsV2ClientCreateDestroy311) generate_cpp_test_driver(${TEST_BINARY_NAME}) diff --git a/shadow/CMakeLists.txt b/shadow/CMakeLists.txt index 00013a1f3..1707d2fae 100644 --- a/shadow/CMakeLists.txt +++ b/shadow/CMakeLists.txt @@ -135,7 +135,7 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/iotshadow-cpp-config.cmake" COMPONENT Development) if(NOT CMAKE_CROSSCOMPILING) - if (BUILD_TESTING) + if (BUILD_TESTING AND NOT BYO_CRYPTO) add_subdirectory(tests) endif() endif() diff --git a/shadow/tests/CMakeLists.txt b/shadow/tests/CMakeLists.txt index a316539ee..bbc19e2a5 100644 --- a/shadow/tests/CMakeLists.txt +++ b/shadow/tests/CMakeLists.txt @@ -8,16 +8,14 @@ file(GLOB TESTS ${TEST_HDRS} ${TEST_SRC}) set(TEST_BINARY_NAME ${PROJECT_NAME}-tests) -if(NOT BYO_CRYPTO) - add_net_test_case(ShadowV2ClientCreateDestroy5) - add_net_test_case(ShadowV2ClientCreateDestroy311) - add_net_test_case(ShadowV2ClientGetNonExistentNamedShadow5) - add_net_test_case(ShadowV2ClientGetNonExistentNamedShadow311) - add_net_test_case(ShadowV2ClientCreateDestroyNamedShadow5) - add_net_test_case(ShadowV2ClientCreateDestroyNamedShadow311) - add_net_test_case(ShadowV2ClientDeltaUpdateNamedShadow5) - add_net_test_case(ShadowV2ClientDeltaUpdateNamedShadow311) -endif() +add_net_test_case(ShadowV2ClientCreateDestroy5) +add_net_test_case(ShadowV2ClientCreateDestroy311) +add_net_test_case(ShadowV2ClientGetNonExistentNamedShadow5) +add_net_test_case(ShadowV2ClientGetNonExistentNamedShadow311) +add_net_test_case(ShadowV2ClientCreateDestroyNamedShadow5) +add_net_test_case(ShadowV2ClientCreateDestroyNamedShadow311) +add_net_test_case(ShadowV2ClientDeltaUpdateNamedShadow5) +add_net_test_case(ShadowV2ClientDeltaUpdateNamedShadow311) generate_cpp_test_driver(${TEST_BINARY_NAME}) From 88769767816881652f17c5e30088347d6d2853b9 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Tue, 12 Nov 2024 14:19:19 -0800 Subject: [PATCH 28/33] Provison second parameter --- identity/tests/v2ClientTests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/identity/tests/v2ClientTests.cpp b/identity/tests/v2ClientTests.cpp index 4326aa608..d7b9d87f6 100644 --- a/identity/tests/v2ClientTests.cpp +++ b/identity/tests/v2ClientTests.cpp @@ -299,6 +299,7 @@ static int s_doProvisionCertKeyTest( ResultWaiter registerResult; Aws::Crt::Map params; params.emplace(Aws::Crt::String("SerialNumber"), Aws::Crt::UUID().ToString()); + params.emplace(Aws::Crt::String("DeviceLocation"), Aws::Crt::String("Seattle")); Aws::Iotidentity::RegisterThingRequest registerRequest; registerRequest.CertificateOwnershipToken = response.CertificateOwnershipToken.value(); From 278a5e1e31282c1cedc40b4c736b6e37b0ff8b16 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Tue, 12 Nov 2024 14:45:49 -0800 Subject: [PATCH 29/33] Temporarily allow mac service testing --- builder.json | 1 + 1 file changed, 1 insertion(+) diff --git a/builder.json b/builder.json index 6f673e9a1..ce13c5307 100644 --- a/builder.json +++ b/builder.json @@ -43,6 +43,7 @@ "targets" : { "macos" : { "!test_steps": [ + "sdk-ci-prep", "test" ] } From 272cf937eda737533954dd4b571a945fdb6caeb4 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Tue, 12 Nov 2024 14:50:01 -0800 Subject: [PATCH 30/33] Device location csr --- identity/tests/v2ClientTests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/identity/tests/v2ClientTests.cpp b/identity/tests/v2ClientTests.cpp index d7b9d87f6..335fa45a0 100644 --- a/identity/tests/v2ClientTests.cpp +++ b/identity/tests/v2ClientTests.cpp @@ -396,6 +396,7 @@ static int s_doProvisionCsrTest( ResultWaiter registerResult; Aws::Crt::Map params; params.emplace(Aws::Crt::String("SerialNumber"), Aws::Crt::UUID().ToString()); + params.emplace(Aws::Crt::String("DeviceLocation"), Aws::Crt::String("Seattle")); Aws::Iotidentity::RegisterThingRequest registerRequest; registerRequest.CertificateOwnershipToken = response.CertificateOwnershipToken.value(); From 5881ac3d656bde4e568879a631d14f2e4f312840 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Wed, 13 Nov 2024 13:04:10 -0800 Subject: [PATCH 31/33] Builder with fleet provisioning env --- .github/workflows/ci.yml | 2 +- builder.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 948822c15..6a8a413ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: - 'docs' env: - BUILDER_VERSION: v0.9.71 + BUILDER_VERSION: v0.9.72 BUILDER_SOURCE: releases BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net PACKAGE_NAME: aws-iot-device-sdk-cpp-v2 diff --git a/builder.json b/builder.json index ce13c5307..6f673e9a1 100644 --- a/builder.json +++ b/builder.json @@ -43,7 +43,6 @@ "targets" : { "macos" : { "!test_steps": [ - "sdk-ci-prep", "test" ] } From 31e556d3abf21e55e1ec21b7e65c87e50654e5a6 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Wed, 13 Nov 2024 13:51:57 -0800 Subject: [PATCH 32/33] Use credentials with smoke tests too --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a8a413ce..cf3802348 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -495,6 +495,11 @@ jobs: sudo apt install cmake gcc --version cmake --version + - name: configure AWS credentials (containers) + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ env.CI_IOT_CONTAINERS }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | echo "Downloading source" From 0e9dc45ea7917ba0f3d021ccf0ba1d4088de63c0 Mon Sep 17 00:00:00 2001 From: Bret Ambrose Date: Thu, 14 Nov 2024 09:38:47 -0800 Subject: [PATCH 33/33] Released CRT --- crt/aws-crt-cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crt/aws-crt-cpp b/crt/aws-crt-cpp index 6ff68c5fa..6bbd4ebe0 160000 --- a/crt/aws-crt-cpp +++ b/crt/aws-crt-cpp @@ -1 +1 @@ -Subproject commit 6ff68c5fa0f151cb59a781227f3c66770046487a +Subproject commit 6bbd4ebe0bfd7f89601f8d2351f1ce54ba7fb27b