public async Task When_Called_By_Multiple_Gateways_Should_Return_Closest()
        {
            var        devEUI = TestEui.GenerateDevEui();
            const uint fcntUp = 1;

            var req1 = new FunctionBundlerRequest()
            {
                GatewayId = "gateway1", ClientFCntUp = fcntUp, Rssi = -180
            };
            var pipeline1 = new FunctionBundlerPipelineExecuter(new IFunctionBundlerExecutionItem[] { this.preferredGatewayExecutionItem }, devEUI, req1);
            var t1        = Task.Run(() => this.preferredGatewayExecutionItem.ExecuteAsync(pipeline1));

            var req2 = new FunctionBundlerRequest()
            {
                GatewayId = "gateway2", ClientFCntUp = fcntUp, Rssi = -179
            };
            var pipeline2 = new FunctionBundlerPipelineExecuter(new IFunctionBundlerExecutionItem[] { this.preferredGatewayExecutionItem }, devEUI, req2);
            var t2        = Task.Run(() => this.preferredGatewayExecutionItem.ExecuteAsync(pipeline2));

            var req3 = new FunctionBundlerRequest()
            {
                GatewayId = "gateway3", ClientFCntUp = fcntUp, Rssi = -39
            };
            var pipeline3 = new FunctionBundlerPipelineExecuter(new IFunctionBundlerExecutionItem[] { this.preferredGatewayExecutionItem }, devEUI, req3);
            var t3        = Task.Run(() => this.preferredGatewayExecutionItem.ExecuteAsync(pipeline3));

            await Task.WhenAll(t1, t2, t3);

            foreach (var reqAndPipeline in new[] { (t1, pipeline1), (t2, pipeline2), (t3, pipeline3) })
        public async Task When_PerformNeededSyncs_Fails_Should_Release_Lock(string lockToTake)
        {
            var devAddrcache = new LoRaDevAddrCache(this.cache, null, null);
            await LockDevAddrHelper.PrepareLocksForTests(this.cache, lockToTake == null?null : new[] { lockToTake });

            var managerInput = new List <DevAddrCacheInfo> {
                new DevAddrCacheInfo()
                {
                    DevEUI = TestEui.GenerateDevEui(), DevAddr = CreateDevAddr()
                }
            };
            var registryManagerMock = InitRegistryManager(managerInput);

            registryManagerMock.Setup(x => x.CreateQuery(It.IsAny <string>())).Throws(new RedisException(string.Empty));
            await devAddrcache.PerformNeededSyncs(registryManagerMock.Object);

            // When doing a full update, the FullUpdateKey lock should be reset to 1min, the GlobalDevAddrUpdateKey should be gone
            // When doing a partial update, the GlobalDevAddrUpdateKey should be gone
            switch (lockToTake)
            {
            case FullUpdateKey:
                Assert.Null(await this.cache.GetObjectTTL(GlobalDevAddrUpdateKey));
                break;

            case null:
                var nextFullUpdate = await this.cache.GetObjectTTL(FullUpdateKey);

                Assert.True(nextFullUpdate <= TimeSpan.FromMinutes(1));
                Assert.Null(await this.cache.GetObjectTTL(GlobalDevAddrUpdateKey));
                break;

            default: throw new InvalidOperationException("invalid test case");
            }
        }
        public async Task MessageDeduplication_DifferentDevices_Allowed()
        {
            var gateway1Id = NewUniqueEUI64();
            var gateway2Id = NewUniqueEUI64();
            var dev1EUI    = TestEui.GenerateDevEui();
            var dev2EUI    = TestEui.GenerateDevEui();

            var result = await this.deduplicationExecutionItem.GetDuplicateMessageResultAsync(dev1EUI, gateway1Id, 1, 1);

            Assert.False(result.IsDuplicate);
            Assert.Equal(gateway1Id, result.GatewayId);

            result = await this.deduplicationExecutionItem.GetDuplicateMessageResultAsync(dev1EUI, gateway2Id, 2, 1);

            Assert.False(result.IsDuplicate);
            Assert.Equal(gateway2Id, result.GatewayId);

            result = await this.deduplicationExecutionItem.GetDuplicateMessageResultAsync(dev2EUI, gateway1Id, 1, 1);

            Assert.False(result.IsDuplicate);
            Assert.Equal(gateway1Id, result.GatewayId);

            result = await this.deduplicationExecutionItem.GetDuplicateMessageResultAsync(dev2EUI, gateway2Id, 2, 1);

            Assert.False(result.IsDuplicate);
            Assert.Equal(gateway2Id, result.GatewayId);
        }
Exemple #4
0
        public async Task FrameCounter_Down_Initial()
        {
            var deviceEUI = TestEui.GenerateDevEui();
            var gatewayId = NewUniqueEUI64();

            var next = await this.fcntCheck.GetNextFCntDownAsync(deviceEUI, gatewayId, 1, 1);

            Assert.Equal(2U, next);
        }
        // This test ensure that if the device has the key within the cache, it should not make any query to iot hub
        public async Task When_Device_Is_Not_Ours_Save_In_Cache_And_Dont_Query_Hub_Again()
        {
            var gatewayId = NewUniqueEUI64();
            var dateTime  = DateTime.UtcNow;
            // In this test we want no updates running
            // initialize locks for test to run correctly
            var lockToTake = new string[2] {
                FullUpdateKey, GlobalDevAddrUpdateKey
            };
            await LockDevAddrHelper.PrepareLocksForTests(this.cache, lockToTake);

            var items        = new List <IoTHubDeviceInfo>();
            var primaryKey   = Convert.ToBase64String(Encoding.UTF8.GetBytes(PrimaryKey));
            var managerInput = new List <DevAddrCacheInfo>();

            for (var i = 0; i < 2; i++)
            {
                managerInput.Add(new DevAddrCacheInfo()
                {
                    DevEUI           = TestEui.GenerateDevEui(),
                    DevAddr          = CreateDevAddr(),
                    GatewayId        = gatewayId,
                    PrimaryKey       = primaryKey,
                    LastUpdatedTwins = dateTime
                });
            }

            var devAddrJoining = CreateDevAddr();

            InitCache(this.cache, managerInput);
            var registryManagerMock = InitRegistryManager(managerInput);

            var deviceGetter = new DeviceGetter(registryManagerMock.Object, this.cache);

            items = await deviceGetter.GetDeviceList(null, gatewayId, new DevNonce(0xABCD), devAddrJoining);

            Assert.Empty(items);
            var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, devAddrJoining));

            Assert.Single(queryResult);
            var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value);

            Assert.Null(resultObject.DevEUI);
            Assert.Null(resultObject.PrimaryKey);
            Assert.Null(resultObject.GatewayId);
            var query2Result = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, devAddrJoining));

            Assert.Single(query2Result);

            // Iot hub should never have been called.
            registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Never, "IoT Hub should not have been called, as the device was present in the cache.");
            registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never, "IoT Hub should not have been called, as the device was present in the cache.");
            // Should not query for the key as key is there
            registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Never);
        }
        public async void DeviceGetter_OTAA_Join()
        {
            var devEui    = TestEui.GenerateDevEui();
            var gatewayId = NewUniqueEUI64();

            var deviceGetter = new DeviceGetter(InitRegistryManager(devEui), new LoRaInMemoryDeviceStore());
            var items        = await deviceGetter.GetDeviceList(devEui, gatewayId, new DevNonce(0xABCD), null);

            Assert.Single(items);
            Assert.Equal(devEui, items[0].DevEUI);
        }
