From f0471a93ce69c0ba5ce922165d131955b9832d2b Mon Sep 17 00:00:00 2001 From: Wosser1sProductions Date: Mon, 20 Feb 2017 20:44:46 +0100 Subject: [PATCH] Sample testing from XML + Added qa_BasicTest_Data.xml file with list of al the samples generated and their setting. + Added qa_BasicTest_XML.py to run Unit Tests by parsing the xml file ~ Changed ReadMe to include these changes --- README.md | 9 +- examples/qa_BasicTest.log | 71 ++-- examples/qa_BasicTest_Data.xml | 619 +++++++++++++++++++++++++++++++++ python/CMakeLists.txt | 1 + python/qa_BasicTest_XML.py | 259 ++++++++++++++ 5 files changed, 920 insertions(+), 39 deletions(-) create mode 100644 examples/qa_BasicTest_Data.xml create mode 100644 python/qa_BasicTest_XML.py diff --git a/README.md b/README.md index ba68adb..ab76ca9 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Though there is no official reference implementation of LoRa, the protocol is de - Decoding + Hamming error correction of the LoRa PHDR length field - Decoding + Hamming error correction of frame payloads (all coding rates) -Not supported yet: +Not supported yet: - CRC checks of the payload and header - Decoding multiple channels simultaneously @@ -41,13 +41,13 @@ make && sudo make install The following dependencies are required: - numpy - scipy -- liquid-dsp (https://github.com/jgaeddert/liquid-dsp) +- [liquid-dsp](https://github.com/jgaeddert/liquid-dsp) Testing ------- -To test your installation, you can download one of the sample LoRa signals at https://github.com/rpp0/gr-lora-samples. Configure ```apps/lora_receive_file.py``` to use the sample and run the script. You should see the decoded sample data: +To test your installation, you can download one of the sample LoRa signals at [rpp0/gr-lora-samples](https://github.com/rpp0/gr-lora-samples). Configure ```apps/lora_receive_file.py``` to use the sample and run the script. You should see the decoded sample data: ``` $ ./lora_receive_file.py @@ -63,6 +63,9 @@ Using Volk machine: avx2_64_mmx_orc ... ``` +Alternatively, if you have a LoRa transmitter, you can configure/modify ```/examples/_examplify.py``` to generate example files and add them to ```python/qa_BasicTest.py``` as Unit Test, or to ```/examples/qa_BasicTest_Data.xml``` to run them automatically with ```python/qa_BasicTest_XML.py``` (```xmltodict``` module needed). +Note that these can be run with their shell script in ```build\python```. + Contributing ------------ diff --git a/examples/qa_BasicTest.log b/examples/qa_BasicTest.log index fad1339..26b6b7a 100644 --- a/examples/qa_BasicTest.log +++ b/examples/qa_BasicTest.log @@ -1,181 +1,180 @@ - --------- Test Results on 2017-02-17 15:37:32 --------- -Test serie 0: ['80 0b 01 01 23 45 67 89 ab cd ef'] * 10 +-------- Test Results on 2017-02-20 14:14:00 --------- +Test serie 0: [u'80 0b 01 01 23 45 67 89 ab cd ef'] * 10 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 5 out of 10 ( 50.00%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) => Total passed: 5 out of 30 (16.67%) -Test serie 1: ['80 0f 02 01 23 45 67 89 ab cd ef'] * 10 +Test serie 1: [u'80 0f 02 01 23 45 67 89 ab cd ef'] * 10 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 4 out of 10 ( 40.00%) => Total passed: 4 out of 20 (20.00%) -Test serie 2: ['80 0d 05 01 23 45 67 89 ab cd ef'] * 10 +Test serie 2: [u'80 0d 05 01 23 45 67 89 ab cd ef'] * 10 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 2 out of 10 ( 20.00%) => Total passed: 2 out of 20 (10.00%) -Test serie 3: ['30 0b 02 11 11 11'] * 1 +Test serie 3: [u'30 0b 02 11 11 11'] * 1 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) => Total passed: 1 out of 3 (33.33%) -Test serie 4: ['30 0f 01 11 11 11'] * 1 +Test serie 4: [u'30 0f 01 11 11 11'] * 1 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) => Total passed: 0 out of 2 (0.00%) -Test serie 5: ['30 0d 06 11 11 11'] * 1 +Test serie 5: [u'30 0d 06 11 11 11'] * 1 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) => Total passed: 0 out of 2 (0.00%) -Test serie 6: ['30 0b 02 11 11 11'] * 5 +Test serie 6: [u'30 0b 02 11 11 11'] * 5 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 3 out of 5 ( 60.00%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) => Total passed: 3 out of 15 (20.00%) -Test serie 7: ['30 0f 01 11 11 11'] * 5 +Test serie 7: [u'30 0f 01 11 11 11'] * 5 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 2 out of 5 ( 40.00%) => Total passed: 2 out of 10 (20.00%) -Test serie 8: ['30 0d 06 11 11 11'] * 5 +Test serie 8: [u'30 0d 06 11 11 11'] * 5 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 5 ( 20.00%) => Total passed: 1 out of 10 (10.00%) -Test serie 9: ['40 0b 07 aa aa aa aa'] * 3 +Test serie 9: [u'40 0b 07 aa aa aa aa'] * 3 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 3 ( 33.33%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) => Total passed: 1 out of 9 (11.11%) -Test serie 10: ['40 0f 04 aa aa aa aa'] * 3 +Test serie 10: [u'40 0f 04 aa aa aa aa'] * 3 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) => Total passed: 0 out of 6 (0.00%) -Test serie 11: ['40 0d 03 aa aa aa aa'] * 3 +Test serie 11: [u'40 0d 03 aa aa aa aa'] * 3 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 3 ( 33.33%) => Total passed: 1 out of 6 (16.67%) -Test serie 12: ['40 0b 07 ff ff ff ff'] * 1 +Test serie 12: [u'40 0b 07 ff ff ff ff'] * 1 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) => Total passed: 0 out of 3 (0.00%) -Test serie 13: ['40 0f 04 ff ff ff ff'] * 1 +Test serie 13: [u'40 0f 04 ff ff ff ff'] * 1 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) => Total passed: 0 out of 2 (0.00%) -Test serie 14: ['40 0d 03 ff ff ff ff'] * 1 +Test serie 14: [u'40 0d 03 ff ff ff ff'] * 1 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) => Total passed: 1 out of 2 (50.00%) -Test serie 15: ['40 0b 07 ff ff ff ff'] * 10 +Test serie 15: [u'40 0b 07 ff ff ff ff'] * 10 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 2 out of 10 ( 20.00%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) => Total passed: 2 out of 30 (6.67%) -Test serie 16: ['40 0f 04 ff ff ff ff'] * 10 +Test serie 16: [u'40 0f 04 ff ff ff ff'] * 10 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) => Total passed: 0 out of 20 (0.00%) -Test serie 17: ['40 0d 03 ff ff ff ff'] * 10 +Test serie 17: [u'40 0d 03 ff ff ff ff'] * 10 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 10 ( 30.00%) => Total passed: 3 out of 20 (15.00%) -Test serie 18: ['40 0b 07 55 55 55 55'] * 3 +Test serie 18: [u'40 0b 07 55 55 55 55'] * 3 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 1 out of 3 ( 33.33%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) => Total passed: 1 out of 9 (11.11%) -Test serie 19: ['40 0f 04 55 55 55 55'] * 3 +Test serie 19: [u'40 0f 04 55 55 55 55'] * 3 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 1 out of 3 ( 33.33%) => Total passed: 1 out of 6 (16.67%) -Test serie 20: ['40 0d 03 55 55 55 55'] * 3 +Test serie 20: [u'40 0d 03 55 55 55 55'] * 3 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 0 out of 3 ( 0.00%) => Total passed: 0 out of 6 (0.00%) -Test serie 21: ['40 0b 07 55 55 55 55'] * 10 +Test serie 21: [u'40 0b 07 55 55 55 55'] * 10 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 2 out of 10 ( 20.00%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) => Total passed: 2 out of 30 (6.67%) -Test serie 22: ['40 0f 04 55 55 55 55'] * 10 +Test serie 22: [u'40 0f 04 55 55 55 55'] * 10 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 5 out of 10 ( 50.00%) => Total passed: 5 out of 20 (25.00%) -Test serie 23: ['40 0d 03 55 55 55 55'] * 10 +Test serie 23: [u'40 0d 03 55 55 55 55'] * 10 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 3 out of 10 ( 30.00%) => Total passed: 3 out of 20 (15.00%) -Test serie 24: ['40 0b 07 88 88 88 88'] * 1 +Test serie 24: [u'40 0b 07 88 88 88 88'] * 1 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) => Total passed: 0 out of 3 (0.00%) -Test serie 25: ['40 0f 04 88 88 88 88'] * 1 +Test serie 25: [u'40 0f 04 88 88 88 88'] * 1 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) => Total passed: 0 out of 2 (0.00%) -Test serie 26: ['40 0d 03 88 88 88 88'] * 1 +Test serie 26: [u'40 0d 03 88 88 88 88'] * 1 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 1 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 1 (100.00%) => Total passed: 1 out of 2 (50.00%) -Test serie 27: ['40 0b 07 88 88 88 88'] * 5 +Test serie 27: [u'40 0b 07 88 88 88 88'] * 5 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 2 out of 5 ( 40.00%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) => Total passed: 2 out of 15 (13.33%) -Test serie 28: ['40 0f 04 88 88 88 88'] * 5 +Test serie 28: [u'40 0f 04 88 88 88 88'] * 5 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) => Total passed: 0 out of 10 (0.00%) -Test serie 29: ['40 0d 03 88 88 88 88'] * 5 +Test serie 29: [u'40 0d 03 88 88 88 88'] * 5 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 5 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 1 out of 5 ( 20.00%) => Total passed: 1 out of 10 (10.00%) -Test serie 30: ['40 0b 07 88 88 88 88'] * 10 +Test serie 30: [u'40 0b 07 88 88 88 88'] * 10 Test 0 :: cr4-5 bw125 sf7 crc1 pwr1 :: passed 5 out of 10 ( 50.00%) Test 1 :: cr4-5 bw125 sf8 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 2 :: cr4-5 bw125 sf12 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) => Total passed: 5 out of 30 (16.67%) -Test serie 31: ['40 0f 04 88 88 88 88'] * 10 +Test serie 31: [u'40 0f 04 88 88 88 88'] * 10 Test 0 :: cr4-7 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 1 :: cr4-7 bw125 sf7 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) => Total passed: 0 out of 20 (0.00%) -Test serie 32: ['40 0d 03 88 88 88 88'] * 10 +Test serie 32: [u'40 0d 03 88 88 88 88'] * 10 Test 0 :: cr4-6 bw125 sf6 crc1 pwr1 :: passed 0 out of 10 ( 0.00%) Test 1 :: cr4-6 bw125 sf7 crc1 pwr1 :: passed 4 out of 10 ( 40.00%) => Total passed: 4 out of 20 (20.00%) ====== Total passed: 51 out of 413 (12.35%) ====== - Ran 33 tests in 278.085s + Ran 1 tests in 278.085s diff --git a/examples/qa_BasicTest_Data.xml b/examples/qa_BasicTest_Data.xml new file mode 100644 index 0000000..ec5833c --- /dev/null +++ b/examples/qa_BasicTest_Data.xml @@ -0,0 +1,619 @@ + + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_000.cfile + 7 + 80 0b 01 01 23 45 67 89 ab cd ef + 80 0b 01 + 01 23 45 67 89 ab cd ef + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_000.cfile + 8 + 80 0b 01 01 23 45 67 89 ab cd ef + 80 0b 01 + 01 23 45 67 89 ab cd ef + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_000.cfile + 12 + 80 0b 01 01 23 45 67 89 ab cd ef + 80 0b 01 + 01 23 45 67 89 ab cd ef + 10 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_000.cfile + 6 + 80 0f 02 01 23 45 67 89 ab cd ef + 80 0f 02 + 01 23 45 67 89 ab cd ef + 10 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_000.cfile + 7 + 80 0f 02 01 23 45 67 89 ab cd ef + 80 0f 02 + 01 23 45 67 89 ab cd ef + 10 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_000.cfile + 6 + 80 0d 05 01 23 45 67 89 ab cd ef + 80 0d 05 + 01 23 45 67 89 ab cd ef + 10 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_000.cfile + 7 + 80 0d 05 01 23 45 67 89 ab cd ef + 80 0d 05 + 01 23 45 67 89 ab cd ef + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_001.cfile + 7 + 30 0b 02 11 11 11 + 30 0b 02 + 11 11 11 + 1 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_001.cfile + 8 + 30 0b 02 11 11 11 + 30 0b 02 + 11 11 11 + 1 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_001.cfile + 12 + 30 0b 02 11 11 11 + 30 0b 02 + 11 11 11 + 1 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_001.cfile + 6 + 30 0f 01 11 11 11 + 30 0f 01 + 11 11 11 + 1 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_001.cfile + 7 + 30 0f 01 11 11 11 + 30 0f 01 + 11 11 11 + 1 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_001.cfile + 6 + 30 0d 06 11 11 11 + 30 0d 06 + 11 11 11 + 1 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_001.cfile + 7 + 30 0d 06 11 11 11 + 30 0d 06 + 11 11 11 + 1 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_002.cfile + 7 + 30 0b 02 11 11 11 + 30 0b 02 + 11 11 11 + 5 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_002.cfile + 8 + 30 0b 02 11 11 11 + 30 0b 02 + 11 11 11 + 5 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_002.cfile + 12 + 30 0b 02 11 11 11 + 30 0b 02 + 11 11 11 + 5 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_002.cfile + 6 + 30 0f 01 11 11 11 + 30 0f 01 + 11 11 11 + 5 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_002.cfile + 7 + 30 0f 01 11 11 11 + 30 0f 01 + 11 11 11 + 5 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_002.cfile + 6 + 30 0d 06 11 11 11 + 30 0d 06 + 11 11 11 + 5 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_002.cfile + 7 + 30 0d 06 11 11 11 + 30 0d 06 + 11 11 11 + 5 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_003.cfile + 7 + 40 0b 07 aa aa aa aa + 40 0b 07 + aa aa aa aa + 3 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_003.cfile + 8 + 40 0b 07 aa aa aa aa + 40 0b 07 + aa aa aa aa + 3 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_003.cfile + 12 + 40 0b 07 aa aa aa aa + 40 0b 07 + aa aa aa aa + 3 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_003.cfile + 6 + 40 0f 04 aa aa aa aa + 40 0f 04 + aa aa aa aa + 3 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_003.cfile + 7 + 40 0f 04 aa aa aa aa + 40 0f 04 + aa aa aa aa + 3 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_003.cfile + 6 + 40 0d 03 aa aa aa aa + 40 0d 03 + aa aa aa aa + 3 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_003.cfile + 7 + 40 0d 03 aa aa aa aa + 40 0d 03 + aa aa aa aa + 3 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_004.cfile + 7 + 40 0b 07 ff ff ff ff + 40 0b 07 + ff ff ff ff + 1 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_004.cfile + 8 + 40 0b 07 ff ff ff ff + 40 0b 07 + ff ff ff ff + 1 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_004.cfile + 12 + 40 0b 07 ff ff ff ff + 40 0b 07 + ff ff ff ff + 1 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_004.cfile + 6 + 40 0f 04 ff ff ff ff + 40 0f 04 + ff ff ff ff + 1 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_004.cfile + 7 + 40 0f 04 ff ff ff ff + 40 0f 04 + ff ff ff ff + 1 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_004.cfile + 6 + 40 0d 03 ff ff ff ff + 40 0d 03 + ff ff ff ff + 1 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_004.cfile + 7 + 40 0d 03 ff ff ff ff + 40 0d 03 + ff ff ff ff + 1 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_005.cfile + 7 + 40 0b 07 ff ff ff ff + 40 0b 07 + ff ff ff ff + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_005.cfile + 8 + 40 0b 07 ff ff ff ff + 40 0b 07 + ff ff ff ff + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_005.cfile + 12 + 40 0b 07 ff ff ff ff + 40 0b 07 + ff ff ff ff + 10 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_005.cfile + 6 + 40 0f 04 ff ff ff ff + 40 0f 04 + ff ff ff ff + 10 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_005.cfile + 7 + 40 0f 04 ff ff ff ff + 40 0f 04 + ff ff ff ff + 10 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_005.cfile + 6 + 40 0d 03 ff ff ff ff + 40 0d 03 + ff ff ff ff + 10 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_005.cfile + 7 + 40 0d 03 ff ff ff ff + 40 0d 03 + ff ff ff ff + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_006.cfile + 7 + 40 0b 07 55 55 55 55 + 40 0b 07 + 55 55 55 55 + 3 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_006.cfile + 8 + 40 0b 07 55 55 55 55 + 40 0b 07 + 55 55 55 55 + 3 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_006.cfile + 12 + 40 0b 07 55 55 55 55 + 40 0b 07 + 55 55 55 55 + 3 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_006.cfile + 6 + 40 0f 04 55 55 55 55 + 40 0f 04 + 55 55 55 55 + 3 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_006.cfile + 7 + 40 0f 04 55 55 55 55 + 40 0f 04 + 55 55 55 55 + 3 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_006.cfile + 6 + 40 0d 03 55 55 55 55 + 40 0d 03 + 55 55 55 55 + 3 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_006.cfile + 7 + 40 0d 03 55 55 55 55 + 40 0d 03 + 55 55 55 55 + 3 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_007.cfile + 7 + 40 0b 07 55 55 55 55 + 40 0b 07 + 55 55 55 55 + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_007.cfile + 8 + 40 0b 07 55 55 55 55 + 40 0b 07 + 55 55 55 55 + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_007.cfile + 12 + 40 0b 07 55 55 55 55 + 40 0b 07 + 55 55 55 55 + 10 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_007.cfile + 6 + 40 0f 04 55 55 55 55 + 40 0f 04 + 55 55 55 55 + 10 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_007.cfile + 7 + 40 0f 04 55 55 55 55 + 40 0f 04 + 55 55 55 55 + 10 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_007.cfile + 6 + 40 0d 03 55 55 55 55 + 40 0d 03 + 55 55 55 55 + 10 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_007.cfile + 7 + 40 0d 03 55 55 55 55 + 40 0d 03 + 55 55 55 55 + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_008.cfile + 7 + 40 0b 07 88 88 88 88 + 40 0b 07 + 88 88 88 88 + 1 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_008.cfile + 8 + 40 0b 07 88 88 88 88 + 40 0b 07 + 88 88 88 88 + 1 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_008.cfile + 12 + 40 0b 07 88 88 88 88 + 40 0b 07 + 88 88 88 88 + 1 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_008.cfile + 6 + 40 0f 04 88 88 88 88 + 40 0f 04 + 88 88 88 88 + 1 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_008.cfile + 7 + 40 0f 04 88 88 88 88 + 40 0f 04 + 88 88 88 88 + 1 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_008.cfile + 6 + 40 0d 03 88 88 88 88 + 40 0d 03 + 88 88 88 88 + 1 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_008.cfile + 7 + 40 0d 03 88 88 88 88 + 40 0d 03 + 88 88 88 88 + 1 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_009.cfile + 7 + 40 0b 07 88 88 88 88 + 40 0b 07 + 88 88 88 88 + 5 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_009.cfile + 8 + 40 0b 07 88 88 88 88 + 40 0b 07 + 88 88 88 88 + 5 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_009.cfile + 12 + 40 0b 07 88 88 88 88 + 40 0b 07 + 88 88 88 88 + 5 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_009.cfile + 6 + 40 0f 04 88 88 88 88 + 40 0f 04 + 88 88 88 88 + 5 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_009.cfile + 7 + 40 0f 04 88 88 88 88 + 40 0f 04 + 88 88 88 88 + 5 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_009.cfile + 6 + 40 0d 03 88 88 88 88 + 40 0d 03 + 88 88 88 88 + 5 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_009.cfile + 7 + 40 0d 03 88 88 88 88 + 40 0d 03 + 88 88 88 88 + 5 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf7_crc1_pwr1_010.cfile + 7 + 40 0b 07 88 88 88 88 + 40 0b 07 + 88 88 88 88 + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf8_crc1_pwr1_010.cfile + 8 + 40 0b 07 88 88 88 88 + 40 0b 07 + 88 88 88 88 + 10 + + + ./examples/lora-samples/hackrf_cr4-5_bw125_sf12_crc1_pwr1_010.cfile + 12 + 40 0b 07 88 88 88 88 + 40 0b 07 + 88 88 88 88 + 10 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf6_crc1_pwr1_010.cfile + 6 + 40 0f 04 88 88 88 88 + 40 0f 04 + 88 88 88 88 + 10 + + + ./examples/lora-samples/hackrf_cr4-7_bw125_sf7_crc1_pwr1_010.cfile + 7 + 40 0f 04 88 88 88 88 + 40 0f 04 + 88 88 88 88 + 10 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_010.cfile + 6 + 40 0d 03 88 88 88 88 + 40 0d 03 + 88 88 88 88 + 10 + + + ./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_010.cfile + 7 + 40 0d 03 88 88 88 88 + 40 0d 03 + 88 88 88 88 + 10 + + diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index fce1485..2de6a8e 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -52,3 +52,4 @@ set(GR_TEST_TARGET_DEPS gnuradio-lora) set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) GR_ADD_TEST(qa_receiver ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_receiver.py) GR_ADD_TEST(qa_BasicTest ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_BasicTest.py) +GR_ADD_TEST(qa_BasicTest_XML ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_BasicTest_XML.py) diff --git a/python/qa_BasicTest_XML.py b/python/qa_BasicTest_XML.py new file mode 100644 index 0000000..dab9782 --- /dev/null +++ b/python/qa_BasicTest_XML.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python2 +import lora, socket, pmt, time +import collections, datetime +import os.path +import xmltodict + +from gnuradio import gr, gr_unittest, blocks + +TestResultData = collections.namedtuple('TestResultData', ['fromfile', 'passing', 'total', 'rate']) +TestSerieSettings = collections.namedtuple('TestSerieSettings', ['data', 'times']) + +class qa_BasicTest_XML (gr_unittest.TestCase): + + # + # Listen on socket for data, append to list if any and return list of captured data. + # + def gatherFromSocket(self, amount): + total_data = [] + data = '' + + for i in range(amount): + try: + data = self.server.recv(4096) + if data: + total_data.append(data) + except: + pass + + return total_data + + # + # Compare captured data list with the expected data list. + # Print received data, expected data and if they match. + # Also give feedback about successrate in the decoding (percentage correctly captured and decoded). + # + def compareDataSets(self, total_data, expected_data, fromfile, cmpHDR): + global testResults + total_passing = 0 + + print '\nReceived:' + + for idx, val in enumerate(expected_data): + data_str = '?' + passed = True + + try: + data_str = " ".join("{:02x}".format(ord(n)) for n in total_data[idx]) + self.assertEqual(val, data_str if cmpHDR else data_str[9:]) + except: + passed = False + + if passed: + total_passing += 1 + print "{0: 3d} :: match:\n {1:s}".format(idx, val) + else: + print "{0: 3d} :: mismatch:\n {1:s}".format(idx, data_str) + print "should be:\n {0:s}".format(expected_data[idx]) + + results = TestResultData(fromfile, total_passing, len(expected_data), float(total_passing) / len(expected_data) * 100.0) + testResults[len(testResults) - 1].append(results) + print ("\nPassed rate: {0:d} out of {1:d} ({2:.2f}%)\n" + .format(results[1], results[2], results[3])) + + # + # Connect a filesource with the given file and run the flowgraph. + # File is acquired from the file_sink block and saved as .cfile (complex IQ data). + # + def runWithFileSourceAndData(self, infile, SpreadingFactor, cmpHDR): + print "Starting test from data in: {0:s}\n".format(infile) + + if os.path.isfile(infile): + self.file_source.close() + self.file_source.open(infile, False) + self.sf = SpreadingFactor + self.lora_lora_receiver_0.set_sf(self.sf) + self.tb.run () + + total_data = self.gatherFromSocket(test_series[len(test_series) - 1][1]) + self.compareDataSets(total_data, + test_series[len(test_series) - 1][0] * test_series[len(test_series) - 1][1], + os.path.splitext(os.path.basename(infile))[0], + cmpHDR) + else: + raise Exception("Error file does not exists!") + + # + # Set up flowgraph before Unit Test. (Gets threrefore called before EVERY test) + # + # 1. Set variables for various blocks (spreading factor from test_series settings) + # 2. Make UDP socket server to listen for outputted messages + # 3. Connect blocks: (file_source) -> throttle -> lora_receiver -> message_socket_sink + # + def setUp (self): + ################################################## + # Variables # + ################################################## + self.target_freq = 868.1e6 + self.sf = 7 + self.samp_rate = 1e6 + self.capture_freq = 868.0e6 + #self.bw = 125e3 + #self.symbols_per_sec = self.bw / (2**self.sf) + self.offset = -(self.capture_freq - self.target_freq) + #self.bitrate = self.sf * (1 / (2**self.sf / self.bw )) + + # Socket connection for sink + self.host = "127.0.0.1" + self.port = 40868 + + self.server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.server.bind((self.host, self.port)) + self.server.setblocking(0) ## or self.server.settimeout(0.5) ? + + self.lastTestComplete = False + + self.logFile = './examples/qa_BasicTest.log' + + self.xmlFile = './examples/qa_BasicTest_Data.xml' + + if os.path.isfile(self.xmlFile): + f = open(self.xmlFile, 'r') + self.xmlTests = xmltodict.parse(f.read())["lora-test-data"]["TEST"] + f.close() + else: + raise Exception("[BasicTest_XML] '" + self.xmlFile + "' does not exists!") + + self.prevData = "" + + ################################################## + # Blocks # + ################################################## + self.tb = gr.top_block () + + self.file_source = blocks.file_source(gr.sizeof_gr_complex*1, "./", False) # Repeat input: True/False + self.lora_lora_receiver_0 = lora.lora_receiver(self.samp_rate, self.capture_freq, self.offset, self.sf, self.samp_rate) + self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, self.samp_rate, True) + self.blocks_message_socket_sink_0 = lora.message_socket_sink() + + self.tb.connect( (self.file_source, 0), (self.blocks_throttle_0, 0)) + self.tb.connect( (self.blocks_throttle_0, 0), (self.lora_lora_receiver_0, 0)) + self.tb.msg_connect( (self.lora_lora_receiver_0, 'frames'), (self.blocks_message_socket_sink_0, 'in')) + + # + # Clean-up flowgraph after Unit Test. (Gets threrefore called after EVERY test) + # + # If last test was completed, report results. + # + def tearDown (self): + self.tb = None + self.xmlTests = None + self.server.close() + + if self.lastTestComplete: + flog = open(self.logFile, 'a') + passed_t_a = 0 + passed_t = 0 + total_t_a = 0 + total_t = 0 + stro = ("-" * 8) + " Test Results on " + str(datetime.datetime.now())[:19] + " " + ("-" * 9) + print(stro) + flog.write(stro + '\n') + + for j, serie in enumerate(testResults): + total_t = passed_t = 0 + + stro = ("Test serie {0: 3d}: {1:s} * {2:d}" + .format(j, test_series[j][0], test_series[j][1])) + print(stro) + flog.write(stro + '\n') + + for i, x in enumerate(serie): + passed_t += x[1] + total_t += x[2] + stro = (" Test {0: 3d} :: {1:5s} {2:5s} {3:4s} {4:4s} {5:4s} :: passed {6: 3d} out of {7: 3d} ({8:6.2f}%)" + .format(i, *(x[0].split('_')[1:-1] + [x[1]] + [x[2]] + [x[3]]))) + print(stro) + flog.write(stro + '\n') + + passed_t_a += passed_t + total_t_a += total_t + stro = (" => Total passed: {0:d} out of {1:d} ({2:.2f}%)\n" + .format(passed_t, total_t, float(passed_t) / (total_t if total_t else 1.0) * 100.0)) + print(stro) + flog.write(stro + '\n') + + stro = ("\n ====== Total passed: {0:d} out of {1:d} ({2:.2f}%) ======" + .format(passed_t_a, total_t_a, float(passed_t_a) / (total_t_a if total_t_a else 1.0) * 100.0)) + print(stro) + flog.write(stro + '\n\n') + flog.close() + + print ("Log appended to: " + self.logFile) + + + +################################################################################################### +# Unit tests # +# These assume a directory "./examples/lora-samples" # +# with the specified .cfiles existing. # +################################################################################################### + # def test_032 (self): + # testResults.append( [] ) + # test_series.append( TestSerieSettings(["40 0d 03 88 88 88 88"] , 10) ) + # + # self.runWithFileSourceAndData('./examples/lora-samples/hackrf_cr4-6_bw125_sf6_crc1_pwr1_010.cfile', 6) + # self.runWithFileSourceAndData('./examples/lora-samples/hackrf_cr4-6_bw125_sf7_crc1_pwr1_010.cfile', 7) + # + # self.lastTestComplete = True + + ############################################################################################### + # Unit tests series from qa_BasicTest_Data.xml # + ############################################################################################### + def test_000 (self): + for test in self.xmlTests: + # print (("Test {0: 3d}\n" + # + " File: {1:s}\n" + # + " SF: {2: 2d}\n" + # + " All data: {3:s}\n" + # + " HDR: {4:s}\n" + # + " DATA: {5:s}\n" + # + " times: {6: 2d}") + # .format(int(test['@id']), test['file'], int(test['spreading-factor']), + # test['expected-data-all'], test['expected-hdr'], + # test['expected-data-only'], int(test['expected-times'])) + # ) + + data = test['expected-data-all'] + hasHDR = True + + if not data: + data = test['expected-hdr'] + if not data: + hasHDR = False + data = test['expected-data-only'] + else: + data = data + " " + test['expected-data-only'] + + infile = str(test['file']) + + if data and os.path.isfile(infile): + if data != self.prevData: + testResults.append( [] ) + test_series.append( TestSerieSettings([data], int(test['expected-times'])) ) + self.prevData = data + self.runWithFileSourceAndData(infile, int(test['spreading-factor']), hasHDR) + else: + print("No test data or file does not exist, skipping test {0: 3d}...".format(int(test['@id']))) + + self.lastTestComplete = True + + +if __name__ == '__main__': + global testResults + testResults = [] + global test_series + test_series = [] + + gr_unittest.run(qa_BasicTest_XML)