コード例 #1
0
 /// <summary>
 /// Notify discovery / registration callbacks
 /// </summary>
 /// <param name="siteId"></param>
 /// <param name="supervisorId"></param>
 /// <param name="result"></param>
 /// <param name="exception"></param>
 /// <returns></returns>
 private async Task CallDiscoveryCallbacksAsync(string siteId,
                                                string supervisorId, DiscoveryResultModel result, Exception exception)
 {
     try {
         var callbacks = result?.DiscoveryConfig?.Callbacks;
         if (callbacks == null || callbacks.Count == 0)
         {
             return;
         }
         await _client.CallAsync(JToken.FromObject(
                                     new {
             id = result.Id,
             supervisorId,
             siteId = siteId ?? supervisorId,
             result = new {
                 config      = result.DiscoveryConfig,
                 diagnostics = exception != null ?
                               JToken.FromObject(exception) : result.Diagnostics
             }
         }),
                                 callbacks.ToArray());
     }
     catch (Exception ex) {
         _logger.Debug(ex, "Failed to notify callbacks. Continue...");
         // Continue...
     }
 }
コード例 #2
0
 /// <inheritdoc/>
 public async Task ProcessDiscoveryResultsAsync(string discovererId,
                                                DiscoveryResultModel result, IEnumerable <DiscoveryEventModel> events)
 {
     await _client.ProcessDiscoveryResultsAsync(discovererId,
                                                new DiscoveryResultListApiModel {
         Result = result.Map <DiscoveryResultApiModel>(),
         Events = events.Map <List <DiscoveryEventApiModel> >()
     });
 }
コード例 #3
0
        /// <inheritdoc/>
        public async Task ProcessDiscoveryResultsAsync(string discovererId, DiscoveryResultModel result,
                                                       IEnumerable <DiscoveryEventModel> events)
        {
            if (string.IsNullOrEmpty(discovererId))
            {
                throw new ArgumentNullException(nameof(discovererId));
            }

            var gatewayId = DiscovererModelEx.ParseDeviceId(discovererId, out _);

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }
            if (events == null)
            {
                throw new ArgumentNullException(nameof(events));
            }
            if ((result.RegisterOnly ?? false) && !events.Any())
            {
                return;
            }

            var sites = events.Select(e => e.Application.SiteId).Distinct();

            if (sites.Count() > 1)
            {
                throw new ArgumentException("Unexpected number of sites in discovery");
            }
            var siteId  = sites.SingleOrDefault() ?? gatewayId;
            var gateway = await _gateways.GetGatewayAsync(gatewayId);

            //
            // Merge in global discovery configuration into the one sent
            // by the discoverer.
            //
            if (result.DiscoveryConfig == null)
            {
                // Use global discovery configuration
                result.DiscoveryConfig = gateway.Modules?.Discoverer?.DiscoveryConfig;
            }
            else
            {
                if (result.DiscoveryConfig.ActivationFilter == null)
                {
                    // Use global activation filter
                    result.DiscoveryConfig.ActivationFilter =
                        gateway.Modules?.Discoverer?.DiscoveryConfig?.ActivationFilter;
                }
            }

            // Process discovery events
            await _applications.ProcessDiscoveryEventsAsync(siteId, discovererId,
                                                            gateway.Modules?.Supervisor?.Id, result, events);
        }
コード例 #4
0
 /// <summary>
 /// Add another discovery from discoverer
 /// </summary>
 /// <param name="model"></param>
 /// <returns></returns>
 public void Enqueue(DiscoveryEventModel model)
 {
     _maxIndex = Math.Max(model.Index, _maxIndex);
     if (model.Registration != null)
     {
         _endpoints.Add(model);
     }
     else
     {
         Result = model.Result ?? new DiscoveryResultModel();
     }
 }
