// Creates a new instance of NetworkServerConfiguration by reading values from environment variables public static NetworkServerConfiguration CreateFromEnvironmentVariables() { var config = new NetworkServerConfiguration(); // Create case insensitive dictionary from environment variables var envVars = new CaseInsensitiveEnvironmentVariables(Environment.GetEnvironmentVariables()); config.RunningAsIoTEdgeModule = !string.IsNullOrEmpty(envVars.GetEnvVar("IOTEDGE_APIVERSION", string.Empty)); config.IoTHubHostName = envVars.GetEnvVar("IOTEDGE_IOTHUBHOSTNAME", string.Empty); config.GatewayHostName = envVars.GetEnvVar("IOTEDGE_GATEWAYHOSTNAME", string.Empty); config.EnableGateway = envVars.GetEnvVar("ENABLE_GATEWAY", config.EnableGateway); config.GatewayID = envVars.GetEnvVar("IOTEDGE_DEVICEID", string.Empty); config.HttpsProxy = envVars.GetEnvVar("HTTPS_PROXY", string.Empty); config.Rx2DataRate = envVars.GetEnvVar("RX2_DATR", -1) is var datrNum && (DataRateIndex)datrNum is var datr && Enum.IsDefined(datr) ? datr : null; config.Rx2Frequency = envVars.GetEnvVar("RX2_FREQ") is { } someFreq?Hertz.Mega(someFreq) : null; config.IoTEdgeTimeout = envVars.GetEnvVar("IOTEDGE_TIMEOUT", config.IoTEdgeTimeout); // facadeurl is allowed to be null as the value is coming from the twin in production. var facadeUrl = envVars.GetEnvVar("FACADE_SERVER_URL", string.Empty); config.FacadeServerUrl = string.IsNullOrEmpty(facadeUrl) ? null : new Uri(envVars.GetEnvVar("FACADE_SERVER_URL", string.Empty)); config.FacadeAuthCode = envVars.GetEnvVar("FACADE_AUTH_CODE", string.Empty); config.LogLevel = envVars.GetEnvVar("LOG_LEVEL", config.LogLevel); config.LogToConsole = envVars.GetEnvVar("LOG_TO_CONSOLE", config.LogToConsole); config.LogToTcp = envVars.GetEnvVar("LOG_TO_TCP", config.LogToTcp); config.LogToHub = envVars.GetEnvVar("LOG_TO_HUB", config.LogToHub); config.LogToTcpAddress = envVars.GetEnvVar("LOG_TO_TCP_ADDRESS", string.Empty); config.LogToTcpPort = envVars.GetEnvVar("LOG_TO_TCP_PORT", config.LogToTcpPort); config.NetId = new NetId(envVars.GetEnvVar("NETID", config.NetId.NetworkId)); config.AllowedDevAddresses = envVars.GetEnvVar("AllowedDevAddresses", string.Empty) .Split(";") .Select(s => DevAddr.TryParse(s, out var devAddr) ? (true, Value: devAddr) : default)
public static RadioMetadata GenerateTestRadioMetadata( DataRateIndex dataRate = DataRateIndex.DR2, Hertz?frequency = null, uint antennaPreference = 1, ulong xtime = 100000, uint gpstime = 100000, double rssi = 2.0, float snr = 0.1f) => new RadioMetadata(dataRate, frequency ?? Hertz.Mega(868.3), new RadioMetadataUpInfo(antennaPreference, xtime, gpstime, rssi, snr));
public async Task When_Has_Custom_RX2DR_Should_Send_Correctly() { var devAddr = new DevAddr(0x023637F8); var appSKey = TestKeys.CreateAppSessionKey(0xABC0200000000000, 0x09); var nwkSKey = TestKeys.CreateNetworkSessionKey(0xABC0200000000000, 0x09); var simDevice = new SimulatedDevice(TestDeviceInfo.CreateOTAADevice(1, deviceClassType: 'c', gatewayID: ServerGatewayID)); var devEUI = simDevice.DevEUI; simDevice.SetupJoin(appSKey, nwkSKey, devAddr); this.deviceApi.Setup(x => x.GetPrimaryKeyByEuiAsync(devEUI)) .ReturnsAsync("123"); var twin = simDevice.CreateOTAATwin( desiredProperties: new Dictionary <string, object> { { TwinProperty.RX2DataRate, "10" } }, reportedProperties: new Dictionary <string, object> { { TwinProperty.RX2DataRate, 10 }, { TwinProperty.Region, LoRaRegionType.US915.ToString() }, // OTAA device, already joined { TwinProperty.DevAddr, devAddr.ToString() }, { TwinProperty.AppSKey, appSKey.ToString() }, { TwinProperty.NwkSKey, nwkSKey.ToString() }, { TwinProperty.LastProcessingStationEui, new StationEui(ulong.MaxValue).ToString() } }); this.deviceClient.Setup(x => x.GetTwinAsync(CancellationToken.None)) .ReturnsAsync(twin); var c2dToDeviceMessage = new ReceivedLoRaCloudToDeviceMessage() { Payload = "hello", DevEUI = devEUI, Fport = TestPort, MessageId = Guid.NewGuid().ToString(), }; DownlinkMessage receivedDownlinkMessage = null; this.downstreamMessageSender.Setup(x => x.SendDownstreamAsync(It.IsNotNull <DownlinkMessage>())) .Returns(Task.CompletedTask) .Callback <DownlinkMessage>(d => receivedDownlinkMessage = d); var target = new DefaultClassCDevicesMessageSender( this.serverConfiguration, this.loRaDeviceRegistry, this.downstreamMessageSender.Object, this.frameCounterStrategyProvider, NullLogger <DefaultClassCDevicesMessageSender> .Instance, TestMeter.Instance); Assert.True(await target.SendAsync(c2dToDeviceMessage)); this.downstreamMessageSender.Verify(x => x.SendDownstreamAsync(It.IsNotNull <DownlinkMessage>()), Times.Once()); EnsureDownlinkIsCorrect(receivedDownlinkMessage, simDevice, c2dToDeviceMessage); Assert.Equal(DataRateIndex.DR10, receivedDownlinkMessage.Rx2.DataRate); Assert.Equal(Hertz.Mega(923.3), receivedDownlinkMessage.Rx2.Frequency); this.downstreamMessageSender.VerifyAll(); this.deviceApi.VerifyAll(); this.deviceClient.VerifyAll(); }
private async Task <uint> SendMessage(float currentLsnr, LoRaDataRate currentDR, uint payloadFcnt, SimulatedDevice simulatedDevice, MessageDispatcher messageProcessor, FrameControlFlags fctrl) { var payloadInt = simulatedDevice.CreateUnconfirmedDataUpMessage("1234", fcnt: payloadFcnt, fctrlFlags: fctrl); using var requestInt = CreateWaitableRequest(new RadioMetadata(TestUtils.TestRegion.GetDataRateIndex(currentDR), Hertz.Mega(868.1), new RadioMetadataUpInfo(0, 0, 0, 0, currentLsnr)), payloadInt); messageProcessor.DispatchRequest(requestInt); Assert.True(await requestInt.WaitCompleteAsync(-1)); payloadFcnt++; return(payloadFcnt); }
public async Task Perform_NbRep_Adaptation_When_Needed() { uint deviceId = 31; var currentDR = LoRaDataRate.SF8BW125; var currentLsnr = -20; var messageCount = 20; uint payloadFcnt = 0; const uint InitialDeviceFcntUp = 1; const uint ExpectedDeviceFcntDown = 4; var simulatedDevice = new SimulatedDevice( TestDeviceInfo.CreateABPDevice(deviceId, gatewayID: ServerConfiguration.GatewayID), frmCntUp: InitialDeviceFcntUp); var loraDevice = CreateLoRaDevice(simulatedDevice); LoRaDeviceClient.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .ReturnsAsync(true); LoRaDeviceClient.Setup(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>())) .ReturnsAsync((Message)null); var reportedNbRep = 0; LoRaDeviceClient.Setup(x => x.UpdateReportedPropertiesAsync(It.IsNotNull <TwinCollection>(), It.IsAny <CancellationToken>())) .Callback <TwinCollection, CancellationToken>((t, _) => { if (t.Contains(TwinProperty.NbRep)) { reportedNbRep = (int)t[TwinProperty.NbRep]; } }) .ReturnsAsync(true); using var cache = EmptyMemoryCache(); using var loraDeviceCache = CreateDeviceCache(loraDevice); using var deviceRegistry = new LoRaDeviceRegistry(ServerConfiguration, cache, LoRaDeviceApi.Object, LoRaDeviceFactory, loraDeviceCache); // Send to message processor using var messageProcessor = new MessageDispatcher( ServerConfiguration, deviceRegistry, FrameCounterUpdateStrategyProvider); payloadFcnt = await InitializeCacheToDefaultValuesAsync(payloadFcnt, simulatedDevice, messageProcessor); // **************************************************** // First part send messages with spaces in fcnt to simulate wrong network connectivity // **************************************************** // send a message with a fcnt every 4. for (var i = 0; i < messageCount; i++) { payloadFcnt = await SendMessage(currentLsnr, currentDR, payloadFcnt + 3, simulatedDevice, messageProcessor, FrameControlFlags.Adr); } var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234", fcnt: payloadFcnt, fctrlFlags: FrameControlFlags.AdrAckReq | FrameControlFlags.Adr); var radioMetadata = new RadioMetadata(TestUtils.TestRegion.GetDataRateIndex(currentDR), Hertz.Mega(868.1), new RadioMetadataUpInfo(0, 0, 0, 0, currentLsnr)); using var request = CreateWaitableRequest(radioMetadata, payload); messageProcessor.DispatchRequest(request); Assert.True(await request.WaitCompleteAsync()); // Expectations // 1. Message was sent to IoT Hub LoRaDeviceClient.VerifyAll(); LoRaDeviceApi.VerifyAll(); Assert.True(request.ProcessingSucceeded); Assert.NotNull(request.ResponseDownlink); Assert.Equal(2, DownstreamMessageSender.DownlinkMessages.Count); var downlinkMessage = DownstreamMessageSender.DownlinkMessages[1]; var payloadDataDown = new LoRaPayloadData(downlinkMessage.Data); // We expect a mac command in the payload Assert.Equal(5, payloadDataDown.Frmpayload.Span.Length); var decryptedPayload = payloadDataDown.Serialize(simulatedDevice.NwkSKey.Value); Assert.Equal(FramePort.MacCommand, payloadDataDown.Fport); Assert.Equal((byte)Cid.LinkADRCmd, decryptedPayload[0]); var linkAdr = new LinkADRRequest(decryptedPayload); Assert.Equal(3, reportedNbRep); Assert.Equal(3, linkAdr.NbRep); Assert.Equal(3, loraDevice.NbRep); // **************************************************** // Second part send normal messages to decrease NbRep // **************************************************** // send a message with a fcnt every 1 for (var i = 0; i < messageCount; i++) { payloadFcnt = await SendMessage(currentLsnr, currentDR, payloadFcnt, simulatedDevice, messageProcessor, FrameControlFlags.Adr); } payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234", fcnt: payloadFcnt, fctrlFlags: FrameControlFlags.AdrAckReq | FrameControlFlags.Adr); using var secondRequest = CreateWaitableRequest(radioMetadata, payload); messageProcessor.DispatchRequest(secondRequest); Assert.True(await secondRequest.WaitCompleteAsync()); // Expectations // 1. Message was sent to IoT Hub LoRaDeviceClient.VerifyAll(); LoRaDeviceApi.VerifyAll(); Assert.True(secondRequest.ProcessingSucceeded); Assert.NotNull(secondRequest.ResponseDownlink); Assert.Equal(3, DownstreamMessageSender.DownlinkMessages.Count); downlinkMessage = DownstreamMessageSender.DownlinkMessages[2]; payloadDataDown = new LoRaPayloadData(downlinkMessage.Data); // We expect a mac command in the payload Assert.Equal(5, payloadDataDown.Frmpayload.Span.Length); decryptedPayload = payloadDataDown.Serialize(simulatedDevice.NwkSKey.Value); Assert.Equal(FramePort.MacCommand, payloadDataDown.Fport); Assert.Equal((byte)Cid.LinkADRCmd, decryptedPayload[0]); linkAdr = new LinkADRRequest(decryptedPayload); Assert.Equal(2, reportedNbRep); Assert.Equal(2, linkAdr.NbRep); Assert.Equal(2, loraDevice.NbRep); // in case no payload the mac is in the FRMPayload and is decrypted with NwkSKey Assert.Equal(payloadDataDown.DevAddr, loraDevice.DevAddr); Assert.False(payloadDataDown.IsConfirmed); Assert.Equal(MacMessageType.UnconfirmedDataDown, payloadDataDown.MessageType); // 4. Frame counter up was updated Assert.Equal(payloadFcnt, loraDevice.FCntUp); // **************************************************** // Third part send normal messages to decrease NbRep to 1 // **************************************************** // send a message with a fcnt every 1 for (var i = 0; i < messageCount; i++) { payloadFcnt = await SendMessage(currentLsnr, currentDR, payloadFcnt, simulatedDevice, messageProcessor, FrameControlFlags.Adr); } payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234", fcnt: payloadFcnt, fctrlFlags: FrameControlFlags.AdrAckReq | FrameControlFlags.Adr); using var thirdRequest = CreateWaitableRequest(radioMetadata, payload); messageProcessor.DispatchRequest(thirdRequest); Assert.True(await thirdRequest.WaitCompleteAsync()); // Expectations // 1. Message was sent to IoT Hub LoRaDeviceClient.VerifyAll(); LoRaDeviceApi.VerifyAll(); Assert.True(thirdRequest.ProcessingSucceeded); Assert.NotNull(thirdRequest.ResponseDownlink); Assert.Equal(4, DownstreamMessageSender.DownlinkMessages.Count); downlinkMessage = DownstreamMessageSender.DownlinkMessages[3]; payloadDataDown = new LoRaPayloadData(downlinkMessage.Data); // We expect a mac command in the payload Assert.Equal(5, payloadDataDown.Frmpayload.Span.Length); decryptedPayload = payloadDataDown.Serialize(simulatedDevice.NwkSKey.Value); Assert.Equal(FramePort.MacCommand, payloadDataDown.Fport); Assert.Equal((byte)Cid.LinkADRCmd, decryptedPayload[0]); linkAdr = new LinkADRRequest(decryptedPayload); Assert.Equal(1, reportedNbRep); Assert.Equal(1, linkAdr.NbRep); Assert.Equal(1, loraDevice.NbRep); // 5. Frame counter down is updated Assert.Equal(ExpectedDeviceFcntDown, loraDevice.FCntDown); Assert.Equal(ExpectedDeviceFcntDown, payloadDataDown.Fcnt); }
public async Task Perform_TXPower_Adaptation_When_Needed() { uint deviceId = 44; var messageCount = 21; uint payloadFcnt = 0; const uint InitialDeviceFcntUp = 9; const uint InitialDeviceFcntDown = 0; var simulatedDevice = new SimulatedDevice( TestDeviceInfo.CreateABPDevice(deviceId, gatewayID: ServerConfiguration.GatewayID), frmCntUp: InitialDeviceFcntUp); var loraDevice = CreateLoRaDevice(simulatedDevice); LoRaDeviceClient.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .ReturnsAsync(true); LoRaDeviceClient.Setup(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>())) .ReturnsAsync((Message)null); var reportedDR = DR0; var reportedTxPower = 0; LoRaDeviceClient.Setup(x => x.UpdateReportedPropertiesAsync(It.IsNotNull <TwinCollection>(), It.IsAny <CancellationToken>())) .Callback <TwinCollection, CancellationToken>((t, _) => { if (t.Contains(TwinProperty.DataRate)) { reportedDR = (DataRateIndex)(int)(object)t[TwinProperty.DataRate].Value; } if (t.Contains(TwinProperty.TxPower)) { reportedTxPower = t[TwinProperty.TxPower].Value; } }) .ReturnsAsync(true); using var cache = EmptyMemoryCache(); using var loraDeviceCache = CreateDeviceCache(loraDevice); using var deviceRegistry = new LoRaDeviceRegistry(ServerConfiguration, cache, LoRaDeviceApi.Object, LoRaDeviceFactory, loraDeviceCache); // Send to message processor using var messageProcessor = new MessageDispatcher( ServerConfiguration, deviceRegistry, FrameCounterUpdateStrategyProvider); payloadFcnt = await InitializeCacheToDefaultValuesAsync(payloadFcnt, simulatedDevice, messageProcessor); // **************************************************** // First part gives very good connectivity and ensure we set power to minimum and DR increase to 5 // **************************************************** // set to very good lsnr and DR3 float currentLsnr = 20; var currentDR = LoRaDataRate.SF9BW125; // todo add case without buffer for (var i = 0; i < messageCount; i++) { payloadFcnt = await SendMessage(currentLsnr, currentDR, payloadFcnt, simulatedDevice, messageProcessor, FrameControlFlags.Adr); } var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234", fcnt: payloadFcnt, fctrlFlags: FrameControlFlags.AdrAckReq | FrameControlFlags.Adr); var radioMetadata = new RadioMetadata(TestUtils.TestRegion.GetDataRateIndex(currentDR), Hertz.Mega(868.1), new RadioMetadataUpInfo(0, 0, 0, 0, currentLsnr)); using var request = CreateWaitableRequest(radioMetadata, payload); messageProcessor.DispatchRequest(request); Assert.True(await request.WaitCompleteAsync()); Assert.NotNull(request.ResponseDownlink); Assert.Equal(2, DownstreamMessageSender.DownlinkMessages.Count); var downlinkMessage = DownstreamMessageSender.DownlinkMessages[1]; var payloadDataDown = new LoRaPayloadData(downlinkMessage.Data); // We expect a mac command in the payload Assert.Equal(5, payloadDataDown.Frmpayload.Span.Length); var decryptedPayload = payloadDataDown.Serialize(simulatedDevice.NwkSKey.Value); Assert.Equal(FramePort.MacCommand, payloadDataDown.Fport); Assert.Equal((byte)Cid.LinkADRCmd, decryptedPayload[0]); var linkAdr = new LinkADRRequest(decryptedPayload); Assert.Equal(DR5, linkAdr.DataRate); Assert.Equal(DR5, loraDevice.DataRate); Assert.Equal(DR5, reportedDR); Assert.Equal(7, linkAdr.TxPower); Assert.Equal(7, loraDevice.TxPower); Assert.Equal(7, reportedTxPower); Assert.Equal(payloadDataDown.DevAddr, loraDevice.DevAddr); Assert.False(payloadDataDown.IsConfirmed); Assert.Equal(MacMessageType.UnconfirmedDataDown, payloadDataDown.MessageType); // 4. Frame counter up was updated Assert.Equal(payloadFcnt, loraDevice.FCntUp); // 5. Frame counter down is updated Assert.Equal(InitialDeviceFcntDown + 1, loraDevice.FCntDown); Assert.Equal(InitialDeviceFcntDown + 1, payloadDataDown.Fcnt); // **************************************************** // Second part reduce connectivity and verify the DR stay to 5 and power set to max // **************************************************** currentLsnr = -50; // DR5 currentDR = LoRaDataRate.SF7BW125; // todo add case without buffer for (var i = 0; i < messageCount; i++) { payloadFcnt = await SendMessage(currentLsnr, currentDR, payloadFcnt, simulatedDevice, messageProcessor, FrameControlFlags.Adr); } payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234", fcnt: payloadFcnt, fctrlFlags: FrameControlFlags.AdrAckReq | FrameControlFlags.Adr); var radioMetadataWithDatr5 = new RadioMetadata(TestUtils.TestRegion.GetDataRateIndex(currentDR), Hertz.Mega(868.1), new RadioMetadataUpInfo(0, 0, 0, 0, currentLsnr)); using var secondRequest = CreateWaitableRequest(radioMetadataWithDatr5, payload); messageProcessor.DispatchRequest(secondRequest); Assert.True(await secondRequest.WaitCompleteAsync()); Assert.NotNull(secondRequest.ResponseDownlink); Assert.Equal(3, DownstreamMessageSender.DownlinkMessages.Count); downlinkMessage = DownstreamMessageSender.DownlinkMessages[2]; payloadDataDown = new LoRaPayloadData(downlinkMessage.Data); // We expect a mac command in the payload Assert.Equal(5, payloadDataDown.Frmpayload.Span.Length); decryptedPayload = payloadDataDown.Serialize(simulatedDevice.NwkSKey.Value); Assert.Equal(FramePort.MacCommand, payloadDataDown.Fport); Assert.Equal((byte)Cid.LinkADRCmd, decryptedPayload[0]); linkAdr = new LinkADRRequest(decryptedPayload); Assert.Equal(DR5, linkAdr.DataRate); Assert.Equal(DR5, loraDevice.DataRate); Assert.Equal(DR5, reportedDR); Assert.Equal(0, linkAdr.TxPower); Assert.Equal(0, loraDevice.TxPower); Assert.Equal(0, reportedTxPower); Assert.Equal(payloadDataDown.DevAddr, loraDevice.DevAddr); Assert.False(payloadDataDown.IsConfirmed); Assert.Equal(MacMessageType.UnconfirmedDataDown, payloadDataDown.MessageType); // 4. Frame counter up was updated Assert.Equal(payloadFcnt, loraDevice.FCntUp); // 5. Frame counter down is updated Assert.Equal(InitialDeviceFcntDown + 2, loraDevice.FCntDown); Assert.Equal(InitialDeviceFcntDown + 2, payloadDataDown.Fcnt); // Expectations // 1. Message was sent to IoT Hub LoRaDeviceClient.VerifyAll(); LoRaDeviceApi.VerifyAll(); Assert.True(secondRequest.ProcessingSucceeded); }
public async Task Perform_DR_Adaptation_When_Needed(uint deviceId, float currentLsnr, string currentDRString, DataRateIndex expectedDR, int expectedTxPower) { var currentDR = LoRaDataRate.Parse(currentDRString); var messageCount = 21; uint payloadFcnt = 0; const uint InitialDeviceFcntUp = 9; const uint ExpectedDeviceFcntDown = 0; var simulatedDevice = new SimulatedDevice( TestDeviceInfo.CreateABPDevice(deviceId, gatewayID: ServerConfiguration.GatewayID), frmCntUp: InitialDeviceFcntUp); var loraDevice = CreateLoRaDevice(simulatedDevice); LoRaDeviceClient.Setup(x => x.SendEventAsync(It.IsNotNull <LoRaDeviceTelemetry>(), null)) .ReturnsAsync(true); LoRaDeviceClient.Setup(x => x.ReceiveAsync(It.IsNotNull <TimeSpan>())) .ReturnsAsync((Message)null); var twinDR = DR0; var twinTxPower = 0; LoRaDeviceClient.Setup(x => x.UpdateReportedPropertiesAsync(It.IsNotNull <TwinCollection>(), It.IsAny <CancellationToken>())) .Callback <TwinCollection, CancellationToken>((t, _) => { if (t.Contains(TwinProperty.DataRate)) { twinDR = t[TwinProperty.DataRate]; } if (t.Contains(TwinProperty.TxPower)) { twinTxPower = (int)t[TwinProperty.TxPower]; } }) .ReturnsAsync(true); using var cache = EmptyMemoryCache(); using var loraDeviceCache = CreateDeviceCache(loraDevice); using var deviceRegistry = new LoRaDeviceRegistry(ServerConfiguration, cache, LoRaDeviceApi.Object, LoRaDeviceFactory, loraDeviceCache); // Send to message processor using var messageProcessor = new MessageDispatcher( ServerConfiguration, deviceRegistry, FrameCounterUpdateStrategyProvider); payloadFcnt = await InitializeCacheToDefaultValuesAsync(payloadFcnt, simulatedDevice, messageProcessor); for (var i = 0; i < messageCount; i++) { payloadFcnt = await SendMessage(currentLsnr, currentDR, payloadFcnt, simulatedDevice, messageProcessor, FrameControlFlags.Adr); } var payload = simulatedDevice.CreateUnconfirmedDataUpMessage("1234", fcnt: payloadFcnt, fctrlFlags: FrameControlFlags.AdrAckReq | FrameControlFlags.Adr); var radioMetadata = new RadioMetadata(TestUtils.TestRegion.GetDataRateIndex(currentDR), Hertz.Mega(868.1), new RadioMetadataUpInfo(0, 0, 0, 0, currentLsnr)); using var request = CreateWaitableRequest(radioMetadata, payload); messageProcessor.DispatchRequest(request); Assert.True(await request.WaitCompleteAsync()); // Expectations // 1. Message was sent to IoT Hub LoRaDeviceClient.VerifyAll(); LoRaDeviceApi.VerifyAll(); Assert.True(request.ProcessingSucceeded); Assert.NotNull(request.ResponseDownlink); var downlinkMessage = DownstreamMessageSender.DownlinkMessages[1]; var payloadDataDown = new LoRaPayloadData(downlinkMessage.Data); // We expect a mac command in the payload if (deviceId == 221) { // In this case, no ADR adaptation is performed, so the message should be empty Assert.Equal(0, payloadDataDown.Frmpayload.Span.Length); Assert.Equal(0, payloadDataDown.Fopts.Span.Length); } else { Assert.Equal(5, payloadDataDown.Frmpayload.Span.Length); var decryptedPayload = payloadDataDown.Serialize(simulatedDevice.NwkSKey.Value); Assert.Equal(FramePort.MacCommand, payloadDataDown.Fport); Assert.Equal((byte)Cid.LinkADRCmd, decryptedPayload[0]); var linkAdr = new LinkADRRequest(decryptedPayload); Assert.Equal(expectedDR, linkAdr.DataRate); Assert.Equal(expectedDR, loraDevice.DataRate); Assert.Equal(expectedDR, twinDR); Assert.Equal(expectedTxPower, linkAdr.TxPower); Assert.Equal(expectedTxPower, loraDevice.TxPower); Assert.Equal(expectedTxPower, twinTxPower); // in case no payload the mac is in the FRMPayload and is decrypted with NwkSKey Assert.Equal(payloadDataDown.DevAddr, loraDevice.DevAddr); Assert.False(payloadDataDown.IsConfirmed); Assert.Equal(MacMessageType.UnconfirmedDataDown, payloadDataDown.MessageType); // 4. Frame counter up was updated Assert.Equal(payloadFcnt, loraDevice.FCntUp); // 5. Frame counter down is updated Assert.Equal(ExpectedDeviceFcntDown + 1, loraDevice.FCntDown); Assert.Equal(ExpectedDeviceFcntDown + 1, payloadDataDown.Fcnt); } }
public async Task SendDownstreamAsync_Succeeds_WithValidDownlinkMessage_ClassADevice(bool rfchHasValue) { // arrange var downlinkMessage = new DownlinkMessage(this.loraDataByteArray, 123456, new ReceiveWindow(DataRateIndex.DR5, Hertz.Mega(868.5)), new ReceiveWindow(DataRateIndex.DR0, Hertz.Mega(869.5)), this.devEui, RxDelay1, LoRaDeviceClassType.A, this.stationEui, rfchHasValue ? 1 : null); var actualMessage = string.Empty; this.webSocketWriter.Setup(s => s.SendAsync(It.IsAny <string>(), It.IsAny <CancellationToken>())) .Callback <string, CancellationToken>((message, _) => { actualMessage = message; }); // act await downlinkSender.SendDownstreamAsync(downlinkMessage); // assert Assert.NotEmpty(actualMessage); Assert.Contains(@"""msgtype"":""dnmsg""", actualMessage, StringComparison.InvariantCulture); Assert.Contains(@"""DevEui"":""FFFFFFFFFFFFFFFF"",", actualMessage, StringComparison.InvariantCulture); Assert.Contains(@"""dC"":0", actualMessage, StringComparison.InvariantCulture); Assert.Contains(@"""pdu"":""5245465551513D3D"",", actualMessage, StringComparison.InvariantCulture); Assert.Contains(@"""RxDelay"":1,", actualMessage, StringComparison.InvariantCulture); Assert.Contains(@"""RX1DR"":5,", actualMessage, StringComparison.InvariantCulture); Assert.Contains(@"""RX1Freq"":868500000,", actualMessage, StringComparison.InvariantCulture); Assert.Contains(@"""RX2DR"":0,", actualMessage, StringComparison.InvariantCulture); Assert.Contains(@"""RX2Freq"":869500000,", actualMessage, StringComparison.InvariantCulture); Assert.Contains(@"""xtime"":123456,", actualMessage, StringComparison.InvariantCulture); Assert.Contains(@"""priority"":0", actualMessage, StringComparison.InvariantCulture); if (rfchHasValue) { Assert.Contains(@"""rctx"":1", actualMessage, StringComparison.InvariantCulture); } else { Assert.DoesNotContain("rctx", actualMessage, StringComparison.InvariantCulture); } }
public async Task SendDownstreamAsync_Fails_WithNonNullMessage_ButDefaultStationEui() { // arrange var downlinkMessage = new DownlinkMessage(this.loraDataByteArray, 0, new ReceiveWindow(DataRateIndex.DR5, Hertz.Mega(868.5)), new ReceiveWindow(DataRateIndex.DR0, Hertz.Mega(868.5)), this.devEui, RxDelay0, LoRaDeviceClassType.C); // act and assert await Assert.ThrowsAsync <ArgumentException>(() => this.downlinkSender.SendDownstreamAsync(downlinkMessage)); }