public async Task <List <IoTHubDeviceInfo> > GetDeviceList(string devEUI, string gatewayId, string devNonce, string devAddr, ILogger log = null) { var results = new List <IoTHubDeviceInfo>(); if (devEUI != null) { var joinInfo = await this.TryGetJoinInfoAndValidateAsync(devEUI, gatewayId, log); // OTAA join using (var deviceCache = new LoRaDeviceCache(this.cacheStore, devEUI, gatewayId)) { var cacheKeyDevNonce = string.Concat(devEUI, ":", devNonce); var lockKeyDevNonce = string.Concat(cacheKeyDevNonce, ":joinlockdevnonce"); if (this.cacheStore.StringSet(cacheKeyDevNonce, devNonce, TimeSpan.FromMinutes(5), onlyIfNotExists: true)) { var iotHubDeviceInfo = new IoTHubDeviceInfo { DevEUI = devEUI, PrimaryKey = joinInfo.PrimaryKey }; results.Add(iotHubDeviceInfo); if (await deviceCache.TryToLockAsync()) { this.cacheStore.KeyDelete(devEUI); log?.LogDebug("Removed key '{key}':{gwid}", devEUI, gatewayId); } else { log?.LogWarning("Failed to acquire lock for '{key}'", devEUI); } } else { log?.LogDebug("dev nonce already used. Ignore request '{key}':{gwid}", devEUI, gatewayId); throw new DeviceNonceUsedException(); } } } else if (devAddr != null) { // ABP or normal message // TODO check for sql injection devAddr = devAddr.Replace('\'', ' '); var devAddrCache = new LoRaDevAddrCache(this.cacheStore, this.registryManager, log, gatewayId); if (await devAddrCache.TryTakeDevAddrUpdateLock(devAddr)) { try { if (devAddrCache.TryGetInfo(devAddr, out List <DevAddrCacheInfo> devAddressesInfo)) { for (int i = 0; i < devAddressesInfo.Count; i++) { if (!string.IsNullOrEmpty(devAddressesInfo[i].DevEUI)) { // device was not yet populated if (!string.IsNullOrEmpty(devAddressesInfo[i].PrimaryKey)) { results.Add(devAddressesInfo[i]); } else { // we need to load the primaryKey from IoTHub // Add a lock loadPrimaryKey get lock get devAddressesInfo[i].PrimaryKey = await this.LoadPrimaryKeyAsync(devAddressesInfo[i].DevEUI); results.Add(devAddressesInfo[i]); devAddrCache.StoreInfo(devAddressesInfo[i]); } // even if we fail to acquire the lock we wont enter in the next condition as devaddressinfo is not null } } } // if the cache results are null, we query the IoT Hub. // if the device is not found is the cache we query, if there was something, it is probably not our device. if (results.Count == 0 && devAddressesInfo == null) { if (await devAddrCache.TryTakeDevAddrUpdateLock(devAddr)) { try { var query = this.registryManager.CreateQuery($"SELECT * FROM devices WHERE properties.desired.DevAddr = '{devAddr}' OR properties.reported.DevAddr ='{devAddr}'", 100); int resultCount = 0; while (query.HasMoreResults) { var page = await query.GetNextAsTwinAsync(); foreach (var twin in page) { if (twin.DeviceId != null) { var device = await this.registryManager.GetDeviceAsync(twin.DeviceId); var iotHubDeviceInfo = new DevAddrCacheInfo { DevAddr = devAddr, DevEUI = twin.DeviceId, PrimaryKey = device.Authentication.SymmetricKey.PrimaryKey, GatewayId = twin.GetGatewayID(), NwkSKey = twin.GetNwkSKey(), LastUpdatedTwins = twin.Properties.Desired.GetLastUpdated() }; results.Add(iotHubDeviceInfo); devAddrCache.StoreInfo((DevAddrCacheInfo)iotHubDeviceInfo); } resultCount++; } } // todo save when not our devaddr if (resultCount == 0) { devAddrCache.StoreInfo(new DevAddrCacheInfo() { DevAddr = devAddr, DevEUI = string.Empty }); } } finally { devAddrCache.ReleaseDevAddrUpdateLock(devAddr); } } } } finally { devAddrCache.ReleaseDevAddrUpdateLock(devAddr); } } } else { throw new Exception("Missing devEUI or devAddr"); } return(results); }
public SyncDevAddrCache(LoRaDevAddrCache loRaDevAddrCache, RegistryManager registryManager) { this.loRaDevAddrCache = loRaDevAddrCache; this.registryManager = registryManager; }
public async Task StartAsync(CancellationToken cancellationToken) { LoRaDevAddrCache loRaDevAddrCache = new LoRaDevAddrCache(this.cacheStore, this.registryManager, this.logger, null); await Task.FromResult(0); }