/// <summary> /// helper to invoke service /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="R"></typeparam> /// <param name="service"></param> /// <param name="registration"></param> /// <param name="request"></param> /// <returns></returns> private async Task <R> CallServiceOnSupervisorAsync <T, R>(string service, EndpointRegistrationModel registration, T request) { if (registration == null) { throw new ArgumentNullException(nameof(registration)); } if (registration.Endpoint == null) { throw new ArgumentNullException(nameof(registration.Endpoint)); } if (string.IsNullOrEmpty(registration.SupervisorId)) { throw new ArgumentNullException(nameof(registration.SupervisorId)); } var sw = Stopwatch.StartNew(); var deviceId = SupervisorModelEx.ParseDeviceId(registration.SupervisorId, out var moduleId); var result = await _client.CallMethodAsync(deviceId, moduleId, service, _serializer.SerializeToString(new { endpoint = registration.Endpoint, request })); _logger.Debug("Calling supervisor service '{service}' on {deviceId}/{moduleId} " + "took {elapsed} ms and returned {result}!", service, deviceId, moduleId, sw.ElapsedMilliseconds, result); return(_serializer.Deserialize <R>(result)); }
public void ProcessDiscoveryWithDifferentSupervisorsSameSiteApplications() { var fix = new Fixture(); var super2 = SupervisorModelEx.CreateSupervisorId(fix.Create <string>(), fix.Create <string>()); // Readjust existing to be reported from different supervisor... CreateFixtures(out var site, out var super, out var existing, out var found, out var registry, -1, x => { x.Application.SupervisorId = super2; x.Endpoints.ForEach(e => e.SupervisorId = super2); return(x); }); // Assert no changes using (var mock = AutoMock.GetLoose()) { // Setup var service = Setup(mock, registry); // Run service.ProcessDiscoveryResultsAsync(super, new DiscoveryResultModel(), found).Wait(); // Assert Assert.True(ApplicationsIn(registry).IsSameAs(existing)); } }
public void ProcessDiscoveryWithNoResultsAndNoExistingApplications() { var found = new List <DiscoveryEventModel>(); var fix = new Fixture(); var device = fix.Create <string>(); var module = fix.Create <string>(); var super = SupervisorModelEx.CreateSupervisorId(device, module); var deviceModel = new DeviceModel { Id = device, ModuleId = module }; var twinModel = new SupervisorModel { Id = super }.ToSupervisorRegistration().ToDeviceTwin(); var registry = IoTHubServices.Create((twinModel, deviceModel).YieldReturn()); using (var mock = AutoMock.GetLoose()) { // Setup mock.Provide <IIoTHubTwinServices>(registry); mock.Provide <ISupervisorRegistry, SupervisorRegistry>(); mock.Provide <IApplicationBulkProcessor, ApplicationRegistry>(); mock.Provide <IEndpointBulkProcessor, EndpointRegistry>(); var service = mock.Create <DiscoveryProcessor>(); // Run service.ProcessDiscoveryResultsAsync(super, new DiscoveryResultModel(), found).Wait(); // Assert Assert.Empty(registry.Devices); } }
public void ProcessDiscoveryWithNoResultsWithDifferentSupervisorsFromExisting() { var fix = new Fixture(); var super2 = SupervisorModelEx.CreateSupervisorId(fix.Create <string>(), fix.Create <string>()); // Readjust existing to be reported from different supervisor... CreateFixtures(out var site, out var super, out var existing, out var found, out var registry, -1, x => { x.Application.SupervisorId = super2; x.Endpoints.ForEach(e => e.SupervisorId = super2); return(x); }); // Found nothing found = new List <DiscoveryEventModel>(); // Assert there is still the same content as originally using (var mock = AutoMock.GetLoose()) { // Setup mock.Provide <IIoTHubTwinServices>(registry); var service = mock.Create <RegistryServices>(); // Run service.ProcessDiscoveryAsync(super, new DiscoveryResultModel(), found, false).Wait(); // Assert Assert.True(ApplicationsIn(registry).IsSameAs(existing)); } }
public void ProcessDiscoveryWithNoResultsAndNoExistingApplications() { var found = new List <DiscoveryEventModel>(); var fix = new Fixture(); var device = fix.Create <string>(); var module = fix.Create <string>(); var super = SupervisorModelEx.CreateSupervisorId(device, module); var deviceModel = new DeviceModel { Id = device, ModuleId = module }; var twinModel = SupervisorRegistration.Patch(null, SupervisorRegistration.FromServiceModel(new SupervisorModel { Id = super })); var registry = new IoTHubServices((twinModel, deviceModel).YieldReturn()); using (var mock = AutoMock.GetLoose()) { // Setup mock.Provide <IIoTHubTwinServices>(registry); var service = mock.Create <RegistryServices>(); // Run service.ProcessDiscoveryAsync(super, new DiscoveryResultModel(), found, false).Wait(); // Assert Assert.Empty(registry.Devices); } }
/// <inheritdoc/> public async Task <byte[]> GetEndpointCertificateAsync( EndpointRegistrationModel registration, CancellationToken ct) { if (registration == null) { throw new ArgumentNullException(nameof(registration)); } if (registration.Endpoint == null) { throw new ArgumentNullException(nameof(registration.Endpoint)); } if (string.IsNullOrEmpty(registration.SupervisorId)) { throw new ArgumentNullException(nameof(registration.SupervisorId)); } var deviceId = SupervisorModelEx.ParseDeviceId(registration.SupervisorId, out var moduleId); var sw = Stopwatch.StartNew(); var result = await _client.CallMethodAsync(deviceId, moduleId, "GetEndpointCertificate_V2", _serializer.SerializeToString(registration.Endpoint), null, ct); _logger.Debug("Calling supervisor {deviceId}/{moduleId} to get certificate." + "Took {elapsed} ms and returned {result}!", deviceId, moduleId, sw.ElapsedMilliseconds, result); return(_serializer.Deserialize <byte[]>(result)); }
/// <summary> /// Enable or disable twin on supervisor /// </summary> /// <param name="supervisorId"></param> /// <param name="twinId"></param> /// <param name="secret"></param> /// <param name="ct"></param> /// <returns></returns> private async Task SetSupervisorTwinSecretAsync(string supervisorId, string twinId, string secret, CancellationToken ct = default) { if (string.IsNullOrEmpty(twinId)) { throw new ArgumentNullException(nameof(twinId)); } if (string.IsNullOrEmpty(supervisorId)) { return; // ok, no supervisor } var deviceId = SupervisorModelEx.ParseDeviceId(supervisorId, out var moduleId); if (secret == null) { // Remove from supervisor - this disconnects the device await _iothub.UpdatePropertyAsync(deviceId, moduleId, twinId, null, ct); _logger.Information("Twin {twinId} deactivated on {supervisorId}.", twinId, supervisorId); } else { // Update supervisor to start supervising this endpoint await _iothub.UpdatePropertyAsync(deviceId, moduleId, twinId, secret, ct); _logger.Information("Twin {twinId} activated on {supervisorId}.", twinId, supervisorId); } }
/// <summary> /// Publisher demands /// </summary> /// <param name="endpoint"></param> /// <returns></returns> private static List <DemandModel> PublisherDemands(EndpointInfoModel endpoint) { var demands = new List <DemandModel> { new DemandModel { Key = "Type", Value = IdentityType.Publisher } }; // Add site as demand if available if (!string.IsNullOrEmpty(endpoint.Registration.SiteId)) { demands.Add(new DemandModel { Key = nameof(endpoint.Registration.SiteId), Value = endpoint.Registration.SiteId }); } else if (!string.IsNullOrEmpty(endpoint.Registration.SupervisorId)) { var deviceId = SupervisorModelEx.ParseDeviceId( endpoint.Registration.SupervisorId, out _); // Otherwise confine to the supervisor's gateway demands.Add(new DemandModel { Key = "DeviceId", Value = deviceId }); } return(demands); }
/// <inheritdoc/> public async Task UpdateSupervisorAsync(string supervisorId, SupervisorUpdateModel request, CancellationToken ct) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (string.IsNullOrEmpty(supervisorId)) { throw new ArgumentException(nameof(supervisorId)); } // Get existing endpoint and compare to see if we need to patch. var deviceId = SupervisorModelEx.ParseDeviceId(supervisorId, out var moduleId); while (true) { try { var twin = await _iothub.GetAsync(deviceId, moduleId, ct); if (twin.Id != deviceId && twin.ModuleId != moduleId) { throw new ArgumentException("Id must be same as twin to patch", nameof(supervisorId)); } var registration = twin.ToEntityRegistration(true) as SupervisorRegistration; if (registration == null) { throw new ResourceNotFoundException( $"{supervisorId} is not a supervisor registration."); } // Update registration from update request var patched = registration.ToServiceModel(); if (request.SiteId != null) { patched.SiteId = string.IsNullOrEmpty(request.SiteId) ? null : request.SiteId; } if (request.LogLevel != null) { patched.LogLevel = request.LogLevel == TraceLogLevel.Information ? null : request.LogLevel; } // Patch await _iothub.PatchAsync(registration.Patch( patched.ToSupervisorRegistration()), false, ct); return; } catch (ResourceOutOfDateException ex) { _logger.Debug(ex, "Retrying updating supervisor..."); continue; } } }
public void ProcessDiscoveryWithDifferentSupervisorsFromExistingWhenExistingDisabled() { var fix = new Fixture(); var super2 = SupervisorModelEx.CreateSupervisorId(fix.Create <string>(), fix.Create <string>()); // Readjust existing to be reported from different supervisor... CreateFixtures(out var site, out var super, out var existing, out var found, out var registry, -1, x => { x.Application.SupervisorId = super2; x.Endpoints.ForEach(e => e.SupervisorId = super2); return(x); }, true); // Assert disabled items are now enabled var count = registry.Devices.Count(); using (var mock = AutoMock.GetLoose()) { // Setup mock.Provide <IIoTHubTwinServices>(registry); var service = mock.Create <RegistryServices>(); // Run service.ProcessDiscoveryAsync(super, new DiscoveryResultModel(), found, false).Wait(); // Assert var inreg = ApplicationsIn(registry); Assert.False(inreg.IsSameAs(existing)); Assert.Equal(count, registry.Devices.Count()); Assert.All(inreg, a => Assert.Equal(super, a.Application.SupervisorId)); Assert.All(inreg, a => Assert.Null(a.Application.NotSeenSince)); Assert.All(inreg, a => Assert.All(a.Endpoints, e => Assert.Equal(super, e.SupervisorId))); } }
/// <inheritdoc/> public async Task HandleDeviceTwinEventAsync(DeviceTwinEvent ev) { if (ev.Handled) { return; } if (string.IsNullOrEmpty(ev.Twin.Id) || string.IsNullOrEmpty(ev.Twin.ModuleId)) { return; } var type = ev.Twin.Properties?.Reported.GetValueOrDefault <string>( TwinProperty.Type, null); if ((ev.Event != DeviceTwinEventType.Delete && ev.IsPatch) || string.IsNullOrEmpty(type)) { try { ev.Twin = await _iothub.GetAsync(ev.Twin.Id, ev.Twin.ModuleId); ev.IsPatch = false; type = ev.Twin.Properties?.Reported?.GetValueOrDefault <string>( TwinProperty.Type, null); } catch (Exception ex) { _logger.Verbose(ex, "Failed to materialize twin"); } } if (IdentityType.Supervisor.EqualsIgnoreCase(type)) { var ctx = new RegistryOperationContextModel { AuthorityId = ev.AuthorityId, Time = ev.Timestamp }; switch (ev.Event) { case DeviceTwinEventType.New: break; case DeviceTwinEventType.Create: await _broker.NotifyAllAsync(l => l.OnSupervisorNewAsync(ctx, ev.Twin.ToSupervisorRegistration(false).ToServiceModel())); break; case DeviceTwinEventType.Update: await _broker.NotifyAllAsync(l => l.OnSupervisorUpdatedAsync(ctx, ev.Twin.ToSupervisorRegistration(false).ToServiceModel())); break; case DeviceTwinEventType.Delete: await _broker.NotifyAllAsync(l => l.OnSupervisorDeletedAsync(ctx, SupervisorModelEx.CreateSupervisorId( ev.Twin.Id, ev.Twin.ModuleId))); break; } ev.Handled = true; } }
/// <summary> /// Create listener /// </summary> /// <param name="logger"></param> /// <param name="events"></param> /// <param name="processor"></param> public DiscoveryMessagePublisher(ILogger logger, IEventEmitter events, ITaskProcessor processor) : base(logger) { _events = events ?? throw new ArgumentNullException(nameof(events)); _processor = processor ?? throw new ArgumentNullException(nameof(processor)); _supervisorId = SupervisorModelEx.CreateSupervisorId(_events.DeviceId, _events.ModuleId); }
/// <summary> /// Send endpoint alert /// </summary> /// <param name="endpoint"></param> /// <param name="message"></param> /// <returns></returns> private Task SendEndpointAlertAsync(EndpointInfoModel endpoint, string message) { #if USE_SUPERVISOR_IDENTITY var deviceId = SupervisorModelEx.ParseDeviceId( endpoint.Registration.SupervisorId, out var moduleId); #else var deviceId = endpoint.Registration.Id; var moduleId = (string)null; #endif return(SendAlertAsync(deviceId, moduleId, message, FlattenToDict(endpoint.Registration))); }
/// <summary> /// Get device scope of the supervisor /// </summary> /// <param name="supervisorId"></param> /// <param name="ct"></param> /// <returns></returns> private async Task <string> GetSupervisorDeviceScopeAsync(string supervisorId, CancellationToken ct = default) { if (string.IsNullOrEmpty(supervisorId)) { return(null); // No scope } var edgeDeviceId = SupervisorModelEx.ParseDeviceId(supervisorId, out _); var edgeDeviceTwin = await _iothub.FindAsync(edgeDeviceId, ct : ct); return(edgeDeviceTwin?.DeviceScope); }
/// <summary> /// Helper to invoke service /// </summary> /// <param name="service"></param> /// <param name="supervisorId"></param> /// <param name="payload"></param> /// <param name="ct"></param> /// <returns></returns> private async Task CallServiceOnSupervisorAsync(string service, string supervisorId, object payload, CancellationToken ct) { var sw = Stopwatch.StartNew(); var deviceId = SupervisorModelEx.ParseDeviceId(supervisorId, out var moduleId); var result = await _client.CallMethodAsync(deviceId, moduleId, service, _serializer.SerializeToString(payload), null, ct); _logger.Debug("Calling supervisor service '{service}' on " + "{deviceId}/{moduleId} took {elapsed} ms.", service, deviceId, moduleId, sw.ElapsedMilliseconds); }
private ReadArrayValueTests <EndpointRegistrationModel> GetTests( string deviceId, string moduleId, IContainer services) { return(new ReadArrayValueTests <EndpointRegistrationModel>( () => services.Resolve <INodeServices <EndpointRegistrationModel> >(), new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = $"opc.tcp://{Dns.GetHostName()}:{_server.Port}/UA/SampleServer" }, Id = "testid", SupervisorId = SupervisorModelEx.CreateSupervisorId(deviceId, moduleId) }, (ep, n) => _server.Client.ReadValueAsync(ep.Endpoint, n))); }
private HistoryReadValuesTests <EndpointRegistrationModel> GetTests() { return(new HistoryReadValuesTests <EndpointRegistrationModel>( () => _module.HubContainer.Resolve <IHistorianServices <EndpointRegistrationModel> >(), new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = $"opc.tcp://{Dns.GetHostName()}:{_server.Port}/UA/SampleServer" }, Id = "testid", SupervisorId = SupervisorModelEx.CreateSupervisorId( _module.DeviceId, _module.ModuleId) })); }
private CallArrayMethodTests <EndpointRegistrationModel> GetTests( string deviceId, string moduleId, IContainer services) { return(new CallArrayMethodTests <EndpointRegistrationModel>( () => services.Resolve <INodeServices <EndpointRegistrationModel> >(), new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = $"opc.tcp://{Dns.GetHostName()}:{_server.Port}/UA/SampleServer" }, Id = "testid", SupervisorId = SupervisorModelEx.CreateSupervisorId(deviceId, moduleId) })); }
/// <summary> /// Helper to invoke service /// </summary> /// <param name="service"></param> /// <param name="supervisorId"></param> /// <param name="payload"></param> /// <returns></returns> private async Task CallServiceOnSupervisor(string service, string supervisorId, object payload) { var sw = Stopwatch.StartNew(); var deviceId = SupervisorModelEx.ParseDeviceId(supervisorId, out var moduleId); var result = await _client.CallMethodAsync(deviceId, moduleId, service, JsonConvertEx.SerializeObject(payload)); _logger.Debug("Calling supervisor service '{service}' on " + "{deviceId}/{moduleId} took {elapsed} ms.", service, deviceId, moduleId, sw.ElapsedMilliseconds); }
/// <summary> /// Send application alert /// </summary> /// <param name="application"></param> /// <param name="message"></param> /// <returns></returns> private Task SendApplicationAlertAsync(ApplicationInfoModel application, string message) { #if !USE_APPLICATION_IDENTITY var deviceId = SupervisorModelEx.ParseDeviceId( application.SupervisorId, out var moduleId); #else var deviceId = application.ApplicationId; var moduleId = (string)null; #endif return(SendAlertAsync(deviceId, moduleId, message, FlattenToDict(application))); }
private WriteScalarValueTests <EndpointRegistrationModel> GetTests() { return(new WriteScalarValueTests <EndpointRegistrationModel>( () => _module.HubContainer.Resolve <INodeServices <EndpointRegistrationModel> >(), new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = $"opc.tcp://{Dns.GetHostName()}:{_server.Port}/UA/SampleServer" }, Id = "testid", SupervisorId = SupervisorModelEx.CreateSupervisorId( _module.DeviceId, _module.ModuleId) }, (ep, n) => _server.Client.ReadValueAsync(ep.Endpoint, n))); }
private CallScalarMethodTests <EndpointRegistrationModel> GetTests() { return(new CallScalarMethodTests <EndpointRegistrationModel>( () => _module.HubContainer.Resolve <INodeServices <EndpointRegistrationModel> >(), new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = $"opc.tcp://{Dns.GetHostName()}:{_server.Port}/UA/SampleServer", Certificate = _server.Certificate?.RawData }, Id = "testid", SupervisorId = SupervisorModelEx.CreateSupervisorId( _module.DeviceId, _module.ModuleId) })); }
private HistoryReadValuesTests <EndpointRegistrationModel> GetTests( string deviceId, string moduleId, IContainer services) { return(new HistoryReadValuesTests <EndpointRegistrationModel>( () => services.Resolve <IHistorianServices <EndpointRegistrationModel> >(), new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = $"opc.tcp://{Dns.GetHostName()}:{_server.Port}/UA/SampleServer", Certificate = _server.Certificate?.RawData }, Id = "testid", SupervisorId = SupervisorModelEx.CreateSupervisorId(deviceId, moduleId) })); }
private CallArrayMethodTests <string> GetTests() { var endpoint = new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = $"opc.tcp://{Dns.GetHostName()}:{_server.Port}/UA/SampleServer" }, Id = "testid", SupervisorId = SupervisorModelEx.CreateSupervisorId( _module.DeviceId, _module.ModuleId) }; endpoint = _module.RegisterAndActivateTwinId(endpoint); return(new CallArrayMethodTests <string>( () => _module.HubContainer.Resolve <INodeServices <string> >(), endpoint.Id)); }
/// <inheritdoc/> public async Task ResetSupervisorAsync(string supervisorId) { if (string.IsNullOrEmpty(supervisorId)) { throw new ArgumentNullException(nameof(supervisorId)); } var sw = Stopwatch.StartNew(); var deviceId = SupervisorModelEx.ParseDeviceId(supervisorId, out var moduleId); var result = await _client.CallMethodAsync(deviceId, moduleId, "Reset_V2", null); _logger.Debug("Reset supervisor {deviceId}/{moduleId} took " + "{elapsed} ms.", deviceId, moduleId, sw.ElapsedMilliseconds); }
public async Task TestGetSupervisor() { using (var harness = new TwinModuleFixture()) { await harness.RunTestAsync(async (device, module, services) => { // Setup var registry = services.Resolve <ISupervisorRegistry>(); // Act var supervisor = await registry.GetSupervisorAsync(SupervisorModelEx.CreateSupervisorId(device, module)); // Assert Assert.True(supervisor.Connected.Value); Assert.True(supervisor.OutOfSync.Value); }); } }
private ReadScalarValueTests <string> GetTests() { var endpoint = new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = $"opc.tcp://{Dns.GetHostName()}:{_server.Port}/UA/SampleServer" }, Id = "testid", SupervisorId = SupervisorModelEx.CreateSupervisorId( _module.DeviceId, _module.ModuleId) }; endpoint = _module.RegisterAndActivateTwinId(endpoint); return(new ReadScalarValueTests <string>( () => _module.HubContainer.Resolve <INodeServices <string> >(), endpoint.Id, (ep, n) => _server.Client.ReadValueAsync(endpoint.Endpoint, n))); }
private BrowseServicesTests <string> GetTests() { var endpoint = new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = $"opc.tcp://{Dns.GetHostName()}:{_server.Port}/UA/SampleServer", Certificate = _server.Certificate?.RawData?.ToThumbprint() }, Id = "testid", SupervisorId = SupervisorModelEx.CreateSupervisorId( _module.DeviceId, _module.ModuleId) }; endpoint = _module.RegisterAndActivateTwinId(endpoint); return(new BrowseServicesTests <string>( () => _module.HubContainer.Resolve <IBrowseServices <string> >(), endpoint.Id)); }
public async Task TestActivateDeactivate20Endpoints5TimesMultiThreaded() { using (var harness = new TwinModuleFixture()) { await harness.RunTestAsync(async (device, module, services) => { // Setup var supervisorId = SupervisorModelEx.CreateSupervisorId(device, module); var activation = services.Resolve <IActivationServices <EndpointRegistrationModel> >(); var hub = services.Resolve <IIoTHubTwinServices>(); for (var i = 0; i < 20; i++) { var twin = new EndpointInfoModel { Registration = new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = "opc.tcp://test" }, SupervisorId = supervisorId }, ApplicationId = "uas" + i }.ToEndpointRegistration().ToDeviceTwin(); await hub.CreateAsync(twin); } var registry = services.Resolve <IEndpointRegistry>(); var endpoints = await registry.ListAllEndpointsAsync(); for (var i = 0; i < 5; i++) { await Task.WhenAll(endpoints.Select(ep => registry.ActivateEndpointAsync(ep.Registration.Id))); await Task.WhenAll(endpoints.Select(ep => registry.DeactivateEndpointAsync(ep.Registration.Id))); } var diagnostics = services.Resolve <ISupervisorDiagnostics>(); endpoints = await registry.ListAllEndpointsAsync(); var status = await diagnostics.GetSupervisorStatusAsync(supervisorId); // Assert Assert.Equal(device, status.DeviceId); Assert.Equal(module, status.ModuleId); Assert.Null(status.SiteId); Assert.Empty(status.Endpoints); Assert.True(endpoints.All(ep => ep.ActivationState == EndpointActivationState.Deactivated)); Assert.True(endpoints.All(ep => ep.EndpointState == null)); }); } }
public async Task TestActivateDeactivateEndpoint20Times() { using (var harness = new TwinModuleFixture()) { await harness.RunTestAsync(async (device, module, services) => { // Setup var supervisorId = SupervisorModelEx.CreateSupervisorId(device, module); var activation = services.Resolve <IActivationServices <EndpointRegistrationModel> >(); var hub = services.Resolve <IIoTHubTwinServices>(); var twin = new EndpointInfoModel { Registration = new EndpointRegistrationModel { Endpoint = new EndpointModel { Url = "opc.tcp://test" }, SupervisorId = supervisorId }, ApplicationId = "ua326029342304923" }.ToEndpointRegistration().ToDeviceTwin(); await hub.CreateAsync(twin); var registry = services.Resolve <IEndpointRegistry>(); var endpoints = await registry.ListAllEndpointsAsync(); var ep1 = endpoints.FirstOrDefault(); Assert.NotNull(ep1); for (var i = 0; i < 20; i++) { // Act await registry.ActivateEndpointAsync(ep1.Registration.Id); await registry.DeactivateEndpointAsync(ep1.Registration.Id); } var diagnostics = services.Resolve <ISupervisorDiagnostics>(); endpoints = await registry.ListAllEndpointsAsync(); var ep3 = endpoints.FirstOrDefault(); var status = await diagnostics.GetSupervisorStatusAsync(supervisorId); // Assert Assert.Equal(device, status.DeviceId); Assert.Equal(module, status.ModuleId); Assert.Null(status.SiteId); Assert.Empty(status.Endpoints); Assert.Equal(EndpointActivationState.Deactivated, ep3.ActivationState); Assert.Null(ep3.EndpointState); }); } }