1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-28 07:51:19 +01:00

tests/pkg_semtech-loramac: add automatic test

This commit is contained in:
Francisco Molina 2019-07-18 17:10:52 +02:00
parent 9e130be8a8
commit f60e6e008d
No known key found for this signature in database
GPG Key ID: 3E94EAC3DBDEEDA8
3 changed files with 255 additions and 0 deletions

View File

@ -26,4 +26,12 @@ USEMODULE += fmt
FEATURES_OPTIONAL += periph_eeprom
# Default IotLab Config to run the test
ifneq (,$(filter iotlab%,$(MAKECMDGOALS)))
IOTLAB_NODES ?= 1
IOTLAB_TYPE ?= st-lrwan1:sx1276
IOTLAB_SITE ?= saclay
include $(RIOTBASE)/dist/testbed-support/Makefile.iotlab
endif
include $(RIOTBASE)/Makefile.include

View File

@ -206,3 +206,63 @@ The node will also print the data received:
> loramac tx test
Data received: This is RIOT!
## Automatic test
The automatic test replicates 11-lorawan release specs tests:
- [11-lorawan](https://github.com/RIOT-OS/Release-Specs/blob/ba236c4a1d1258ab63d21b0a860d0f5a5935bbd4/11-lorawan/11-lorawan.md)
- [Task #02 - OTAA join procedure](https://github.com/RIOT-OS/Release-Specs/blob/ba236c4a1d1258ab63d21b0a860d0f5a5935bbd4/11-lorawan/11-lorawan.md#task-02---otaa-join-procedure)
- [Task #03 - ABP join procedure](https://github.com/RIOT-OS/Release-Specs/blob/ba236c4a1d1258ab63d21b0a860d0f5a5935bbd4/11-lorawan/11-lorawan.md#task-03---abp-join-procedure)
- [Task #04 - LoRaWAN device parameters persistence](https://github.com/RIOT-OS/Release-Specs/blob/master/11-lorawan/11-lorawan.md#task-04---lorawan-device-parameters-persistence)
It is recommended to test using iotlab-nodes. The default configuration is already
set on the application Makefile.
### Requirements
- The tests assumes that there is a gateway in all DR distance to the device and the
device was flashed with the correct keys. The APPEUI is assumed to be the same for OTAA
and ABP.
- The DR duty cycling time-offs values are for EU863-870
- To use iotlab it is required to have a valid account for the FIT IoT-LAB
(registration there is open for everyone) and the [iot-lab/cli-tools](https://github.com/iot-lab/cli-tools) need to be installed.
- The frame counters must be reset on the LoRaWAN backend at the beginning of the
test.
- iotlab uses TTN lorawan gateways, to run the test you will need to create an
[account](https://account.thethingsnetwork.org/), add an [application](https://www.thethingsnetwork.org/docs/applications/add.html)
and [register](https://www.thethingsnetwork.org/docs/devices/registration.html)
a device. Two devices must be registered, one configured for OTA and another
for ABP. For this test you need to take note of the Device EUI, Application EUI
& Application Key of the device registered for OTA, as well as the Device EUI,
Device Address, Network and Application session keys of the device registered
for ABP. The test assumes that both devices have the same Application EUI.
### Usage
1. flash device with appropriate keys and test
$ DEVEUI_OTA=<...> DEVEUI_ABP=<...> APPEUI=<...> APPKEY=<...> DEVADDR=<...> NWKSKEY=<...> APPSKEY=<...> RX2_DR=<...> make BOARD=b-l072z-lrwan1 -C tests/pkg_semtech-loramac test
#### With iotlab
1. setup the iotlab experiment:
$ make -C tests/pkg_semtech-loramac iotlab-exp
2. flash device with the appropriate keys and test
$ DEVEUI=<...> APPEUI=<...> APPKEY=<...> DEVADDR=<...> NWKSKEY=<...> APPSKEY=<...> RX2_DR=<...> IOTLAB_NODE=auto-ssh make -C tests/pkg_semtech-loramac flash test
3. stop the iotlab experiment:
$ make -C examples/lorawan/ iotlab-stop
_note_: if you have multiple running experiments you will need to set `IOTLAB_EXP_ID`
to the appropriate experiment, when using the `iotlab-exp` you will see a:
`Waiting that experiment 175694 gets in state Running`. That number matches
the experiment id you started.

View File

@ -0,0 +1,187 @@
#!/usr/bin/env python3
# Copyright (C) 2019 Inria
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
import os
import sys
import time
from testrunner import run
# It's assumed that the same APPEUI is used for abp and otaa
DEVEUI_ABP = os.getenv('DEVEUI_ABP')
DEVEUI_OTA = os.getenv('DEVEUI_OTA')
APPEUI = os.getenv('APPEUI')
APPKEY = os.getenv('APPKEY')
DEVADDR = os.getenv('DEVADDR')
NWKSKEY = os.getenv('NWKSKEY')
APPSKEY = os.getenv('APPSKEY')
# Default to things network RX2_DR
TEST_RX2_DR = os.getenv('RX2_DR', 3)
# Theoretical duty cycling timeoff for EU863-870
# https://www.semtech.com/uploads/documents/LoraDesignGuide_STD.pdf#page=7
TEST_DATA_RATES = {"0": 164.6, "3": 20.6, "5": 6.2}
# Dummy Message
MSG = "This is RIOT"
def _send_line_echo(child, line):
child.sendline(line)
child.expect_exact(line)
child.expect_exact(">")
def _send_line(child, line, expect_line):
child.sendline(line)
child.expect_exact(expect_line)
child.expect_exact(">")
def _reset_config(child):
# Start with a clean config
child.sendline("loramac erase")
child.expect("loramac erase")
child.expect_exact(">")
child.sendline("reboot")
child.expect_exact("reboot")
child.expect_exact("All up, running the shell now")
child.expect_exact(">")
def _check_eeprom(child):
# Check if eeprom is supported
child.sendline("loramac help")
child.expect(r'Usage: loramac \<([\w+\|?]+)\>')
return (len(child.match.group(1).split('|')) == 7)
def _reboot(child, join):
if join == "abp":
child.sendline("loramac get ul_cnt")
child.expect(r'Uplink Counter: (\d+)')
uplink_counter = int(child.match.group(1))
child.sendline("reboot")
child.expect_exact("All up, running the shell now")
child.expect_exact(">")
if join == "abp":
_send_line_echo(child, "loramac set ul_cnt {}".format(uplink_counter))
def _loramac_setup(child, join):
if join == "abp":
_send_line_echo(child, "loramac set deveui {}".format(DEVEUI_ABP))
_send_line_echo(child, "loramac set appeui {}".format(APPEUI))
_send_line_echo(child, "loramac set devaddr {}".format(DEVADDR))
_send_line_echo(child, "loramac set nwkskey {}".format(NWKSKEY))
_send_line_echo(child, "loramac set appskey {}".format(APPSKEY))
_send_line_echo(child, "loramac set rx2_dr {}".format(TEST_RX2_DR))
else:
_send_line_echo(child, "loramac set deveui {}".format(DEVEUI_OTA))
_send_line_echo(child, "loramac set appeui {}".format(APPEUI))
_send_line_echo(child, "loramac set appkey {}".format(APPKEY))
def loramac_tx_test(child, join):
_reset_config(child)
# test all data rates
for key, time_off in TEST_DATA_RATES.items():
# Setup keys and rx2_dr
_loramac_setup(child, join)
# Set DR and join
_send_line_echo(child, "loramac set dr {}".format(key))
child.sendline("loramac join {}".format(join))
child.expect_exact(["Join procedure succeeded!",
"Warning: already joined!"])
child.expect_exact(">")
# Transmit cnf message
child.sendline("loramac tx \"{}\" cnf 123".format(MSG))
child.expect_exact("Received ACK from network", timeout=30)
child.expect_exact("Message sent with success")
child.expect_exact(">")
# Wake-up just before time_off, fail to send
time.sleep(time_off)
# Send uncnf message with success
child.sendline("loramac tx \"{}\" uncnf 42".format(MSG))
child.expect_exact("Message sent with success")
child.expect_exact(">")
# Reboot node
_reboot(child, join)
def test_task02(child):
loramac_tx_test(child, "otaa")
def test_task03(child):
loramac_tx_test(child, "abp")
def test_task04(child):
# Erase eeprom
_reset_config(child)
# Verify start from erased state
_send_line(child, "loramac get deveui", "DEVEUI: 0000000000000000")
_send_line(child, "loramac get appeui", "APPEUI: 0000000000000000")
_send_line(child, "loramac get appkey",
"APPKEY: 00000000000000000000000000000000")
_send_line(child, "loramac get devaddr", "DEVADDR: 00000000")
_send_line(child, "loramac get nwkskey",
"NWKSKEY: 00000000000000000000000000000000")
_send_line(child, "loramac get appskey",
"APPSKEY: 00000000000000000000000000000000")
# Save and verify otaa keys
_loramac_setup(child, "otaa")
_send_line_echo(child, "loramac save")
child.sendline("reboot")
child.expect_exact("All up, running the shell now")
child.expect_exact(">")
_send_line(child, "loramac get deveui", "DEVEUI: {}".format(DEVEUI_OTA))
_send_line(child, "loramac get appeui", "APPEUI: {}".format(APPEUI))
_send_line(child, "loramac get appkey", "APPKEY: {}".format(APPKEY))
_reset_config(child)
# Save and verify abp keys
_loramac_setup(child, "abp")
_send_line_echo(child, "loramac save")
child.sendline("reboot")
child.expect_exact("All up, running the shell now")
child.expect_exact(">")
_send_line(child, "loramac get devaddr", "DEVADDR: {}".format(DEVADDR))
_send_line(child, "loramac get nwkskey", "NWKSKEY: {}".format(NWKSKEY))
_send_line(child, "loramac get appskey", "APPSKEY: {}".format(APPSKEY))
def testfunc(child):
def run(func):
if child.logfile == sys.stdout:
func(child)
else:
try:
func(child)
print(".", end="", flush=True)
except Exception as e:
print("FAILED")
raise e
run(test_task02)
run(test_task03)
if(_check_eeprom(child)):
run(test_task04)
print("TEST PASSED")
if __name__ == "__main__":
sys.exit(run(testfunc))