public async Task When_Device_Is_Not_In_Cache_And_Found_In_Api_Does_Not_Match_Gateway_Should_Return_Null() { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: "a_different_one")); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); payload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DeviceID, string.Empty); apiService.Setup(x => x.SearchByDevAddrAsync(It.IsNotNull <string>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); var createdLoraDevice = TestUtils.CreateFromSimulatedDevice(simulatedDevice, this.loRaDeviceClient.Object); this.loraDeviceFactoryMock.Setup(x => x.Create(iotHubDeviceInfo)) .Returns(createdLoraDevice); // device will be initialized this.loRaDeviceClient.Setup(x => x.GetTwinAsync()) .ReturnsAsync(new Twin()); var target = new LoRaDeviceRegistry(this.serverConfiguration, this.cache, apiService.Object, this.loraDeviceFactoryMock.Object); var actual = await target.GetDeviceForPayloadAsync(payload); Assert.Null(actual); // Device was searched by DevAddr apiService.VerifyAll(); // Device was created by factory this.loraDeviceFactoryMock.VerifyAll(); }
public LoRaDevice Create(IoTHubDeviceInfo deviceInfo) { return(new LoRaDevice( deviceInfo.DevAddr, deviceInfo.DevEUI, this.loRaDeviceClient)); }
public async Task When_Device_Is_Assigned_To_Another_Gateway_After_Getting_Twin_Cache_Locally_And_Return_Null() { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: "another-gateway")); var apiService = new Mock <LoRaDeviceAPIServiceBase>(MockBehavior.Strict); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DeviceID, string.Empty); apiService.Setup(x => x.SearchByDevAddrAsync(It.IsNotNull <string>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); this.loRaDeviceClient.Setup(x => x.GetTwinAsync()) .ReturnsAsync(simulatedDevice.CreateABPTwin()); this.loRaDeviceClient.Setup(x => x.Disconnect()) .Returns(true); var deviceFactory = new TestLoRaDeviceFactory(this.loRaDeviceClient.Object); var target = new LoRaDeviceRegistry(this.serverConfiguration, this.cache, apiService.Object, deviceFactory); // request #1 var payload1 = simulatedDevice.CreateUnconfirmedDataUpMessage("1", fcnt: 11); payload1.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey); var request1 = new WaitableLoRaRequest(payload1); target.GetLoRaRequestQueue(request1).Queue(request1); Assert.True(await request1.WaitCompleteAsync()); Assert.True(request1.ProcessingFailed); Assert.Equal(LoRaDeviceRequestFailedReason.BelongsToAnotherGateway, request1.ProcessingFailedReason); // request #2 var payload2 = simulatedDevice.CreateUnconfirmedDataUpMessage("2", fcnt: 12); payload2.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey); var request2 = new WaitableLoRaRequest(payload2); target.GetLoRaRequestQueue(request2).Queue(request2); Assert.True(await request2.WaitCompleteAsync()); Assert.True(request2.ProcessingFailed); Assert.Equal(LoRaDeviceRequestFailedReason.BelongsToAnotherGateway, request2.ProcessingFailedReason); // Device was searched by DevAddr apiService.VerifyAll(); apiService.Verify(x => x.SearchByDevAddrAsync(It.IsNotNull <string>()), Times.Once()); this.loRaDeviceClient.VerifyAll(); this.loRaDeviceClient.Verify(x => x.GetTwinAsync(), Times.Once()); // device is in cache var devAddrDictionary = target.InternalGetCachedDevicesForDevAddr(LoRaTools.Utils.ConversionHelper.ByteArrayToString(payload1.DevAddr)); Assert.NotNull(devAddrDictionary); Assert.True(devAddrDictionary.TryGetValue(simulatedDevice.DevEUI, out var cachedLoRaDevice)); Assert.False(cachedLoRaDevice.IsOurDevice); }
public void Serialize_Deserialize_Composition_Should_Preserve_Information(IoTHubDeviceInfo initial) { // act var result = JsonConvert.DeserializeObject <IoTHubDeviceInfo>(JsonConvert.SerializeObject(initial)); // assert Assert.Equal(initial.DevAddr, result.DevAddr); Assert.Equal(initial.DevEUI, result.DevEUI); Assert.Equal(initial.GatewayId, result.GatewayId); Assert.Equal(initial.NwkSKey, result.NwkSKey); Assert.Equal(initial.PrimaryKey, result.PrimaryKey); }
public async Task When_New_ABP_Device_Instance_Is_Created_Should_Increment_FCntDown() { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: ServerGatewayID)); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DeviceID, string.Empty); this.LoRaDeviceApi.Setup(x => x.SearchByDevAddrAsync(It.IsNotNull <string>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); // device will: // - be initialized // - send event // - receive c2d this.LoRaDeviceClient.Setup(x => x.GetTwinAsync()) .ReturnsAsync(simulatedDevice.CreateABPTwin()); this.LoRaDeviceClient.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .ReturnsAsync(true); this.LoRaDeviceClient.Setup(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>())) .ReturnsAsync((Message)null); var deviceRegistry = new LoRaDeviceRegistry(this.ServerConfiguration, this.NewMemoryCache(), this.LoRaDeviceApi.Object, this.LoRaDeviceFactory); // Send to message processor var messageProcessor = new MessageDispatcher( this.ServerConfiguration, deviceRegistry, this.FrameCounterUpdateStrategyProvider); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("2", fcnt: 2); var rxpk = payload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey).Rxpk[0]; var request = this.CreateWaitableRequest(rxpk, constantElapsedTime: TimeSpan.FromMilliseconds(300)); messageProcessor.DispatchRequest(request); Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingSucceeded); // Wait until loader updates the device cache await Task.Delay(50); var devices = deviceRegistry.InternalGetCachedDevicesForDevAddr(simulatedDevice.DevAddr); Assert.Single(devices); Assert.True(devices.TryGetValue(simulatedDevice.DevEUI, out var cachedDevice)); Assert.True(cachedDevice.IsOurDevice); Assert.Equal(Constants.MAX_FCNT_UNSAVED_DELTA - 1U, cachedDevice.FCntDown); Assert.Equal(payload.GetFcnt(), (ushort)cachedDevice.FCntUp); // Device was searched by DevAddr this.LoRaDeviceApi.VerifyAll(); // Device was created by factory this.LoRaDeviceClient.VerifyAll(); }
public async Task When_New_ABP_Device_Instance_Is_Created_Should_Increment_FCntDown() { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: ServerGatewayID)); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DevEui, "pk"); LoRaDeviceApi.Setup(x => x.SearchByDevAddrAsync(It.IsAny <DevAddr>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); // device will: // - be initialized // - send event // - receive c2d LoRaDeviceClient.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(simulatedDevice.CreateABPTwin()); LoRaDeviceClient.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .ReturnsAsync(true); LoRaDeviceClient.Setup(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>())) .ReturnsAsync((Message)null); using var cache = NewMemoryCache(); using var deviceRegistry = new LoRaDeviceRegistry(ServerConfiguration, cache, LoRaDeviceApi.Object, LoRaDeviceFactory, DeviceCache); // Send to message processor using var messageProcessor = new MessageDispatcher( ServerConfiguration, deviceRegistry, FrameCounterUpdateStrategyProvider); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("2", fcnt: 2); using var request = CreateWaitableRequest(TestUtils.GenerateTestRadioMetadata(), payload, constantElapsedTime: TimeSpan.FromMilliseconds(300)); messageProcessor.DispatchRequest(request); Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingSucceeded); // Wait until loader updates the device cache await Task.Delay(50); Assert.Equal(1, DeviceCache.RegistrationCount(simulatedDevice.DevAddr.Value)); Assert.True(DeviceCache.TryGetForPayload(request.Payload, out var cachedDevice)); Assert.True(cachedDevice.IsOurDevice); Assert.Equal(Constants.MaxFcntUnsavedDelta - 1U, cachedDevice.FCntDown); Assert.Equal(payload.Fcnt, (ushort)cachedDevice.FCntUp); // Device was searched by DevAddr LoRaDeviceApi.VerifyAll(); // Device was created by factory LoRaDeviceClient.VerifyAll(); }
public async Task When_Device_Does_Not_Match_Gateway_Should_Fail_Request() { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: "a_different_one")); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); payload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DeviceID, string.Empty) { GatewayId = "a_different_one", }; apiService.Setup(x => x.SearchByDevAddrAsync(It.IsNotNull <string>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); var loRaDeviceClient = new Mock <ILoRaDeviceClient>(MockBehavior.Strict); var deviceFactory = new TestLoRaDeviceFactory(loRaDeviceClient.Object); var destinationDictionary = new DevEUIToLoRaDeviceDictionary(); var finished = new SemaphoreSlim(0); var target = new DeviceLoaderSynchronizer( simulatedDevice.DevAddr, apiService.Object, deviceFactory, destinationDictionary, null, this.serverConfiguration, (_, l) => { finished.Release(); }, (d) => destinationDictionary.TryAdd(d.DevEUI, d)); var request = new WaitableLoRaRequest(payload); target.Queue(request); Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingFailed); Assert.Equal(LoRaDeviceRequestFailedReason.BelongsToAnotherGateway, request.ProcessingFailedReason); // device should not be initialized, since it belongs to another gateway loRaDeviceClient.Verify(x => x.GetTwinAsync(), Times.Never()); // device should not be disconnected (was never connected) loRaDeviceClient.Verify(x => x.Disconnect(), Times.Never()); // Device was searched by DevAddr apiService.VerifyAll(); // Device was created by factory loRaDeviceClient.VerifyAll(); }
public async Task When_Device_Is_Assigned_To_Another_Gateway_Cache_Locally_And_Return_Null() { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: "another-gateway")); var apiService = new Mock <LoRaDeviceAPIServiceBase>(MockBehavior.Strict); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DevEui, "pk") { GatewayId = "another-gateway", NwkSKey = simulatedDevice.NwkSKey.Value }; apiService.Setup(x => x.SearchByDevAddrAsync(It.IsAny <DevAddr>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); var deviceFactory = new TestLoRaDeviceFactory(LoRaDeviceClient.Object, DeviceCache, ConnectionManager); using var target = new LoRaDeviceRegistry(ServerConfiguration, this.cache, apiService.Object, deviceFactory, DeviceCache); // request #1 var payload1 = simulatedDevice.CreateUnconfirmedDataUpMessage("1", fcnt: 11); using var request1 = WaitableLoRaRequest.Create(payload1); target.GetLoRaRequestQueue(request1).Queue(request1); Assert.True(await request1.WaitCompleteAsync()); Assert.True(request1.ProcessingFailed); Assert.Equal(LoRaDeviceRequestFailedReason.BelongsToAnotherGateway, request1.ProcessingFailedReason); // request #2 var payload2 = simulatedDevice.CreateUnconfirmedDataUpMessage("2", fcnt: 12); using var request2 = WaitableLoRaRequest.Create(payload2); target.GetLoRaRequestQueue(request2).Queue(request2); Assert.True(await request2.WaitCompleteAsync()); Assert.True(request2.ProcessingFailed); Assert.Equal(LoRaDeviceRequestFailedReason.BelongsToAnotherGateway, request2.ProcessingFailedReason); // Device was searched by DevAddr apiService.VerifyAll(); apiService.Verify(x => x.SearchByDevAddrAsync(It.IsAny <DevAddr>()), Times.Once()); // Device should not be connected LoRaDeviceClient.VerifyAll(); LoRaDeviceClient.Verify(x => x.GetTwinAsync(CancellationToken.None), Times.Never()); LoRaDeviceClient.Verify(x => x.Disconnect(), Times.Never()); // device is in cache Assert.True(DeviceCache.TryGetForPayload(request1.Payload, out var loRaDevice)); Assert.False(loRaDevice.IsOurDevice); }
public async Task When_Device_Does_Not_Match_Gateway_Should_Fail_Request() { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: "a_different_one")); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DevEui, "pk") { GatewayId = "a_different_one", NwkSKey = simulatedDevice.NwkSKey.Value }; apiService.Setup(x => x.SearchByDevAddrAsync(It.IsAny <DevAddr>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); var loRaDeviceClient = new Mock <ILoRaDeviceClient>(MockBehavior.Loose); using var deviceCache = LoRaDeviceCacheDefault.CreateDefault(); var deviceFactory = new TestLoRaDeviceFactory(loRaDeviceClient.Object, deviceCache, this.connectionManager); var target = new DeviceLoaderSynchronizer( simulatedDevice.DevAddr.Value, apiService.Object, deviceFactory, new NetworkServerConfiguration(), deviceCache, null, NullLogger <DeviceLoaderSynchronizer> .Instance); _ = target.LoadAsync(); using var request = WaitableLoRaRequest.Create(payload); target.Queue(request); Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingFailed); Assert.Equal(LoRaDeviceRequestFailedReason.BelongsToAnotherGateway, request.ProcessingFailedReason); // device should not be initialized, since it belongs to another gateway loRaDeviceClient.Verify(x => x.GetTwinAsync(CancellationToken.None), Times.Never()); // device should not be disconnected (was never connected) loRaDeviceClient.Verify(x => x.Disconnect(), Times.Never()); // Device was searched by DevAddr apiService.VerifyAll(); // Device was created by factory loRaDeviceClient.VerifyAll(); }
public void Can_Be_Json_Deserialized_As_IoTHubDeviceInfo_From_NetworkServer() { // arrange var original = new IoTHubDeviceInfo { DevAddr = new DevAddr(123), DevEUI = new DevEui(234), PrimaryKey = "someprimarykey" }; // act var result = JsonConvert.DeserializeObject <LoRaWan.NetworkServer.IoTHubDeviceInfo>(JsonConvert.SerializeObject(original)); // assert Assert.NotNull(result); Assert.Equal(original.DevEUI, result !.DevEUI); Assert.Equal(original.PrimaryKey, result.PrimaryKey); Assert.Equal(original.DevAddr, result.DevAddr); }
protected override LoRaDevice CreateDevice(IoTHubDeviceInfo deviceInfo) { var connectionManager = new Mock <ILoRaDeviceClientConnectionManager>(); var device = new Mock <LoRaDevice>(deviceInfo.DevAddr, deviceInfo.DevEUI, connectionManager.Object); if (this.deviceSetup != null) { this.deviceSetup(device); } else { device.Setup(x => x.InitializeAsync(It.IsAny <NetworkServerConfiguration>(), It.IsAny <CancellationToken>())).ReturnsAsync(true); } LastDeviceMock = device; return(device.Object); }
public void Serializes_To_Expected_Json_Object() { // arrange var original = new IoTHubDeviceInfo { DevAddr = new DevAddr(123), DevEUI = new DevEui(234), PrimaryKey = "someprimarykey" }; // act var obj = JsonConvert.DeserializeObject <JObject>(JsonConvert.SerializeObject(original)); // assert Assert.NotNull(obj); Assert.Equal(3, obj !.Count); Assert.Equal(original.DevEuiString, obj["DevEUI"]); Assert.Equal(original.PrimaryKey, obj["PrimaryKey"]); Assert.Equal(original.DevAddrString, obj["DevAddr"]); }
public async Task When_Device_Is_Not_In_Cache_And_Found_In_Api_Does_Not_Match_Mic_Should_Fail_Request(string deviceGatewayID) { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DeviceID, string.Empty); apiService.Setup(x => x.SearchByDevAddrAsync(It.IsNotNull <string>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); // Will get device twin var loRaDeviceClient = new Mock <ILoRaDeviceClient>(MockBehavior.Strict); loRaDeviceClient.Setup(x => x.GetTwinAsync()) .ReturnsAsync(TestUtils.CreateABPTwin(simulatedDevice)); var deviceFactory = new TestLoRaDeviceFactory(loRaDeviceClient.Object); var destinationDictionary = new DevEUIToLoRaDeviceDictionary(); var finished = new SemaphoreSlim(0); var target = new DeviceLoaderSynchronizer( simulatedDevice.DevAddr, apiService.Object, deviceFactory, destinationDictionary, null, this.serverConfiguration, (_, l) => { finished.Release(); }, (d) => destinationDictionary.TryAdd(d.DevEUI, d)); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); payload.SerializeUplink(simulatedDevice.AppSKey, "00000000000000000000000000EEAAFF"); var request = new WaitableLoRaRequest(payload); target.Queue(request); Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingFailed); Assert.Equal(LoRaDeviceRequestFailedReason.NotMatchingDeviceByMicCheck, request.ProcessingFailedReason); // Device was searched by DevAddr apiService.VerifyAll(); loRaDeviceClient.VerifyAll(); }
public async Task When_ABP_Device_Is_Created_Should_Call_Initializers(string deviceGatewayID) { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); payload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DeviceID, string.Empty); apiService.Setup(x => x.SearchByDevAddrAsync(It.IsNotNull <string>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); var createdLoraDevice = TestUtils.CreateFromSimulatedDevice(simulatedDevice, this.loRaDeviceClient.Object); this.loraDeviceFactoryMock.Setup(x => x.Create(iotHubDeviceInfo)) .Returns(createdLoraDevice); // device will be initialized this.loRaDeviceClient.Setup(x => x.GetTwinAsync()) .ReturnsAsync(simulatedDevice.CreateABPTwin()); var target = new LoRaDeviceRegistry(this.serverConfiguration, this.cache, apiService.Object, this.loraDeviceFactoryMock.Object); var initializer = new Mock <ILoRaDeviceInitializer>(); initializer.Setup(x => x.Initialize(createdLoraDevice)); target.RegisterDeviceInitializer(initializer.Object); var actual = await target.GetDeviceForPayloadAsync(payload); Assert.NotNull(actual); Assert.Same(actual, createdLoraDevice); Assert.True(actual.IsOurDevice); // Device was searched by DevAddr apiService.VerifyAll(); // Device was created by factory this.loraDeviceFactoryMock.VerifyAll(); // initializer was called initializer.VerifyAll(); }
public async Task When_Device_Is_Assigned_To_Another_Gateway_After_No_Connection_Should_Be_Established() { const string gatewayId = "another-gateway"; var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: gatewayId)); var apiService = new Mock <LoRaDeviceAPIServiceBase>(MockBehavior.Strict); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DevEui, "pk") { NwkSKey = simulatedDevice.NwkSKey.Value, GatewayId = gatewayId }; apiService.Setup(x => x.SearchByDevAddrAsync(It.IsAny <DevAddr>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); var deviceFactory = new TestLoRaDeviceFactory(LoRaDeviceClient.Object, DeviceCache, ConnectionManager); using var target = new LoRaDeviceRegistry(ServerConfiguration, this.cache, apiService.Object, deviceFactory, DeviceCache); // setup 2 requests - ensure the cache is validated before fetching from the function var requests = Enumerable.Range(1, 2).Select((n) => { var payload = simulatedDevice.CreateUnconfirmedDataUpMessage(n.ToString(CultureInfo.InvariantCulture), fcnt: (uint)n + 10); var request = WaitableLoRaRequest.Create(payload); target.GetLoRaRequestQueue(request).Queue(request); return(request); } ).ToList(); foreach (var request in requests) { Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingFailed); Assert.Equal(LoRaDeviceRequestFailedReason.BelongsToAnotherGateway, request.ProcessingFailedReason); } // Device was searched by DevAddr apiService.VerifyAll(); apiService.Verify(x => x.SearchByDevAddrAsync(It.IsAny <DevAddr>()), Times.Once()); LoRaDeviceClient.Verify(x => x.GetTwinAsync(CancellationToken.None), Times.Never()); // device is in cache Assert.True(DeviceCache.TryGetForPayload(requests.First().Payload, out var cachedLoRaDevice)); Assert.False(cachedLoRaDevice.IsOurDevice); }
public async Task When_Device_Is_Not_In_Cache_And_Found_In_Api_Should_Cache_And_Process_Request(string deviceGatewayID) { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); payload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DeviceID, string.Empty); apiService.Setup(x => x.SearchByDevAddrAsync(It.IsNotNull <string>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); // device will be initialized this.loRaDeviceClient.Setup(x => x.GetTwinAsync()) .ReturnsAsync(simulatedDevice.CreateABPTwin()); var request = new WaitableLoRaRequest(payload); var requestHandler = new Mock <ILoRaDataRequestHandler>(MockBehavior.Strict); requestHandler.Setup(x => x.ProcessRequestAsync(request, It.IsNotNull <LoRaDevice>())) .ReturnsAsync(new LoRaDeviceRequestProcessResult(null, request)); var deviceFactory = new TestLoRaDeviceFactory(this.loRaDeviceClient.Object, requestHandler.Object); var target = new LoRaDeviceRegistry(this.serverConfiguration, this.cache, apiService.Object, deviceFactory); target.GetLoRaRequestQueue(request).Queue(request); Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingSucceeded); // Device was searched by DevAddr apiService.VerifyAll(); // ensure device is in cache var cachedItem = target.InternalGetCachedDevicesForDevAddr(simulatedDevice.DevAddr); Assert.NotNull(cachedItem); Assert.Single(cachedItem); Assert.True(cachedItem.TryGetValue(simulatedDevice.DevEUI, out var actualCachedLoRaDevice)); // request was handled requestHandler.VerifyAll(); }
public async Task When_Device_Is_Assigned_To_Another_Gateway_Cache_Locally_And_Return_Null() { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: "another-gateway")); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DeviceID, string.Empty); apiService.Setup(x => x.SearchByDevAddrAsync(It.IsNotNull <string>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); var createdLoraDevice = TestUtils.CreateFromSimulatedDevice(simulatedDevice, this.loRaDeviceClient.Object); this.loraDeviceFactoryMock.Setup(x => x.Create(iotHubDeviceInfo)) .Returns(createdLoraDevice); // device will be initialized this.loRaDeviceClient.Setup(x => x.GetTwinAsync()) .ReturnsAsync(simulatedDevice.CreateABPTwin()); var target = new LoRaDeviceRegistry(this.serverConfiguration, this.cache, apiService.Object, this.loraDeviceFactoryMock.Object); var actual = await target.GetDeviceForPayloadAsync(payload); Assert.Null(actual); // search again var actual2 = await target.GetDeviceForPayloadAsync(payload); Assert.Null(actual2); // Device was searched by DevAddr apiService.VerifyAll(); // Device was created by factory this.loraDeviceFactoryMock.VerifyAll(); // device is in cache Assert.Equal(1, this.cache.Count); var devAddrDictionary = target.InternalGetCachedDevicesForDevAddr(LoRaTools.Utils.ConversionHelper.ByteArrayToString(payload.DevAddr)); Assert.NotNull(devAddrDictionary); Assert.True(devAddrDictionary.TryGetValue(createdLoraDevice.DevEUI, out var cachedLoRaDevice)); Assert.False(cachedLoRaDevice.IsOurDevice); }
public async Task When_Cache_Clear_Is_Called_Should_Removed_Cached_Devices(string deviceGatewayID) { const int deviceCount = 10; var foundDeviceList = new HashSet <LoRaDevice>(); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var deviceFactory = new TestLoRaDeviceFactory(this.loRaDeviceClient.Object); var target = new LoRaDeviceRegistry(this.serverConfiguration, this.cache, apiService.Object, deviceFactory); var getTwinMockSequence = this.loRaDeviceClient.SetupSequence(x => x.GetTwinAsync()); for (var deviceID = 1; deviceID <= deviceCount; ++deviceID) { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice((uint)deviceID, gatewayID: deviceGatewayID)); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); payload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey); // force mic creation var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DeviceID, string.Empty); apiService.Setup(x => x.SearchByDevAddrAsync(simulatedDevice.DevAddr)) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); // device will be initialized getTwinMockSequence.ReturnsAsync(simulatedDevice.CreateABPTwin()); var actual = await target.GetDeviceForPayloadAsync(payload); Assert.NotNull(actual); foundDeviceList.Add(actual); } Assert.Equal(deviceCount, foundDeviceList.Count); // Device was searched by DevAddr apiService.VerifyAll(); // Device was created by factory this.loraDeviceFactoryMock.VerifyAll(); // ensure all devices are in cache Assert.Equal(deviceCount, foundDeviceList.Count(x => target.InternalGetCachedDevicesForDevAddr(x.DevAddr).Count == 1)); target.ResetDeviceCache(); Assert.False(foundDeviceList.Any(x => target.InternalGetCachedDevicesForDevAddr(x.DevAddr).Count > 0), "Should not find devices again"); }
public async Task When_Device_Is_Not_In_Cache_And_Found_In_Api_Should_Cache_And_Return_It(string deviceGatewayID) { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); payload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DeviceID, string.Empty); apiService.Setup(x => x.SearchByDevAddrAsync(It.IsNotNull <string>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); var createdLoraDevice = TestUtils.CreateFromSimulatedDevice(simulatedDevice, this.loRaDeviceClient.Object); this.loraDeviceFactoryMock.Setup(x => x.Create(iotHubDeviceInfo)) .Returns(createdLoraDevice); // device will be initialized this.loRaDeviceClient.Setup(x => x.GetTwinAsync()) .ReturnsAsync(simulatedDevice.CreateABPTwin()); var target = new LoRaDeviceRegistry(this.serverConfiguration, this.cache, apiService.Object, this.loraDeviceFactoryMock.Object); var actual = await target.GetDeviceForPayloadAsync(payload); Assert.NotNull(actual); Assert.Same(actual, createdLoraDevice); Assert.True(actual.IsOurDevice); // Device was searched by DevAddr apiService.VerifyAll(); // Device was created by factory this.loraDeviceFactoryMock.VerifyAll(); // ensure device is in cache var cachedItem = target.InternalGetCachedDevicesForDevAddr(createdLoraDevice.DevAddr); Assert.NotNull(cachedItem); Assert.Single(cachedItem); Assert.True(cachedItem.TryGetValue(createdLoraDevice.DevEUI, out var actualCachedLoRaDevice)); Assert.Same(createdLoraDevice, actualCachedLoRaDevice); }
public async Task When_ABP_Device_Is_Created_Should_Call_Initializers(string deviceGatewayID) { LoRaDeviceClient.Setup(ldc => ldc.Dispose()); var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DevEui, string.Empty); apiService.Setup(x => x.SearchByDevAddrAsync(It.IsAny <DevAddr>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); using var connectionManager = new SingleDeviceConnectionManager(LoRaDeviceClient.Object); using var createdLoraDevice = TestUtils.CreateFromSimulatedDevice(simulatedDevice, connectionManager); this.loraDeviceFactoryMock.Setup(x => x.CreateAndRegisterAsync(iotHubDeviceInfo, It.IsAny <CancellationToken>())) .ReturnsAsync(createdLoraDevice); // device will be initialized LoRaDeviceClient.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(simulatedDevice.CreateABPTwin()); using var target = new LoRaDeviceRegistry(ServerConfiguration, this.cache, apiService.Object, this.loraDeviceFactoryMock.Object, DeviceCache); var initializer = new Mock <ILoRaDeviceInitializer>(); initializer.Setup(x => x.Initialize(createdLoraDevice)); target.RegisterDeviceInitializer(initializer.Object); using var request = WaitableLoRaRequest.Create(payload); target.GetLoRaRequestQueue(request).Queue(request); Assert.True(await request.WaitCompleteAsync()); // Device was searched by DevAddr apiService.VerifyAll(); // Device was created by factory this.loraDeviceFactoryMock.VerifyAll(); // initializer was called initializer.VerifyAll(); }
public LoRaDevice Create(IoTHubDeviceInfo deviceInfo) { if (!this.deviceClientMap.TryGetValue(deviceInfo.DevEUI, out var deviceClientToAssign)) { deviceClientToAssign = this.loRaDeviceClient; } var loRaDevice = new LoRaDevice( deviceInfo.DevAddr, deviceInfo.DevEUI, this.connectionManager); this.connectionManager.Register(loRaDevice, deviceClientToAssign); loRaDevice.SetRequestHandler(this.requestHandler ?? new DefaultLoRaDataRequestHandler(this.configuration, this.frameCounterUpdateStrategyProvider, new LoRaPayloadDecoder(), this.deduplicationFactory, this.adrStrategyProvider, this.adrManagerFactory, this.functionBundlerProvider)); this.deviceMap[deviceInfo.DevEUI] = loRaDevice; return(loRaDevice); }
public async Task When_Device_Is_Not_In_Cache_And_Found_In_Api_Should_Cache_And_Process_Request(string deviceGatewayID) { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234"); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DevEui, "pk") { GatewayId = deviceGatewayID }; apiService.Setup(x => x.SearchByDevAddrAsync(It.IsAny <DevAddr>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); // device will be initialized LoRaDeviceClient.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(simulatedDevice.CreateABPTwin()); using var request = WaitableLoRaRequest.Create(payload); var requestHandler = new Mock <ILoRaDataRequestHandler>(MockBehavior.Strict); requestHandler.Setup(x => x.ProcessRequestAsync(request, It.IsNotNull <LoRaDevice>())) .ReturnsAsync(new LoRaDeviceRequestProcessResult(null, request)); var deviceFactory = new TestLoRaDeviceFactory(LoRaDeviceClient.Object, requestHandler.Object, DeviceCache, ConnectionManager); using var target = new LoRaDeviceRegistry(ServerConfiguration, this.cache, apiService.Object, deviceFactory, DeviceCache); target.GetLoRaRequestQueue(request).Queue(request); Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingSucceeded); // Device was searched by DevAddr apiService.VerifyAll(); // ensure device is in cache Assert.True(DeviceCache.TryGetForPayload(request.Payload, out var actualCachedLoRaDevice)); // request was handled requestHandler.VerifyAll(); }
public async Task When_Device_Is_Not_In_Cache_And_Found_In_Api_Does_Not_Match_Mic_Should_Fail_Request(string deviceGatewayID) { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); var iotHubDeviceInfo = new IoTHubDeviceInfo(simulatedDevice.LoRaDevice.DevAddr, simulatedDevice.LoRaDevice.DevEui, "pk"); apiService.Setup(x => x.SearchByDevAddrAsync(It.IsAny <DevAddr>())) .ReturnsAsync(new SearchDevicesResult(iotHubDeviceInfo.AsList())); // Will get device twin var loRaDeviceClient = new Mock <ILoRaDeviceClient>(MockBehavior.Loose); loRaDeviceClient.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(TestUtils.CreateABPTwin(simulatedDevice)); using var deviceCache = LoRaDeviceCacheDefault.CreateDefault(); var deviceFactory = new TestLoRaDeviceFactory(loRaDeviceClient.Object, deviceCache, this.connectionManager); var target = new DeviceLoaderSynchronizer( simulatedDevice.DevAddr.Value, apiService.Object, deviceFactory, new NetworkServerConfiguration(), deviceCache, null, NullLogger <DeviceLoaderSynchronizer> .Instance); _ = target.LoadAsync(); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234", appSKey: simulatedDevice.AppSKey, nwkSKey: TestKeys.CreateNetworkSessionKey(0xEEAAFF)); using var request = WaitableLoRaRequest.Create(payload); target.Queue(request); Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingFailed); Assert.Equal(LoRaDeviceRequestFailedReason.NotMatchingDeviceByMicCheck, request.ProcessingFailedReason); // Device was searched by DevAddr apiService.VerifyAll(); loRaDeviceClient.VerifyAll(); }
public async Task When_Queueing_To_Multiple_Devices_With_Same_DevAddr_Should_Queue_To_Device_Matching_Mic(string deviceGatewayID) { var simulatedDevice1 = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); var payload = simulatedDevice1.CreateUnconfirmedDataUpMessage("1234"); payload.SerializeUplink(simulatedDevice1.AppSKey, simulatedDevice1.NwkSKey); var loRaDeviceClient1 = new Mock<ILoRaDeviceClient>(MockBehavior.Strict); loRaDeviceClient1.Setup(x => x.GetTwinAsync()) .ReturnsAsync(simulatedDevice1.CreateABPTwin()); var loraDevice1 = TestUtils.CreateFromSimulatedDevice(simulatedDevice1, loRaDeviceClient1.Object); var devAddr = loraDevice1.DevAddr; WaitableLoRaRequest request = null; var reqHandler1 = new Mock<ILoRaDataRequestHandler>(MockBehavior.Strict); reqHandler1.Setup(x => x.ProcessRequestAsync(It.IsNotNull<LoRaRequest>(), loraDevice1)) .ReturnsAsync(new LoRaDeviceRequestProcessResult(loraDevice1, request)); loraDevice1.SetRequestHandler(reqHandler1.Object); var simulatedDevice2 = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); simulatedDevice2.LoRaDevice.DeviceID = "00000002"; simulatedDevice2.LoRaDevice.NwkSKey = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; var loRaDeviceClient2 = new Mock<ILoRaDeviceClient>(MockBehavior.Strict); loRaDeviceClient2.Setup(x => x.GetTwinAsync()) .ReturnsAsync(simulatedDevice2.CreateABPTwin()); var loraDevice2 = TestUtils.CreateFromSimulatedDevice(simulatedDevice2, loRaDeviceClient2.Object); // Api service: search devices async var iotHubDeviceInfo1 = new IoTHubDeviceInfo(devAddr, loraDevice1.DevEUI, string.Empty); var iotHubDeviceInfo2 = new IoTHubDeviceInfo(devAddr, loraDevice2.DevEUI, string.Empty); var apiService = new Mock<LoRaDeviceAPIServiceBase>(); apiService.Setup(x => x.SearchByDevAddrAsync(devAddr)) .ReturnsAsync(new SearchDevicesResult(new IoTHubDeviceInfo[] { iotHubDeviceInfo2, iotHubDeviceInfo1, })); // Device factory: create 2 devices this.loraDeviceFactoryMock.Setup(x => x.Create(iotHubDeviceInfo1)).Returns(loraDevice1); this.loraDeviceFactoryMock.Setup(x => x.Create(iotHubDeviceInfo2)).Returns(loraDevice2); var target = new LoRaDeviceRegistry(this.serverConfiguration, this.cache, apiService.Object, this.loraDeviceFactoryMock.Object); request = new WaitableLoRaRequest(payload); target.GetLoRaRequestQueue(request).Queue(request); Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingSucceeded); // Device was searched by DevAddr apiService.VerifyAll(); // Device was created by factory this.loraDeviceFactoryMock.VerifyAll(); // Both devices are in cache var devicesByDevAddrDictionary = target.InternalGetCachedDevicesForDevAddr(devAddr); Assert.NotNull(devicesByDevAddrDictionary); Assert.Equal(2, devicesByDevAddrDictionary.Count); // 2 devices with same devAddr exist in cache // find device 1 Assert.True(devicesByDevAddrDictionary.TryGetValue(loraDevice1.DevEUI, out var actualCachedLoRaDevice1)); Assert.Same(loraDevice1, actualCachedLoRaDevice1); Assert.True(loraDevice1.IsOurDevice); // find device 2 Assert.True(devicesByDevAddrDictionary.TryGetValue(loraDevice2.DevEUI, out var actualCachedLoRaDevice2)); Assert.Same(loraDevice2, actualCachedLoRaDevice2); Assert.True(loraDevice2.IsOurDevice); reqHandler1.VerifyAll(); loRaDeviceClient1.VerifyAll(); loRaDeviceClient2.VerifyAll(); }
// [InlineData(200, 500, 100, 100, 1)] public async Task When_Multiple_Devices_And_Conflicting_DevAddr_Send_Telemetry_Queue_Sends_Messages_To_IoTHub( int searchDelay, int getTwinDelay, int sendMessageDelay, int receiveDelay, int delayBetweenMessages) { const int messagePerDeviceCount = 10; const int payloadInitialFcnt = 2; var device1 = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1)); var device1Twin = TestUtils.CreateABPTwin(device1); var device2 = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(2)) { DevAddr = device1.DevAddr }; var device2Twin = TestUtils.CreateABPTwin(device2); var device3 = new SimulatedDevice(TestDeviceInfo.CreateOTAADevice(3)); device3.SetupJoin(TestKeys.CreateAppSessionKey(0x88), TestKeys.CreateNetworkSessionKey(0x88), new DevAddr(0x02000088)); var device3Twin = TestUtils.CreateOTAATwin(device3); var device4 = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(4)); var device4Twin = TestUtils.CreateABPTwin(device4); var device1And2Result = new IoTHubDeviceInfo[] { new IoTHubDeviceInfo(device1.DevAddr, device1.DevEUI, "1"), new IoTHubDeviceInfo(device2.DevAddr, device2.DevEUI, "2"), }; LoRaDeviceApi.Setup(x => x.SearchByDevAddrAsync(device1.DevAddr.Value)) .ReturnsAsync(new SearchDevicesResult(device1And2Result), TimeSpan.FromMilliseconds(searchDelay)); LoRaDeviceApi.Setup(x => x.SearchByDevAddrAsync(device3.DevAddr.Value)) .ReturnsAsync(new SearchDevicesResult(new IoTHubDeviceInfo(device3.DevAddr, device3.DevEUI, "3").AsList()), TimeSpan.FromMilliseconds(searchDelay)); LoRaDeviceApi.Setup(x => x.SearchByDevAddrAsync(device4.DevAddr.Value)) .ReturnsAsync(new SearchDevicesResult(new IoTHubDeviceInfo(device4.DevAddr, device4.DevEUI, "3").AsList()), TimeSpan.FromMilliseconds(searchDelay)); var deviceClient1 = new Mock <ILoRaDeviceClient>(); var deviceClient1Telemetry = new List <LoRaDeviceTelemetry>(); deviceClient1.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(device1Twin, TimeSpan.FromMilliseconds(getTwinDelay)); deviceClient1.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .Callback <LoRaDeviceTelemetry, Dictionary <string, string> >((t, d) => deviceClient1Telemetry.Add(t)) .ReturnsAsync(true, TimeSpan.FromMilliseconds(sendMessageDelay)); deviceClient1.Setup(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>())) .ReturnsAsync(null, TimeSpan.FromMilliseconds(receiveDelay)); deviceClient1.Setup(x => x.UpdateReportedPropertiesAsync(It.IsAny <TwinCollection>(), It.IsAny <CancellationToken>())).ReturnsAsync(true); var deviceClient2 = new Mock <ILoRaDeviceClient>(); var deviceClient2Telemetry = new List <LoRaDeviceTelemetry>(); deviceClient2.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(device2Twin, TimeSpan.FromMilliseconds(getTwinDelay)); deviceClient2.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .Callback <LoRaDeviceTelemetry, Dictionary <string, string> >((t, d) => deviceClient2Telemetry.Add(t)) .ReturnsAsync(true, TimeSpan.FromMilliseconds(sendMessageDelay)); deviceClient2.Setup(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>())) .ReturnsAsync(null, TimeSpan.FromMilliseconds(receiveDelay)); deviceClient2.Setup(x => x.UpdateReportedPropertiesAsync(It.IsAny <TwinCollection>(), It.IsAny <CancellationToken>())).ReturnsAsync(true); var deviceClient3 = new Mock <ILoRaDeviceClient>(); var deviceClient3Telemetry = new List <LoRaDeviceTelemetry>(); deviceClient3.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(device3Twin, TimeSpan.FromMilliseconds(getTwinDelay)); deviceClient3.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .Callback <LoRaDeviceTelemetry, Dictionary <string, string> >((t, d) => deviceClient3Telemetry.Add(t)) .ReturnsAsync(true, TimeSpan.FromMilliseconds(sendMessageDelay)); deviceClient3.Setup(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>())) .ReturnsAsync(null, TimeSpan.FromMilliseconds(receiveDelay)); deviceClient3.Setup(x => x.UpdateReportedPropertiesAsync(It.IsAny <TwinCollection>(), It.IsAny <CancellationToken>())).ReturnsAsync(true); var deviceClient4 = new Mock <ILoRaDeviceClient>(); var deviceClient4Telemetry = new List <LoRaDeviceTelemetry>(); deviceClient4.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(device4Twin, TimeSpan.FromMilliseconds(getTwinDelay)); deviceClient4.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .Callback <LoRaDeviceTelemetry, Dictionary <string, string> >((t, d) => deviceClient4Telemetry.Add(t)) .ReturnsAsync(true, TimeSpan.FromMilliseconds(sendMessageDelay)); deviceClient4.Setup(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>())) .ReturnsAsync(null, TimeSpan.FromMilliseconds(receiveDelay)); deviceClient4.Setup(x => x.UpdateReportedPropertiesAsync(It.IsAny <TwinCollection>(), It.IsAny <CancellationToken>())).ReturnsAsync(true); LoRaDeviceFactory.SetClient(device1.DevEUI, deviceClient1.Object); LoRaDeviceFactory.SetClient(device2.DevEUI, deviceClient2.Object); LoRaDeviceFactory.SetClient(device3.DevEUI, deviceClient3.Object); LoRaDeviceFactory.SetClient(device4.DevEUI, deviceClient4.Object); using var cache = NewMemoryCache(); using var deviceRegistry = new LoRaDeviceRegistry(ServerConfiguration, cache, LoRaDeviceApi.Object, LoRaDeviceFactory, DeviceCache); using var messageDispatcher = new MessageDispatcher( ServerConfiguration, deviceRegistry, FrameCounterUpdateStrategyProvider); var device1Messages = await SendMessages(device1, messageDispatcher, payloadInitialFcnt, delayBetweenMessages, messagePerDeviceCount); var device2Messages = await SendMessages(device2, messageDispatcher, payloadInitialFcnt, delayBetweenMessages, messagePerDeviceCount); var device3Messages = await SendMessages(device3, messageDispatcher, payloadInitialFcnt, delayBetweenMessages, messagePerDeviceCount); var device4Messages = await SendMessages(device4, messageDispatcher, payloadInitialFcnt, delayBetweenMessages, messagePerDeviceCount); var allMessages = device1Messages .Concat(device2Messages) .Concat(device3Messages) .Concat(device4Messages) .ToList(); Assert.Equal(messagePerDeviceCount * 4, allMessages.Count); await Task.WhenAll(allMessages.Select(x => x.WaitCompleteAsync())); Assert.All(allMessages, m => Assert.True(m.ProcessingSucceeded)); var telemetries = new[] { deviceClient1Telemetry, deviceClient2Telemetry, deviceClient3Telemetry, deviceClient4Telemetry }; foreach (var telemetry in telemetries) { Assert.Equal(messagePerDeviceCount, telemetry.Count); for (var i = 0; i < messagePerDeviceCount; ++i) { Assert.Equal(payloadInitialFcnt + i, telemetry[i].Fcnt); } } deviceClient1.VerifyAll(); deviceClient1.Verify(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null), Times.Exactly(messagePerDeviceCount)); deviceClient2.VerifyAll(); deviceClient2.Verify(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null), Times.Exactly(messagePerDeviceCount)); deviceClient3.VerifyAll(); deviceClient3.Verify(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null), Times.Exactly(messagePerDeviceCount)); deviceClient4.VerifyAll(); deviceClient4.Verify(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null), Times.Exactly(messagePerDeviceCount)); LoRaDeviceApi.VerifyAll(); }
public async Task When_Queueing_To_Multiple_Devices_With_Same_DevAddr_Should_Queue_To_Device_Matching_Mic(string deviceGatewayID) { var simulatedDevice1 = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); var payload = simulatedDevice1.CreateUnconfirmedDataUpMessage("1234"); var loRaDeviceClient1 = new Mock <ILoRaDeviceClient>(MockBehavior.Loose); loRaDeviceClient1.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(simulatedDevice1.CreateABPTwin()); using var connectionManager1 = new SingleDeviceConnectionManager(loRaDeviceClient1.Object); using var loraDevice1 = TestUtils.CreateFromSimulatedDevice(simulatedDevice1, connectionManager1); var devAddr = loraDevice1.DevAddr.Value; var reqHandler1 = new Mock <ILoRaDataRequestHandler>(MockBehavior.Strict); reqHandler1.Setup(x => x.ProcessRequestAsync(It.IsNotNull <LoRaRequest>(), loraDevice1)) .ReturnsAsync(new LoRaDeviceRequestProcessResult(loraDevice1, null)); loraDevice1.SetRequestHandler(reqHandler1.Object); var simulatedDevice2 = new SimulatedDevice(TestDeviceInfo.CreateABPDevice(1, gatewayID: deviceGatewayID)); simulatedDevice2.LoRaDevice.DeviceID = new DevEui(2).ToString(); simulatedDevice2.LoRaDevice.NwkSKey = TestKeys.CreateNetworkSessionKey(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF); var loRaDeviceClient2 = new Mock <ILoRaDeviceClient>(MockBehavior.Loose); loRaDeviceClient2.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(simulatedDevice2.CreateABPTwin()); using var connectionManager2 = new SingleDeviceConnectionManager(loRaDeviceClient2.Object); using var loraDevice2 = TestUtils.CreateFromSimulatedDevice(simulatedDevice2, connectionManager2); // Api service: search devices async var iotHubDeviceInfo1 = new IoTHubDeviceInfo(devAddr, loraDevice1.DevEUI, string.Empty); var iotHubDeviceInfo2 = new IoTHubDeviceInfo(devAddr, loraDevice2.DevEUI, string.Empty); var apiService = new Mock <LoRaDeviceAPIServiceBase>(); apiService.Setup(x => x.SearchByDevAddrAsync(devAddr)) .ReturnsAsync(new SearchDevicesResult(new IoTHubDeviceInfo[] { iotHubDeviceInfo2, iotHubDeviceInfo1, })); // Device factory: create 2 devices this.loraDeviceFactoryMock.Setup(x => x.CreateAndRegisterAsync(iotHubDeviceInfo1, It.IsAny <CancellationToken>())).ReturnsAsync(() => { DeviceCache.Register(loraDevice1); return(loraDevice1); }); this.loraDeviceFactoryMock.Setup(x => x.CreateAndRegisterAsync(iotHubDeviceInfo2, It.IsAny <CancellationToken>())).ReturnsAsync(() => { DeviceCache.Register(loraDevice2); return(loraDevice2); }); using var target = new LoRaDeviceRegistry(ServerConfiguration, this.cache, apiService.Object, this.loraDeviceFactoryMock.Object, DeviceCache); using var request = WaitableLoRaRequest.Create(payload); target.GetLoRaRequestQueue(request).Queue(request); Assert.True(await request.WaitCompleteAsync()); Assert.True(request.ProcessingSucceeded); // Device was searched by DevAddr apiService.VerifyAll(); // Device was created by factory this.loraDeviceFactoryMock.VerifyAll(); // Both devices are in cache Assert.Equal(2, DeviceCache.RegistrationCount(devAddr)); // 2 devices with same devAddr exist in cache // find device 1 Assert.True(DeviceCache.TryGetForPayload(request.Payload, out var actualCachedLoRaDevice1)); Assert.Same(loraDevice1, actualCachedLoRaDevice1); Assert.True(loraDevice1.IsOurDevice); // find device 2 Assert.True(DeviceCache.TryGetByDevEui(loraDevice2.DevEUI, out var actualCachedLoRaDevice2)); Assert.Same(loraDevice2, actualCachedLoRaDevice2); Assert.True(loraDevice2.IsOurDevice); reqHandler1.VerifyAll(); }