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); } }
/// <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); }