Exemple #7
0
        public async Task FunctionBundler_Multi()
        {
            var gatewayId1 = NewUniqueEUI64();
            var gatewayId2 = NewUniqueEUI64();
            var gatewayId3 = NewUniqueEUI64();
            var gatewayId4 = NewUniqueEUI64();
            var devEUI     = TestEui.GenerateDevEui();

            var requests = new FunctionBundlerRequest[]
            {
                CreateStandardBundlerRequest(gatewayId1),
                CreateStandardBundlerRequest(gatewayId2),
                CreateStandardBundlerRequest(gatewayId3),
                CreateStandardBundlerRequest(gatewayId4)
            };

            foreach (var req in requests)
            {
                await PrepareADRFrames(devEUI, 20, req.AdrRequest);

                req.ClientFCntUp   = req.AdrRequest.FCntUp;
                req.ClientFCntDown = req.AdrRequest.FCntDown;
            }

            var functionBundlerResults = await Task.WhenAll(from req in requests select ExecuteRequest(devEUI, req));

            // only one request should be winning the race
            var winners = 0;
            var dups    = 0;

            foreach (var res in functionBundlerResults)
            {
                if (!res.DeduplicationResult.IsDuplicate)
                {
                    Assert.NotNull(res.AdrResult);
                    Assert.True(res.AdrResult.CanConfirmToDevice);
                    Assert.Equal(res.AdrResult.FCntDown, res.NextFCntDown);
                    Assert.True(res.NextFCntDown.GetValueOrDefault() > 0);
                    winners++;
                }
                else
                {
                    Assert.NotNull(res.AdrResult);
                    Assert.False(res.AdrResult.CanConfirmToDevice);
                    Assert.Equal(0U, res.AdrResult.FCntDown.GetValueOrDefault());
                    Assert.Null(res.NextFCntDown);
                    dups++;
                }
            }

            Assert.Equal(1, winners);
            Assert.Equal(functionBundlerResults.Length - 1, dups);
        }
        // This test simulate a call received by multiple server. It ensures IoT Hub is only queried once.
        public async Task Multi_Gateway_When_DevAddr_Is_Not_In_Cache_Query_Iot_Hub_Only_Once_And_Save_In_Cache()
        {
            var gateway1     = NewUniqueEUI64();
            var gateway2     = NewUniqueEUI64();
            var dateTime     = DateTime.UtcNow;
            var managerInput = new List <DevAddrCacheInfo>();

            for (var i = 0; i < 2; i++)
            {
                managerInput.Add(new DevAddrCacheInfo()
                {
                    DevEUI  = TestEui.GenerateDevEui(),
                    DevAddr = CreateDevAddr()
                });
            }

            var devAddrJoining      = managerInput[0].DevAddr;
            var registryManagerMock = InitRegistryManager(managerInput);

            // In this test we want no updates running
            // initialize locks for test to run correctly
            var lockToTake = new string[2] {
                FullUpdateKey, GlobalDevAddrUpdateKey
            };
            await LockDevAddrHelper.PrepareLocksForTests(this.cache, lockToTake);

            var deviceGetter = new DeviceGetter(registryManagerMock.Object, this.cache);
            // Simulate three queries
            var tasks =
                from gw in new[] { gateway1, gateway2 }
            select Enumerable.Repeat(gw, 2) into gws     // repeat each gateway twice
            from gw in gws
            select deviceGetter.GetDeviceList(null, gw, new DevNonce(0xABCD), devAddrJoining);

            await Task.WhenAll(tasks);

            // If a cache miss it should save it in the redisCache
            var devAddrcache = new LoRaDevAddrCache(this.cache, null, null);
            var queryResult  = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, devAddrJoining));

            Assert.Single(queryResult);
            var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value);

            Assert.Equal(managerInput[0].DevAddr, resultObject.DevAddr);
            Assert.Equal(managerInput[0].GatewayId ?? string.Empty, resultObject.GatewayId);
            Assert.Equal(managerInput[0].DevEUI, resultObject.DevEUI);

            registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>(), It.IsAny <int>()), Times.Once);
            registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never);
            registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Once);
        }
        // This test ensure that if a device is in cache without a key, it get the keys from iot hub and save it
        public async Task Multi_Gateway_When_DevAddr_Is_In_Cache_Without_Key_Should_Not_Query_Iot_Hub_For_Twin_But_Should_Get_Key_And_Update()
        {
            var gatewayId    = NewUniqueEUI64();
            var dateTime     = DateTime.UtcNow;
            var managerInput = new List <DevAddrCacheInfo>();

            for (var i = 0; i < 2; i++)
            {
                managerInput.Add(new DevAddrCacheInfo()
                {
                    DevEUI           = TestEui.GenerateDevEui(),
                    DevAddr          = CreateDevAddr(),
                    GatewayId        = gatewayId,
                    LastUpdatedTwins = dateTime
                });
            }

            var devAddrJoining = managerInput[0].DevAddr;

            InitCache(this.cache, managerInput);
            var registryManagerMock = InitRegistryManager(managerInput);

            // In this test we want no updates running
            // initialize locks for test to run correctly
            var lockToTake = new string[2] {
                FullUpdateKey, GlobalDevAddrUpdateKey
            };
            await LockDevAddrHelper.PrepareLocksForTests(this.cache, lockToTake);

            var deviceGetter = new DeviceGetter(registryManagerMock.Object, this.cache);
            var tasks        =
                from gw in Enumerable.Repeat(gatewayId, 3)
                select deviceGetter.GetDeviceList(null, gw, new DevNonce(0xABCD), devAddrJoining);

            await Task.WhenAll(tasks);

            // Iot hub should never have been called.
            registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Never, "IoT Hub should not have been called, as the device was present in the cache.");
            registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>(), It.IsAny <int>()), Times.Never, "IoT Hub should not have been called, as the device was present in the cache.");
            registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never, "IoT Hub should not have been called, as the device was present in the cache.");
            // Should query for the key as key is missing
            registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Once);
            var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, devAddrJoining));

            Assert.Single(queryResult);
            // The key should have been saved
            var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value);

            Assert.NotNull(resultObject.PrimaryKey);
        }
        // Check that the server perform a full reload if the locking key for full reload is not present
        public async Task When_FullUpdateKey_Is_Not_there_Should_Perform_Full_Reload()
        {
            var gatewayId    = NewUniqueEUI64();
            var dateTime     = DateTime.UtcNow;
            var primaryKey   = Convert.ToBase64String(Encoding.UTF8.GetBytes(PrimaryKey));
            var managerInput = new List <DevAddrCacheInfo>();

            for (var i = 0; i < 5; i++)
            {
                managerInput.Add(new DevAddrCacheInfo()
                {
                    DevEUI    = TestEui.GenerateDevEui(),
                    DevAddr   = CreateDevAddr(),
                    GatewayId = gatewayId,
                });
            }

            var devAddrJoining = managerInput[0].DevAddr;
            // The cache start as empty
            var registryManagerMock = InitRegistryManager(managerInput);

            // initialize locks for test to run correctly
            await LockDevAddrHelper.PrepareLocksForTests(this.cache);

            var items = new List <IoTHubDeviceInfo>();

            var deviceGetter = new DeviceGetter(registryManagerMock.Object, this.cache);

            items = await deviceGetter.GetDeviceList(null, gatewayId, new DevNonce(0xABCD), devAddrJoining);

            Assert.Single(items);
            // Iot hub should never have been called.
            registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Once);
            registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never);
            // We expect to query for the key once (the device with an active connection)
            registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Once);

            // we expect the devices are saved
            for (var i = 1; i < 5; i++)
            {
                var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, managerInput[i].DevAddr));
                Assert.Single(queryResult);
                var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value);
                Assert.Equal(managerInput[i].GatewayId, resultObject.GatewayId);
                Assert.Equal(managerInput[i].DevEUI, resultObject.DevEUI);
            }
        }
