AWS IoT ejemplos que utilizan SDK para .NET (v4) - AWS SDK para .NET (V4)

¡Se AWS SDK para .NET ha publicado la versión 4 (V4) del!

Para obtener información sobre los cambios más importantes y la migración de sus aplicaciones, consulte el tema sobre migración.

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

AWS IoT ejemplos que utilizan SDK para .NET (v4)

Los siguientes ejemplos de código muestran cómo realizar acciones e implementar escenarios comunes mediante el uso de AWS SDK para .NET (v4) con AWS IoT.

Los conceptos básicos son ejemplos de código que muestran cómo realizar las operaciones esenciales dentro de un servicio.

Las acciones son extractos de código de programas más grandes y deben ejecutarse en contexto. Mientras las acciones muestran cómo llamar a las distintas funciones de servicio, es posible ver las acciones en contexto en los escenarios relacionados.

En cada ejemplo se incluye un enlace al código de origen completo, con instrucciones de configuración y ejecución del código en el contexto.

Introducción

En los siguientes ejemplos de código se muestra cómo empezar a utilizar AWS IoT.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Hello AWS IoT example. /// </summary> public class HelloIoT { /// <summary> /// Main method to run the Hello IoT example. /// </summary> /// <param name="args">Command line arguments.</param> /// <returns>A Task object.</returns> public static async Task Main(string[] args) { var iotClient = new AmazonIoTClient(); try { Console.WriteLine("Hello AWS IoT! Let's list your IoT Things:"); Console.WriteLine(new string('-', 80)); // Use pages of 10. var request = new ListThingsRequest() { MaxResults = 10 }; var response = await iotClient.ListThingsAsync(request); // Since there is not a built-in paginator, use the NextMarker to paginate. bool hasMoreResults = true; var things = new List<ThingAttribute>(); while (hasMoreResults) { things.AddRange(response.Things); // If NextMarker is not null, there are more results. Get the next page of results. if (!String.IsNullOrEmpty(response.NextMarker)) { request.Marker = response.NextMarker; response = await iotClient.ListThingsAsync(request); } else hasMoreResults = false; } if (things is { Count: > 0 }) { Console.WriteLine($"Found {things.Count} IoT Things:"); foreach (var thing in things) { Console.WriteLine($"- Thing Name: {thing.ThingName}"); Console.WriteLine($" Thing ARN: {thing.ThingArn}"); Console.WriteLine($" Thing Type: {thing.ThingTypeName ?? "No type specified"}"); Console.WriteLine($" Version: {thing.Version}"); if (thing.Attributes?.Count > 0) { Console.WriteLine(" Attributes:"); foreach (var attr in thing.Attributes) { Console.WriteLine($" {attr.Key}: {attr.Value}"); } } Console.WriteLine(); } } else { Console.WriteLine("No IoT Things found in your account."); Console.WriteLine("You can create IoT Things using the IoT Basics scenario example."); } Console.WriteLine("Hello IoT completed successfully."); } catch (Amazon.IoT.Model.ThrottlingException ex) { Console.WriteLine($"Request throttled, please try again later: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"Couldn't list Things. Here's why: {ex.Message}"); } } }
  • Para obtener información sobre la API, consulte listThings en la Referencia de la API de AWS SDK para .NET .

Conceptos básicos

En el siguiente ejemplo de código, se muestra cómo:

  • Crea una AWS IoT cosa.

  • Generar un certificado de dispositivo.

  • Actualiza AWS IoT cualquier cosa con atributos.

  • Devolver un punto de conexión único.

  • Enumere sus AWS IoT certificados.

  • Actualiza y AWS IoT oculta.

  • Escribir la información de estado.

  • Crear una regla.

  • Mostrar las reglas.

  • Buscar objetos con el nombre de objeto.

  • Elimina cualquier AWS IoT cosa.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

Ejecute un escenario interactivo que demuestre AWS IoT las funciones.

