mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #16080 from jia200x/pr/gnrc_lorawan_netif
gnrc_lorawan: encode LoRaWAN port in netif header
This commit is contained in:
commit
ae81b808a1
@ -1,24 +1,37 @@
|
||||
# name of your application
|
||||
APPLICATION = gnrc_lorawan
|
||||
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
USEMODULE += gnrc_netdev_default
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
USEMODULE += gnrc_lorawan
|
||||
USEMODULE += gnrc_pktdump
|
||||
USEMODULE += gnrc_neterr
|
||||
|
||||
BOARD ?= b-l072z-lrwan1
|
||||
RIOTBASE ?= ../../
|
||||
|
||||
# Turn on developer helpers
|
||||
DEVELHELP ?= 1
|
||||
|
||||
# use SX1276 by default
|
||||
DRIVER ?= sx1276
|
||||
BOARD ?= b-l072z-lrwan1
|
||||
RIOTBASE ?= ../../
|
||||
|
||||
USEMODULE += $(DRIVER)
|
||||
# Include board's default network devices and auto-initialization of GNRC
|
||||
# interfaces
|
||||
USEMODULE += gnrc_netdev_default
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
|
||||
# Add support for GNRC LoRaWAN
|
||||
USEMODULE += gnrc_lorawan
|
||||
|
||||
# Use GNRC pktdump to print downlink messages
|
||||
USEMODULE += gnrc_pktdump
|
||||
|
||||
# Include the shell and shell commands.
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
|
||||
# Use GNRC Txtsnd to transmit LoRaWAN from the shell
|
||||
USEMODULE += gnrc_txtsnd
|
||||
|
||||
# Uncomment as needed if a board doesn't include a LoRa radio by default
|
||||
# USEMODULE += sx1272
|
||||
# USEMODULE += sx1276
|
||||
|
||||
# As there is an 'app.config' we want to explicitly disable Kconfig by setting
|
||||
# the variable to empty
|
||||
SHOULD_RUN_KCONFIG ?=
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
||||
@ -33,6 +46,14 @@ include $(RIOTBASE)/Makefile.include
|
||||
# Check if being configured via Kconfig
|
||||
ifndef CONFIG_KCONFIG_USEMODULE_LORAWAN
|
||||
|
||||
# Tell GNRC to encode LoRaWAN port in the GNRC netif header.
|
||||
# This allows us to use `gnrc_txtsnd` to send data from the shell using the
|
||||
# `txtsnd` command.
|
||||
#
|
||||
# Note: From Release 22.01 all GNRC LoRaWAN packets will include the netif
|
||||
# header. Therefore this flag will be removed after that
|
||||
CFLAGS += -DCONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR
|
||||
|
||||
CFLAGS += -DCONFIG_LORAMAC_APP_KEY_DEFAULT=\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"
|
||||
CFLAGS += -DCONFIG_LORAMAC_APP_EUI_DEFAULT=\"BBBBBBBBBBBBBBBB\"
|
||||
CFLAGS += -DCONFIG_LORAMAC_DEV_EUI_DEFAULT=\"CCCCCCCCCCCCCCCC\"
|
||||
|
@ -15,7 +15,6 @@ Usage
|
||||
|
||||
It's necessary to join the LoRaWAN network either via OTAA or ABP.
|
||||
All keys, addresses and EUIs are in network endian (big endian).
|
||||
The application listens to downlinks on Port 2 by default.
|
||||
Region need to be set in the Makefile.
|
||||
|
||||
## OTAA
|
||||
@ -73,10 +72,15 @@ CFLAGS += -DCONFIG_LORAMAC_DEV_ADDR_DEFAULT=\"FFFFFFFF\"
|
||||
|
||||
## Send data
|
||||
|
||||
After join, send data using `send` command. E.g to send "Hello RIOT!" to port 2:
|
||||
After join, send data using `txtsnd` command:
|
||||
```
|
||||
txtsnd <if> <hex_port> <data>
|
||||
```
|
||||
|
||||
E.g to send "Hello RIOT!" to LoRaWAN port 123 (hex 0x7B) via interface 3:
|
||||
|
||||
```
|
||||
send 3 "Hello RIOT!" 2
|
||||
txtsnd 3 7B "Hello RIOT!"
|
||||
```
|
||||
|
||||
## Changing datarate of transmission
|
||||
@ -100,7 +104,7 @@ Send some data. The result of the Link Check request can be seen with
|
||||
|
||||
```
|
||||
ifconfig 3 link_check
|
||||
send 3 "Join the RIOT!"
|
||||
txtsnd 3 01 "Join the RIOT!"
|
||||
```
|
||||
|
||||
Check demodulation margin and number of gateways using `ifconfig`
|
||||
@ -124,18 +128,43 @@ E.g send confirmable messages:
|
||||
|
||||
```
|
||||
ifconfig 3 ack_req
|
||||
send 3 "My confirmable message"
|
||||
txtsnd 3 01 "My confirmable message"
|
||||
```
|
||||
|
||||
And unconfirmable messages:
|
||||
|
||||
```
|
||||
ifconfig 3 -ack_req
|
||||
send 3 "My unconfirmable message"
|
||||
txtsnd 3 01 "My unconfirmable message"
|
||||
```
|
||||
|
||||
## Receiving data
|
||||
|
||||
Schedule a downlink for the LoRaWAN node in the Application Server. If using
|
||||
TTN, this can be done under `Applications > <APP> > Devices > <DEV> > Overview`
|
||||
and then check the `Downlink` section.
|
||||
|
||||
After sending data, the LoRaWAN Network Server will reply with the downlink
|
||||
data. For simplicity, this application is configured to dump downlink data to
|
||||
[GNRC pktdump](https://doc.riot-os.org/pktdump_8h.html).
|
||||
|
||||
E.g:
|
||||
```
|
||||
PKTDUMP: data received:
|
||||
~~ SNIP 0 - size: 2 byte, type: NETTYPE_UNDEF (0)
|
||||
00000000 AA AA
|
||||
~~ SNIP 1 - size: 9 byte, type: NETTYPE_NETIF (-1)
|
||||
if_pid: 3 rssi: -32768 lqi: 0
|
||||
flags: 0x0
|
||||
src_l2addr: (nil)
|
||||
dst_l2addr: 01
|
||||
~~ PKT - 2 snips, total size: 11 byte
|
||||
```
|
||||
|
||||
This downlink was sent to port 1 (check `dst_l2addr` field)
|
||||
|
||||
Current state and future plans
|
||||
============
|
||||
==============================
|
||||
|
||||
The current GNRC LoRaWAN stack is still in an experimental state. It's still
|
||||
not compliant with the LoRaWAN specification because some features like duty
|
||||
|
2
examples/gnrc_lorawan/app.config
Normal file
2
examples/gnrc_lorawan/app.config
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_KCONFIG_USEMODULE_GNRC_NETIF=y
|
||||
CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR=y
|
@ -31,81 +31,23 @@
|
||||
#include "net/gnrc/netif.h"
|
||||
|
||||
#include "net/gnrc/pktbuf.h"
|
||||
#include "net/gnrc/pktdump.h"
|
||||
#include "net/gnrc/netreg.h"
|
||||
#include "net/gnrc/pktdump.h"
|
||||
#include "net/loramac.h"
|
||||
|
||||
#define LORAWAN_QUEUE_SIZE (4U)
|
||||
|
||||
static void _usage(void)
|
||||
{
|
||||
puts("usage: send <if_pid> <payload> [port]");
|
||||
}
|
||||
|
||||
int tx_cmd(int argc, char **argv)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt;
|
||||
uint8_t port = CONFIG_LORAMAC_DEFAULT_TX_PORT; /* Default: 2 */
|
||||
int interface;
|
||||
|
||||
if (argc < 3) {
|
||||
_usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
interface = atoi(argv[1]);
|
||||
/* handle optional parameters */
|
||||
if (argc > 3) {
|
||||
port = atoi(argv[3]);
|
||||
if (port == 0 || port >= 224) {
|
||||
printf("error: invalid port given '%d', "
|
||||
"port can only be between 1 and 223\n", port);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
pkt = gnrc_pktbuf_add(NULL, argv[2], strlen(argv[2]), GNRC_NETTYPE_UNDEF);
|
||||
|
||||
/* register for returned packet status */
|
||||
if (gnrc_neterr_reg(pkt) != 0) {
|
||||
puts("Can not register for error reporting");
|
||||
return 0;
|
||||
}
|
||||
|
||||
gnrc_netapi_set(interface, NETOPT_LORAWAN_TX_PORT, 0, &port, sizeof(port));
|
||||
gnrc_netif_send(gnrc_netif_get_by_pid(interface), pkt);
|
||||
|
||||
/* wait for packet status and check */
|
||||
msg_t msg;
|
||||
msg_receive(&msg);
|
||||
if ((msg.type != GNRC_NETERR_MSG_TYPE) ||
|
||||
(msg.content.value != GNRC_NETERR_SUCCESS)) {
|
||||
printf("Error sending packet: (status: %d\n)", (int) msg.content.value);
|
||||
}
|
||||
else {
|
||||
puts("Successfully sent packet");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "send", "Send LoRaWAN data", tx_cmd },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* start the shell */
|
||||
puts("Initialization successful - starting the shell now");
|
||||
gnrc_netreg_entry_t dump = GNRC_NETREG_ENTRY_INIT_PID(CONFIG_LORAMAC_DEFAULT_TX_PORT,
|
||||
|
||||
/* Receive LoRaWAN packets in GNRC pktdump */
|
||||
gnrc_netreg_entry_t dump = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL,
|
||||
gnrc_pktdump_pid);
|
||||
|
||||
gnrc_netreg_register(GNRC_NETTYPE_LORAWAN, &dump);
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump);
|
||||
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -31,6 +31,21 @@ extern "C" {
|
||||
*/
|
||||
#define GNRC_NETIF_LORAWAN_FLAGS_LINK_CHECK (0x1U)
|
||||
|
||||
/**
|
||||
* @brief Encode LoRaWAN port in GNRC netif header.
|
||||
*
|
||||
* When set, GNRC netif will interpret the destination address of the
|
||||
* GNRC netif header as the LoRaWAN port. For downlinks, a GNRC netif header
|
||||
* with the received port in destination field will be included in the
|
||||
* first snip.
|
||||
*
|
||||
* @deprecated From Release 2021.10 all GNRC LoRaWAN packets will include
|
||||
* the GNRC Netif header. Therefore this parameter will be removed
|
||||
*/
|
||||
#if defined(DOXYGEN)
|
||||
#define CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GNRC LoRaWAN interface descriptor
|
||||
*/
|
||||
|
@ -640,6 +640,20 @@ typedef enum {
|
||||
/**
|
||||
* @brief (uint8_t) LoRaWAN TX application port
|
||||
* - LoRaWAN: between 1 and 223 (included)
|
||||
*
|
||||
* @deprecated This option is deprecated and will be removed in the
|
||||
* 2022.01 Release.
|
||||
* The port is encoded now as a one byte
|
||||
* destination address in a @ref net_gnrc_netif_hdr snip
|
||||
* prepended in the packet.
|
||||
* The user must take care of prepending the required snip
|
||||
* during transmission. On reception, the
|
||||
* snip is prepended automatically by the stack and shall be
|
||||
* consumed by the user.
|
||||
* During the deprecation period it is required to
|
||||
* compile with @ref
|
||||
* CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR
|
||||
*
|
||||
*/
|
||||
NETOPT_LORAWAN_TX_PORT,
|
||||
|
||||
|
@ -118,6 +118,11 @@ int gnrc_lorawan_parse_dl(gnrc_lorawan_t *mac, uint8_t *buf, size_t len,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pkt->port > LORAMAC_PORT_MAX) {
|
||||
DEBUG("gnrc_lorawan: packet with port > 223. Drop\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buf < p_mic) {
|
||||
pkt->enc_payload.iol_base = buf;
|
||||
pkt->enc_payload.iol_len = p_mic - buf;
|
||||
|
@ -61,4 +61,17 @@ config GNRC_NETIF_PKTQ_TIMER_US
|
||||
Set to -1 to deactivate dequeing by timer. For this it has to be ensured
|
||||
that none of the notifications by the driver are missed!
|
||||
|
||||
config GNRC_NETIF_LORAWAN_NETIF_HDR
|
||||
bool "Encode LoRaWAN port in GNRC netif header"
|
||||
depends on USEMODULE_GNRC_LORAWAN
|
||||
help
|
||||
When set, GNRC Netif will interpret
|
||||
the destination address of the GNRC netif header as
|
||||
the LoRaWAN port. For downlinks, a GNRC netif header
|
||||
with the received port in destination field will be
|
||||
included in the first snip. From Release 2021.10 all
|
||||
GNRC LoRaWAN packets will include the GNRC Netif
|
||||
header. Therefore this parameter will be removed
|
||||
|
||||
|
||||
endif # KCONFIG_USEMODULE_GNRC_NETIF
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "net/gnrc/pktbuf.h"
|
||||
#include "net/gnrc/netif.h"
|
||||
#include "net/gnrc/netif/hdr.h"
|
||||
#include "net/gnrc/netif/lorawan.h"
|
||||
#include "net/gnrc/netif/internal.h"
|
||||
#include "net/gnrc/lorawan.h"
|
||||
@ -107,19 +108,47 @@ static inline void _set_be_addr(gnrc_lorawan_t *mac, uint8_t *be_addr)
|
||||
|
||||
void gnrc_lorawan_mcps_indication(gnrc_lorawan_t *mac, mcps_indication_t *ind)
|
||||
{
|
||||
(void)mac;
|
||||
gnrc_netif_t *netif = container_of(mac, gnrc_netif_t, lorawan.mac);
|
||||
gnrc_nettype_t nettype = IS_ACTIVE(CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR)
|
||||
? GNRC_NETTYPE_UNDEF
|
||||
: GNRC_NETTYPE_LORAWAN;
|
||||
uint32_t demux = IS_ACTIVE(CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR)
|
||||
? GNRC_NETREG_DEMUX_CTX_ALL
|
||||
: ind->data.port;
|
||||
|
||||
assert(ind->data.port >= LORAMAC_PORT_MIN && ind->data.port <= LORAMAC_PORT_MAX);
|
||||
|
||||
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, ind->data.pkt->iol_base,
|
||||
ind->data.pkt->iol_len,
|
||||
GNRC_NETTYPE_LORAWAN);
|
||||
nettype);
|
||||
if (!pkt) {
|
||||
DEBUG("gnrc_lorawan: mcps_indication: couldn't allocate pktbuf\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_LORAWAN, ind->data.port,
|
||||
pkt)) {
|
||||
gnrc_pktbuf_release(pkt);
|
||||
if (IS_ACTIVE(CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR)) {
|
||||
gnrc_pktsnip_t *netif_snip = gnrc_netif_hdr_build(NULL, 0,
|
||||
&ind->data.port,
|
||||
sizeof(ind->data.port));
|
||||
if (netif_snip == NULL) {
|
||||
DEBUG("gnrc_lorawan_netif: no space left in packet buffer\n");
|
||||
goto release;
|
||||
}
|
||||
|
||||
gnrc_netif_hdr_t *hdr = netif_snip->data;
|
||||
gnrc_netif_hdr_set_netif(hdr, netif);
|
||||
pkt = gnrc_pkt_append(pkt, netif_snip);
|
||||
}
|
||||
|
||||
if (!gnrc_netapi_dispatch_receive(nettype, demux, pkt)) {
|
||||
DEBUG("gnrc_lorawan_netif: unable to forward packet\n")
|
||||
goto release;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
release:
|
||||
gnrc_pktbuf_release(pkt);
|
||||
}
|
||||
|
||||
void gnrc_lorawan_mlme_indication(gnrc_lorawan_t *mac, mlme_indication_t *ind)
|
||||
@ -271,23 +300,51 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *payload)
|
||||
mlme_request_t mlme_request;
|
||||
mlme_confirm_t mlme_confirm;
|
||||
|
||||
gnrc_pktsnip_t *head;
|
||||
uint8_t port;
|
||||
int res = -EINVAL;
|
||||
|
||||
if (IS_ACTIVE(CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR)) {
|
||||
gnrc_netif_hdr_t *netif_hdr;
|
||||
const uint8_t *dst;
|
||||
netif_hdr = payload->data;
|
||||
dst = gnrc_netif_hdr_get_dst_addr(netif_hdr);
|
||||
|
||||
assert(payload->type == GNRC_NETTYPE_NETIF);
|
||||
head = payload->next;
|
||||
port = dst[0];
|
||||
|
||||
if (netif_hdr->dst_l2addr_len != sizeof(port)) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else {
|
||||
head = payload;
|
||||
port = netif->lorawan.port;
|
||||
}
|
||||
|
||||
if (netif->lorawan.flags & GNRC_NETIF_LORAWAN_FLAGS_LINK_CHECK) {
|
||||
mlme_request.type = MLME_LINK_CHECK;
|
||||
gnrc_lorawan_mlme_request(&netif->lorawan.mac, &mlme_request,
|
||||
&mlme_confirm);
|
||||
}
|
||||
|
||||
mcps_request_t req =
|
||||
{ .type = netif->lorawan.ack_req ? MCPS_CONFIRMED : MCPS_UNCONFIRMED,
|
||||
.data =
|
||||
{ .pkt = (iolist_t *)payload, .port = netif->lorawan.port,
|
||||
{ .pkt = (iolist_t *)head, .port = port,
|
||||
.dr = netif->lorawan.datarate } };
|
||||
mcps_confirm_t conf;
|
||||
|
||||
gnrc_lorawan_mcps_request(&netif->lorawan.mac, &req, &conf);
|
||||
if (conf.status < 0) {
|
||||
gnrc_pktbuf_release_error(payload, conf.status);
|
||||
res = conf.status;
|
||||
|
||||
end:
|
||||
if (res < 0) {
|
||||
gnrc_pktbuf_release_error(payload, res);
|
||||
}
|
||||
return conf.status;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void _msg_handler(gnrc_netif_t *netif, msg_t *msg)
|
||||
|
Loading…
Reference in New Issue
Block a user