Exemple #11
0
        public async Task ADR_First_Entry_Device_Reset()
        {
            var deviceEUI = TestEui.GenerateDevEui();
            var gatewayId = NewUniqueEUI64();

            var req = CreateStandardADRRequest(gatewayId);

            var result = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req);

            Assert.NotNull(result);
            Assert.Equal(1, result.NumberOfFrames);
            Assert.True(result.CanConfirmToDevice);

            Assert.Equal(0, result.TxPower);
            Assert.Equal(req.DataRate, result.DataRate);
            Assert.Equal(1, result.NbRepetition);
        }
Exemple #12
0
        public async Task ADR_MultiGateway_Full_Frame()
        {
            var deviceEUI = TestEui.GenerateDevEui();

            var gateway1Id = NewUniqueEUI64();
            var gateway2Id = NewUniqueEUI64();

            var req1 = CreateStandardADRRequest(gateway1Id, -10);
            var req2 = CreateStandardADRRequest(gateway2Id, -10);

            var rnd = new Random();

            // add just 1 under the limit to the table
            for (var i = 0; i < LoRaADRTable.FrameCountCaptureCount - 1; i++)
            {
                var res1 = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req1);

                var res2 = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req2);

                var winner = req1.RequiredSnr < req2.RequiredSnr ? gateway2Id : gateway1Id;
                var last   = await this.adrManager.GetLastEntryAsync(deviceEUI);

                Assert.Equal(winner, last.GatewayId);
                Assert.Equal(2U, last.GatewayCount);

                req1.RequiredSnr = rnd.Next(-20, 5);
                req2.RequiredSnr = rnd.Next(-20, 5);
                req2.FCntUp      = ++req1.FCntUp;
                req1.FCntDown    = res1.FCntDown.GetValueOrDefault() > 0 ? res1.FCntDown.Value : req1.FCntDown;
                req2.FCntDown    = res2.FCntDown.GetValueOrDefault() > 0 ? res2.FCntDown.Value : req2.FCntDown;
            }

            req2.FCntUp = ++req1.FCntUp;

            // first one should win
            var result1 = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req1);

            var result2 = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req2);

            Assert.True(result1.CanConfirmToDevice);
            Assert.False(result2.CanConfirmToDevice);

            Assert.Equal(req1.FCntDown + 1, result1.FCntDown);
            Assert.Equal(0U, result2.FCntDown.GetValueOrDefault());
        }
