private async Task SendABPMessages(int messages_count, TestDeviceInfo device)
        {
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            // Sends 10x unconfirmed messages
            for (var i = 0; i < messages_count; ++i)
            {
                var msg = GeneratePayloadMessage();
                Log($"{device.DeviceID}: Sending unconfirmed '{msg}' {i + 1}/{messages_count}");
                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);

                // 0000000000000005: valid frame counter, msg: 1 server: 0
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: valid frame counter, msg:");

                // 0000000000000005: decoding with: DecoderValueSensor port: 8
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: decoding with: {device.SensorDecoder} port:");

                // 0000000000000005: message '{"value": 51}' sent to hub
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: message '{{\"value\":{msg}}}' sent to hub");

                TestFixtureCi.ClearLogs();
            }

            // Sends 10x confirmed messages
            for (var i = 0; i < messages_count; ++i)
            {
                var msg = GeneratePayloadMessage();
                Log($"{device.DeviceID}: Sending confirmed '{msg}' {i + 1}/{messages_count}");
                await ArduinoDevice.transferPacketWithConfirmedAsync(msg, 10);

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

                // After transferPacketWithConfirmed: Expectation from serial
                // +CMSG: ACK Received
                await AssertUtils.ContainsWithRetriesAsync("+CMSG: ACK Received", ArduinoDevice.SerialLogs);

                // 0000000000000005: valid frame counter, msg: 1 server: 0
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: valid frame counter, msg:");

                // 0000000000000005: decoding with: DecoderValueSensor port: 8
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: decoding with: {device.SensorDecoder} port:");

                // 0000000000000005: message '{"value": 51}' sent to hub
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: message '{{\"value\":{msg}}}' sent to hub");

                TestFixtureCi.ClearLogs();
            }
        }
Beispiel #2
0
        public async Task OTAA_Join_With_Wrong_AppKey_Fails()
        {
            var device = TestFixtureCi.Device3_OTAA;

            LogTestStart(device);
            var appKeyToUse = AppKey.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");

            Assert.NotEqual(appKeyToUse, device.AppKey);
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 3);

            Assert.False(joinSucceeded, "Join suceeded for invalid AppKey (mic check should fail)");
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync(
                $"{device.DeviceID}: join refused: invalid MIC",
                $"{device.DeviceID}: join request MIC invalid");

            await ArduinoDevice.WaitForIdleAsync();
        }
        public async Task SensorDecoder_ReflectionBased_ValueSensorDecoder_DecodesPayload()
        {
            var device = TestFixtureCi.Device12_OTAA;

            LogTestStart(device);
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

            Assert.True(joinSucceeded, "Join failed");

            // wait 1 second after joined
            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_JOIN);

            await ArduinoDevice.transferPacketWithConfirmedAsync("4321", 10);

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            // +CMSG: ACK Received
            await AssertUtils.ContainsWithRetriesAsync("+CMSG: ACK Received", ArduinoDevice.SerialLogs);

            // Find "0000000000000011: message '{"value":1234}' sent to hub" in network server logs
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: message '{{\"value\":4321}}' sent to hub");

            TestFixtureCi.ClearLogs();
        }
        // Ensures that Mac Commands C2D messages working
        // Uses Device23_OTAA
        private async Task Test_OTAA_Unconfirmed_Send_And_Receive_C2D_Mac_Commands(TestDeviceInfo device)
        {
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

            Assert.True(joinSucceeded, "Join failed");

            // wait 1 second after joined
            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_JOIN);

            if (device.IsMultiGw)
            {
                await TestFixtureCi.WaitForTwinSyncAfterJoinAsync(ArduinoDevice.SerialLogs, device.DevEui);
            }

            await Test_OTAA_Unconfirmed_Send_And_Receive_C2D_Mac_CommandsImplAsync(device, "test");
            await Test_OTAA_Unconfirmed_Send_And_Receive_C2D_Mac_CommandsImplAsync(device, string.Empty);
        }
