public async Task Data_Rate_Is_Updated_When_C2D_With_LinkADRCmd_Received()
        {
            const int messagesToSend     = 10;
            const int warmUpMessageCount = 2;

            var device = TestFixtureCi.Device32_ABP;

            LogTestStart(device);

            // Setup LoRa device properties
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

            await ArduinoDevice.setIdAsync(device.DevAddr, device.DeviceID, device.AppEui);

            await ArduinoDevice.setKeyAsync(device.NwkSKey, device.AppSKey, device.AppKey);

            // Setup protocol properties
            // Start with DR5
            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration.LoraRegion, LoRaArduinoSerial._data_rate_t.DR5, 4, true);

            await TestFixture.CleanupC2DDeviceQueueAsync(device.DeviceID);

            // Sends 2x unconfirmed messages
            for (var i = 1; i <= warmUpMessageCount; ++i)
            {
                var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
                Log($"{device.DeviceID}: Sending unconfirmed '{msg}' {i}/{messagesToSend}");
                await ArduinoDevice.transferPacketAsync(msg, 10);

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

                await AssertUtils.ContainsWithRetriesAsync("+MSG: Done", ArduinoDevice.SerialLogs);

                TestFixture.ClearLogs();
            }

            var c2dMessage = new LoRaCloudToDeviceMessage()
            {
                Fport       = FramePort.MacCommand,
                Payload     = String.Empty,
                MacCommands = { new LinkADRRequest(datarate: 3, txPower: 4, chMask: 25, chMaskCntl: 0, nbTrans: 1) } // Update data rate to DR3
            };

            await TestFixtureCi.SendCloudToDeviceMessageAsync(device.DeviceID, c2dMessage);

            Log($"C2D Message sent to device, need to check if it receives");

            var foundC2DMessage      = false;
            var foundLinkADRCmd      = false;
            var foundChangedDataRate = false;

            // Sends 8x unconfirmed messages, stopping if C2D message is found and data rate is updated
            for (var i = warmUpMessageCount + 1; i <= messagesToSend; ++i)
            {
                var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
                Log($"{device.DeviceID}: Sending unconfirmed '{msg}' {i}/{messagesToSend}");
                await ArduinoDevice.transferPacketAsync(msg, 10);

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

                // After transferPacket: Expectation from serial
                // +MSG: Done
                await AssertUtils.ContainsWithRetriesAsync("+MSG: Done", ArduinoDevice.SerialLogs);

                // check if C2D message was found
                if (await SearchMessageAsync($"{device.DeviceID}: cloud to device MAC command LinkADRCmd received Type: LinkADRCmd Answer, datarate: 3"))
                {
                    foundC2DMessage = true;
                }

                // check if LinkADRCmd MAC Command was detected
                if (await SearchMessageAsync("LinkADRCmd mac command detected in upstream payload: Type: LinkADRCmd Answer, power: changed, data rate: changed"))
                {
                    foundLinkADRCmd = true;
                }

                // check if the data rate was changed to DR3
                if (await SearchMessageAsync("\"datr\":\"SF9BW125\""))
                {
                    foundChangedDataRate = true;
                }

                async Task <bool> SearchMessageAsync(string message)
                {
                    var searchResult =
                        await TestFixtureCi.SearchNetworkServerModuleAsync(messageBody => messageBody.Contains(message, StringComparison.OrdinalIgnoreCase),
                                                                           new SearchLogOptions(message)
                    {
                        MaxAttempts = 1
                    });

                    return(searchResult.Found);
                }

                TestFixture.ClearLogs();
                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

                if (foundC2DMessage && foundLinkADRCmd && foundChangedDataRate)
                {
                    break;
                }
            }

            Assert.True(foundC2DMessage, $"Could not find C2D message with MAC command LinkADRCmd in LNS log");
            Assert.True(foundLinkADRCmd, $"Could not find LinkADRCmd MAC Command in LNS log");
            Assert.True(foundChangedDataRate, $"Could not find updated data rate in LNS log");
        }