Exemple #13
0
        public async Task FunctionBundler_FCntDown_Only()
        {
            var gatewayId1 = NewUniqueEUI64();
            var devEUI     = TestEui.GenerateDevEui();

            var req = CreateStandardBundlerRequest(gatewayId1);

            req.AdrRequest    = null;
            req.FunctionItems = FunctionBundlerItemType.FCntDown;

            var resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req);

            Assert.NotNull(resp);
            Assert.Null(resp.AdrResult);

            Assert.Null(resp.DeduplicationResult);

            Assert.Equal(req.ClientFCntDown + 1, resp.NextFCntDown);
        }
Exemple #14
0
        public async Task ADR_MultiGateway_Entry_Update()
        {
            var deviceEUI = TestEui.GenerateDevEui();

            var gateway1Id = NewUniqueEUI64();
            var gateway2Id = NewUniqueEUI64();

            var req  = CreateStandardADRRequest(gateway1Id, -10);
            var req2 = CreateStandardADRRequest(gateway2Id, -10);

            _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req);

            _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req2);

            // last entry should have 2 and the id should be from gw1
            var last = await this.adrManager.GetLastEntryAsync(deviceEUI);

            Assert.Equal(2U, last.GatewayCount);
            Assert.Equal(gateway1Id, last.GatewayId);

            // reply
            _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req);

            _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req2);

            last = await this.adrManager.GetLastEntryAsync(deviceEUI);

            Assert.Equal(4U, last.GatewayCount);

            // add new fcnt and change snr for gw2
            req2.FCntUp      = ++req.FCntUp;
            req2.RequiredSnr = -9;
            _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req);

            _ = await this.adrExecutionItem.HandleADRRequest(deviceEUI, req2);

            last = await this.adrManager.GetLastEntryAsync(deviceEUI);

            Assert.Equal(2U, last.GatewayCount);
            Assert.Equal(gateway2Id, last.GatewayId);
            Assert.Equal(-9, last.Snr);
        }