Beispiel #5
0
        public async Task Test_MultiGW_OTTA_Join_Single()
        {
            var device = TestFixtureCi.Device27_OTAA;

            LogTestStart(device);

            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

            Assert.True(joinSucceeded, "Join failed");
            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_JOIN);

            // validate that one GW refused the join
            const string joinRefusedMsg = "join refused";
            var          joinRefused    = await TestFixtureCi.AssertNetworkServerModuleLogExistsAsync((s) => s.IndexOf(joinRefusedMsg, StringComparison.Ordinal) != -1, new SearchLogOptions(joinRefusedMsg));

            Assert.True(joinRefused.Found);

            await TestFixtureCi.WaitForTwinSyncAfterJoinAsync(ArduinoDevice.SerialLogs, device.DevEui);

            // expecting both gw to start picking up messages
            // and sending to IoT hub.
            var bothReported = false;

            for (var i = 0; i < 5; i++)
            {
                var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
                await ArduinoDevice.transferPacketAsync(msg, 10);

                await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_SENDING_PACKET);

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

                var expectedPayload = $"{{\"value\":{msg}}}";
                await TestFixtureCi.AssertIoTHubDeviceMessageExistsAsync(device.DeviceID, expectedPayload, new SearchLogOptions(expectedPayload));

                bothReported = await TestFixtureCi.ValidateMultiGatewaySources((log) => log.StartsWith($"{device.DeviceID}: sending message", StringComparison.OrdinalIgnoreCase));

                if (bothReported)
                {
                    break;
                }
            }

            Assert.True(bothReported);
        }
        public async Task Test_Concentrator_Deduplication_OTAA()
        {
            Assert.True(this.initializationSucceeded);
            var device = TestFixtureCi.GetDeviceByPropertyName("Device31_OTAA");

            LogTestStart(device);

            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

            Assert.True(joinSucceeded, "Join failed");

            var droppedLog = await TestFixtureCi.SearchNetworkServerModuleAsync(
                (log) => log.IndexOf(this.expectedLog, StringComparison.Ordinal) != -1, new SearchLogOptions(this.expectedLog));

            Assert.NotNull(droppedLog.MatchedEvent);

            // wait 1 second after joined
            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_JOIN);

            const int MESSAGE_COUNT = 5;

            for (var i = 0; i < MESSAGE_COUNT; ++i)
            {
                Log($"{device.DeviceID}: Sending OTAA confirmed message {i + 1}/{MESSAGE_COUNT}");

                var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
                await ArduinoDevice.transferPacketWithConfirmedAsync(msg, 10);

                await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_SENDING_PACKET);

                // After transferPacketWithConfirmed: Expectation from serial
                // +CMSG: ACK Received
                await AssertUtils.ContainsWithRetriesAsync("+CMSG: ACK Received", ArduinoDevice.SerialLogs);

                // 0000000000000031: message '{"value": 101}' sent to hub
                var expectedPayload = $"{{\"value\":{msg}}}";
                await TestFixtureCi.AssertIoTHubDeviceMessageExistsAsync(device.DeviceID, expectedPayload, new SearchLogOptions(expectedPayload));

                droppedLog = await TestFixtureCi.SearchNetworkServerModuleAsync(
                    (log) => log.IndexOf(this.expectedLog, StringComparison.Ordinal) != -1, new SearchLogOptions(this.expectedLog));

                Assert.NotNull(droppedLog.MatchedEvent);

                TestFixtureCi.ClearLogs();
            }
        }
        public async Task Test_ClassC_Send_Message_Using_Function_Endpoint_Should_Be_Received()
        {
            var device = TestFixtureCi.Device24_ABP;

            LogTestStart(device);

            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            await ArduinoDevice.setClassTypeAsync(LoRaArduinoSerial._class_type_t.CLASS_C);

            // send one confirmed message for ensuring that a basicstation is "bound" to the device
            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);

            Log($"{device.DeviceID}: Sending confirmed '{msg}'");
            await ArduinoDevice.transferPacketWithConfirmedAsync(msg, 10);

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            TestFixtureCi.ClearLogs();

            // Now sending a c2d
            var c2d = new LoRaCloudToDeviceMessage()
            {
                DevEUI     = DevEui.Parse(device.DeviceID),
                MessageId  = Guid.NewGuid().ToString(),
                Fport      = FramePorts.App23,
                RawPayload = Convert.ToBase64String(new byte[] { 0xFF, 0x00 }),
            };

            TestLogger.Log($"[INFO] Using service API to send C2D message to device {device.DeviceID}");
            TestLogger.Log($"[INFO] {JsonConvert.SerializeObject(c2d, Formatting.None)}");

            // send message using the SendCloudToDeviceMessage API endpoint
            Assert.True(await LoRaAPIHelper.SendCloudToDeviceMessage(device.DevEui, c2d));

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            // 0000000000000024: received cloud to device message from direct method
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: received cloud to device message from direct method");

            Assert.Contains(ArduinoDevice.SerialLogs, (l) => l.Contains("PORT: 23; RX: \"FF00\"", StringComparison.Ordinal));
            Assert.Contains(ArduinoDevice.SerialLogs, (l) => l.Contains("RXWIN0, RSSI", StringComparison.Ordinal));
            await AssertUtils.ContainsWithRetriesAsync("+MSG: Done", ArduinoDevice.SerialLogs);
        }
        public async Task Test_ABP_Mismatch_NwkSKey_And_AppSKey_Fails_Mic_Validation()
        {
            var device = TestFixtureCi.Device7_ABP;

            LogTestStart(device);

            var appSKeyToUse = AppSessionKey.Parse("000102030405060708090A0B0C0D0E0F");
            var nwkSKeyToUse = NetworkSessionKey.Parse("01020304050607080910111213141516");

            Assert.NotEqual(appSKeyToUse, device.AppSKey);
            Assert.NotEqual(nwkSKeyToUse, device.NwkSKey);
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

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

            await ArduinoDevice.setKeyAsync(nwkSKeyToUse, appSKeyToUse, null);

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            await ArduinoDevice.transferPacketAsync(GeneratePayloadMessage(), 10);

            // wait for serial logs to be ready
            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_SENDING_PACKET);

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

            // 0000000000000005: with devAddr 0028B1B0 check MIC failed. Device will be ignored from now on
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DevAddr}: with devAddr {device.DevAddr} check MIC failed");

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            TestFixtureCi.ClearLogs();

            // Try with confirmed message
            await ArduinoDevice.transferPacketWithConfirmedAsync(GeneratePayloadMessage(), 10);

            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_SENDING_PACKET);

            // 0000000000000005: with devAddr 0028B1B0 check MIC failed
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DevAddr}: with devAddr {device.DevAddr} check MIC failed");

            // wait until arduino stops trying to send confirmed msg
            await ArduinoDevice.WaitForIdleAsync();
        }
        public async Task Test_Device_Initiated_Mac_LinkCheckCmd_Should_work()
        {
            try
            {
                const int MESSAGES_COUNT = 3;

                var device = TestFixtureCi.Device22_ABP;
                LogTestStart(device);
                await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

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

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

                await ArduinoDevice.setPortAsync(0);

                await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

                for (var i = 0; i < MESSAGES_COUNT; ++i)
                {
                    var msg = "02";
                    Log($"{device.DeviceID}: Sending unconfirmed Mac LinkCheckCmd message");
                    await ArduinoDevice.transferHexPacketAsync(msg, 10);

                    await Task.Delay(2 *Constants.DELAY_BETWEEN_MESSAGES);

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

                    await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: valid frame counter, msg:");

                    await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: LinkCheckCmd mac command detected in upstream payload:");
                }

                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: answering to a");
            }
            finally
            {
                await ArduinoDevice.setPortAsync(1);
            }

            TestFixtureCi.ClearLogs();
        }
