的版本 4 (V4) 适用于 .NET 的 AWS SDK 已经发布!
有关重大更改和迁移应用程序的信息,请参阅迁移主题。
本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
AWS IoT 使用 适用于 .NET 的 SDK (v4) 的示例
以下代码示例向您展示了如何通过使用 适用于 .NET 的 AWS SDK (v4) 来执行操作和实现常见场景。 AWS IoT
基本功能是向您展示如何在服务中执行基本操作的代码示例。
操作是大型程序的代码摘录,必须在上下文中运行。您可以通过操作了解如何调用单个服务函数,还可以通过函数相关场景的上下文查看操作。
每个示例都包含一个指向完整源代码的链接,您可以从中找到有关如何在上下文中设置和运行代码的说明。
开始使用
以下代码示例展示了如何开始使用 AWS IoT。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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}"); } } }-
有关 API 详细信息,请参阅《适用于 .NET 的 AWS SDK API Reference》中的 listThings。
-
基本功能
以下代码示例展示了如何:
创建 AWS IoT 事物。
生成设备证书。
使用属性更新 AWS IoT 事物。
返回一个唯一的端点。
列出您的 AWS IoT 证书。
更新 AWS IoT 阴影。
写出状态信息。
创建规则。
列出您的规则。
使用事物名称搜索事物。
删除 AWS IoT 事物。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 AWS 代码示例存储库
中查找完整示例,了解如何进行设置和运行。 运行演示 AWS IoT 功能的交互式场景。
/// <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; } }AWS IoT 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>(); } } }
操作
以下代码示例演示了如何使用 AttachThingPrincipal。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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; } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考AttachThingPrincipal中的。
-
以下代码示例演示了如何使用 CreateKeysAndCertificate。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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; } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考CreateKeysAndCertificate中的。
-
以下代码示例演示了如何使用 CreateThing。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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; } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考CreateThing中的。
-
以下代码示例演示了如何使用 CreateTopicRule。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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; } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考CreateTopicRule中的。
-
以下代码示例演示了如何使用 DeleteCertificate。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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; } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考DeleteCertificate中的。
-
以下代码示例演示了如何使用 DeleteThing。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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; } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考DeleteThing中的。
-
以下代码示例演示了如何使用 DescribeEndpoint。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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; } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考DescribeEndpoint中的。
-
以下代码示例演示了如何使用 DetachThingPrincipal。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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; } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考DetachThingPrincipal中的。
-
以下代码示例演示了如何使用 ListCertificates。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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>(); } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考ListCertificates中的。
-
以下代码示例演示了如何使用 ListThings。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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>(); } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考ListThings中的。
-
以下代码示例演示了如何使用 SearchIndex。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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>(); } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考SearchIndex中的。
-
以下代码示例演示了如何使用 UpdateThing。
- 适用于 .NET 的 SDK (v4)
-
注意
还有更多相关信息 GitHub。在 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; } }-
有关 API 的详细信息,请参阅 适用于 .NET 的 AWS SDK API 参考UpdateThing中的。
-