Exemple #15
0
        public ADRTestData()
        {
            // First test not enough entries to send back an answer
            var tableentries = new List <LoRaADRTableEntry>();

            var deviceEuiNotEnoughEntries = TestEui.GenerateDevEui();

            for (uint i = 0; i < 10; i++)
            {
                tableentries.Add(new LoRaADRTableEntry()
                {
                    DevEUI       = deviceEuiNotEnoughEntries,
                    FCnt         = i,
                    GatewayCount = 1,
                    GatewayId    = "mygateway",
                    Snr          = -20
                });
            }

            var radioMetadata = new RadioMetadata(DataRateIndex.DR5, TestUtils.TestRegion.GetDefaultRX2ReceiveWindow(default).Frequency, null);
Exemple #16
0
        public async Task FunctionBundler_All_Functions()
        {
            var gatewayId1 = NewUniqueEUI64();
            var devEUI     = TestEui.GenerateDevEui();

            var req = CreateStandardBundlerRequest(gatewayId1);

            var resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req);

            Assert.NotNull(resp);
            Assert.NotNull(resp.AdrResult);
            Assert.False(resp.AdrResult.CanConfirmToDevice);
            Assert.Equal(1, resp.AdrResult.NumberOfFrames);

            Assert.NotNull(resp.DeduplicationResult);
            Assert.Equal(gatewayId1, resp.DeduplicationResult.GatewayId);
            Assert.False(resp.DeduplicationResult.IsDuplicate);

            Assert.Equal(req.ClientFCntDown + 1, resp.NextFCntDown);
        }
Exemple #17
0
        public async Task FunctionBundler_Adr_Only()
        {
            var gatewayId1 = NewUniqueEUI64();
            var devEUI     = TestEui.GenerateDevEui();

            var req = CreateStandardBundlerRequest(gatewayId1);

            req.FunctionItems = FunctionBundlerItemType.ADR;

            var resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req);

            Assert.NotNull(resp);
            Assert.NotNull(resp.AdrResult);
            Assert.True(resp.AdrResult.CanConfirmToDevice);
            Assert.Equal(req.AdrRequest.DataRate, resp.AdrResult.DataRate);
            Assert.Equal(0, resp.AdrResult.TxPower);
            Assert.Equal(1, resp.AdrResult.NumberOfFrames);

            Assert.Null(resp.DeduplicationResult);
            Assert.Equal(2U, resp.NextFCntDown);
        }
        // Trigger delta update correctly to see if it performs correctly on an empty cache
        public async Task Delta_Update_Perform_Correctly_On_Empty_Cache()
        {
            var gatewayId = NewUniqueEUI64();
            var dateTime  = DateTime.UtcNow;

            var managerInput = new List <DevAddrCacheInfo>();

            for (var i = 0; i < 5; i++)
            {
                managerInput.Add(new DevAddrCacheInfo()
                {
                    DevEUI           = TestEui.GenerateDevEui(),
                    DevAddr          = CreateDevAddr(),
                    GatewayId        = gatewayId,
                    LastUpdatedTwins = dateTime
                });
            }

            var devAddrJoining = managerInput[0].DevAddr;
            // The cache start as empty
            var registryManagerMock = InitRegistryManager(managerInput);

            // initialize locks for test to run correctly
            var locksToTake = new string[1] {
                FullUpdateKey
            };
            await LockDevAddrHelper.PrepareLocksForTests(this.cache, locksToTake);

            var devAddrCache = new LoRaDevAddrCache(this.cache, null, gatewayId);
            await devAddrCache.PerformNeededSyncs(registryManagerMock.Object);

            while (!string.IsNullOrEmpty(this.cache.StringGet(GlobalDevAddrUpdateKey)))
            {
                await Task.Delay(100);
            }

            var foundItem = 0;

            // we expect the devices are saved
            for (var i = 0; i < 5; i++)
            {
                var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, managerInput[i].DevAddr));
                if (queryResult.Length > 0)
                {
                    foundItem++;
                    Assert.Single(queryResult);
                    var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value);
                    Assert.Equal(managerInput[i].GatewayId, resultObject.GatewayId);
                    Assert.Equal(managerInput[i].DevEUI, resultObject.DevEUI);
                }
            }

            // Only two items should be updated by the delta updates
            Assert.Equal(2, foundItem);

            // Iot hub should never have been called.
            registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Once);
            registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never);
            // We expect to query for the key once (the device with an active connection)
            registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Never);
        }