Beispiel #10
0
        public async Task OTAA_Join_With_Wrong_DevEUI_Fails()
        {
            var device = TestFixtureCi.Device2_OTAA;

            LogTestStart(device);
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 3);

            Assert.False(joinSucceeded, "Join suceeded for invalid DevEUI");

            await ArduinoDevice.WaitForIdleAsync();
        }
        public async Task Test_ABP_Invalid_NwkSKey_Fails_With_Mic_Error()
        {
            var device = TestFixtureCi.Device8_ABP;

            LogTestStart(device);

            var nwkSKeyToUse = NetworkSessionKey.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");

            Assert.NotEqual(nwkSKeyToUse, device.NwkSKey);
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

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

            await ArduinoDevice.setKeyAsync(nwkSKeyToUse, device.AppSKey, null);

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            await ArduinoDevice.transferPacketAsync(GeneratePayloadMessage(), 10);

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

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

            // 0000000000000008: with devAddr 0028B1B3 check MIC failed. Device will be ignored from now on
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DevAddr}: with devAddr {device.DevAddr} check MIC failed");

            TestFixtureCi.ClearLogs();

            // Try with confirmed message
            await ArduinoDevice.transferPacketWithConfirmedAsync(GeneratePayloadMessage(), 10);

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            // 0000000000000008: with devAddr 0028B1B3 check MIC failed.
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DevAddr}: with devAddr {device.DevAddr} check MIC failed");

            // Before starting new test, wait until Lora drivers stops sending/receiving data
            await ArduinoDevice.WaitForIdleAsync();
        }
        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");
        }
        // Verifies that ABP confirmed and unconfirmed messages are working
        // Uses Device5_ABP
        private async Task Test_ABP_Confirmed_And_Unconfirmed_Message_With_ADR(TestDeviceInfo device)
        {
            if (device.IsMultiGw)
            {
                Assert.True(await LoRaAPIHelper.ResetADRCache(device.DevEui));
            }

            await ArduinoDevice.setDeviceDefaultAsync();

            const int MESSAGES_COUNT = 10;
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration.LoraRegion, LoRaArduinoSerial._data_rate_t.DR3, 4, true);

            // for a reason I need to set DR twice otherwise it reverts to DR 0
            // await ArduinoDevice.setDataRateAsync(LoRaArduinoSerial._data_rate_t.DR3, LoRaArduinoSerial._physical_type_t.EU868);
            // Sends 5x unconfirmed messages
            for (var i = 0; i < MESSAGES_COUNT / 2; ++i)
            {
                var msg = GeneratePayloadMessage();
                Log($"{device.DeviceID}: Sending unconfirmed '{msg}' {i + 1}/{MESSAGES_COUNT}");
                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);

                // 0000000000000005: valid frame counter, msg: 1 server: 0
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: valid frame counter, msg:");

                // 0000000000000005: decoding with: DecoderValueSensor port: 8
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: decoding with: {device.SensorDecoder} port:");

                // 0000000000000005: message '{"value": 51}' sent to hub
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: message '{{\"value\":{msg}}}' sent to hub");

                TestFixtureCi.ClearLogs();
            }

            // Sends 5x confirmed messages
            for (var i = 0; i < MESSAGES_COUNT / 2; ++i)
            {
                var msg = GeneratePayloadMessage();
                Log($"{device.DeviceID}: Sending confirmed '{msg}' {i + 1}/{MESSAGES_COUNT / 2}");
                await ArduinoDevice.transferPacketWithConfirmedAsync(msg, 10);

                await Task.Delay(2 *Constants.DELAY_BETWEEN_MESSAGES);

                // After transferPacketWithConfirmed: Expectation from serial
                // +CMSG: ACK Received
                await AssertUtils.ContainsWithRetriesAsync("+CMSG: ACK Received", ArduinoDevice.SerialLogs);

                // 0000000000000005: valid frame counter, msg: 1 server: 0
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: valid frame counter, msg:");

                // 0000000000000005: decoding with: DecoderValueSensor port: 8
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: decoding with: {device.SensorDecoder} port:");

                // 0000000000000005: message '{"value": 51}' sent to hub
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: message '{{\"value\":{msg}}}' sent to hub");

                if (device.IsMultiGw)
                {
                    var searchTokenSending = $"{device.DeviceID}: sending message to station with EUI";
                    var sending            = await TestFixtureCi.SearchNetworkServerModuleAsync((log) => log.StartsWith(searchTokenSending, StringComparison.OrdinalIgnoreCase), new SearchLogOptions(searchTokenSending));

                    Assert.NotNull(sending.MatchedEvent);

                    var searchTokenAlreadySent = $"{device.DeviceID}: another gateway has already sent ack or downlink msg";
                    var ignored = await TestFixtureCi.SearchNetworkServerModuleAsync((log) => log.StartsWith(searchTokenAlreadySent, StringComparison.OrdinalIgnoreCase), new SearchLogOptions(searchTokenAlreadySent));

                    Assert.NotNull(ignored.MatchedEvent);

                    Assert.NotEqual(sending.MatchedEvent.SourceId, ignored.MatchedEvent.SourceId);
                }

                TestFixtureCi.ClearLogs();
            }

            // Sends 10x unconfirmed messages
            for (var i = 0; i < MESSAGES_COUNT; ++i)
            {
                var msg = GeneratePayloadMessage();
                Log($"{device.DeviceID}: Sending unconfirmed '{msg}' {i + 1}/{MESSAGES_COUNT / 2}");
                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);

                // 0000000000000005: valid frame counter, msg: 1 server: 0
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: valid frame counter, msg:");

                // 0000000000000005: decoding with: DecoderValueSensor port: 8
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: decoding with: {device.SensorDecoder} port:");

                // 0000000000000005: message '{"value": 51}' sent to hub
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: message '{{\"value\":{msg}}}' sent to hub");

                TestFixtureCi.ClearLogs();
            }

            // Starting ADR test protocol
            Log($"{device.DeviceID}: Starting ADR protocol");

            for (var i = 0; i < 56; ++i)
            {
                var message = GeneratePayloadMessage();
                await ArduinoDevice.transferPacketAsync(message, 10);

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

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

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: ADR ack request received");

            var searchTokenADRRateAdaptation = $"{device.DeviceID}: performing a rate adaptation: DR";
            var received = await TestFixtureCi.SearchNetworkServerModuleAsync((log) => log.StartsWith(searchTokenADRRateAdaptation, StringComparison.OrdinalIgnoreCase), new SearchLogOptions(searchTokenADRRateAdaptation));

            Assert.NotNull(received.MatchedEvent);

            if (device.IsMultiGw)
            {
                var searchTokenADRAlreadySent = $"{device.DeviceID}: another gateway has already sent ack or downlink msg";
                var ignored = await TestFixtureCi.SearchNetworkServerModuleAsync((log) => log.StartsWith(searchTokenADRAlreadySent, StringComparison.OrdinalIgnoreCase), new SearchLogOptions(searchTokenADRAlreadySent));

                Assert.NotNull(ignored.MatchedEvent);
                Assert.NotEqual(received.MatchedEvent.SourceId, ignored.MatchedEvent.SourceId);
            }

            // Check the messages are now sent on DR5
            for (var i = 0; i < 2; ++i)
            {
                var message = GeneratePayloadMessage();
                await ArduinoDevice.transferPacketAsync(message, 10);

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

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

                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: LinkADRCmd mac command detected in upstream payload: Type: LinkADRCmd Answer, power: changed, data rate: changed,", $"{device.DevAddr}: LinkADRCmd mac command detected in upstream payload: Type: LinkADRCmd Answer, power: not changed, data rate: changed,");
            }
        }
        public async Task Test_ABP_Device_With_Connection_Timeout()
        {
            LogTestStart(new TestDeviceInfo[] { TestFixtureCi.Device25_ABP, TestFixtureCi.Device26_ABP });

            // Sends 1 message from device 25
            var device25 = TestFixtureCi.Device25_ABP;
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

            await ArduinoDevice.setIdAsync(device25.DevAddr, device25.DeviceID, null);

            await ArduinoDevice.setKeyAsync(device25.NwkSKey, device25.AppSKey, null);

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            await ArduinoDevice.transferPacketAsync(GeneratePayloadMessage(), 10);

            var expectedLog = $"{device25.DeviceID}: processing time";
            await TestFixtureCi.SearchNetworkServerModuleAsync((log) => log.StartsWith(expectedLog, StringComparison.Ordinal), new SearchLogOptions(expectedLog));

            // wait 61 seconds
            await Task.Delay(TimeSpan.FromSeconds(120));

            // Send 1 message from device 26
            var device26 = TestFixtureCi.Device26_ABP;
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

            await ArduinoDevice.setIdAsync(device26.DevAddr, device26.DeviceID, null);

            await ArduinoDevice.setKeyAsync(device26.NwkSKey, device26.AppSKey, null);

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            await ArduinoDevice.transferPacketAsync(GeneratePayloadMessage(), 10);

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            var expectedLog2 = $"{device25.DeviceID}: device client disconnected";
            var result       = await TestFixtureCi.SearchNetworkServerModuleAsync(
                msg => msg.StartsWith(expectedLog2, StringComparison.Ordinal),
                new SearchLogOptions(expectedLog2)
            {
                MaxAttempts    = 10,
                SourceIdFilter = device25.GatewayID,
            });

            Assert.NotNull(result.MatchedEvent);

            TestFixtureCi.ClearLogs();

            // Send 1 message from device 25 and check that connection was restablished
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

            await ArduinoDevice.setIdAsync(device25.DevAddr, device25.DeviceID, null);

            await ArduinoDevice.setKeyAsync(device25.NwkSKey, device25.AppSKey, null);

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var expectedMessage = GeneratePayloadMessage();
            await ArduinoDevice.transferPacketAsync(expectedMessage, 10);

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

            // 0000000000000005: message '{"value": 51}' sent to hub
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device25.DeviceID}: message '{{\"value\":{expectedMessage}}}' sent to hub");

            // "device client reconnected"
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device25.DeviceID}: device client reconnected");
        }
