public void When_Missed_Both_Windows_Should_Resolve_Window_0(int delayInMs) { var target = new LoRaOperationTimeWatcher(RegionFactory.CreateEU868Region(), DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMilliseconds(delayInMs))); var loRaDevice = new LoRaDevice("31312", "312321321", null); Assert.Equal(0, target.ResolveReceiveWindowToUse(loRaDevice)); }
public void After_One_Second_Join_First_Window_Should_Be_Greater_Than_3sec() { var target = new LoRaOperationTimeWatcher(RegionFactory.CreateEU868Region(), DateTimeOffset.UtcNow.Subtract(TimeSpan.FromSeconds(1))); var actual = target.GetRemainingTimeToJoinAcceptFirstWindow(); Assert.InRange(actual.TotalMilliseconds, 3500, 5000); }
public void After_5_Seconds_Join_First_Window_Should_Be_Negative() { var target = new LoRaOperationTimeWatcher(RegionFactory.CreateEU868Region(), DateTimeOffset.UtcNow.Subtract(TimeSpan.FromSeconds(5))); var actual = target.GetRemainingTimeToJoinAcceptFirstWindow(); Assert.True(actual.TotalMilliseconds < 0, $"First window is over, value should be negative"); }
public void When_Out_Of_Time_For_Join_Accept_Second_Window_Should_Resolve_Window_0(int delayInMs) { var target = new LoRaOperationTimeWatcher(RegionFactory.CreateEU868Region(), DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMilliseconds(delayInMs))); var loRaDevice = new LoRaDevice("31312", "312321321", null); Assert.Equal(0, target.ResolveJoinAcceptWindowToUse(loRaDevice)); }
public void When_Device_PreferredWindow1_In_Time_For_First_Window_Should_Get_Check_C2D_Avaible_Time_Correctly(int delayInMs, int expectedMinMs, int expectedMaxMs) { var target = new LoRaOperationTimeWatcher(RegionFactory.CreateEU868Region(), DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMilliseconds(delayInMs))); var loRaDevice = new LoRaDevice("1111", "2222", null); // Will be around 1000 - delay - 400 Assert.InRange(target.GetAvailableTimeToCheckCloudToDeviceMessage(loRaDevice), TimeSpan.FromMilliseconds(expectedMinMs), TimeSpan.FromMilliseconds(expectedMaxMs)); }
public void When_In_Time_For_First_Window_But_Device_Preferes_Seconds_Should_Resolve_Window_2(int delayInMs) { var target = new LoRaOperationTimeWatcher(RegionFactory.CreateEU868Region(), DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMilliseconds(delayInMs))); var loRaDevice = new LoRaDevice("31312", "312321321", null) { PreferredWindow = 2, }; Assert.Equal(2, target.ResolveReceiveWindowToUse(loRaDevice)); }
public void When_Device_Out_Of_Time_For_C2D_Receive_Should_Return_TimeSpan_Zero(int delayInMs, int devicePreferredReceiveWindow) { var target = new LoRaOperationTimeWatcher(RegionFactory.CreateEU868Region(), DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMilliseconds(delayInMs))); var loRaDevice = new LoRaDevice("1111", "2222", null) { PreferredWindow = devicePreferredReceiveWindow, }; Assert.Equal(TimeSpan.Zero, target.GetAvailableTimeToCheckCloudToDeviceMessage(loRaDevice)); }
public void TestPhysicalMappingEU( [CombinatorialValues("SF12BW125", "SF11BW125", "SF10BW125", "SF9BW125", "SF8BW125", "SF7BW125", "SF7BW250")] string datr, [CombinatorialValues(868.1, 868.3, 868.5)] double freq) { List <Rxpk> rxpk = GenerateRxpk(datr, freq); // in EU in standard parameters the expectation is that the reply arrive at same place. var expFreq = freq; var expDatr = datr; Assert.Equal(RegionFactory.CreateEU868Region().GetDownstreamChannelFrequency(rxpk[0]), expFreq); Assert.Equal(RegionFactory.CreateEU868Region().GetDownstreamDR(rxpk[0]), expDatr); }
public void EnsureRegionLimitTestAreWorking(double freq, string datarate, LoRaRegion region) { var rxpk = GenerateRxpk(datarate, freq); if (region == LoRaRegion.EU868) { Assert.Throws <RegionLimitException>(() => { RegionFactory.CreateEU868Region().GetDownstreamChannelFrequency(rxpk[0]); RegionFactory.CreateEU868Region().GetDownstreamDR(rxpk[0]); }); } if (region == LoRaRegion.US915) { Assert.Throws <RegionLimitException>(() => { RegionFactory.CreateUS915Region().GetDownstreamChannelFrequency(rxpk[0]); RegionFactory.CreateUS915Region().GetDownstreamDR(rxpk[0]); }); } }
public async Task OTAA_Join_Should_Use_Rchf_0(string deviceGatewayID, uint rfch) { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateOTAADevice(1, gatewayID: deviceGatewayID)); var joinRequest = simulatedDevice.CreateJoinRequest(); // Create Rxpk var joinRxpk = joinRequest.SerializeUplink(simulatedDevice.LoRaDevice.AppKey).Rxpk[0]; joinRxpk.Rfch = rfch; var devNonce = ConversionHelper.ByteArrayToString(joinRequest.DevNonce); var devAddr = string.Empty; var devEUI = simulatedDevice.LoRaDevice.DeviceID; var appEUI = simulatedDevice.LoRaDevice.AppEUI; var loRaDeviceClient = new Mock <ILoRaDeviceClient>(MockBehavior.Strict); // Device twin will be queried var twin = new Twin(); twin.Properties.Desired[TwinProperty.DevEUI] = devEUI; twin.Properties.Desired[TwinProperty.AppEUI] = simulatedDevice.LoRaDevice.AppEUI; twin.Properties.Desired[TwinProperty.AppKey] = simulatedDevice.LoRaDevice.AppKey; twin.Properties.Desired[TwinProperty.GatewayID] = deviceGatewayID; twin.Properties.Desired[TwinProperty.SensorDecoder] = simulatedDevice.LoRaDevice.SensorDecoder; loRaDeviceClient.Setup(x => x.GetTwinAsync()).ReturnsAsync(twin); // Device twin will be updated loRaDeviceClient.Setup(x => x.UpdateReportedPropertiesAsync(It.IsNotNull <TwinCollection>())) .ReturnsAsync(true); // Lora device api will be search by devices with matching deveui, var loRaDeviceApi = new Mock <LoRaDeviceAPIServiceBase>(MockBehavior.Strict); loRaDeviceApi.Setup(x => x.SearchAndLockForJoinAsync(this.ServerConfiguration.GatewayID, devEUI, appEUI, devNonce)) .ReturnsAsync(new SearchDevicesResult(new IoTHubDeviceInfo(devAddr, devEUI, "aabb").AsList())); // using factory to create mock of var loRaDeviceFactory = new TestLoRaDeviceFactory(loRaDeviceClient.Object); var memoryCache = new MemoryCache(new MemoryCacheOptions()); var deviceRegistry = new LoRaDeviceRegistry(this.ServerConfiguration, memoryCache, loRaDeviceApi.Object, loRaDeviceFactory); var frameCounterUpdateStrategyFactory = new LoRaDeviceFrameCounterUpdateStrategyFactory(this.ServerConfiguration.GatewayID, loRaDeviceApi.Object); // Send to message processor var messageProcessor = new MessageProcessor( this.ServerConfiguration, deviceRegistry, frameCounterUpdateStrategyFactory, new LoRaPayloadDecoder()); var downlinkJoinAcceptMessage = await messageProcessor.ProcessMessageAsync(joinRxpk); Assert.NotNull(downlinkJoinAcceptMessage); // validates txpk according to eu region Assert.Equal(0U, downlinkJoinAcceptMessage.Txpk.Rfch); Assert.Equal(RegionFactory.CreateEU868Region().GetDownstreamChannelFrequency(joinRxpk), downlinkJoinAcceptMessage.Txpk.Freq); Assert.Equal("4/5", downlinkJoinAcceptMessage.Txpk.Codr); Assert.False(downlinkJoinAcceptMessage.Txpk.Imme); Assert.True(downlinkJoinAcceptMessage.Txpk.Ipol); Assert.Equal("LORA", downlinkJoinAcceptMessage.Txpk.Modu); loRaDeviceClient.VerifyAll(); loRaDeviceApi.VerifyAll(); }
public async Task Join_And_Send_Unconfirmed_And_Confirmed_Messages(string deviceGatewayID, int initialFcntUp, int initialFcntDown, int startingPayloadFcnt, uint netId) { var simulatedDevice = new SimulatedDevice(TestDeviceInfo.CreateOTAADevice(1, gatewayID: deviceGatewayID)); var joinRequest = simulatedDevice.CreateJoinRequest(); // Create Rxpk var joinRxpk = joinRequest.SerializeUplink(simulatedDevice.LoRaDevice.AppKey).Rxpk[0]; var devNonce = LoRaTools.Utils.ConversionHelper.ByteArrayToString(joinRequest.DevNonce); var devAddr = string.Empty; var devEUI = simulatedDevice.LoRaDevice.DeviceID; var appEUI = simulatedDevice.LoRaDevice.AppEUI; var loRaDeviceClient = new Mock <ILoRaDeviceClient>(MockBehavior.Strict); this.ServerConfiguration.NetId = netId; // Device twin will be queried var twin = new Twin(); twin.Properties.Desired[TwinProperty.DevEUI] = devEUI; twin.Properties.Desired[TwinProperty.AppEUI] = simulatedDevice.LoRaDevice.AppEUI; twin.Properties.Desired[TwinProperty.AppKey] = simulatedDevice.LoRaDevice.AppKey; twin.Properties.Desired[TwinProperty.GatewayID] = deviceGatewayID; twin.Properties.Desired[TwinProperty.SensorDecoder] = simulatedDevice.LoRaDevice.SensorDecoder; twin.Properties.Reported[TwinProperty.FCntUp] = initialFcntUp; twin.Properties.Reported[TwinProperty.FCntDown] = initialFcntDown; loRaDeviceClient.Setup(x => x.GetTwinAsync()).ReturnsAsync(twin); // Device twin will be updated string afterJoinAppSKey = null; string afterJoinNwkSKey = null; string afterJoinDevAddr = null; int afterJoinFcntDown = -1; int afterJoinFcntUp = -1; loRaDeviceClient.Setup(x => x.UpdateReportedPropertiesAsync(It.IsNotNull <TwinCollection>())) .Callback <TwinCollection>((updatedTwin) => { afterJoinAppSKey = updatedTwin[TwinProperty.AppSKey]; afterJoinNwkSKey = updatedTwin[TwinProperty.NwkSKey]; afterJoinDevAddr = updatedTwin[TwinProperty.DevAddr]; afterJoinFcntDown = updatedTwin[TwinProperty.FCntDown]; afterJoinFcntUp = updatedTwin[TwinProperty.FCntUp]; }) .ReturnsAsync(true); // message will be sent var sentTelemetry = new List <LoRaDeviceTelemetry>(); loRaDeviceClient.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .Callback <LoRaDeviceTelemetry, Dictionary <string, string> >((t, _) => sentTelemetry.Add(t)) .ReturnsAsync(true); // C2D message will be checked loRaDeviceClient.Setup(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>())) .ReturnsAsync((Message)null); // Lora device api will be search by devices with matching deveui, var loRaDeviceApi = new Mock <LoRaDeviceAPIServiceBase>(MockBehavior.Strict); loRaDeviceApi.Setup(x => x.SearchAndLockForJoinAsync(this.ServerConfiguration.GatewayID, devEUI, appEUI, devNonce)) .ReturnsAsync(new SearchDevicesResult(new IoTHubDeviceInfo(devAddr, devEUI, "aabb").AsList())); // multi gateway will request a next frame count down from the lora device api, prepare it if (string.IsNullOrEmpty(deviceGatewayID)) { loRaDeviceApi.Setup(x => x.NextFCntDownAsync(devEUI, 0, startingPayloadFcnt + 1, this.ServerConfiguration.GatewayID)) .ReturnsAsync((ushort)1); } // using factory to create mock of var loRaDeviceFactory = new TestLoRaDeviceFactory(loRaDeviceClient.Object); var memoryCache = new MemoryCache(new MemoryCacheOptions()); var deviceRegistry = new LoRaDeviceRegistry(this.ServerConfiguration, memoryCache, loRaDeviceApi.Object, loRaDeviceFactory); var frameCounterUpdateStrategyFactory = new LoRaDeviceFrameCounterUpdateStrategyFactory(this.ServerConfiguration.GatewayID, loRaDeviceApi.Object); // Send to message processor var messageProcessor = new MessageProcessor( this.ServerConfiguration, deviceRegistry, frameCounterUpdateStrategyFactory, new LoRaPayloadDecoder()); var downlinkJoinAcceptMessage = await messageProcessor.ProcessMessageAsync(joinRxpk); Assert.NotNull(downlinkJoinAcceptMessage); var joinAccept = new LoRaPayloadJoinAccept(Convert.FromBase64String(downlinkJoinAcceptMessage.Txpk.Data), simulatedDevice.LoRaDevice.AppKey); Assert.Equal(joinAccept.DevAddr.ToArray(), ConversionHelper.StringToByteArray(afterJoinDevAddr)); // check that the device is in cache var devicesForDevAddr = deviceRegistry.InternalGetCachedDevicesForDevAddr(afterJoinDevAddr); Assert.Single(devicesForDevAddr); // should have the single device Assert.True(devicesForDevAddr.TryGetValue(devEUI, out var loRaDevice)); Assert.Equal(afterJoinAppSKey, loRaDevice.AppSKey); Assert.Equal(afterJoinNwkSKey, loRaDevice.NwkSKey); Assert.Equal(afterJoinDevAddr, loRaDevice.DevAddr); var netIdBytes = BitConverter.GetBytes(netId); Assert.Equal((uint)(netIdBytes[0] & 0b01111111), NetIdHelper.GetNwkIdPart(afterJoinDevAddr)); if (deviceGatewayID == null) { Assert.Null(loRaDevice.GatewayID); } else { Assert.Equal(deviceGatewayID, loRaDevice.GatewayID); } // fcnt is restarted Assert.Equal(0, afterJoinFcntDown); Assert.Equal(0, afterJoinFcntUp); Assert.Equal(0, loRaDevice.FCntUp); Assert.Equal(0, loRaDevice.FCntDown); Assert.False(loRaDevice.HasFrameCountChanges); simulatedDevice.LoRaDevice.AppSKey = afterJoinAppSKey; simulatedDevice.LoRaDevice.NwkSKey = afterJoinNwkSKey; simulatedDevice.LoRaDevice.DevAddr = afterJoinDevAddr; // sends unconfirmed message var unconfirmedMessagePayload = simulatedDevice.CreateUnconfirmedDataUpMessage("100", fcnt: startingPayloadFcnt); var unconfirmedMessageResult = await messageProcessor.ProcessMessageAsync(unconfirmedMessagePayload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey).Rxpk[0]); Assert.Null(unconfirmedMessageResult); // fcnt up was updated Assert.Equal(startingPayloadFcnt, loRaDevice.FCntUp); Assert.Equal(0, loRaDevice.FCntDown); if (startingPayloadFcnt != 0) { // Frame change flag will be set, only saving every 10 messages Assert.True(loRaDevice.HasFrameCountChanges); } Assert.Single(sentTelemetry); // sends confirmed message var confirmedMessagePayload = simulatedDevice.CreateConfirmedDataUpMessage("200", fcnt: startingPayloadFcnt + 1); var confirmedMessageRxpk = confirmedMessagePayload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey).Rxpk[0]; var confirmedMessage = await messageProcessor.ProcessMessageAsync(confirmedMessageRxpk); Assert.NotNull(confirmedMessage); Assert.NotNull(confirmedMessage.Txpk); Assert.Equal(2, sentTelemetry.Count); // validates txpk according to eu region Assert.Equal(RegionFactory.CreateEU868Region().GetDownstreamChannelFrequency(confirmedMessageRxpk), confirmedMessage.Txpk.Freq); Assert.Equal("4/5", confirmedMessage.Txpk.Codr); Assert.False(confirmedMessage.Txpk.Imme); Assert.True(confirmedMessage.Txpk.Ipol); Assert.Equal("LORA", confirmedMessage.Txpk.Modu); // fcnt up was updated Assert.Equal(startingPayloadFcnt + 1, loRaDevice.FCntUp); Assert.Equal(1, loRaDevice.FCntDown); // Frame change flag will be set, only saving every 10 messages Assert.True(loRaDevice.HasFrameCountChanges); // C2D message will be checked twice loRaDeviceClient.Verify(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>()), Times.Exactly(2)); // has telemetry with both fcnt Assert.Single(sentTelemetry, (t) => t.Fcnt == startingPayloadFcnt); Assert.Single(sentTelemetry, (t) => t.Fcnt == (startingPayloadFcnt + 1)); loRaDeviceClient.VerifyAll(); loRaDeviceApi.VerifyAll(); }
public async Task When_Device_Checks_For_C2D_Message_Uses_Available_Time( int preferredWindow, int sendEventDurationInMs, int checkMinDuration, int checkMaxDuration, int expectedRX) { const int PayloadFcnt = 10; const int InitialDeviceFcntUp = 9; const int InitialDeviceFcntDown = 20; var simulatedDevice = new SimulatedDevice( TestDeviceInfo.CreateABPDevice(1, gatewayID: this.ServerConfiguration.GatewayID), frmCntUp: InitialDeviceFcntUp, frmCntDown: InitialDeviceFcntDown); var devAddr = simulatedDevice.DevAddr; var devEUI = simulatedDevice.DevEUI; var loraDeviceClient = new Mock <ILoRaDeviceClient>(MockBehavior.Strict); var sentEventAsyncSetup = loraDeviceClient.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)); sentEventAsyncSetup.Returns(() => { if (sendEventDurationInMs > 0) { var task = Task.Delay(sendEventDurationInMs).ContinueWith <bool>((_) => true); task.ConfigureAwait(false); return(task); } return(Task.FromResult(true)); }); var cloudToDeviceMessage = new Message(Encoding.UTF8.GetBytes("c2d")); cloudToDeviceMessage.Properties[MessageProcessor.FPORT_MSG_PROPERTY_KEY] = "1"; loraDeviceClient.Setup(x => x.ReceiveAsync(It.IsInRange <TimeSpan>(TimeSpan.FromMilliseconds(checkMinDuration), TimeSpan.FromMilliseconds(checkMaxDuration), Range.Inclusive))) .ReturnsAsync(cloudToDeviceMessage); loraDeviceClient.Setup(x => x.ReceiveAsync(LoRaOperationTimeWatcher.MinimumAvailableTimeToCheckForCloudMessage)) .Returns(this.EmptyAdditionalMessageReceiveAsync); // 2nd cloud to device message does not return anything loraDeviceClient.Setup(x => x.CompleteAsync(cloudToDeviceMessage)) .ReturnsAsync(true); var loRaDeviceAPI = new Mock <LoRaDeviceAPIServiceBase>(); var loRaDevice = TestUtils.CreateFromSimulatedDevice(simulatedDevice, loraDeviceClient.Object); loRaDevice.PreferredWindow = preferredWindow; this.LoRaDeviceRegistry.Setup(x => x.GetDeviceForPayloadAsync(It.IsNotNull <LoRaPayloadData>())) .ReturnsAsync(loRaDevice); var loRaDeviceRegistry = new LoRaDeviceRegistry(this.ServerConfiguration, new MemoryCache(new MemoryCacheOptions()), loRaDeviceAPI.Object, new TestLoRaDeviceFactory(loraDeviceClient.Object)); // Send to message processor var messageProcessor = new MessageProcessor( this.ServerConfiguration, this.LoRaDeviceRegistry.Object, new LoRaDeviceFrameCounterUpdateStrategyFactory(this.ServerConfiguration.GatewayID, loRaDeviceAPI.Object), new LoRaPayloadDecoder()); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234", fcnt: PayloadFcnt); var rxpk = payload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey).Rxpk[0]; var actualDownlink = await messageProcessor.ProcessMessageAsync(rxpk); Assert.NotNull(actualDownlink); loraDeviceClient.VerifyAll(); this.LoRaDeviceRegistry.VerifyAll(); var euRegion = RegionFactory.CreateEU868Region(); if (expectedRX == 1) { // ensure response is for RX1 Assert.Equal(rxpk.Tmst + 1000000, actualDownlink.Txpk.Tmst); } else { // ensure response is for RX2 Assert.Equal(rxpk.Tmst + 2000000, actualDownlink.Txpk.Tmst); } }
public async Task When_Device_Prefers_Second_Window_Should_Send_Downstream_In_Second_Window() { const int PayloadFcnt = 10; const int InitialDeviceFcntUp = 9; const int InitialDeviceFcntDown = 20; var simulatedDevice = new SimulatedDevice( TestDeviceInfo.CreateABPDevice(1, gatewayID: this.ServerConfiguration.GatewayID), frmCntUp: InitialDeviceFcntUp, frmCntDown: InitialDeviceFcntDown); var devAddr = simulatedDevice.DevAddr; var devEUI = simulatedDevice.DevEUI; var loraDeviceClient = new Mock <ILoRaDeviceClient>(MockBehavior.Strict); // Will get twin to initialize LoRaDevice var deviceTwin = TestUtils.CreateABPTwin( simulatedDevice, desiredProperties: new Dictionary <string, object> { { TwinProperty.PreferredWindow, 2 } }); loraDeviceClient.Setup(x => x.GetTwinAsync()).ReturnsAsync(deviceTwin); loraDeviceClient.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .ReturnsAsync(true); loraDeviceClient.Setup(x => x.UpdateReportedPropertiesAsync(It.IsNotNull <TwinCollection>())) .ReturnsAsync(true); var cloudToDeviceMessage = new Message(Encoding.UTF8.GetBytes("c2d")); cloudToDeviceMessage.Properties[MessageProcessor.FPORT_MSG_PROPERTY_KEY] = "1"; loraDeviceClient.SetupSequence(x => x.ReceiveAsync(It.IsAny <TimeSpan>())) .ReturnsAsync(cloudToDeviceMessage) .Returns(this.EmptyAdditionalMessageReceiveAsync); // 2nd cloud to device message does not return anything loraDeviceClient.Setup(x => x.CompleteAsync(cloudToDeviceMessage)) .ReturnsAsync(true); var payloadDecoder = new Mock <ILoRaPayloadDecoder>(); var loRaDeviceAPI = new Mock <LoRaDeviceAPIServiceBase>(); loRaDeviceAPI.Setup(x => x.SearchByDevAddrAsync(devAddr)) .ReturnsAsync(new SearchDevicesResult(new IoTHubDeviceInfo(devAddr, devEUI, "adad").AsList())); var loRaDeviceRegistry = new LoRaDeviceRegistry(this.ServerConfiguration, new MemoryCache(new MemoryCacheOptions()), loRaDeviceAPI.Object, new TestLoRaDeviceFactory(loraDeviceClient.Object)); // Send to message processor var messageProcessor = new MessageProcessor( this.ServerConfiguration, loRaDeviceRegistry, new LoRaDeviceFrameCounterUpdateStrategyFactory(this.ServerConfiguration.GatewayID, loRaDeviceAPI.Object), new LoRaPayloadDecoder()); var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234", fcnt: PayloadFcnt); var rxpk = payload.SerializeUplink(simulatedDevice.AppSKey, simulatedDevice.NwkSKey).Rxpk[0]; var actual = await messageProcessor.ProcessMessageAsync(rxpk); // Expectations // 1. Message was sent to IoT Hub loraDeviceClient.VerifyAll(); // 2. Single gateway frame counter strategy was used this.FrameCounterUpdateStrategyFactory.VerifyAll(); // 3. Return is downstream message Assert.NotNull(actual); Assert.IsType <DownlinkPktFwdMessage>(actual); var downlinkMessage = (DownlinkPktFwdMessage)actual; var euRegion = RegionFactory.CreateEU868Region(); // Ensure we are using second window frequency Assert.Equal(euRegion.RX2DefaultReceiveWindows.frequency, actual.Txpk.Freq); // Ensure we are using second window datr Assert.Equal(euRegion.DRtoConfiguration[euRegion.RX2DefaultReceiveWindows.dr].configuration, actual.Txpk.Datr); // Ensure tmst was computed to 2 seconds (2 windows in Europe) Assert.Equal(2000000, actual.Txpk.Tmst); // Get the device from registry var deviceDictionary = loRaDeviceRegistry.InternalGetCachedDevicesForDevAddr(devAddr); Assert.True(deviceDictionary.TryGetValue(simulatedDevice.DevEUI, out var loRaDevice)); var payloadDataDown = new LoRaPayloadData(Convert.FromBase64String(downlinkMessage.Txpk.Data)); payloadDataDown.PerformEncryption(loRaDevice.AppSKey); Assert.Equal(payloadDataDown.DevAddr.ToArray(), ConversionHelper.StringToByteArray(loRaDevice.DevAddr)); Assert.False(payloadDataDown.IsConfirmed()); Assert.Equal(LoRaMessageType.UnconfirmedDataDown, payloadDataDown.LoRaMessageType); // 4. Frame counter up was updated Assert.Equal(PayloadFcnt, loRaDevice.FCntUp); // 5. Frame counter down is updated var expectedFcntDown = InitialDeviceFcntDown + 10 + 1; // adding 10 as buffer when creating a new device instance Assert.Equal(expectedFcntDown, loRaDevice.FCntDown); Assert.Equal(expectedFcntDown, payloadDataDown.GetFcnt()); // 6. Frame count has no pending changes Assert.False(loRaDevice.HasFrameCountChanges); }
public void After_6_Seconds_Should_Not_Be_In_Time_For_Join() { var target = new LoRaOperationTimeWatcher(RegionFactory.CreateEU868Region(), DateTimeOffset.UtcNow.Subtract(TimeSpan.FromSeconds(6))); Assert.False(target.InTimeForJoinAccept()); }