/// <summary> /// Scenario class for AWS IoT basics. /// </summary> public class IoTBasics { public static bool IsInteractive = true; public static IoTWrapper? Wrapper = null; public static IAmazonCloudFormation? CloudFormationClient = null; public static ILogger<IoTBasics> logger = null!; private static IoTWrapper _iotWrapper = null!; private static IAmazonCloudFormation _amazonCloudFormation = null!; private static ILogger<IoTBasics> _logger = null!; private static string _stackName = "IoTBasicsStack"; private static string _stackResourcePath = "../../../../../../scenarios/basics/iot/iot_usecase/resources/cfn_template.yaml"; /// <summary> /// Main method for the IoT Basics scenario. /// </summary> /// <param name="args">Command line arguments.</param> /// <returns>A Task object.</returns> public static async Task Main(string[] args) { // Set up dependency injection for the Amazon service. using var host = Host.CreateDefaultBuilder(args) .ConfigureServices((_, services) => services.AddAWSService<IAmazonIoT>(new AWSOptions() { Region = RegionEndpoint.USEast1 }) .AddAWSService<IAmazonCloudFormation>() .AddTransient<IoTWrapper>() .AddLogging(builder => builder.AddConsole()) .AddSingleton<IAmazonIotData>(sp => { var iotService = sp.GetRequiredService<IAmazonIoT>(); var request = new DescribeEndpointRequest { EndpointType = "iot:Data-ATS" }; var response = iotService.DescribeEndpointAsync(request).Result; return new AmazonIotDataClient($"https://{response.EndpointAddress}/"); }) ) .Build(); logger = LoggerFactory.Create(builder => builder.AddConsole()) .CreateLogger<IoTBasics>(); Wrapper = host.Services.GetRequiredService<IoTWrapper>(); CloudFormationClient = host.Services.GetRequiredService<IAmazonCloudFormation>(); // Set the private fields for backwards compatibility _logger = logger; _iotWrapper = Wrapper; _amazonCloudFormation = CloudFormationClient; Console.WriteLine(new string('-', 80)); Console.WriteLine("Welcome to the AWS IoT example scenario."); Console.WriteLine("This example program demonstrates various interactions with the AWS Internet of Things (IoT) Core service."); Console.WriteLine(); if (IsInteractive) { Console.WriteLine("Press Enter to continue..."); Console.ReadLine(); } Console.WriteLine(new string('-', 80)); try { await RunScenarioAsync(); } catch (Exception ex) { _logger.LogError(ex, "There was a problem running the scenario."); Console.WriteLine($"\nAn error occurred: {ex.Message}"); } Console.WriteLine(new string('-', 80)); Console.WriteLine("The AWS IoT scenario has successfully completed."); Console.WriteLine(new string('-', 80)); } /// <summary> /// Run the IoT Basics scenario. /// </summary> /// <returns>A Task object.</returns> public static async Task RunScenarioAsync() { // Use static properties if available, otherwise use private fields var iotWrapper = Wrapper ?? _iotWrapper; var cloudFormationClient = CloudFormationClient ?? _amazonCloudFormation; var scenarioLogger = logger ?? _logger; await RunScenarioInternalAsync(iotWrapper, cloudFormationClient, scenarioLogger); } /// <summary> /// Internal method to run the IoT Basics scenario with injected dependencies. /// </summary> /// <param name="iotWrapper">The IoT wrapper instance.</param> /// <param name="cloudFormationClient">The CloudFormation client instance.</param> /// <param name="scenarioLogger">The logger instance.</param> /// <returns>A Task object.</returns> private static async Task RunScenarioInternalAsync(IoTWrapper iotWrapper, IAmazonCloudFormation cloudFormationClient, ILogger<IoTBasics> scenarioLogger) { string thingName = $"iot-thing-{Guid.NewGuid():N}"; string certificateArn = ""; string certificateId = ""; string ruleName = $"iotruledefault"; string snsTopicArn = ""; try { // Step 1: Create an AWS IoT Thing Console.WriteLine(new string('-', 80)); Console.WriteLine("1. Create an AWS IoT Thing."); Console.WriteLine("An AWS IoT Thing represents a virtual entity in the AWS IoT service that can be associated with a physical device."); Console.WriteLine(); if (IsInteractive) { Console.Write("Enter Thing name: "); var userInput = Console.ReadLine(); if (!string.IsNullOrEmpty(userInput)) thingName = userInput; } else { Console.WriteLine($"Using default Thing name: {thingName}"); } var thingArn = await iotWrapper.CreateThingAsync(thingName); Console.WriteLine($"{thingName} was successfully created. The ARN value is {thingArn}"); Console.WriteLine(new string('-', 80)); // Step 1.1: List AWS IoT Things Console.WriteLine(new string('-', 80)); Console.WriteLine("2. List AWS IoT Things."); Console.WriteLine("Now let's list the IoT Things to see the Thing we just created."); Console.WriteLine(); if (IsInteractive) { Console.WriteLine("Press Enter to continue..."); Console.ReadLine(); } var things = await iotWrapper.ListThingsAsync(); Console.WriteLine($"Found {things.Count} IoT Things:"); foreach (var thing in things.Take(10)) // Show first 10 things { Console.WriteLine($"Thing Name: {thing.ThingName}"); Console.WriteLine($"Thing ARN: {thing.ThingArn}"); if (thing.Attributes != null && thing.Attributes.Any()) { Console.WriteLine("Attributes:"); foreach (var attr in thing.Attributes) { Console.WriteLine($" {attr.Key}: {attr.Value}"); } } Console.WriteLine("--------------"); } Console.WriteLine(); Console.WriteLine(new string('-', 80)); // Step 2: Generate a Device Certificate Console.WriteLine(new string('-', 80)); Console.WriteLine("3. Generate a device certificate."); Console.WriteLine("A device certificate performs a role in securing the communication between devices (Things) and the AWS IoT platform."); Console.WriteLine(); var createCert = "y"; if (IsInteractive) { Console.Write($"Do you want to create a certificate for {thingName}? (y/n)"); createCert = Console.ReadLine(); } else { Console.WriteLine($"Creating certificate for {thingName}..."); } if (createCert?.ToLower() == "y") { var certificateResult = await iotWrapper.CreateKeysAndCertificateAsync(); if (certificateResult.HasValue) { var (certArn, certPem, certId) = certificateResult.Value; certificateArn = certArn; certificateId = certId; Console.WriteLine($"\nCertificate:"); // Show only first few lines of certificate for brevity var lines = certPem.Split('\n'); for (int i = 0; i < Math.Min(lines.Length, 5); i++) { Console.WriteLine(lines[i]); } if (lines.Length > 5) { Console.WriteLine("..."); } Console.WriteLine($"\nCertificate ARN:"); Console.WriteLine(certificateArn); // Step 3: Attach the Certificate to the AWS IoT Thing Console.WriteLine("Attach the certificate to the AWS IoT Thing."); var attachResult = await iotWrapper.AttachThingPrincipalAsync(thingName, certificateArn); if (attachResult) { Console.WriteLine("Certificate attached to Thing successfully."); } else { Console.WriteLine("Failed to attach certificate to Thing."); } Console.WriteLine("Thing Details:"); Console.WriteLine($"Thing Name: {thingName}"); Console.WriteLine($"Thing ARN: {thingArn}"); } else { Console.WriteLine("Failed to create certificate."); } } Console.WriteLine(new string('-', 80)); // Step 4: Update an AWS IoT Thing with Attributes Console.WriteLine(new string('-', 80)); Console.WriteLine("4. Update an AWS IoT Thing with Attributes."); Console.WriteLine("IoT Thing attributes, represented as key-value pairs, offer a pivotal advantage in facilitating efficient data"); Console.WriteLine("management and retrieval within the AWS IoT ecosystem."); Console.WriteLine(); if (IsInteractive) { Console.WriteLine("Press Enter to continue..."); Console.ReadLine(); } var attributes = new Dictionary<string, string> { { "Location", "Seattle" }, { "DeviceType", "Sensor" }, { "Firmware", "1.2.3" } }; await iotWrapper.UpdateThingAsync(thingName, attributes); Console.WriteLine("Thing attributes updated successfully."); Console.WriteLine(new string('-', 80)); // Step 5: Return a unique endpoint specific to the Amazon Web Services account Console.WriteLine(new string('-', 80)); Console.WriteLine("5. Return a unique endpoint specific to the Amazon Web Services account."); Console.WriteLine(); if (IsInteractive) { Console.WriteLine("Press Enter to continue..."); Console.ReadLine(); } var endpoint = await iotWrapper.DescribeEndpointAsync(); if (endpoint != null) { var subdomain = endpoint.Split('.')[0]; Console.WriteLine($"Extracted subdomain: {subdomain}"); Console.WriteLine($"Full Endpoint URL: https://{endpoint}"); } else { Console.WriteLine("Failed to retrieve endpoint."); } Console.WriteLine(new string('-', 80)); // Step 6: List your AWS IoT certificates Console.WriteLine(new string('-', 80)); Console.WriteLine("6. List your AWS IoT certificates"); if (IsInteractive) { Console.WriteLine("Press Enter to continue..."); Console.ReadLine(); } var certificates = await iotWrapper.ListCertificatesAsync(); foreach (var cert in certificates.Take(5)) // Show first 5 certificates { Console.WriteLine($"Cert id: {cert.CertificateId}"); Console.WriteLine($"Cert Arn: {cert.CertificateArn}"); } Console.WriteLine(); Console.WriteLine(new string('-', 80)); // Step 7: Create an IoT shadow Console.WriteLine(new string('-', 80)); Console.WriteLine("7. Update an IoT shadow that refers to a digital representation or virtual twin of a physical IoT device"); Console.WriteLine(); if (IsInteractive) { Console.WriteLine("Press Enter to continue..."); Console.ReadLine(); } var shadowPayload = JsonSerializer.Serialize(new { state = new { desired = new { temperature = 25, humidity = 50 } } }); await iotWrapper.UpdateThingShadowAsync(thingName, shadowPayload); Console.WriteLine("Thing Shadow updated successfully."); Console.WriteLine(new string('-', 80)); // Step 8: Write out the state information, in JSON format Console.WriteLine(new string('-', 80)); Console.WriteLine("8. Write out the state information, in JSON format."); if (IsInteractive) { Console.WriteLine("Press Enter to continue..."); Console.ReadLine(); } var shadowData = await iotWrapper.GetThingShadowAsync(thingName); Console.WriteLine($"Received Shadow Data: {shadowData}"); Console.WriteLine(new string('-', 80)); // Step 9: Set up resources (SNS topic and IAM role) and create a rule Console.WriteLine(new string('-', 80)); Console.WriteLine("9. Set up resources and create a rule"); Console.WriteLine(); // Deploy CloudFormation stack to create SNS topic and IAM role Console.WriteLine("Deploying CloudFormation stack to create SNS topic and IAM role..."); var deployStack = !IsInteractive || GetYesNoResponse("Would you like to deploy the CloudFormation stack? (y/n) "); if (deployStack) { if (IsInteractive) { Console.Write( $"Enter stack resource file path (or press Enter for default '{_stackResourcePath}'): "); var userResourcePath = Console.ReadLine(); if (!string.IsNullOrEmpty(userResourcePath)) _stackResourcePath = userResourcePath; } _stackName = PromptUserForStackName(); var deploySuccess = await DeployCloudFormationStack(_stackName, cloudFormationClient, scenarioLogger); if (deploySuccess) { // Get stack outputs var stackOutputs = await GetStackOutputs(_stackName, cloudFormationClient, scenarioLogger); if (stackOutputs != null) { snsTopicArn = stackOutputs["SNSTopicArn"]; string roleArn = stackOutputs["RoleArn"]; Console.WriteLine($"Successfully deployed stack. SNS topic: {snsTopicArn}"); Console.WriteLine($"Successfully deployed stack. IAM role: {roleArn}"); if (IsInteractive) { Console.Write($"Enter Rule name (press Enter for default '{ruleName}'): "); var userRuleName = Console.ReadLine(); if (!string.IsNullOrEmpty(userRuleName)) ruleName = userRuleName; } else { Console.WriteLine($"Using default rule name: {ruleName}"); } // Now create the IoT rule with the CloudFormation outputs var ruleResult = await iotWrapper.CreateTopicRuleAsync(ruleName, snsTopicArn, roleArn); if (ruleResult) { Console.WriteLine("IoT Rule created successfully."); } else { Console.WriteLine("Failed to create IoT rule."); } } else { Console.WriteLine("Failed to get stack outputs. Skipping rule creation."); } } else { Console.WriteLine("Failed to deploy CloudFormation stack. Skipping rule creation."); } } else { Console.WriteLine("Skipping CloudFormation stack deployment and rule creation."); } Console.WriteLine(new string('-', 80)); // Step 10: List your rules Console.WriteLine(new string('-', 80)); Console.WriteLine("10. List your rules."); if (IsInteractive) { Console.WriteLine("Press Enter to continue..."); Console.ReadLine(); } var rules = await iotWrapper.ListTopicRulesAsync(); Console.WriteLine("List of IoT Rules:"); foreach (var rule in rules.Take(5)) // Show first 5 rules { Console.WriteLine($"Rule Name: {rule.RuleName}"); Console.WriteLine($"Rule ARN: {rule.RuleArn}"); Console.WriteLine("--------------"); } Console.WriteLine(); Console.WriteLine(new string('-', 80)); // Step 11: Search things using the Thing name Console.WriteLine(new string('-', 80)); Console.WriteLine("11. Search things using the Thing name."); if (IsInteractive) { Console.WriteLine("Press Enter to continue..."); Console.ReadLine(); } var searchResults = await iotWrapper.SearchIndexAsync($"thingName:{thingName}"); if (searchResults.Any()) { Console.WriteLine($"Thing id found using search is {searchResults.First().ThingId}"); } else { Console.WriteLine($"No search results found for Thing: {thingName}"); } Console.WriteLine(new string('-', 80)); // Step 12: Cleanup - Detach and delete certificate if (!string.IsNullOrEmpty(certificateArn)) { Console.WriteLine(new string('-', 80)); var deleteCert = "y"; if (IsInteractive) { Console.Write($"Do you want to detach and delete the certificate for {thingName}? (y/n)"); deleteCert = Console.ReadLine(); } else { Console.WriteLine($"Detaching and deleting certificate for {thingName}..."); } if (deleteCert?.ToLower() == "y") { Console.WriteLine("12. You selected to detach and delete the certificate."); if (IsInteractive) { Console.WriteLine("Press Enter to continue..."); Console.ReadLine(); } await iotWrapper.DetachThingPrincipalAsync(thingName, certificateArn); Console.WriteLine($"{certificateArn} was successfully removed from {thingName}"); await iotWrapper.DeleteCertificateAsync(certificateId); Console.WriteLine($"{certificateArn} was successfully deleted."); } Console.WriteLine(new string('-', 80)); } // Step 13: Delete the AWS IoT Thing Console.WriteLine(new string('-', 80)); Console.WriteLine("13. Delete the AWS IoT Thing."); var deleteThing = "y"; if (IsInteractive) { Console.Write($"Do you want to delete the IoT Thing? (y/n)"); deleteThing = Console.ReadLine(); } else { Console.WriteLine($"Deleting IoT Thing {thingName}..."); } if (deleteThing?.ToLower() == "y") { await iotWrapper.DeleteThingAsync(thingName); Console.WriteLine($"Deleted Thing {thingName}"); } Console.WriteLine(new string('-', 80)); // Step 14: Clean up CloudFormation stack if (!string.IsNullOrEmpty(snsTopicArn)) { Console.WriteLine(new string('-', 80)); Console.WriteLine("14. Clean up CloudFormation stack."); Console.WriteLine("Deleting the CloudFormation stack and all resources..."); var cleanup = !IsInteractive || GetYesNoResponse("Do you want to delete the CloudFormation stack and all resources? (y/n) "); if (cleanup) { var ruleCleanupSuccess = await iotWrapper.DeleteTopicRuleAsync(ruleName); var stackCleanupSuccess = await DeleteCloudFormationStack(_stackName, cloudFormationClient, scenarioLogger); if (ruleCleanupSuccess && stackCleanupSuccess) { Console.WriteLine("Successfully cleaned up CloudFormation stack and all resources."); } else { Console.WriteLine("Some cleanup operations failed. Check the logs for details."); } } else { Console.WriteLine($"Resources will remain. Stack name: {_stackName}"); } Console.WriteLine(new string('-', 80)); } } catch (Exception ex) { scenarioLogger.LogError(ex, "Error occurred during scenario execution."); // Cleanup on error if (!string.IsNullOrEmpty(certificateArn) && !string.IsNullOrEmpty(thingName)) { try { await iotWrapper.DetachThingPrincipalAsync(thingName, certificateArn); await iotWrapper.DeleteCertificateAsync(certificateId); } catch (Exception cleanupEx) { scenarioLogger.LogError(cleanupEx, "Error during cleanup."); } } if (!string.IsNullOrEmpty(thingName)) { try { await iotWrapper.DeleteThingAsync(thingName); } catch (Exception cleanupEx) { scenarioLogger.LogError(cleanupEx, "Error during Thing cleanup."); } } // Clean up CloudFormation stack on error if (!string.IsNullOrEmpty(snsTopicArn)) { try { await _iotWrapper.DeleteTopicRuleAsync(ruleName); await DeleteCloudFormationStack(_stackName, cloudFormationClient, scenarioLogger); } catch (Exception cleanupEx) { scenarioLogger.LogError(cleanupEx, "Error during CloudFormation stack cleanup."); } } throw; } } /// <summary> /// Deploys the CloudFormation stack with the necessary resources. /// </summary> /// <param name="stackName">The name of the CloudFormation stack.</param> /// <param name="cloudFormationClient">The CloudFormation client.</param> /// <param name="scenarioLogger">The logger.</param> /// <returns>True if the stack was deployed successfully.</returns> private static async Task<bool> DeployCloudFormationStack(string stackName, IAmazonCloudFormation cloudFormationClient, ILogger<IoTBasics> scenarioLogger) { Console.WriteLine($"\nDeploying CloudFormation stack: {stackName}"); try { var request = new CreateStackRequest { StackName = stackName, TemplateBody = await File.ReadAllTextAsync(_stackResourcePath), Capabilities = new List<string> { Capability.CAPABILITY_NAMED_IAM } }; var response = await cloudFormationClient.CreateStackAsync(request); if (response.HttpStatusCode == System.Net.HttpStatusCode.OK) { Console.WriteLine($"CloudFormation stack creation started: {stackName}"); bool stackCreated = await WaitForStackCompletion(response.StackId, cloudFormationClient, scenarioLogger); if (stackCreated) { Console.WriteLine("CloudFormation stack created successfully."); return true; } else { scenarioLogger.LogError($"CloudFormation stack creation failed: {stackName}"); return false; } } else { scenarioLogger.LogError($"Failed to create CloudFormation stack: {stackName}"); return false; } } catch (AlreadyExistsException) { scenarioLogger.LogWarning($"CloudFormation stack '{stackName}' already exists. Please provide a unique name."); var newStackName = PromptUserForStackName(); return await DeployCloudFormationStack(newStackName, cloudFormationClient, scenarioLogger); } catch (Exception ex) { scenarioLogger.LogError(ex, $"An error occurred while deploying the CloudFormation stack: {stackName}"); return false; } } /// <summary> /// Waits for the CloudFormation stack to be in the CREATE_COMPLETE state. /// </summary> /// <param name="stackId">The ID of the CloudFormation stack.</param> /// <param name="cloudFormationClient">The CloudFormation client.</param> /// <param name="scenarioLogger">The logger.</param> /// <returns>True if the stack was created successfully.</returns> private static async Task<bool> WaitForStackCompletion(string stackId, IAmazonCloudFormation cloudFormationClient, ILogger<IoTBasics> scenarioLogger) { int retryCount = 0; const int maxRetries = 30; const int retryDelay = 10000; while (retryCount < maxRetries) { var describeStacksRequest = new DescribeStacksRequest { StackName = stackId }; var describeStacksResponse = await cloudFormationClient.DescribeStacksAsync(describeStacksRequest); if (describeStacksResponse.Stacks.Count > 0) { if (describeStacksResponse.Stacks[0].StackStatus == StackStatus.CREATE_COMPLETE) { return true; } if (describeStacksResponse.Stacks[0].StackStatus == StackStatus.CREATE_FAILED || describeStacksResponse.Stacks[0].StackStatus == StackStatus.ROLLBACK_COMPLETE) { return false; } } Console.WriteLine("Waiting for CloudFormation stack creation to complete..."); await Task.Delay(retryDelay); retryCount++; } scenarioLogger.LogError("Timed out waiting for CloudFormation stack creation to complete."); return false; } /// <summary> /// Gets the outputs from the CloudFormation stack. /// </summary> /// <param name="stackName">The name of the CloudFormation stack.</param> /// <param name="cloudFormationClient">The CloudFormation client.</param> /// <param name="scenarioLogger">The logger.</param> /// <returns>A dictionary of stack outputs.</returns> private static async Task<Dictionary<string, string>?> GetStackOutputs(string stackName, IAmazonCloudFormation cloudFormationClient, ILogger<IoTBasics> scenarioLogger) { try { var describeStacksRequest = new DescribeStacksRequest { StackName = stackName }; var response = await cloudFormationClient.DescribeStacksAsync(describeStacksRequest); if (response.Stacks.Count > 0) { var outputs = new Dictionary<string, string>(); foreach (var output in response.Stacks[0].Outputs) { outputs[output.OutputKey] = output.OutputValue; } return outputs; } return null; } catch (Exception ex) { scenarioLogger.LogError(ex, $"Failed to get stack outputs for {stackName}"); return null; } } /// <summary> /// Deletes the CloudFormation stack and waits for confirmation. /// </summary> /// <param name="stackName">The name of the CloudFormation stack.</param> /// <param name="cloudFormationClient">The CloudFormation client.</param> /// <param name="scenarioLogger">The logger.</param> /// <returns>True if the stack was deleted successfully.</returns> private static async Task<bool> DeleteCloudFormationStack(string stackName, IAmazonCloudFormation cloudFormationClient, ILogger<IoTBasics> scenarioLogger) { try { var request = new DeleteStackRequest { StackName = stackName }; await cloudFormationClient.DeleteStackAsync(request); Console.WriteLine($"CloudFormation stack '{stackName}' is being deleted. This may take a few minutes."); bool stackDeleted = await WaitForStackDeletion(stackName, cloudFormationClient, scenarioLogger); if (stackDeleted) { Console.WriteLine($"CloudFormation stack '{stackName}' has been deleted."); return true; } else { scenarioLogger.LogError($"Failed to delete CloudFormation stack '{stackName}'."); return false; } } catch (Exception ex) { scenarioLogger.LogError(ex, $"An error occurred while deleting the CloudFormation stack: {stackName}"); return false; } } /// <summary> /// Waits for the stack to be deleted. /// </summary> /// <param name="stackName">The name of the CloudFormation stack.</param> /// <param name="cloudFormationClient">The CloudFormation client.</param> /// <param name="scenarioLogger">The logger.</param> /// <returns>True if the stack was deleted successfully.</returns> private static async Task<bool> WaitForStackDeletion(string stackName, IAmazonCloudFormation cloudFormationClient, ILogger<IoTBasics> scenarioLogger) { int retryCount = 0; const int maxRetries = 30; const int retryDelay = 10000; while (retryCount < maxRetries) { var describeStacksRequest = new DescribeStacksRequest { StackName = stackName }; try { var describeStacksResponse = await cloudFormationClient.DescribeStacksAsync(describeStacksRequest); if (describeStacksResponse.Stacks.Count == 0 || describeStacksResponse.Stacks[0].StackStatus == StackStatus.DELETE_COMPLETE) { return true; } } catch (AmazonCloudFormationException ex) when (ex.ErrorCode == "ValidationError") { return true; } Console.WriteLine($"Waiting for CloudFormation stack '{stackName}' to be deleted..."); await Task.Delay(retryDelay); retryCount++; } scenarioLogger.LogError($"Timed out waiting for CloudFormation stack '{stackName}' to be deleted."); return false; } /// <summary> /// Helper method to get a yes or no response from the user. /// </summary> private static bool GetYesNoResponse(string question) { Console.WriteLine(question); var ynResponse = Console.ReadLine(); var response = ynResponse != null && ynResponse.Equals("y", StringComparison.InvariantCultureIgnoreCase); return response; } /// <summary> /// Prompts the user for a stack name. /// </summary> private static string PromptUserForStackName() { if (IsInteractive) { Console.Write($"Enter a name for the CloudFormation stack (press Enter for default '{_stackName}'): "); string? input = Console.ReadLine(); if (!string.IsNullOrWhiteSpace(input)) { var regex = new System.Text.RegularExpressions.Regex("[a-zA-Z][-a-zA-Z0-9]*"); if (!regex.IsMatch(input)) { Console.WriteLine($"Invalid stack name. Using default: {_stackName}"); return _stackName; } return input; } } return _stackName; } }