Beispiel #15
0
        /* Commented multi gateway tests as they make C2D tests flaky for now
         * [RetryFact]
         * public Task Test_OTAA_Unconfirmed_Receives_Confirmed_C2D_Message_MultiGw()
         * {
         *  var device = TestFixtureCi.GetDeviceByPropertyName(nameof(TestFixtureCi.Device14_OTAA_MultiGw));
         *  LogTestStart(device);
         *  return Test_OTAA_Unconfirmed_Receives_Confirmed_C2D_Message(device);
         * }
         */

        // Ensures that C2D messages are received when working with unconfirmed messages
        // Uses Device10_OTAA
        private async Task Test_OTAA_Unconfirmed_Receives_Confirmed_C2D_Message(TestDeviceInfo device)
        {
            const int messagesToSend     = 10;
            const int warmUpMessageCount = 2;

            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            await TestFixture.CleanupC2DDeviceQueueAsync(device.DeviceID);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

            Assert.True(joinSucceeded, "Join failed");

            // wait 1 second after joined
            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_JOIN);

            if (device.IsMultiGw)
            {
                await TestFixtureCi.WaitForTwinSyncAfterJoinAsync(ArduinoDevice.SerialLogs, device.DevEui);
            }

            // 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);

                TestFixtureCi.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 expectedRxSerial        = $"+MSG: PORT: 1; RX: \"{ToHexString(c2dMessageBody)}\"";
            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: {expectedRxSerial}");
            Log($"Expected TCP log starting with: {expectedTcpMessageV1} or {expectedTcpMessageV2}");

            // Sends 8x unconfirmed 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_FOR_SERIAL_AFTER_SENDING_PACKET);

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

                // check if c2d message was found
                var searchResults = await TestFixtureCi.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);
                }

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

                TestFixtureCi.ClearLogs();

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);
            }

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

            // checks if log arrived
            if (foundReceivePacketCount == 0)
            {
                if (ArduinoDevice.SerialLogs.Contains(expectedRxSerial))
                {
                    foundReceivePacketCount++;
                }
            }

            Assert.True(foundReceivePacketCount > 0, $"Could not find lora receiving message '{expectedRxSerial}'");
        }
