From f3af6c4653d63b37425d09227813dd5cf8ae73ad Mon Sep 17 00:00:00 2001 From: scmacdon Date: Mon, 16 Sep 2024 18:23:22 -0400 Subject: [PATCH 01/41] Add Java Basics for IoT Sitewise --- basics_scenarios/sitewise_scenario/README.md | 51 ++ .../sitewise_scenario/SPECIFICATION.md | 310 ++++++++++ javav2/example_code/iotsitewise/.gitignore | 38 ++ javav2/example_code/iotsitewise/pom.xml | 127 +++++ .../iotsitewise/CreateBulkImportJob.java | 165 ++++++ .../iotsitewise/scenario/SitewiseActions.java | 528 ++++++++++++++++++ .../scenario/SitewiseScenario.java | 441 +++++++++++++++ .../iotsitewise/src/main/resources/data.json | 44 ++ .../iotsitewise/src/main/resources/log4j2.xml | 18 + 9 files changed, 1722 insertions(+) create mode 100644 basics_scenarios/sitewise_scenario/README.md create mode 100644 basics_scenarios/sitewise_scenario/SPECIFICATION.md create mode 100644 javav2/example_code/iotsitewise/.gitignore create mode 100644 javav2/example_code/iotsitewise/pom.xml create mode 100644 javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/CreateBulkImportJob.java create mode 100644 javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java create mode 100644 javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java create mode 100644 javav2/example_code/iotsitewise/src/main/resources/data.json create mode 100644 javav2/example_code/iotsitewise/src/main/resources/log4j2.xml diff --git a/basics_scenarios/sitewise_scenario/README.md b/basics_scenarios/sitewise_scenario/README.md new file mode 100644 index 00000000000..8308cb63ba0 --- /dev/null +++ b/basics_scenarios/sitewise_scenario/README.md @@ -0,0 +1,51 @@ +# Amazon OpenSearch Service Basic Scenario + +## Overview + + This Amazon OpenSearch Service (Amazon ECR) basic scenario demonstrates how to interact with the Amazon OpenSearch service using an AWS SDK. The scenario covers various operations such as creating an OpenSearch domain, modifying a domain, waiting for changes to the domain to enter a complete state, and so on. + + Here are the top five service operations this scenario covers. + +**Create an Amazon OpenSearch Domain**: + - Description: This operation creates a new Amazon OpenSearch domain, which is a managed instance of the OpenSearch engine. + +2. **Describe the Amazon OpenSearch Domain**: + - Description: This operation retrieves information about the specified Amazon OpenSearch domain. + - The method `describeDomain(domainName)` is called to obtain the Amazon Resource Name (ARN) of the specified OpenSearch domain. + +3. **List the Domains in Your Account**: + - Description: This operation lists all the Amazon OpenSearch domains in the current AWS account. + - The method `listAllDomains()` is called to retrieve a list of all the OpenSearch domains available in the account. + +4. **Wait until the Domain's Change Status Reaches a Completed State**: + - Description: This operation waits until the change status of the specified Amazon OpenSearch domain reaches a completed state. + - When making changes to an OpenSearch domain, such as scaling the number of data nodes or updating the OpenSearch version, the domain goes through a change process. This method, `domainChangeProgress(domainName)`, waits until the change status of the specified domain reaches a completed state, which can take several minutes to several hours, depending on the complexity of the change and the current load on the OpenSearch service. + Note this operation may take up to 20 minutes. + +5. **Modify the Domain**: + - Description: This operation modifies the cluster configuration of the specified Amazon OpenSearch domain, such as the instance count. + - The flexibility to modify the OpenSearch domain's configuration is particularly useful when the data or usage patterns change over time, as you can easily scale the domain to meet the new requirements without having to recreate the entire domain. + - The method `updateSpecificDomain(domainName)` is called to update the configuration of the specified OpenSearch domain. + +Note: These steps are not the complete program, but summarizes the 5 high-level steps. See the Eng Spec for a complete listing of operations. + +### Resources + +This scenario does not require any additional AWS resources to run. + + +## Implementations + +This scenario example will be implemented in the following languages: + +- Java +- Python +- JavaScript + +## Additional reading + +- [Amazon ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/what-is-ecr.html) + +--- + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 diff --git a/basics_scenarios/sitewise_scenario/SPECIFICATION.md b/basics_scenarios/sitewise_scenario/SPECIFICATION.md new file mode 100644 index 00000000000..c4781a30547 --- /dev/null +++ b/basics_scenarios/sitewise_scenario/SPECIFICATION.md @@ -0,0 +1,310 @@ +# AWS IoT SiteWise Service Scenario Specification + +## Overview +This SDK Basics scenario demonstrates how to interact with AWS IoT SiteWise using the AWS SDK. It demonstrates various tasks such as creating a SiteWise Asset Model, creating an asset, sending data to the asset, reading data, and so on. Finally this scenario demonstrates how to clean up resources. Its purpose is to demonstrate how to get up and running with AWS IoT SiteWise and the AWS SDK. + +## Resources +This Basics scenario has a depedency on an IAM role that has permissions for this service. We will create this resource using a CloudFormation template so the user does not have to manually create it. + +## Hello Amazon OpenSearch +This program is intended for users not familiar with the AWS IoT SiteWise Service to easily get up and running. The logic is to show use of ` +`???. + +## Scenario Program Flow +The AWS IoT SiteWise Basics scenario executes the following operations. + +1. **Create an AWS SiteWise Asset Model**: + - Description: This operation creates an AWS SiteWise Asset Model. Invoke the `createAssetModel` method. + - Exception Handling: Check to see if a `ResourceAlreadyExistsException` is thrown. If it is thrown, get the asset model id and move on. + +2. **Create an AWS IoT SiteWise Asset**: + - Description: This operation creates an AWS SiteWise asset. + - The method `createAsset` is called to obtain the asset id. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + +3. **Retrieve the property ID values**: + - Description: To send data to an asset, we need to get the property ID values for the Temperature and Humidity properties. + - The method `listAssetModels()` is called to retrieve asset id values. + - Exception Handling: Check to see if a `IoTSiteWiseException` is thrown. There are not many other useful exceptions for this specific call. If so, display the message and end the program. + +4. **Send data to an AWS IoT SiteWise Asset**: + - Description: This operation sends data to an IoT SiteWise Asset. + - This step uses the method `batchPutAssetPropertyValue()`. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + +5. **Retrieve the value of the IoT SiteWise Asset property**: + - Description: This operation gets data from the asset. + - This step uses the method `getAssetPropertyValue()`. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + +6. **Create an IoT SiteWise Portal**: + - Description: This operation is creates a Sitewise portal. + - The method `createPortal` is called. + - Exception Handling: Check to see if a `IoTSiteWiseException` is thrown. + +7. **Describe the Portal**: + - Description: This operation descrines the portal and returns an URL for the portal. + - The method `describePortal()` is called and retutns URL. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + +8. **Create an IoTSitewise Gateway**: + - Description: This operation creates a Sitewise Gateway. + - The method `createGateway)` is called. + - Exception Handling: Check to see if a `IoTSiteWiseException` is thrown. + +9. **Describe the Sitewise Gateway**: + - Description: This operation describes the Gateway. + - The method `describeGateway()` is called." + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + +10. **Delete the AWS IoT SiteWise Assets** + - The `delete()` methods ares called to clean up the resources. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + +### Program execution +The following shows the output of the AWS IoT SiteWise Basics scenario in the console. + +``` +AWS IoT SiteWise is a fully managed industrial software-as-a-service (SaaS) that +makes it easy to collect, store, organize, and monitor data from industrial equipment and processes. +It is designed to help industrial and manufacturing organizations collect data from their equipment and +processes, and use that data to make informed decisions about their operations. + +One of the key features of AWS IoT SiteWise is its ability to connect to a wide range of industrial +equipment and systems, including programmable logic controllers (PLCs), sensors, and other +industrial devices. It can collect data from these devices and organize it into a unified data model, +making it easier to analyze and gain insights from the data. AWS IoT SiteWise also provides tools for +visualizing the data, setting up alarms and alerts, and generating reports. + +Another key feature of AWS IoT SiteWise is its ability to scale to handle large volumes of data. +It can collect and store data from thousands of devices and process millions of data points per second, +making it suitable for large-scale industrial operations. Additionally, AWS IoT SiteWise is designed +to be secure and compliant, with features like role-based access controls, data encryption, +and integration with other AWS services for additional security and compliance features. + +Let's get started... + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +1. Create an AWS SiteWise Asset Model + An AWS IoT SiteWise Asset Model is a way to represent the physical assets, such as equipment, + processes, and systems, that exist in an industrial environment. This model provides a structured and + hierarchical representation of these assets, allowing users to define the relationships and properties + of each asset. + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +The Asset Model MyAssetModel2 already exists. The id of the existing model is 754c6991-9b34-4fd3-85a5-d4261b1324a1. Moving on... + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +2. Create an AWS IoT SiteWise Asset + The IoT SiteWise model defines the structure and metadata for your physical assets. Now we + can use the asset model to create the asset. + + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +Asset created with ID: c11d78da-4356-4f52-8c11-24a02dcf3c5b + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +3. Retrieve the property ID values + To send data to an asset, we need to get the property ID values for the + Temperature and Humidity properties. + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +The Humidity property Id is cfd388c0-b70c-4e25-b656-675d909f7ef7 +The Temperature property Id is fac55cfe-6e7f-4c5e-8bea-2d3e333f169d + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +4. Send data to an AWS IoT SiteWise Asset +By sending data to an IoT SiteWise Asset, you can aggregate data from +multiple sources, normalize the data into a standard format, and store it in a +centralized location. This makes it easier to analyze and gain insights from the data. + +This example demonstrate how to generate sample data and ingest it into the AWS IoT SiteWise asset. + + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +Data sent successfully. + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +5. Retrieve the value of the IoT SiteWise Asset property +IoT SiteWise is an AWS service that allows you to collect, process, and analyze industrial data +from connected equipment and sensors. One of the key benefits of reading an IoT SiteWise property +is the ability to gain valuable insights from your industrial data. + + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +The property name is: Temperature property +The value of this property is 23.5 + +Enter 'c' followed by to continue: +c +Continuing with the program... + +The property name is: Humidity property +The value of this property is 65.0 + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +6. Create an IoT SiteWise Portal + An IoT SiteWise Portal allows you to aggregate data from multiple industrial sources, + such as sensors, equipment, and control systems, into a centralized platform. + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +Portal created successfully. Portal ID 391384ff-f439-481d-a6bb-2195fe70418e +The portal Id is 391384ff-f439-481d-a6bb-2195fe70418e + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +7. Describe the Portal + In this step, we will describe the step and provide the portal URL. + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +Portal URL: https://p-9l9bnfd7.app.iotsitewise.aws + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +8. Create an IoTSitewise Gateway +IoTSitewise Gateway serves as the bridge between industrial equipment, sensors, and the +cloud-based IoTSitewise service. It is responsible for securely collecting, processing, and +transmitting data from various industrial assets to the IoTSitewise platform, +enabling real-time monitoring, analysis, and optimization of industrial operations. + + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +The ARN of the gateway is arn:aws:iotsitewise:us-east-1:814548047983:gateway/417f041e-44e8-40e8-93f4-2904f3a8febd +Gateway creation completed successfully. id is 417f041e-44e8-40e8-93f4-2904f3a8febd +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +9. Describe the IoTSitewise Gateway + +Enter 'c' followed by to continue: +c +Continuing with the program... + +Gateway Name: myGateway11 +Gateway ARN: arn:aws:iotsitewise:us-east-1:814548047983:gateway/417f041e-44e8-40e8-93f4-2904f3a8febd +Gateway Platform: GatewayPlatform(GreengrassV2=GreengrassV2(CoreDeviceThingName=myThing78)) +Gateway Creation Date: 2024-09-13T16:50:54.037Z +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +10. Delete the AWS IoT SiteWise Assets +Before you can delete the Asset Model, you must delete the assets. + + +Would you like to delete the IoT Sitewise Assets? (y/n) +y +You selected to delete the Sitewise assets. + +Enter 'c' followed by to continue: +c +Continuing with the program... + +Portal 391384ff-f439-481d-a6bb-2195fe70418e was deleted successfully. +The Gateway was deleted +Asset deleted successfully. +Lets wait 1 min for the asset to be deleted +00:00Countdown complete! + +Enter 'c' followed by to continue: +c +Continuing with the program... + +Delete the AWS IoT SiteWise Asset Model +IoT SiteWise error occurred: Error message: Asset model had assets when delete was called (Service: IoTSiteWise, Status Code: 400, Request ID: 6ebc4c3e-82e8-4a8b-a6d7-de0c8ada5a9d), Error code InvalidRequestException + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +This concludes the AWS SiteWise Scenario +-------------------------------------------------------------------------------- + + +``` + +## SOS Tags + +The following table describes the metadata used in this Basics Scenario. + + +| action | metadata file | metadata key | +|--------------------------------|-----------------------------------|---------------------------------------- | +| `createDomain` | opensearch_metadata.yaml | opensearch_CreateDomain | +| `deleteDomain ` | opensearch_metadata.yaml | opensearch_DeleteDomain | +| `listDomainNames ` | opensearch_metadata.yaml | opensearch_ListDomainNames | +| `updateDomainConfig` | opensearch_metadata.yaml | opensearch_UpdateDomainConfig | +| `describeDomain` | opensearch_metadata.yaml | opensearch_DescribeDomain | +| `describeDomainChangeProgress` | opensearch_metadata.yaml | opensearch_ChangeProgress | +| `listDomainTags` | opensearch_metadata.yaml | opensearch_ListTags | +| `scenario` | opensearch_metadata.yaml | opensearch_Scenario | + diff --git a/javav2/example_code/iotsitewise/.gitignore b/javav2/example_code/iotsitewise/.gitignore new file mode 100644 index 00000000000..5ff6309b719 --- /dev/null +++ b/javav2/example_code/iotsitewise/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/javav2/example_code/iotsitewise/pom.xml b/javav2/example_code/iotsitewise/pom.xml new file mode 100644 index 00000000000..512f822d0f1 --- /dev/null +++ b/javav2/example_code/iotsitewise/pom.xml @@ -0,0 +1,127 @@ + + + 4.0.0 + + org.example + iotsitewise + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + IntegrationTest + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + + + + + + + + software.amazon.awssdk + bom + 2.27.22 + pom + import + + + org.apache.logging.log4j + log4j-bom + 2.23.1 + pom + import + + + + + + org.junit.jupiter + junit-jupiter-api + 5.9.2 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.9.2 + test + + + software.amazon.awssdk + netty-nio-client + + + org.junit.platform + junit-platform-commons + 1.9.2 + + + software.amazon.awssdk + iotsitewise + + + com.google.code.gson + gson + 2.10.1 + + + software.amazon.awssdk + sso + + + software.amazon.awssdk + ssooidc + + + org.junit.platform + junit-platform-launcher + 1.9.2 + test + + + software.amazon.awssdk + ec2 + + + software.amazon.awssdk + ssm + + + org.apache.logging.log4j + log4j-core + + + org.slf4j + slf4j-api + 2.0.13 + + + org.apache.logging.log4j + log4j-slf4j2-impl + + + org.apache.logging.log4j + log4j-1.2-api + + + \ No newline at end of file diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/CreateBulkImportJob.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/CreateBulkImportJob.java new file mode 100644 index 00000000000..0f2005b9845 --- /dev/null +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/CreateBulkImportJob.java @@ -0,0 +1,165 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.iotsitewise; + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseClient; +import software.amazon.awssdk.services.iotsitewise.model.ColumnName; +import software.amazon.awssdk.services.iotsitewise.model.CreateBulkImportJobRequest; +import software.amazon.awssdk.services.iotsitewise.model.CreateBulkImportJobResponse; +import software.amazon.awssdk.services.iotsitewise.model.Csv; +import software.amazon.awssdk.services.iotsitewise.model.CustomerManagedS3Storage; +import software.amazon.awssdk.services.iotsitewise.model.DescribeStorageConfigurationRequest; +import software.amazon.awssdk.services.iotsitewise.model.DescribeStorageConfigurationResponse; +import software.amazon.awssdk.services.iotsitewise.model.ErrorReportLocation; +import software.amazon.awssdk.services.iotsitewise.model.File; +import software.amazon.awssdk.services.iotsitewise.model.FileFormat; +import software.amazon.awssdk.services.iotsitewise.model.InvalidRequestException; +import software.amazon.awssdk.services.iotsitewise.model.IoTSiteWiseException; +import software.amazon.awssdk.services.iotsitewise.model.JobConfiguration; +import software.amazon.awssdk.services.iotsitewise.model.MultiLayerStorage; +import software.amazon.awssdk.services.iotsitewise.model.PutStorageConfigurationRequest; +import software.amazon.awssdk.services.iotsitewise.model.PutStorageConfigurationResponse; +import software.amazon.awssdk.services.iotsitewise.model.StorageType; + +import java.util.ArrayList; +import java.util.List; + +public class CreateBulkImportJob { + + public static void main(String[]args){ + setConfig(); + checkStorageConfig(); + createBulkImportJob(); + } + + private static IoTSiteWiseClient getClient() { + IoTSiteWiseClient client = IoTSiteWiseClient.builder() + .region(Region.US_EAST_1) + .build(); + + return client; + } + + public static void createBulkImportJob() { + List files = new ArrayList<>(); + files.add(software.amazon.awssdk.services.iotsitewise.model.File.builder() + .bucket("scottsitewise") + .key("data.csv") + .build()); + + Csv csvFormat = Csv.builder() + .columnNames( + ColumnName.ASSET_ID, // Correct column names + ColumnName.PROPERTY_ID, // Correct column names + ColumnName.DATA_TYPE, + ColumnName.TIMESTAMP_SECONDS, + ColumnName.VALUE + ) + .build(); + + FileFormat fileFormat = FileFormat.builder() + .csv(csvFormat) // Set headers + .build(); + + JobConfiguration job = JobConfiguration.builder() + .fileFormat(fileFormat) + .build(); + + ErrorReportLocation errorReportLocation = ErrorReportLocation.builder() + .bucket("scottsitewise") + .prefix("") + .build(); + + CreateBulkImportJobRequest bulkImportJobRequest = CreateBulkImportJobRequest.builder() + .jobName("BulkImportJob") + .errorReportLocation(errorReportLocation) + .jobRoleArn("arn:aws:iam::814548047983:role/AWSIoTSiteWiseMonitorServiceRole_8jLqg43nJ") + .files(files) + .jobConfiguration(job) + .build(); + + try { + CreateBulkImportJobResponse res = getClient().createBulkImportJob(bulkImportJobRequest); + System.out.println("It worked"); + + } catch (InvalidRequestException e) { + System.err.println("Error creating bulk import job: " + e.getMessage()); + e.printStackTrace(); + } catch (IoTSiteWiseException e) { + System.err.println("Unexpected error occurred: " + e.getMessage()); + e.printStackTrace(); + } + } + + public static void checkStorageConfig() { + DescribeStorageConfigurationRequest request = DescribeStorageConfigurationRequest.builder().build(); + + try { + // Pass the request object to the describeStorageConfiguration method + DescribeStorageConfigurationResponse response = getClient().describeStorageConfiguration(request); + + // Output the current storage configuration + System.out.println("Current Storage Type: " + response.storageType()); + + // Check if Multi-Layer Storage is enabled + if (response.multiLayerStorage() != null) { + System.out.println("Multi-Layer Storage is enabled: " + response.multiLayerStorage()); + } else { + System.out.println("Multi-Layer Storage is not enabled."); + } + } catch (IoTSiteWiseException e) { + System.err.println("Failed to describe storage configuration: " + e.getMessage()); + e.printStackTrace(); + } + } + public static void setConfig() { + CustomerManagedS3Storage managedS3Storage = CustomerManagedS3Storage.builder() + .roleArn("arn:aws:iam::814548047983:role/service-role/AWSIoTSiteWiseMonitorServiceRole_8jLqg43nJ") + .s3ResourceArn("arn:aws:s3:::scottsitewise") + .build(); + + // Configure the S3 bucket for cold tier storage in multi-layer storage + MultiLayerStorage multiLayerStorage = MultiLayerStorage.builder() + .customerManagedS3Storage(managedS3Storage) + .build(); + + PutStorageConfigurationRequest storageConfigurationRequest = PutStorageConfigurationRequest.builder() + .storageType(StorageType.MULTI_LAYER_STORAGE) // Specify the storage type + .multiLayerStorage(multiLayerStorage) + .build(); + + try { + // Call the API to set the storage configuration + PutStorageConfigurationResponse response = getClient().putStorageConfiguration(storageConfigurationRequest); + System.out.println("Multi-layer storage configuration updated: " + response); + + // Optional: Check if cold storage is ready for bulk imports + checkStorageReadyForBulkImports(); + + } catch (InvalidRequestException e) { + System.err.println("Error creating bulk import job: " + e.getMessage()); + e.printStackTrace(); + } catch (IoTSiteWiseException e) { + System.err.println("Unexpected error occurred: " + e.getMessage()); + e.printStackTrace(); + } + } + + // Additional method to check if storage is ready for bulk imports + private static void checkStorageReadyForBulkImports() { + DescribeStorageConfigurationRequest request = DescribeStorageConfigurationRequest.builder().build(); + try { + DescribeStorageConfigurationResponse response = getClient().describeStorageConfiguration(request); + if (response.multiLayerStorage() != null) { + System.out.println("Cold tier storage is configured for bulk imports."); + } else { + System.out.println("Cold tier storage is NOT configured for bulk imports."); + } + } catch (IoTSiteWiseException e) { + System.err.println("Failed to describe storage configuration: " + e.getMessage()); + e.printStackTrace(); + } + } +} diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java new file mode 100644 index 00000000000..d0bce451ab9 --- /dev/null +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -0,0 +1,528 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.iotsitewise.scenario; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.services.iotsitewise.model.BatchPutAssetPropertyValueResponse; +import software.amazon.awssdk.services.iotsitewise.model.CreateGatewayRequest; +import software.amazon.awssdk.services.iotsitewise.model.CreateGatewayResponse; +import software.amazon.awssdk.services.iotsitewise.model.DeleteGatewayRequest; +import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayRequest; +import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayResponse; +import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.retry.RetryPolicy; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseAsyncClient; +import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseClient; +import software.amazon.awssdk.services.iotsitewise.model.AssetModelProperty; +import software.amazon.awssdk.services.iotsitewise.model.AssetModelPropertyDefinition; +import software.amazon.awssdk.services.iotsitewise.model.AssetModelSummary; +import software.amazon.awssdk.services.iotsitewise.model.AssetPropertyValue; +import software.amazon.awssdk.services.iotsitewise.model.BatchPutAssetPropertyValueRequest; +import software.amazon.awssdk.services.iotsitewise.model.CreateAssetModelRequest; +import software.amazon.awssdk.services.iotsitewise.model.CreateAssetModelResponse; +import software.amazon.awssdk.services.iotsitewise.model.CreateAssetRequest; +import software.amazon.awssdk.services.iotsitewise.model.CreateAssetResponse; +import software.amazon.awssdk.services.iotsitewise.model.CreatePortalRequest; +import software.amazon.awssdk.services.iotsitewise.model.CreatePortalResponse; +import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetModelRequest; +import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetModelResponse; +import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetRequest; +import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetResponse; +import software.amazon.awssdk.services.iotsitewise.model.DeletePortalRequest; +import software.amazon.awssdk.services.iotsitewise.model.DeletePortalResponse; +import software.amazon.awssdk.services.iotsitewise.model.DescribeAssetModelRequest; +import software.amazon.awssdk.services.iotsitewise.model.DescribePortalRequest; +import software.amazon.awssdk.services.iotsitewise.model.GatewayPlatform; +import software.amazon.awssdk.services.iotsitewise.model.GetAssetPropertyValueRequest; +import software.amazon.awssdk.services.iotsitewise.model.GetAssetPropertyValueResponse; +import software.amazon.awssdk.services.iotsitewise.model.GreengrassV2; +import software.amazon.awssdk.services.iotsitewise.model.ListAssetModelsRequest; +import software.amazon.awssdk.services.iotsitewise.model.Measurement; +import software.amazon.awssdk.services.iotsitewise.model.PropertyDataType; +import software.amazon.awssdk.services.iotsitewise.model.PropertyType; +import software.amazon.awssdk.services.iotsitewise.model.PutAssetPropertyValueEntry; +import software.amazon.awssdk.services.iotsitewise.model.TimeInNanos; +import software.amazon.awssdk.services.iotsitewise.model.Variant; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +public class SitewiseActions { + + private static final Logger logger = LoggerFactory.getLogger(SitewiseActions.class); + + private static IoTSiteWiseAsyncClient ioTSiteWiseAsyncClient; + + private static IoTSiteWiseAsyncClient getAsyncClient() { + if (ioTSiteWiseAsyncClient == null) { + SdkAsyncHttpClient httpClient = NettyNioAsyncHttpClient.builder() + .maxConcurrency(100) + .connectionTimeout(Duration.ofSeconds(60)) + .readTimeout(Duration.ofSeconds(60)) + .writeTimeout(Duration.ofSeconds(60)) + .build(); + + ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder() + .apiCallTimeout(Duration.ofMinutes(2)) + .apiCallAttemptTimeout(Duration.ofSeconds(90)) + .retryPolicy(RetryPolicy.builder() + .numRetries(3) + .build()) + .build(); + + ioTSiteWiseAsyncClient = IoTSiteWiseAsyncClient.builder() + .httpClient(httpClient) + .overrideConfiguration(overrideConfig) + .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) + .build(); + } + return ioTSiteWiseAsyncClient; + } + + private static IoTSiteWiseClient getClient() { + IoTSiteWiseClient client = IoTSiteWiseClient.builder() + .region(Region.US_EAST_1) + .build(); + + return client; + } + + // snippet-start:[sitewise.java2_create_asset_model.main] + /** + * Creates an asset model asynchronously. + * + * @param name the name of the asset model to create + * @return a {@link CompletableFuture} that completes with the created {@link CreateAssetModelResponse} when the operation is complete + */ + public CompletableFuture createAssetModelAsync(String name) { + PropertyType humidity = PropertyType.builder() + .measurement(Measurement.builder().build()) + .build(); + + PropertyType propertyType = PropertyType.builder() + .measurement(Measurement.builder().build()) + .build(); + + AssetModelPropertyDefinition temperatureProperty = AssetModelPropertyDefinition.builder() + .name("Temperature") + .dataType(PropertyDataType.DOUBLE) + .type(propertyType) + .build(); + + AssetModelPropertyDefinition humidityProperty = AssetModelPropertyDefinition.builder() + .name("Humidity") + .dataType(PropertyDataType.DOUBLE) + .type(humidity) + .build(); + + AssetModelPropertyDefinition measurementProperty = AssetModelPropertyDefinition.builder() + .name("Temperature") + .dataType(PropertyDataType.DOUBLE) + .type(temperatureProperty.type()) + .build(); + + CreateAssetModelRequest createAssetModelRequest = CreateAssetModelRequest.builder() + .assetModelName(name) + .assetModelDescription("This is my asset model") + .assetModelProperties(measurementProperty, humidityProperty) + .build(); + + return getAsyncClient().createAssetModel(createAssetModelRequest) + .handle((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to create asset model: " + exception.getMessage(), exception); + } + return response; + }); + } + + // snippet-end:[sitewise.java2_create_asset_model.main] + + // snippet-start:[sitewise.java2_create_asset.main] + /** + * Asynchronously creates an asset with the specified name and model ARN. + * + * @param assetName the name of the asset to create + * @param assetModelArn the ARN of the asset model to associate with the asset + * @return a {@link CompletableFuture} that completes with the {@link CreateAssetResponse} when the asset creation is complete + * @throws RuntimeException if the asset creation fails + */ + public CompletableFuture createAssetAsync(String assetName, String assetModelArn) { + CreateAssetRequest createAssetRequest = CreateAssetRequest.builder() + .assetModelId(assetModelArn) + .assetDescription("Created using the AWS SDK for Java") + .assetName(assetName) + .build(); + + return getAsyncClient().createAsset(createAssetRequest) + .handle((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to create asset: " + exception.getMessage(), exception); + } + return response; // Return the response if successful + }); + } + // snippet-end:[sitewise.java2_create_asset.main] + + // snippet-start:[sitewise.java2_put_property.main] + public CompletableFuture sendDataToSiteWiseAsync(String assetId, String humPropId, String idHum) { + Map sampleData = generateSampleData(); + long timestamp = Instant.now().toEpochMilli(); + + TimeInNanos time = TimeInNanos.builder() + .timeInSeconds(timestamp / 1000) + .offsetInNanos((int) ((timestamp % 1000) * 1000000)) + .build(); + + BatchPutAssetPropertyValueRequest request = BatchPutAssetPropertyValueRequest.builder() + .entries(Arrays.asList( + PutAssetPropertyValueEntry.builder() + .entryId("entry-3") + .assetId(assetId) + .propertyId(humPropId) + .propertyValues(Arrays.asList( + AssetPropertyValue.builder() + .value(Variant.builder() + .doubleValue(sampleData.get("Temperature")) + .build()) + .timestamp(time) + .build() + )) + .build(), + PutAssetPropertyValueEntry.builder() + .entryId("entry-4") + .assetId(assetId) + .propertyId(idHum) + .propertyValues(Arrays.asList( + AssetPropertyValue.builder() + .value(Variant.builder() + .doubleValue(sampleData.get("Humidity")) + .build()) + .timestamp(time) + .build() + )) + .build() + )) + .build(); + + return getAsyncClient().batchPutAssetPropertyValue(request) + .whenComplete((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to send data to SiteWise: " + exception.getMessage(), exception); + } else { + logger.info("Data sent successfully."); + } + }); + } + // snippet-end:[sitewise.java2_put_property.main] + + // snippet-start:[sitewise.java2_get_property.main] + public void getAssetPropValueAsync(String propName, String propId, String assetId) { + GetAssetPropertyValueRequest assetPropertyValueRequest = GetAssetPropertyValueRequest.builder() + .propertyId(propId) + .assetId(assetId) + .build(); + + CompletableFuture futureResponse = getAsyncClient().getAssetPropertyValue(assetPropertyValueRequest); + futureResponse.whenComplete((response, exception) -> { + if (exception != null) { + // Handle the exception, rethrow as RuntimeException or log it + throw new RuntimeException("Error occurred while fetching property value: " + exception.getMessage(), exception); + } else { + // Process the response + String assetPropName = response.toString(); + String assetVal = String.valueOf(response.propertyValue().value().doubleValue()); + + logger.info("The property name is: " + propName); + logger.info("The value of this property is " + assetVal); + } + }).join(); // You can remove this join() if you don't need to block the thread. + } + // snippet-end:[sitewise.java2_get_property.main] + + // snippet-start:[sitewise.java2.describe.asset.model.main] + /** + * Finds the property ID of a given property name asynchronously. + * + * @param propertyName the name of the property to search for + * @return a {@link CompletableFuture} that completes with the property ID if found, or null if not found + * @throws RuntimeException if an exception occurs during the search + */ + public CompletableFuture findPropertyIdByNameAsync(String propertyName) { + ListAssetModelsRequest listRequest = ListAssetModelsRequest.builder().build(); + + return getAsyncClient().listAssetModels(listRequest) + .thenCompose(listResponse -> { + List> futures = new ArrayList<>(); + for (AssetModelSummary modelSummary : listResponse.assetModelSummaries()) { + DescribeAssetModelRequest describeRequest = DescribeAssetModelRequest.builder() + .assetModelId(modelSummary.id()) + .build(); + + CompletableFuture future = getAsyncClient().describeAssetModel(describeRequest) + .thenApply(describeResponse -> { + for (AssetModelProperty property : describeResponse.assetModelProperties()) { + if (property.name().equals(propertyName)) { + return property.id(); + } + } + return null; // Continue searching in other models if not found + }); + + futures.add(future); + } + + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .thenApply(v -> { + for (CompletableFuture future : futures) { + String propertyId = future.join(); + if (propertyId != null) { + return propertyId; + } + } + return null; + }); + }) + .handle((propertyId, exception) -> { + if (exception != null) { + // Handle exception, log it, or rethrow + throw new RuntimeException("Failed to find property by name: " + exception.getMessage(), exception); + } + return propertyId; + }); + } + // snippet-end:[sitewise.java2.describe.asset.model.main] + + // snippet-start:[sitewise.java2.delete.asset.main] + /** + * Deletes an asset asynchronously. + * + * @param assetId the ID of the asset to be deleted + * @return a {@link CompletableFuture} that represents the asynchronous operation of deleting the asset + * @throws RuntimeException if the asset deletion fails + */ + public CompletableFuture deleteAssetAsync(String assetId) { + DeleteAssetRequest deleteAssetRequest = DeleteAssetRequest.builder() + .assetId(assetId) + .build(); + + return getAsyncClient().deleteAsset(deleteAssetRequest) + .whenComplete((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to delete asset with ID: " + assetId + ". Error: " + exception.getMessage(), exception); + } + }); + } + // snippet-end:[sitewise.java2.delete.asset.main] + + // snippet-start:[sitewise.java2.delete.asset.model.main] + /** + * Asynchronously deletes an Asset Model with the specified ID. + * + * @param assetModelId the ID of the Asset Model to delete + * @return a {@link CompletableFuture} that completes with the {@link DeleteAssetModelResponse} when the operation is complete + * @throws RuntimeException if the operation fails, containing the error message and the underlying exception + */ + public CompletableFuture deleteAssetModelAsync(String assetModelId) { + DeleteAssetModelRequest deleteAssetModelRequest = DeleteAssetModelRequest.builder() + .assetModelId(assetModelId) + .build(); + + return getAsyncClient().deleteAssetModel(deleteAssetModelRequest) + .whenComplete((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to delete asset model with ID: " + assetModelId + ". Error: " + exception.getMessage(), exception); + } + }); + } + // snippet-end:[sitewise.java2.delete.asset.model.main] + + // snippet-start:[sitewise.java2.create.portal.main] + /** + * Creates a new IoT SiteWise portal asynchronously. + * + * @param portalName the name of the portal to create + * @param iamRole the IAM role ARN to use for the portal + * @param contactEmail the email address of the portal contact + * @return a {@link CompletableFuture} that completes with the portal ID when the portal is created successfully, or throws a {@link RuntimeException} if the creation fails + */ + public CompletableFuture createPortalAsync(String portalName, String iamRole, String contactEmail) { + CreatePortalRequest createPortalRequest = CreatePortalRequest.builder() + .portalName(portalName) + .portalDescription("This is my custom IoT SiteWise portal.") + .portalContactEmail(contactEmail) + .roleArn(iamRole) + .build(); + + return getAsyncClient().createPortal(createPortalRequest) + .thenApply(CreatePortalResponse::portalId) + .whenComplete((portalId, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to create portal with name: " + portalName + ". Error: " + exception.getMessage(), exception); + } + }); + } + // snippet-end:[sitewise.java2.create.portal.main] + + // snippet-start:[sitewise.java2.delete.portal.main] + /** + * Deletes a portal asynchronously. + * + * @param portalId the ID of the portal to be deleted + * @return a {@link CompletableFuture} containing the {@link DeletePortalResponse} when the operation is complete + * @throws RuntimeException if the portal deletion fails, with the error message and the underlying exception + */ + public CompletableFuture deletePortalAsync(String portalId) { + DeletePortalRequest deletePortalRequest = DeletePortalRequest.builder() + .portalId(portalId) + .build(); + + return getAsyncClient().deletePortal(deletePortalRequest) + .whenComplete((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to delete portal with ID: " + portalId + ". Error: " + exception.getMessage(), exception); + } + }); + } + // snippet-end:[sitewise.java2.delete.portal.main] + + // snippet-start:[sitewise.java2.list.asset.model.main] + /** + * Retrieves the asset model ID asynchronously for the given asset model name. + * + * @param assetModelName the name of the asset model to retrieve the ID for + * @return a {@link CompletableFuture} that, when completed, contains the asset model ID, or {@code null} if the asset model is not found + */ + public CompletableFuture getAssetModelIdAsync(String assetModelName) { + ListAssetModelsRequest listAssetModelsRequest = ListAssetModelsRequest.builder().build(); + return getAsyncClient().listAssetModels(listAssetModelsRequest) + .handle((listAssetModelsResponse, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to retrieve Asset Model ARN: " + exception.getMessage(), exception); + } + for (AssetModelSummary assetModelSummary : listAssetModelsResponse.assetModelSummaries()) { + if (assetModelSummary.name().equals(assetModelName)) { + return assetModelSummary.id(); // Return the ARN if found. + } + } + return null; + }); + } + // snippet-end:[sitewise.java2.list.asset.model.main] + + // snippet-start:[sitewise.java2.describe.portal.main] + /** + * Asynchronously describes a portal. + * + * @param portalId the ID of the portal to describe + * @return a {@link CompletableFuture} that, when completed, will contain the URL of the described portal + * @throws RuntimeException if the portal description operation fails + */ + public CompletableFuture describePortalAsync(String portalId) { + DescribePortalRequest request = DescribePortalRequest.builder() + .portalId(portalId) + .build(); + + return getAsyncClient().describePortal(request) + .handle((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to describe portal: " + exception.getMessage(), exception); + } + // Return the portal URL if the operation is successful + return response.portalStartUrl(); + }); + } + // snippet-start:[sitewise.java2.describe.portal.main] + + // snippet-start:[sitewise.java2.create.gateway.main] + /** + * Creates a new IoTSitewise gateway asynchronously. + * + * @return a {@link CompletableFuture} containing the {@link CreateGatewayResponse} representing the created gateway + * @throws RuntimeException if there was an error creating the gateway + */ + public CompletableFuture createGatewayAsync(String gatewayName, String myThing) { + GreengrassV2 gg = GreengrassV2.builder() + .coreDeviceThingName(myThing) + .build(); + + GatewayPlatform platform = GatewayPlatform.builder() + .greengrassV2(gg) + .build(); + + Map tag = new HashMap<>(); + tag.put("Environment", "Production"); + + CreateGatewayRequest createGatewayRequest = CreateGatewayRequest.builder() + .gatewayName(gatewayName) + .gatewayPlatform(platform) + .tags(tag) + .build(); + + return getAsyncClient().createGateway(createGatewayRequest) + .handle((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Error creating gateway", exception); + } + System.out.println("The ARN of the gateway is " + response.gatewayArn()); + return response; + }); + } + // snippet-end:[sitewise.java2.create.gateway.main] + + // snippet-start:[sitewise.java2.delete.gateway.main] + public CompletableFuture deleteGatewayAsync(String gatewayARN) { + DeleteGatewayRequest deleteGatewayRequest = DeleteGatewayRequest.builder() + .gatewayId(gatewayARN) + .build(); + + getAsyncClient().deleteGateway(deleteGatewayRequest) + .whenComplete((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Error creating gateway", exception); + } else { + System.out.println("The Gateway was deleted successfully"); + } + }); + return null; + } + // snippet-end:[sitewise.java2.delete.gateway.main] + + // snippet-start:[sitewise.java2.describe.gateway.main] + public CompletableFuture describeGatewayAsync(String gatewayId) { + DescribeGatewayRequest request = DescribeGatewayRequest.builder() + .gatewayId(gatewayId) + .build(); + + return getAsyncClient().describeGateway(request) + .handle((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to describe the SiteWise gateway", exception); + } + System.out.println("Gateway Name: " + response.gatewayName()); + System.out.println("Gateway ARN: " + response.gatewayArn()); + System.out.println("Gateway Platform: " + response.gatewayPlatform().toString()); + System.out.println("Gateway Creation Date: " + response.creationDate()); + return response; + }); + } + // snippet-end:[sitewise.java2.describe.gateway.main] + + private static Map generateSampleData() { + Map data = new HashMap<>(); + data.put("Temperature", 23.5); + data.put("Humidity", 65.0); + return data; + } +} diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java new file mode 100644 index 00000000000..94e51dd4f2d --- /dev/null +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -0,0 +1,441 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.iotsitewise.scenario; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.services.iotsitewise.model.BatchPutAssetPropertyValueResponse; +import software.amazon.awssdk.services.iotsitewise.model.CreateAssetModelResponse; +import software.amazon.awssdk.services.iotsitewise.model.CreateAssetResponse; +import software.amazon.awssdk.services.iotsitewise.model.CreateGatewayResponse; +import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetModelResponse; +import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetResponse; +import software.amazon.awssdk.services.iotsitewise.model.DeletePortalResponse; +import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayResponse; +import software.amazon.awssdk.services.iotsitewise.model.IoTSiteWiseException; +import software.amazon.awssdk.services.iotsitewise.model.ResourceAlreadyExistsException; +import software.amazon.awssdk.services.ssm.model.ResourceNotFoundException; + +import java.util.Scanner; +import java.util.concurrent.CompletableFuture; + +public class SitewiseScenario { + + public static final String DASHES = new String(new char[80]).replace("\0", "-"); + + private static final Logger logger = LoggerFactory.getLogger(SitewiseScenario.class); + static Scanner scanner = new Scanner(System.in); + + static SitewiseActions sitewiseActions = new SitewiseActions(); + + public static void main(String[] args) throws Throwable { + Scanner scanner = new Scanner(System.in); + String assetModelName = "MyAssetModel2"; + String assetName = "MyAsset"; + String iamRole = "arn:aws:iam::814548047983:role/service-role/AWSIoTSiteWiseMonitorServiceRole_8jLqg43nJ"; + String portalName = "MyPortal"; + String contactEmail = "scmacdon@amazon.com"; + String gatewayName = "myGateway11"; + String myThing = "myThing78"; + + logger.info(""" + AWS IoT SiteWise is a fully managed industrial software-as-a-service (SaaS) that + makes it easy to collect, store, organize, and monitor data from industrial equipment and processes. + It is designed to help industrial and manufacturing organizations collect data from their equipment and + processes, and use that data to make informed decisions about their operations. + + One of the key features of AWS IoT SiteWise is its ability to connect to a wide range of industrial + equipment and systems, including programmable logic controllers (PLCs), sensors, and other + industrial devices. It can collect data from these devices and organize it into a unified data model, + making it easier to analyze and gain insights from the data. AWS IoT SiteWise also provides tools for + visualizing the data, setting up alarms and alerts, and generating reports. + + Another key feature of AWS IoT SiteWise is its ability to scale to handle large volumes of data. + It can collect and store data from thousands of devices and process millions of data points per second, + making it suitable for large-scale industrial operations. Additionally, AWS IoT SiteWise is designed + to be secure and compliant, with features like role-based access controls, data encryption, + and integration with other AWS services for additional security and compliance features. + + Let's get started... + """); + + waitForInputToContinue(scanner); + logger.info(DASHES); + + try { + runScenario(assetModelName, assetName, iamRole, portalName, contactEmail, gatewayName, myThing); + } catch (RuntimeException e) { + logger.info(e.getMessage()); + } + } + + public static void runScenario(String assetModelName, String assetName, String iamRole, String portalName, String contactEmail, String gatewayName, String myThing) throws Throwable { + logger.info(DASHES); + logger.info("1. Create an AWS SiteWise Asset Model"); + logger.info(""" + An AWS IoT SiteWise Asset Model is a way to represent the physical assets, such as equipment, + processes, and systems, that exist in an industrial environment. This model provides a structured and + hierarchical representation of these assets, allowing users to define the relationships and properties + of each asset. + """); + waitForInputToContinue(scanner); + String assetModelId = ""; + try { + CompletableFuture future = sitewiseActions.createAssetModelAsync(assetModelName); + CreateAssetModelResponse response = future.join(); + assetModelId = response.assetModelId(); + logger.info("Asset Model successfully created. Asset Model ID: {}. ", assetModelId); + + } catch (RuntimeException rt) { + Throwable cause = rt; + + // Unwrap nested exceptions to find the root cause. + while (cause.getCause() != null && !(cause instanceof ResourceAlreadyExistsException)) { + cause = cause.getCause(); + } + if (cause instanceof ResourceAlreadyExistsException) { + assetModelId = sitewiseActions.getAssetModelIdAsync(assetModelName).join(); + logger.info("The Asset Model {} already exists. The id of the existing model is {}. Moving on...", assetModelName, assetModelId); + } else { + // Log unexpected errors + logger.info("An unexpected error occurred: " + rt.getMessage(), rt); + throw cause; + } + } + waitForInputToContinue(scanner); + + logger.info(DASHES); + logger.info("2. Create an AWS IoT SiteWise Asset"); + logger.info(""" + The IoT SiteWise model defines the structure and metadata for your physical assets. Now we + can use the asset model to create the asset. + + """); + waitForInputToContinue(scanner); + String assetId = ""; + try { + CompletableFuture future = sitewiseActions.createAssetAsync(assetName, assetModelId); + CreateAssetResponse response = future.join(); + assetId = response.assetId(); + logger.info("Asset created with ID: " + assetId); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + // Unwrap nested exceptions to find the root cause. + while (cause != null) { + if (cause instanceof software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException) { + logger.info("The AWS resource was not found: {}", cause.getMessage()); + break; + } + cause = cause.getCause(); + } + + if (cause == null) { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("3. Retrieve the property ID values"); + logger.info(""" + To send data to an asset, we need to get the property ID values for the + Temperature and Humidity properties. + """); + waitForInputToContinue(scanner); + + String humPropId = ""; + try { + CompletableFuture future = sitewiseActions.findPropertyIdByNameAsync("Humidity"); + humPropId = future.join(); + logger.info("The Humidity property Id is {}", humPropId); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof IoTSiteWiseException siteWiseEx) { + logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: " + rt.getMessage()); + } + throw cause; + } + + String tempPropId; + try { + CompletableFuture future = sitewiseActions.findPropertyIdByNameAsync("Temperature"); + tempPropId = future.join(); + logger.info("The Temperature property Id is {}", tempPropId); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof IoTSiteWiseException siteWiseEx) { + logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: " + rt.getMessage()); + } + throw cause; + } + + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("4. Send data to an AWS IoT SiteWise Asset"); + logger.info(""" + By sending data to an IoT SiteWise Asset, you can aggregate data from + multiple sources, normalize the data into a standard format, and store it in a + centralized location. This makes it easier to analyze and gain insights from the data. + + This example demonstrate how to generate sample data and ingest it into the AWS IoT SiteWise asset. + + """); + waitForInputToContinue(scanner); + try { + CompletableFuture future = sitewiseActions.sendDataToSiteWiseAsync(assetId, tempPropId, humPropId); + future.join(); + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + while (cause != null) { + if (cause instanceof software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException) { + logger.info("The AWS resource was not found: {}", cause.getMessage()); + break; + } + cause = cause.getCause(); + } + + if (cause == null) { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("5. Retrieve the value of the IoT SiteWise Asset property"); + logger.info(""" + IoT SiteWise is an AWS service that allows you to collect, process, and analyze industrial data + from connected equipment and sensors. One of the key benefits of reading an IoT SiteWise property + is the ability to gain valuable insights from your industrial data. + + """); + waitForInputToContinue(scanner); + try { + sitewiseActions.getAssetPropValueAsync("Temperature property", tempPropId, assetId); + waitForInputToContinue(scanner); + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + while (cause != null) { + if (cause instanceof software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException) { + logger.info("The AWS resource was not found: {}", cause.getMessage()); + break; + } + cause = cause.getCause(); + } + + if (cause == null) { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + + throw cause; + } + sitewiseActions.getAssetPropValueAsync("Humidity property", humPropId, assetId); + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("6. Create an IoT SiteWise Portal"); + logger.info(""" + An IoT SiteWise Portal allows you to aggregate data from multiple industrial sources, + such as sensors, equipment, and control systems, into a centralized platform. + """); + waitForInputToContinue(scanner); + String portalId = ""; + try { + CompletableFuture future = sitewiseActions.createPortalAsync(portalName, iamRole, contactEmail); + portalId = future.join(); + logger.info("Portal created successfully. Portal ID {}", portalId); + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof IoTSiteWiseException siteWiseEx) { + logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: " + rt.getMessage()); + } + } + logger.info("The portal Id is " + portalId); + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("7. Describe the Portal"); + logger.info(""" + In this step, we will describe the step and provide the portal URL. + """); + waitForInputToContinue(scanner); + try { + CompletableFuture future = sitewiseActions.describePortalAsync(portalId); + String portalUrl = future.join(); + logger.info("Portal URL: {}", portalUrl); + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof IoTSiteWiseException siteWiseEx) { + logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: " + rt.getMessage()); + } + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("8. Create an IoTSitewise Gateway"); + logger.info( + """ + IoTSitewise Gateway serves as the bridge between industrial equipment, sensors, and the + cloud-based IoTSitewise service. It is responsible for securely collecting, processing, and + transmitting data from various industrial assets to the IoTSitewise platform, + enabling real-time monitoring, analysis, and optimization of industrial operations. + + """); + waitForInputToContinue(scanner); + String gatewayId = ""; + try { + CompletableFuture future = sitewiseActions.createGatewayAsync(gatewayName, myThing); + CreateGatewayResponse response = future.join(); + gatewayId = response.gatewayId(); + logger.info("Gateway creation completed successfully. id is {}",gatewayId ); + } catch (RuntimeException e) { + System.err.println("Failed to create gateway: " + e.getMessage()); + } + logger.info(DASHES); + + + logger.info(DASHES); + logger.info("9. Describe the IoTSitewise Gateway"); + waitForInputToContinue(scanner); + try { + CompletableFuture future = sitewiseActions.describeGatewayAsync(gatewayId) ; + future.join(); + + } catch (RuntimeException e) { + System.err.println("Failed to create gateway: " + e.getMessage()); + } + logger.info(DASHES); + + logger.info(DASHES); + logger.info("10. Delete the AWS IoT SiteWise Assets"); + logger.info( + """ + Before you can delete the Asset Model, you must delete the assets. + + """); + logger.info("Would you like to delete the IoT Sitewise Assets? (y/n)"); + String delAns = scanner.nextLine().trim(); + if (delAns.equalsIgnoreCase("y")) { + logger.info("You selected to delete the Sitewise assets."); + waitForInputToContinue(scanner); + try { + CompletableFuture future = sitewiseActions.deletePortalAsync(portalId); + future.join(); + logger.info("Portal {} was deleted successfully.", portalId); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof IoTSiteWiseException siteWiseEx) { + logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: " + rt.getMessage()); + } + } + + // Delete the Gateway. + try { + CompletableFuture future = sitewiseActions.deleteGatewayAsync(gatewayId); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof IoTSiteWiseException siteWiseEx) { + logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: " + rt.getMessage()); + } + } + + try { + CompletableFuture future = sitewiseActions.deleteAssetAsync(assetId); + future.join(); + logger.info("Asset deleted successfully."); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof IoTSiteWiseException siteWiseEx) { + logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: " + rt.getMessage()); + } + } + logger.info("Lets wait 1 min for the asset to be deleted"); + countdown(1); + waitForInputToContinue(scanner); + logger.info("Delete the AWS IoT SiteWise Asset Model"); + try { + CompletableFuture future = sitewiseActions.deleteAssetModelAsync(assetModelId); + future.join(); + logger.info("Asset model deleted successfully."); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof IoTSiteWiseException siteWiseEx) { + logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: " + rt.getMessage()); + } + } + waitForInputToContinue(scanner); + + } else { + logger.info("The resources will not be deleted."); + } + logger.info(DASHES); + + logger.info(DASHES); + logger.info("This concludes the AWS SiteWise Scenario"); + logger.info(DASHES); + } + + private static void waitForInputToContinue(Scanner scanner) { + while (true) { + System.out.println(""); + System.out.println("Enter 'c' followed by to continue:"); + String input = scanner.nextLine(); + + if (input.trim().equalsIgnoreCase("c")) { + System.out.println("Continuing with the program..."); + System.out.println(""); + break; + } else { + // Handle invalid input. + System.out.println("Invalid input. Please try again."); + } + } + } + + public static void countdown(int minutes) throws InterruptedException { + int seconds = 0; + for (int i = minutes * 60 + seconds; i >= 0; i--) { + int displayMinutes = i / 60; + int displaySeconds = i % 60; + System.out.print(String.format("\r%02d:%02d", displayMinutes, displaySeconds)); + Thread.sleep(1000); // Wait for 1 second + } + + System.out.println("Countdown complete!"); + } +} diff --git a/javav2/example_code/iotsitewise/src/main/resources/data.json b/javav2/example_code/iotsitewise/src/main/resources/data.json new file mode 100644 index 00000000000..2cdbfb2feb0 --- /dev/null +++ b/javav2/example_code/iotsitewise/src/main/resources/data.json @@ -0,0 +1,44 @@ +{ + "assets": [ + { + "name": "Temperature", + "description": "Measures the ambient temperature", + "properties": [ + { + "name": "value", + "type": "number", + "unit": "°C", + "description": "The current temperature reading", + "value": 25.6 + }, + { + "name": "timestamp", + "type": "string", + "format": "date-time", + "description": "The timestamp of the temperature reading", + "value": "2024-09-09T12:30:00Z" + } + ] + }, + { + "name": "Humidity", + "description": "Measures the ambient humidity", + "properties": [ + { + "name": "value", + "type": "number", + "unit": "%", + "description": "The current humidity reading", + "value": 45.3 + }, + { + "name": "timestamp", + "type": "string", + "format": "date-time", + "description": "The timestamp of the humidity reading", + "value": "2024-09-09T12:35:00Z" + } + ] + } + ] +} diff --git a/javav2/example_code/iotsitewise/src/main/resources/log4j2.xml b/javav2/example_code/iotsitewise/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..225afe2b3a8 --- /dev/null +++ b/javav2/example_code/iotsitewise/src/main/resources/log4j2.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file From da03f63d8cce438c657fedce9264158e01fa3c8c Mon Sep 17 00:00:00 2001 From: scmacdon Date: Tue, 17 Sep 2024 09:11:16 -0400 Subject: [PATCH 02/41] updated Java file --- javav2/example_code/iotsitewise/.gitignore | 38 ----- javav2/example_code/iotsitewise/README.md | 153 ++++++++++++++++++ .../scenario/SitewiseScenario.java | 3 +- 3 files changed, 154 insertions(+), 40 deletions(-) delete mode 100644 javav2/example_code/iotsitewise/.gitignore create mode 100644 javav2/example_code/iotsitewise/README.md diff --git a/javav2/example_code/iotsitewise/.gitignore b/javav2/example_code/iotsitewise/.gitignore deleted file mode 100644 index 5ff6309b719..00000000000 --- a/javav2/example_code/iotsitewise/.gitignore +++ /dev/null @@ -1,38 +0,0 @@ -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### IntelliJ IDEA ### -.idea/modules.xml -.idea/jarRepositories.xml -.idea/compiler.xml -.idea/libraries/ -*.iws -*.iml -*.ipr - -### Eclipse ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ - -### Mac OS ### -.DS_Store \ No newline at end of file diff --git a/javav2/example_code/iotsitewise/README.md b/javav2/example_code/iotsitewise/README.md new file mode 100644 index 00000000000..7a8cff90e3c --- /dev/null +++ b/javav2/example_code/iotsitewise/README.md @@ -0,0 +1,153 @@ +# Amazon EC2 code examples for the SDK for Java 2.x + +## Overview + +Shows how to use the AWS SDK for Java 2.x to work with Amazon Elastic Compute Cloud (Amazon EC2). + + + + +_Amazon EC2 is a web service that provides resizable computing capacity—literally, servers in Amazon's data centers—that you use to build and host your software systems._ + +## ⚠ Important + +* Running this code might result in charges to your AWS account. For more details, see [AWS Pricing](https://aws.amazon.com/pricing/) and [Free Tier](https://aws.amazon.com/free/). +* Running the tests might result in charges to your AWS account. +* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege). +* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services). + + + + +## Code examples + +### Prerequisites + +For prerequisites, see the [README](../../README.md#Prerequisites) in the `javav2` folder. + + + + + +### Get started + +- [Hello Amazon EC2](src/main/java/com/example/ec2/scenario/EC2Actions.java#L468) (`DescribeSecurityGroups`) + + +### Basics + +Code examples that show you how to perform the essential operations within a service. + +- [Learn the basics](src/main/java/com/example/ec2/scenario/EC2Scenario.java) + + +### Single actions + +Code excerpts that show you how to call individual service functions. + +- [AllocateAddress](src/main/java/com/example/ec2/scenario/EC2Actions.java#L265) +- [AssociateAddress](src/main/java/com/example/ec2/scenario/EC2Actions.java#L235) +- [AuthorizeSecurityGroupIngress](src/main/java/com/example/ec2/scenario/EC2Actions.java#L505) +- [CreateKeyPair](src/main/java/com/example/ec2/scenario/EC2Actions.java#L585) +- [CreateSecurityGroup](src/main/java/com/example/ec2/scenario/EC2Actions.java#L505) +- [DeleteKeyPair](src/main/java/com/example/ec2/scenario/EC2Actions.java#L106) +- [DeleteSecurityGroup](src/main/java/com/example/ec2/scenario/EC2Actions.java#L132) +- [DescribeInstanceTypes](src/main/java/com/example/ec2/scenario/EC2Actions.java#L356) +- [DescribeInstances](src/main/java/com/example/ec2/scenario/EC2Actions.java#L402) +- [DescribeKeyPairs](src/main/java/com/example/ec2/scenario/EC2Actions.java#L566) +- [DescribeSecurityGroups](src/main/java/com/example/ec2/scenario/EC2Actions.java#L468) +- [DisassociateAddress](src/main/java/com/example/ec2/scenario/EC2Actions.java#L207) +- [GetPasswordData](src/main/java/com/example/ec2/GetPasswordData.java#L6) +- [ReleaseAddress](src/main/java/com/example/ec2/scenario/EC2Actions.java#L184) +- [RunInstances](src/main/java/com/example/ec2/scenario/EC2Actions.java#L319) +- [StartInstances](src/main/java/com/example/ec2/scenario/EC2Actions.java#L696) +- [StopInstances](src/main/java/com/example/ec2/scenario/EC2Actions.java#L653) +- [TerminateInstances](src/main/java/com/example/ec2/scenario/EC2Actions.java#L155) + +### Scenarios + +Code examples that show you how to accomplish a specific task by calling multiple +functions within the same service. + +- [Build and manage a resilient service](../../usecases/resilient_service/src/main/java/com/example/resilient/Main.java) + + + + + +## Run the examples + +### Instructions + + + + + +#### Hello Amazon EC2 + +This example shows you how to get started using Amazon EC2. + + +#### Learn the basics + +This example shows you how to do the following: + +- Create a key pair and security group. +- Select an Amazon Machine Image (AMI) and compatible instance type, then create an instance. +- Stop and restart the instance. +- Associate an Elastic IP address with your instance. +- Connect to your instance with SSH, then clean up resources. + + + + + + + + + +#### Build and manage a resilient service + +This example shows you how to create a load-balanced web service that returns book, movie, and song recommendations. The example shows how the service responds to failures, and how to restructure the service for more resilience when failures occur. + +- Use an Amazon EC2 Auto Scaling group to create Amazon Elastic Compute Cloud (Amazon EC2) instances based on a launch template and to keep the number of instances in a specified range. +- Handle and distribute HTTP requests with Elastic Load Balancing. +- Monitor the health of instances in an Auto Scaling group and forward requests only to healthy instances. +- Run a Python web server on each EC2 instance to handle HTTP requests. The web server responds with recommendations and health checks. +- Simulate a recommendation service with an Amazon DynamoDB table. +- Control web server response to requests and health checks by updating AWS Systems Manager parameters. + + + + + + + + +### Tests + +⚠ Running tests might result in charges to your AWS account. + + +To find instructions for running these tests, see the [README](../../README.md#Tests) +in the `javav2` folder. + + + + + + +## Additional resources + +- [Amazon EC2 User Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html) +- [Amazon EC2 API Reference](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Welcome.html) +- [SDK for Java 2.x Amazon EC2 reference](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/package-summary.html) + + + + +--- + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 \ No newline at end of file diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index 94e51dd4f2d..66ffe3ff16d 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -148,7 +148,7 @@ public static void runScenario(String assetModelName, String assetName, String """); waitForInputToContinue(scanner); - String humPropId = ""; + String humPropId; try { CompletableFuture future = sitewiseActions.findPropertyIdByNameAsync("Humidity"); humPropId = future.join(); @@ -241,7 +241,6 @@ public static void runScenario(String assetModelName, String assetName, String if (cause == null) { logger.info("An unexpected error occurred: {}", rt.getMessage()); } - throw cause; } sitewiseActions.getAssetPropValueAsync("Humidity property", humPropId, assetId); From b8a57c5581443da570c6b1a81bd5f6e50fb4e30f Mon Sep 17 00:00:00 2001 From: scmacdon Date: Tue, 17 Sep 2024 13:38:03 -0400 Subject: [PATCH 03/41] updated Java Scenario --- .../iotsitewise/scenario/SitewiseScenario.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index 66ffe3ff16d..3c1607a09fb 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -15,7 +15,6 @@ import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayResponse; import software.amazon.awssdk.services.iotsitewise.model.IoTSiteWiseException; import software.amazon.awssdk.services.iotsitewise.model.ResourceAlreadyExistsException; -import software.amazon.awssdk.services.ssm.model.ResourceNotFoundException; import java.util.Scanner; import java.util.concurrent.CompletableFuture; @@ -89,8 +88,6 @@ public static void runScenario(String assetModelName, String assetName, String } catch (RuntimeException rt) { Throwable cause = rt; - - // Unwrap nested exceptions to find the root cause. while (cause.getCause() != null && !(cause instanceof ResourceAlreadyExistsException)) { cause = cause.getCause(); } @@ -98,7 +95,6 @@ public static void runScenario(String assetModelName, String assetName, String assetModelId = sitewiseActions.getAssetModelIdAsync(assetModelName).join(); logger.info("The Asset Model {} already exists. The id of the existing model is {}. Moving on...", assetModelName, assetModelId); } else { - // Log unexpected errors logger.info("An unexpected error occurred: " + rt.getMessage(), rt); throw cause; } @@ -113,12 +109,12 @@ public static void runScenario(String assetModelName, String assetName, String """); waitForInputToContinue(scanner); - String assetId = ""; + String assetId; try { CompletableFuture future = sitewiseActions.createAssetAsync(assetName, assetModelId); CreateAssetResponse response = future.join(); assetId = response.assetId(); - logger.info("Asset created with ID: " + assetId); + logger.info("Asset created with ID: {}", assetId); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); @@ -134,7 +130,6 @@ public static void runScenario(String assetModelName, String assetName, String if (cause == null) { logger.info("An unexpected error occurred: {}", rt.getMessage()); } - throw cause; } waitForInputToContinue(scanner); @@ -310,7 +305,7 @@ public static void runScenario(String assetModelName, String assetName, String gatewayId = response.gatewayId(); logger.info("Gateway creation completed successfully. id is {}",gatewayId ); } catch (RuntimeException e) { - System.err.println("Failed to create gateway: " + e.getMessage()); + logger.info("Failed to create gateway: {} ", e.getMessage()); } logger.info(DASHES); From fe55670f62164e123ee505fe280964a680c8325f Mon Sep 17 00:00:00 2001 From: scmacdon Date: Tue, 17 Sep 2024 18:17:37 -0400 Subject: [PATCH 04/41] update tag --- .../java/com/example/iotsitewise/scenario/SitewiseActions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index d0bce451ab9..6f735ecf9c0 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -443,7 +443,7 @@ public CompletableFuture describePortalAsync(String portalId) { return response.portalStartUrl(); }); } - // snippet-start:[sitewise.java2.describe.portal.main] + // snippet-end:[sitewise.java2.describe.portal.main] // snippet-start:[sitewise.java2.create.gateway.main] /** From 121a654419fc600407c3d3c29af977b8a6c877ff Mon Sep 17 00:00:00 2001 From: scmacdon Date: Tue, 17 Sep 2024 19:11:11 -0400 Subject: [PATCH 05/41] added sitewise yaml --- .doc_gen/metadata/iot_sitewise_metadata.yaml | 19 +++++++++++++++++++ .../iotsitewise/scenario/SitewiseActions.java | 13 +++++++------ .../scenario/SitewiseScenario.java | 4 ++-- 3 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 .doc_gen/metadata/iot_sitewise_metadata.yaml diff --git a/.doc_gen/metadata/iot_sitewise_metadata.yaml b/.doc_gen/metadata/iot_sitewise_metadata.yaml new file mode 100644 index 00000000000..ffd4b07c9fa --- /dev/null +++ b/.doc_gen/metadata/iot_sitewise_metadata.yaml @@ -0,0 +1,19 @@ +# zexi 0.4.0 +iotsitewise_Scenario: + synopsis: Learn core operations for &ITSWlong; using an &AWS; SDK + category: Basics + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + sdkguide: + excerpts: + - description: Run an interactive scenario demonstrating &ITSW; features. + snippet_tags: + - iotsitewise.java2.scenario.main + - description: A wrapper class for &ITSW; SDK methods. + snippet_tags: + - iotsitewise.java2.actions.main + services: + iotsitewise: {} diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index 6f735ecf9c0..a6aa2375571 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -58,6 +58,7 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; +// snippet-start:[iotsitewise.java2.actions.main] public class SitewiseActions { private static final Logger logger = LoggerFactory.getLogger(SitewiseActions.class); @@ -296,7 +297,6 @@ public CompletableFuture findPropertyIdByNameAsync(String propertyName) }) .handle((propertyId, exception) -> { if (exception != null) { - // Handle exception, log it, or rethrow throw new RuntimeException("Failed to find property by name: " + exception.getMessage(), exception); } return propertyId; @@ -492,7 +492,7 @@ public CompletableFuture deleteGatewayAsync(String gatewayA if (exception != null) { throw new RuntimeException("Error creating gateway", exception); } else { - System.out.println("The Gateway was deleted successfully"); + logger.info("The Gateway was deleted successfully"); } }); return null; @@ -510,10 +510,10 @@ public CompletableFuture describeGatewayAsync(String ga if (exception != null) { throw new RuntimeException("Failed to describe the SiteWise gateway", exception); } - System.out.println("Gateway Name: " + response.gatewayName()); - System.out.println("Gateway ARN: " + response.gatewayArn()); - System.out.println("Gateway Platform: " + response.gatewayPlatform().toString()); - System.out.println("Gateway Creation Date: " + response.creationDate()); + logger.info("Gateway Name: " + response.gatewayName()); + logger.info("Gateway ARN: " + response.gatewayArn()); + logger.info("Gateway Platform: " + response.gatewayPlatform().toString()); + logger.info("Gateway Creation Date: " + response.creationDate()); return response; }); } @@ -526,3 +526,4 @@ private static Map generateSampleData() { return data; } } +// snippet-end:[iotsitewise.java2.actions.main] \ No newline at end of file diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index 3c1607a09fb..ebf90e153e6 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -15,10 +15,10 @@ import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayResponse; import software.amazon.awssdk.services.iotsitewise.model.IoTSiteWiseException; import software.amazon.awssdk.services.iotsitewise.model.ResourceAlreadyExistsException; - import java.util.Scanner; import java.util.concurrent.CompletableFuture; +// snippet-start:[iotsitewise.java2.scenario.main] public class SitewiseScenario { public static final String DASHES = new String(new char[80]).replace("\0", "-"); @@ -118,7 +118,6 @@ public static void runScenario(String assetModelName, String assetName, String } catch (RuntimeException rt) { Throwable cause = rt.getCause(); - // Unwrap nested exceptions to find the root cause. while (cause != null) { if (cause instanceof software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException) { logger.info("The AWS resource was not found: {}", cause.getMessage()); @@ -433,3 +432,4 @@ public static void countdown(int minutes) throws InterruptedException { System.out.println("Countdown complete!"); } } +// snippet-end:[iotsitewise.java2.scenario.main] \ No newline at end of file From 52e03d9b5454f53bd60ddf143a41720a3d0a4f0a Mon Sep 17 00:00:00 2001 From: scmacdon Date: Tue, 17 Sep 2024 19:47:45 -0400 Subject: [PATCH 06/41] updated YAML file --- .doc_gen/metadata/iot_sitewise_metadata.yaml | 12 ++++++++++++ .../iotsitewise/scenario/SitewiseActions.java | 9 --------- .../scenario/SitewiseScenario.java | 19 +++++++++++++++++++ .../src/test/java/SitewiseTests.java | 2 ++ 4 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java diff --git a/.doc_gen/metadata/iot_sitewise_metadata.yaml b/.doc_gen/metadata/iot_sitewise_metadata.yaml index ffd4b07c9fa..9f9a040ec06 100644 --- a/.doc_gen/metadata/iot_sitewise_metadata.yaml +++ b/.doc_gen/metadata/iot_sitewise_metadata.yaml @@ -1,4 +1,16 @@ # zexi 0.4.0 +iotsitewise_CreateAssetModel: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2_create_asset_model.main + services: + iotsitewise: {CreateAssetModel} iotsitewise_Scenario: synopsis: Learn core operations for &ITSWlong; using an &AWS; SDK category: Basics diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index a6aa2375571..d03fc0812c7 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -91,14 +91,6 @@ private static IoTSiteWiseAsyncClient getAsyncClient() { return ioTSiteWiseAsyncClient; } - private static IoTSiteWiseClient getClient() { - IoTSiteWiseClient client = IoTSiteWiseClient.builder() - .region(Region.US_EAST_1) - .build(); - - return client; - } - // snippet-start:[sitewise.java2_create_asset_model.main] /** * Creates an asset model asynchronously. @@ -147,7 +139,6 @@ public CompletableFuture createAssetModelAsync(String return response; }); } - // snippet-end:[sitewise.java2_create_asset_model.main] // snippet-start:[sitewise.java2_create_asset.main] diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index ebf90e153e6..efbbd6e05a4 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -29,6 +29,25 @@ public class SitewiseScenario { static SitewiseActions sitewiseActions = new SitewiseActions(); public static void main(String[] args) throws Throwable { + final String usage = """ + Usage: + + + Where: + assetModelName - The name of the asset model used in the IoT SiteWise program. + assetName - The name of the asset created in the IoT SiteWise program. + iamRole - The Amazon Resource Name (ARN) of the IAM role used by the IoT SiteWise service to access other AWS services. + portalName - The name of the IoT SiteWise portal where the asset and other resources are created. + contactEmail - The email address of the contact person associated with the IoT SiteWise program. + gatewayName - The name of the IoT SiteWise gateway used to collect and send data to the IoT SiteWise service. + myThing - The name of the IoT thing or device that is connected to the IoT SiteWise gateway. + """; + + if (args.length != 4) { + logger.info(usage); + return; + } + Scanner scanner = new Scanner(System.in); String assetModelName = "MyAssetModel2"; String assetName = "MyAsset"; diff --git a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java new file mode 100644 index 00000000000..e25c4ca7943 --- /dev/null +++ b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java @@ -0,0 +1,2 @@ +public class SitewiseTests { +} From 4a73906f4411c2aee56ce8fa542a1305270367e8 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 09:54:49 -0400 Subject: [PATCH 07/41] updated YAML file --- .doc_gen/metadata/iot_sitewise_metadata.yaml | 156 ++++++++++++++++++ .../iotsitewise/scenario/SitewiseActions.java | 7 +- 2 files changed, 157 insertions(+), 6 deletions(-) diff --git a/.doc_gen/metadata/iot_sitewise_metadata.yaml b/.doc_gen/metadata/iot_sitewise_metadata.yaml index 9f9a040ec06..a63a088e989 100644 --- a/.doc_gen/metadata/iot_sitewise_metadata.yaml +++ b/.doc_gen/metadata/iot_sitewise_metadata.yaml @@ -1,4 +1,160 @@ # zexi 0.4.0 +iotsitewise_DescribeGateway: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2.describe.gateway.main + services: + iotsitewise: {iotsitewise_DescribeGateway} +iotsitewise_DeleteGateway: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2.delete.gateway.main + services: + iotsitewise: {iotsitewise_DeleteGateway} +iotsitewise_CreateGateway: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2.create.gateway.main + services: + iotsitewise: {iotsitewise_CreateGateway} +iotsitewise_DescribePortal: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2.describe.portal.main + services: + iotsitewise: {iotsitewise_DescribePortal} +iotsitewise_ListAssetModels: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2.list.asset.model.main + services: + iotsitewise: {iotsitewise_ListAssetModels} +iotsitewise_DeletePortal: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2.delete.portal.main + services: + iotsitewise: {iotsitewise_DeletePortal} +iotsitewise_CreatePortal: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2.create.portal.main + services: + iotsitewise: {iotsitewise_CreatePortal} +iotsitewise_DeleteAssetModel: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2.delete.asset.model.main + services: + iotsitewise: {iotsitewise_DeleteAssetModel} +iotsitewise_DeleteAsset: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2.delete.asset.main + services: + iotsitewise: {iotsitewise_DeleteAsset} +iotsitewise_DescribeAssetModel: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2.describe.asset.model.main + services: + iotsitewise: {iotsitewise_DescribeAssetModel} +iotsitewise_GetAssetPropertyValue: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2_get_property.main + services: + iotsitewise: {iotsitewise_GetAssetPropertyValue} +iotsitewise_BatchPutAssetPropertyValue: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2_put_property.main + services: + iotsitewise: {iotsitewise_BatchPutAssetPropertyValue} +iotsitewise_CreateAsset: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + excerpts: + - description: + snippet_tags: + - sitewise.java2_create_asset.main + services: + iotsitewise: {CreateAsset} iotsitewise_CreateAssetModel: languages: Java: diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index d03fc0812c7..f547a1e707b 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -16,9 +16,7 @@ import software.amazon.awssdk.core.retry.RetryPolicy; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseAsyncClient; -import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseClient; import software.amazon.awssdk.services.iotsitewise.model.AssetModelProperty; import software.amazon.awssdk.services.iotsitewise.model.AssetModelPropertyDefinition; import software.amazon.awssdk.services.iotsitewise.model.AssetModelSummary; @@ -232,10 +230,7 @@ public void getAssetPropValueAsync(String propName, String propId, String assetI // Handle the exception, rethrow as RuntimeException or log it throw new RuntimeException("Error occurred while fetching property value: " + exception.getMessage(), exception); } else { - // Process the response - String assetPropName = response.toString(); String assetVal = String.valueOf(response.propertyValue().value().doubleValue()); - logger.info("The property name is: " + propName); logger.info("The value of this property is " + assetVal); } @@ -269,7 +264,7 @@ public CompletableFuture findPropertyIdByNameAsync(String propertyName) return property.id(); } } - return null; // Continue searching in other models if not found + return null; }); futures.add(future); From ad40905a4bf0c5a3622ec85e1a18d399e36001d3 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 10:51:27 -0400 Subject: [PATCH 08/41] updated YAML file to include Hello --- .doc_gen/metadata/iot_sitewise_metadata.yaml | 17 ++++++ .../example/iotsitewise/HelloSitewise.java | 54 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java diff --git a/.doc_gen/metadata/iot_sitewise_metadata.yaml b/.doc_gen/metadata/iot_sitewise_metadata.yaml index a63a088e989..fc383c31010 100644 --- a/.doc_gen/metadata/iot_sitewise_metadata.yaml +++ b/.doc_gen/metadata/iot_sitewise_metadata.yaml @@ -1,4 +1,21 @@ # zexi 0.4.0 +iotsitewise_Hello: + title: Hello &ITSWlong; + title_abbrev: Hello &ITSW; + synopsis: get started using &ITSW;. + category: Hello + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/iotsitewise + sdkguide: + excerpts: + - description: + snippet_tags: + - iotsitewise.hello.main + services: + iotsitewise: {ListVersions} iotsitewise_DescribeGateway: languages: Java: diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java new file mode 100644 index 00000000000..b2e2fd52975 --- /dev/null +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java @@ -0,0 +1,54 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.iotsitewise; + +import com.example.iotsitewise.scenario.SitewiseActions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseAsyncClient; +import software.amazon.awssdk.services.iotsitewise.model.AssetSummary; +import software.amazon.awssdk.services.iotsitewise.model.ListAssetsRequest; +import java.util.List; + +// snippet-start:[iotsitewise.hello.main] +public class HelloSitewise { + private static final Logger logger = LoggerFactory.getLogger(HelloSitewise.class); + public static void main(String[] args) { + String modelId = "754c6991-9b34-4fd3-85a5-d4261b1324a1"; + IoTSiteWiseAsyncClient siteWiseAsyncClient = IoTSiteWiseAsyncClient.builder() + .region(Region.US_EAST_1) + .build(); + + fetchAssets(siteWiseAsyncClient, modelId); + } + + /** + * Fetches assets from AWS IoT SiteWise using the provided {@link IoTSiteWiseAsyncClient}. + * + * @param siteWiseAsyncClient the AWS IoT SiteWise asynchronous client to use for the request + * @param modelId the ID of the asset model to fetch assets for + */ + public static void fetchAssets(IoTSiteWiseAsyncClient siteWiseAsyncClient, String modelId) { + ListAssetsRequest assetsRequest = ListAssetsRequest.builder() + .maxResults(10) + .assetModelId(modelId) + .build(); + + siteWiseAsyncClient.listAssets(assetsRequest) + .whenComplete((response, throwable) -> { + if (throwable != null) { + logger.info("Error fetching assets: {} ", throwable.getMessage()); + } else { + List assetList = response.assetSummaries(); + logger.info("Fetched assets:"); + for (AssetSummary asset : assetList) { + logger.info("- " + asset.name()); + } + } + }) + .join(); + } +} +// snippet-end:[iotsitewise.hello.main] \ No newline at end of file From 48907e3afe537c3625139d87a5a3f43addb87c83 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 11:23:40 -0400 Subject: [PATCH 09/41] updated YAML file --- .doc_gen/metadata/iot_sitewise_metadata.yaml | 24 +++++----- .../sitewise_scenario/SPECIFICATION.md | 6 +-- .../example/iotsitewise/HelloSitewise.java | 44 ++++++++++++------- .../scenario/SitewiseScenario.java | 2 +- 4 files changed, 44 insertions(+), 32 deletions(-) diff --git a/.doc_gen/metadata/iot_sitewise_metadata.yaml b/.doc_gen/metadata/iot_sitewise_metadata.yaml index fc383c31010..396d9661b42 100644 --- a/.doc_gen/metadata/iot_sitewise_metadata.yaml +++ b/.doc_gen/metadata/iot_sitewise_metadata.yaml @@ -27,7 +27,7 @@ iotsitewise_DescribeGateway: snippet_tags: - sitewise.java2.describe.gateway.main services: - iotsitewise: {iotsitewise_DescribeGateway} + iotsitewise: {DescribeGateway} iotsitewise_DeleteGateway: languages: Java: @@ -39,7 +39,7 @@ iotsitewise_DeleteGateway: snippet_tags: - sitewise.java2.delete.gateway.main services: - iotsitewise: {iotsitewise_DeleteGateway} + iotsitewise: {DeleteGateway} iotsitewise_CreateGateway: languages: Java: @@ -51,7 +51,7 @@ iotsitewise_CreateGateway: snippet_tags: - sitewise.java2.create.gateway.main services: - iotsitewise: {iotsitewise_CreateGateway} + iotsitewise: {CreateGateway} iotsitewise_DescribePortal: languages: Java: @@ -63,7 +63,7 @@ iotsitewise_DescribePortal: snippet_tags: - sitewise.java2.describe.portal.main services: - iotsitewise: {iotsitewise_DescribePortal} + iotsitewise: {DescribePortal} iotsitewise_ListAssetModels: languages: Java: @@ -75,7 +75,7 @@ iotsitewise_ListAssetModels: snippet_tags: - sitewise.java2.list.asset.model.main services: - iotsitewise: {iotsitewise_ListAssetModels} + iotsitewise: {ListAssetModels} iotsitewise_DeletePortal: languages: Java: @@ -87,7 +87,7 @@ iotsitewise_DeletePortal: snippet_tags: - sitewise.java2.delete.portal.main services: - iotsitewise: {iotsitewise_DeletePortal} + iotsitewise: {DeletePortal} iotsitewise_CreatePortal: languages: Java: @@ -99,7 +99,7 @@ iotsitewise_CreatePortal: snippet_tags: - sitewise.java2.create.portal.main services: - iotsitewise: {iotsitewise_CreatePortal} + iotsitewise: {CreatePortal} iotsitewise_DeleteAssetModel: languages: Java: @@ -111,7 +111,7 @@ iotsitewise_DeleteAssetModel: snippet_tags: - sitewise.java2.delete.asset.model.main services: - iotsitewise: {iotsitewise_DeleteAssetModel} + iotsitewise: {DeleteAssetModel} iotsitewise_DeleteAsset: languages: Java: @@ -123,7 +123,7 @@ iotsitewise_DeleteAsset: snippet_tags: - sitewise.java2.delete.asset.main services: - iotsitewise: {iotsitewise_DeleteAsset} + iotsitewise: {DeleteAsset} iotsitewise_DescribeAssetModel: languages: Java: @@ -135,7 +135,7 @@ iotsitewise_DescribeAssetModel: snippet_tags: - sitewise.java2.describe.asset.model.main services: - iotsitewise: {iotsitewise_DescribeAssetModel} + iotsitewise: {DescribeAssetModel} iotsitewise_GetAssetPropertyValue: languages: Java: @@ -147,7 +147,7 @@ iotsitewise_GetAssetPropertyValue: snippet_tags: - sitewise.java2_get_property.main services: - iotsitewise: {iotsitewise_GetAssetPropertyValue} + iotsitewise: {GetAssetPropertyValue} iotsitewise_BatchPutAssetPropertyValue: languages: Java: @@ -159,7 +159,7 @@ iotsitewise_BatchPutAssetPropertyValue: snippet_tags: - sitewise.java2_put_property.main services: - iotsitewise: {iotsitewise_BatchPutAssetPropertyValue} + iotsitewise: {BatchPutAssetPropertyValue} iotsitewise_CreateAsset: languages: Java: diff --git a/basics_scenarios/sitewise_scenario/SPECIFICATION.md b/basics_scenarios/sitewise_scenario/SPECIFICATION.md index c4781a30547..ca030139ace 100644 --- a/basics_scenarios/sitewise_scenario/SPECIFICATION.md +++ b/basics_scenarios/sitewise_scenario/SPECIFICATION.md @@ -6,9 +6,9 @@ This SDK Basics scenario demonstrates how to interact with AWS IoT SiteWise usin ## Resources This Basics scenario has a depedency on an IAM role that has permissions for this service. We will create this resource using a CloudFormation template so the user does not have to manually create it. -## Hello Amazon OpenSearch -This program is intended for users not familiar with the AWS IoT SiteWise Service to easily get up and running. The logic is to show use of ` -`???. +## Hello AWS IoT SiteWise +This program is intended for users not familiar with the AWS IoT SiteWise Service to easily get up and running. The logic is to show use of +`listAssetslistAssetsPaginator`. ## Scenario Program Flow The AWS IoT SiteWise Basics scenario executes the following operations. diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java index b2e2fd52975..cb5df09c1f3 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java @@ -3,25 +3,40 @@ package com.example.iotsitewise; -import com.example.iotsitewise.scenario.SitewiseActions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseAsyncClient; import software.amazon.awssdk.services.iotsitewise.model.AssetSummary; import software.amazon.awssdk.services.iotsitewise.model.ListAssetsRequest; +import software.amazon.awssdk.services.iotsitewise.paginators.ListAssetsPublisher; + import java.util.List; +import java.util.concurrent.CompletableFuture; // snippet-start:[iotsitewise.hello.main] public class HelloSitewise { private static final Logger logger = LoggerFactory.getLogger(HelloSitewise.class); public static void main(String[] args) { - String modelId = "754c6991-9b34-4fd3-85a5-d4261b1324a1"; + final String usage = """ + Usage: + + + Where: + assetModelId - The Id value of the asset model used in the IoT SiteWise program. + """; + + // if (args.length != 1) { + // logger.info(usage); + /// return; + // } + + String assetModelId = "754c6991-9b34-4fd3-85a5-d4261b1324a1"; IoTSiteWiseAsyncClient siteWiseAsyncClient = IoTSiteWiseAsyncClient.builder() .region(Region.US_EAST_1) .build(); - fetchAssets(siteWiseAsyncClient, modelId); + fetchAssets(siteWiseAsyncClient, assetModelId); } /** @@ -36,19 +51,16 @@ public static void fetchAssets(IoTSiteWiseAsyncClient siteWiseAsyncClient, Strin .assetModelId(modelId) .build(); - siteWiseAsyncClient.listAssets(assetsRequest) - .whenComplete((response, throwable) -> { - if (throwable != null) { - logger.info("Error fetching assets: {} ", throwable.getMessage()); - } else { - List assetList = response.assetSummaries(); - logger.info("Fetched assets:"); - for (AssetSummary asset : assetList) { - logger.info("- " + asset.name()); - } - } - }) - .join(); + // Asynchronous paginator - process paginated results. + ListAssetsPublisher listAssetsPaginator = siteWiseAsyncClient.listAssetsPaginator(assetsRequest); + CompletableFuture future = listAssetsPaginator.subscribe(response -> { + response.assetSummaries().forEach(assetSummary -> + logger.info("Asset Name: {} ", assetSummary.name()) + ); + }); + + // Wait for the asynchronous operation to complete + future.join(); } } // snippet-end:[iotsitewise.hello.main] \ No newline at end of file diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index efbbd6e05a4..f9feb745d9e 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -43,7 +43,7 @@ public static void main(String[] args) throws Throwable { myThing - The name of the IoT thing or device that is connected to the IoT SiteWise gateway. """; - if (args.length != 4) { + if (args.length != 7) { logger.info(usage); return; } From f692fb318e86007bf769632b236dac47d2e4d67b Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 11:51:06 -0400 Subject: [PATCH 10/41] updated Spec to specify metadata tags --- .../sitewise_scenario/SPECIFICATION.md | 27 +++++++++++++------ .../example/iotsitewise/HelloSitewise.java | 10 +++---- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/basics_scenarios/sitewise_scenario/SPECIFICATION.md b/basics_scenarios/sitewise_scenario/SPECIFICATION.md index ca030139ace..7341ad32d28 100644 --- a/basics_scenarios/sitewise_scenario/SPECIFICATION.md +++ b/basics_scenarios/sitewise_scenario/SPECIFICATION.md @@ -299,12 +299,23 @@ The following table describes the metadata used in this Basics Scenario. | action | metadata file | metadata key | |--------------------------------|-----------------------------------|---------------------------------------- | -| `createDomain` | opensearch_metadata.yaml | opensearch_CreateDomain | -| `deleteDomain ` | opensearch_metadata.yaml | opensearch_DeleteDomain | -| `listDomainNames ` | opensearch_metadata.yaml | opensearch_ListDomainNames | -| `updateDomainConfig` | opensearch_metadata.yaml | opensearch_UpdateDomainConfig | -| `describeDomain` | opensearch_metadata.yaml | opensearch_DescribeDomain | -| `describeDomainChangeProgress` | opensearch_metadata.yaml | opensearch_ChangeProgress | -| `listDomainTags` | opensearch_metadata.yaml | opensearch_ListTags | -| `scenario` | opensearch_metadata.yaml | opensearch_Scenario | +| `describeGateway` | iot_sitewise_metadata.yaml | iotsitewise_DescribeGateway | +| `deleteGateway ` | iot_sitewise_metadata.yaml | iotsitewise_DeleteGateway | +| `createGateway ` | iot_sitewise_metadata.yaml | iotsitewise_CreateGateway | +| `describePortal` | iot_sitewise_metadata.yaml | iotsitewise_DescribePortal | +| `listAssetModels` | iot_sitewise_metadata.yaml | iotsitewise_ListAssetModels | +| `deletePortal` | iot_sitewise_metadata.yaml | iotsitewise_DeletePortal | +| `createPortals` | iot_sitewise_metadata.yaml | iotsitewise_CreatePortal | +| `deleteAssetModel` | iot_sitewise_metadata.yaml | iotsitewise_DeleteAssetModel | +| `deleteAsset` | iot_sitewise_metadata.yaml | iotsitewise_DeleteAsset | +| `describeAssetModel` | iot_sitewise_metadata.yaml | iotsitewise_DescribeAssetModel | +| `getAssetPropertyValue` | iot_sitewise_metadata.yaml | iotsitewise_GetAssetPropertyValue | +| `batchPutAssetPropertyValue` | iot_sitewise_metadata.yaml | iotsitewise_BatchPutAssetPropertyValue | +| `createAsset` | iot_sitewise_metadata.yaml | iotsitewise_CreateAsset | +| `createAsset` | iot_sitewise_metadata.yaml | iotsitewise_CreateAsset | +| `createAssetModel ` | iot_sitewise_metadata.yaml | iotsitewise_CreateAssetModel | +| `scenario` | iot_sitewise_metadata.yaml | iotsitewise_Scenario | +| `hello` | iot_sitewise_metadata.yaml | iotsitewise_Hello | + + diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java index cb5df09c1f3..e223f1fbf31 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java @@ -26,12 +26,12 @@ public static void main(String[] args) { assetModelId - The Id value of the asset model used in the IoT SiteWise program. """; - // if (args.length != 1) { - // logger.info(usage); - /// return; - // } + if (args.length != 1) { + logger.info(usage); + return; + } - String assetModelId = "754c6991-9b34-4fd3-85a5-d4261b1324a1"; + String assetModelId = args[0]; IoTSiteWiseAsyncClient siteWiseAsyncClient = IoTSiteWiseAsyncClient.builder() .region(Region.US_EAST_1) .build(); From 8687a6563d822fca805744316fd35ba56f1c5f5f Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 12:01:05 -0400 Subject: [PATCH 11/41] updated YAML --- .doc_gen/metadata/iot_sitewise_metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.doc_gen/metadata/iot_sitewise_metadata.yaml b/.doc_gen/metadata/iot_sitewise_metadata.yaml index 396d9661b42..350cda9287c 100644 --- a/.doc_gen/metadata/iot_sitewise_metadata.yaml +++ b/.doc_gen/metadata/iot_sitewise_metadata.yaml @@ -159,7 +159,7 @@ iotsitewise_BatchPutAssetPropertyValue: snippet_tags: - sitewise.java2_put_property.main services: - iotsitewise: {BatchPutAssetPropertyValue} + iotsitewise: {BatchPutAssetPropertyValue } iotsitewise_CreateAsset: languages: Java: From e704981fc7275a48a49e163198c0d3dce6616c14 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 12:32:48 -0400 Subject: [PATCH 12/41] updated Readme --- javav2/example_code/iotsitewise/README.md | 92 +++++++---------------- 1 file changed, 29 insertions(+), 63 deletions(-) diff --git a/javav2/example_code/iotsitewise/README.md b/javav2/example_code/iotsitewise/README.md index 7a8cff90e3c..b337bbacab3 100644 --- a/javav2/example_code/iotsitewise/README.md +++ b/javav2/example_code/iotsitewise/README.md @@ -1,13 +1,13 @@ -# Amazon EC2 code examples for the SDK for Java 2.x +# AWS IoT SiteWise code examples for the SDK for Java 2.x ## Overview -Shows how to use the AWS SDK for Java 2.x to work with Amazon Elastic Compute Cloud (Amazon EC2). +Shows how to use the AWS SDK for Java 2.x to work with AWS IoT SiteWise. -_Amazon EC2 is a web service that provides resizable computing capacity—literally, servers in Amazon's data centers—that you use to build and host your software systems._ +_AWS IoT SiteWise _ ## ⚠ Important @@ -31,45 +31,34 @@ For prerequisites, see the [README](../../README.md#Prerequisites) in the `javav ### Get started -- [Hello Amazon EC2](src/main/java/com/example/ec2/scenario/EC2Actions.java#L468) (`DescribeSecurityGroups`) +- [Hello AWS IoT SiteWise](src/main/java/com/example/iotsitewise/HelloSitewise.java#L17) (`ListVersions`) ### Basics Code examples that show you how to perform the essential operations within a service. -- [Learn the basics](src/main/java/com/example/ec2/scenario/EC2Scenario.java) +- [Learn the basics](src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java) ### Single actions Code excerpts that show you how to call individual service functions. -- [AllocateAddress](src/main/java/com/example/ec2/scenario/EC2Actions.java#L265) -- [AssociateAddress](src/main/java/com/example/ec2/scenario/EC2Actions.java#L235) -- [AuthorizeSecurityGroupIngress](src/main/java/com/example/ec2/scenario/EC2Actions.java#L505) -- [CreateKeyPair](src/main/java/com/example/ec2/scenario/EC2Actions.java#L585) -- [CreateSecurityGroup](src/main/java/com/example/ec2/scenario/EC2Actions.java#L505) -- [DeleteKeyPair](src/main/java/com/example/ec2/scenario/EC2Actions.java#L106) -- [DeleteSecurityGroup](src/main/java/com/example/ec2/scenario/EC2Actions.java#L132) -- [DescribeInstanceTypes](src/main/java/com/example/ec2/scenario/EC2Actions.java#L356) -- [DescribeInstances](src/main/java/com/example/ec2/scenario/EC2Actions.java#L402) -- [DescribeKeyPairs](src/main/java/com/example/ec2/scenario/EC2Actions.java#L566) -- [DescribeSecurityGroups](src/main/java/com/example/ec2/scenario/EC2Actions.java#L468) -- [DisassociateAddress](src/main/java/com/example/ec2/scenario/EC2Actions.java#L207) -- [GetPasswordData](src/main/java/com/example/ec2/GetPasswordData.java#L6) -- [ReleaseAddress](src/main/java/com/example/ec2/scenario/EC2Actions.java#L184) -- [RunInstances](src/main/java/com/example/ec2/scenario/EC2Actions.java#L319) -- [StartInstances](src/main/java/com/example/ec2/scenario/EC2Actions.java#L696) -- [StopInstances](src/main/java/com/example/ec2/scenario/EC2Actions.java#L653) -- [TerminateInstances](src/main/java/com/example/ec2/scenario/EC2Actions.java#L155) - -### Scenarios - -Code examples that show you how to accomplish a specific task by calling multiple -functions within the same service. - -- [Build and manage a resilient service](../../usecases/resilient_service/src/main/java/com/example/resilient/Main.java) +- [BatchPutAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L168) +- [CreateAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L142) +- [CreateAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L92) +- [CreateGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L434) +- [CreatePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L337) +- [DeleteAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L293) +- [DeleteAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L315) +- [DeleteGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L470) +- [DeletePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L364) +- [DescribeAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L241) +- [DescribeGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L488) +- [DescribePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L410) +- [GetAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L220) +- [ListAssetModels](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L386) @@ -83,47 +72,24 @@ functions within the same service. -#### Hello Amazon EC2 +#### Hello AWS IoT SiteWise -This example shows you how to get started using Amazon EC2. +This example shows you how to get started using AWS IoT SiteWise. #### Learn the basics -This example shows you how to do the following: +This example shows you how to Learn core operations for AWS IoT SiteWise using an AWS SDK -- Create a key pair and security group. -- Select an Amazon Machine Image (AMI) and compatible instance type, then create an instance. -- Stop and restart the instance. -- Associate an Elastic IP address with your instance. -- Connect to your instance with SSH, then clean up resources. - - + + - - + + -#### Build and manage a resilient service - -This example shows you how to create a load-balanced web service that returns book, movie, and song recommendations. The example shows how the service responds to failures, and how to restructure the service for more resilience when failures occur. - -- Use an Amazon EC2 Auto Scaling group to create Amazon Elastic Compute Cloud (Amazon EC2) instances based on a launch template and to keep the number of instances in a specified range. -- Handle and distribute HTTP requests with Elastic Load Balancing. -- Monitor the health of instances in an Auto Scaling group and forward requests only to healthy instances. -- Run a Python web server on each EC2 instance to handle HTTP requests. The web server responds with recommendations and health checks. -- Simulate a recommendation service with an Amazon DynamoDB table. -- Control web server response to requests and health checks by updating AWS Systems Manager parameters. - - - - - - - - ### Tests ⚠ Running tests might result in charges to your AWS account. @@ -139,9 +105,9 @@ in the `javav2` folder. ## Additional resources -- [Amazon EC2 User Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html) -- [Amazon EC2 API Reference](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Welcome.html) -- [SDK for Java 2.x Amazon EC2 reference](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/package-summary.html) +- [AWS IoT SiteWise Developer Guide](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/what-is-sitewise.html) +- [AWS IoT SiteWise API Reference](https://docs.aws.amazon.com/iot-sitewise/latest/APIReference/Welcome.html) +- [SDK for Java 2.x AWS IoT SiteWise reference](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/package-summary.html) From dcf124d3c007437c748929114fb9e1f982c32cf0 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 12:35:46 -0400 Subject: [PATCH 13/41] updated yaml to address a lint issue --- .doc_gen/metadata/iot_sitewise_metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.doc_gen/metadata/iot_sitewise_metadata.yaml b/.doc_gen/metadata/iot_sitewise_metadata.yaml index 350cda9287c..396d9661b42 100644 --- a/.doc_gen/metadata/iot_sitewise_metadata.yaml +++ b/.doc_gen/metadata/iot_sitewise_metadata.yaml @@ -159,7 +159,7 @@ iotsitewise_BatchPutAssetPropertyValue: snippet_tags: - sitewise.java2_put_property.main services: - iotsitewise: {BatchPutAssetPropertyValue } + iotsitewise: {BatchPutAssetPropertyValue} iotsitewise_CreateAsset: languages: Java: From 5c913ad582e27da9f1aba9267dbd038fb7ca8999 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 12:39:14 -0400 Subject: [PATCH 14/41] updated a placeholder for tests --- .../example_code/iotsitewise/src/test/java/SitewiseTests.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java index e25c4ca7943..3cc65de7d9e 100644 --- a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java +++ b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java @@ -1,2 +1,5 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + public class SitewiseTests { } From 62b27c0feb50bfd1e6ac4ba5fe4411282a019fe1 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 12:44:05 -0400 Subject: [PATCH 15/41] updated yaml to address lint issue --- .doc_gen/metadata/iot_sitewise_metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.doc_gen/metadata/iot_sitewise_metadata.yaml b/.doc_gen/metadata/iot_sitewise_metadata.yaml index 396d9661b42..8a7f7027423 100644 --- a/.doc_gen/metadata/iot_sitewise_metadata.yaml +++ b/.doc_gen/metadata/iot_sitewise_metadata.yaml @@ -188,7 +188,7 @@ iotsitewise_Scenario: synopsis: Learn core operations for &ITSWlong; using an &AWS; SDK category: Basics languages: - Java: + Java: versions: - sdk_version: 2 github: javav2/example_code/iotsitewise From c2dee0543c5c8cc1ffb6f9366b6ed439f678fbe1 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 16:38:23 -0400 Subject: [PATCH 16/41] updated scout to use a Cloudformation template --- javav2/example_code/iotsitewise/pom.xml | 4 + .../scenario/CloudFormationHelper.java | 131 ++++++++++++++++++ .../iotsitewise/scenario/SitewiseActions.java | 8 +- .../scenario/SitewiseScenario.java | 30 ++-- .../resources/SitewiseRoles-template.yaml | 130 +++++++++++++++++ 5 files changed, 288 insertions(+), 15 deletions(-) create mode 100644 javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java create mode 100644 javav2/example_code/iotsitewise/src/main/resources/SitewiseRoles-template.yaml diff --git a/javav2/example_code/iotsitewise/pom.xml b/javav2/example_code/iotsitewise/pom.xml index 512f822d0f1..f464fe3f557 100644 --- a/javav2/example_code/iotsitewise/pom.xml +++ b/javav2/example_code/iotsitewise/pom.xml @@ -115,6 +115,10 @@ slf4j-api 2.0.13 + + software.amazon.awssdk + cloudformation + org.apache.logging.log4j log4j-slf4j2-impl diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java new file mode 100644 index 00000000000..740904b43ed --- /dev/null +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java @@ -0,0 +1,131 @@ +package com.example.iotsitewise.scenario; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.cloudformation.CloudFormationAsyncClient; +import software.amazon.awssdk.services.cloudformation.CloudFormationClient; +import software.amazon.awssdk.services.cloudformation.model.Capability; +import software.amazon.awssdk.services.cloudformation.model.CloudFormationException; +import software.amazon.awssdk.services.cloudformation.model.DescribeStacksRequest; +import software.amazon.awssdk.services.cloudformation.model.DescribeStacksResponse; +import software.amazon.awssdk.services.cloudformation.model.Output; +import software.amazon.awssdk.services.cloudformation.model.Stack; +import software.amazon.awssdk.services.cloudformation.waiters.CloudFormationAsyncWaiter; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +public class CloudFormationHelper { + private static final String CFN_TEMPLATE = "SitewiseRoles-template.yaml"; + private static final Logger logger = LoggerFactory.getLogger(CloudFormationHelper.class); + + private static CloudFormationAsyncClient getCloudFormationClient() { + CloudFormationAsyncClient cfClient = CloudFormationAsyncClient.builder() + .region(Region.US_EAST_1) + .build(); + + return cfClient; + } + + public static void deployCloudFormationStack(String stackName) { + String templateBody; + boolean doesExist = describeStack(stackName); + if (!doesExist) { + try { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Path filePath = Paths.get(classLoader.getResource(CFN_TEMPLATE).toURI()); + templateBody = Files.readString(filePath); + } catch (IOException | URISyntaxException e) { + throw new RuntimeException(e); + } + + getCloudFormationClient().createStack(b -> b.stackName(stackName) + .templateBody(templateBody) + .capabilities(Capability.CAPABILITY_IAM)) + .whenComplete((csr, t) -> { + if (csr != null) { + System.out.println("Stack creation requested, ARN is " + csr.stackId()); + try (CloudFormationAsyncWaiter waiter = getCloudFormationClient().waiter()) { + waiter.waitUntilStackCreateComplete(request -> request.stackName(stackName)) + .whenComplete((dsr, th) -> { + if (th != null) { + System.out.println("Error waiting for stack creation: " + th.getMessage()); + } else { + dsr.matched().response().orElseThrow(() -> new RuntimeException("Failed to deploy")); + System.out.println("Stack created successfully"); + } + }).join(); + } + } else { + System.out.format("Error creating stack: " + t.getMessage(), t); + throw new RuntimeException(t.getCause().getMessage(), t); + } + }).join(); + } else { + logger.info("{} stack already exists", CFN_TEMPLATE); + } + } + + // Check to see if the Stack exists before deploying it + + public static Boolean describeStack(String stackName) { + try { + CompletableFuture future = getCloudFormationClient().describeStacks(); + DescribeStacksResponse stacksResponse = (DescribeStacksResponse) future.join(); + List stacks = stacksResponse.stacks(); + for (Stack myStack :stacks) { + if (myStack.stackName().compareTo(stackName)==0){ + return true; + } + } + } catch (CloudFormationException e) { + System.err.println(e.getMessage()); + } + return false; + } + static void destroyCloudFormationStack(String stackName) { + getCloudFormationClient().deleteStack(b -> b.stackName(stackName)) + .whenComplete((dsr, t) -> { + if (dsr != null) { + System.out.println("Delete stack requested ...."); + try (CloudFormationAsyncWaiter waiter = getCloudFormationClient().waiter()) { + waiter.waitUntilStackDeleteComplete(request -> request.stackName(stackName)) + .whenComplete((waiterResponse, throwable) -> + System.out.println("Stack deleted successfully.")) + .join(); + } + } else { + System.out.format("Error deleting stack: " + t.getMessage(), t); + throw new RuntimeException(t.getCause().getMessage(), t); + } + }).join(); + } + + public static Map getStackOutputs(String stackName) { + CloudFormationClient cfClient = CloudFormationClient.create(); + DescribeStacksRequest describeStacksRequest = DescribeStacksRequest.builder() + .stackName(stackName) + .build(); + + DescribeStacksResponse describeStacksResponse = cfClient.describeStacks(describeStacksRequest); + List stacks = describeStacksResponse.stacks(); + + if (stacks.isEmpty()) { + throw new RuntimeException("Stack not found: " + stackName); + } + + Stack stack = stacks.get(0); + Map outputs = new HashMap<>(); + for (Output output : stack.outputs()) { + outputs.put(output.outputKey(), output.outputValue()); + } + + return outputs; + } +} diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index f547a1e707b..c51dfb392f9 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -218,6 +218,7 @@ public CompletableFuture sendDataToSiteWiseA // snippet-end:[sitewise.java2_put_property.main] // snippet-start:[sitewise.java2_get_property.main] + // TODO -- fix this including Javadoc public void getAssetPropValueAsync(String propName, String propId, String assetId) { GetAssetPropertyValueRequest assetPropertyValueRequest = GetAssetPropertyValueRequest.builder() .propertyId(propId) @@ -227,14 +228,13 @@ public void getAssetPropValueAsync(String propName, String propId, String assetI CompletableFuture futureResponse = getAsyncClient().getAssetPropertyValue(assetPropertyValueRequest); futureResponse.whenComplete((response, exception) -> { if (exception != null) { - // Handle the exception, rethrow as RuntimeException or log it throw new RuntimeException("Error occurred while fetching property value: " + exception.getMessage(), exception); } else { String assetVal = String.valueOf(response.propertyValue().value().doubleValue()); - logger.info("The property name is: " + propName); - logger.info("The value of this property is " + assetVal); + logger.info("The property name is: {} ", propName); + logger.info("The value of this property is {}", assetVal); } - }).join(); // You can remove this join() if you don't need to block the thread. + }).join(); } // snippet-end:[sitewise.java2_get_property.main] diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index f9feb745d9e..f4e4b1b1f4f 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -15,6 +15,7 @@ import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayResponse; import software.amazon.awssdk.services.iotsitewise.model.IoTSiteWiseException; import software.amazon.awssdk.services.iotsitewise.model.ResourceAlreadyExistsException; +import java.util.Map; import java.util.Scanner; import java.util.concurrent.CompletableFuture; @@ -26,32 +27,32 @@ public class SitewiseScenario { private static final Logger logger = LoggerFactory.getLogger(SitewiseScenario.class); static Scanner scanner = new Scanner(System.in); + private static final String ROLES_STACK = "RoleSitewise"; + static SitewiseActions sitewiseActions = new SitewiseActions(); public static void main(String[] args) throws Throwable { final String usage = """ Usage: - + Where: assetModelName - The name of the asset model used in the IoT SiteWise program. assetName - The name of the asset created in the IoT SiteWise program. - iamRole - The Amazon Resource Name (ARN) of the IAM role used by the IoT SiteWise service to access other AWS services. portalName - The name of the IoT SiteWise portal where the asset and other resources are created. contactEmail - The email address of the contact person associated with the IoT SiteWise program. gatewayName - The name of the IoT SiteWise gateway used to collect and send data to the IoT SiteWise service. myThing - The name of the IoT thing or device that is connected to the IoT SiteWise gateway. """; - if (args.length != 7) { - logger.info(usage); - return; - } + //if (args.length != 6) { + // logger.info(usage); + // return; + // } Scanner scanner = new Scanner(System.in); - String assetModelName = "MyAssetModel2"; + String assetModelName = "MyAssetModel"; String assetName = "MyAsset"; - String iamRole = "arn:aws:iam::814548047983:role/service-role/AWSIoTSiteWiseMonitorServiceRole_8jLqg43nJ"; String portalName = "MyPortal"; String contactEmail = "scmacdon@amazon.com"; String gatewayName = "myGateway11"; @@ -82,13 +83,19 @@ equipment and systems, including programmable logic controllers (PLCs), sensors, logger.info(DASHES); try { - runScenario(assetModelName, assetName, iamRole, portalName, contactEmail, gatewayName, myThing); + runScenario(assetModelName, assetName, portalName, contactEmail, gatewayName, myThing); } catch (RuntimeException e) { logger.info(e.getMessage()); } } - public static void runScenario(String assetModelName, String assetName, String iamRole, String portalName, String contactEmail, String gatewayName, String myThing) throws Throwable { + public static void runScenario(String assetModelName, String assetName, String portalName, String contactEmail, String gatewayName, String myThing) throws Throwable { + + logger.info("Use AWS CloudFormation to create an IAM role that are required for this scenario."); + CloudFormationHelper.deployCloudFormationStack(ROLES_STACK); + Map stackOutputs = CloudFormationHelper.getStackOutputs(ROLES_STACK); + String iamRole = stackOutputs.get("SitewiseRoleArn"); + logger.info(DASHES); logger.info("1. Create an AWS SiteWise Asset Model"); logger.info(""" @@ -98,7 +105,7 @@ public static void runScenario(String assetModelName, String assetName, String of each asset. """); waitForInputToContinue(scanner); - String assetModelId = ""; + String assetModelId; try { CompletableFuture future = sitewiseActions.createAssetModelAsync(assetModelName); CreateAssetModelResponse response = future.join(); @@ -418,6 +425,7 @@ public static void runScenario(String assetModelName, String assetName, String logger.info(DASHES); logger.info(DASHES); + CloudFormationHelper.destroyCloudFormationStack(ROLES_STACK); logger.info("This concludes the AWS SiteWise Scenario"); logger.info(DASHES); } diff --git a/javav2/example_code/iotsitewise/src/main/resources/SitewiseRoles-template.yaml b/javav2/example_code/iotsitewise/src/main/resources/SitewiseRoles-template.yaml new file mode 100644 index 00000000000..3c0568a6fce --- /dev/null +++ b/javav2/example_code/iotsitewise/src/main/resources/SitewiseRoles-template.yaml @@ -0,0 +1,130 @@ +Resources: + RoleSitewiseF9E96FB3: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: iotsitewise.amazonaws.com + Version: "2012-10-17" + ManagedPolicyArns: + - Fn::Join: + - "" + - - "arn:" + - Ref: AWS::Partition + - :iam::aws:policy/AWSIoTSiteWiseFullAccess + Metadata: + aws:cdk:path: SitewiseStack/RoleSitewise/Resource + CDKMetadata: + Type: AWS::CDK::Metadata + Properties: + Analytics: v2:deflate64:H4sIAAAAAAAA/zPSMzQ21TNQTCwv1k1OydbNyUzSqw4uSUzO1kksL47PTMzVqw7Kz0nVcU7LA9G1OkGpxfmlRclgEf/SkoLSErAckqhzfl5KZklmfl6tjldiWaK+obmegZ6hkWJWcWamblFpXklmbqpeEIQGALeO80GAAAAA + Metadata: + aws:cdk:path: SitewiseStack/CDKMetadata/Default + Condition: CDKMetadataAvailable +Outputs: + SitewiseRoleArn: + Description: The ARN of the SiteWise Role + Value: + Fn::GetAtt: + - RoleSitewiseF9E96FB3 + - Arn +Conditions: + CDKMetadataAvailable: + Fn::Or: + - Fn::Or: + - Fn::Equals: + - Ref: AWS::Region + - af-south-1 + - Fn::Equals: + - Ref: AWS::Region + - ap-east-1 + - Fn::Equals: + - Ref: AWS::Region + - ap-northeast-1 + - Fn::Equals: + - Ref: AWS::Region + - ap-northeast-2 + - Fn::Equals: + - Ref: AWS::Region + - ap-south-1 + - Fn::Equals: + - Ref: AWS::Region + - ap-southeast-1 + - Fn::Equals: + - Ref: AWS::Region + - ap-southeast-2 + - Fn::Equals: + - Ref: AWS::Region + - ca-central-1 + - Fn::Equals: + - Ref: AWS::Region + - cn-north-1 + - Fn::Equals: + - Ref: AWS::Region + - cn-northwest-1 + - Fn::Or: + - Fn::Equals: + - Ref: AWS::Region + - eu-central-1 + - Fn::Equals: + - Ref: AWS::Region + - eu-north-1 + - Fn::Equals: + - Ref: AWS::Region + - eu-south-1 + - Fn::Equals: + - Ref: AWS::Region + - eu-west-1 + - Fn::Equals: + - Ref: AWS::Region + - eu-west-2 + - Fn::Equals: + - Ref: AWS::Region + - eu-west-3 + - Fn::Equals: + - Ref: AWS::Region + - il-central-1 + - Fn::Equals: + - Ref: AWS::Region + - me-central-1 + - Fn::Equals: + - Ref: AWS::Region + - me-south-1 + - Fn::Equals: + - Ref: AWS::Region + - sa-east-1 + - Fn::Or: + - Fn::Equals: + - Ref: AWS::Region + - us-east-1 + - Fn::Equals: + - Ref: AWS::Region + - us-east-2 + - Fn::Equals: + - Ref: AWS::Region + - us-west-1 + - Fn::Equals: + - Ref: AWS::Region + - us-west-2 +Parameters: + BootstrapVersion: + Type: AWS::SSM::Parameter::Value + Default: /cdk-bootstrap/hnb659fds/version + Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip] +Rules: + CheckBootstrapVersion: + Assertions: + - Assert: + Fn::Not: + - Fn::Contains: + - - "1" + - "2" + - "3" + - "4" + - "5" + - Ref: BootstrapVersion + AssertDescription: CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI. + From 181cec2fbc5b836f57e783a76e089f3cf4b4ea81 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 16:43:39 -0400 Subject: [PATCH 17/41] updated scout to use a Cloudformation template --- .../com/example/iotsitewise/scenario/SitewiseScenario.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index f4e4b1b1f4f..618267ba020 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -90,11 +90,12 @@ equipment and systems, including programmable logic controllers (PLCs), sensors, } public static void runScenario(String assetModelName, String assetName, String portalName, String contactEmail, String gatewayName, String myThing) throws Throwable { - - logger.info("Use AWS CloudFormation to create an IAM role that are required for this scenario."); + logger.info("Use AWS CloudFormation to create an IAM role that is required for this scenario."); CloudFormationHelper.deployCloudFormationStack(ROLES_STACK); Map stackOutputs = CloudFormationHelper.getStackOutputs(ROLES_STACK); String iamRole = stackOutputs.get("SitewiseRoleArn"); + logger.info("The ARN of the IAM role is {}",iamRole); + logger.info(DASHES); logger.info(DASHES); logger.info("1. Create an AWS SiteWise Asset Model"); From 5873c6960e94eb3651e713d75e7a0d989e91391e Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 17:22:31 -0400 Subject: [PATCH 18/41] updated spec --- .../sitewise_scenario/SPECIFICATION.md | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/basics_scenarios/sitewise_scenario/SPECIFICATION.md b/basics_scenarios/sitewise_scenario/SPECIFICATION.md index 7341ad32d28..03174e02c60 100644 --- a/basics_scenarios/sitewise_scenario/SPECIFICATION.md +++ b/basics_scenarios/sitewise_scenario/SPECIFICATION.md @@ -4,7 +4,7 @@ This SDK Basics scenario demonstrates how to interact with AWS IoT SiteWise using the AWS SDK. It demonstrates various tasks such as creating a SiteWise Asset Model, creating an asset, sending data to the asset, reading data, and so on. Finally this scenario demonstrates how to clean up resources. Its purpose is to demonstrate how to get up and running with AWS IoT SiteWise and the AWS SDK. ## Resources -This Basics scenario has a depedency on an IAM role that has permissions for this service. We will create this resource using a CloudFormation template so the user does not have to manually create it. +This Basics scenario has a depedency on an IAM role that has permissions for this service. We will create this resource using a CloudFormation template so the user does not have to manually create it. You can see this functionality in the Program execution section below. ## Hello AWS IoT SiteWise This program is intended for users not familiar with the AWS IoT SiteWise Service to easily get up and running. The logic is to show use of @@ -90,6 +90,9 @@ c Continuing with the program... -------------------------------------------------------------------------------- +Use AWS CloudFormation to create an IAM role that are required for this scenario. +Stack creation requested, ARN is arn:aws:cloudformation:us-east-1:814548047983:stack/RoleSitewise/29f480c0-75fd-11ef-a42e-12cd4e534049 +Stack created successfully -------------------------------------------------------------------------------- 1. Create an AWS SiteWise Asset Model An AWS IoT SiteWise Asset Model is a way to represent the physical assets, such as equipment, @@ -102,7 +105,7 @@ Enter 'c' followed by to continue: c Continuing with the program... -The Asset Model MyAssetModel2 already exists. The id of the existing model is 754c6991-9b34-4fd3-85a5-d4261b1324a1. Moving on... +The Asset Model MyAssetModel already exists. The id of the existing model is ffbc475b-73ad-4eb6-bf28-8728818fa8ef. Moving on... Enter 'c' followed by to continue: c @@ -119,7 +122,7 @@ Enter 'c' followed by to continue: c Continuing with the program... -Asset created with ID: c11d78da-4356-4f52-8c11-24a02dcf3c5b +Asset created with ID: 4d681624-a303-46dd-8830-6189790ae915 Enter 'c' followed by to continue: c @@ -136,8 +139,8 @@ Enter 'c' followed by to continue: c Continuing with the program... -The Humidity property Id is cfd388c0-b70c-4e25-b656-675d909f7ef7 -The Temperature property Id is fac55cfe-6e7f-4c5e-8bea-2d3e333f169d +The Humidity property Id is feb4aba6-55f9-4b00-b366-27b9d7e5a747 +The Temperature property Id is 6cb505aa-6bcc-46f4-a12a-7ca5df8eb028 Enter 'c' followed by to continue: c @@ -177,14 +180,14 @@ Enter 'c' followed by to continue: c Continuing with the program... -The property name is: Temperature property +The property name is: Temperature property The value of this property is 23.5 Enter 'c' followed by to continue: c Continuing with the program... -The property name is: Humidity property +The property name is: Humidity property The value of this property is 65.0 Enter 'c' followed by to continue: @@ -202,8 +205,8 @@ Enter 'c' followed by to continue: c Continuing with the program... -Portal created successfully. Portal ID 391384ff-f439-481d-a6bb-2195fe70418e -The portal Id is 391384ff-f439-481d-a6bb-2195fe70418e +Portal created successfully. Portal ID 63e65729-b7a1-410a-aa36-94145fe92153 +The portal Id is 63e65729-b7a1-410a-aa36-94145fe92153 Enter 'c' followed by to continue: c @@ -219,7 +222,7 @@ Enter 'c' followed by to continue: c Continuing with the program... -Portal URL: https://p-9l9bnfd7.app.iotsitewise.aws +Portal URL: https://p-fy9qnrqy.app.iotsitewise.aws Enter 'c' followed by to continue: c @@ -239,8 +242,8 @@ Enter 'c' followed by to continue: c Continuing with the program... -The ARN of the gateway is arn:aws:iotsitewise:us-east-1:814548047983:gateway/417f041e-44e8-40e8-93f4-2904f3a8febd -Gateway creation completed successfully. id is 417f041e-44e8-40e8-93f4-2904f3a8febd +The ARN of the gateway is arn:aws:iotsitewise:us-east-1:814548047983:gateway/50320670-1d88-4a7e-9013-1d7e8a3af832 +Gateway creation completed successfully. id is 50320670-1d88-4a7e-9013-1d7e8a3af832 -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- 9. Describe the IoTSitewise Gateway @@ -250,9 +253,9 @@ c Continuing with the program... Gateway Name: myGateway11 -Gateway ARN: arn:aws:iotsitewise:us-east-1:814548047983:gateway/417f041e-44e8-40e8-93f4-2904f3a8febd +Gateway ARN: arn:aws:iotsitewise:us-east-1:814548047983:gateway/50320670-1d88-4a7e-9013-1d7e8a3af832 Gateway Platform: GatewayPlatform(GreengrassV2=GreengrassV2(CoreDeviceThingName=myThing78)) -Gateway Creation Date: 2024-09-13T16:50:54.037Z +Gateway Creation Date: 2024-09-18T20:34:13.117Z -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- 10. Delete the AWS IoT SiteWise Assets @@ -267,10 +270,11 @@ Enter 'c' followed by to continue: c Continuing with the program... -Portal 391384ff-f439-481d-a6bb-2195fe70418e was deleted successfully. -The Gateway was deleted +Portal 63e65729-b7a1-410a-aa36-94145fe92153 was deleted successfully. +An unexpected error occurred: Cannot invoke "java.util.concurrent.CompletableFuture.join()" because "future" is null Asset deleted successfully. Lets wait 1 min for the asset to be deleted +01:00The Gateway was deleted successfully 00:00Countdown complete! Enter 'c' followed by to continue: @@ -278,7 +282,7 @@ c Continuing with the program... Delete the AWS IoT SiteWise Asset Model -IoT SiteWise error occurred: Error message: Asset model had assets when delete was called (Service: IoTSiteWise, Status Code: 400, Request ID: 6ebc4c3e-82e8-4a8b-a6d7-de0c8ada5a9d), Error code InvalidRequestException +Asset model deleted successfully. Enter 'c' followed by to continue: c @@ -286,6 +290,8 @@ Continuing with the program... -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- +Delete stack requested .... +Stack deleted successfully. This concludes the AWS SiteWise Scenario -------------------------------------------------------------------------------- From f2907764e89a40150993f39178097ab73e960284 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 17:27:52 -0400 Subject: [PATCH 19/41] updated spec --- basics_scenarios/sitewise_scenario/SPECIFICATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basics_scenarios/sitewise_scenario/SPECIFICATION.md b/basics_scenarios/sitewise_scenario/SPECIFICATION.md index 03174e02c60..ef39ed69b66 100644 --- a/basics_scenarios/sitewise_scenario/SPECIFICATION.md +++ b/basics_scenarios/sitewise_scenario/SPECIFICATION.md @@ -8,7 +8,7 @@ This Basics scenario has a depedency on an IAM role that has permissions for thi ## Hello AWS IoT SiteWise This program is intended for users not familiar with the AWS IoT SiteWise Service to easily get up and running. The logic is to show use of -`listAssetslistAssetsPaginator`. +`listAssetsPaginator`. ## Scenario Program Flow The AWS IoT SiteWise Basics scenario executes the following operations. From ec874d620755b1b4db0bcec41230add724fa8165 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 18 Sep 2024 17:32:17 -0400 Subject: [PATCH 20/41] updated spec --- .../sitewise_scenario/SPECIFICATION.md | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/basics_scenarios/sitewise_scenario/SPECIFICATION.md b/basics_scenarios/sitewise_scenario/SPECIFICATION.md index ef39ed69b66..ba766f7e117 100644 --- a/basics_scenarios/sitewise_scenario/SPECIFICATION.md +++ b/basics_scenarios/sitewise_scenario/SPECIFICATION.md @@ -14,52 +14,52 @@ This program is intended for users not familiar with the AWS IoT SiteWise Servic The AWS IoT SiteWise Basics scenario executes the following operations. 1. **Create an AWS SiteWise Asset Model**: - - Description: This operation creates an AWS SiteWise Asset Model. Invoke the `createAssetModel` method. - - Exception Handling: Check to see if a `ResourceAlreadyExistsException` is thrown. If it is thrown, get the asset model id and move on. + - Description: This operation creates an AWS SiteWise Asset Model. Invoke the `createAssetModel` method. + - Exception Handling: Check to see if a `ResourceAlreadyExistsException` is thrown. If it is thrown, get the asset model ID and move on. 2. **Create an AWS IoT SiteWise Asset**: - Description: This operation creates an AWS SiteWise asset. - - The method `createAsset` is called to obtain the asset id. - - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + - The method `createAsset` is called to obtain the asset ID. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. 3. **Retrieve the property ID values**: - Description: To send data to an asset, we need to get the property ID values for the Temperature and Humidity properties. - - The method `listAssetModels()` is called to retrieve asset id values. - - Exception Handling: Check to see if a `IoTSiteWiseException` is thrown. There are not many other useful exceptions for this specific call. If so, display the message and end the program. + - The method `listAssetModels()` is called to retrieve the asset ID values. + - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. There are not many other useful exceptions for this specific call. If so, display the message and end the program. 4. **Send data to an AWS IoT SiteWise Asset**: - Description: This operation sends data to an IoT SiteWise Asset. - This step uses the method `batchPutAssetPropertyValue()`. - - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. 5. **Retrieve the value of the IoT SiteWise Asset property**: - Description: This operation gets data from the asset. - This step uses the method `getAssetPropertyValue()`. - - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. 6. **Create an IoT SiteWise Portal**: - - Description: This operation is creates a Sitewise portal. + - Description: This operation creates an IoT SiteWise portal. - The method `createPortal` is called. - - Exception Handling: Check to see if a `IoTSiteWiseException` is thrown. + - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. 7. **Describe the Portal**: - - Description: This operation descrines the portal and returns an URL for the portal. - - The method `describePortal()` is called and retutns URL. - - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + - Description: This operation describes the portal and returns a URL for the portal. + - The method `describePortal()` is called and returns the URL. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. 8. **Create an IoTSitewise Gateway**: - - Description: This operation creates a Sitewise Gateway. - - The method `createGateway)` is called. - - Exception Handling: Check to see if a `IoTSiteWiseException` is thrown. + - Description: This operation creates an IoT SiteWise Gateway. + - The method `createGateway` is called. + - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. -9. **Describe the Sitewise Gateway**: +9. **Describe the IoT SiteWise Gateway**: - Description: This operation describes the Gateway. - - The method `describeGateway()` is called." - - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. + - The method `describeGateway()` is called. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. -10. **Delete the AWS IoT SiteWise Assets** - - The `delete()` methods ares called to clean up the resources. - - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end program. +10. **Delete the AWS IoT SiteWise Assets**: + - The `delete()` methods are called to clean up the resources. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program." ### Program execution The following shows the output of the AWS IoT SiteWise Basics scenario in the console. From d4100071a3b38ebf83cb4bd02df88dbb1b52ff5f Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 25 Sep 2024 14:31:11 -0400 Subject: [PATCH 21/41] Rolled in reviewers changes --- javav2/example_code/iotsitewise/pom.xml | 8 + .../iotsitewise/scenario/SitewiseActions.java | 131 +++++------- .../scenario/SitewiseScenario.java | 193 ++++++++---------- 3 files changed, 146 insertions(+), 186 deletions(-) diff --git a/javav2/example_code/iotsitewise/pom.xml b/javav2/example_code/iotsitewise/pom.xml index f464fe3f557..11961182276 100644 --- a/javav2/example_code/iotsitewise/pom.xml +++ b/javav2/example_code/iotsitewise/pom.xml @@ -106,6 +106,14 @@ software.amazon.awssdk ssm + + software.amazon.awssdk + sso + + + software.amazon.awssdk + ssooidc + org.apache.logging.log4j log4j-core diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index c51dfb392f9..c7f0fa43d9a 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -5,10 +5,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import software.amazon.awssdk.services.iotsitewise.model.AssetModelPropertySummary; import software.amazon.awssdk.services.iotsitewise.model.BatchPutAssetPropertyValueResponse; import software.amazon.awssdk.services.iotsitewise.model.CreateGatewayRequest; import software.amazon.awssdk.services.iotsitewise.model.CreateGatewayResponse; import software.amazon.awssdk.services.iotsitewise.model.DeleteGatewayRequest; +import software.amazon.awssdk.services.iotsitewise.model.DeleteGatewayResponse; import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayRequest; import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayResponse; import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; @@ -40,6 +42,7 @@ import software.amazon.awssdk.services.iotsitewise.model.GetAssetPropertyValueRequest; import software.amazon.awssdk.services.iotsitewise.model.GetAssetPropertyValueResponse; import software.amazon.awssdk.services.iotsitewise.model.GreengrassV2; +import software.amazon.awssdk.services.iotsitewise.model.ListAssetModelPropertiesRequest; import software.amazon.awssdk.services.iotsitewise.model.ListAssetModelsRequest; import software.amazon.awssdk.services.iotsitewise.model.Measurement; import software.amazon.awssdk.services.iotsitewise.model.PropertyDataType; @@ -55,6 +58,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.stream.Collectors; // snippet-start:[iotsitewise.java2.actions.main] public class SitewiseActions { @@ -83,7 +88,7 @@ private static IoTSiteWiseAsyncClient getAsyncClient() { ioTSiteWiseAsyncClient = IoTSiteWiseAsyncClient.builder() .httpClient(httpClient) .overrideConfiguration(overrideConfig) - .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) + // .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build(); } return ioTSiteWiseAsyncClient; @@ -101,14 +106,14 @@ public CompletableFuture createAssetModelAsync(String .measurement(Measurement.builder().build()) .build(); - PropertyType propertyType = PropertyType.builder() + PropertyType temperaturePropertyType = PropertyType.builder() .measurement(Measurement.builder().build()) .build(); AssetModelPropertyDefinition temperatureProperty = AssetModelPropertyDefinition.builder() .name("Temperature") .dataType(PropertyDataType.DOUBLE) - .type(propertyType) + .type(temperaturePropertyType) .build(); AssetModelPropertyDefinition humidityProperty = AssetModelPropertyDefinition.builder() @@ -117,16 +122,11 @@ public CompletableFuture createAssetModelAsync(String .type(humidity) .build(); - AssetModelPropertyDefinition measurementProperty = AssetModelPropertyDefinition.builder() - .name("Temperature") - .dataType(PropertyDataType.DOUBLE) - .type(temperatureProperty.type()) - .build(); CreateAssetModelRequest createAssetModelRequest = CreateAssetModelRequest.builder() .assetModelName(name) .assetModelDescription("This is my asset model") - .assetModelProperties(measurementProperty, humidityProperty) + .assetModelProperties(temperatureProperty, humidityProperty) .build(); return getAsyncClient().createAssetModel(createAssetModelRequest) @@ -165,8 +165,8 @@ public CompletableFuture createAssetAsync(String assetName, } // snippet-end:[sitewise.java2_create_asset.main] - // snippet-start:[sitewise.java2_put_property.main] - public CompletableFuture sendDataToSiteWiseAsync(String assetId, String humPropId, String idHum) { + // snippet-start:[sitewise.java2_put_batch_property.main] + public CompletableFuture sendDataToSiteWiseAsync(String assetId, String tempPropertyId, String humidityPropId) { Map sampleData = generateSampleData(); long timestamp = Instant.now().toEpochMilli(); @@ -180,7 +180,7 @@ public CompletableFuture sendDataToSiteWiseA PutAssetPropertyValueEntry.builder() .entryId("entry-3") .assetId(assetId) - .propertyId(humPropId) + .propertyId(tempPropertyId) .propertyValues(Arrays.asList( AssetPropertyValue.builder() .value(Variant.builder() @@ -193,7 +193,7 @@ public CompletableFuture sendDataToSiteWiseA PutAssetPropertyValueEntry.builder() .entryId("entry-4") .assetId(assetId) - .propertyId(idHum) + .propertyId(humidityPropId) .propertyValues(Arrays.asList( AssetPropertyValue.builder() .value(Variant.builder() @@ -209,13 +209,13 @@ public CompletableFuture sendDataToSiteWiseA return getAsyncClient().batchPutAssetPropertyValue(request) .whenComplete((response, exception) -> { if (exception != null) { - throw new RuntimeException("Failed to send data to SiteWise: " + exception.getMessage(), exception); + logger.error("An exception occurred: {}", exception.getCause().getMessage()); } else { logger.info("Data sent successfully."); } }); } - // snippet-end:[sitewise.java2_put_property.main] + // snippet-end:[sitewise.java2_put_batch_property.main] // snippet-start:[sitewise.java2_get_property.main] // TODO -- fix this including Javadoc @@ -240,53 +240,21 @@ public void getAssetPropValueAsync(String propName, String propId, String assetI // snippet-start:[sitewise.java2.describe.asset.model.main] /** - * Finds the property ID of a given property name asynchronously. - * - * @param propertyName the name of the property to search for - * @return a {@link CompletableFuture} that completes with the property ID if found, or null if not found - * @throws RuntimeException if an exception occurs during the search + * @param assetModelId The Id of the asset model. + * @return A map of the asset model properties when the CompletableFuture completes. */ - public CompletableFuture findPropertyIdByNameAsync(String propertyName) { - ListAssetModelsRequest listRequest = ListAssetModelsRequest.builder().build(); - - return getAsyncClient().listAssetModels(listRequest) - .thenCompose(listResponse -> { - List> futures = new ArrayList<>(); - for (AssetModelSummary modelSummary : listResponse.assetModelSummaries()) { - DescribeAssetModelRequest describeRequest = DescribeAssetModelRequest.builder() - .assetModelId(modelSummary.id()) - .build(); - - CompletableFuture future = getAsyncClient().describeAssetModel(describeRequest) - .thenApply(describeResponse -> { - for (AssetModelProperty property : describeResponse.assetModelProperties()) { - if (property.name().equals(propertyName)) { - return property.id(); - } - } - return null; - }); - - futures.add(future); - } - - return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) - .thenApply(v -> { - for (CompletableFuture future : futures) { - String propertyId = future.join(); - if (propertyId != null) { - return propertyId; - } - } - return null; - }); - }) - .handle((propertyId, exception) -> { - if (exception != null) { - throw new RuntimeException("Failed to find property by name: " + exception.getMessage(), exception); - } - return propertyId; - }); + CompletableFuture> getPropertyIds(String assetModelId){ + ListAssetModelPropertiesRequest modelPropertiesRequest = ListAssetModelPropertiesRequest.builder().assetModelId(assetModelId).build(); + return getAsyncClient().listAssetModelProperties(modelPropertiesRequest) + .handle( (response, throwable) -> { + if (response != null){ + return response.assetModelPropertySummaries().stream() + .collect(Collectors + .toMap(AssetModelPropertySummary::name, AssetModelPropertySummary::id)); + } else { + throw (CompletionException) throwable.getCause(); + } + }); } // snippet-end:[sitewise.java2.describe.asset.model.main] @@ -306,7 +274,9 @@ public CompletableFuture deleteAssetAsync(String assetId) { return getAsyncClient().deleteAsset(deleteAssetRequest) .whenComplete((response, exception) -> { if (exception != null) { - throw new RuntimeException("Failed to delete asset with ID: " + assetId + ". Error: " + exception.getMessage(), exception); + logger.error("An error occurred deleting asset with id: {}", assetId); + } else { + logger.info("Request to delete the asset completed successfully."); } }); } @@ -352,11 +322,12 @@ public CompletableFuture createPortalAsync(String portalName, String iam .build(); return getAsyncClient().createPortal(createPortalRequest) - .thenApply(CreatePortalResponse::portalId) - .whenComplete((portalId, exception) -> { + .handle ((response, exception) -> { if (exception != null) { - throw new RuntimeException("Failed to create portal with name: " + portalName + ". Error: " + exception.getMessage(), exception); + logger.error("Failed to create portal: {} ", exception.getCause().getMessage()); + throw (CompletionException) exception; } + return response.portalId(); }); } // snippet-end:[sitewise.java2.create.portal.main] @@ -438,7 +409,7 @@ public CompletableFuture describePortalAsync(String portalId) { * @return a {@link CompletableFuture} containing the {@link CreateGatewayResponse} representing the created gateway * @throws RuntimeException if there was an error creating the gateway */ - public CompletableFuture createGatewayAsync(String gatewayName, String myThing) { + public CompletableFuture createGatewayAsync(String gatewayName, String myThing) { GreengrassV2 gg = GreengrassV2.builder() .coreDeviceThingName(myThing) .build(); @@ -459,29 +430,29 @@ public CompletableFuture createGatewayAsync(String gatewa return getAsyncClient().createGateway(createGatewayRequest) .handle((response, exception) -> { if (exception != null) { - throw new RuntimeException("Error creating gateway", exception); + logger.error("Error creating the gateway."); + throw (RuntimeException) exception; } System.out.println("The ARN of the gateway is " + response.gatewayArn()); - return response; + return response.gatewayId(); }); } // snippet-end:[sitewise.java2.create.gateway.main] // snippet-start:[sitewise.java2.delete.gateway.main] - public CompletableFuture deleteGatewayAsync(String gatewayARN) { + public CompletableFuture deleteGatewayAsync(String gatewayARN) { DeleteGatewayRequest deleteGatewayRequest = DeleteGatewayRequest.builder() .gatewayId(gatewayARN) .build(); - getAsyncClient().deleteGateway(deleteGatewayRequest) + return getAsyncClient().deleteGateway(deleteGatewayRequest) .whenComplete((response, exception) -> { if (exception != null) { - throw new RuntimeException("Error creating gateway", exception); + logger.error("An error occurred during the deleteGateway method."); } else { - logger.info("The Gateway was deleted successfully"); + logger.info("The Gateway was deleted successfully."); } }); - return null; } // snippet-end:[sitewise.java2.delete.gateway.main] @@ -492,15 +463,15 @@ public CompletableFuture describeGatewayAsync(String ga .build(); return getAsyncClient().describeGateway(request) - .handle((response, exception) -> { + .whenComplete((response, exception) -> { if (exception != null) { - throw new RuntimeException("Failed to describe the SiteWise gateway", exception); + logger.error("An error occurred during the describeGateway method"); + } else { + logger.info("Gateway Name: " + response.gatewayName()); + logger.info("Gateway ARN: " + response.gatewayArn()); + logger.info("Gateway Platform: " + response.gatewayPlatform().toString()); + logger.info("Gateway Creation Date: " + response.creationDate()); } - logger.info("Gateway Name: " + response.gatewayName()); - logger.info("Gateway ARN: " + response.gatewayArn()); - logger.info("Gateway Platform: " + response.gatewayPlatform().toString()); - logger.info("Gateway Creation Date: " + response.creationDate()); - return response; }); } // snippet-end:[sitewise.java2.describe.gateway.main] diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index 618267ba020..ba4cbe9c737 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -15,6 +15,9 @@ import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayResponse; import software.amazon.awssdk.services.iotsitewise.model.IoTSiteWiseException; import software.amazon.awssdk.services.iotsitewise.model.ResourceAlreadyExistsException; +import software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException; + +import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.concurrent.CompletableFuture; @@ -59,7 +62,7 @@ public static void main(String[] args) throws Throwable { String myThing = "myThing78"; logger.info(""" - AWS IoT SiteWise is a fully managed industrial software-as-a-service (SaaS) that + AWS IoT SiteWise is a fully managed software-as-a-service (SaaS) that makes it easy to collect, store, organize, and monitor data from industrial equipment and processes. It is designed to help industrial and manufacturing organizations collect data from their equipment and processes, and use that data to make informed decisions about their operations. @@ -104,6 +107,8 @@ public static void runScenario(String assetModelName, String assetName, String processes, and systems, that exist in an industrial environment. This model provides a structured and hierarchical representation of these assets, allowing users to define the relationships and properties of each asset. + + This scenario creates two asset model properties: temperature and humidity. """); waitForInputToContinue(scanner); String assetModelId; @@ -131,8 +136,8 @@ public static void runScenario(String assetModelName, String assetName, String logger.info(DASHES); logger.info("2. Create an AWS IoT SiteWise Asset"); logger.info(""" - The IoT SiteWise model defines the structure and metadata for your physical assets. Now we - can use the asset model to create the asset. + The IoT SiteWise model that we just created defines the structure and metadata for your physical assets. Now we create + an asset from the asset model. """); waitForInputToContinue(scanner); @@ -147,7 +152,7 @@ public static void runScenario(String assetModelName, String assetName, String Throwable cause = rt.getCause(); while (cause != null) { if (cause instanceof software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException) { - logger.info("The AWS resource was not found: {}", cause.getMessage()); + logger.info("The AWS resource was not found: {}", cause.getMessage()); // QUESTION: What resource? the asset model? Clarify if that is the case? break; } cause = cause.getCause(); @@ -164,42 +169,27 @@ public static void runScenario(String assetModelName, String assetName, String logger.info(DASHES); logger.info("3. Retrieve the property ID values"); logger.info(""" - To send data to an asset, we need to get the property ID values for the - Temperature and Humidity properties. + To send data to an asset, we need to get the property ID values. In this scenario, we access the + temperature and humidity property ID values. """); waitForInputToContinue(scanner); - String humPropId; - try { - CompletableFuture future = sitewiseActions.findPropertyIdByNameAsync("Humidity"); - humPropId = future.join(); - logger.info("The Humidity property Id is {}", humPropId); - - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause instanceof IoTSiteWiseException siteWiseEx) { - logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); - } else { - logger.info("An unexpected error occurred: " + rt.getMessage()); - } - throw cause; - } - - String tempPropId; + Map propertyIds = null; try { - CompletableFuture future = sitewiseActions.findPropertyIdByNameAsync("Temperature"); - tempPropId = future.join(); - logger.info("The Temperature property Id is {}", tempPropId); - - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause instanceof IoTSiteWiseException siteWiseEx) { - logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + propertyIds = sitewiseActions.getPropertyIds(assetModelId).join(); + } catch (RuntimeException e) { + Throwable cause = e.getCause(); + if (cause != null && cause instanceof IoTSiteWiseException) { + logger.error("IoTSiteWiseException occurred: {}", cause.getMessage(), e); } else { - logger.info("An unexpected error occurred: " + rt.getMessage()); + logger.error("An unexpected error occurred: {}", e.getMessage(), e); } - throw cause; + return; } + String humPropId = propertyIds.get("Humidity"); + logger.info("The Humidity property Id is {}", humPropId); + String tempPropId = propertyIds.get("Temperature"); + logger.info("The Temperature property Id is {}", tempPropId); waitForInputToContinue(scanner); logger.info(DASHES); @@ -211,28 +201,20 @@ public static void runScenario(String assetModelName, String assetName, String multiple sources, normalize the data into a standard format, and store it in a centralized location. This makes it easier to analyze and gain insights from the data. - This example demonstrate how to generate sample data and ingest it into the AWS IoT SiteWise asset. + In this example, we generate sample temperature and humidity data and send it to the AWS IoT SiteWise asset. """); waitForInputToContinue(scanner); try { - CompletableFuture future = sitewiseActions.sendDataToSiteWiseAsync(assetId, tempPropId, humPropId); - future.join(); + sitewiseActions.sendDataToSiteWiseAsync(assetId, tempPropId, humPropId).join(); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); - while (cause != null) { - if (cause instanceof software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException) { - logger.info("The AWS resource was not found: {}", cause.getMessage()); - break; - } - cause = cause.getCause(); - } - - if (cause == null) { - logger.info("An unexpected error occurred: {}", rt.getMessage()); + if (cause != null && cause instanceof ResourceNotFoundException) { + logger.error("The AWS resource was not found: {}", cause.getMessage(), rt); + } else { + logger.error("An unexpected error occurred: {}", rt.getMessage(), rt); } - - throw cause; + return; } waitForInputToContinue(scanner); logger.info(DASHES); @@ -247,7 +229,7 @@ public static void runScenario(String assetModelName, String assetName, String """); waitForInputToContinue(scanner); try { - sitewiseActions.getAssetPropValueAsync("Temperature property", tempPropId, assetId); + sitewiseActions.getAssetPropValueAsync("Temperature property", tempPropId, assetId); // FIXME <------------------ waitForInputToContinue(scanner); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); @@ -264,7 +246,7 @@ public static void runScenario(String assetModelName, String assetName, String } throw cause; } - sitewiseActions.getAssetPropValueAsync("Humidity property", humPropId, assetId); + sitewiseActions.getAssetPropValueAsync("Humidity property", humPropId, assetId); // FIXME <------------------ waitForInputToContinue(scanner); logger.info(DASHES); @@ -277,18 +259,17 @@ public static void runScenario(String assetModelName, String assetName, String waitForInputToContinue(scanner); String portalId = ""; try { - CompletableFuture future = sitewiseActions.createPortalAsync(portalName, iamRole, contactEmail); - portalId = future.join(); + portalId = sitewiseActions.createPortalAsync(portalName, iamRole, contactEmail).join(); logger.info("Portal created successfully. Portal ID {}", portalId); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); - if (cause instanceof IoTSiteWiseException siteWiseEx) { - logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + if (cause != null && cause instanceof IoTSiteWiseException siteWiseEx) { + logger.error("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); } else { - logger.info("An unexpected error occurred: " + rt.getMessage()); + logger.error("An unexpected error occurred: {}", rt.getMessage()); } + return; } - logger.info("The portal Id is " + portalId); waitForInputToContinue(scanner); logger.info(DASHES); @@ -299,52 +280,59 @@ public static void runScenario(String assetModelName, String assetName, String """); waitForInputToContinue(scanner); try { - CompletableFuture future = sitewiseActions.describePortalAsync(portalId); - String portalUrl = future.join(); + String portalUrl = sitewiseActions.describePortalAsync(portalId).join(); logger.info("Portal URL: {}", portalUrl); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); - if (cause instanceof IoTSiteWiseException siteWiseEx) { - logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); } else { - logger.info("An unexpected error occurred: " + rt.getMessage()); + logger.error("An unexpected error occurred: {}", rt.getMessage()); } + return; } waitForInputToContinue(scanner); logger.info(DASHES); logger.info(DASHES); - logger.info("8. Create an IoTSitewise Gateway"); + logger.info("8. Create an IoT SiteWise Gateway"); logger.info( """ - IoTSitewise Gateway serves as the bridge between industrial equipment, sensors, and the - cloud-based IoTSitewise service. It is responsible for securely collecting, processing, and - transmitting data from various industrial assets to the IoTSitewise platform, + IoT SiteWise Gateway serves as the bridge between industrial equipment, sensors, and the + cloud-based IoT SiteWise service. It is responsible for securely collecting, processing, and + transmitting data from various industrial assets to the IoT SiteWise platform, enabling real-time monitoring, analysis, and optimization of industrial operations. """); waitForInputToContinue(scanner); String gatewayId = ""; try { - CompletableFuture future = sitewiseActions.createGatewayAsync(gatewayName, myThing); - CreateGatewayResponse response = future.join(); - gatewayId = response.gatewayId(); - logger.info("Gateway creation completed successfully. id is {}",gatewayId ); - } catch (RuntimeException e) { - logger.info("Failed to create gateway: {} ", e.getMessage()); + gatewayId = sitewiseActions.createGatewayAsync(gatewayName, myThing).join(); + logger.info("Gateway creation completed successfully. id is {}", gatewayId ); + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause != null && cause instanceof IoTSiteWiseException siteWiseEx) { + logger.error("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } else { + logger.error("An unexpected error occurred: {}", rt.getMessage()); + } + return; } logger.info(DASHES); - - logger.info(DASHES); - logger.info("9. Describe the IoTSitewise Gateway"); + + logger.info("9. Describe the IoT SiteWise Gateway"); waitForInputToContinue(scanner); try { - CompletableFuture future = sitewiseActions.describeGatewayAsync(gatewayId) ; - future.join(); - - } catch (RuntimeException e) { - System.err.println("Failed to create gateway: " + e.getMessage()); + sitewiseActions.describeGatewayAsync(gatewayId).join(); + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); + } else { + logger.error("An unexpected error occurred: {}", rt.getMessage()); + } + return; } logger.info(DASHES); @@ -355,67 +343,60 @@ public static void runScenario(String assetModelName, String assetName, String Before you can delete the Asset Model, you must delete the assets. """); - logger.info("Would you like to delete the IoT Sitewise Assets? (y/n)"); + logger.info("Would you like to delete the IoT SiteWise Assets? (y/n)"); String delAns = scanner.nextLine().trim(); if (delAns.equalsIgnoreCase("y")) { - logger.info("You selected to delete the Sitewise assets."); + logger.info("You selected to delete the SiteWise assets."); waitForInputToContinue(scanner); try { - CompletableFuture future = sitewiseActions.deletePortalAsync(portalId); - future.join(); + sitewiseActions.deletePortalAsync(portalId).join(); logger.info("Portal {} was deleted successfully.", portalId); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); - if (cause instanceof IoTSiteWiseException siteWiseEx) { - logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); } else { - logger.info("An unexpected error occurred: " + rt.getMessage()); + logger.error("An unexpected error occurred: {}", rt.getMessage()); } } // Delete the Gateway. try { - CompletableFuture future = sitewiseActions.deleteGatewayAsync(gatewayId); - future.join(); - + sitewiseActions.deleteGatewayAsync(gatewayId).join(); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); - if (cause instanceof IoTSiteWiseException siteWiseEx) { - logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); } else { - logger.info("An unexpected error occurred: " + rt.getMessage()); + logger.error("An unexpected error occurred: {}", rt.getMessage()); } } try { - CompletableFuture future = sitewiseActions.deleteAssetAsync(assetId); - future.join(); - logger.info("Asset deleted successfully."); - + sitewiseActions.deleteAssetAsync(assetId).join(); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); - if (cause instanceof IoTSiteWiseException siteWiseEx) { - logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); } else { - logger.info("An unexpected error occurred: " + rt.getMessage()); + logger.error("An unexpected error occurred: {}", rt.getMessage()); } } - logger.info("Lets wait 1 min for the asset to be deleted"); + logger.info("Let's wait 1 minute for the asset to be deleted."); countdown(1); waitForInputToContinue(scanner); logger.info("Delete the AWS IoT SiteWise Asset Model"); try { - CompletableFuture future = sitewiseActions.deleteAssetModelAsync(assetModelId); - future.join(); + sitewiseActions.deleteAssetModelAsync(assetModelId).join(); logger.info("Asset model deleted successfully."); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); - if (cause instanceof IoTSiteWiseException siteWiseEx) { - logger.info("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); } else { - logger.info("An unexpected error occurred: " + rt.getMessage()); + logger.error("An unexpected error occurred: {}", rt.getMessage()); } } waitForInputToContinue(scanner); @@ -427,7 +408,7 @@ public static void runScenario(String assetModelName, String assetName, String logger.info(DASHES); CloudFormationHelper.destroyCloudFormationStack(ROLES_STACK); - logger.info("This concludes the AWS SiteWise Scenario"); + logger.info("This concludes the AWS IoT SiteWise Scenario"); logger.info(DASHES); } From ba100f79bf3656f26b86b708b60c4fc6552cbb56 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 25 Sep 2024 14:56:19 -0400 Subject: [PATCH 22/41] updated Spec --- .../sitewise_scenario/SPECIFICATION.md | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/basics_scenarios/sitewise_scenario/SPECIFICATION.md b/basics_scenarios/sitewise_scenario/SPECIFICATION.md index ba766f7e117..95545274577 100644 --- a/basics_scenarios/sitewise_scenario/SPECIFICATION.md +++ b/basics_scenarios/sitewise_scenario/SPECIFICATION.md @@ -1,31 +1,40 @@ # AWS IoT SiteWise Service Scenario Specification ## Overview -This SDK Basics scenario demonstrates how to interact with AWS IoT SiteWise using the AWS SDK. It demonstrates various tasks such as creating a SiteWise Asset Model, creating an asset, sending data to the asset, reading data, and so on. Finally this scenario demonstrates how to clean up resources. Its purpose is to demonstrate how to get up and running with AWS IoT SiteWise and the AWS SDK. +This SDK Basics scenario demonstrates how to interact with AWS IoT SiteWise using an AWS SDK. +It demonstrates various tasks such as creating a SiteWise Asset Model, creating an asset, +sending data to the asset, reading data, and so on. Finally this scenario demonstrates how +to clean up resources. Its purpose is to demonstrate how to get up and running with +AWS IoT SiteWise and an AWS SDK. ## Resources -This Basics scenario has a depedency on an IAM role that has permissions for this service. We will create this resource using a CloudFormation template so the user does not have to manually create it. You can see this functionality in the Program execution section below. +This Basics scenario requires an IAM role that has permissions to work with AWS IoT +SiteWise service. The scenario creates this resource using a CloudFormation template. ## Hello AWS IoT SiteWise This program is intended for users not familiar with the AWS IoT SiteWise Service to easily get up and running. The logic is to show use of `listAssetsPaginator`. -## Scenario Program Flow +## Basics Scenario Program Flow The AWS IoT SiteWise Basics scenario executes the following operations. 1. **Create an AWS SiteWise Asset Model**: - - Description: This operation creates an AWS SiteWise Asset Model. Invoke the `createAssetModel` method. - - Exception Handling: Check to see if a `ResourceAlreadyExistsException` is thrown. If it is thrown, get the asset model ID and move on. + - Description: This step creates an AWS SiteWise Asset Model by invoking the `createAssetModel` method. + - Exception Handling: Check to see if a `ResourceAlreadyExistsException` is thrown. + If it is thrown, get the asset model ID and move on. 2. **Create an AWS IoT SiteWise Asset**: - Description: This operation creates an AWS SiteWise asset. - The method `createAsset` is called to obtain the asset ID. - - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, + display the message and end the program. 3. **Retrieve the property ID values**: - - Description: To send data to an asset, we need to get the property ID values for the Temperature and Humidity properties. - - The method `listAssetModels()` is called to retrieve the asset ID values. - - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. There are not many other useful exceptions for this specific call. If so, display the message and end the program. + - Description: To send data to an asset, we need to get the property ID values for the + the model properties. This scenario uses temperature and humidity properties. + - The method `listAssetModelProperties()` is called to retrieve the property ID values. + - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. There are not + many other useful exceptions for this specific call. If so, display the message and end the program. 4. **Send data to an AWS IoT SiteWise Asset**: - Description: This operation sends data to an IoT SiteWise Asset. @@ -47,7 +56,7 @@ The AWS IoT SiteWise Basics scenario executes the following operations. - The method `describePortal()` is called and returns the URL. - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. -8. **Create an IoTSitewise Gateway**: +8. **Create an IoTSiteWise Gateway**: - Description: This operation creates an IoT SiteWise Gateway. - The method `createGateway` is called. - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. From b6777e93aad521a8ce941a3b2afe493be3615635 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 26 Sep 2024 09:54:24 -0400 Subject: [PATCH 23/41] updated Sitewise Java examples --- .../iotsitewise/CreateBulkImportJob.java | 165 ------------------ 1 file changed, 165 deletions(-) delete mode 100644 javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/CreateBulkImportJob.java diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/CreateBulkImportJob.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/CreateBulkImportJob.java deleted file mode 100644 index 0f2005b9845..00000000000 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/CreateBulkImportJob.java +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.iotsitewise; - -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseClient; -import software.amazon.awssdk.services.iotsitewise.model.ColumnName; -import software.amazon.awssdk.services.iotsitewise.model.CreateBulkImportJobRequest; -import software.amazon.awssdk.services.iotsitewise.model.CreateBulkImportJobResponse; -import software.amazon.awssdk.services.iotsitewise.model.Csv; -import software.amazon.awssdk.services.iotsitewise.model.CustomerManagedS3Storage; -import software.amazon.awssdk.services.iotsitewise.model.DescribeStorageConfigurationRequest; -import software.amazon.awssdk.services.iotsitewise.model.DescribeStorageConfigurationResponse; -import software.amazon.awssdk.services.iotsitewise.model.ErrorReportLocation; -import software.amazon.awssdk.services.iotsitewise.model.File; -import software.amazon.awssdk.services.iotsitewise.model.FileFormat; -import software.amazon.awssdk.services.iotsitewise.model.InvalidRequestException; -import software.amazon.awssdk.services.iotsitewise.model.IoTSiteWiseException; -import software.amazon.awssdk.services.iotsitewise.model.JobConfiguration; -import software.amazon.awssdk.services.iotsitewise.model.MultiLayerStorage; -import software.amazon.awssdk.services.iotsitewise.model.PutStorageConfigurationRequest; -import software.amazon.awssdk.services.iotsitewise.model.PutStorageConfigurationResponse; -import software.amazon.awssdk.services.iotsitewise.model.StorageType; - -import java.util.ArrayList; -import java.util.List; - -public class CreateBulkImportJob { - - public static void main(String[]args){ - setConfig(); - checkStorageConfig(); - createBulkImportJob(); - } - - private static IoTSiteWiseClient getClient() { - IoTSiteWiseClient client = IoTSiteWiseClient.builder() - .region(Region.US_EAST_1) - .build(); - - return client; - } - - public static void createBulkImportJob() { - List files = new ArrayList<>(); - files.add(software.amazon.awssdk.services.iotsitewise.model.File.builder() - .bucket("scottsitewise") - .key("data.csv") - .build()); - - Csv csvFormat = Csv.builder() - .columnNames( - ColumnName.ASSET_ID, // Correct column names - ColumnName.PROPERTY_ID, // Correct column names - ColumnName.DATA_TYPE, - ColumnName.TIMESTAMP_SECONDS, - ColumnName.VALUE - ) - .build(); - - FileFormat fileFormat = FileFormat.builder() - .csv(csvFormat) // Set headers - .build(); - - JobConfiguration job = JobConfiguration.builder() - .fileFormat(fileFormat) - .build(); - - ErrorReportLocation errorReportLocation = ErrorReportLocation.builder() - .bucket("scottsitewise") - .prefix("") - .build(); - - CreateBulkImportJobRequest bulkImportJobRequest = CreateBulkImportJobRequest.builder() - .jobName("BulkImportJob") - .errorReportLocation(errorReportLocation) - .jobRoleArn("arn:aws:iam::814548047983:role/AWSIoTSiteWiseMonitorServiceRole_8jLqg43nJ") - .files(files) - .jobConfiguration(job) - .build(); - - try { - CreateBulkImportJobResponse res = getClient().createBulkImportJob(bulkImportJobRequest); - System.out.println("It worked"); - - } catch (InvalidRequestException e) { - System.err.println("Error creating bulk import job: " + e.getMessage()); - e.printStackTrace(); - } catch (IoTSiteWiseException e) { - System.err.println("Unexpected error occurred: " + e.getMessage()); - e.printStackTrace(); - } - } - - public static void checkStorageConfig() { - DescribeStorageConfigurationRequest request = DescribeStorageConfigurationRequest.builder().build(); - - try { - // Pass the request object to the describeStorageConfiguration method - DescribeStorageConfigurationResponse response = getClient().describeStorageConfiguration(request); - - // Output the current storage configuration - System.out.println("Current Storage Type: " + response.storageType()); - - // Check if Multi-Layer Storage is enabled - if (response.multiLayerStorage() != null) { - System.out.println("Multi-Layer Storage is enabled: " + response.multiLayerStorage()); - } else { - System.out.println("Multi-Layer Storage is not enabled."); - } - } catch (IoTSiteWiseException e) { - System.err.println("Failed to describe storage configuration: " + e.getMessage()); - e.printStackTrace(); - } - } - public static void setConfig() { - CustomerManagedS3Storage managedS3Storage = CustomerManagedS3Storage.builder() - .roleArn("arn:aws:iam::814548047983:role/service-role/AWSIoTSiteWiseMonitorServiceRole_8jLqg43nJ") - .s3ResourceArn("arn:aws:s3:::scottsitewise") - .build(); - - // Configure the S3 bucket for cold tier storage in multi-layer storage - MultiLayerStorage multiLayerStorage = MultiLayerStorage.builder() - .customerManagedS3Storage(managedS3Storage) - .build(); - - PutStorageConfigurationRequest storageConfigurationRequest = PutStorageConfigurationRequest.builder() - .storageType(StorageType.MULTI_LAYER_STORAGE) // Specify the storage type - .multiLayerStorage(multiLayerStorage) - .build(); - - try { - // Call the API to set the storage configuration - PutStorageConfigurationResponse response = getClient().putStorageConfiguration(storageConfigurationRequest); - System.out.println("Multi-layer storage configuration updated: " + response); - - // Optional: Check if cold storage is ready for bulk imports - checkStorageReadyForBulkImports(); - - } catch (InvalidRequestException e) { - System.err.println("Error creating bulk import job: " + e.getMessage()); - e.printStackTrace(); - } catch (IoTSiteWiseException e) { - System.err.println("Unexpected error occurred: " + e.getMessage()); - e.printStackTrace(); - } - } - - // Additional method to check if storage is ready for bulk imports - private static void checkStorageReadyForBulkImports() { - DescribeStorageConfigurationRequest request = DescribeStorageConfigurationRequest.builder().build(); - try { - DescribeStorageConfigurationResponse response = getClient().describeStorageConfiguration(request); - if (response.multiLayerStorage() != null) { - System.out.println("Cold tier storage is configured for bulk imports."); - } else { - System.out.println("Cold tier storage is NOT configured for bulk imports."); - } - } catch (IoTSiteWiseException e) { - System.err.println("Failed to describe storage configuration: " + e.getMessage()); - e.printStackTrace(); - } - } -} From 094a7099965c15bdeb5b0490298090fbbe854270 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 26 Sep 2024 10:02:37 -0400 Subject: [PATCH 24/41] updated Sitewise YAML file --- .doc_gen/metadata/iot_sitewise_metadata.yaml | 2 +- .../example/iotsitewise/scenario/SitewiseActions.java | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/.doc_gen/metadata/iot_sitewise_metadata.yaml b/.doc_gen/metadata/iot_sitewise_metadata.yaml index 8a7f7027423..957e674b013 100644 --- a/.doc_gen/metadata/iot_sitewise_metadata.yaml +++ b/.doc_gen/metadata/iot_sitewise_metadata.yaml @@ -157,7 +157,7 @@ iotsitewise_BatchPutAssetPropertyValue: excerpts: - description: snippet_tags: - - sitewise.java2_put_property.main + - sitewise.java2_put_batch_property.main services: iotsitewise: {BatchPutAssetPropertyValue} iotsitewise_CreateAsset: diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index c7f0fa43d9a..18a3116d135 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -5,6 +5,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.services.iotsitewise.model.AssetModelPropertySummary; import software.amazon.awssdk.services.iotsitewise.model.BatchPutAssetPropertyValueResponse; import software.amazon.awssdk.services.iotsitewise.model.CreateGatewayRequest; @@ -13,13 +14,11 @@ import software.amazon.awssdk.services.iotsitewise.model.DeleteGatewayResponse; import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayRequest; import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayResponse; -import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.retry.RetryPolicy; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseAsyncClient; -import software.amazon.awssdk.services.iotsitewise.model.AssetModelProperty; import software.amazon.awssdk.services.iotsitewise.model.AssetModelPropertyDefinition; import software.amazon.awssdk.services.iotsitewise.model.AssetModelSummary; import software.amazon.awssdk.services.iotsitewise.model.AssetPropertyValue; @@ -36,7 +35,6 @@ import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetResponse; import software.amazon.awssdk.services.iotsitewise.model.DeletePortalRequest; import software.amazon.awssdk.services.iotsitewise.model.DeletePortalResponse; -import software.amazon.awssdk.services.iotsitewise.model.DescribeAssetModelRequest; import software.amazon.awssdk.services.iotsitewise.model.DescribePortalRequest; import software.amazon.awssdk.services.iotsitewise.model.GatewayPlatform; import software.amazon.awssdk.services.iotsitewise.model.GetAssetPropertyValueRequest; @@ -52,10 +50,8 @@ import software.amazon.awssdk.services.iotsitewise.model.Variant; import java.time.Duration; import java.time.Instant; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -80,15 +76,12 @@ private static IoTSiteWiseAsyncClient getAsyncClient() { ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder() .apiCallTimeout(Duration.ofMinutes(2)) .apiCallAttemptTimeout(Duration.ofSeconds(90)) - .retryPolicy(RetryPolicy.builder() - .numRetries(3) - .build()) + .retryStrategy(RetryMode.STANDARD) .build(); ioTSiteWiseAsyncClient = IoTSiteWiseAsyncClient.builder() .httpClient(httpClient) .overrideConfiguration(overrideConfig) - // .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build(); } return ioTSiteWiseAsyncClient; From 628c6c22e2ac19ec8bbaaacd6676e800be5bec81 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 26 Sep 2024 10:05:41 -0400 Subject: [PATCH 25/41] updated Sitewise Java file --- .../com/example/iotsitewise/scenario/CloudFormationHelper.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java index 740904b43ed..75282f0e61f 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java @@ -1,3 +1,6 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + package com.example.iotsitewise.scenario; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From 7add687fb956397075ec2e46d5df27968859a314 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 26 Sep 2024 10:09:05 -0400 Subject: [PATCH 26/41] updated Sitewise Readme --- javav2/example_code/iotsitewise/README.md | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/javav2/example_code/iotsitewise/README.md b/javav2/example_code/iotsitewise/README.md index b337bbacab3..9318e7b4c5e 100644 --- a/javav2/example_code/iotsitewise/README.md +++ b/javav2/example_code/iotsitewise/README.md @@ -45,20 +45,20 @@ Code examples that show you how to perform the essential operations within a ser Code excerpts that show you how to call individual service functions. -- [BatchPutAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L168) -- [CreateAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L142) -- [CreateAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L92) -- [CreateGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L434) -- [CreatePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L337) -- [DeleteAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L293) -- [DeleteAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L315) -- [DeleteGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L470) -- [DeletePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L364) -- [DescribeAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L241) -- [DescribeGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L488) -- [DescribePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L410) -- [GetAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L220) -- [ListAssetModels](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L386) +- [BatchPutAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L161) +- [CreateAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L135) +- [CreateAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L90) +- [CreateGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L398) +- [CreatePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L300) +- [DeleteAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L254) +- [DeleteAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L278) +- [DeleteGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L435) +- [DeletePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L328) +- [DescribeAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L234) +- [DescribeGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L452) +- [DescribePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L374) +- [GetAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L213) +- [ListAssetModels](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L350) From f89fc0bd3dfb1d4ff65b25b152b9a79f38d97bba Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 26 Sep 2024 14:08:48 -0400 Subject: [PATCH 27/41] updated Sitewise Java files --- javav2/example_code/iotsitewise/pom.xml | 4 + .../example/iotsitewise/HelloSitewise.java | 13 +- .../scenario/CloudFormationHelper.java | 2 +- .../iotsitewise/scenario/SitewiseActions.java | 2 +- .../scenario/SitewiseScenario.java | 36 ++- .../src/test/java/SitewiseTests.java | 255 ++++++++++++++++++ 6 files changed, 282 insertions(+), 30 deletions(-) diff --git a/javav2/example_code/iotsitewise/pom.xml b/javav2/example_code/iotsitewise/pom.xml index 11961182276..843d3ebdbae 100644 --- a/javav2/example_code/iotsitewise/pom.xml +++ b/javav2/example_code/iotsitewise/pom.xml @@ -66,6 +66,10 @@ 5.9.2 test + + software.amazon.awssdk + secretsmanager + software.amazon.awssdk netty-nio-client diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java index e223f1fbf31..7f0b39b2478 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java @@ -32,20 +32,19 @@ public static void main(String[] args) { } String assetModelId = args[0]; - IoTSiteWiseAsyncClient siteWiseAsyncClient = IoTSiteWiseAsyncClient.builder() - .region(Region.US_EAST_1) - .build(); - - fetchAssets(siteWiseAsyncClient, assetModelId); + fetchAssets(assetModelId); } /** * Fetches assets from AWS IoT SiteWise using the provided {@link IoTSiteWiseAsyncClient}. * - * @param siteWiseAsyncClient the AWS IoT SiteWise asynchronous client to use for the request * @param modelId the ID of the asset model to fetch assets for */ - public static void fetchAssets(IoTSiteWiseAsyncClient siteWiseAsyncClient, String modelId) { + public static void fetchAssets(String modelId) { + IoTSiteWiseAsyncClient siteWiseAsyncClient = IoTSiteWiseAsyncClient.builder() + .region(Region.US_EAST_1) + .build(); + ListAssetsRequest assetsRequest = ListAssetsRequest.builder() .maxResults(10) .assetModelId(modelId) diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java index 75282f0e61f..fe8650b844e 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java @@ -92,7 +92,7 @@ public static Boolean describeStack(String stackName) { } return false; } - static void destroyCloudFormationStack(String stackName) { + public static void destroyCloudFormationStack(String stackName) { getCloudFormationClient().deleteStack(b -> b.stackName(stackName)) .whenComplete((dsr, t) -> { if (dsr != null) { diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index 18a3116d135..a2ca93097e6 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -236,7 +236,7 @@ public void getAssetPropValueAsync(String propName, String propId, String assetI * @param assetModelId The Id of the asset model. * @return A map of the asset model properties when the CompletableFuture completes. */ - CompletableFuture> getPropertyIds(String assetModelId){ + public CompletableFuture> getPropertyIds(String assetModelId){ ListAssetModelPropertiesRequest modelPropertiesRequest = ListAssetModelPropertiesRequest.builder().assetModelId(assetModelId).build(); return getAsyncClient().listAssetModelProperties(modelPropertiesRequest) .handle( (response, throwable) -> { diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index ba4cbe9c737..55e5079bd44 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -5,19 +5,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import software.amazon.awssdk.services.iotsitewise.model.BatchPutAssetPropertyValueResponse; import software.amazon.awssdk.services.iotsitewise.model.CreateAssetModelResponse; import software.amazon.awssdk.services.iotsitewise.model.CreateAssetResponse; -import software.amazon.awssdk.services.iotsitewise.model.CreateGatewayResponse; -import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetModelResponse; -import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetResponse; -import software.amazon.awssdk.services.iotsitewise.model.DeletePortalResponse; -import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayResponse; import software.amazon.awssdk.services.iotsitewise.model.IoTSiteWiseException; import software.amazon.awssdk.services.iotsitewise.model.ResourceAlreadyExistsException; import software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException; - -import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.concurrent.CompletableFuture; @@ -48,18 +40,18 @@ public static void main(String[] args) throws Throwable { myThing - The name of the IoT thing or device that is connected to the IoT SiteWise gateway. """; - //if (args.length != 6) { - // logger.info(usage); - // return; - // } + if (args.length != 6) { + logger.info(usage); + return; + } Scanner scanner = new Scanner(System.in); - String assetModelName = "MyAssetModel"; - String assetName = "MyAsset"; - String portalName = "MyPortal"; - String contactEmail = "scmacdon@amazon.com"; - String gatewayName = "myGateway11"; - String myThing = "myThing78"; + String assetModelName = args[0]; + String assetName = args[1]; + String portalName = args[2]; + String contactEmail = args[3]; + String gatewayName = args[4]; + String myThing = args[5]; logger.info(""" AWS IoT SiteWise is a fully managed software-as-a-service (SaaS) that @@ -140,6 +132,8 @@ public static void runScenario(String assetModelName, String assetName, String an asset from the asset model. """); + logger.info("Let's wait 1 minute for the asset model to be ready."); + countdown(1); waitForInputToContinue(scanner); String assetId; try { @@ -229,7 +223,7 @@ public static void runScenario(String assetModelName, String assetName, String """); waitForInputToContinue(scanner); try { - sitewiseActions.getAssetPropValueAsync("Temperature property", tempPropId, assetId); // FIXME <------------------ + sitewiseActions.getAssetPropValueAsync("Temperature property", tempPropId, assetId); waitForInputToContinue(scanner); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); @@ -246,7 +240,7 @@ public static void runScenario(String assetModelName, String assetName, String } throw cause; } - sitewiseActions.getAssetPropValueAsync("Humidity property", humPropId, assetId); // FIXME <------------------ + sitewiseActions.getAssetPropValueAsync("Humidity property", humPropId, assetId); waitForInputToContinue(scanner); logger.info(DASHES); @@ -257,7 +251,7 @@ public static void runScenario(String assetModelName, String assetName, String such as sensors, equipment, and control systems, into a centralized platform. """); waitForInputToContinue(scanner); - String portalId = ""; + String portalId; try { portalId = sitewiseActions.createPortalAsync(portalName, iamRole, contactEmail).join(); logger.info("Portal created successfully. Portal ID {}", portalId); diff --git a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java index 3cc65de7d9e..2d366cdcb15 100644 --- a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java +++ b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java @@ -1,5 +1,260 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 + +import com.example.iotsitewise.HelloSitewise; +import com.example.iotsitewise.scenario.CloudFormationHelper; +import com.example.iotsitewise.scenario.SitewiseActions; +import com.google.gson.Gson; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; +import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.iotsitewise.model.CreateAssetModelResponse; +import software.amazon.awssdk.services.iotsitewise.model.CreateAssetResponse; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertFalse; + +@TestInstance(TestInstance.Lifecycle.PER_METHOD) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class SitewiseTests { + + private static final String assetModelName = "MyAssetModel"+ UUID.randomUUID(); + private static final String assetName = "MyAsset"; + + private static String assetId = ""; + private static final String portalName = "MyPortal"; + private static String contactEmail = ""; + private static final String gatewayName = "myGateway"+ UUID.randomUUID(); + private static final String myThing = "myThing"+ UUID.randomUUID(); + + private static String assetModelHello = ""; + + private static String assetModelId = ""; + + private static String iamRole = ""; + + private static final SitewiseActions sitewiseActions = new SitewiseActions(); + + private static Map propertyIds; + + private static String humPropId = ""; + + private static String tempPropId = ""; + + private static String portalId = ""; + + private static String gatewayId = ""; + private static final String ROLES_STACK = "RoleSitewise"; + + @BeforeAll + public static void setUp() { + CloudFormationHelper.deployCloudFormationStack(ROLES_STACK); + Map stackOutputs = CloudFormationHelper.getStackOutputs(ROLES_STACK); + iamRole = stackOutputs.get("SitewiseRoleArn"); + + Gson gson = new Gson(); + String json = getSecretValues(); + SecretValues values = gson.fromJson(json, SecretValues.class); + contactEmail = values.getContactEmail(); + assetModelHello = values.getAssetModelHello(); + } + + @Test + @Tag("IntegrationTest") + @Order(1) + public void testHelloService() { + assertDoesNotThrow(() -> HelloSitewise.fetchAssets(assetModelHello)); + System.out.println(" Test 1 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(2) + public void testCreateAssetModel() { + assertDoesNotThrow(() -> { + CompletableFuture future = sitewiseActions.createAssetModelAsync(assetModelName); + CreateAssetModelResponse response = future.join(); + + if (response == null || response.assetModelId() == null) { + throw new RuntimeException("Simulating failure: response or assetModelId is null"); + } + + // Simulate successful creation (won't reach this if above condition is met) + assetModelId = response.assetModelId(); + }); + + // This won't be reached if the assert fails + System.out.println("Test 2 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(3) + public void testCreateAsset() throws InterruptedException { + Thread.sleep(30000); + assertDoesNotThrow(() -> { + CompletableFuture future = sitewiseActions.createAssetAsync(assetName, assetModelId); + CreateAssetResponse response = future.join(); + assetId = response.assetId(); + }); + System.out.println("Test 3 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(4) + public void testGetPropIds() { + assertDoesNotThrow(() -> { + propertyIds = sitewiseActions.getPropertyIds(assetModelId).join(); + humPropId = propertyIds.get("Humidity"); + System.out.println("The Humidity property Id is "+ humPropId); + tempPropId = propertyIds.get("Temperature"); + System.out.println("The Temperature property Id is " + tempPropId); + }); + System.out.println("Test 4 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(5) + public void testSendProps() { + assertDoesNotThrow(() -> { + sitewiseActions.sendDataToSiteWiseAsync(assetId, tempPropId, humPropId).join(); + }); + System.out.println("Test 5 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(6) + public void testGETHumValue() { + assertDoesNotThrow(() -> { + sitewiseActions.getAssetPropValueAsync("Humidity property", humPropId, assetId); + }); + System.out.println("Test 6 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(7) + public void testCreatePortal() { + assertDoesNotThrow(() -> { + portalId = sitewiseActions.createPortalAsync(portalName, iamRole, contactEmail).join(); + }); + System.out.println("Test 7 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(8) + public void testDescribePortal() { + assertDoesNotThrow(() -> { + String portalUrl = sitewiseActions.describePortalAsync(portalId).join(); + assertFalse(portalUrl.isEmpty()); + }); + System.out.println("Test 8 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(9) + public void testCreateGateway() { + assertDoesNotThrow(() -> { + gatewayId = sitewiseActions.createGatewayAsync(gatewayName, myThing).join(); + assertFalse(gatewayId.isEmpty()); + }); + System.out.println("Test 9 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(10) + public void testDescribeGateway() { + assertDoesNotThrow(() -> { + sitewiseActions.describeGatewayAsync(gatewayId).join(); + }); + System.out.println("Test 10 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(11) + public void testDeletePortal() throws InterruptedException { + Thread.sleep(30000); + assertDoesNotThrow(() -> { + sitewiseActions.deletePortalAsync(portalId).join(); + }); + System.out.println("Test 11 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(12) + public void testDeleteAsset() throws InterruptedException { + Thread.sleep(30000); + assertDoesNotThrow(() -> { + sitewiseActions.deleteAssetAsync(assetId).join(); + }); + System.out.println("Test 11 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(12) + public void testDeleteAssetModel() throws InterruptedException { + Thread.sleep(30000); + assertDoesNotThrow(() -> { + sitewiseActions.deleteAssetModelAsync(assetModelId).join(); + }); + CloudFormationHelper.destroyCloudFormationStack(ROLES_STACK); + System.out.println("Test 11 passed"); + } + + + private static String getSecretValues() { + SecretsManagerClient secretClient = SecretsManagerClient.builder() + .region(Region.US_EAST_1) + .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) + .build(); + String secretName = "test/sitewise"; + + GetSecretValueRequest valueRequest = GetSecretValueRequest.builder() + .secretId(secretName) + .build(); + + GetSecretValueResponse valueResponse = secretClient.getSecretValue(valueRequest); + return valueResponse.secretString(); + } + + @Nested + @DisplayName("A class used to get test values from test/sitewise (an AWS Secrets Manager secret)") + class SecretValues { + private String contactEmail; + + private String assetModelHello; + + public String getContactEmail() { + return this.contactEmail; + } + + public String getAssetModelHello() { + return this.assetModelHello; + } + } } + From 4a3ecce054a908ee931070165fb3530b0e9c0c10 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 26 Sep 2024 14:22:32 -0400 Subject: [PATCH 28/41] updated high level Readme --- basics_scenarios/sitewise_scenario/README.md | 38 ++++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/basics_scenarios/sitewise_scenario/README.md b/basics_scenarios/sitewise_scenario/README.md index 8308cb63ba0..65f6ce8a678 100644 --- a/basics_scenarios/sitewise_scenario/README.md +++ b/basics_scenarios/sitewise_scenario/README.md @@ -1,37 +1,35 @@ -# Amazon OpenSearch Service Basic Scenario +# AWS IoT SiteWise Service Basic Scenario ## Overview - This Amazon OpenSearch Service (Amazon ECR) basic scenario demonstrates how to interact with the Amazon OpenSearch service using an AWS SDK. The scenario covers various operations such as creating an OpenSearch domain, modifying a domain, waiting for changes to the domain to enter a complete state, and so on. + This AWS IoT SiteWise Service basic scenario demonstrates how to interact with the AWS IoT SiteWise service using an AWS SDK. The scenario covers various operations such as creating a Asset Model, creating assets, sending data to assets, retrieving data, and so on. Here are the top five service operations this scenario covers. -**Create an Amazon OpenSearch Domain**: - - Description: This operation creates a new Amazon OpenSearch domain, which is a managed instance of the OpenSearch engine. +1. **Create an AWS SiteWise Asset Model**: + - Description: This step creates an AWS SiteWise Asset Model by invoking the `createAssetModel` method. -2. **Describe the Amazon OpenSearch Domain**: - - Description: This operation retrieves information about the specified Amazon OpenSearch domain. - - The method `describeDomain(domainName)` is called to obtain the Amazon Resource Name (ARN) of the specified OpenSearch domain. +2. **Create an AWS IoT SiteWise Asset**: + - Description: This operation creates an AWS SiteWise asset. -3. **List the Domains in Your Account**: - - Description: This operation lists all the Amazon OpenSearch domains in the current AWS account. - - The method `listAllDomains()` is called to retrieve a list of all the OpenSearch domains available in the account. -4. **Wait until the Domain's Change Status Reaches a Completed State**: - - Description: This operation waits until the change status of the specified Amazon OpenSearch domain reaches a completed state. - - When making changes to an OpenSearch domain, such as scaling the number of data nodes or updating the OpenSearch version, the domain goes through a change process. This method, `domainChangeProgress(domainName)`, waits until the change status of the specified domain reaches a completed state, which can take several minutes to several hours, depending on the complexity of the change and the current load on the OpenSearch service. - Note this operation may take up to 20 minutes. +3. **Retrieve the property ID values**: + - Description: To send data to an asset, we need to get the property ID values for the + the model properties. This scenario uses temperature and humidity properties. -5. **Modify the Domain**: - - Description: This operation modifies the cluster configuration of the specified Amazon OpenSearch domain, such as the instance count. - - The flexibility to modify the OpenSearch domain's configuration is particularly useful when the data or usage patterns change over time, as you can easily scale the domain to meet the new requirements without having to recreate the entire domain. - - The method `updateSpecificDomain(domainName)` is called to update the configuration of the specified OpenSearch domain. + +4. **Send data to an AWS IoT SiteWise Asset**: + - Description: This operation sends data to an IoT SiteWise Asset. + +5. **Retrieve the value of the IoT SiteWise Asset property**: + - Description: This operation gets data from the asset. Note: These steps are not the complete program, but summarizes the 5 high-level steps. See the Eng Spec for a complete listing of operations. ### Resources -This scenario does not require any additional AWS resources to run. +This Basics scenario requires an IAM role that has permissions to work with AWS IoT +SiteWise service. The scenario creates this resource using a CloudFormation template. ## Implementations @@ -44,7 +42,7 @@ This scenario example will be implemented in the following languages: ## Additional reading -- [Amazon ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/what-is-ecr.html) +- [AWS Sitewise](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/what-is-sitewise.html) --- From c66f236c36623c6a6d2ba3a20f529feb5924b2a8 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 26 Sep 2024 14:24:39 -0400 Subject: [PATCH 29/41] updated high level Readme --- basics_scenarios/sitewise_scenario/README.md | 34 +++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/basics_scenarios/sitewise_scenario/README.md b/basics_scenarios/sitewise_scenario/README.md index 65f6ce8a678..42d5529c665 100644 --- a/basics_scenarios/sitewise_scenario/README.md +++ b/basics_scenarios/sitewise_scenario/README.md @@ -1,36 +1,26 @@ -# AWS IoT SiteWise Service Basic Scenario - ## Overview +This AWS IoT SiteWise Service basic scenario demonstrates how to interact with the AWS IoT SiteWise service using an AWS SDK. The scenario covers various operations such as creating an Asset Model, creating assets, sending data to assets, and retrieving data. - This AWS IoT SiteWise Service basic scenario demonstrates how to interact with the AWS IoT SiteWise service using an AWS SDK. The scenario covers various operations such as creating a Asset Model, creating assets, sending data to assets, retrieving data, and so on. - - Here are the top five service operations this scenario covers. +## Key Operations 1. **Create an AWS SiteWise Asset Model**: - - Description: This step creates an AWS SiteWise Asset Model by invoking the `createAssetModel` method. + - This step creates an AWS SiteWise Asset Model by invoking the `createAssetModel` method. 2. **Create an AWS IoT SiteWise Asset**: - - Description: This operation creates an AWS SiteWise asset. - + - This operation creates an AWS SiteWise asset. 3. **Retrieve the property ID values**: - - Description: To send data to an asset, we need to get the property ID values for the - the model properties. This scenario uses temperature and humidity properties. - + - To send data to an asset, we need to get the property ID values for the model properties. This scenario uses temperature and humidity properties. 4. **Send data to an AWS IoT SiteWise Asset**: - - Description: This operation sends data to an IoT SiteWise Asset. + - This operation sends data to an IoT SiteWise Asset. 5. **Retrieve the value of the IoT SiteWise Asset property**: - - Description: This operation gets data from the asset. + - This operation gets data from the asset. -Note: These steps are not the complete program, but summarizes the 5 high-level steps. See the Eng Spec for a complete listing of operations. - -### Resources - -This Basics scenario requires an IAM role that has permissions to work with AWS IoT -SiteWise service. The scenario creates this resource using a CloudFormation template. +## Resources +This Basics scenario requires an IAM role that has permissions to work with the AWS IoT SiteWise service. The scenario creates this resource using a CloudFormation template. ## Implementations @@ -40,10 +30,8 @@ This scenario example will be implemented in the following languages: - Python - JavaScript -## Additional reading - -- [AWS Sitewise](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/what-is-sitewise.html) +## Additional Reading ---- +- [AWS IoT SiteWise Documentation](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/what-is-sitewise.html) Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 From c9d56ec3876105b0308cb59627e64f24a09d339e Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 26 Sep 2024 14:26:11 -0400 Subject: [PATCH 30/41] updated high level Readme --- basics_scenarios/sitewise_scenario/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/basics_scenarios/sitewise_scenario/README.md b/basics_scenarios/sitewise_scenario/README.md index 42d5529c665..9df7e209432 100644 --- a/basics_scenarios/sitewise_scenario/README.md +++ b/basics_scenarios/sitewise_scenario/README.md @@ -18,6 +18,8 @@ This AWS IoT SiteWise Service basic scenario demonstrates how to interact with t 5. **Retrieve the value of the IoT SiteWise Asset property**: - This operation gets data from the asset. +**Note** See the Eng spec for a full listing of operations. + ## Resources This Basics scenario requires an IAM role that has permissions to work with the AWS IoT SiteWise service. The scenario creates this resource using a CloudFormation template. From a959f55f6f6216d2919ae08a24c6ba3f045a4cb1 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 26 Sep 2024 15:20:28 -0400 Subject: [PATCH 31/41] Rolled in review comments --- .doc_gen/metadata/iot_sitewise_metadata.yaml | 2 +- basics_scenarios/sitewise_scenario/SPECIFICATION.md | 5 ++--- javav2/example_code/iotsitewise/README.md | 2 +- .../com/example/iotsitewise/scenario/SitewiseScenario.java | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.doc_gen/metadata/iot_sitewise_metadata.yaml b/.doc_gen/metadata/iot_sitewise_metadata.yaml index 957e674b013..3aa344b21a1 100644 --- a/.doc_gen/metadata/iot_sitewise_metadata.yaml +++ b/.doc_gen/metadata/iot_sitewise_metadata.yaml @@ -185,7 +185,7 @@ iotsitewise_CreateAssetModel: services: iotsitewise: {CreateAssetModel} iotsitewise_Scenario: - synopsis: Learn core operations for &ITSWlong; using an &AWS; SDK + synopsis: Learn core operations for &ITSWlong; using an &AWS; SDK. category: Basics languages: Java: diff --git a/basics_scenarios/sitewise_scenario/SPECIFICATION.md b/basics_scenarios/sitewise_scenario/SPECIFICATION.md index 95545274577..ed281d58d07 100644 --- a/basics_scenarios/sitewise_scenario/SPECIFICATION.md +++ b/basics_scenarios/sitewise_scenario/SPECIFICATION.md @@ -12,8 +12,7 @@ This Basics scenario requires an IAM role that has permissions to work with AWS SiteWise service. The scenario creates this resource using a CloudFormation template. ## Hello AWS IoT SiteWise -This program is intended for users not familiar with the AWS IoT SiteWise Service to easily get up and running. The logic is to show use of -`listAssetsPaginator`. +This program is intended for users not familiar with the AWS IoT SiteWise Service to easily get up and running. The program uses a `listAssetsPaginator` to demonstrate how you can read through Asset information. ## Basics Scenario Program Flow The AWS IoT SiteWise Basics scenario executes the following operations. @@ -21,7 +20,7 @@ The AWS IoT SiteWise Basics scenario executes the following operations. 1. **Create an AWS SiteWise Asset Model**: - Description: This step creates an AWS SiteWise Asset Model by invoking the `createAssetModel` method. - Exception Handling: Check to see if a `ResourceAlreadyExistsException` is thrown. - If it is thrown, get the asset model ID and move on. + If it is thrown, display the asset model ID and move on. 2. **Create an AWS IoT SiteWise Asset**: - Description: This operation creates an AWS SiteWise asset. diff --git a/javav2/example_code/iotsitewise/README.md b/javav2/example_code/iotsitewise/README.md index 9318e7b4c5e..11bf1e97381 100644 --- a/javav2/example_code/iotsitewise/README.md +++ b/javav2/example_code/iotsitewise/README.md @@ -107,7 +107,7 @@ in the `javav2` folder. - [AWS IoT SiteWise Developer Guide](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/what-is-sitewise.html) - [AWS IoT SiteWise API Reference](https://docs.aws.amazon.com/iot-sitewise/latest/APIReference/Welcome.html) -- [SDK for Java 2.x AWS IoT SiteWise reference](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/package-summary.html) +- [SDK for Java 2.x AWS IoT SiteWise reference](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/iotsitewise/package-summary.html) diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index 55e5079bd44..5c533fa6fd7 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -146,7 +146,7 @@ public static void runScenario(String assetModelName, String assetName, String Throwable cause = rt.getCause(); while (cause != null) { if (cause instanceof software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException) { - logger.info("The AWS resource was not found: {}", cause.getMessage()); // QUESTION: What resource? the asset model? Clarify if that is the case? + logger.info("The AWS resource was not found: {}", cause.getMessage()); break; } cause = cause.getCause(); From 96a2111ec287fad4635f73b3a0fb5c5ce8bbb812 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 26 Sep 2024 15:23:10 -0400 Subject: [PATCH 32/41] Rolled in review comments --- javav2/example_code/iotsitewise/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javav2/example_code/iotsitewise/README.md b/javav2/example_code/iotsitewise/README.md index 11bf1e97381..314ac2126ec 100644 --- a/javav2/example_code/iotsitewise/README.md +++ b/javav2/example_code/iotsitewise/README.md @@ -79,7 +79,7 @@ This example shows you how to get started using AWS IoT SiteWise. #### Learn the basics -This example shows you how to Learn core operations for AWS IoT SiteWise using an AWS SDK +This example shows you how to Learn core operations for AWS IoT SiteWise using an AWS SDK. From 17673864dd285e3779a1b08b638347a8a0a69638 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Fri, 27 Sep 2024 09:42:55 -0400 Subject: [PATCH 33/41] Rolled in review comments --- .../sitewise_scenario/SPECIFICATION.md | 23 +++-- javav2/example_code/iotsitewise/pom.xml | 16 ---- .../example/iotsitewise/HelloSitewise.java | 1 - .../scenario/CloudFormationHelper.java | 1 - .../iotsitewise/scenario/SitewiseActions.java | 94 +++++++++++++------ 5 files changed, 77 insertions(+), 58 deletions(-) diff --git a/basics_scenarios/sitewise_scenario/SPECIFICATION.md b/basics_scenarios/sitewise_scenario/SPECIFICATION.md index ed281d58d07..98361b4b2ce 100644 --- a/basics_scenarios/sitewise_scenario/SPECIFICATION.md +++ b/basics_scenarios/sitewise_scenario/SPECIFICATION.md @@ -25,48 +25,48 @@ The AWS IoT SiteWise Basics scenario executes the following operations. 2. **Create an AWS IoT SiteWise Asset**: - Description: This operation creates an AWS SiteWise asset. - The method `createAsset` is called to obtain the asset ID. - - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown if the asset model id provided in the request is invalid. If so, display the message and end the program. 3. **Retrieve the property ID values**: - Description: To send data to an asset, we need to get the property ID values for the the model properties. This scenario uses temperature and humidity properties. - - The method `listAssetModelProperties()` is called to retrieve the property ID values. + - The method `listAssetModelProperties` is called to retrieve the property ID values. - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. There are not many other useful exceptions for this specific call. If so, display the message and end the program. 4. **Send data to an AWS IoT SiteWise Asset**: - Description: This operation sends data to an IoT SiteWise Asset. - - This step uses the method `batchPutAssetPropertyValue()`. + - This step uses the method `batchPutAssetPropertyValue`. - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. 5. **Retrieve the value of the IoT SiteWise Asset property**: - Description: This operation gets data from the asset. - - This step uses the method `getAssetPropertyValue()`. + - This step uses the method `getAssetPropertyValue`. - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. 6. **Create an IoT SiteWise Portal**: - Description: This operation creates an IoT SiteWise portal. - The method `createPortal` is called. - - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. + - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. If so, display the message and end the program. 7. **Describe the Portal**: - Description: This operation describes the portal and returns a URL for the portal. - - The method `describePortal()` is called and returns the URL. + - The method `describePortal` is called and returns the URL. - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. -8. **Create an IoTSiteWise Gateway**: +8. **Create an IoT SiteWise Gateway**: - Description: This operation creates an IoT SiteWise Gateway. - The method `createGateway` is called. - - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. + - Exception Handling: Check to see if an `IoTSiteWiseException` is thrown. If so, display the message and end the program. 9. **Describe the IoT SiteWise Gateway**: - Description: This operation describes the Gateway. - - The method `describeGateway()` is called. + - The method `describeGateway` is called. - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. 10. **Delete the AWS IoT SiteWise Assets**: - - The `delete()` methods are called to clean up the resources. + - The `delete` methods are called to clean up the resources. - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program." ### Program execution @@ -319,14 +319,13 @@ The following table describes the metadata used in this Basics Scenario. | `describePortal` | iot_sitewise_metadata.yaml | iotsitewise_DescribePortal | | `listAssetModels` | iot_sitewise_metadata.yaml | iotsitewise_ListAssetModels | | `deletePortal` | iot_sitewise_metadata.yaml | iotsitewise_DeletePortal | -| `createPortals` | iot_sitewise_metadata.yaml | iotsitewise_CreatePortal | +| `createPortal` | iot_sitewise_metadata.yaml | iotsitewise_CreatePortal | | `deleteAssetModel` | iot_sitewise_metadata.yaml | iotsitewise_DeleteAssetModel | | `deleteAsset` | iot_sitewise_metadata.yaml | iotsitewise_DeleteAsset | | `describeAssetModel` | iot_sitewise_metadata.yaml | iotsitewise_DescribeAssetModel | | `getAssetPropertyValue` | iot_sitewise_metadata.yaml | iotsitewise_GetAssetPropertyValue | | `batchPutAssetPropertyValue` | iot_sitewise_metadata.yaml | iotsitewise_BatchPutAssetPropertyValue | | `createAsset` | iot_sitewise_metadata.yaml | iotsitewise_CreateAsset | -| `createAsset` | iot_sitewise_metadata.yaml | iotsitewise_CreateAsset | | `createAssetModel ` | iot_sitewise_metadata.yaml | iotsitewise_CreateAssetModel | | `scenario` | iot_sitewise_metadata.yaml | iotsitewise_Scenario | | `hello` | iot_sitewise_metadata.yaml | iotsitewise_Hello | diff --git a/javav2/example_code/iotsitewise/pom.xml b/javav2/example_code/iotsitewise/pom.xml index 843d3ebdbae..0efee79a8ad 100644 --- a/javav2/example_code/iotsitewise/pom.xml +++ b/javav2/example_code/iotsitewise/pom.xml @@ -88,28 +88,12 @@ gson 2.10.1 - - software.amazon.awssdk - sso - - - software.amazon.awssdk - ssooidc - org.junit.platform junit-platform-launcher 1.9.2 test - - software.amazon.awssdk - ec2 - - - software.amazon.awssdk - ssm - software.amazon.awssdk sso diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java index 7f0b39b2478..782a905e41f 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java @@ -42,7 +42,6 @@ public static void main(String[] args) { */ public static void fetchAssets(String modelId) { IoTSiteWiseAsyncClient siteWiseAsyncClient = IoTSiteWiseAsyncClient.builder() - .region(Region.US_EAST_1) .build(); ListAssetsRequest assetsRequest = ListAssetsRequest.builder() diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java index fe8650b844e..79040a7318d 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java @@ -30,7 +30,6 @@ public class CloudFormationHelper { private static CloudFormationAsyncClient getCloudFormationClient() { CloudFormationAsyncClient cfClient = CloudFormationAsyncClient.builder() - .region(Region.US_EAST_1) .build(); return cfClient; diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index a2ca93097e6..9e41d417385 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -15,7 +15,6 @@ import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayRequest; import software.amazon.awssdk.services.iotsitewise.model.DescribeGatewayResponse; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.core.retry.RetryPolicy; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseAsyncClient; @@ -28,7 +27,6 @@ import software.amazon.awssdk.services.iotsitewise.model.CreateAssetRequest; import software.amazon.awssdk.services.iotsitewise.model.CreateAssetResponse; import software.amazon.awssdk.services.iotsitewise.model.CreatePortalRequest; -import software.amazon.awssdk.services.iotsitewise.model.CreatePortalResponse; import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetModelRequest; import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetModelResponse; import software.amazon.awssdk.services.iotsitewise.model.DeleteAssetRequest; @@ -48,6 +46,7 @@ import software.amazon.awssdk.services.iotsitewise.model.PutAssetPropertyValueEntry; import software.amazon.awssdk.services.iotsitewise.model.TimeInNanos; import software.amazon.awssdk.services.iotsitewise.model.Variant; + import java.time.Duration; import java.time.Instant; import java.util.Arrays; @@ -88,8 +87,9 @@ private static IoTSiteWiseAsyncClient getAsyncClient() { } // snippet-start:[sitewise.java2_create_asset_model.main] + /** - * Creates an asset model asynchronously. + * Creates an asset model. * * @param name the name of the asset model to create * @return a {@link CompletableFuture} that completes with the created {@link CreateAssetModelResponse} when the operation is complete @@ -115,7 +115,6 @@ public CompletableFuture createAssetModelAsync(String .type(humidity) .build(); - CreateAssetModelRequest createAssetModelRequest = CreateAssetModelRequest.builder() .assetModelName(name) .assetModelDescription("This is my asset model") @@ -133,10 +132,11 @@ public CompletableFuture createAssetModelAsync(String // snippet-end:[sitewise.java2_create_asset_model.main] // snippet-start:[sitewise.java2_create_asset.main] + /** - * Asynchronously creates an asset with the specified name and model ARN. + * Creates an asset with the specified name and model ARN. * - * @param assetName the name of the asset to create + * @param assetName the name of the asset to create * @param assetModelArn the ARN of the asset model to associate with the asset * @return a {@link CompletableFuture} that completes with the {@link CreateAssetResponse} when the asset creation is complete * @throws RuntimeException if the asset creation fails @@ -153,12 +153,21 @@ public CompletableFuture createAssetAsync(String assetName, if (exception != null) { throw new RuntimeException("Failed to create asset: " + exception.getMessage(), exception); } - return response; // Return the response if successful + return response; }); } // snippet-end:[sitewise.java2_create_asset.main] // snippet-start:[sitewise.java2_put_batch_property.main] + + /** + * Sends data to the SiteWise service. + * + * @param assetId the ID of the asset to which the data will be sent + * @param tempPropertyId the ID of the temperature property + * @param humidityPropId the ID of the humidity property + * @return a CompletableFuture representing the response from the SiteWise service + */ public CompletableFuture sendDataToSiteWiseAsync(String assetId, String tempPropertyId, String humidityPropId) { Map sampleData = generateSampleData(); long timestamp = Instant.now().toEpochMilli(); @@ -211,7 +220,15 @@ public CompletableFuture sendDataToSiteWiseA // snippet-end:[sitewise.java2_put_batch_property.main] // snippet-start:[sitewise.java2_get_property.main] - // TODO -- fix this including Javadoc + + /** + * Asynchronously fetches the value of an asset property. + * + * @param propName the name of the asset property to fetch + * @param propId the ID of the asset property to fetch + * @param assetId the ID of the asset to fetch the property value for + * @throws RuntimeException if an error occurs while fetching the property value + */ public void getAssetPropValueAsync(String propName, String propId, String assetId) { GetAssetPropertyValueRequest assetPropertyValueRequest = GetAssetPropertyValueRequest.builder() .propertyId(propId) @@ -232,26 +249,31 @@ public void getAssetPropValueAsync(String propName, String propId, String assetI // snippet-end:[sitewise.java2_get_property.main] // snippet-start:[sitewise.java2.describe.asset.model.main] + /** - * @param assetModelId The Id of the asset model. - * @return A map of the asset model properties when the CompletableFuture completes. + * Retrieves the property IDs associated with a specific asset model. + * + * @param assetModelId the ID of the asset model to retrieve the property IDs for + * @return a {@link CompletableFuture} that, when completed, contains a {@link Map} mapping the property names to their corresponding IDs + * @throws CompletionException if an error occurs while retrieving the asset model properties */ - public CompletableFuture> getPropertyIds(String assetModelId){ + public CompletableFuture> getPropertyIds(String assetModelId) { ListAssetModelPropertiesRequest modelPropertiesRequest = ListAssetModelPropertiesRequest.builder().assetModelId(assetModelId).build(); return getAsyncClient().listAssetModelProperties(modelPropertiesRequest) - .handle( (response, throwable) -> { - if (response != null){ - return response.assetModelPropertySummaries().stream() - .collect(Collectors - .toMap(AssetModelPropertySummary::name, AssetModelPropertySummary::id)); - } else { - throw (CompletionException) throwable.getCause(); - } - }); + .handle((response, throwable) -> { + if (response != null) { + return response.assetModelPropertySummaries().stream() + .collect(Collectors + .toMap(AssetModelPropertySummary::name, AssetModelPropertySummary::id)); + } else { + throw (CompletionException) throwable.getCause(); + } + }); } // snippet-end:[sitewise.java2.describe.asset.model.main] // snippet-start:[sitewise.java2.delete.asset.main] + /** * Deletes an asset asynchronously. * @@ -277,7 +299,7 @@ public CompletableFuture deleteAssetAsync(String assetId) { // snippet-start:[sitewise.java2.delete.asset.model.main] /** - * Asynchronously deletes an Asset Model with the specified ID. + * Deletes an Asset Model with the specified ID. * * @param assetModelId the ID of the Asset Model to delete * @return a {@link CompletableFuture} that completes with the {@link DeleteAssetModelResponse} when the operation is complete @@ -298,11 +320,12 @@ public CompletableFuture deleteAssetModelAsync(String // snippet-end:[sitewise.java2.delete.asset.model.main] // snippet-start:[sitewise.java2.create.portal.main] + /** - * Creates a new IoT SiteWise portal asynchronously. + * Creates a new IoT SiteWise portal. * - * @param portalName the name of the portal to create - * @param iamRole the IAM role ARN to use for the portal + * @param portalName the name of the portal to create + * @param iamRole the IAM role ARN to use for the portal * @param contactEmail the email address of the portal contact * @return a {@link CompletableFuture} that completes with the portal ID when the portal is created successfully, or throws a {@link RuntimeException} if the creation fails */ @@ -315,7 +338,7 @@ public CompletableFuture createPortalAsync(String portalName, String iam .build(); return getAsyncClient().createPortal(createPortalRequest) - .handle ((response, exception) -> { + .handle((response, exception) -> { if (exception != null) { logger.error("Failed to create portal: {} ", exception.getCause().getMessage()); throw (CompletionException) exception; @@ -327,7 +350,7 @@ public CompletableFuture createPortalAsync(String portalName, String iam // snippet-start:[sitewise.java2.delete.portal.main] /** - * Deletes a portal asynchronously. + * Deletes a portal. * * @param portalId the ID of the portal to be deleted * @return a {@link CompletableFuture} containing the {@link DeletePortalResponse} when the operation is complete @@ -349,7 +372,7 @@ public CompletableFuture deletePortalAsync(String portalId // snippet-start:[sitewise.java2.list.asset.model.main] /** - * Retrieves the asset model ID asynchronously for the given asset model name. + * Retrieves the asset model ID for the given asset model name. * * @param assetModelName the name of the asset model to retrieve the ID for * @return a {@link CompletableFuture} that, when completed, contains the asset model ID, or {@code null} if the asset model is not found @@ -363,7 +386,7 @@ public CompletableFuture getAssetModelIdAsync(String assetModelName) { } for (AssetModelSummary assetModelSummary : listAssetModelsResponse.assetModelSummaries()) { if (assetModelSummary.name().equals(assetModelName)) { - return assetModelSummary.id(); // Return the ARN if found. + return assetModelSummary.id(); } } return null; @@ -433,6 +456,13 @@ public CompletableFuture createGatewayAsync(String gatewayName, String m // snippet-end:[sitewise.java2.create.gateway.main] // snippet-start:[sitewise.java2.delete.gateway.main] + + /** + * Deletes the specified gateway asynchronously. + * + * @param gatewayARN the Amazon Resource Name (ARN) of the gateway to be deleted + * @return a {@link CompletableFuture} representing the asynchronous operation of deleting the gateway + */ public CompletableFuture deleteGatewayAsync(String gatewayARN) { DeleteGatewayRequest deleteGatewayRequest = DeleteGatewayRequest.builder() .gatewayId(gatewayARN) @@ -450,6 +480,14 @@ public CompletableFuture deleteGatewayAsync(String gatewa // snippet-end:[sitewise.java2.delete.gateway.main] // snippet-start:[sitewise.java2.describe.gateway.main] + /** + * Asynchronously describes the specified gateway. + * + * @param gatewayId the ID of the gateway to describe + * @return a {@link CompletableFuture} that represents the asynchronous operation, + * which will complete with a {@link DescribeGatewayResponse} containing + * information about the specified gateway + */ public CompletableFuture describeGatewayAsync(String gatewayId) { DescribeGatewayRequest request = DescribeGatewayRequest.builder() .gatewayId(gatewayId) From 0bbe562bcaa2d2933d48da35782b75d6844e31f7 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Fri, 27 Sep 2024 12:25:19 -0400 Subject: [PATCH 34/41] Rolled in review comments --- .../scenario/CloudFormationHelper.java | 64 ++++++--- .../iotsitewise/scenario/SitewiseActions.java | 133 ++++++++---------- .../scenario/SitewiseScenario.java | 58 +++++--- .../iotsitewise/src/main/resources/data.json | 44 ------ .../src/test/java/SitewiseTests.java | 6 +- 5 files changed, 139 insertions(+), 166 deletions(-) delete mode 100644 javav2/example_code/iotsitewise/src/main/resources/data.json diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java index 79040a7318d..6217de1ed5e 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java @@ -4,7 +4,10 @@ package com.example.iotsitewise.scenario; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; import software.amazon.awssdk.services.cloudformation.CloudFormationAsyncClient; import software.amazon.awssdk.services.cloudformation.CloudFormationClient; import software.amazon.awssdk.services.cloudformation.model.Capability; @@ -14,12 +17,12 @@ import software.amazon.awssdk.services.cloudformation.model.Output; import software.amazon.awssdk.services.cloudformation.model.Stack; import software.amazon.awssdk.services.cloudformation.waiters.CloudFormationAsyncWaiter; - import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.Duration; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,11 +31,29 @@ public class CloudFormationHelper { private static final String CFN_TEMPLATE = "SitewiseRoles-template.yaml"; private static final Logger logger = LoggerFactory.getLogger(CloudFormationHelper.class); + private static CloudFormationAsyncClient cloudFormationClient; + private static CloudFormationAsyncClient getCloudFormationClient() { - CloudFormationAsyncClient cfClient = CloudFormationAsyncClient.builder() - .build(); + if (cloudFormationClient == null) { + SdkAsyncHttpClient httpClient = NettyNioAsyncHttpClient.builder() + .maxConcurrency(100) + .connectionTimeout(Duration.ofSeconds(60)) + .readTimeout(Duration.ofSeconds(60)) + .writeTimeout(Duration.ofSeconds(60)) + .build(); - return cfClient; + ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder() + .apiCallTimeout(Duration.ofMinutes(2)) + .apiCallAttemptTimeout(Duration.ofSeconds(90)) + .retryStrategy(RetryMode.STANDARD) + .build(); + + cloudFormationClient = CloudFormationAsyncClient.builder() + .httpClient(httpClient) + .overrideConfiguration(overrideConfig) + .build(); + } + return cloudFormationClient; } public static void deployCloudFormationStack(String stackName) { @@ -75,7 +96,6 @@ public static void deployCloudFormationStack(String stackName) { } // Check to see if the Stack exists before deploying it - public static Boolean describeStack(String stackName) { try { CompletableFuture future = getCloudFormationClient().describeStacks(); @@ -109,25 +129,31 @@ public static void destroyCloudFormationStack(String stackName) { }).join(); } - public static Map getStackOutputs(String stackName) { - CloudFormationClient cfClient = CloudFormationClient.create(); + public static CompletableFuture> getStackOutputsAsync(String stackName) { + CloudFormationAsyncClient cloudFormationAsyncClient = getCloudFormationClient(); + DescribeStacksRequest describeStacksRequest = DescribeStacksRequest.builder() .stackName(stackName) .build(); - DescribeStacksResponse describeStacksResponse = cfClient.describeStacks(describeStacksRequest); - List stacks = describeStacksResponse.stacks(); + return cloudFormationAsyncClient.describeStacks(describeStacksRequest) + .handle((describeStacksResponse, throwable) -> { + if (throwable != null) { + throw new RuntimeException("Failed to get stack outputs for: " + stackName, throwable); + } - if (stacks.isEmpty()) { - throw new RuntimeException("Stack not found: " + stackName); - } + // Process the result + if (describeStacksResponse.stacks().isEmpty()) { + throw new RuntimeException("Stack not found: " + stackName); + } - Stack stack = stacks.get(0); - Map outputs = new HashMap<>(); - for (Output output : stack.outputs()) { - outputs.put(output.outputKey(), output.outputValue()); - } + Stack stack = describeStacksResponse.stacks().get(0); + Map outputs = new HashMap<>(); + for (Output output : stack.outputs()) { + outputs.put(output.outputKey(), output.outputValue()); + } - return outputs; + return outputs; + }); } } diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index 9e41d417385..87fdb418739 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -46,7 +46,6 @@ import software.amazon.awssdk.services.iotsitewise.model.PutAssetPropertyValueEntry; import software.amazon.awssdk.services.iotsitewise.model.TimeInNanos; import software.amazon.awssdk.services.iotsitewise.model.Variant; - import java.time.Duration; import java.time.Instant; import java.util.Arrays; @@ -87,12 +86,12 @@ private static IoTSiteWiseAsyncClient getAsyncClient() { } // snippet-start:[sitewise.java2_create_asset_model.main] - /** * Creates an asset model. * - * @param name the name of the asset model to create - * @return a {@link CompletableFuture} that completes with the created {@link CreateAssetModelResponse} when the operation is complete + * @param name the name of the asset model to create. + * @return a {@link CompletableFuture} that completes with the created {@link CreateAssetModelResponse} when the operation is complete. + * @throws RuntimeException if an error occurs while creating the asset model. */ public CompletableFuture createAssetModelAsync(String name) { PropertyType humidity = PropertyType.builder() @@ -122,51 +121,47 @@ public CompletableFuture createAssetModelAsync(String .build(); return getAsyncClient().createAssetModel(createAssetModelRequest) - .handle((response, exception) -> { + .whenComplete((response, exception) -> { if (exception != null) { throw new RuntimeException("Failed to create asset model: " + exception.getMessage(), exception); } - return response; }); } // snippet-end:[sitewise.java2_create_asset_model.main] // snippet-start:[sitewise.java2_create_asset.main] - /** - * Creates an asset with the specified name and model ARN. + * Creates an asset with the specified name and model Id. * - * @param assetName the name of the asset to create - * @param assetModelArn the ARN of the asset model to associate with the asset - * @return a {@link CompletableFuture} that completes with the {@link CreateAssetResponse} when the asset creation is complete - * @throws RuntimeException if the asset creation fails + * @param assetName the name of the asset to create. + * @param assetModelId the Id of the asset model to associate with the asset. + * @return a {@link CompletableFuture} that completes with the {@link CreateAssetResponse} when the asset creation is complete. + * @throws RuntimeException if the asset creation fails. */ - public CompletableFuture createAssetAsync(String assetName, String assetModelArn) { + public CompletableFuture createAssetAsync(String assetName, String assetModelId) { CreateAssetRequest createAssetRequest = CreateAssetRequest.builder() - .assetModelId(assetModelArn) + .assetModelId(assetModelId) .assetDescription("Created using the AWS SDK for Java") .assetName(assetName) .build(); return getAsyncClient().createAsset(createAssetRequest) - .handle((response, exception) -> { + .whenComplete((response, exception) -> { if (exception != null) { throw new RuntimeException("Failed to create asset: " + exception.getMessage(), exception); } - return response; }); } // snippet-end:[sitewise.java2_create_asset.main] // snippet-start:[sitewise.java2_put_batch_property.main] - /** * Sends data to the SiteWise service. * - * @param assetId the ID of the asset to which the data will be sent - * @param tempPropertyId the ID of the temperature property - * @param humidityPropId the ID of the humidity property - * @return a CompletableFuture representing the response from the SiteWise service + * @param assetId the ID of the asset to which the data will be sent. + * @param tempPropertyId the ID of the temperature property. + * @param humidityPropId the ID of the humidity property. + * @return a CompletableFuture representing the response from the SiteWise service. */ public CompletableFuture sendDataToSiteWiseAsync(String assetId, String tempPropertyId, String humidityPropId) { Map sampleData = generateSampleData(); @@ -220,42 +215,35 @@ public CompletableFuture sendDataToSiteWiseA // snippet-end:[sitewise.java2_put_batch_property.main] // snippet-start:[sitewise.java2_get_property.main] - /** - * Asynchronously fetches the value of an asset property. + * Fetches the value of an asset property. * - * @param propName the name of the asset property to fetch - * @param propId the ID of the asset property to fetch - * @param assetId the ID of the asset to fetch the property value for - * @throws RuntimeException if an error occurs while fetching the property value + * @param propId the ID of the asset property to fetch. + * @param assetId the ID of the asset to fetch the property value for. + * @throws RuntimeException if an error occurs while fetching the property value. */ - public void getAssetPropValueAsync(String propName, String propId, String assetId) { + public CompletableFuture getAssetPropValueAsync(String propId, String assetId) { GetAssetPropertyValueRequest assetPropertyValueRequest = GetAssetPropertyValueRequest.builder() .propertyId(propId) .assetId(assetId) .build(); CompletableFuture futureResponse = getAsyncClient().getAssetPropertyValue(assetPropertyValueRequest); - futureResponse.whenComplete((response, exception) -> { + return futureResponse.whenComplete((response, exception) -> { if (exception != null) { throw new RuntimeException("Error occurred while fetching property value: " + exception.getMessage(), exception); - } else { - String assetVal = String.valueOf(response.propertyValue().value().doubleValue()); - logger.info("The property name is: {} ", propName); - logger.info("The value of this property is {}", assetVal); } - }).join(); + }).thenApply(response -> String.valueOf(response.propertyValue().value().doubleValue())); } // snippet-end:[sitewise.java2_get_property.main] // snippet-start:[sitewise.java2.describe.asset.model.main] - /** * Retrieves the property IDs associated with a specific asset model. * - * @param assetModelId the ID of the asset model to retrieve the property IDs for - * @return a {@link CompletableFuture} that, when completed, contains a {@link Map} mapping the property names to their corresponding IDs - * @throws CompletionException if an error occurs while retrieving the asset model properties + * @param assetModelId the ID of the asset model to retrieve the property IDs for. + * @return a {@link CompletableFuture} that, when completed, contains a {@link Map} mapping the property names to their corresponding IDs. + * @throws CompletionException if an error occurs while retrieving the asset model properties. */ public CompletableFuture> getPropertyIds(String assetModelId) { ListAssetModelPropertiesRequest modelPropertiesRequest = ListAssetModelPropertiesRequest.builder().assetModelId(assetModelId).build(); @@ -273,13 +261,12 @@ public CompletableFuture> getPropertyIds(String assetModelId // snippet-end:[sitewise.java2.describe.asset.model.main] // snippet-start:[sitewise.java2.delete.asset.main] - /** - * Deletes an asset asynchronously. + * Deletes an asset. * - * @param assetId the ID of the asset to be deleted - * @return a {@link CompletableFuture} that represents the asynchronous operation of deleting the asset - * @throws RuntimeException if the asset deletion fails + * @param assetId the ID of the asset to be deleted. + * @return a {@link CompletableFuture} that represents the asynchronous operation of deleting the asset. + * @throws RuntimeException if the asset deletion fails. */ public CompletableFuture deleteAssetAsync(String assetId) { DeleteAssetRequest deleteAssetRequest = DeleteAssetRequest.builder() @@ -301,9 +288,9 @@ public CompletableFuture deleteAssetAsync(String assetId) { /** * Deletes an Asset Model with the specified ID. * - * @param assetModelId the ID of the Asset Model to delete - * @return a {@link CompletableFuture} that completes with the {@link DeleteAssetModelResponse} when the operation is complete - * @throws RuntimeException if the operation fails, containing the error message and the underlying exception + * @param assetModelId the ID of the Asset Model to delete. + * @return a {@link CompletableFuture} that completes with the {@link DeleteAssetModelResponse} when the operation is complete. + * @throws RuntimeException if the operation fails, containing the error message and the underlying exception. */ public CompletableFuture deleteAssetModelAsync(String assetModelId) { DeleteAssetModelRequest deleteAssetModelRequest = DeleteAssetModelRequest.builder() @@ -320,14 +307,13 @@ public CompletableFuture deleteAssetModelAsync(String // snippet-end:[sitewise.java2.delete.asset.model.main] // snippet-start:[sitewise.java2.create.portal.main] - /** * Creates a new IoT SiteWise portal. * - * @param portalName the name of the portal to create - * @param iamRole the IAM role ARN to use for the portal - * @param contactEmail the email address of the portal contact - * @return a {@link CompletableFuture} that completes with the portal ID when the portal is created successfully, or throws a {@link RuntimeException} if the creation fails + * @param portalName the name of the portal to create. + * @param iamRole the IAM role ARN to use for the portal. + * @param contactEmail the email address of the portal contact. + * @return a {@link CompletableFuture} that completes with the portal ID when the portal is created successfully, or throws a {@link RuntimeException} if the creation fails. */ public CompletableFuture createPortalAsync(String portalName, String iamRole, String contactEmail) { CreatePortalRequest createPortalRequest = CreatePortalRequest.builder() @@ -352,9 +338,9 @@ public CompletableFuture createPortalAsync(String portalName, String iam /** * Deletes a portal. * - * @param portalId the ID of the portal to be deleted - * @return a {@link CompletableFuture} containing the {@link DeletePortalResponse} when the operation is complete - * @throws RuntimeException if the portal deletion fails, with the error message and the underlying exception + * @param portalId the ID of the portal to be deleted. + * @return a {@link CompletableFuture} containing the {@link DeletePortalResponse} when the operation is complete. + * @throws RuntimeException if the portal deletion fails, with the error message and the underlying exception. */ public CompletableFuture deletePortalAsync(String portalId) { DeletePortalRequest deletePortalRequest = DeletePortalRequest.builder() @@ -374,8 +360,8 @@ public CompletableFuture deletePortalAsync(String portalId /** * Retrieves the asset model ID for the given asset model name. * - * @param assetModelName the name of the asset model to retrieve the ID for - * @return a {@link CompletableFuture} that, when completed, contains the asset model ID, or {@code null} if the asset model is not found + * @param assetModelName the name of the asset model to retrieve the ID for. + * @return a {@link CompletableFuture} that, when completed, contains the asset model ID, or {@code null} if the asset model is not found. */ public CompletableFuture getAssetModelIdAsync(String assetModelName) { ListAssetModelsRequest listAssetModelsRequest = ListAssetModelsRequest.builder().build(); @@ -398,9 +384,9 @@ public CompletableFuture getAssetModelIdAsync(String assetModelName) { /** * Asynchronously describes a portal. * - * @param portalId the ID of the portal to describe - * @return a {@link CompletableFuture} that, when completed, will contain the URL of the described portal - * @throws RuntimeException if the portal description operation fails + * @param portalId the ID of the portal to describe. + * @return a {@link CompletableFuture} that, when completed, will contain the URL of the described portal. + * @throws RuntimeException if the portal description operation fails. */ public CompletableFuture describePortalAsync(String portalId) { DescribePortalRequest request = DescribePortalRequest.builder() @@ -412,7 +398,6 @@ public CompletableFuture describePortalAsync(String portalId) { if (exception != null) { throw new RuntimeException("Failed to describe portal: " + exception.getMessage(), exception); } - // Return the portal URL if the operation is successful return response.portalStartUrl(); }); } @@ -420,10 +405,10 @@ public CompletableFuture describePortalAsync(String portalId) { // snippet-start:[sitewise.java2.create.gateway.main] /** - * Creates a new IoTSitewise gateway asynchronously. + * Creates a new IoT Sitewise gateway. * - * @return a {@link CompletableFuture} containing the {@link CreateGatewayResponse} representing the created gateway - * @throws RuntimeException if there was an error creating the gateway + * @return a {@link CompletableFuture} containing the {@link CreateGatewayResponse} representing the created gateway. + * @throws RuntimeException if there was an error creating the gateway. */ public CompletableFuture createGatewayAsync(String gatewayName, String myThing) { GreengrassV2 gg = GreengrassV2.builder() @@ -456,12 +441,12 @@ public CompletableFuture createGatewayAsync(String gatewayName, String m // snippet-end:[sitewise.java2.create.gateway.main] // snippet-start:[sitewise.java2.delete.gateway.main] - /** * Deletes the specified gateway asynchronously. * - * @param gatewayARN the Amazon Resource Name (ARN) of the gateway to be deleted - * @return a {@link CompletableFuture} representing the asynchronous operation of deleting the gateway + * @param gatewayARN the ARN of the gateway to delete. + * @return a CompletableFuture containing the response of the delete operation. + * @throws RuntimeException if an error occurs during the delete operation. */ public CompletableFuture deleteGatewayAsync(String gatewayARN) { DeleteGatewayRequest deleteGatewayRequest = DeleteGatewayRequest.builder() @@ -471,7 +456,7 @@ public CompletableFuture deleteGatewayAsync(String gatewa return getAsyncClient().deleteGateway(deleteGatewayRequest) .whenComplete((response, exception) -> { if (exception != null) { - logger.error("An error occurred during the deleteGateway method."); + throw new RuntimeException("Failed to delete gateway: " + exception.getMessage(), exception); } else { logger.info("The Gateway was deleted successfully."); } @@ -483,10 +468,10 @@ public CompletableFuture deleteGatewayAsync(String gatewa /** * Asynchronously describes the specified gateway. * - * @param gatewayId the ID of the gateway to describe - * @return a {@link CompletableFuture} that represents the asynchronous operation, + * @param gatewayId the ID of the gateway to describe. + * @return a {@link CompletableFuture} that represents the asynchronous operation * which will complete with a {@link DescribeGatewayResponse} containing - * information about the specified gateway + * information about the specified gateway. */ public CompletableFuture describeGatewayAsync(String gatewayId) { DescribeGatewayRequest request = DescribeGatewayRequest.builder() @@ -496,15 +481,11 @@ public CompletableFuture describeGatewayAsync(String ga return getAsyncClient().describeGateway(request) .whenComplete((response, exception) -> { if (exception != null) { - logger.error("An error occurred during the describeGateway method"); - } else { - logger.info("Gateway Name: " + response.gatewayName()); - logger.info("Gateway ARN: " + response.gatewayArn()); - logger.info("Gateway Platform: " + response.gatewayPlatform().toString()); - logger.info("Gateway Creation Date: " + response.creationDate()); + logger.error("An error occurred during the describeGateway method", exception); } }); } + // snippet-end:[sitewise.java2.describe.gateway.main] private static Map generateSampleData() { diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index 5c533fa6fd7..59682e6a406 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -29,29 +29,25 @@ public class SitewiseScenario { public static void main(String[] args) throws Throwable { final String usage = """ Usage: - + Where: - assetModelName - The name of the asset model used in the IoT SiteWise program. - assetName - The name of the asset created in the IoT SiteWise program. - portalName - The name of the IoT SiteWise portal where the asset and other resources are created. contactEmail - The email address of the contact person associated with the IoT SiteWise program. - gatewayName - The name of the IoT SiteWise gateway used to collect and send data to the IoT SiteWise service. - myThing - The name of the IoT thing or device that is connected to the IoT SiteWise gateway. + """; - if (args.length != 6) { - logger.info(usage); - return; - } + // if (args.length != 1) { + // logger.info(usage); + // return; + // } Scanner scanner = new Scanner(System.in); - String assetModelName = args[0]; - String assetName = args[1]; - String portalName = args[2]; - String contactEmail = args[3]; - String gatewayName = args[4]; - String myThing = args[5]; + String contactEmail = "scmacdon@amazon.com" ; //args[0]; + String assetModelName = "MyAssetModel1"; + String assetName = "MyAsset1" ; + String portalName = "MyPortal1" ; + String gatewayName = "MyGateway1" ; + String myThing = "MyThing1" ; logger.info(""" AWS IoT SiteWise is a fully managed software-as-a-service (SaaS) that @@ -87,7 +83,7 @@ equipment and systems, including programmable logic controllers (PLCs), sensors, public static void runScenario(String assetModelName, String assetName, String portalName, String contactEmail, String gatewayName, String myThing) throws Throwable { logger.info("Use AWS CloudFormation to create an IAM role that is required for this scenario."); CloudFormationHelper.deployCloudFormationStack(ROLES_STACK); - Map stackOutputs = CloudFormationHelper.getStackOutputs(ROLES_STACK); + Map stackOutputs = CloudFormationHelper.getStackOutputsAsync(ROLES_STACK).join(); String iamRole = stackOutputs.get("SitewiseRoleArn"); logger.info("The ARN of the IAM role is {}",iamRole); logger.info(DASHES); @@ -223,8 +219,17 @@ public static void runScenario(String assetModelName, String assetName, String """); waitForInputToContinue(scanner); try { - sitewiseActions.getAssetPropValueAsync("Temperature property", tempPropId, assetId); - waitForInputToContinue(scanner); + sitewiseActions.getAssetPropValueAsync(tempPropId, assetId) + .whenComplete((assetVal, exception) -> { + if (exception != null) { + logger.error("Error fetching asset property value: {}", exception.getMessage(), exception); + } else { + logger.info("The property name is: {}", "Temperature"); + logger.info("The value of this property is: {}", assetVal); + } + }).join(); + waitForInputToContinue(scanner); + } catch (RuntimeException rt) { Throwable cause = rt.getCause(); while (cause != null) { @@ -238,9 +243,11 @@ public static void runScenario(String assetModelName, String assetName, String if (cause == null) { logger.info("An unexpected error occurred: {}", rt.getMessage()); } - throw cause; + + // Rethrow the root cause to ensure the exception is propagated properly + throw new RuntimeException(cause); } - sitewiseActions.getAssetPropValueAsync("Humidity property", humPropId, assetId); + sitewiseActions.getAssetPropValueAsync(humPropId, assetId); waitForInputToContinue(scanner); logger.info(DASHES); @@ -318,7 +325,13 @@ public static void runScenario(String assetModelName, String assetName, String logger.info("9. Describe the IoT SiteWise Gateway"); waitForInputToContinue(scanner); try { - sitewiseActions.describeGatewayAsync(gatewayId).join(); + sitewiseActions.describeGatewayAsync(gatewayId) + .thenAccept(response -> { + logger.info("Gateway Name: {}", response.gatewayName()); + logger.info("Gateway ARN: {}", response.gatewayArn()); + logger.info("Gateway Platform: {}", response.gatewayPlatform()); + logger.info("Gateway Creation Date: {}", response.creationDate()); + }).join(); } catch (RuntimeException rt) { Throwable cause = rt.getCause(); if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { @@ -355,7 +368,6 @@ public static void runScenario(String assetModelName, String assetName, String } } - // Delete the Gateway. try { sitewiseActions.deleteGatewayAsync(gatewayId).join(); } catch (RuntimeException rt) { diff --git a/javav2/example_code/iotsitewise/src/main/resources/data.json b/javav2/example_code/iotsitewise/src/main/resources/data.json deleted file mode 100644 index 2cdbfb2feb0..00000000000 --- a/javav2/example_code/iotsitewise/src/main/resources/data.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "assets": [ - { - "name": "Temperature", - "description": "Measures the ambient temperature", - "properties": [ - { - "name": "value", - "type": "number", - "unit": "°C", - "description": "The current temperature reading", - "value": 25.6 - }, - { - "name": "timestamp", - "type": "string", - "format": "date-time", - "description": "The timestamp of the temperature reading", - "value": "2024-09-09T12:30:00Z" - } - ] - }, - { - "name": "Humidity", - "description": "Measures the ambient humidity", - "properties": [ - { - "name": "value", - "type": "number", - "unit": "%", - "description": "The current humidity reading", - "value": 45.3 - }, - { - "name": "timestamp", - "type": "string", - "format": "date-time", - "description": "The timestamp of the humidity reading", - "value": "2024-09-09T12:35:00Z" - } - ] - } - ] -} diff --git a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java index 2d366cdcb15..6a25eed3eb9 100644 --- a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java +++ b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java @@ -64,7 +64,7 @@ public class SitewiseTests { @BeforeAll public static void setUp() { CloudFormationHelper.deployCloudFormationStack(ROLES_STACK); - Map stackOutputs = CloudFormationHelper.getStackOutputs(ROLES_STACK); + Map stackOutputs = CloudFormationHelper.getStackOutputsAsync(ROLES_STACK).join(); iamRole = stackOutputs.get("SitewiseRoleArn"); Gson gson = new Gson(); @@ -94,11 +94,9 @@ public void testCreateAssetModel() { throw new RuntimeException("Simulating failure: response or assetModelId is null"); } - // Simulate successful creation (won't reach this if above condition is met) assetModelId = response.assetModelId(); }); - // This won't be reached if the assert fails System.out.println("Test 2 passed"); } @@ -144,7 +142,7 @@ public void testSendProps() { @Order(6) public void testGETHumValue() { assertDoesNotThrow(() -> { - sitewiseActions.getAssetPropValueAsync("Humidity property", humPropId, assetId); + sitewiseActions.getAssetPropValueAsync(humPropId, assetId); }); System.out.println("Test 6 passed"); } From 95c89046649f1c564f38fc417a129629bcb22aa4 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Mon, 30 Sep 2024 16:45:10 -0400 Subject: [PATCH 35/41] rolled in review comments --- .../example/iotsitewise/HelloSitewise.java | 48 +++++-------------- .../scenario/CloudFormationHelper.java | 2 - .../iotsitewise/scenario/SitewiseActions.java | 38 +++++++-------- .../scenario/SitewiseScenario.java | 32 ++++--------- .../src/test/java/SitewiseTests.java | 17 ++++--- 5 files changed, 50 insertions(+), 87 deletions(-) diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java index 782a905e41f..7e6ee563da5 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/HelloSitewise.java @@ -5,55 +5,33 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.iotsitewise.IoTSiteWiseAsyncClient; -import software.amazon.awssdk.services.iotsitewise.model.AssetSummary; -import software.amazon.awssdk.services.iotsitewise.model.ListAssetsRequest; -import software.amazon.awssdk.services.iotsitewise.paginators.ListAssetsPublisher; - -import java.util.List; +import software.amazon.awssdk.services.iotsitewise.model.AssetModelType; +import software.amazon.awssdk.services.iotsitewise.model.ListAssetModelsRequest; +import software.amazon.awssdk.services.iotsitewise.paginators.ListAssetModelsPublisher; import java.util.concurrent.CompletableFuture; // snippet-start:[iotsitewise.hello.main] public class HelloSitewise { private static final Logger logger = LoggerFactory.getLogger(HelloSitewise.class); public static void main(String[] args) { - final String usage = """ - Usage: - - - Where: - assetModelId - The Id value of the asset model used in the IoT SiteWise program. - """; - - if (args.length != 1) { - logger.info(usage); - return; - } - - String assetModelId = args[0]; - fetchAssets(assetModelId); + fetchAssetModels(); } /** - * Fetches assets from AWS IoT SiteWise using the provided {@link IoTSiteWiseAsyncClient}. - * - * @param modelId the ID of the asset model to fetch assets for + * Fetches asset models using the provided {@link IoTSiteWiseAsyncClient}. */ - public static void fetchAssets(String modelId) { - IoTSiteWiseAsyncClient siteWiseAsyncClient = IoTSiteWiseAsyncClient.builder() - .build(); - - ListAssetsRequest assetsRequest = ListAssetsRequest.builder() - .maxResults(10) - .assetModelId(modelId) + public static void fetchAssetModels() { + IoTSiteWiseAsyncClient siteWiseAsyncClient = IoTSiteWiseAsyncClient.create(); + ListAssetModelsRequest assetModelsRequest = ListAssetModelsRequest.builder() + .assetModelTypes(AssetModelType.ASSET_MODEL) .build(); // Asynchronous paginator - process paginated results. - ListAssetsPublisher listAssetsPaginator = siteWiseAsyncClient.listAssetsPaginator(assetsRequest); - CompletableFuture future = listAssetsPaginator.subscribe(response -> { - response.assetSummaries().forEach(assetSummary -> - logger.info("Asset Name: {} ", assetSummary.name()) + ListAssetModelsPublisher listModelsPaginator = siteWiseAsyncClient.listAssetModelsPaginator(assetModelsRequest); + CompletableFuture future = listModelsPaginator.subscribe(response -> { + response.assetModelSummaries().forEach(assetSummary -> + logger.info("Asset Model Name: {} ", assetSummary.name()) ); }); diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java index 6217de1ed5e..0f5c9ee220b 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java @@ -9,7 +9,6 @@ import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; import software.amazon.awssdk.services.cloudformation.CloudFormationAsyncClient; -import software.amazon.awssdk.services.cloudformation.CloudFormationClient; import software.amazon.awssdk.services.cloudformation.model.Capability; import software.amazon.awssdk.services.cloudformation.model.CloudFormationException; import software.amazon.awssdk.services.cloudformation.model.DescribeStacksRequest; @@ -32,7 +31,6 @@ public class CloudFormationHelper { private static final Logger logger = LoggerFactory.getLogger(CloudFormationHelper.class); private static CloudFormationAsyncClient cloudFormationClient; - private static CloudFormationAsyncClient getCloudFormationClient() { if (cloudFormationClient == null) { SdkAsyncHttpClient httpClient = NettyNioAsyncHttpClient.builder() diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index 87fdb418739..993d9d30f6b 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -36,7 +36,6 @@ import software.amazon.awssdk.services.iotsitewise.model.DescribePortalRequest; import software.amazon.awssdk.services.iotsitewise.model.GatewayPlatform; import software.amazon.awssdk.services.iotsitewise.model.GetAssetPropertyValueRequest; -import software.amazon.awssdk.services.iotsitewise.model.GetAssetPropertyValueResponse; import software.amazon.awssdk.services.iotsitewise.model.GreengrassV2; import software.amazon.awssdk.services.iotsitewise.model.ListAssetModelPropertiesRequest; import software.amazon.awssdk.services.iotsitewise.model.ListAssetModelsRequest; @@ -123,7 +122,7 @@ public CompletableFuture createAssetModelAsync(String return getAsyncClient().createAssetModel(createAssetModelRequest) .whenComplete((response, exception) -> { if (exception != null) { - throw new RuntimeException("Failed to create asset model: " + exception.getMessage(), exception); + logger.error("Failed to create asset model: {} ", exception.getMessage()); } }); } @@ -148,7 +147,7 @@ public CompletableFuture createAssetAsync(String assetName, return getAsyncClient().createAsset(createAssetRequest) .whenComplete((response, exception) -> { if (exception != null) { - throw new RuntimeException("Failed to create asset: " + exception.getMessage(), exception); + logger.error("Failed to create asset: {}", exception.getMessage()); } }); } @@ -218,22 +217,24 @@ public CompletableFuture sendDataToSiteWiseA /** * Fetches the value of an asset property. * - * @param propId the ID of the asset property to fetch. - * @param assetId the ID of the asset to fetch the property value for. + * @param propId the ID of the asset property to fetch. + * @param assetId the ID of the asset to fetch the property value for. * @throws RuntimeException if an error occurs while fetching the property value. */ - public CompletableFuture getAssetPropValueAsync(String propId, String assetId) { + public CompletableFuture getAssetPropValueAsync(String propId, String assetId) { GetAssetPropertyValueRequest assetPropertyValueRequest = GetAssetPropertyValueRequest.builder() .propertyId(propId) .assetId(assetId) .build(); - CompletableFuture futureResponse = getAsyncClient().getAssetPropertyValue(assetPropertyValueRequest); - return futureResponse.whenComplete((response, exception) -> { + return getAsyncClient().getAssetPropertyValue(assetPropertyValueRequest) + .handle((response, exception) -> { if (exception != null) { - throw new RuntimeException("Error occurred while fetching property value: " + exception.getMessage(), exception); + logger.error("Error occurred while fetching property value: " + exception.getMessage(), exception); + throw (RuntimeException) exception; } - }).thenApply(response -> String.valueOf(response.propertyValue().value().doubleValue())); + return response.propertyValue().value().doubleValue(); + }); } // snippet-end:[sitewise.java2_get_property.main] @@ -300,7 +301,7 @@ public CompletableFuture deleteAssetModelAsync(String return getAsyncClient().deleteAssetModel(deleteAssetModelRequest) .whenComplete((response, exception) -> { if (exception != null) { - throw new RuntimeException("Failed to delete asset model with ID: " + assetModelId + ". Error: " + exception.getMessage(), exception); + logger.error("Failed to delete asset model with ID:{}.", exception.getMessage()); } }); } @@ -327,7 +328,7 @@ public CompletableFuture createPortalAsync(String portalName, String iam .handle((response, exception) -> { if (exception != null) { logger.error("Failed to create portal: {} ", exception.getCause().getMessage()); - throw (CompletionException) exception; + throw (RuntimeException) exception; } return response.portalId(); }); @@ -350,7 +351,7 @@ public CompletableFuture deletePortalAsync(String portalId return getAsyncClient().deletePortal(deletePortalRequest) .whenComplete((response, exception) -> { if (exception != null) { - throw new RuntimeException("Failed to delete portal with ID: " + portalId + ". Error: " + exception.getMessage(), exception); + logger.error("Failed to delete portal with ID: " + portalId + ". Error: " + exception.getMessage(), exception); } }); } @@ -382,7 +383,7 @@ public CompletableFuture getAssetModelIdAsync(String assetModelName) { // snippet-start:[sitewise.java2.describe.portal.main] /** - * Asynchronously describes a portal. + * Describes a portal. * * @param portalId the ID of the portal to describe. * @return a {@link CompletableFuture} that, when completed, will contain the URL of the described portal. @@ -434,7 +435,7 @@ public CompletableFuture createGatewayAsync(String gatewayName, String m logger.error("Error creating the gateway."); throw (RuntimeException) exception; } - System.out.println("The ARN of the gateway is " + response.gatewayArn()); + logger.info("The ARN of the gateway is {}" , response.gatewayArn()); return response.gatewayId(); }); } @@ -442,7 +443,7 @@ public CompletableFuture createGatewayAsync(String gatewayName, String m // snippet-start:[sitewise.java2.delete.gateway.main] /** - * Deletes the specified gateway asynchronously. + * Deletes the specified gateway. * * @param gatewayARN the ARN of the gateway to delete. * @return a CompletableFuture containing the response of the delete operation. @@ -456,7 +457,7 @@ public CompletableFuture deleteGatewayAsync(String gatewa return getAsyncClient().deleteGateway(deleteGatewayRequest) .whenComplete((response, exception) -> { if (exception != null) { - throw new RuntimeException("Failed to delete gateway: " + exception.getMessage(), exception); + logger.error("Failed to delete gateway: " + exception.getMessage(), exception); } else { logger.info("The Gateway was deleted successfully."); } @@ -466,7 +467,7 @@ public CompletableFuture deleteGatewayAsync(String gatewa // snippet-start:[sitewise.java2.describe.gateway.main] /** - * Asynchronously describes the specified gateway. + * Describes the specified gateway. * * @param gatewayId the ID of the gateway to describe. * @return a {@link CompletableFuture} that represents the asynchronous operation @@ -485,7 +486,6 @@ public CompletableFuture describeGatewayAsync(String ga } }); } - // snippet-end:[sitewise.java2.describe.gateway.main] private static Map generateSampleData() { diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index 59682e6a406..ae8a0f87967 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -27,22 +27,8 @@ public class SitewiseScenario { static SitewiseActions sitewiseActions = new SitewiseActions(); public static void main(String[] args) throws Throwable { - final String usage = """ - Usage: - - - Where: - contactEmail - The email address of the contact person associated with the IoT SiteWise program. - - """; - - // if (args.length != 1) { - // logger.info(usage); - // return; - // } - Scanner scanner = new Scanner(System.in); - String contactEmail = "scmacdon@amazon.com" ; //args[0]; + String contactEmail = "user@mydomain.com"; // Change email address. String assetModelName = "MyAssetModel1"; String assetName = "MyAsset1" ; String portalName = "MyPortal1" ; @@ -420,17 +406,16 @@ public static void runScenario(String assetModelName, String assetName, String private static void waitForInputToContinue(Scanner scanner) { while (true) { - System.out.println(""); - System.out.println("Enter 'c' followed by to continue:"); + logger.info(""); + logger.info("Enter 'c' followed by to continue:"); String input = scanner.nextLine(); if (input.trim().equalsIgnoreCase("c")) { - System.out.println("Continuing with the program..."); - System.out.println(""); + logger.info("Continuing with the program..."); + logger.info(""); break; } else { - // Handle invalid input. - System.out.println("Invalid input. Please try again."); + logger.info("Invalid input. Please try again."); } } } @@ -440,11 +425,10 @@ public static void countdown(int minutes) throws InterruptedException { for (int i = minutes * 60 + seconds; i >= 0; i--) { int displayMinutes = i / 60; int displaySeconds = i % 60; - System.out.print(String.format("\r%02d:%02d", displayMinutes, displaySeconds)); + System.out.printf("\r%02d:%02d", displayMinutes, displaySeconds); Thread.sleep(1000); // Wait for 1 second } - - System.out.println("Countdown complete!"); + logger.info("Countdown complete!"); } } // snippet-end:[iotsitewise.java2.scenario.main] \ No newline at end of file diff --git a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java index 6a25eed3eb9..a15069cc52f 100644 --- a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java +++ b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java @@ -28,6 +28,7 @@ import java.util.concurrent.CompletableFuture; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; @TestInstance(TestInstance.Lifecycle.PER_METHOD) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @@ -42,8 +43,6 @@ public class SitewiseTests { private static final String gatewayName = "myGateway"+ UUID.randomUUID(); private static final String myThing = "myThing"+ UUID.randomUUID(); - private static String assetModelHello = ""; - private static String assetModelId = ""; private static String iamRole = ""; @@ -67,18 +66,20 @@ public static void setUp() { Map stackOutputs = CloudFormationHelper.getStackOutputsAsync(ROLES_STACK).join(); iamRole = stackOutputs.get("SitewiseRoleArn"); + /* + The following values used in these integration tests are retrieved from AWS Secrets Manager. + */ Gson gson = new Gson(); String json = getSecretValues(); SecretValues values = gson.fromJson(json, SecretValues.class); contactEmail = values.getContactEmail(); - assetModelHello = values.getAssetModelHello(); } @Test @Tag("IntegrationTest") @Order(1) public void testHelloService() { - assertDoesNotThrow(() -> HelloSitewise.fetchAssets(assetModelHello)); + assertDoesNotThrow(HelloSitewise::fetchAssetModels); System.out.println(" Test 1 passed"); } @@ -93,8 +94,8 @@ public void testCreateAssetModel() { if (response == null || response.assetModelId() == null) { throw new RuntimeException("Simulating failure: response or assetModelId is null"); } - assetModelId = response.assetModelId(); + assertNotNull(assetModelId); }); System.out.println("Test 2 passed"); @@ -109,6 +110,7 @@ public void testCreateAsset() throws InterruptedException { CompletableFuture future = sitewiseActions.createAssetAsync(assetName, assetModelId); CreateAssetResponse response = future.join(); assetId = response.assetId(); + assertNotNull(assetId); }); System.out.println("Test 3 passed"); } @@ -153,6 +155,7 @@ public void testGETHumValue() { public void testCreatePortal() { assertDoesNotThrow(() -> { portalId = sitewiseActions.createPortalAsync(portalName, iamRole, contactEmail).join(); + assertNotNull(portalId); }); System.out.println("Test 7 passed"); } @@ -163,7 +166,7 @@ public void testCreatePortal() { public void testDescribePortal() { assertDoesNotThrow(() -> { String portalUrl = sitewiseActions.describePortalAsync(portalId).join(); - assertFalse(portalUrl.isEmpty()); + assertNotNull(portalUrl); }); System.out.println("Test 8 passed"); } @@ -174,7 +177,7 @@ public void testDescribePortal() { public void testCreateGateway() { assertDoesNotThrow(() -> { gatewayId = sitewiseActions.createGatewayAsync(gatewayName, myThing).join(); - assertFalse(gatewayId.isEmpty()); + assertNotNull(gatewayId); }); System.out.println("Test 9 passed"); } From 354df7813f890f65c0de99b3be4e97b1d72b3d54 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Mon, 30 Sep 2024 17:04:53 -0400 Subject: [PATCH 36/41] rolled in review comments --- basics_scenarios/sitewise_scenario/SPECIFICATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basics_scenarios/sitewise_scenario/SPECIFICATION.md b/basics_scenarios/sitewise_scenario/SPECIFICATION.md index 98361b4b2ce..71208af7df0 100644 --- a/basics_scenarios/sitewise_scenario/SPECIFICATION.md +++ b/basics_scenarios/sitewise_scenario/SPECIFICATION.md @@ -12,7 +12,7 @@ This Basics scenario requires an IAM role that has permissions to work with AWS SiteWise service. The scenario creates this resource using a CloudFormation template. ## Hello AWS IoT SiteWise -This program is intended for users not familiar with the AWS IoT SiteWise Service to easily get up and running. The program uses a `listAssetsPaginator` to demonstrate how you can read through Asset information. +This program is intended for users not familiar with the AWS IoT SiteWise Service to easily get up and running. The program uses a `listAssetModelsPaginator` to demonstrate how you can read through Asset Model information. ## Basics Scenario Program Flow The AWS IoT SiteWise Basics scenario executes the following operations. From f1c037e304be05618755cb72fbc939627e46b289 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 2 Oct 2024 14:48:36 -0400 Subject: [PATCH 37/41] Rolled in reviewers changes --- .../iotsitewise/scenario/SitewiseActions.java | 212 +++++++++++------ .../scenario/SitewiseScenario.java | 225 +++++++++--------- 2 files changed, 252 insertions(+), 185 deletions(-) diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java index 993d9d30f6b..079ca3a48da 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java @@ -34,6 +34,7 @@ import software.amazon.awssdk.services.iotsitewise.model.DeletePortalRequest; import software.amazon.awssdk.services.iotsitewise.model.DeletePortalResponse; import software.amazon.awssdk.services.iotsitewise.model.DescribePortalRequest; +import software.amazon.awssdk.services.iotsitewise.model.DescribePortalResponse; import software.amazon.awssdk.services.iotsitewise.model.GatewayPlatform; import software.amazon.awssdk.services.iotsitewise.model.GetAssetPropertyValueRequest; import software.amazon.awssdk.services.iotsitewise.model.GreengrassV2; @@ -85,12 +86,18 @@ private static IoTSiteWiseAsyncClient getAsyncClient() { } // snippet-start:[sitewise.java2_create_asset_model.main] + /** * Creates an asset model. * * @param name the name of the asset model to create. - * @return a {@link CompletableFuture} that completes with the created {@link CreateAssetModelResponse} when the operation is complete. - * @throws RuntimeException if an error occurs while creating the asset model. + * @return a {@link CompletableFuture} that represents a {@link CreateAssetModelResponse} result. The calling code + * can attach callbacks, then handle the result or exception by calling {@link CompletableFuture#join()} or + * {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps it + * available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture createAssetModelAsync(String name) { PropertyType humidity = PropertyType.builder() @@ -122,20 +129,26 @@ public CompletableFuture createAssetModelAsync(String return getAsyncClient().createAssetModel(createAssetModelRequest) .whenComplete((response, exception) -> { if (exception != null) { - logger.error("Failed to create asset model: {} ", exception.getMessage()); + logger.error("Failed to create asset model: {} ", exception.getCause().getMessage()); } }); } // snippet-end:[sitewise.java2_create_asset_model.main] // snippet-start:[sitewise.java2_create_asset.main] + /** - * Creates an asset with the specified name and model Id. + * Creates an asset with the specified name and asset model Id. * - * @param assetName the name of the asset to create. + * @param assetName the name of the asset to create. * @param assetModelId the Id of the asset model to associate with the asset. - * @return a {@link CompletableFuture} that completes with the {@link CreateAssetResponse} when the asset creation is complete. - * @throws RuntimeException if the asset creation fails. + * @return a {@link CompletableFuture} that represents a {@link CreateAssetResponse} result. The calling code can + * attach callbacks, then handle the result or exception by calling {@link CompletableFuture#join()} or + * {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps it + * available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture createAssetAsync(String assetName, String assetModelId) { CreateAssetRequest createAssetRequest = CreateAssetRequest.builder() @@ -147,7 +160,7 @@ public CompletableFuture createAssetAsync(String assetName, return getAsyncClient().createAsset(createAssetRequest) .whenComplete((response, exception) -> { if (exception != null) { - logger.error("Failed to create asset: {}", exception.getMessage()); + logger.error("Failed to create asset: {}", exception.getCause().getMessage()); } }); } @@ -160,7 +173,13 @@ public CompletableFuture createAssetAsync(String assetName, * @param assetId the ID of the asset to which the data will be sent. * @param tempPropertyId the ID of the temperature property. * @param humidityPropId the ID of the humidity property. - * @return a CompletableFuture representing the response from the SiteWise service. + * @return a {@link CompletableFuture} that represents a {@link BatchPutAssetPropertyValueResponse} result. The + * calling code can attach callbacks, then handle the result or exception by calling + * {@link CompletableFuture#join()} or {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps it + * available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture sendDataToSiteWiseAsync(String assetId, String tempPropertyId, String humidityPropId) { Map sampleData = generateSampleData(); @@ -206,8 +225,6 @@ public CompletableFuture sendDataToSiteWiseA .whenComplete((response, exception) -> { if (exception != null) { logger.error("An exception occurred: {}", exception.getCause().getMessage()); - } else { - logger.info("Data sent successfully."); } }); } @@ -219,22 +236,28 @@ public CompletableFuture sendDataToSiteWiseA * * @param propId the ID of the asset property to fetch. * @param assetId the ID of the asset to fetch the property value for. - * @throws RuntimeException if an error occurs while fetching the property value. + * @return a {@link CompletableFuture} that represents a {@link Double} result. The calling code can attach + * callbacks, then handle the result or exception by calling {@link CompletableFuture#join()} or + * {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture getAssetPropValueAsync(String propId, String assetId) { GetAssetPropertyValueRequest assetPropertyValueRequest = GetAssetPropertyValueRequest.builder() - .propertyId(propId) - .assetId(assetId) - .build(); + .propertyId(propId) + .assetId(assetId) + .build(); return getAsyncClient().getAssetPropertyValue(assetPropertyValueRequest) - .handle((response, exception) -> { - if (exception != null) { - logger.error("Error occurred while fetching property value: " + exception.getMessage(), exception); - throw (RuntimeException) exception; - } - return response.propertyValue().value().doubleValue(); - }); + .handle((response, exception) -> { + if (exception != null) { + logger.error("Error occurred while fetching property value: {}.", exception.getCause().getMessage()); + throw (CompletionException) exception; + } + return response.propertyValue().value().doubleValue(); + }); } // snippet-end:[sitewise.java2_get_property.main] @@ -242,9 +265,14 @@ public CompletableFuture getAssetPropValueAsync(String propId, String as /** * Retrieves the property IDs associated with a specific asset model. * - * @param assetModelId the ID of the asset model to retrieve the property IDs for. - * @return a {@link CompletableFuture} that, when completed, contains a {@link Map} mapping the property names to their corresponding IDs. - * @throws CompletionException if an error occurs while retrieving the asset model properties. + * @param assetModelId the ID of the asset model that defines the properties. + * @return a {@link CompletableFuture} that represents a {@link Map} result that associates the property name to the + * propert ID. The calling code can attach callbacks, then handle the result or exception by calling + * {@link CompletableFuture#join()} or {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture> getPropertyIds(String assetModelId) { ListAssetModelPropertiesRequest modelPropertiesRequest = ListAssetModelPropertiesRequest.builder().assetModelId(assetModelId).build(); @@ -255,7 +283,8 @@ public CompletableFuture> getPropertyIds(String assetModelId .collect(Collectors .toMap(AssetModelPropertySummary::name, AssetModelPropertySummary::id)); } else { - throw (CompletionException) throwable.getCause(); + logger.error("Error occurred while fetching property IDs: {}.", throwable.getCause().getMessage()); + throw (CompletionException) throwable; } }); } @@ -266,8 +295,13 @@ public CompletableFuture> getPropertyIds(String assetModelId * Deletes an asset. * * @param assetId the ID of the asset to be deleted. - * @return a {@link CompletableFuture} that represents the asynchronous operation of deleting the asset. - * @throws RuntimeException if the asset deletion fails. + * @return a {@link CompletableFuture} that represents a {@link DeleteAssetResponse} result. The calling code can + * attach callbacks, then handle the result or exception by calling {@link CompletableFuture#join()} or + * {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture deleteAssetAsync(String assetId) { DeleteAssetRequest deleteAssetRequest = DeleteAssetRequest.builder() @@ -278,8 +312,6 @@ public CompletableFuture deleteAssetAsync(String assetId) { .whenComplete((response, exception) -> { if (exception != null) { logger.error("An error occurred deleting asset with id: {}", assetId); - } else { - logger.info("Request to delete the asset completed successfully."); } }); } @@ -290,8 +322,13 @@ public CompletableFuture deleteAssetAsync(String assetId) { * Deletes an Asset Model with the specified ID. * * @param assetModelId the ID of the Asset Model to delete. - * @return a {@link CompletableFuture} that completes with the {@link DeleteAssetModelResponse} when the operation is complete. - * @throws RuntimeException if the operation fails, containing the error message and the underlying exception. + * @return a {@link CompletableFuture} that represents a {@link DeleteAssetModelResponse} result. The calling code + * can attach callbacks, then handle the result or exception by calling {@link CompletableFuture#join()} or + * {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture deleteAssetModelAsync(String assetModelId) { DeleteAssetModelRequest deleteAssetModelRequest = DeleteAssetModelRequest.builder() @@ -314,7 +351,13 @@ public CompletableFuture deleteAssetModelAsync(String * @param portalName the name of the portal to create. * @param iamRole the IAM role ARN to use for the portal. * @param contactEmail the email address of the portal contact. - * @return a {@link CompletableFuture} that completes with the portal ID when the portal is created successfully, or throws a {@link RuntimeException} if the creation fails. + * @return a {@link CompletableFuture} that represents a {@link String} result of the portal ID. The calling code + * can attach callbacks, then handle the result or exception by calling {@link CompletableFuture#join()} or + * {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture createPortalAsync(String portalName, String iamRole, String contactEmail) { CreatePortalRequest createPortalRequest = CreatePortalRequest.builder() @@ -328,7 +371,7 @@ public CompletableFuture createPortalAsync(String portalName, String iam .handle((response, exception) -> { if (exception != null) { logger.error("Failed to create portal: {} ", exception.getCause().getMessage()); - throw (RuntimeException) exception; + throw (CompletionException) exception; } return response.portalId(); }); @@ -340,8 +383,13 @@ public CompletableFuture createPortalAsync(String portalName, String iam * Deletes a portal. * * @param portalId the ID of the portal to be deleted. - * @return a {@link CompletableFuture} containing the {@link DeletePortalResponse} when the operation is complete. - * @throws RuntimeException if the portal deletion fails, with the error message and the underlying exception. + * @return a {@link CompletableFuture} that represents a {@link DeletePortalResponse}. The calling code can attach + * callbacks, then handle the result or exception by calling {@link CompletableFuture#join()} or + * {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture deletePortalAsync(String portalId) { DeletePortalRequest deletePortalRequest = DeletePortalRequest.builder() @@ -351,7 +399,7 @@ public CompletableFuture deletePortalAsync(String portalId return getAsyncClient().deletePortal(deletePortalRequest) .whenComplete((response, exception) -> { if (exception != null) { - logger.error("Failed to delete portal with ID: " + portalId + ". Error: " + exception.getMessage(), exception); + logger.error("Failed to delete portal with ID: {}. Error: {}", portalId, exception.getCause().getMessage()); } }); } @@ -361,33 +409,45 @@ public CompletableFuture deletePortalAsync(String portalId /** * Retrieves the asset model ID for the given asset model name. * - * @param assetModelName the name of the asset model to retrieve the ID for. - * @return a {@link CompletableFuture} that, when completed, contains the asset model ID, or {@code null} if the asset model is not found. + * @param assetModelName the name of the asset model for the ID. + * @return a {@link CompletableFuture} that represents a {@link String} result of the asset model ID or null if the + * asset model cannot be found. The calling code can attach callbacks, then handle the result or exception + * by calling {@link CompletableFuture#join()} or {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture getAssetModelIdAsync(String assetModelName) { ListAssetModelsRequest listAssetModelsRequest = ListAssetModelsRequest.builder().build(); return getAsyncClient().listAssetModels(listAssetModelsRequest) - .handle((listAssetModelsResponse, exception) -> { - if (exception != null) { - throw new RuntimeException("Failed to retrieve Asset Model ARN: " + exception.getMessage(), exception); - } - for (AssetModelSummary assetModelSummary : listAssetModelsResponse.assetModelSummaries()) { - if (assetModelSummary.name().equals(assetModelName)) { - return assetModelSummary.id(); + .handle((listAssetModelsResponse, exception) -> { + if (exception != null) { + logger.error("Failed to retrieve Asset Model ID: {}", exception.getCause().getMessage()); + throw (CompletionException) exception; } - } - return null; - }); + for (AssetModelSummary assetModelSummary : listAssetModelsResponse.assetModelSummaries()) { + if (assetModelSummary.name().equals(assetModelName)) { + return assetModelSummary.id(); + } + } + return null; + }); } // snippet-end:[sitewise.java2.list.asset.model.main] // snippet-start:[sitewise.java2.describe.portal.main] /** - * Describes a portal. + * Retrieves a portal's description. * * @param portalId the ID of the portal to describe. - * @return a {@link CompletableFuture} that, when completed, will contain the URL of the described portal. - * @throws RuntimeException if the portal description operation fails. + * @return a {@link CompletableFuture} that represents a {@link String} result of the portal's start URL + * (see: {@link DescribePortalResponse#portalStartUrl()}). The calling code can attach callbacks, then handle the + * result or exception by calling {@link CompletableFuture#join()} or {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture describePortalAsync(String portalId) { DescribePortalRequest request = DescribePortalRequest.builder() @@ -397,7 +457,8 @@ public CompletableFuture describePortalAsync(String portalId) { return getAsyncClient().describePortal(request) .handle((response, exception) -> { if (exception != null) { - throw new RuntimeException("Failed to describe portal: " + exception.getMessage(), exception); + logger.error("An exception occurred retrieving the portal description: {}", exception.getCause().getMessage()); + throw (CompletionException) exception; } return response.portalStartUrl(); }); @@ -405,11 +466,19 @@ public CompletableFuture describePortalAsync(String portalId) { // snippet-end:[sitewise.java2.describe.portal.main] // snippet-start:[sitewise.java2.create.gateway.main] + /** * Creates a new IoT Sitewise gateway. * - * @return a {@link CompletableFuture} containing the {@link CreateGatewayResponse} representing the created gateway. - * @throws RuntimeException if there was an error creating the gateway. + * @param gatewayName The name of the gateway to create. + * @param myThing The name of the core device thing to associate with the gateway. + * @return a {@link CompletableFuture} that represents a {@link String} result of the gateways ID. The calling code + * can attach callbacks, then handle the result or exception by calling {@link CompletableFuture#join()} or + * {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture createGatewayAsync(String gatewayName, String myThing) { GreengrassV2 gg = GreengrassV2.builder() @@ -433,7 +502,7 @@ public CompletableFuture createGatewayAsync(String gatewayName, String m .handle((response, exception) -> { if (exception != null) { logger.error("Error creating the gateway."); - throw (RuntimeException) exception; + throw (CompletionException) exception; } logger.info("The ARN of the gateway is {}" , response.gatewayArn()); return response.gatewayId(); @@ -445,21 +514,24 @@ public CompletableFuture createGatewayAsync(String gatewayName, String m /** * Deletes the specified gateway. * - * @param gatewayARN the ARN of the gateway to delete. - * @return a CompletableFuture containing the response of the delete operation. - * @throws RuntimeException if an error occurs during the delete operation. + * @param gatewayId the ID of the gateway to delete. + * @return a {@link CompletableFuture} that represents a {@link DeleteGatewayResponse} result.. The calling code + * can attach callbacks, then handle the result or exception by calling {@link CompletableFuture#join()} or + * {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ - public CompletableFuture deleteGatewayAsync(String gatewayARN) { + public CompletableFuture deleteGatewayAsync(String gatewayId) { DeleteGatewayRequest deleteGatewayRequest = DeleteGatewayRequest.builder() - .gatewayId(gatewayARN) + .gatewayId(gatewayId) .build(); return getAsyncClient().deleteGateway(deleteGatewayRequest) .whenComplete((response, exception) -> { if (exception != null) { - logger.error("Failed to delete gateway: " + exception.getMessage(), exception); - } else { - logger.info("The Gateway was deleted successfully."); + logger.error("Failed to delete gateway: {}", exception.getCause().getMessage()); } }); } @@ -470,9 +542,13 @@ public CompletableFuture deleteGatewayAsync(String gatewa * Describes the specified gateway. * * @param gatewayId the ID of the gateway to describe. - * @return a {@link CompletableFuture} that represents the asynchronous operation - * which will complete with a {@link DescribeGatewayResponse} containing - * information about the specified gateway. + * @return a {@link CompletableFuture} that represents a {@link DescribeGatewayResponse} result. The calling code + * can attach callbacks, then handle the result or exception by calling {@link CompletableFuture#join()} or + * {@link CompletableFuture#get()}. + *