Exemple #2
0
        public async Task C2D_When_Device_Has_Preferred_Windows_2_Should_Receive_In_2nd_Window_With_Custom_DR()
        {
            const int messagesToSend     = 10;
            const int warmUpMessageCount = 2;
            var       device             = TestFixtureCi.Device21_ABP;

            LogTestStart(device);
            // Setup LoRa device properties
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

            await ArduinoDevice.setIdAsync(device.DevAddr, device.DeviceID, device.AppEui);

            await ArduinoDevice.setKeyAsync(device.NwkSKey, device.AppSKey, device.AppKey);

            // Setup protocol properties
            await ArduinoDevice.SetupLora(TestFixture.Configuration);

            await TestFixture.CleanupC2DDeviceQueueAsync(device.DeviceID);

            // Sends 2x unconfirmed messages
            for (var i = 1; i <= warmUpMessageCount; ++i)
            {
                var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
                Log($"{device.DeviceID}: Sending unconfirmed '{msg}' {i}/{messagesToSend}");

                await ArduinoDevice.transferPacketAsync(msg, 10);

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

                await AssertUtils.ContainsWithRetriesAsync("+MSG: Done", ArduinoDevice.SerialLogs);

                TestFixture.ClearLogs();
            }

            // sends C2D - between 10 and 99
            var c2dMessageBody = (100 + random.Next(90)).ToString(CultureInfo.InvariantCulture);
            var msgId          = Guid.NewGuid().ToString();
            var c2dMessage     = new LoRaCloudToDeviceMessage()
            {
                Payload   = c2dMessageBody,
                Fport     = FramePorts.App1,
                MessageId = msgId,
                Confirmed = true,
            };

            await TestFixtureCi.SendCloudToDeviceMessageAsync(device.DeviceID, c2dMessage);

            Log($"Message {c2dMessageBody} sent to device, need to check if it receives");

            var foundC2DMessageCount         = 0;
            var foundReceivePacketCount      = 0;
            var foundReceivePacketInRX2Count = 0;
            var expectedRxSerial1            = $"+MSG: PORT: 1; RX: \"{ToHexString(c2dMessageBody)}\"";
            var expectedRxSerial2            = $"+MSG: RXWIN2";
            var expectedTcpMessageV1         = $"{device.DevAddr}: ConfirmedDataDown";
            var expectedTcpMessageV2         = $"{device.DeviceID}: cloud to device message: {ToHexString(c2dMessageBody)}, id: {msgId}, fport: 1, confirmed: True";

            Log($"Expected C2D received log is: {expectedRxSerial1} and {expectedRxSerial2}");
            Log($"Expected TCP log starting with: {expectedTcpMessageV1} or {expectedTcpMessageV2}");

            // Sends 8x confirmed messages, stopping if C2D message is found
            for (var i = warmUpMessageCount + 1; i <= messagesToSend; ++i)
            {
                var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
                Log($"{device.DeviceID}: Sending unconfirmed '{msg}' {i}/{messagesToSend}");
                await ArduinoDevice.transferPacketAsync(msg, 10);

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

                await AssertUtils.ContainsWithRetriesAsync("+MSG: Done", ArduinoDevice.SerialLogs);

                // check if c2d message was found
                var searchResults = await TestFixture.SearchNetworkServerModuleAsync(
                    (messageBody) =>
                {
                    return(messageBody.StartsWith(expectedTcpMessageV1, StringComparison.OrdinalIgnoreCase) || messageBody.StartsWith(expectedTcpMessageV2, StringComparison.OrdinalIgnoreCase));
                },
                    new SearchLogOptions($"{expectedTcpMessageV1} or {expectedTcpMessageV2}")
                {
                    MaxAttempts = 1,
                });

                // We should only receive the message once
                if (searchResults.Found)
                {
                    foundC2DMessageCount++;
                    Log($"{device.DeviceID}: Found C2D message in log (after sending {i}/{messagesToSend}) {foundC2DMessageCount} times");
                    EnsureNotSeenTooManyTimes(foundC2DMessageCount);
                }

                if (ArduinoDevice.SerialLogs.Contains(expectedRxSerial1))
                {
                    foundReceivePacketCount++;
                    Log($"{device.DeviceID}: Found C2D message in serial logs (after sending {i}/{messagesToSend}) {foundReceivePacketCount} times");
                    EnsureNotSeenTooManyTimes(foundReceivePacketCount);
                }

                if (ArduinoDevice.SerialLogs.Any(x => x.StartsWith(expectedRxSerial2, StringComparison.OrdinalIgnoreCase)))
                {
                    foundReceivePacketInRX2Count++;
                    Log($"{device.DeviceID}: Found C2D message (rx2) in serial logs (after sending {i}/{messagesToSend}) {foundReceivePacketInRX2Count} times");
                    EnsureNotSeenTooManyTimes(foundReceivePacketInRX2Count);
                }

                if (foundReceivePacketCount > 0 && foundReceivePacketInRX2Count > 0 && foundC2DMessageCount > 0)
                {
                    Log($"{device.DeviceID}: Found all messages in log (after sending {i}/{messagesToSend})");
                    break;
                }

                TestFixture.ClearLogs();

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);
            }

            Assert.True(foundC2DMessageCount > 0, $"Did not find {expectedTcpMessageV1} or {expectedTcpMessageV2} in logs");

            // checks if serial received the message
            if (foundReceivePacketCount == 0)
            {
                if (ArduinoDevice.SerialLogs.Contains(expectedRxSerial1))
                {
                    foundReceivePacketCount++;
                }
            }

            Assert.True(foundReceivePacketCount > 0, $"Could not find lora receiving message '{expectedRxSerial1}'");

            // checks if serial received the message in RX2
            if (foundReceivePacketInRX2Count == 0)
            {
                if (ArduinoDevice.SerialLogs.Any(x => x.StartsWith(expectedRxSerial2, StringComparison.OrdinalIgnoreCase)))
                {
                    foundReceivePacketInRX2Count++;
                }
            }

            Assert.True(foundReceivePacketInRX2Count > 0, $"Could not find lora receiving message '{expectedRxSerial2}'");
        }