Beispiel #16
0
        private async Task Test_Deduplication_Strategies(string devicePropertyName, string strategy)
        {
            var device = TestFixtureCi.GetDeviceByPropertyName(devicePropertyName);

            LogTestStart(device);

            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWABP);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            for (var i = 0; i < 10; i++)
            {
                var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
                await ArduinoDevice.transferPacketWithConfirmedAsync(msg, 10);

                await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_SENDING_PACKET);

                // After transferPacket: Expectation from serial
                // +CMSG: ACK Received
                await AssertUtils.ContainsWithRetriesAsync("+CMSG: ACK Received", ArduinoDevice.SerialLogs);

                var allGwGotIt = await TestFixtureCi.ValidateMultiGatewaySources((log) => log.IndexOf($"deduplication Strategy: {strategy}", StringComparison.OrdinalIgnoreCase) != -1);

                if (allGwGotIt)
                {
                    var notDuplicate = "\"IsDuplicate\":false";
                    var isDuplicate  = "\"IsDuplicate\":true";

                    var notDuplicateResult = await TestFixtureCi.SearchNetworkServerModuleAsync((s) => s.IndexOf(notDuplicate, StringComparison.Ordinal) != -1, new SearchLogOptions(notDuplicate));

                    var duplicateResult = await TestFixtureCi.SearchNetworkServerModuleAsync((s) => s.IndexOf(isDuplicate, StringComparison.Ordinal) != -1, new SearchLogOptions(isDuplicate));

                    Assert.NotNull(notDuplicateResult.MatchedEvent);
                    Assert.NotNull(duplicateResult.MatchedEvent);

                    Assert.NotEqual(duplicateResult.MatchedEvent.SourceId, notDuplicateResult.MatchedEvent.SourceId);

                    switch (strategy)
                    {
                    case "Mark":
                        var expectedProperty = "dupmsg";
                        await TestFixture.AssertIoTHubDeviceMessageExistsAsync(device.DeviceID, expectedProperty, "true", new SearchLogOptions(expectedProperty) { SourceIdFilter = duplicateResult.MatchedEvent.SourceId, TreatAsError = true });

                        await TestFixture.AssertIoTHubDeviceMessageExistsAsync(device.DeviceID, expectedProperty, "true", new SearchLogOptions(expectedProperty) { SourceIdFilter = notDuplicateResult.MatchedEvent.SourceId, TreatAsError = true });

                        break;

                    case "Drop":
                        var logMsg     = $"{device.DeviceID}: duplication strategy indicated to not process message";
                        var droppedLog = await TestFixtureCi.SearchNetworkServerModuleAsync((log) => log.StartsWith(logMsg, StringComparison.Ordinal), new SearchLogOptions(logMsg) { SourceIdFilter = duplicateResult.MatchedEvent.SourceId });

                        Assert.NotNull(droppedLog.MatchedEvent);

                        var expectedPayload = $"{{\"value\":{msg}}}";
                        await TestFixtureCi.AssertIoTHubDeviceMessageExistsAsync(device.DeviceID, expectedPayload, new SearchLogOptions(expectedPayload) { TreatAsError = true });

                        break;

                    default:
                        throw new SwitchExpressionException();
                    }
                }

                TestFixtureCi.ClearLogs();
            }
        }
Beispiel #17
0
        public async Task Test_Concentrator_Can_Receive_Updates_Then_Connect_To_Lns_And_Receive_Messages()
        {
            //arrange
            var temporaryDirectoryName = string.Empty;
            var stationEui             = StationEui.Parse(TestFixture.Configuration.CupsBasicStationEui);
            var clientThumbprint       = TestFixture.Configuration.ClientThumbprint;
            var crcParseResult         = uint.TryParse(TestFixture.Configuration.ClientBundleCrc, out var crc);
            var sigCrcParseResult      = uint.TryParse(TestFixture.Configuration.CupsSigKeyChecksum, out var sigCrc);

            try
            {
                var device = TestFixtureCi.GetDeviceByPropertyName(nameof(TestFixtureCi.Device33_OTAA));
                LogTestStart(device, stationEui);

                if (!string.IsNullOrEmpty(clientThumbprint))
                {
                    //if a test re-run, clientThumbprint will be empty, therefore there's nothing to do, previously generated certificates will be reused
                    //update allowed client thumbprints in IoT Hub Twin to only have the one being added
                    await TestFixture.UpdateExistingConcentratorThumbprint(stationEui,
                                                                           condition : (originalArray) => !originalArray.Any(x => x.Equals(clientThumbprint, StringComparison.OrdinalIgnoreCase)),
                                                                           action : (originalList) =>
                    {
                        originalList.RemoveAll(x => true);                                                        // remove all keys
                        originalList.Add(clientThumbprint);                                                       // add only new thumbprint
                    });
                }

                if (crcParseResult)
                {
                    //if a test re-run, crc field will be empty, therefore there's nothing to do, previously generated certificates will be reused
                    //update crc value with the one being generated in ci
                    await TestFixture.UpdateExistingConcentratorCrcValues(stationEui, crc);
                }

                var fwDigest  = TestFixture.Configuration.CupsFwDigest;
                var fwPackage = TestFixture.Configuration.CupsBasicStationPackage;
                var fwUrl     = TestFixture.Configuration.CupsFwUrl;
                if (sigCrcParseResult && !string.IsNullOrEmpty(fwDigest) && !string.IsNullOrEmpty(fwPackage) && fwUrl is not null)
                {
                    //if a test re-run, the fields will be empty, therefore there's no update to achieve
                    await TestFixture.UpdateExistingFirmwareUpgradeValues(stationEui, sigCrc, fwDigest, fwPackage, fwUrl);
                }

                //setup the concentrator with CUPS_URI only (certificates are retrieved from default location)
                TestUtils.StartBasicsStation(TestFixture.Configuration, new Dictionary <string, string>()
                {
                    { "TLS_SNI", "false" },
                    { "CUPS_URI", TestFixture.Configuration.SharedCupsEndpoint },
                    { "FIXED_STATION_EUI", stationEui.ToString() },
                    { "RADIODEV", TestFixture.Configuration.RadioDev }
                }, out temporaryDirectoryName);

                // Waiting 30s for being sure that BasicStation actually started up
                await Task.Delay(30_000);

                // If package log does not match, firmware upgrade process failed
                var expectedLog = stationEui + $": Received 'version' message for station '{TestFixture.Configuration.CupsBasicStationVersion}' with package '{fwPackage}'";
                var log         = await TestFixtureCi.SearchNetworkServerModuleAsync(
                    (log) => log.IndexOf(expectedLog, StringComparison.Ordinal) != -1, new SearchLogOptions(expectedLog) { MaxAttempts = 1 });

                Assert.True(log.Found);

                //the concentrator should be ready at this point to receive messages
                //if receiving 'updf' is succeeding, cups worked successfully
                await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

                await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

                var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

                Assert.True(joinSucceeded, "Join failed");

                var expectedLog2 = stationEui + ": Received 'jreq' message";
                var jreqLog      = await TestFixtureCi.SearchNetworkServerModuleAsync(
                    (log) => log.IndexOf(expectedLog2, StringComparison.Ordinal) != -1, new SearchLogOptions(expectedLog2) { MaxAttempts = 2 });

                Assert.NotNull(jreqLog.MatchedEvent);

                // wait 1 second after joined
                await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_JOIN);

                Log($"{device.DeviceID}: Sending OTAA unconfirmed message");

                var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
                await ArduinoDevice.transferPacketAsync(msg, 10);

                await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_SENDING_PACKET);

                var expectedLog3 = $"{{\"value\":{msg}}}";
                await TestFixtureCi.AssertIoTHubDeviceMessageExistsAsync(device.DeviceID, expectedLog3, new SearchLogOptions(expectedLog3) { MaxAttempts = 2 });

                var expectedLog4 = stationEui + ": Received 'updf' message";
                var updfLog      = await TestFixtureCi.SearchNetworkServerModuleAsync(
                    (log) => log.IndexOf(expectedLog4, StringComparison.Ordinal) != -1, new SearchLogOptions(expectedLog4) { MaxAttempts = 2 });

                Assert.True(updfLog.Found);

                var twin = await TestFixture.GetTwinAsync(stationEui.ToString());

                var twinReader = new TwinCollectionReader(twin.Properties.Reported, null);
                Assert.True(twinReader.TryRead <string>(TwinProperty.Package, out var reportedPackage) &&
                            string.Equals(fwPackage, reportedPackage, StringComparison.OrdinalIgnoreCase));
            }
            finally
            {
                TestUtils.KillBasicsStation(TestFixture.Configuration, temporaryDirectoryName, out var logFilePath);
                if (!string.IsNullOrEmpty(logFilePath) && File.Exists(logFilePath))
                {
                    Log("[INFO] ** Basic Station Logs Start **");
                    Log(await File.ReadAllTextAsync(logFilePath));
                    Log("[INFO] ** Basic Station Logs End **");
                    File.Delete(logFilePath);
                }
            }
            TestFixtureCi.ClearLogs();
        }
