/// <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.Publisher.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.OnPublisherNewAsync(ctx, ev.Twin.ToPublisherRegistration(false).ToServiceModel())); break; case DeviceTwinEventType.Update: await _broker.NotifyAllAsync(l => l.OnPublisherUpdatedAsync(ctx, ev.Twin.ToPublisherRegistration(false).ToServiceModel())); break; case DeviceTwinEventType.Delete: await _broker.NotifyAllAsync(l => l.OnPublisherDeletedAsync(ctx, PublisherModelEx.CreatePublisherId( ev.Twin.Id, ev.Twin.ModuleId))); break; } ev.Handled = true; } }
/// <inheritdoc/> public async Task <PublisherModel> GetPublisherAsync(string id, bool onlyServerState, CancellationToken ct) { if (string.IsNullOrEmpty(id)) { throw new ArgumentException(nameof(id)); } var deviceId = PublisherModelEx.ParseDeviceId(id, out var moduleId); var device = await _iothub.GetAsync(deviceId, moduleId, ct); var registration = device.ToEntityRegistration(onlyServerState) as PublisherRegistration; if (registration == null) { throw new ResourceNotFoundException( $"{id} is not a supervisor registration."); } return(registration.ToServiceModel()); }
/// <inheritdoc/> public async Task <(string, EndpointModel)> FindPublisherEndpoint( string endpointId, CancellationToken ct) { // Get the endpoint and the endpoints supervisor var device = await _iothub.GetAsync(endpointId, null, ct); var registration = device.ToEndpointRegistration(false); var endpoint = registration.ToServiceModel(); var supervisorId = endpoint?.Registration?.SupervisorId; if (string.IsNullOrEmpty(supervisorId)) { // No supervisor set for the retrieved endpoint throw new ResourceInvalidStateException( $"Endpoint {endpointId} has no supervisor"); } // Get iotedge device var deviceId = SupervisorModelEx.ParseDeviceId(supervisorId, out _); // Query for the publisher in the same edge device var query = "SELECT * FROM devices.modules WHERE " + $"properties.reported.{TwinProperty.Type} = '{IdentityType.Publisher}' " + $"AND deviceId = '{deviceId}'"; var devices = await _iothub.QueryAllDeviceTwinsAsync(query, ct); device = devices.SingleOrDefault(); if (device == null) { throw new ResourceNotFoundException( $"No publisher found for {endpointId} in {deviceId}"); } var publisherId = PublisherModelEx.CreatePublisherId( device.Id, device.ModuleId); return(publisherId, endpoint.Registration.Endpoint); }
/// <summary> /// Helper to create fixtures /// </summary> /// <param name="site"></param> /// <param name="discoverer"></param> /// <param name="existing"></param> /// <param name="found"></param> /// <param name="registry"></param> /// <param name="countDevices"></param> /// <param name="fixup"></param> /// <param name="disable"></param> private void CreateFixtures(out string site, out string discoverer, out string supervisor, out string publisher, out string gateway, out List <ApplicationRegistrationModel> existing, out List <DiscoveryEventModel> found, out IoTHubServices registry, int countDevices = -1, Func <ApplicationRegistrationModel, ApplicationRegistrationModel> fixup = null, bool disable = false) { var fix = new Fixture(); // Create template applications and endpoints fix.Customizations.Add(new TypeRelay(typeof(VariantValue), typeof(VariantValue))); fix.Behaviors.OfType <ThrowingRecursionBehavior>().ToList() .ForEach(b => fix.Behaviors.Remove(b)); fix.Behaviors.Add(new OmitOnRecursionBehavior()); var sitex = site = fix.Create <string>(); gateway = fix.Create <string>(); var Gateway = (new GatewayModel { SiteId = site, Id = gateway }.ToGatewayRegistration().ToDeviceTwin(), new DeviceModel { Id = gateway }); var module = fix.Create <string>(); var discovererx = discoverer = DiscovererModelEx.CreateDiscovererId(gateway, module); var Discoverer = (new DiscovererModel { SiteId = site, Id = discovererx }.ToDiscovererRegistration().ToDeviceTwin(_serializer), new DeviceModel { Id = gateway, ModuleId = module }); module = fix.Create <string>(); var supervisorx = supervisor = SupervisorModelEx.CreateSupervisorId(gateway, module); var Supervisor = (new SupervisorModel { SiteId = site, Id = supervisorx }.ToSupervisorRegistration().ToDeviceTwin(_serializer), new DeviceModel { Id = gateway, ModuleId = module }); module = fix.Create <string>(); var publisherx = publisher = PublisherModelEx.CreatePublisherId(gateway, module); var Publisher = (new PublisherModel { SiteId = site, Id = publisherx }.ToPublisherRegistration().ToDeviceTwin(_serializer), new DeviceModel { Id = gateway, ModuleId = module }); var template = fix .Build <ApplicationRegistrationModel>() .Without(x => x.Application) .Do(c => c.Application = fix .Build <ApplicationInfoModel>() .Without(x => x.NotSeenSince) .With(x => x.SiteId, sitex) .With(x => x.DiscovererId, discovererx) .Create()) .Without(x => x.Endpoints) .Do(c => c.Endpoints = fix .Build <EndpointRegistrationModel>() .With(x => x.SiteId, sitex) .With(x => x.DiscovererId, discovererx) .With(x => x.SupervisorId, supervisorx) .CreateMany(5) .ToList()) .CreateMany(5) .ToList(); template.ForEach(a => a.Application.ApplicationId = ApplicationInfoModelEx.CreateApplicationId(a.Application) ); // Create discovery results from template var i = 0; var now = DateTime.UtcNow; found = template .SelectMany(a => a.Endpoints.Select( e => new DiscoveryEventModel { Application = a.Application, Registration = e, Index = i++, TimeStamp = now })) .ToList(); // Clone and fixup existing applications as per test case existing = template .Select(e => e.Clone()) .Select(fixup ?? (a => a)) .ToList(); // and fill registry with them... var appdevices = existing .Select(a => a.Application.ToApplicationRegistration(disable)) .Select(a => a.ToDeviceTwin(_serializer)) .Select(d => (d, new DeviceModel { Id = d.Id })); var epdevices = existing .SelectMany(a => a.Endpoints .Select(e => new EndpointInfoModel { ApplicationId = a.Application.ApplicationId, Registration = e }.ToEndpointRegistration(_serializer, disable)) .Select(e => e.ToDeviceTwin(_serializer))) .Select(d => (d, new DeviceModel { Id = d.Id })); appdevices = appdevices.Concat(epdevices); if (countDevices != -1) { appdevices = appdevices.Take(countDevices); } registry = IoTHubServices.Create(appdevices .Concat(Gateway.YieldReturn()) .Concat(Discoverer.YieldReturn()) .Concat(Supervisor.YieldReturn()) .Concat(Publisher.YieldReturn())); }
public void ProcessDiscoveryWithNoResultsAndNoExistingApplications() { var found = new List <DiscoveryEventModel>(); var fix = new Fixture(); var gateway = fix.Create <string>(); var Gateway = (new GatewayModel { Id = gateway }.ToGatewayRegistration().ToDeviceTwin(), new DeviceModel { Id = gateway }); var module = fix.Create <string>(); var discoverer = DiscovererModelEx.CreateDiscovererId(gateway, module); var Discoverer = (new DiscovererModel { Id = discoverer }.ToDiscovererRegistration().ToDeviceTwin(_serializer), new DeviceModel { Id = gateway, ModuleId = module }); module = fix.Create <string>(); var supervisor = SupervisorModelEx.CreateSupervisorId(gateway, module); var Supervisor = (new SupervisorModel { Id = supervisor }.ToSupervisorRegistration().ToDeviceTwin(_serializer), new DeviceModel { Id = gateway, ModuleId = module }); module = fix.Create <string>(); var publisher = PublisherModelEx.CreatePublisherId(gateway, module); var Publisher = (new PublisherModel { Id = publisher }.ToPublisherRegistration().ToDeviceTwin(_serializer), new DeviceModel { Id = gateway, ModuleId = module }); var registry = IoTHubServices.Create(Gateway.YieldReturn() // Single device .Append(Discoverer) .Append(Supervisor) .Append(Publisher)); using (var mock = AutoMock.GetLoose(builder => { // Setup builder.RegisterInstance(registry).As <IIoTHubTwinServices>(); builder.RegisterType <ApplicationTwins>().As <IApplicationRepository>(); builder.RegisterType <DiscovererRegistry>().As <IDiscovererRegistry>(); builder.RegisterType <SupervisorRegistry>().As <ISupervisorRegistry>(); builder.RegisterType <PublisherRegistry>().As <IPublisherRegistry>(); builder.RegisterType <GatewayRegistry>().As <IGatewayRegistry>(); builder.RegisterType <ApplicationRegistry>().As <IApplicationBulkProcessor>(); builder.RegisterType <EndpointRegistry>().As <IEndpointBulkProcessor>(); })) { var service = mock.Create <DiscoveryProcessor>(); // Run service.ProcessDiscoveryResultsAsync(discoverer, new DiscoveryResultModel(), found).Wait(); // Assert Assert.Single(registry.Devices); Assert.Equal(gateway, registry.Devices.First().Device.Id); } }