public static async Task <int> MainAsync() { Logger.LogInformation($"Starting DirectMethodCloudSender with the following settings:\r\n{Settings.Current}"); try { string serviceClientConnectionString = Settings.Current.ServiceClientConnectionString; Uri analyzerUrl = Settings.Current.AnalyzerUrl; ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(serviceClientConnectionString, (TransportType)Settings.Current.TransportType); AnalyzerClient analyzerClient = new AnalyzerClient { BaseUrl = analyzerUrl.AbsoluteUri }; (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), Logger); await CallDirectMethodFromCloud(serviceClient, Settings.Current.DirectMethodDelay, analyzerClient, cts); completed.Set(); handler.ForEach(h => GC.KeepAlive(h)); Logger.LogInformation("DirectMethodCloudSender Main() finished."); } catch (Exception ex) { Logger.LogError($"Error occurred during direct method cloud sender test setup.\r\n{ex}"); } return(0); }
static async Task <int> MainAsync() { Logger.LogInformation("DirectMethodCloudSender Main() started."); IConfiguration configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("config/appsettings.json", optional: true) .AddEnvironmentVariables() .Build(); string serviceClientConnectionString = Preconditions.CheckNonWhiteSpace(configuration.GetValue <string>("ServiceClientConnectionString"), nameof(serviceClientConnectionString)); // Get device id of this device, exposed as a system variable by the iot edge runtime string targetDeviceId = configuration.GetValue <string>("IOTEDGE_DEVICEID"); string targetModuleId = configuration.GetValue("TargetModuleId", "DirectMethodReceiver"); TimeSpan dmDelay = configuration.GetValue("DirectMethodDelay", TimeSpan.FromSeconds(5)); Uri analyzerUrl = configuration.GetValue("AnalyzerUrl", new Uri("http://analyzer:15000")); AnalyzerClient analyzerClient = new AnalyzerClient { BaseUrl = analyzerUrl.AbsoluteUri }; (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), Logger); await CallDirectMethodFromCloud(serviceClientConnectionString, targetDeviceId, targetModuleId, dmDelay, analyzerClient, cts); completed.Set(); handler.ForEach(h => GC.KeepAlive(h)); Logger.LogInformation("DirectMethodCloudSender Main() finished."); return(0); }
public ReportedPropertyOperation(RegistryManager registryManager, ModuleClient moduleClient, AnalyzerClient analyzerClient, TwinEventStorage storage, TwinState twinState) { this.registryManager = registryManager; this.moduleClient = moduleClient; this.analyzerClient = analyzerClient; this.storage = storage; this.twinState = twinState; }
public DesiredPropertyOperation(RegistryManager registryManager, ModuleClient moduleClient, AnalyzerClient analyzerClient, TwinEventStorage storage, TwinState twinState) { this.registryManager = registryManager; this.moduleClient = moduleClient; this.analyzerClient = analyzerClient; this.storage = storage; this.twinState = twinState; this.moduleClient.SetDesiredPropertyUpdateCallbackAsync(this.OnDesiredPropertyUpdateAsync, storage); }
public TwinAllOperationsResultHandler(Uri analyzerClientUri, TwinEventStorage storage, string moduleId) { this.analyzerClient = new AnalyzerClient() { BaseUrl = analyzerClientUri.AbsoluteUri }; this.moduleId = moduleId; this.storage = storage; }
static async Task ReportStatus(string moduleId, HttpStatusCode result, AnalyzerClient analyzerClient) { try { await analyzerClient.ReportResultAsync(new TestOperationResult { Source = moduleId, Result = result.ToString(), CreatedAt = DateTime.UtcNow, Type = Enum.GetName(typeof(TestOperationResultType), TestOperationResultType.LegacyDirectMethod) }); } catch (Exception e) { Logger.LogError(e.ToString()); } }
static async Task ReportStatus(string moduleId, MethodResponse response, AnalyzerClient analyzerClient) { try { await analyzerClient.ReportResultAsync(new TestOperationResult { Source = moduleId, Result = response.Status.ToString(), CreatedAt = DateTime.UtcNow, Type = "LegacyDirectMethod" }); } catch (Exception e) { Logger.LogError(e.ToString()); } }
protected async Task CallAnalyzerToReportStatusAsync(AnalyzerClient analyzerClient, string moduleId, string status) { try { await analyzerClient.AddTwinStatusAsync(new ResponseStatus { ModuleId = moduleId, StatusCode = status, EnqueuedDateTime = DateTime.UtcNow }); } catch (Exception e) { this.Logger.LogError($"Failed call to report status to analyzer: {e}"); } }
protected async Task CallAnalyzerToReportStatusAsync(AnalyzerClient analyzerClient, string moduleId, string status) { try { await analyzerClient.ReportResultAsync(new TestOperationResult { Source = moduleId, Result = status, CreatedAt = DateTime.UtcNow, Type = "LegacyTwin" }); } catch (Exception e) { this.Logger.LogError($"Failed call to report status to analyzer: {e}"); } }
static async Task CallDirectMethodFromCloud( ServiceClient serviceClient, TimeSpan delay, AnalyzerClient analyzerClient, CancellationTokenSource cts) { Logger.LogInformation("CallDirectMethodFromCloud started."); CloudToDeviceMethod cloudToDeviceMethod = new CloudToDeviceMethod("HelloWorldMethod").SetPayloadJson("{ \"Message\": \"Hello\" }"); string deviceId = Settings.Current.DeviceId; string targetModuleId = Settings.Current.TargetModuleId; int directMethodCount = 1; while (!cts.Token.IsCancellationRequested) { Logger.LogInformation($"Calling Direct Method from cloud on device {Settings.Current.DeviceId} targeting module [{Settings.Current.TargetModuleId}] with count {directMethodCount}."); try { CloudToDeviceMethodResult result = await serviceClient.InvokeDeviceMethodAsync(deviceId, targetModuleId, cloudToDeviceMethod, CancellationToken.None); string statusMessage = $"Calling Direct Method from cloud with count {directMethodCount} returned with status code {result.Status}"; if (result.Status == (int)HttpStatusCode.OK) { Logger.LogDebug(statusMessage); } else { Logger.LogError(statusMessage); } await ReportStatus(targetModuleId, result, analyzerClient); directMethodCount++; } catch (Exception e) { Logger.LogError($"Exception caught with count {directMethodCount}: {e}"); } await Task.Delay(delay, cts.Token); } Logger.LogInformation("CallDirectMethodFromCloud finished."); await serviceClient.CloseAsync(); }
static async Task CallDirectMethod( ModuleClient moduleClient, AnalyzerClient analyzerClient, TimeSpan delay, CancellationTokenSource cts) { var request = new MethodRequest("HelloWorldMethod", Encoding.UTF8.GetBytes("{ \"Message\": \"Hello\" }")); string deviceId = Settings.Current.DeviceId; string targetModuleId = Settings.Current.TargetModuleId; int directMethodCount = 1; while (!cts.Token.IsCancellationRequested) { Logger.LogInformation($"Calling Direct Method on device {deviceId} targeting module {targetModuleId}."); try { MethodResponse response = await moduleClient.InvokeMethodAsync(deviceId, targetModuleId, request); string statusMessage = $"Calling Direct Method with count {directMethodCount} returned with status code {response.Status}"; if (response.Status == (int)HttpStatusCode.OK) { Logger.LogDebug(statusMessage); } else { Logger.LogError(statusMessage); } await ReportStatus(targetModuleId, response, analyzerClient); directMethodCount++; } catch (Exception e) { Logger.LogError(e, "Exception caught"); } await Task.Delay(delay, cts.Token); } }
static async Task Main() { Logger.LogInformation($"Starting twin tester with the following settings:\r\n{Settings.Current}"); try { RegistryManager registryManager = RegistryManager.CreateFromConnectionString(Settings.Current.ServiceClientConnectionString); ModuleClient moduleClient = await ModuleUtil.CreateModuleClientAsync( Settings.Current.TransportType, ModuleUtil.DefaultTimeoutErrorDetectionStrategy, ModuleUtil.DefaultTransientRetryStrategy, Logger); await moduleClient.OpenAsync(); AnalyzerClient analyzerClient = new AnalyzerClient { BaseUrl = Settings.Current.AnalyzerUrl.AbsoluteUri }; TwinEventStorage storage = new TwinEventStorage(); storage.Init(Settings.Current.StoragePath, new SystemEnvironment(), Settings.Current.StorageOptimizeForPerformance); TwinOperator twinOperator = await TwinOperator.CreateAsync(registryManager, moduleClient, analyzerClient, storage); twinOperator.Start(); (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), Logger); await cts.Token.WhenCanceled(); completed.Set(); handler.ForEach(h => GC.KeepAlive(h)); Logger.LogInformation("TwinTester exiting."); } catch (Exception ex) { Logger.LogError($"Error occurred during twin test setup.\r\n{ex}"); } }
public static async Task <int> MainAsync() { Logger.LogInformation($"Starting DirectMethodSender with the following settings:\r\n{Settings.Current}"); try { ModuleClient moduleClient = await ModuleUtil.CreateModuleClientAsync( Settings.Current.TransportType, ModuleUtil.DefaultTimeoutErrorDetectionStrategy, ModuleUtil.DefaultTransientRetryStrategy, Logger); Uri analyzerUrl = Settings.Current.AnalyzerUrl; AnalyzerClient analyzerClient = new AnalyzerClient { BaseUrl = analyzerUrl.AbsoluteUri }; (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), Logger); await CallDirectMethod(moduleClient, analyzerClient, Settings.Current.DirectMethodDelay, cts); await moduleClient.CloseAsync(); await cts.Token.WhenCanceled(); completed.Set(); handler.ForEach(h => GC.KeepAlive(h)); Logger.LogInformation("DirectMethodSender Main() finished."); } catch (Exception e) { Logger.LogError(e, "Error occurred during direct method sender test setup"); } return(0); }
static async Task CallAnalyzerToReportStatusAsync(string moduleId, CloudToDeviceMethodResult result, AnalyzerClient analyzerClient) { try { await analyzerClient.AddDirectMethodStatusAsync(new ResponseStatus { ModuleId = moduleId, StatusCode = result.Status.ToString(), EnqueuedDateTime = DateTime.UtcNow }); } catch (Exception e) { Logger.LogError($"Failed call to report status to analyzer: {e}"); } }
public static async Task <TwinOperator> CreateAsync(RegistryManager registryManager, ModuleClient moduleClient, AnalyzerClient analyzerClient, TwinEventStorage storage) { try { TwinState initializedState; Twin twin = await registryManager.GetTwinAsync(Settings.Current.DeviceId, Settings.Current.ModuleId); Dictionary <string, DateTime> reportedPropertyUpdates = await storage.GetAllReportedPropertiesUpdatedAsync(); Dictionary <string, DateTime> desiredPropertyUpdates = await storage.GetAllDesiredPropertiesUpdatedAsync(); if (reportedPropertyUpdates.Count == 0 && desiredPropertyUpdates.Count == 0 && (await storage.GetAllDesiredPropertiesReceivedAsync()).Count == 0) { Logger.LogInformation("No existing storage detected. Initializing new module twin for fresh run."); // reset desired properties Twin desiredPropertyResetTwin = await registryManager.ReplaceTwinAsync(Settings.Current.DeviceId, Settings.Current.ModuleId, new Twin(), twin.ETag); // reset reported properties TwinCollection eraseReportedProperties = GetReportedPropertiesResetTwin(desiredPropertyResetTwin); await moduleClient.UpdateReportedPropertiesAsync(eraseReportedProperties); await Task.Delay(TimeSpan.FromSeconds(10)); // give enough time for reported properties reset to reach cloud twin = await registryManager.GetTwinAsync(Settings.Current.DeviceId, Settings.Current.ModuleId); initializedState = new TwinState { ReportedPropertyUpdateCounter = 0, DesiredPropertyUpdateCounter = 0, TwinETag = twin.ETag, LastTimeOffline = DateTime.MinValue }; } else { Logger.LogInformation("Existing storage detected. Initializing reported / desired property update counters."); initializedState = new TwinState { ReportedPropertyUpdateCounter = GetNewPropertyCounter(reportedPropertyUpdates), DesiredPropertyUpdateCounter = GetNewPropertyCounter(desiredPropertyUpdates), TwinETag = twin.ETag, LastTimeOffline = DateTime.MinValue }; } Logger.LogInformation($"Start state of module twin: {JsonConvert.SerializeObject(twin, Formatting.Indented)}"); return(new TwinOperator(registryManager, moduleClient, analyzerClient, storage, initializedState)); } catch (Exception e) { throw new Exception($"Shutting down module. Initialization failure: {e}"); } }
static async Task CallDirectMethodFromCloud( string serviceClientConnectionString, string deviceId, string moduleId, TimeSpan delay, AnalyzerClient analyzerClient, CancellationTokenSource cts) { Logger.LogInformation("CallDirectMethodFromCloud started."); ServiceClient serviceClient = null; try { int count = 1; IotHubConnectionStringBuilder iotHubConnectionStringBuilder = IotHubConnectionStringBuilder.Create(serviceClientConnectionString); Logger.LogInformation($"Prepare to call Direct Method from cloud ({iotHubConnectionStringBuilder.IotHubName}) on device [{deviceId}] module [{moduleId}]"); serviceClient = ServiceClient.CreateFromConnectionString(serviceClientConnectionString, Microsoft.Azure.Devices.TransportType.Amqp); var cloudToDeviceMethod = new CloudToDeviceMethod("HelloWorldMethod").SetPayloadJson("{ \"Message\": \"Hello\" }"); while (!cts.Token.IsCancellationRequested) { Logger.LogInformation($"Calling Direct Method from cloud ({iotHubConnectionStringBuilder.IotHubName}) on device [{deviceId}] module [{moduleId}] of count {count}."); try { CloudToDeviceMethodResult result = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, cloudToDeviceMethod, CancellationToken.None); if (result.Status == (int)HttpStatusCode.OK) { Logger.LogDebug($"Calling Direct Method from cloud with count {count} returned with status code {result.Status}."); } else { Logger.LogError($"Calling Direct Method from cloud with count {count} failed with status code {result.Status}."); } await CallAnalyzerToReportStatusAsync(moduleId, result, analyzerClient); count++; } catch (Exception e) { Logger.LogError($"Exception caught with count {count}: {e}"); } await Task.Delay(delay, cts.Token); } } catch (Exception e) { Logger.LogError($"Exception caught: {e}"); throw; } finally { Logger.LogInformation("Close connection for service client and module client"); if (serviceClient != null) { await serviceClient.CloseAsync(); } } Logger.LogInformation("CallDirectMethodFromCloud finished."); }
static async Task ReportStatus(string moduleId, CloudToDeviceMethodResult result, AnalyzerClient analyzerClient) { try { await analyzerClient.ReportResultAsync(new TestOperationResult { Source = moduleId, Result = result.Status.ToString(), CreatedAt = DateTime.UtcNow, Type = "LegacyDirectMethod" }); } catch (Exception e) { Logger.LogError(e, "Failed call to report status to analyzer"); } }
public static async Task <int> MainAsync() { Logger.LogInformation($"Starting DirectMethodSender with the following settings:\r\n{Settings.Current}"); (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), Logger); DirectMethodSenderBase directMethodClient = null; ModuleClient reportClient = null; Option <Uri> analyzerUrl = Settings.Current.AnalyzerUrl; Option <Uri> testReportCoordinatorUrl = Settings.Current.TestResultCoordinatorUrl; try { Guid batchId = Guid.NewGuid(); Logger.LogInformation($"Batch Id={batchId}"); directMethodClient = await CreateClientAsync(Settings.Current.InvocationSource); reportClient = await ModuleUtil.CreateModuleClientAsync( Settings.Current.TransportType, ModuleUtil.DefaultTimeoutErrorDetectionStrategy, ModuleUtil.DefaultTransientRetryStrategy, Logger); Logger.LogInformation($"Load gen delay start for {Settings.Current.TestStartDelay}."); await Task.Delay(Settings.Current.TestStartDelay, cts.Token); DateTime testStartAt = DateTime.UtcNow; while (!cts.Token.IsCancellationRequested && IsTestTimeUp(testStartAt)) { (HttpStatusCode result, long dmCounter) = await directMethodClient.InvokeDirectMethodAsync(cts); // TODO: Create an abstract class to handle the reporting client generation if (testReportCoordinatorUrl.HasValue) { await testReportCoordinatorUrl.ForEachAsync( async (Uri uri) => { TestResultCoordinatorClient trcClient = new TestResultCoordinatorClient { BaseUrl = uri.AbsoluteUri }; await ModuleUtil.ReportStatus( trcClient, Logger, Settings.Current.ModuleId + ".send", ModuleUtil.FormatDirectMethodTestResultValue( Settings.Current.TrackingId.Expect(() => new ArgumentException("TrackingId is empty")), batchId.ToString(), dmCounter.ToString(), result.ToString()), TestOperationResultType.DirectMethod.ToString()); }); } else { await analyzerUrl.ForEachAsync( async (Uri uri) => { AnalyzerClient analyzerClient = new AnalyzerClient { BaseUrl = uri.AbsoluteUri }; await ReportStatus(Settings.Current.TargetModuleId, result, analyzerClient); }, async() => { await reportClient.SendEventAsync("AnyOutput", new Message(Encoding.UTF8.GetBytes("Direct Method call succeeded."))); }); } await Task.Delay(Settings.Current.DirectMethodDelay, cts.Token); } await cts.Token.WhenCanceled(); } catch (Exception e) { Logger.LogError(e, "Error occurred during direct method sender test setup"); } finally { // Implicit CloseAsync() directMethodClient?.Dispose(); reportClient?.Dispose(); } completed.Set(); handler.ForEach(h => GC.KeepAlive(h)); Logger.LogInformation("DirectMethodSender Main() finished."); return(0); }
private TwinOperator(RegistryManager registryManager, ModuleClient moduleClient, AnalyzerClient analyzerClient, TwinEventStorage storage, TwinState twinState) { this.reportedPropertyOperation = new ReportedPropertyOperation(registryManager, moduleClient, analyzerClient, storage, twinState); this.desiredPropertyOperation = new DesiredPropertyOperation(registryManager, moduleClient, analyzerClient, storage, twinState); }