Beispiel #18
0
        public async Task OTAA_Join_With_Valid_Device_Updates_DeviceTwin()
        {
            var device = TestFixtureCi.Device1_OTAA;

            LogTestStart(device);

            var twinBeforeJoin = await TestFixtureCi.GetTwinAsync(device.DeviceID);

            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

            Assert.True(joinSucceeded, "Join failed");

            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_JOIN);

            // After join: Expectation on serial
            // +JOIN: Network joined
            // +JOIN: NetID 010000 DevAddr 02:9B:0D:3E
            // Assert.Contains("+JOIN: Network joined", this.lora.SerialLogs);
            await AssertUtils.ContainsWithRetriesAsync(
                (s) => s.StartsWith("+JOIN: NetID", StringComparison.Ordinal),
                ArduinoDevice.SerialLogs);

            // verify status in device twin
            await Task.Delay(TimeSpan.FromSeconds(60));

            var twinAfterJoin = await TestFixtureCi.GetTwinAsync(device.DeviceID);

            Assert.NotNull(twinAfterJoin);
            Assert.NotNull(twinAfterJoin.Properties.Reported);
            try
            {
                Assert.True(twinAfterJoin.Properties.Reported.Contains("FCntUp"), "Property FCntUp does not exist");
                Assert.True(twinAfterJoin.Properties.Reported.Contains("FCntDown"), "Property FCntDown does not exist");
                Assert.True(twinAfterJoin.Properties.Reported.Contains("NetId"), "Property NetId does not exist");
                Assert.True(twinAfterJoin.Properties.Reported.Contains("DevAddr"), "Property DevAddr does not exist");
                Assert.True(twinAfterJoin.Properties.Reported.Contains("DevNonce"), "Property DevNonce does not exist");
                Assert.True(twinAfterJoin.Properties.Reported.Contains("NwkSKey"), "Property NwkSKey does not exist");
                Assert.True(twinAfterJoin.Properties.Reported.Contains("AppSKey"), "Property AppSKey does not exist");
                Assert.True(twinAfterJoin.Properties.Reported.Contains("DevEUI"), "Property DevEUI does not exist");
                var devAddrBefore        = (string)twinBeforeJoin.Properties.Reported["DevAddr"];
                var devAddrAfter         = (string)twinAfterJoin.Properties.Reported["DevAddr"];
                var actualReportedDevEUI = (string)twinAfterJoin.Properties.Reported["DevEUI"];
                Assert.NotEqual(devAddrAfter, devAddrBefore);
                Assert.Equal(device.DeviceID, actualReportedDevEUI);
                Assert.True(twinBeforeJoin.Properties.Reported.Version < twinAfterJoin.Properties.Reported.Version, "Twin was not updated after join");
                Log($"[INFO] Twin was updated successfully. Version changed from {twinBeforeJoin.Properties.Reported.Version} to {twinAfterJoin.Properties.Reported.Version}");
            }
            catch (XunitException xunitException)
            {
                if (TestFixtureCi.Configuration.IoTHubAssertLevel == LogValidationAssertLevel.Warning)
                {
                    Log($"[WARN] {nameof(OTAA_Join_With_Valid_Device_Updates_DeviceTwin)} failed. {xunitException}");
                }
                else if (TestFixtureCi.Configuration.IoTHubAssertLevel == LogValidationAssertLevel.Error)
                {
                    throw;
                }
            }
        }