Una clase contenedora para los métodos AWS IoT del SDK.

/// <summary> /// Wrapper methods to use Amazon IoT Core with .NET. /// </summary> public class IoTWrapper { private readonly IAmazonIoT _amazonIoT; private readonly IAmazonIotData _amazonIotData; private readonly ILogger<IoTWrapper> _logger; /// <summary> /// Constructor for the IoT wrapper. /// </summary> /// <param name="amazonIoT">The injected IoT client.</param> /// <param name="amazonIotData">The injected IoT Data client.</param> /// <param name="logger">The injected logger.</param> public IoTWrapper(IAmazonIoT amazonIoT, IAmazonIotData amazonIotData, ILogger<IoTWrapper> logger) { _amazonIoT = amazonIoT; _amazonIotData = amazonIotData; _logger = logger; } /// <summary> /// Creates an AWS IoT Thing. /// </summary> /// <param name="thingName">The name of the Thing to create.</param> /// <returns>The ARN of the Thing created, or null if creation failed.</returns> public async Task<string?> CreateThingAsync(string thingName) { try { var request = new CreateThingRequest { ThingName = thingName }; var response = await _amazonIoT.CreateThingAsync(request); _logger.LogInformation($"Created Thing {thingName} with ARN {response.ThingArn}"); return response.ThingArn; } catch (Amazon.IoT.Model.ResourceAlreadyExistsException ex) { _logger.LogWarning($"Thing {thingName} already exists: {ex.Message}"); return null; } catch (Exception ex) { _logger.LogError($"Couldn't create Thing {thingName}. Here's why: {ex.Message}"); return null; } } /// <summary> /// Creates a device certificate for AWS IoT. /// </summary> /// <returns>The certificate details including ARN and certificate PEM, or null if creation failed.</returns> public async Task<(string CertificateArn, string CertificatePem, string CertificateId)?> CreateKeysAndCertificateAsync() { try { var request = new CreateKeysAndCertificateRequest { SetAsActive = true }; var response = await _amazonIoT.CreateKeysAndCertificateAsync(request); _logger.LogInformation($"Created certificate with ARN {response.CertificateArn}"); return (response.CertificateArn, response.CertificatePem, response.CertificateId); } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return null; } catch (Exception ex) { _logger.LogError($"Couldn't create certificate. Here's why: {ex.Message}"); return null; } } /// <summary> /// Attaches a certificate to an IoT Thing. /// </summary> /// <param name="thingName">The name of the Thing.</param> /// <param name="certificateArn">The ARN of the certificate to attach.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> AttachThingPrincipalAsync(string thingName, string certificateArn) { try { var request = new AttachThingPrincipalRequest { ThingName = thingName, Principal = certificateArn }; await _amazonIoT.AttachThingPrincipalAsync(request); _logger.LogInformation($"Attached certificate {certificateArn} to Thing {thingName}"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot attach certificate - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't attach certificate to Thing. Here's why: {ex.Message}"); return false; } } /// <summary> /// Updates an IoT Thing with attributes. /// </summary> /// <param name="thingName">The name of the Thing to update.</param> /// <param name="attributes">Dictionary of attributes to add.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> UpdateThingAsync(string thingName, Dictionary<string, string> attributes) { try { var request = new UpdateThingRequest { ThingName = thingName, AttributePayload = new AttributePayload { Attributes = attributes, Merge = true } }; await _amazonIoT.UpdateThingAsync(request); _logger.LogInformation($"Updated Thing {thingName} with attributes"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot update Thing - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't update Thing attributes. Here's why: {ex.Message}"); return false; } } /// <summary> /// Gets the AWS IoT endpoint URL. /// </summary> /// <returns>The endpoint URL, or null if retrieval failed.</returns> public async Task<string?> DescribeEndpointAsync() { try { var request = new DescribeEndpointRequest { EndpointType = "iot:Data-ATS" }; var response = await _amazonIoT.DescribeEndpointAsync(request); _logger.LogInformation($"Retrieved endpoint: {response.EndpointAddress}"); return response.EndpointAddress; } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return null; } catch (Exception ex) { _logger.LogError($"Couldn't describe endpoint. Here's why: {ex.Message}"); return null; } } /// <summary> /// Lists all certificates associated with the account. /// </summary> /// <returns>List of certificate information, or empty list if listing failed.</returns> public async Task<List<Certificate>> ListCertificatesAsync() { try { var request = new ListCertificatesRequest(); var response = await _amazonIoT.ListCertificatesAsync(request); _logger.LogInformation($"Retrieved {response.Certificates.Count} certificates"); return response.Certificates; } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return new List<Certificate>(); } catch (Exception ex) { _logger.LogError($"Couldn't list certificates. Here's why: {ex.Message}"); return new List<Certificate>(); } } /// <summary> /// Updates the Thing's shadow with new state information. /// </summary> /// <param name="thingName">The name of the Thing.</param> /// <param name="shadowPayload">The shadow payload in JSON format.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> UpdateThingShadowAsync(string thingName, string shadowPayload) { try { var request = new UpdateThingShadowRequest { ThingName = thingName, Payload = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(shadowPayload)) }; await _amazonIotData.UpdateThingShadowAsync(request); _logger.LogInformation($"Updated shadow for Thing {thingName}"); return true; } catch (Amazon.IotData.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot update Thing shadow - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't update Thing shadow. Here's why: {ex.Message}"); return false; } } /// <summary> /// Gets the Thing's shadow information. /// </summary> /// <param name="thingName">The name of the Thing.</param> /// <returns>The shadow data as a string, or null if retrieval failed.</returns> public async Task<string?> GetThingShadowAsync(string thingName) { try { var request = new GetThingShadowRequest { ThingName = thingName }; var response = await _amazonIotData.GetThingShadowAsync(request); using var reader = new StreamReader(response.Payload); var shadowData = await reader.ReadToEndAsync(); _logger.LogInformation($"Retrieved shadow for Thing {thingName}"); return shadowData; } catch (Amazon.IotData.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot get Thing shadow - resource not found: {ex.Message}"); return null; } catch (Exception ex) { _logger.LogError($"Couldn't get Thing shadow. Here's why: {ex.Message}"); return null; } } /// <summary> /// Creates an IoT topic rule. /// </summary> /// <param name="ruleName">The name of the rule.</param> /// <param name="snsTopicArn">The ARN of the SNS topic for the action.</param> /// <param name="roleArn">The ARN of the IAM role.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> CreateTopicRuleAsync(string ruleName, string snsTopicArn, string roleArn) { try { var request = new CreateTopicRuleRequest { RuleName = ruleName, TopicRulePayload = new TopicRulePayload { Sql = "SELECT * FROM 'topic/subtopic'", Description = $"Rule created by .NET example: {ruleName}", Actions = new List<Amazon.IoT.Model.Action> { new Amazon.IoT.Model.Action { Sns = new SnsAction { TargetArn = snsTopicArn, RoleArn = roleArn } } }, RuleDisabled = false } }; await _amazonIoT.CreateTopicRuleAsync(request); _logger.LogInformation($"Created IoT rule {ruleName}"); return true; } catch (Amazon.IoT.Model.ResourceAlreadyExistsException ex) { _logger.LogWarning($"Rule {ruleName} already exists: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't create topic rule. Here's why: {ex.Message}"); return false; } } /// <summary> /// Deletes an IoT topic rule. /// </summary> /// <param name="ruleName">The name of the rule.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> DeleteTopicRuleAsync(string ruleName) { try { var request = new DeleteTopicRuleRequest { RuleName = ruleName, }; await _amazonIoT.DeleteTopicRuleAsync(request); _logger.LogInformation($"Deleted IoT rule {ruleName}"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogWarning($"Rule {ruleName} not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't delete topic rule. Here's why: {ex.Message}"); return false; } } /// <summary> /// Lists all IoT topic rules. /// </summary> /// <returns>List of topic rules, or empty list if listing failed.</returns> public async Task<List<TopicRuleListItem>> ListTopicRulesAsync() { try { var request = new ListTopicRulesRequest(); var response = await _amazonIoT.ListTopicRulesAsync(request); _logger.LogInformation($"Retrieved {response.Rules.Count} IoT rules"); return response.Rules; } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return new List<TopicRuleListItem>(); } catch (Exception ex) { _logger.LogError($"Couldn't list topic rules. Here's why: {ex.Message}"); return new List<TopicRuleListItem>(); } } /// <summary> /// Searches for IoT Things using the search index. /// </summary> /// <param name="queryString">The search query string.</param> /// <returns>List of Things that match the search criteria, or empty list if search failed.</returns> public async Task<List<ThingDocument>> SearchIndexAsync(string queryString) { try { // First, try to perform the search var request = new SearchIndexRequest { QueryString = queryString }; var response = await _amazonIoT.SearchIndexAsync(request); _logger.LogInformation($"Search found {response.Things.Count} Things"); return response.Things; } catch (Amazon.IoT.Model.IndexNotReadyException ex) { _logger.LogWarning($"Search index not ready, setting up indexing configuration: {ex.Message}"); return await SetupIndexAndRetrySearchAsync(queryString); } catch (Amazon.IoT.Model.ResourceNotFoundException ex) when (ex.Message.Contains("index") || ex.Message.Contains("Index")) { _logger.LogWarning($"Search index not configured, setting up indexing configuration: {ex.Message}"); return await SetupIndexAndRetrySearchAsync(queryString); } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return new List<ThingDocument>(); } catch (Exception ex) { _logger.LogError($"Couldn't search index. Here's why: {ex.Message}"); return new List<ThingDocument>(); } } /// <summary> /// Sets up the indexing configuration and retries the search after waiting for the index to be ready. /// </summary> /// <param name="queryString">The search query string.</param> /// <returns>List of Things that match the search criteria, or empty list if setup/search failed.</returns> private async Task<List<ThingDocument>> SetupIndexAndRetrySearchAsync(string queryString) { try { // Update indexing configuration to REGISTRY mode _logger.LogInformation("Setting up IoT search indexing configuration..."); await _amazonIoT.UpdateIndexingConfigurationAsync( new UpdateIndexingConfigurationRequest() { ThingIndexingConfiguration = new ThingIndexingConfiguration() { ThingIndexingMode = ThingIndexingMode.REGISTRY } }); _logger.LogInformation("Indexing configuration updated. Waiting for index to be ready..."); // Wait for the index to be set up - this can take some time const int maxRetries = 10; const int retryDelaySeconds = 10; for (int attempt = 1; attempt <= maxRetries; attempt++) { try { _logger.LogInformation($"Waiting for index to be ready (attempt {attempt}/{maxRetries})..."); await Task.Delay(TimeSpan.FromSeconds(retryDelaySeconds)); // Try to get the current indexing configuration to see if it's ready var configResponse = await _amazonIoT.GetIndexingConfigurationAsync(new GetIndexingConfigurationRequest()); if (configResponse.ThingIndexingConfiguration?.ThingIndexingMode == ThingIndexingMode.REGISTRY) { // Try the search again var request = new SearchIndexRequest { QueryString = queryString }; var response = await _amazonIoT.SearchIndexAsync(request); _logger.LogInformation($"Search found {response.Things.Count} Things after index setup"); return response.Things; } } catch (Amazon.IoT.Model.IndexNotReadyException) { // Index still not ready, continue waiting _logger.LogInformation("Index still not ready, continuing to wait..."); continue; } catch (Amazon.IoT.Model.InvalidRequestException ex) when (ex.Message.Contains("index") || ex.Message.Contains("Index")) { // Index still not ready, continue waiting _logger.LogInformation("Index still not ready, continuing to wait..."); continue; } } _logger.LogWarning("Timeout waiting for search index to be ready after configuration update"); return new List<ThingDocument>(); } catch (Exception ex) { _logger.LogError($"Couldn't set up search index configuration. Here's why: {ex.Message}"); return new List<ThingDocument>(); } } /// <summary> /// Detaches a certificate from an IoT Thing. /// </summary> /// <param name="thingName">The name of the Thing.</param> /// <param name="certificateArn">The ARN of the certificate to detach.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> DetachThingPrincipalAsync(string thingName, string certificateArn) { try { var request = new DetachThingPrincipalRequest { ThingName = thingName, Principal = certificateArn }; await _amazonIoT.DetachThingPrincipalAsync(request); _logger.LogInformation($"Detached certificate {certificateArn} from Thing {thingName}"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot detach certificate - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't detach certificate from Thing. Here's why: {ex.Message}"); return false; } } /// <summary> /// Deletes an IoT certificate. /// </summary> /// <param name="certificateId">The ID of the certificate to delete.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> DeleteCertificateAsync(string certificateId) { try { // First, update the certificate to inactive state var updateRequest = new UpdateCertificateRequest { CertificateId = certificateId, NewStatus = CertificateStatus.INACTIVE }; await _amazonIoT.UpdateCertificateAsync(updateRequest); // Then delete the certificate var deleteRequest = new DeleteCertificateRequest { CertificateId = certificateId }; await _amazonIoT.DeleteCertificateAsync(deleteRequest); _logger.LogInformation($"Deleted certificate {certificateId}"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot delete certificate - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't delete certificate. Here's why: {ex.Message}"); return false; } } /// <summary> /// Deletes an IoT Thing. /// </summary> /// <param name="thingName">The name of the Thing to delete.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> DeleteThingAsync(string thingName) { try { var request = new DeleteThingRequest { ThingName = thingName }; await _amazonIoT.DeleteThingAsync(request); _logger.LogInformation($"Deleted Thing {thingName}"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot delete Thing - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't delete Thing. Here's why: {ex.Message}"); return false; } } /// <summary> /// Lists IoT Things with pagination support. /// </summary> /// <returns>List of Things, or empty list if listing failed.</returns> public async Task<List<ThingAttribute>> ListThingsAsync() { try { // Use pages of 10. var request = new ListThingsRequest() { MaxResults = 10 }; var response = await _amazonIoT.ListThingsAsync(request); // Since there is not a built-in paginator, use the NextMarker to paginate. bool hasMoreResults = true; var things = new List<ThingAttribute>(); while (hasMoreResults) { things.AddRange(response.Things); // If NextMarker is not null, there are more results. Get the next page of results. if (!String.IsNullOrEmpty(response.NextMarker)) { request.Marker = response.NextMarker; response = await _amazonIoT.ListThingsAsync(request); } else hasMoreResults = false; } _logger.LogInformation($"Retrieved {things.Count} Things"); return things; } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return new List<ThingAttribute>(); } catch (Exception ex) { _logger.LogError($"Couldn't list Things. Here's why: {ex.Message}"); return new List<ThingAttribute>(); } } }

