/** * @defgroup pkg_semtech-loramac Semtech LoRaMAC implementation * @ingroup pkg * @ingroup net * @brief Provides a RIOT adaption of Semtech LoRaMAC implementation * * # Introduction * * This package provides an API built on top of the * [Semtech LoRaMAC-node](https://github.com/Lora-net/LoRaMac-node) reference * implementation of a LoRa network. * * * # Importing this package in an application * * This package works with Semtech SX1261, SX1262, SX1268, SX1272 and SX1276 radio * devices. Thus, in order to use it properly, the application `Makefile` must * import the corresponding device driver: * ```mk * USEMODULE += sx1261 # for a SX1261 radio device * USEMODULE += sx1262 # for a SX1262 radio device * USEMODULE += sx1268 # for a SX1268 radio device * USEMODULE += sx1272 # for a SX1272 radio device * USEMODULE += sx1276 # for a SX1276 radio device * ``` * * In order to use this package in an application, add the following in * the application `Makefile`: * ```mk * USEPKG += semtech-loramac * ``` * * Since the LoRa radio depends on regional parameters regarding the access * to the physical support, the region where the device is used needs to be * set at compile time. Example for EU868: * ```mk * LORA_REGION = EU868 * ``` * * # Using the package API * * The package provides a simple API for initializing the MAC, setting/getting * parameters, joining a network and sending/receiving packets to/from a LoRa * Network. * * In your `main.c`, some header files must be first included: * ```c * #include "net/loramac.h" /* core loramac definitions */ * #include "semtech_loramac.h" /* package API */ * ``` * * Then define global variables: * ```c * semtech_loramac_t loramac; /* The loramac stack device descriptor */ * /* define the required keys for OTAA, e.g over-the-air activation (the * null arrays need to be updated with valid LoRa values) */ * static const uint8_t deveui[LORAMAC_DEVEUI_LEN] = { 0x00, 0x00, 0x00, 0x00, \ * 0x00, 0x00, 0x00, 0x00 }; * static const uint8_t appeui[LORAMAC_APPEUI_LEN] = { 0x00, 0x00, 0x00, 0x00, \ * 0x00, 0x00, 0x00, 0x00 }; * static const uint8_t appkey[LORAMAC_APPKEY_LEN] = { 0x00, 0x00, 0x00, 0x00, \ * 0x00, 0x00, 0x00, 0x00, \ * 0x00, 0x00, 0x00, 0x00, \ * 0x00, 0x00, 0x00, 0x00 }; * ``` * * Now in the `main` function: * 1. initialize the LoRaMAC MAC layer * 2. set the LoRa keys * 3. join the network * 4. send some data to the network * * ```c * int main(void) * { * /* 1. initialize the LoRaMAC MAC layer */ * semtech_loramac_init(&loramac); * * /* 2. set the keys identifying the device */ * semtech_loramac_set_deveui(&loramac, deveui); * semtech_loramac_set_appeui(&loramac, appeui); * semtech_loramac_set_appkey(&loramac, appkey); * * /* 3. join the network */ * if (semtech_loramac_join(&loramac, LORAMAC_JOIN_OTAA) != SEMTECH_LORAMAC_JOIN_SUCCEEDED) { * puts("Join procedure failed"); * return 1; * } * puts("Join procedure succeeded"); * * /* 4. send some data */ * char *message = "This is RIOT"; * if (semtech_loramac_send(&loramac, * (uint8_t *)message, strlen(message)) != SEMTECH_LORAMAC_TX_DONE) { printf("Cannot send message '%s'\n", message); * return 1; * } * * } * ``` * * To receive downlink messages, enable the `semtech_loramac_rx` and use a * dedicated receiving thread. * - In the application Makefile, add * ```mk * USEMODULE += semtech_loramac_rx * ``` * - At the beginning of the application source file, add the necessary * includes and declare the message queue and stack arrays: * ```c * #include "thread.h" * * #define RECV_MSG_QUEUE (4U) * static msg_t _recv_queue[RECV_MSG_QUEUE]; * * static char _recv_stack[THREAD_STACKSIZE_DEFAULT]; * ``` * - Implement the thread: it initializes its message queue and then * simply calls the blocking `semtech_loramac_recv` function in a loop: * ```c * static void *_recv(void *arg) * { * msg_init_queue(_recv_queue, RECV_MSG_QUEUE); * * (void)arg; * while (1) { * /* blocks until some data is received */ * semtech_loramac_recv(&loramac); * loramac.rx_data.payload[loramac.rx_data.payload_len] = 0; * printf("Data received: %s, port: %d\n", * (char *)loramac.rx_data.payload, loramac.rx_data.port); * } * return NULL; * } * ``` * - Finally, this thread can be started after the join procedure * succeeds: * ```c * thread_create(_recv_stack, sizeof(_recv_stack), * THREAD_PRIORITY_MAIN - 1, 0, _recv, NULL, "recv thread"); * ``` * * # Persistence * * If the board CPU provides an internal EEPROM, this package provides a * mechanism for storing EUIs, keys and some MAC parameters (frame counter, * join status). * After a successful join procedure, use `semtech_loramac_save` function to * persist this information and it will be loaded automatically at the next * reboot. * If the device is already joined to a network, to avoid another OTAA join * procedure use `semtech_loramac_is_mac_joined` function to check the join * status of the device. * * This mechanism is especially useful when using deep sleep power modes that * don't preserve RAM. * * # Low power considerations * * The internal implementation of the required LoRaWAN timings (delay before * opening RX windows, duty-cycle delays) automatically achieves the lowest * possible power consumption while remaining usable when RIOT's low power modes * are not blocked. All timings are managed by the @ref sys_ztimer * running on the low-level @ref drivers_periph_rtt peripheral which * allows for: * - going to a deep-sleep mode with RAM retention (no reboot) between TX and * RX1 and between RX1 and RX2 windows, and as a result reduces the power * consumption * - using deep-sleep mode with RAM retention and have the duty-cycle * restriction still usable between each active cycle (wake-up, measure, send, * receive, sleep). * As a result, this package can only be used on boards that provide the * `periph_rtt` feature. * * @warning It is not possible to directly call the original LoRaMAC-node API * using this package. This package should only be considered as a * wrapper around the original LoRaMAC-node API and only the API * provided by this package should be used. * * # License * * The library is using the BSD 3-clause license. * * @see https://github.com/Lora-net/LoRaMac-node */