Beispiel #19
0
        // Performs a OTAA join and sends 1 unconfirmed, 1 confirmed and rejoins
        private async Task Test_OTAA_Join_Send_And_Rejoin_With_Custom_RX2_DR(TestDeviceInfo device)
        {
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

            Assert.True(joinSucceeded, "Join failed");

            // wait 1 second after joined
            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_JOIN);

            if (device.IsMultiGw)
            {
                await TestFixtureCi.WaitForTwinSyncAfterJoinAsync(ArduinoDevice.SerialLogs, device.DevEui);
            }

            // Sends 1x unconfirmed messages
            TestFixtureCi.ClearLogs();

            var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
            await ArduinoDevice.transferPacketAsync(msg, 10);

            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_SENDING_PACKET);

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

            // 0000000000000004: valid frame counter, msg: 1 server: 0
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: valid frame counter, msg:");

            // 0000000000000004: decoding with: DecoderValueSensor port: 8
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: decoding with: {device.SensorDecoder} port:");

            // 0000000000000004: message '{"value": 51}' sent to hub
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: message '{{\"value\":{msg}}}' sent to hub");

            // Ensure device payload is available
            // Data: {"value": 51}
            var expectedPayload = $"{{\"value\":{msg}}}";
            await TestFixtureCi.AssertIoTHubDeviceMessageExistsAsync(device.DeviceID, expectedPayload, new SearchLogOptions(expectedPayload));

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            TestFixtureCi.ClearLogs();

            msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
            await ArduinoDevice.transferPacketWithConfirmedAsync(msg, 10);

            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_SENDING_PACKET);

            // After transferPacketWithConfirmed: Expectation from serial
            // +CMSG: ACK Received
            await AssertUtils.ContainsWithRetriesAsync("+CMSG: ACK Received", ArduinoDevice.SerialLogs);

            // Checking than the communication occurs on DR 4 and RX2 as part of preferred windows RX2 and custom RX2 DR
            await AssertUtils.ContainsWithRetriesAsync(x => x.StartsWith("+CMSG: RXWIN2", StringComparison.Ordinal), ArduinoDevice.SerialLogs);

            // this test has a custom datarate for RX 2 of 3
            const string logMessage2 = "\"Rx2\":{\"DataRate\":3";
            await TestFixtureCi.AssertNetworkServerModuleLogExistsAsync(x => x.Contains(logMessage2, StringComparison.Ordinal), new SearchLogOptions(logMessage2));


            // 0000000000000004: decoding with: DecoderValueSensor port: 8
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: decoding with: {device.SensorDecoder} port:");

            // 0000000000000004: message '{"value": 51}' sent to hub
            await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: message '{{\"value\":{msg}}}' sent to hub");

            // Ensure device payload is available
            // Data: {"value": 51}
            expectedPayload = $"{{\"value\":{msg}}}";
            await TestFixtureCi.AssertIoTHubDeviceMessageExistsAsync(device.DeviceID, expectedPayload, new SearchLogOptions(expectedPayload));

            await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

            // rejoin
            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var joinSucceeded2 = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

            Assert.True(joinSucceeded2, "Rejoin failed");

            if (device.IsMultiGw)
            {
                const string joinRefusedMsg = "join refused";
                var          joinRefused    = await TestFixtureCi.AssertNetworkServerModuleLogExistsAsync((s) => s.IndexOf(joinRefusedMsg, StringComparison.Ordinal) != -1, new SearchLogOptions(joinRefusedMsg));

                Assert.True(joinRefused.Found);
            }
        }
