Example #1
0
        async Task Load()
        {
            try
            {
                // If device was not found, search in the device API, updating local cache
                Logger.Log(this.devAddr, "querying the registry for device", LogLevel.Debug);

                SearchDevicesResult searchDeviceResult = null;
                try
                {
                    searchDeviceResult = await this.loRaDeviceAPIService.SearchByDevAddrAsync(this.devAddr);

                    // If device was not found, search in the device API, updating local cache
                    Logger.Log(this.devAddr, $"querying the registry for devices by devAddr {this.devAddr} found {searchDeviceResult.Devices?.Count ?? 0} devices", LogLevel.Debug);
                }
                catch (Exception ex)
                {
                    Logger.Log(this.devAddr, $"error searching device for payload. {ex.Message}", LogLevel.Error);
                    throw;
                }

                this.SetState(LoaderState.CreatingDeviceInstances);
                var createdDevices = await this.CreateDevicesAsync(searchDeviceResult.Devices);

                // Dispatch queued requests to created devices
                // those without a matching device will receive "failed" notification
                lock (this.queueLock)
                {
                    this.SetState(LoaderState.DispatchingQueuedItems);

                    this.DispatchQueuedItems(createdDevices);

                    foreach (var device in createdDevices)
                    {
                        this.registerDeviceAction(device);
                    }

                    this.CreatedDevicesCount = createdDevices.Count;

                    this.SetState(LoaderState.Finished);
                }
            }
            catch (Exception ex)
            {
                Logger.Log(this.devAddr, $"failed to create one or more devices. {ex.Message}", LogLevel.Error);
                this.NotifyQueueItemsDueToError();
                throw;
            }
            finally
            {
                this.SetState(LoaderState.Finished);
            }
        }
        internal async Task LoadAsync()
        {
            try
            {
                // If device was not found, search in the device API, updating local cache
                this.logger.LogDebug("querying the registry for device");

                SearchDevicesResult searchDeviceResult = null;
                try
                {
                    searchDeviceResult = await this.loRaDeviceAPIService.SearchByDevAddrAsync(this.devAddr);

                    // If device was not found, search in the device API, updating local cache
                    this.logger.LogDebug($"querying the registry for devices by devAddr {this.devAddr} found {searchDeviceResult.Devices?.Count ?? 0} devices");
                }
                catch (Exception ex)
                {
                    throw new LoRaProcessingException("Error when searching device for payload.", ex);
                }

                SetState(LoaderState.CreatingDeviceInstances);
                await CreateDevicesAsync(searchDeviceResult.Devices);

                // Dispatch queued requests to created devices
                // those without a matching device will receive "failed" notification
                lock (this.queueLock)
                {
                    SetState(LoaderState.DispatchingQueuedItems);

                    DispatchQueuedItems();

                    SetState(LoaderState.Finished);
                }
            }
            catch (Exception)
            {
                NotifyQueueItemsDueToError(LoRaDeviceRequestFailedReason.ApplicationError);
                throw;
            }
            finally
            {
                SetState(LoaderState.Finished);
            }
        }
Example #3
0
        /// <summary>
        /// Finds a device based on the <see cref="LoRaPayloadData"/>
        /// </summary>
        public async Task <LoRaDevice> GetDeviceForPayloadAsync(LoRaPayloadData loraPayload)
        {
            var devAddr = ConversionHelper.ByteArrayToString(loraPayload.DevAddr.ToArray());
            var devicesMatchingDevAddr = this.InternalGetCachedDevicesForDevAddr(devAddr);

            // If already in cache, return quickly
            if (devicesMatchingDevAddr.Count > 0)
            {
                var matchingDevice = devicesMatchingDevAddr.Values.FirstOrDefault(x => this.IsValidDeviceForPayload(x, loraPayload, logError: false));
                if (matchingDevice != null)
                {
                    if (matchingDevice.IsOurDevice)
                    {
                        Logger.Log(matchingDevice.DevEUI, "device in cache", LogLevel.Debug);
                        return(matchingDevice);
                    }
                    else
                    {
                        Logger.Log(matchingDevice.DevEUI ?? devAddr, $"device is not our device, ignore message", LogLevel.Information);
                        return(null);
                    }
                }
            }

            // If device was not found, search in the device API, updating local cache
            Logger.Log(devAddr, "querying the registry for device", LogLevel.Information);

            SearchDevicesResult searchDeviceResult = null;

            try
            {
                searchDeviceResult = await this.loRaDeviceAPIService.SearchByDevAddrAsync(devAddr);
            }
            catch (Exception ex)
            {
                Logger.Log(devAddr, $"Error searching device for payload. {ex.Message}", LogLevel.Error);
                return(null);
            }

            if (searchDeviceResult?.Devices != null)
            {
                foreach (var foundDevice in searchDeviceResult.Devices)
                {
                    var loRaDevice = this.deviceFactory.Create(foundDevice);
                    if (loRaDevice != null && devicesMatchingDevAddr.TryAdd(loRaDevice.DevEUI, loRaDevice))
                    {
                        try
                        {
                            // Calling initialize async here to avoid making async calls in the concurrent dictionary
                            // Since only one device will be added, we guarantee that initialization only happens once
                            if (await loRaDevice.InitializeAsync())
                            {
                                loRaDevice.IsOurDevice = string.IsNullOrEmpty(loRaDevice.GatewayID) || string.Equals(loRaDevice.GatewayID, this.configuration.GatewayID, StringComparison.InvariantCultureIgnoreCase);

                                // once added, call initializers
                                foreach (var initializer in this.initializers)
                                {
                                    initializer.Initialize(loRaDevice);
                                }

                                if (loRaDevice.DevEUI != null)
                                {
                                    Logger.Log(loRaDevice.DevEUI, "device added to cache", LogLevel.Debug);
                                }

                                // TODO: stop if we found the matching device?
                                // If we continue we can cache for later usage, but then do it in a new thread
                                if (this.IsValidDeviceForPayload(loRaDevice, loraPayload, logError: false))
                                {
                                    if (!loRaDevice.IsOurDevice)
                                    {
                                        Logger.Log(loRaDevice.DevEUI ?? devAddr, $"device is not our device, ignore message", LogLevel.Information);
                                        return(null);
                                    }

                                    return(loRaDevice);
                                }
                            }
                            else
                            {
                                // could not initialize device
                                // remove it from cache since it does not have required properties
                                devicesMatchingDevAddr.TryRemove(loRaDevice.DevEUI, out _);
                            }
                        }
                        catch (Exception ex)
                        {
                            // problem initializing the device (get twin timeout, etc)
                            // remove it from the cache
                            Logger.Log(loRaDevice.DevEUI ?? devAddr, $"Error initializing device {loRaDevice.DevEUI}. {ex.Message}", LogLevel.Error);

                            devicesMatchingDevAddr.TryRemove(loRaDevice.DevEUI, out _);
                        }
                    }
                }

                // try now with updated cache
                var matchingDevice = devicesMatchingDevAddr.Values.FirstOrDefault(x => this.IsValidDeviceForPayload(x, loraPayload, logError: true));
                if (matchingDevice != null && !matchingDevice.IsOurDevice)
                {
                    Logger.Log(matchingDevice.DevEUI ?? devAddr, $"device is not our device, ignore message", LogLevel.Information);
                    return(null);
                }

                return(matchingDevice);
            }

            return(null);
        }