+ * If any completion stage in this method throws an exception, the method logs the exception cause and keeps + * it available to the calling code as a {@link CompletionException}. By calling + * {@link CompletionException#getCause()}, the calling code can access the original exception. */ public CompletableFuture describeGatewayAsync(String gatewayId) { DescribeGatewayRequest request = DescribeGatewayRequest.builder() @@ -482,7 +558,7 @@ public CompletableFuture describeGatewayAsync(String ga return getAsyncClient().describeGateway(request) .whenComplete((response, exception) -> { if (exception != null) { - logger.error("An error occurred during the describeGateway method", exception); + logger.error("An error occurred during the describeGateway method: {}", exception.getCause().getMessage()); } }); } diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index ae8a0f87967..f8794855bd7 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -13,6 +13,7 @@ import java.util.Map; import java.util.Scanner; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; // snippet-start:[iotsitewise.java2.scenario.main] public class SitewiseScenario { @@ -85,24 +86,24 @@ public static void runScenario(String assetModelName, String assetName, String This scenario creates two asset model properties: temperature and humidity. """); waitForInputToContinue(scanner); - String assetModelId; + String assetModelId = null; try { - CompletableFuture future = sitewiseActions.createAssetModelAsync(assetModelName); - CreateAssetModelResponse response = future.join(); + CreateAssetModelResponse response = sitewiseActions.createAssetModelAsync(assetModelName).join(); assetModelId = response.assetModelId(); logger.info("Asset Model successfully created. Asset Model ID: {}. ", assetModelId); - - } catch (RuntimeException rt) { - Throwable cause = rt; - while (cause.getCause() != null && !(cause instanceof ResourceAlreadyExistsException)) { - cause = cause.getCause(); - } + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); if (cause instanceof ResourceAlreadyExistsException) { - assetModelId = sitewiseActions.getAssetModelIdAsync(assetModelName).join(); - logger.info("The Asset Model {} already exists. The id of the existing model is {}. Moving on...", assetModelName, assetModelId); + try { + assetModelId = sitewiseActions.getAssetModelIdAsync(assetModelName).join(); + logger.info("The Asset Model {} already exists. The id of the existing model is {}. Moving on...", assetModelName, assetModelId); + } catch (CompletionException cex) { + logger.error("Exception thrown acquiring the asset model id: {}", cex.getCause().getCause(), cex); + return; + } } else { - logger.info("An unexpected error occurred: " + rt.getMessage(), rt); - throw cause; + logger.info("An unexpected error occurred: " + cause.getMessage(), cause); + return; } } waitForInputToContinue(scanner); @@ -110,34 +111,26 @@ public static void runScenario(String assetModelName, String assetName, String logger.info(DASHES); logger.info("2. Create an AWS IoT SiteWise Asset"); logger.info(""" - The IoT SiteWise model that we just created defines the structure and metadata for your physical assets. Now we create - an asset from the asset model. - + The IoT SiteWise model that we just created defines the structure and metadata for your physical assets. + Now we create an asset from the asset model. + """); - logger.info("Let's wait 1 minute for the asset model to be ready."); - countdown(1); + logger.info("Let's wait 30 seconds for the asset to be ready."); + countdown(30); waitForInputToContinue(scanner); String assetId; try { - CompletableFuture future = sitewiseActions.createAssetAsync(assetName, assetModelId); - CreateAssetResponse response = future.join(); + CreateAssetResponse response = sitewiseActions.createAssetAsync(assetName, assetModelId).join(); assetId = response.assetId(); logger.info("Asset created with ID: {}", assetId); - - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - while (cause != null) { - if (cause instanceof software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException) { - logger.info("The AWS resource was not found: {}", cause.getMessage()); - break; - } - cause = cause.getCause(); - } - - if (cause == null) { - logger.info("An unexpected error occurred: {}", rt.getMessage()); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof ResourceNotFoundException) { + logger.info("The asset model id was not found: {}", cause.getMessage(), cause); + } else { + logger.info("An unexpected error occurred: {}", cause.getMessage(), cause); } - throw cause; + return; } waitForInputToContinue(scanner); logger.info(DASHES); @@ -149,16 +142,15 @@ public static void runScenario(String assetModelName, String assetName, String temperature and humidity property ID values. """); waitForInputToContinue(scanner); - - Map propertyIds = null; + Map propertyIds = null; try { propertyIds = sitewiseActions.getPropertyIds(assetModelId).join(); - } catch (RuntimeException e) { - Throwable cause = e.getCause(); - if (cause != null && cause instanceof IoTSiteWiseException) { - logger.error("IoTSiteWiseException occurred: {}", cause.getMessage(), e); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof IoTSiteWiseException) { + logger.error("IoTSiteWiseException occurred: {}", cause.getMessage(), ce); } else { - logger.error("An unexpected error occurred: {}", e.getMessage(), e); + logger.error("An unexpected error occurred: {}", cause.getMessage(), ce); } return; } @@ -183,12 +175,13 @@ public static void runScenario(String assetModelName, String assetName, String waitForInputToContinue(scanner); try { sitewiseActions.sendDataToSiteWiseAsync(assetId, tempPropId, humPropId).join(); - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause != null && cause instanceof ResourceNotFoundException) { - logger.error("The AWS resource was not found: {}", cause.getMessage(), rt); + logger.info("Data sent successfully."); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof ResourceNotFoundException) { + logger.error("The AWS resource was not found: {}", cause.getMessage(), cause); } else { - logger.error("An unexpected error occurred: {}", rt.getMessage(), rt); + logger.error("An unexpected error occurred: {}", cause.getMessage(), cause); } return; } @@ -205,35 +198,24 @@ public static void runScenario(String assetModelName, String assetName, String """); waitForInputToContinue(scanner); try { - sitewiseActions.getAssetPropValueAsync(tempPropId, assetId) - .whenComplete((assetVal, exception) -> { - if (exception != null) { - logger.error("Error fetching asset property value: {}", exception.getMessage(), exception); - } else { - logger.info("The property name is: {}", "Temperature"); - logger.info("The value of this property is: {}", assetVal); - } - }).join(); + Double assetVal = sitewiseActions.getAssetPropValueAsync(tempPropId, assetId).join(); + logger.info("The property name is: {}", "Temperature"); + logger.info("The value of this property is: {}", assetVal); + waitForInputToContinue(scanner); - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - while (cause != null) { - if (cause instanceof software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException) { - logger.info("The AWS resource was not found: {}", cause.getMessage()); - break; + assetVal = sitewiseActions.getAssetPropValueAsync(humPropId, assetId).join(); + logger.info("The property name is: {}", "Humidity"); + logger.info("The value of this property is: {}", assetVal); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof ResourceNotFoundException) { + logger.info("The AWS resource was not found: {}", cause.getMessage(), cause); + } else { + logger.info("An unexpected error occurred: {}", cause.getMessage(), cause); } - cause = cause.getCause(); + return; } - - if (cause == null) { - logger.info("An unexpected error occurred: {}", rt.getMessage()); - } - - // Rethrow the root cause to ensure the exception is propagated properly - throw new RuntimeException(cause); - } - sitewiseActions.getAssetPropValueAsync(humPropId, assetId); waitForInputToContinue(scanner); logger.info(DASHES); @@ -248,12 +230,13 @@ public static void runScenario(String assetModelName, String assetName, String try { portalId = sitewiseActions.createPortalAsync(portalName, iamRole, contactEmail).join(); logger.info("Portal created successfully. Portal ID {}", portalId); - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause != null && cause instanceof IoTSiteWiseException siteWiseEx) { - logger.error("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof IoTSiteWiseException siteWiseEx) { + logger.error("IoT SiteWise error occurred: Error message: {}, Error code {}", + siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode(), siteWiseEx); } else { - logger.error("An unexpected error occurred: {}", rt.getMessage()); + logger.error("An unexpected error occurred: {}", cause.getMessage()); } return; } @@ -263,18 +246,19 @@ public static void runScenario(String assetModelName, String assetName, String logger.info(DASHES); logger.info("7. Describe the Portal"); logger.info(""" - In this step, we will describe the step and provide the portal URL. + In this step, we get a description of the portal and display the portal URL. """); waitForInputToContinue(scanner); try { String portalUrl = sitewiseActions.describePortalAsync(portalId).join(); logger.info("Portal URL: {}", portalUrl); - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { - logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", + notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode(), notFoundException); } else { - logger.error("An unexpected error occurred: {}", rt.getMessage()); + logger.error("An unexpected error occurred: {}", cause.getMessage()); } return; } @@ -296,12 +280,13 @@ public static void runScenario(String assetModelName, String assetName, String try { gatewayId = sitewiseActions.createGatewayAsync(gatewayName, myThing).join(); logger.info("Gateway creation completed successfully. id is {}", gatewayId ); - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause != null && cause instanceof IoTSiteWiseException siteWiseEx) { - logger.error("IoT SiteWise error occurred: Error message: {}, Error code {}", siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode()); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof IoTSiteWiseException siteWiseEx) { + logger.error("IoT SiteWise error occurred: Error message: {}, Error code {}", + siteWiseEx.getMessage(), siteWiseEx.awsErrorDetails().errorCode(), siteWiseEx); } else { - logger.error("An unexpected error occurred: {}", rt.getMessage()); + logger.error("An unexpected error occurred: {}", cause.getMessage()); } return; } @@ -318,12 +303,13 @@ public static void runScenario(String assetModelName, String assetName, String logger.info("Gateway Platform: {}", response.gatewayPlatform()); logger.info("Gateway Creation Date: {}", response.creationDate()); }).join(); - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { - logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", + notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode(), notFoundException); } else { - logger.error("An unexpected error occurred: {}", rt.getMessage()); + logger.error("An unexpected error occurred: {}", cause.getMessage(), cause); } return; } @@ -345,50 +331,55 @@ public static void runScenario(String assetModelName, String assetName, String sitewiseActions.deletePortalAsync(portalId).join(); logger.info("Portal {} was deleted successfully.", portalId); - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { - logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", + notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode(), notFoundException); } else { - logger.error("An unexpected error occurred: {}", rt.getMessage()); + logger.error("An unexpected error occurred: {}", cause.getMessage()); } } try { sitewiseActions.deleteGatewayAsync(gatewayId).join(); - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { - logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); + logger.info("Gateway {} was deleted successfully.", gatewayId); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", + notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode(), notFoundException); } else { - logger.error("An unexpected error occurred: {}", rt.getMessage()); + logger.error("An unexpected error occurred: {}", cause.getMessage()); } } try { sitewiseActions.deleteAssetAsync(assetId).join(); - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { - logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); + logger.info("Request to delete asset {} sent successfully", assetId); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", + notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode(), notFoundException); } else { - logger.error("An unexpected error occurred: {}", rt.getMessage()); + logger.error("An unexpected error occurred: {}", cause.getMessage()); } } logger.info("Let's wait 1 minute for the asset to be deleted."); - countdown(1); + countdown(60); waitForInputToContinue(scanner); logger.info("Delete the AWS IoT SiteWise Asset Model"); try { sitewiseActions.deleteAssetModelAsync(assetModelId).join(); logger.info("Asset model deleted successfully."); - - } catch (RuntimeException rt) { - Throwable cause = rt.getCause(); - if (cause != null && cause instanceof ResourceNotFoundException notFoundException) { - logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode()); + } catch (CompletionException ce) { + Throwable cause = ce.getCause(); + if (cause instanceof ResourceNotFoundException notFoundException) { + logger.error("A ResourceNotFoundException occurred: Error message: {}, Error code {}", + notFoundException.getMessage(), notFoundException.awsErrorDetails().errorCode(), notFoundException); } else { - logger.error("An unexpected error occurred: {}", rt.getMessage()); + logger.error("An unexpected error occurred: {}", cause.getMessage()); } } waitForInputToContinue(scanner); @@ -420,14 +411,14 @@ private static void waitForInputToContinue(Scanner scanner) { } } - public static void countdown(int minutes) throws InterruptedException { - int seconds = 0; - for (int i = minutes * 60 + seconds; i >= 0; i--) { + public static void countdown(int totalSeconds) throws InterruptedException { + for (int i = totalSeconds; i >= 0; i--) { int displayMinutes = i / 60; int displaySeconds = i % 60; System.out.printf("\r%02d:%02d", displayMinutes, displaySeconds); Thread.sleep(1000); // Wait for 1 second } + System.out.println(); // Move to the next line after countdown logger.info("Countdown complete!"); } } From e88e71123bfb9844c85127c313f3de4221556af1 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 2 Oct 2024 14:49:36 -0400 Subject: [PATCH 38/41] Rolled in reviewers changes --- .../java/com/example/iotsitewise/scenario/SitewiseScenario.java | 1 - 1 file changed, 1 deletion(-) diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java index f8794855bd7..2f313697f90 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/SitewiseScenario.java @@ -12,7 +12,6 @@ import software.amazon.awssdk.services.iotsitewise.model.ResourceNotFoundException; import java.util.Map; import java.util.Scanner; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; // snippet-start:[iotsitewise.java2.scenario.main] From 765a9365c4d8c197291bfad06bd2b45e0ba848b4 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Wed, 2 Oct 2024 15:21:10 -0400 Subject: [PATCH 39/41] updated readme --- javav2/example_code/iotsitewise/README.md | 30 +++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/javav2/example_code/iotsitewise/README.md b/javav2/example_code/iotsitewise/README.md index 314ac2126ec..71c24b6f9b5 100644 --- a/javav2/example_code/iotsitewise/README.md +++ b/javav2/example_code/iotsitewise/README.md @@ -31,7 +31,7 @@ For prerequisites, see the [README](../../README.md#Prerequisites) in the `javav ### Get started -- [Hello AWS IoT SiteWise](src/main/java/com/example/iotsitewise/HelloSitewise.java#L17) (`ListVersions`) +- [Hello AWS IoT SiteWise](src/main/java/com/example/iotsitewise/HelloSitewise.java#L14) (`ListVersions`) ### Basics @@ -45,20 +45,20 @@ Code examples that show you how to perform the essential operations within a ser Code excerpts that show you how to call individual service functions. -- [BatchPutAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L161) -- [CreateAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L135) -- [CreateAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L90) -- [CreateGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L398) -- [CreatePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L300) -- [DeleteAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L254) -- [DeleteAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L278) -- [DeleteGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L435) -- [DeletePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L328) -- [DescribeAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L234) -- [DescribeGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L452) -- [DescribePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L374) -- [GetAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L213) -- [ListAssetModels](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L350) +- [BatchPutAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L169) +- [CreateAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L138) +- [CreateAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L88) +- [CreateGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L468) +- [CreatePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L347) +- [DeleteAsset](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L293) +- [DeleteAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L320) +- [DeleteGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L513) +- [DeletePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L381) +- [DescribeAssetModel](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L264) +- [DescribeGateway](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L540) +- [DescribePortal](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L439) +- [GetAssetPropertyValue](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L233) +- [ListAssetModels](src/main/java/com/example/iotsitewise/scenario/SitewiseActions.java#L408) From 3765597d077945c6cf8ec10364e6d40cd3ea69bb Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 3 Oct 2024 14:54:55 -0400 Subject: [PATCH 40/41] rolled in review comments --- .../scenario/CloudFormationHelper.java | 9 +++++-- .../src/test/java/SitewiseTests.java | 27 +++++-------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java index 0f5c9ee220b..1d97c226f18 100644 --- a/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java +++ b/javav2/example_code/iotsitewise/src/main/java/com/example/iotsitewise/scenario/CloudFormationHelper.java @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 package com.example.iotsitewise.scenario; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; @@ -16,6 +17,7 @@ import software.amazon.awssdk.services.cloudformation.model.Output; import software.amazon.awssdk.services.cloudformation.model.Stack; import software.amazon.awssdk.services.cloudformation.waiters.CloudFormationAsyncWaiter; + import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; @@ -26,11 +28,13 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; + public class CloudFormationHelper { private static final String CFN_TEMPLATE = "SitewiseRoles-template.yaml"; private static final Logger logger = LoggerFactory.getLogger(CloudFormationHelper.class); private static CloudFormationAsyncClient cloudFormationClient; + private static CloudFormationAsyncClient getCloudFormationClient() { if (cloudFormationClient == null) { SdkAsyncHttpClient httpClient = NettyNioAsyncHttpClient.builder() @@ -99,8 +103,8 @@ public static Boolean describeStack(String stackName) { CompletableFuture future = getCloudFormationClient().describeStacks(); DescribeStacksResponse stacksResponse = (DescribeStacksResponse) future.join(); List stacks = stacksResponse.stacks(); - for (Stack myStack :stacks) { - if (myStack.stackName().compareTo(stackName)==0){ + for (Stack myStack : stacks) { + if (myStack.stackName().compareTo(stackName) == 0) { return true; } } @@ -109,6 +113,7 @@ public static Boolean describeStack(String stackName) { } return false; } + public static void destroyCloudFormationStack(String stackName) { getCloudFormationClient().deleteStack(b -> b.stackName(stackName)) .whenComplete((dsr, t) -> { diff --git a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java index a15069cc52f..43668733106 100644 --- a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java +++ b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; + import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -34,14 +35,14 @@ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class SitewiseTests { - private static final String assetModelName = "MyAssetModel"+ UUID.randomUUID(); + private static final String assetModelName = "MyAssetModel" + UUID.randomUUID(); private static final String assetName = "MyAsset"; private static String assetId = ""; private static final String portalName = "MyPortal"; private static String contactEmail = ""; - private static final String gatewayName = "myGateway"+ UUID.randomUUID(); - private static final String myThing = "myThing"+ UUID.randomUUID(); + private static final String gatewayName = "myGateway" + UUID.randomUUID(); + private static final String myThing = "myThing" + UUID.randomUUID(); private static String assetModelId = ""; @@ -80,7 +81,6 @@ public static void setUp() { @Order(1) public void testHelloService() { assertDoesNotThrow(HelloSitewise::fetchAssetModels); - System.out.println(" Test 1 passed"); } @Test @@ -97,8 +97,6 @@ public void testCreateAssetModel() { assetModelId = response.assetModelId(); assertNotNull(assetModelId); }); - - System.out.println("Test 2 passed"); } @Test @@ -112,7 +110,6 @@ public void testCreateAsset() throws InterruptedException { assetId = response.assetId(); assertNotNull(assetId); }); - System.out.println("Test 3 passed"); } @Test @@ -121,12 +118,11 @@ public void testCreateAsset() throws InterruptedException { public void testGetPropIds() { assertDoesNotThrow(() -> { propertyIds = sitewiseActions.getPropertyIds(assetModelId).join(); - humPropId = propertyIds.get("Humidity"); - System.out.println("The Humidity property Id is "+ humPropId); + humPropId = propertyIds.get("Humidity"); + System.out.println("The Humidity property Id is " + humPropId); tempPropId = propertyIds.get("Temperature"); System.out.println("The Temperature property Id is " + tempPropId); }); - System.out.println("Test 4 passed"); } @Test @@ -136,7 +132,6 @@ public void testSendProps() { assertDoesNotThrow(() -> { sitewiseActions.sendDataToSiteWiseAsync(assetId, tempPropId, humPropId).join(); }); - System.out.println("Test 5 passed"); } @Test @@ -146,7 +141,6 @@ public void testGETHumValue() { assertDoesNotThrow(() -> { sitewiseActions.getAssetPropValueAsync(humPropId, assetId); }); - System.out.println("Test 6 passed"); } @Test @@ -157,7 +151,6 @@ public void testCreatePortal() { portalId = sitewiseActions.createPortalAsync(portalName, iamRole, contactEmail).join(); assertNotNull(portalId); }); - System.out.println("Test 7 passed"); } @Test @@ -168,7 +161,6 @@ public void testDescribePortal() { String portalUrl = sitewiseActions.describePortalAsync(portalId).join(); assertNotNull(portalUrl); }); - System.out.println("Test 8 passed"); } @Test @@ -179,7 +171,6 @@ public void testCreateGateway() { gatewayId = sitewiseActions.createGatewayAsync(gatewayName, myThing).join(); assertNotNull(gatewayId); }); - System.out.println("Test 9 passed"); } @Test @@ -189,7 +180,6 @@ public void testDescribeGateway() { assertDoesNotThrow(() -> { sitewiseActions.describeGatewayAsync(gatewayId).join(); }); - System.out.println("Test 10 passed"); } @Test @@ -199,8 +189,7 @@ public void testDeletePortal() throws InterruptedException { Thread.sleep(30000); assertDoesNotThrow(() -> { sitewiseActions.deletePortalAsync(portalId).join(); - }); - System.out.println("Test 11 passed"); + }); } @Test @@ -211,7 +200,6 @@ public void testDeleteAsset() throws InterruptedException { assertDoesNotThrow(() -> { sitewiseActions.deleteAssetAsync(assetId).join(); }); - System.out.println("Test 11 passed"); } @Test @@ -223,7 +211,6 @@ public void testDeleteAssetModel() throws InterruptedException { sitewiseActions.deleteAssetModelAsync(assetModelId).join(); }); CloudFormationHelper.destroyCloudFormationStack(ROLES_STACK); - System.out.println("Test 11 passed"); } From 556fb72a9048baa493de305ae917c05d014f9b55 Mon Sep 17 00:00:00 2001 From: scmacdon Date: Thu, 3 Oct 2024 18:48:11 -0400 Subject: [PATCH 41/41] updated sitewise tests --- .../example_code/iotsitewise/src/test/java/SitewiseTests.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java index 43668733106..c59e652473d 100644 --- a/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java +++ b/javav2/example_code/iotsitewise/src/test/java/SitewiseTests.java @@ -201,7 +201,6 @@ public void testDeleteAsset() throws InterruptedException { sitewiseActions.deleteAssetAsync(assetId).join(); }); } - @Test @Tag("IntegrationTest") @Order(12) @@ -213,7 +212,6 @@ public void testDeleteAssetModel() throws InterruptedException { CloudFormationHelper.destroyCloudFormationStack(ROLES_STACK); } - private static String getSecretValues() { SecretsManagerClient secretClient = SecretsManagerClient.builder() .region(Region.US_EAST_1)