-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
examples: add a lorawan OTAA/class A example
- Loading branch information
Showing
3 changed files
with
239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# name of your application | ||
APPLICATION = lorawan | ||
|
||
# Use the ST B-L072Z-LRWAN1 board by default: | ||
BOARD ?= b-l072z-lrwan1 | ||
|
||
# This has to be the absolute path to the RIOT base directory: | ||
RIOTBASE ?= $(CURDIR)/../.. | ||
|
||
BOARD_INSUFFICIENT_MEMORY := nucleo32-f031 nucleo32-f042 nucleo32-l031 | ||
|
||
DEVEUI ?= 0000000000000000 | ||
APPEUI ?= 0000000000000000 | ||
APPKEY ?= 00000000000000000000000000000000 | ||
|
||
# Default radio driver is Semtech SX1276 (used by the B-L072Z-LRWAN1 board) | ||
DRIVER ?= sx1276 | ||
|
||
# Default region is Europe and default band is 868MHz | ||
REGION ?= EU868 | ||
|
||
# Include the Semtech-loramac package | ||
USEPKG += semtech-loramac | ||
|
||
USEMODULE += $(DRIVER) | ||
USEMODULE += fmt | ||
FEATURES_REQUIRED += periph_rtc | ||
|
||
CFLAGS += -DREGION_$(REGION) | ||
CFLAGS += -DDEVEUI=\"$(DEVEUI)\" -DAPPEUI=\"$(APPEUI)\" -DAPPKEY=\"$(APPKEY)\" | ||
|
||
# Comment this out to disable code in RIOT that does safety checking | ||
# which is not needed in a production environment but helps in the | ||
# development process: | ||
DEVELHELP ?= 1 | ||
|
||
# Change this to 0 show compiler invocation lines by default: | ||
QUIET ?= 1 | ||
|
||
include $(RIOTBASE)/Makefile.include |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
LoRaWAN | ||
======= | ||
|
||
Description | ||
----------- | ||
|
||
This application shows a simple use case of LoRaWAN with RIOT. | ||
|
||
By using the real time clock and low-power capabilities of a board, this | ||
application shows how to program a LoRaWAN Class A devices using RIOT. | ||
|
||
This application is using the Over-The-Air Activation procedure. | ||
|
||
Usage | ||
----- | ||
|
||
Simply build and flash the application for a ST B-L072Z-LRWAN1 board: | ||
|
||
make flash term | ||
|
||
Use the `BOARD`, `DRIVER` and `REGION` make variables to adapt the application | ||
to your hardware setup and region of use: | ||
|
||
- `BOARD` can be one of the nucleo-64 boards | ||
- `DRIVER` can be either `sx1276` or `sx1272` | ||
- `REGION` can be `EU868`, `US915`, etc (see LoRaWAN regional parameters for | ||
details). | ||
|
||
ST Nucleo-64 can be used with an mbed LoRa shield: there's one based on | ||
[the sx1276 radio](https://os.mbed.com/components/SX1276MB1xAS/) and one based | ||
on the [the sx1272 radio](https://os.mbed.com/components/SX1272MB2xAS/). | ||
|
||
Finally, to join a LoRaWAN network using OTAA activation, edit the application | ||
`Makefile` and set your device information: | ||
|
||
DEVEUI ?= 0000000000000000 | ||
APPEUI ?= 0000000000000000 | ||
APPKEY ?= 00000000000000000000000000000000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
/* | ||
* Copyright (C) 2018 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. | ||
*/ | ||
|
||
/** | ||
* @ingroup examples | ||
* @{ | ||
* | ||
* @file | ||
* @brief Example demonstrating the use of LoRaWAN with RIOT | ||
* | ||
* @author Alexandre Abadie <alexandre.abadie@inria.fr> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <string.h> | ||
#include <stdlib.h> | ||
#include <time.h> | ||
|
||
#include "msg.h" | ||
#include "thread.h" | ||
#include "fmt.h" | ||
|
||
#ifdef MODULE_PM_LAYERED | ||
#include "pm_layered.h" | ||
#endif | ||
#include "periph/rtc.h" | ||
|
||
#include "net/loramac.h" | ||
#include "semtech_loramac.h" | ||
|
||
/* Use the STOP mode to ensure memory retention between each send */ | ||
#define PM_MODE (1) | ||
|
||
/* Messages are sent every 20s to respect the duty cycle on each channel */ | ||
#define PERIOD (20U) | ||
|
||
#define SENDER_PRIO (THREAD_PRIORITY_MAIN - 1) | ||
static kernel_pid_t sender_pid; | ||
static char sender_stack[THREAD_STACKSIZE_MAIN / 2]; | ||
|
||
semtech_loramac_t loramac; | ||
|
||
static const char *message = "This is RIOT!"; | ||
|
||
static uint8_t deveui[LORAMAC_DEVEUI_LEN]; | ||
static uint8_t appeui[LORAMAC_APPEUI_LEN]; | ||
static uint8_t appkey[LORAMAC_APPKEY_LEN]; | ||
|
||
static void rtc_cb(void *arg) | ||
{ | ||
(void) arg; | ||
msg_t msg; | ||
msg_send(&msg, sender_pid); | ||
} | ||
|
||
static void _prepare_next_alarm(void) | ||
{ | ||
struct tm time; | ||
rtc_get_time(&time); | ||
/* set initial alarm */ | ||
time.tm_sec += PERIOD; | ||
while (time.tm_sec > 60) { | ||
time.tm_min++; | ||
time.tm_sec -= 60; | ||
} | ||
while (time.tm_min > 60) { | ||
time.tm_hour++; | ||
time.tm_min -= 60; | ||
} | ||
while (time.tm_hour > 24) { | ||
time.tm_mday++; | ||
time.tm_hour -= 24; | ||
} | ||
rtc_set_alarm(&time, rtc_cb, NULL); | ||
} | ||
|
||
static void _send_message(void) | ||
{ | ||
printf("Sending: %s\n", message); | ||
/* The send call blocks until done */ | ||
semtech_loramac_send(&loramac, (uint8_t *)message, strlen(message)); | ||
/* Wait until the send cycle has completed */ | ||
semtech_loramac_recv(&loramac); | ||
} | ||
|
||
static void *sender(void *arg) | ||
{ | ||
(void)arg; | ||
|
||
msg_t msg; | ||
msg_t msg_queue[8]; | ||
msg_init_queue(msg_queue, 8); | ||
|
||
while (1) { | ||
msg_receive(&msg); | ||
|
||
/* Trigger the message send */ | ||
_send_message(); | ||
|
||
/* Schedule the next wake-up alarm */ | ||
_prepare_next_alarm(); | ||
|
||
#ifdef MODULE_PM_LAYERED | ||
/* enable low-power mode */ | ||
pm_set(PM_MODE); | ||
#endif | ||
} | ||
|
||
/* this should never be reached */ | ||
return NULL; | ||
} | ||
|
||
int main(void) | ||
{ | ||
puts("LoRaWAN Class A low-power application"); | ||
puts("====================================="); | ||
|
||
/* Convert identifiers and application key */ | ||
fmt_hex_bytes(deveui, DEVEUI); | ||
fmt_hex_bytes(appeui, APPEUI); | ||
fmt_hex_bytes(appkey, APPKEY); | ||
|
||
/* Initialize the loramac stack */ | ||
semtech_loramac_init(&loramac); | ||
semtech_loramac_set_deveui(&loramac, deveui); | ||
semtech_loramac_set_appeui(&loramac, appeui); | ||
semtech_loramac_set_appkey(&loramac, appkey); | ||
|
||
/* Use a fast datarate, e.g. BW125/SF7 in EU868 */ | ||
semtech_loramac_set_dr(&loramac, LORAMAC_DR_5); | ||
|
||
/* Send unconfirmed messages */ | ||
semtech_loramac_set_tx_mode(&loramac, LORAMAC_TX_UNCNF); | ||
|
||
/* Start the Over-The-Air Activation (OTAA) procedure to retrieve the | ||
* generated device address and to get the network and application session | ||
* keys. | ||
*/ | ||
puts("Starting join procedure"); | ||
if (semtech_loramac_join(&loramac, LORAMAC_JOIN_OTAA) != SEMTECH_LORAMAC_JOIN_SUCCEEDED) { | ||
puts("Join procedure failed"); | ||
return 1; | ||
} | ||
puts("Join procedure succeeded"); | ||
|
||
/* start the sender thread */ | ||
sender_pid = thread_create(sender_stack, sizeof(sender_stack), | ||
SENDER_PRIO, 0, sender, NULL, "sender"); | ||
|
||
/* trigger the first send */ | ||
msg_t msg; | ||
msg_send(&msg, sender_pid); | ||
return 0; | ||
} |