コード例 #5
0
        /// <inheritdoc/>
        public async Task ProcessDiscoveryEventsAsync(IEnumerable <EndpointInfoModel> newEndpoints,
                                                      DiscoveryResultModel result, string discovererId, string supervisorId,
                                                      string applicationId, bool hardDelete)
        {
            if (newEndpoints == null)
            {
                throw new ArgumentNullException(nameof(newEndpoints));
            }

            var context = result.Context.Validate();

            var found = newEndpoints
                        .Select(e => e.ToEndpointRegistration(_serializer, false,
                                                              discovererId, supervisorId))
                        .ToList();

            var existing = Enumerable.Empty <EndpointRegistration>();

            if (!string.IsNullOrEmpty(applicationId))
            {
                // Merge with existing endpoints of the application
                existing = await GetEndpointsAsync(applicationId, true);
            }

            var remove = new HashSet <EndpointRegistration>(existing,
                                                            EndpointRegistrationEx.Logical);
            var add = new HashSet <EndpointRegistration>(found,
                                                         EndpointRegistrationEx.Logical);
            var unchange = new HashSet <EndpointRegistration>(existing,
                                                              EndpointRegistrationEx.Logical);
            var change = new HashSet <EndpointRegistration>(found,
                                                            EndpointRegistrationEx.Logical);

            unchange.IntersectWith(add);
            change.IntersectWith(remove);
            remove.ExceptWith(found);
            add.ExceptWith(existing);

            var added     = 0;
            var updated   = 0;
            var unchanged = 0;
            var removed   = 0;

            if (!(result.RegisterOnly ?? false))
            {
                // Remove or disable an endpoint
                foreach (var item in remove)
                {
                    try {
                        // Only touch applications the discoverer owns.
                        if (item.DiscovererId == discovererId)
                        {
                            if (hardDelete)
                            {
                                var device = await _iothub.GetAsync(item.DeviceId);

                                // First we update any registration
                                var existingEndpoint = device.ToEndpointRegistration(false);
                                if (!string.IsNullOrEmpty(existingEndpoint.SupervisorId))
                                {
                                    await ClearSupervisorTwinSecretAsync(device.Id,
                                                                         existingEndpoint.SupervisorId);
                                }
                                // Then hard delete...
                                await _iothub.DeleteAsync(item.DeviceId);

                                await _broker.NotifyAllAsync(l => l.OnEndpointDeletedAsync(context,
                                                                                           item.DeviceId, item.ToServiceModel()));
                            }
                            else if (!(item.IsDisabled ?? false))
                            {
                                var endpoint = item.ToServiceModel();
                                var update   = endpoint.ToEndpointRegistration(_serializer, true);
                                await _iothub.PatchAsync(item.Patch(update, _serializer), true);

                                await _broker.NotifyAllAsync(
                                    l => l.OnEndpointDisabledAsync(context, endpoint));
                            }
                            else
                            {
                                unchanged++;
                                continue;
                            }
                            removed++;
                        }
                        else
                        {
                            // Skip the ones owned by other supervisors
                            unchanged++;
                        }
                    }
                    catch (Exception ex) {
                        unchanged++;
                        _logger.Error(ex, "Exception during discovery removal.");
                    }
                }
            }

            // Update endpoints that were disabled
            foreach (var exists in unchange)
            {
                try {
                    if (exists.DiscovererId == null || exists.DiscovererId == discovererId ||
                        (exists.IsDisabled ?? false))
                    {
                        // Get the new one we will patch over the existing one...
                        var patch = change.First(x =>
                                                 EndpointRegistrationEx.Logical.Equals(x, exists));
                        if (exists.Activated ?? false)
                        {
                            patch.ActivationState = exists.ActivationState;
                        }
                        else
                        {
                            await ApplyActivationFilterAsync(result.DiscoveryConfig?.ActivationFilter,
                                                             patch, context);
                        }
                        if (exists != patch)
                        {
                            await _iothub.PatchAsync(exists.Patch(patch, _serializer), true);

                            var endpoint = patch.ToServiceModel();

                            // await _broker.NotifyAllAsync(
                            //     l => l.OnEndpointUpdatedAsync(context, endpoint));
                            if (exists.IsDisabled ?? false)
                            {
                                await _broker.NotifyAllAsync(
                                    l => l.OnEndpointEnabledAsync(context, endpoint));
                            }
                            updated++;
                            continue;
                        }
                    }
                    unchanged++;
                }
                catch (Exception ex) {
                    unchanged++;
                    _logger.Error(ex, "Exception during update.");
                }
            }

            // Add endpoint
            foreach (var item in add)
            {
                try {
                    await ApplyActivationFilterAsync(result.DiscoveryConfig?.ActivationFilter,
                                                     item, context);

                    await _iothub.CreateAsync(item.ToDeviceTwin(_serializer), true);

                    var endpoint = item.ToServiceModel();
                    await _broker.NotifyAllAsync(l => l.OnEndpointNewAsync(context, endpoint));

                    await _broker.NotifyAllAsync(l => l.OnEndpointEnabledAsync(context, endpoint));

                    added++;
                }
                catch (Exception ex) {
                    unchanged++;
                    _logger.Error(ex, "Exception adding endpoint from discovery.");
                }
            }

            if (added != 0 || removed != 0)
            {
                _logger.Information("processed endpoint results: {added} endpoints added, {updated} " +
                                    "updated, {removed} removed or disabled, and {unchanged} unchanged.",
                                    added, updated, removed, unchanged);
            }
        }