Exemple #19
0
        public async System.Threading.Tasks.Task CheckADRReturnsDefaultValueIfCacheCrash()
        {
            var devEUI = TestEui.GenerateDevEui();
            var region = RegionManager.EU868;
            ILoRaADRStrategyProvider provider = new LoRaADRStrategyProvider(NullLoggerFactory.Instance);
            var datarate = DataRateIndex.DR5;

            using var inMemoryStore = new LoRaADRInMemoryStore();
            var loRaADRManager = new Mock <LoRaADRManagerBase>(MockBehavior.Loose, inMemoryStore, provider, NullLogger <LoRaADRManagerBase> .Instance)
            {
                CallBase = true
            };

            _ = loRaADRManager.Setup(x => x.NextFCntDown(It.IsAny <DevEui>(), It.IsAny <string>(), It.IsAny <uint>(), It.IsAny <uint>())).ReturnsAsync(1U);

            // setup table with default value
            _ = await loRaADRManager.Object.CalculateADRResultAndAddEntryAsync(devEUI, string.Empty, 1, 1, (float)region.RequiredSnr(datarate), region.GetDownstreamDataRate(datarate), region.TXPowertoMaxEIRP.Count - 1, region.MaxADRDataRate, new LoRaADRTableEntry()
            {
                Snr          = 0,
                FCnt         = 1,
                DevEUI       = devEUI,
                GatewayCount = 1,
                GatewayId    = "gateway"
            });

            // Add measurement and compute new ADR
            for (uint i = 0; i < 21; i++)
            {
                await loRaADRManager.Object.StoreADREntryAsync(
                    new LoRaADRTableEntry()
                {
                    DevEUI       = devEUI,
                    FCnt         = i,
                    GatewayCount = 1,
                    GatewayId    = "mygateway",
                    Snr          = 50
                });
            }

            var adrResult = await loRaADRManager.Object.CalculateADRResultAndAddEntryAsync(devEUI, string.Empty, 1, 1, (float)region.RequiredSnr(datarate), region.GetDownstreamDataRate(datarate), region.TXPowertoMaxEIRP.Count - 1, region.MaxADRDataRate);

            Assert.Equal(DR5, adrResult.DataRate);
            Assert.Equal(7, adrResult.TxPower);
            Assert.Equal(1, adrResult.NbRepetition);

            // reset cache and check we get default values
            _ = await loRaADRManager.Object.ResetAsync(devEUI);

            adrResult = await loRaADRManager.Object.CalculateADRResultAndAddEntryAsync(devEUI, string.Empty, 1, 1, (float)region.RequiredSnr(datarate), region.GetDownstreamDataRate(datarate), region.TXPowertoMaxEIRP.Count - 1, region.MaxADRDataRate, new LoRaADRTableEntry()
            {
                Snr          = 0,
                FCnt         = 1,
                DevEUI       = devEUI,
                GatewayCount = 1,
                GatewayId    = "gateway"
            });

            Assert.Equal(DR5, adrResult.DataRate);
            Assert.Equal(0, adrResult.TxPower);
            Assert.Equal(1, adrResult.NbRepetition);

            loRaADRManager.Verify(x => x.NextFCntDown(It.IsAny <DevEui>(), It.IsAny <string>(), It.IsAny <uint>(), It.IsAny <uint>()), Times.AtLeastOnce, "NextFCntDown");
        }
        // This test perform a delta update and we check the following
        // primary key present in the cache is still here after a delta up
        // Items with save Devaddr are correctly saved (one old from cache, one from iot hub)
        // Gateway Id is correctly updated in old cache information.
        // Primary Key are kept as UpdateTime is similar
        public async Task Delta_Update_Perform_Correctly_On_Non_Empty_Cache_And_Keep_Old_Values()
        {
            var oldGatewayId = NewUniqueEUI64();
            var newGatewayId = NewUniqueEUI64();
            var dateTime     = DateTime.UtcNow;

            var primaryKey   = Convert.ToBase64String(Encoding.UTF8.GetBytes(PrimaryKey));
            var managerInput = new List <DevAddrCacheInfo>();

            var adressForDuplicateDevAddr = CreateDevAddr();

            for (var i = 0; i < 5; i++)
            {
                managerInput.Add(new DevAddrCacheInfo()
                {
                    DevEUI           = TestEui.GenerateDevEui(),
                    DevAddr          = CreateDevAddr(),
                    GatewayId        = newGatewayId,
                    LastUpdatedTwins = dateTime
                });
            }

            managerInput.Add(new DevAddrCacheInfo()
            {
                DevEUI           = TestEui.GenerateDevEui(),
                DevAddr          = adressForDuplicateDevAddr,
                GatewayId        = newGatewayId,
                LastUpdatedTwins = dateTime
            });

            var devAddrJoining = managerInput[0].DevAddr;
            // The cache start as empty
            var registryManagerMock = InitRegistryManager(managerInput, managerInput.Count);

            // Set up the cache with expectation.
            var cacheInput = new List <DevAddrCacheInfo>();

            for (var i = 0; i < 5; i++)
            {
                cacheInput.Add(new DevAddrCacheInfo()
                {
                    DevEUI           = managerInput[i].DevEUI,
                    DevAddr          = managerInput[i].DevAddr,
                    GatewayId        = oldGatewayId,
                    LastUpdatedTwins = dateTime
                });
            }

            cacheInput[2].PrimaryKey = primaryKey;
            cacheInput[3].PrimaryKey = primaryKey;

            var devEui = TestEui.GenerateDevEui();

            cacheInput.Add(new DevAddrCacheInfo()
            {
                DevEUI           = devEui,
                DevAddr          = adressForDuplicateDevAddr,
                GatewayId        = oldGatewayId,
                PrimaryKey       = primaryKey,
                LastUpdatedTwins = dateTime
            });
            InitCache(this.cache, cacheInput);

            // initialize locks for test to run correctly
            var locksToTake = new string[1] {
                FullUpdateKey
            };
            await LockDevAddrHelper.PrepareLocksForTests(this.cache, locksToTake);

            var devAddrCache = new LoRaDevAddrCache(this.cache, null, newGatewayId);
            await devAddrCache.PerformNeededSyncs(registryManagerMock.Object);

            // we expect the devices are saved
            for (var i = 0; i < managerInput.Count; i++)
            {
                if (managerInput[i].DevAddr != adressForDuplicateDevAddr)
                {
                    var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, managerInput[i].DevAddr));
                    Assert.Single(queryResult);
                    var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value);
                    Assert.Equal(managerInput[i].GatewayId, resultObject.GatewayId);
                    Assert.Equal(managerInput[i].DevEUI, resultObject.DevEUI);
                    Assert.Equal(cacheInput[i].PrimaryKey, resultObject.PrimaryKey);
                }
            }

            // let's check the devices with a double EUI
            var query2Result = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, adressForDuplicateDevAddr));

            Assert.Equal(2, query2Result.Length);
            for (var i = 0; i < 2; i++)
            {
                var resultObject = JsonConvert.DeserializeObject <DevAddrCacheInfo>(query2Result[0].Value);
                if (resultObject.DevEUI == devEui)
                {
                    Assert.Equal(oldGatewayId, resultObject.GatewayId);
                    Assert.Equal(primaryKey, resultObject.PrimaryKey);
                }
                else
                {
                    Assert.Equal(newGatewayId, resultObject.GatewayId);
                    Assert.True(string.IsNullOrEmpty(resultObject.PrimaryKey));
                }
            }

            // Iot hub should never have been called.
            registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Once);
            registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never);
            // We expect to query for the key once (the device with an active connection)
            registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Never);
            registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>(), It.IsAny <int>()), Times.Never);
        }