Beispiel #20
0
        public async Task Test_OTAA_Confirmed_Receives_C2D_Message_With_RX_Delay_2()
        {
            const int messagesToSend     = 10;
            const int warmUpMessageCount = 2;
            var       device             = TestFixtureCi.Device9_OTAA;

            LogTestStart(device);

            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            await TestFixture.CleanupC2DDeviceQueueAsync(device.DeviceID);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

            Assert.True(joinSucceeded, "Join failed");

            // find the gateway that accepted the join
            const string expectedLog = "JoinAccept";
            var          joinAccept  = await TestFixtureCi.SearchNetworkServerModuleAsync((s) => s.IndexOf(expectedLog, StringComparison.OrdinalIgnoreCase) != -1, new SearchLogOptions(expectedLog));

            Assert.NotNull(joinAccept);
            Assert.NotNull(joinAccept.MatchedEvent);

            var targetGw = joinAccept.MatchedEvent.SourceId;

            Assert.Equal(device.GatewayID, targetGw);

            // wait 1 second after joined
            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_JOIN);

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

                await ArduinoDevice.transferPacketWithConfirmedAsync(msg, 10);

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);

                // +CMSG: ACK Received
                await AssertUtils.ContainsWithRetriesAsync("+CMSG: ACK Received", ArduinoDevice.SerialLogs);

                TestFixtureCi.ClearLogs();
            }

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

            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 expectedRxSerial        = $"+CMSG: PORT: 1; RX: \"{ToHexString(c2dMessageBody)}\"";

            Log($"Expected C2D received log is: {expectedRxSerial}");

            var c2dLogMessage = $"{device.DeviceID}: done completing cloud to device message, id: {c2dMessage.MessageId}";

            Log($"Expected C2D network server log is: {expectedRxSerial}");

            // 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 confirmed '{msg}' {i}/{messagesToSend}");
                await ArduinoDevice.transferPacketWithConfirmedAsync(msg, 10);

                await Task.Delay(TimeSpan.FromSeconds(5));

                // After transferPacketWithConfirmed: Expectation from serial
                // +CMSG: ACK Received
                await AssertUtils.ContainsWithRetriesAsync("+CMSG: ACK Received", ArduinoDevice.SerialLogs);

                // Check that RXDelay was correctly used
                await TestFixtureCi.CheckAnswerTimingAsync(device.RXDelay, device.GatewayID);

                // check if c2d message was found
                // 0000000000000009: C2D message: 58
                var searchResults = await TestFixtureCi.SearchNetworkServerModuleAsync(
                    (messageBody) =>
                {
                    return(messageBody.StartsWith(c2dLogMessage, StringComparison.OrdinalIgnoreCase));
                },
                    new SearchLogOptions(c2dLogMessage)
                {
                    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);
                }

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

                TestFixtureCi.ClearLogs();

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);
            }

            Assert.True(foundC2DMessageCount > 0, $"Did not find '{device.DeviceID}: C2D message: {c2dMessageBody}' in logs");

            // checks if log arrived
            if (foundReceivePacketCount == 0)
            {
                if (ArduinoDevice.SerialLogs.Contains(expectedRxSerial))
                {
                    foundReceivePacketCount++;
                }
            }

            Assert.True(foundReceivePacketCount > 0, $"Could not find lora receiving message '{expectedRxSerial}'");
        }
        // Performs a OTAA join and sends N confirmed and unconfirmed messages
        // Expects that:
        // - device message is available on IoT Hub
        // - frame counter validation is done
        // - Message is decoded
        private async Task Test_OTAA_Confirmed_And_Unconfirmed_Message_With_Custom_RX1_DR_Offset(TestDeviceInfo device)
        {
            const int MESSAGES_COUNT = 10;

            await ArduinoDevice.setDeviceModeAsync(LoRaArduinoSerial._device_mode_t.LWOTAA);

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

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

            await ArduinoDevice.SetupLora(TestFixtureCi.Configuration);

            var joinSucceeded = await ArduinoDevice.setOTAAJoinAsyncWithRetry(LoRaArduinoSerial._otaa_join_cmd_t.JOIN, 20000, 5);

            Assert.True(joinSucceeded, "Join failed");

            // wait 1 second after joined
            await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_JOIN);

            if (device.IsMultiGw)
            {
                await TestFixtureCi.WaitForTwinSyncAfterJoinAsync(ArduinoDevice.SerialLogs, device.DevEui);
            }

            // Sends 10x unconfirmed messages
            for (var i = 0; i < MESSAGES_COUNT; ++i)
            {
                Console.WriteLine($"Starting sending OTAA unconfirmed message {i + 1}/{MESSAGES_COUNT}");
                TestFixtureCi.ClearLogs();

                var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
                await ArduinoDevice.transferPacketAsync(msg, 10);

                await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_SENDING_PACKET);

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

                // 0000000000000004: valid frame counter, msg: 1 server: 0
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: valid frame counter, msg:");

                // 0000000000000004: decoding with: DecoderValueSensor port: 8
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: decoding with: {device.SensorDecoder} port:");

                // 0000000000000004: message '{"value": 51}' sent to hub
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: message '{{\"value\":{msg}}}' sent to hub");

                // Ensure device payload is available
                // Data: {"value": 51}
                var expectedPayload = $"{{\"value\":{msg}}}";
                await TestFixtureCi.AssertIoTHubDeviceMessageExistsAsync(device.DeviceID, expectedPayload, new SearchLogOptions(expectedPayload));

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);
            }

            // Sends 10x confirmed messages
            for (var i = 0; i < MESSAGES_COUNT; ++i)
            {
                Console.WriteLine($"Starting sending OTAA confirmed message {i + 1}/{MESSAGES_COUNT}");
                TestFixtureCi.ClearLogs();

                var msg = PayloadGenerator.Next().ToString(CultureInfo.InvariantCulture);
                await ArduinoDevice.transferPacketWithConfirmedAsync(msg, 10);

                await Task.Delay(Constants.DELAY_FOR_SERIAL_AFTER_SENDING_PACKET);

                if (device.IsMultiGw)
                {
                    // multi gw, make sure one ignored the message
                    var searchTokenSending = $"{device.DeviceID}: sending message to station with EUI";
                    var sending            = await TestFixtureCi.SearchNetworkServerModuleAsync((log) => log.StartsWith(searchTokenSending, StringComparison.OrdinalIgnoreCase), new SearchLogOptions(searchTokenSending));

                    Assert.NotNull(sending.MatchedEvent);

                    var searchTokenAlreadySent = $"{device.DeviceID}: another gateway has already sent ack or downlink msg";
                    var ignored = await TestFixtureCi.SearchNetworkServerModuleAsync((log) => log.StartsWith(searchTokenAlreadySent, StringComparison.OrdinalIgnoreCase), new SearchLogOptions(searchTokenAlreadySent));

                    Assert.NotNull(ignored.MatchedEvent);

                    Assert.NotEqual(sending.MatchedEvent.SourceId, ignored.MatchedEvent.SourceId);
                }

                // After transferPacketWithConfirmed: Expectation from serial
                // +CMSG: ACK Received
                await AssertUtils.ContainsWithRetriesAsync("+CMSG: ACK Received", ArduinoDevice.SerialLogs, maxAttempts : 5, interval : TimeSpan.FromSeconds(10));

                // 0000000000000004: decoding with: DecoderValueSensor port: 8
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: decoding with: {device.SensorDecoder} port:");

                // 0000000000000004: message '{"value": 51}' sent to hub
                await TestFixtureCi.AssertNetworkServerModuleLogStartsWithAsync($"{device.DeviceID}: message '{{\"value\":{msg}}}' sent to hub");

                if (ArduinoDevice.SerialLogs.Any(x => x.StartsWith("+CMSG: RXWIN1", StringComparison.Ordinal)))
                {
                    // Expect that the response is done on DR4 as the RX1 offset is 1 on this device.
                    const string logMessage = "\"Rx1\":{\"DataRate\":4";
                    await TestFixtureCi.AssertNetworkServerModuleLogExistsAsync(log => log.Contains(logMessage, StringComparison.Ordinal), new SearchLogOptions(logMessage));
                }

                // Ensure device payload is available
                // Data: {"value": 51}
                var expectedPayload = $"{{\"value\":{msg}}}";
                await TestFixtureCi.AssertIoTHubDeviceMessageExistsAsync(device.DeviceID, expectedPayload, new SearchLogOptions(expectedPayload));

                await Task.Delay(Constants.DELAY_BETWEEN_MESSAGES);
            }
        }
Beispiel #22
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}'");
        }