Acciones

En el siguiente ejemplo de código, se muestra cómo utilizar AttachThingPrincipal.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Attaches a certificate to an IoT Thing. /// </summary> /// <param name="thingName">The name of the Thing.</param> /// <param name="certificateArn">The ARN of the certificate to attach.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> AttachThingPrincipalAsync(string thingName, string certificateArn) { try { var request = new AttachThingPrincipalRequest { ThingName = thingName, Principal = certificateArn }; await _amazonIoT.AttachThingPrincipalAsync(request); _logger.LogInformation($"Attached certificate {certificateArn} to Thing {thingName}"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot attach certificate - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't attach certificate to Thing. Here's why: {ex.Message}"); return false; } }
  • Para obtener más información sobre la API, consulta AttachThingPrincipalla Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar CreateKeysAndCertificate.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Creates a device certificate for AWS IoT. /// </summary> /// <returns>The certificate details including ARN and certificate PEM, or null if creation failed.</returns> public async Task<(string CertificateArn, string CertificatePem, string CertificateId)?> CreateKeysAndCertificateAsync() { try { var request = new CreateKeysAndCertificateRequest { SetAsActive = true }; var response = await _amazonIoT.CreateKeysAndCertificateAsync(request); _logger.LogInformation($"Created certificate with ARN {response.CertificateArn}"); return (response.CertificateArn, response.CertificatePem, response.CertificateId); } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return null; } catch (Exception ex) { _logger.LogError($"Couldn't create certificate. Here's why: {ex.Message}"); return null; } }
  • Para obtener más información sobre la API, consulta CreateKeysAndCertificatela Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar CreateThing.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Creates an AWS IoT Thing. /// </summary> /// <param name="thingName">The name of the Thing to create.</param> /// <returns>The ARN of the Thing created, or null if creation failed.</returns> public async Task<string?> CreateThingAsync(string thingName) { try { var request = new CreateThingRequest { ThingName = thingName }; var response = await _amazonIoT.CreateThingAsync(request); _logger.LogInformation($"Created Thing {thingName} with ARN {response.ThingArn}"); return response.ThingArn; } catch (Amazon.IoT.Model.ResourceAlreadyExistsException ex) { _logger.LogWarning($"Thing {thingName} already exists: {ex.Message}"); return null; } catch (Exception ex) { _logger.LogError($"Couldn't create Thing {thingName}. Here's why: {ex.Message}"); return null; } }
  • Para obtener más información sobre la API, consulta CreateThingla Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar CreateTopicRule.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Creates an IoT topic rule. /// </summary> /// <param name="ruleName">The name of the rule.</param> /// <param name="snsTopicArn">The ARN of the SNS topic for the action.</param> /// <param name="roleArn">The ARN of the IAM role.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> CreateTopicRuleAsync(string ruleName, string snsTopicArn, string roleArn) { try { var request = new CreateTopicRuleRequest { RuleName = ruleName, TopicRulePayload = new TopicRulePayload { Sql = "SELECT * FROM 'topic/subtopic'", Description = $"Rule created by .NET example: {ruleName}", Actions = new List<Amazon.IoT.Model.Action> { new Amazon.IoT.Model.Action { Sns = new SnsAction { TargetArn = snsTopicArn, RoleArn = roleArn } } }, RuleDisabled = false } }; await _amazonIoT.CreateTopicRuleAsync(request); _logger.LogInformation($"Created IoT rule {ruleName}"); return true; } catch (Amazon.IoT.Model.ResourceAlreadyExistsException ex) { _logger.LogWarning($"Rule {ruleName} already exists: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't create topic rule. Here's why: {ex.Message}"); return false; } }
  • Para obtener más información sobre la API, consulta CreateTopicRulela Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar DeleteCertificate.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Deletes an IoT certificate. /// </summary> /// <param name="certificateId">The ID of the certificate to delete.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> DeleteCertificateAsync(string certificateId) { try { // First, update the certificate to inactive state var updateRequest = new UpdateCertificateRequest { CertificateId = certificateId, NewStatus = CertificateStatus.INACTIVE }; await _amazonIoT.UpdateCertificateAsync(updateRequest); // Then delete the certificate var deleteRequest = new DeleteCertificateRequest { CertificateId = certificateId }; await _amazonIoT.DeleteCertificateAsync(deleteRequest); _logger.LogInformation($"Deleted certificate {certificateId}"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot delete certificate - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't delete certificate. Here's why: {ex.Message}"); return false; } }
  • Para obtener más información sobre la API, consulta DeleteCertificatela Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar DeleteThing.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Deletes an IoT Thing. /// </summary> /// <param name="thingName">The name of the Thing to delete.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> DeleteThingAsync(string thingName) { try { var request = new DeleteThingRequest { ThingName = thingName }; await _amazonIoT.DeleteThingAsync(request); _logger.LogInformation($"Deleted Thing {thingName}"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot delete Thing - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't delete Thing. Here's why: {ex.Message}"); return false; } }
  • Para obtener más información sobre la API, consulta DeleteThingla Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar DescribeEndpoint.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Gets the AWS IoT endpoint URL. /// </summary> /// <returns>The endpoint URL, or null if retrieval failed.</returns> public async Task<string?> DescribeEndpointAsync() { try { var request = new DescribeEndpointRequest { EndpointType = "iot:Data-ATS" }; var response = await _amazonIoT.DescribeEndpointAsync(request); _logger.LogInformation($"Retrieved endpoint: {response.EndpointAddress}"); return response.EndpointAddress; } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return null; } catch (Exception ex) { _logger.LogError($"Couldn't describe endpoint. Here's why: {ex.Message}"); return null; } }
  • Para obtener más información sobre la API, consulta DescribeEndpointla Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar DetachThingPrincipal.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Detaches a certificate from an IoT Thing. /// </summary> /// <param name="thingName">The name of the Thing.</param> /// <param name="certificateArn">The ARN of the certificate to detach.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> DetachThingPrincipalAsync(string thingName, string certificateArn) { try { var request = new DetachThingPrincipalRequest { ThingName = thingName, Principal = certificateArn }; await _amazonIoT.DetachThingPrincipalAsync(request); _logger.LogInformation($"Detached certificate {certificateArn} from Thing {thingName}"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot detach certificate - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't detach certificate from Thing. Here's why: {ex.Message}"); return false; } }
  • Para obtener más información sobre la API, consulta DetachThingPrincipalla Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar ListCertificates.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Lists all certificates associated with the account. /// </summary> /// <returns>List of certificate information, or empty list if listing failed.</returns> public async Task<List<Certificate>> ListCertificatesAsync() { try { var request = new ListCertificatesRequest(); var response = await _amazonIoT.ListCertificatesAsync(request); _logger.LogInformation($"Retrieved {response.Certificates.Count} certificates"); return response.Certificates; } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return new List<Certificate>(); } catch (Exception ex) { _logger.LogError($"Couldn't list certificates. Here's why: {ex.Message}"); return new List<Certificate>(); } }
  • Para obtener más información sobre la API, consulta ListCertificatesla Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar ListThings.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Lists IoT Things with pagination support. /// </summary> /// <returns>List of Things, or empty list if listing failed.</returns> public async Task<List<ThingAttribute>> ListThingsAsync() { try { // Use pages of 10. var request = new ListThingsRequest() { MaxResults = 10 }; var response = await _amazonIoT.ListThingsAsync(request); // Since there is not a built-in paginator, use the NextMarker to paginate. bool hasMoreResults = true; var things = new List<ThingAttribute>(); while (hasMoreResults) { things.AddRange(response.Things); // If NextMarker is not null, there are more results. Get the next page of results. if (!String.IsNullOrEmpty(response.NextMarker)) { request.Marker = response.NextMarker; response = await _amazonIoT.ListThingsAsync(request); } else hasMoreResults = false; } _logger.LogInformation($"Retrieved {things.Count} Things"); return things; } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return new List<ThingAttribute>(); } catch (Exception ex) { _logger.LogError($"Couldn't list Things. Here's why: {ex.Message}"); return new List<ThingAttribute>(); } }
  • Para obtener más información sobre la API, consulta ListThingsla Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar SearchIndex.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Searches for IoT Things using the search index. /// </summary> /// <param name="queryString">The search query string.</param> /// <returns>List of Things that match the search criteria, or empty list if search failed.</returns> public async Task<List<ThingDocument>> SearchIndexAsync(string queryString) { try { // First, try to perform the search var request = new SearchIndexRequest { QueryString = queryString }; var response = await _amazonIoT.SearchIndexAsync(request); _logger.LogInformation($"Search found {response.Things.Count} Things"); return response.Things; } catch (Amazon.IoT.Model.IndexNotReadyException ex) { _logger.LogWarning($"Search index not ready, setting up indexing configuration: {ex.Message}"); return await SetupIndexAndRetrySearchAsync(queryString); } catch (Amazon.IoT.Model.ResourceNotFoundException ex) when (ex.Message.Contains("index") || ex.Message.Contains("Index")) { _logger.LogWarning($"Search index not configured, setting up indexing configuration: {ex.Message}"); return await SetupIndexAndRetrySearchAsync(queryString); } catch (Amazon.IoT.Model.ThrottlingException ex) { _logger.LogWarning($"Request throttled, please try again later: {ex.Message}"); return new List<ThingDocument>(); } catch (Exception ex) { _logger.LogError($"Couldn't search index. Here's why: {ex.Message}"); return new List<ThingDocument>(); } } /// <summary> /// Sets up the indexing configuration and retries the search after waiting for the index to be ready. /// </summary> /// <param name="queryString">The search query string.</param> /// <returns>List of Things that match the search criteria, or empty list if setup/search failed.</returns> private async Task<List<ThingDocument>> SetupIndexAndRetrySearchAsync(string queryString) { try { // Update indexing configuration to REGISTRY mode _logger.LogInformation("Setting up IoT search indexing configuration..."); await _amazonIoT.UpdateIndexingConfigurationAsync( new UpdateIndexingConfigurationRequest() { ThingIndexingConfiguration = new ThingIndexingConfiguration() { ThingIndexingMode = ThingIndexingMode.REGISTRY } }); _logger.LogInformation("Indexing configuration updated. Waiting for index to be ready..."); // Wait for the index to be set up - this can take some time const int maxRetries = 10; const int retryDelaySeconds = 10; for (int attempt = 1; attempt <= maxRetries; attempt++) { try { _logger.LogInformation($"Waiting for index to be ready (attempt {attempt}/{maxRetries})..."); await Task.Delay(TimeSpan.FromSeconds(retryDelaySeconds)); // Try to get the current indexing configuration to see if it's ready var configResponse = await _amazonIoT.GetIndexingConfigurationAsync(new GetIndexingConfigurationRequest()); if (configResponse.ThingIndexingConfiguration?.ThingIndexingMode == ThingIndexingMode.REGISTRY) { // Try the search again var request = new SearchIndexRequest { QueryString = queryString }; var response = await _amazonIoT.SearchIndexAsync(request); _logger.LogInformation($"Search found {response.Things.Count} Things after index setup"); return response.Things; } } catch (Amazon.IoT.Model.IndexNotReadyException) { // Index still not ready, continue waiting _logger.LogInformation("Index still not ready, continuing to wait..."); continue; } catch (Amazon.IoT.Model.InvalidRequestException ex) when (ex.Message.Contains("index") || ex.Message.Contains("Index")) { // Index still not ready, continue waiting _logger.LogInformation("Index still not ready, continuing to wait..."); continue; } } _logger.LogWarning("Timeout waiting for search index to be ready after configuration update"); return new List<ThingDocument>(); } catch (Exception ex) { _logger.LogError($"Couldn't set up search index configuration. Here's why: {ex.Message}"); return new List<ThingDocument>(); } }
  • Para obtener más información sobre la API, consulta SearchIndexla Referencia AWS SDK para .NET de la API.

En el siguiente ejemplo de código, se muestra cómo utilizar UpdateThing.

SDK para .NET (v4)
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS.

/// <summary> /// Updates an IoT Thing with attributes. /// </summary> /// <param name="thingName">The name of the Thing to update.</param> /// <param name="attributes">Dictionary of attributes to add.</param> /// <returns>True if successful, false otherwise.</returns> public async Task<bool> UpdateThingAsync(string thingName, Dictionary<string, string> attributes) { try { var request = new UpdateThingRequest { ThingName = thingName, AttributePayload = new AttributePayload { Attributes = attributes, Merge = true } }; await _amazonIoT.UpdateThingAsync(request); _logger.LogInformation($"Updated Thing {thingName} with attributes"); return true; } catch (Amazon.IoT.Model.ResourceNotFoundException ex) { _logger.LogError($"Cannot update Thing - resource not found: {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"Couldn't update Thing attributes. Here's why: {ex.Message}"); return false; } }
  • Para obtener más información sobre la API, consulta UpdateThingla Referencia AWS SDK para .NET de la API.