Exemple #21
0
        public async Task FunctionBundler_Adr_and_Dedup()
        {
            var gatewayId1 = NewUniqueEUI64();
            var gatewayId2 = NewUniqueEUI64();
            var devEUI     = TestEui.GenerateDevEui();

            var req  = CreateStandardBundlerRequest(gatewayId1);
            var req2 = CreateStandardBundlerRequest(gatewayId2);

            req.FunctionItems  = FunctionBundlerItemType.ADR | FunctionBundlerItemType.Deduplication;
            req2.FunctionItems = FunctionBundlerItemType.ADR | FunctionBundlerItemType.Deduplication;

            var resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req);

            Assert.NotNull(resp);
            Assert.NotNull(resp.AdrResult);
            Assert.False(resp.AdrResult.CanConfirmToDevice);
            Assert.Equal(1, resp.AdrResult.NumberOfFrames);

            Assert.NotNull(resp.DeduplicationResult);
            Assert.Equal(gatewayId1, resp.DeduplicationResult.GatewayId);
            Assert.False(resp.DeduplicationResult.IsDuplicate);

            Assert.Null(resp.NextFCntDown);

            // with ADR frames
            await this.adrManager.ResetAsync(devEUI);

            await PrepareADRFrames(devEUI, LoRaADRTable.FrameCountCaptureCount - 1, req.AdrRequest);

            req.ClientFCntUp = req.AdrRequest.FCntUp;

            resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req);

            Assert.NotNull(resp);
            Assert.NotNull(resp.AdrResult);
            Assert.Equal(LoRaADRTable.FrameCountCaptureCount, resp.AdrResult.NumberOfFrames);

            Assert.NotNull(resp.DeduplicationResult);
            Assert.Equal(gatewayId1, resp.DeduplicationResult.GatewayId);
            Assert.False(resp.DeduplicationResult.IsDuplicate);
            Assert.True(resp.AdrResult.CanConfirmToDevice || resp.NextFCntDown == null);

            // multi request
            req.AdrRequest.FCntUp   = req2.AdrRequest.FCntUp = req2.ClientFCntUp = ++req.ClientFCntUp;
            req.AdrRequest.FCntDown = req2.AdrRequest.FCntDown = req2.ClientFCntDown = req.ClientFCntDown = resp.NextFCntDown.GetValueOrDefault();

            resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req);

            Assert.NotNull(resp);
            Assert.NotNull(resp.AdrResult);

            Assert.NotNull(resp.DeduplicationResult);
            Assert.Equal(gatewayId1, resp.DeduplicationResult.GatewayId);
            Assert.False(resp.DeduplicationResult.IsDuplicate);

            Assert.True(resp.AdrResult.CanConfirmToDevice || resp.NextFCntDown == null);

            resp = await this.functionBundler.HandleFunctionBundlerInvoke(devEUI, req2);

            Assert.NotNull(resp);
            Assert.NotNull(resp.AdrResult);
            Assert.True(resp.AdrResult.CanConfirmToDevice || resp.NextFCntDown == null);

            Assert.NotNull(resp.DeduplicationResult);
            Assert.Equal(gatewayId1, resp.DeduplicationResult.GatewayId);
            Assert.True(resp.DeduplicationResult.IsDuplicate);
        }
        // This test perform a full update and we check the following
        // primary key present in the cache is still here after a fullupdate
        // Items with same Devaddr are correctly saved (one old from cache, one from iot hub)
        // Old cache items sharing a devaddr not in the new update are correctly removed
        // Items with a devAddr not in the update are correctly still in cache
        // Gateway Id is correctly updated in old cache information.
        // Primary Key are not kept as UpdateTime is not similar
        public async Task Full_Update_Perform_Correctly_On_Non_Empty_Cache_And_Keep_Old_Values_Except_Primary_Keys()
        {
            var oldGatewayId   = NewUniqueEUI64();
            var newGatewayId   = NewUniqueEUI64();
            var dateTime       = DateTime.UtcNow;
            var updateDateTime = DateTime.UtcNow.AddMinutes(3);
            var primaryKey     = Convert.ToBase64String(Encoding.UTF8.GetBytes(PrimaryKey));
            var newValues      = new List <DevAddrCacheInfo>();

            for (var i = 0; i < 5; i++)
            {
                newValues.Add(new DevAddrCacheInfo()
                {
                    DevEUI           = TestEui.GenerateDevEui(),
                    DevAddr          = CreateDevAddr(),
                    GatewayId        = newGatewayId,
                    LastUpdatedTwins = updateDateTime
                });
            }

            // The cache start as empty
            var registryManagerMock = InitRegistryManager(newValues, newValues.Count);

            // Set up the cache with expectation.
            var cacheInput = new List <DevAddrCacheInfo>();

            for (var i = 0; i < 5; i++)
            {
                cacheInput.Add(new DevAddrCacheInfo()
                {
                    DevEUI           = newValues[i].DevEUI,
                    DevAddr          = newValues[i].DevAddr,
                    GatewayId        = oldGatewayId,
                    LastUpdatedTwins = dateTime,
                    PrimaryKey       = primaryKey
                });
            }

            InitCache(this.cache, cacheInput);

            // initialize locks for test to run correctly
            await LockDevAddrHelper.PrepareLocksForTests(this.cache);

            var devAddrCache = new LoRaDevAddrCache(this.cache, null, newGatewayId);
            await devAddrCache.PerformNeededSyncs(registryManagerMock.Object);

            // we expect the devices are saved, the double device id should not be there anymore
            for (var i = 0; i < newValues.Count; i++)
            {
                var queryResult = this.cache.GetHashObject(string.Concat(CacheKeyPrefix, newValues[i].DevAddr));
                Assert.Single(queryResult);
                var result2Object = JsonConvert.DeserializeObject <DevAddrCacheInfo>(queryResult[0].Value);
                Assert.Equal(newGatewayId, result2Object.GatewayId);
                Assert.Equal(newValues[i].DevEUI, result2Object.DevEUI);
                Assert.Equal(string.Empty, result2Object.PrimaryKey);
            }

            // Iot hub should never have been called.
            registryManagerMock.Verify(x => x.CreateQuery(It.IsAny <string>()), Times.Once);
            registryManagerMock.Verify(x => x.GetTwinAsync(It.IsAny <string>()), Times.Never);
            // We expect to query for the key once (the device with an active connection)
            registryManagerMock.Verify(x => x.GetDeviceAsync(It.IsAny <string>()), Times.Never);
        }