コード例 #6
0
 /// <inheritdoc/>
 public Task ProcessDiscoveryEventsAsync(string siteId, string supervisorId,
                                         DiscoveryResultModel result, IEnumerable <DiscoveryEventModel> events)
 {
     return(Task.CompletedTask);
 }
コード例 #7
0
 /// <inheritdoc/>
 public Task ProcessDiscoveryEventsAsync(IEnumerable <EndpointInfoModel> found,
                                         DiscoveryResultModel context, string supervisorId, string applicationId,
                                         bool hardDelete)
 {
     return(Task.CompletedTask);
 }
コード例 #8
0
        /// <inheritdoc/>
        public async Task ProcessDiscoveryResultsAsync(string supervisorId, DiscoveryResultModel result,
                                                       IEnumerable <DiscoveryEventModel> events)
        {
            if (string.IsNullOrEmpty(supervisorId))
            {
                throw new ArgumentNullException(nameof(supervisorId));
            }
            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }
            if (events == null)
            {
                throw new ArgumentNullException(nameof(events));
            }
            if ((result.RegisterOnly ?? false) && !events.Any())
            {
                return;
            }
            var sites = events.Select(e => e.Application.SiteId).Distinct();

            if (sites.Count() > 1)
            {
                throw new ArgumentException("Unexpected number of sites in discovery");
            }
            var siteId = sites.SingleOrDefault() ?? supervisorId;

            try {
                //
                // Merge in global discovery configuration into the one sent
                // by the supervisor.
                //
                var supervisor = await _supervisors.GetSupervisorAsync(supervisorId, false);

                if (result.DiscoveryConfig == null)
                {
                    // Use global discovery configuration
                    result.DiscoveryConfig = supervisor.DiscoveryConfig;
                }
                else
                {
                    if (supervisor.DiscoveryConfig?.Callbacks != null)
                    {
                        if (result.DiscoveryConfig.Callbacks == null)
                        {
                            result.DiscoveryConfig.Callbacks =
                                supervisor.DiscoveryConfig.Callbacks;
                        }
                        else
                        {
                            result.DiscoveryConfig.Callbacks.AddRange(
                                supervisor.DiscoveryConfig.Callbacks);
                        }
                    }
                    if (result.DiscoveryConfig.ActivationFilter == null)
                    {
                        // Use global activation filter
                        result.DiscoveryConfig.ActivationFilter =
                            supervisor.DiscoveryConfig?.ActivationFilter;
                    }
                }

                // Process discovery events
                await _applications.ProcessDiscoveryEventsAsync(siteId, supervisorId, result, events);

                // Notify callbacks
                await CallDiscoveryCallbacksAsync(siteId, supervisorId, result, null);
            }
            catch (Exception ex) {
                // Notify callbacks
                await CallDiscoveryCallbacksAsync(siteId, supervisorId, result, ex);

                throw ex;
            }
        }