Пример #1
0
        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);
        }
Пример #2
0
 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);
 }