Commit b85232d0 authored by Guillaume Gonnet's avatar Guillaume Gonnet
Browse files

Continue app implementation.

parent cda1ddf6
# Ignore "bin" directory.
/bin/
\ No newline at end of file
/bin/
# Ignore editor config.
.vscode/
\ No newline at end of file
......@@ -18,9 +18,16 @@ export LORAMAC_INC := \
-I$(LORAMAC_DIR)/mac
# Directory containing LoRaRIOT.
export LORAMAC_DIR := LoRaRIO$(CURDIR)/lorariot
# Include folders for LoRaRIOT.
export LORAMAC_INC := -I$(LORAMAC_DIR)
# Add source directories.
DIRS += app
DIRS += loramac
# DIRS += $(CURDIR)/lorariot
DIRS += lorariot
include $(RIOTBASE)/Makefile.base
/*
Manage device activation via OTAA or ABP.
Copyright (C) 2019, ENSIMAG students
This project is under the MIT license
*/
\ No newline at end of file
......@@ -10,7 +10,10 @@ This project is under the MIT license
#include <stdio.h>
// Entry point of the whole application.
int main(void)
{
lorariot_init();
puts("Hello !\n");
}
......@@ -31,3 +31,18 @@ static pvd_otta_t orange_cmd_otta = {
};
provider_t pvd_orange_cmd = PVD_IMPLEM_OTAA(orange_cmd_otta);
// The current provider.
static provider_t *current_pvd;
// Change the current LoRaWAN provider.
void change_provider(provider_t *pvd)
{
if (pvd == current_pvd) return;
if (current_pvd) current_pvd->disable();
pvd->enable(pvd);
current_pvd = pvd;
}
......@@ -15,8 +15,9 @@ typedef (*pvd_join_t)(struct provider_t *);
typedef struct provider_t {
void *data; // Provider specific data.
pvd_configure_t configure;
pvd_join_t join;
pvd_configure_t enable;
pvd_configure_t disable;
pvd_join_t reset;
} provider_t;
......@@ -43,3 +44,15 @@ extern provider_t pvd_orange_cmd;
// TTN provider.
extern provider_t pvd_ttn_bm;
// Change the current LoRaWAN provider.
void change_provider(provider_t *pvd);
/**
* @brief Send some data using the specified provider.
* @param pvd the provider to use.
* @param mcps MCPS information (data, DR, ...).
*/
void pvd_send(provider_t *pvd, lorariot_mcps_t *mcps);
/*
Send some data using a provider.
Copyright (C) 2019, ENSIMAG students
This project is under the MIT license
*/
#include "providers.h"
// Current loaded provider.
static provider_t *current_pvd;
// Mutex on sending.
static mutex_t send_mutex = MUTEX_INIT;
// Change the current provider.
static void change_provider(provider_t *pvd)
{
// TODO.
}
/**
* @brief Send some data using the specified provider.
* @param pvd the provider to use.
* @param mcps MCPS information (data, DR, ...).
*/
void pvd_send(provider_t *pvd, lorariot_mcps_t *mcps)
{
// Wait for the current LoRaMAC-node operation to be completed.
mutex_lock(&send_mutex);
// The wanted provider is not the current provider, we must switch to this
// provider.
if (current_pvd != pvd)
change_provider(pvd);
// Send the MCPS message.
lorariot_send(mcps);
// Wait for "confirm" (for UNCONFIRMED messages) or "indication" (for
// CONFIRMED messages) event given by LoRaMAC-node.
lorariot_waitsend();
// Unlock one other waiting thread.
mutex_unlock(&send_mutex);
}
......@@ -9,6 +9,6 @@ This project is under the MIT license
// Orange provider for benchmark.
#define ORANGE_BM_DEVEUI
#define ORANGE_BM_APPEUI
#define ORANGE_BM_APPKEY
#define ORANGE_BM_DEVEUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define ORANGE_BM_APPEUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define ORANGE_BM_APPKEY { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
/*
* Copyright (C) 2017 Inria
* 2017 Inria Chile
*
* 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 pkg_semtech-loramac
*
* @file
* @brief Implementation of public API for Semtech LoRaMAC
*
* This implementation is an adaption of the applications provided on the
* Semtech Lora-net repository.
*
* The LoRaMAC stack and the SX127x driver run in their own thread and simple
* IPC messages are exchanged to control the MAC.
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
* @author Jose Alamos <jose.alamos@inria.cl>
* @}
*/
#include <string.h>
#include "msg.h"
#include "mutex.h"
#include "net/netdev.h"
#include "net/netdev/lora.h"
#include "net/loramac.h"
#include "sx127x.h"
#include "sx127x_params.h"
#include "sx127x_netdev.h"
#include "semtech_loramac.h"
#include "LoRaMac.h"
#include "region/Region.h"
#ifdef MODULE_PERIPH_EEPROM
#include "periph/eeprom.h"
#endif
#define ENABLE_DEBUG (0)
#include "debug.h"
#define SEMTECH_LORAMAC_MSG_QUEUE (16U)
#define SEMTECH_LORAMAC_LORAMAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
static msg_t _semtech_loramac_msg_queue[SEMTECH_LORAMAC_MSG_QUEUE];
static char _semtech_loramac_stack[SEMTECH_LORAMAC_LORAMAC_STACKSIZE];
kernel_pid_t semtech_loramac_pid;
Controller for LoRaWAN adapter for RIOT.
This file is based on "semtech-loramac" module from RIOT OS, under the
LGPLv2.1 license.
*/
#include "controller.h"
// Message queue of event loop.
#define LORARIOT_MSG_QUEUE (16U)
static msg_t _lorariot_msg_queue[LORARIOT_MSG_QUEUE];
// LoRaRIOT event loop.
#define LORARIOT_LORAMAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
static char _lorariot_stack[LORARIOT_LORAMAC_STACKSIZE];
//
sx127x_t sx127x;
RadioEvents_t semtech_loramac_radio_events;
LoRaMacPrimitives_t semtech_loramac_primitives;
LoRaMacCallback_t semtech_loramac_callbacks;
typedef struct {
uint8_t *payload;
uint8_t len;
} loramac_send_params_t;
// Unique instance of `lorariot_ctrl_t`.
lorariot_ctrl_t lorariot;
typedef void (*semtech_loramac_func_t)(semtech_loramac_t *, void *);
/**
* @brief Struct containing a semtech loramac function call
*
* This function is called inside the semtech loramac thread context.
*/
typedef struct {
semtech_loramac_func_t func; /**< the function to call. */
void *arg; /**< argument of the function **/
} semtech_loramac_call_t;
// Callback functions.
extern void lorariot_mcps_confirm(McpsConfirm_t *confirm);
extern void lorariot_mlme_confirm(MlmeConfirm_t *confirm);
extern void lorariot_mcps_indication(McpsIndication_t *indication);
extern void lorariot_mlme_indication(MlmeIndication_t *indication);
void _init_loramac(semtech_loramac_t *mac, LoRaMacPrimitives_t * primitives,
LoRaMacCallback_t *callbacks)
// Main event loop for LoRaRIOT.
void *lorariot_event_loop(void *arg)
{
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] initializing LoRaMAC-node\n");
primitives->MacMcpsConfirm = mcps_confirm;
primitives->MacMcpsIndication = mcps_indication;
primitives->MacMlmeConfirm = mlme_confirm;
primitives->MacMlmeIndication = mlme_indication;
LoRaMacInitialization(&semtech_loramac_radio_events, primitives, callbacks,
LORAMAC_ACTIVE_REGION);
mutex_unlock(&mac->lock);
msg_init_queue(msg_queue, LORARIOT_MSG_QUEUE);
while (true) {
msg_t msg;
msg_receive(&msg);
switch (msg.type) {
case MSG_TYPE_ISR: {
netdev_t *dev = msg.content.ptr;
dev->driver->isr(dev);
} break;
case MSG_TYPE_RX_TIMEOUT: {
lorariot_radio_events.RxTimeout();
} break;
case MSG_TYPE_TX_TIMEOUT: {
lorariot_radio_events.TxTimeout();
} break;
case MSG_TYPE_MAC_TIMEOUT: {
void (*callback)(void) = msg.content.ptr;
callback();
} break;
case MSG_TYPE_LORAMAC_CMD: {
msg_t msg_resp;
lorariot_call_t *call = msg.content.ptr;
call->func(mac, call->arg);
msg_reply(&msg, &msg_resp);
} break;
case MSG_TYPE_LORAMAC_JOIN: {
msg_t msg_ret;
msg_ret.content.value = msg.content.value;
msg_send(&msg_ret, mac->caller_pid);
} break;
case MSG_TYPE_LORAMAC_LINK_CHECK: {
MlmeConfirm_t *confirm = (MlmeConfirm_t *)msg.content.ptr;
mac->link_chk.demod_margin = confirm->DemodMargin;
mac->link_chk.nb_gateways = confirm->NbGateways;
mac->link_chk.available = true;
} break;
case MSG_TYPE_LORAMAC_TX_STATUS: {
DEBUG("[lorariot] received TX status\n");
msg_t msg_ret;
msg_ret.type = msg.type;
msg_ret.content.value = msg.content.value;
msg_send(&msg_ret, mac->caller_pid);
} break;
case MSG_TYPE_LORAMAC_RX: {
// TODO: call receive thread.
} break;
default:
DEBUG("[semtech-loramac] Unexpected msg type '%04x'\n", msg.type);
}
}
}
static void _semtech_loramac_event_cb(netdev_t *dev, netdev_event_t event)
// Call a function in LoRaRIOT event loop.
void lorariot_call(lorariot_func_t func, void *arg)
{
netdev_lora_rx_info_t packet_info;
msg_t msg;
msg.content.ptr = dev;
switch (event) {
case NETDEV_EVENT_ISR:
msg.type = MSG_TYPE_ISR;
if (msg_send(&msg, semtech_loramac_pid) <= 0) {
DEBUG("[semtech-loramac] possibly lost interrupt.\n");
}
break;
case NETDEV_EVENT_TX_COMPLETE:
sx127x_set_sleep((sx127x_t *)dev);
semtech_loramac_radio_events.TxDone();
DEBUG("[semtech-loramac] Transmission completed\n");
break;
case NETDEV_EVENT_TX_TIMEOUT:
msg.type = MSG_TYPE_TX_TIMEOUT;
if (msg_send(&msg, semtech_loramac_pid) <= 0) {
DEBUG("[semtech-loramac] TX timeout, possibly lost interrupt.\n");
}
break;
case NETDEV_EVENT_RX_COMPLETE: {
size_t len;
uint8_t radio_payload[SX127X_RX_BUFFER_SIZE];
len = dev->driver->recv(dev, NULL, 0, 0);
dev->driver->recv(dev, radio_payload, len, &packet_info);
semtech_loramac_radio_events.RxDone(radio_payload,
len, packet_info.rssi,
packet_info.snr);
break;
}
case NETDEV_EVENT_RX_TIMEOUT:
msg.type = MSG_TYPE_RX_TIMEOUT;
if (msg_send(&msg, semtech_loramac_pid) <= 0) {
DEBUG("[semtech-loramac] RX timeout, possibly lost interrupt.\n");
}
break;
case NETDEV_EVENT_CRC_ERROR:
DEBUG("[semtech-loramac] RX CRC error\n");
semtech_loramac_radio_events.RxError();
break;
case NETDEV_EVENT_FHSS_CHANGE_CHANNEL:
DEBUG("[semtech-loramac] FHSS channel change\n");
if (semtech_loramac_radio_events.FhssChangeChannel) {
semtech_loramac_radio_events.FhssChangeChannel((
(sx127x_t *)dev)->_internal.last_channel);
}
break;
case NETDEV_EVENT_CAD_DONE:
DEBUG("[semtech-loramac] test: CAD done\n");
if (semtech_loramac_radio_events.CadDone) {
semtech_loramac_radio_events.CadDone((
(sx127x_t *)dev)->_internal.is_last_cad_success);
}
break;
default:
DEBUG("[semtech-loramac] unexpected netdev event received: %d\n",
event);
}
msg_t msg, msg_resp;
lorariot_call_t call = { func, arg };
msg.type = MSG_TYPE_LORAMAC_CMD;
msg.content.ptr = &call;
msg_send_receive(&msg, &msg_resp, lorariot_pid);
}
int semtech_loramac_init(semtech_loramac_t *mac)
// Initialize LoRaRIOT and LoRaMAC-node.
int lorariot_init()
{
DEBUG("[lorariot] initializing LoRaRIOT and LoRaMAC-node\n");
// Initialize Radio module.
sx127x_setup(&sx127x, &sx127x_params[0]);
sx127x.netdev.driver = &sx127x_driver;
sx127x.netdev.event_callback = _semtech_loramac_event_cb;
// Create event loop thread.
lorariot_pid = thread_create(_lorariot_stack, sizeof(_lorariot_stack),
THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST,
lorariot_event_loop, NULL, "lorariot-evloop");
if (lorariot_pid <= KERNEL_PID_UNDEF) {
DEBUG("[lorariot] creation of event loop thread failed\n");
return -1;
}
// Initialize LoRaMAC-node module.
primitives->MacMcpsConfirm = mcps_confirm;
primitives->MacMcpsIndication = mcps_indication;
primitives->MacMlmeConfirm = mlme_confirm;
primitives->MacMlmeIndication = mlme_indication;
LoRaMacInitialization(&lorariot_radio_events, primitives, callbacks,
REGION_IMAG);
return 0;
}
/*
Manage message sending.
This file is based on "semtech-loramac" module from RIOT OS, under the
LGPLv2.1 license.
*/
#include "lorariot.h"
#include <msg.h>
// All message types for LoRaRIOT event loop.
#define LORARIOT_TYPE_ISR (0x3456) // radio device ISR */
#define LORARIOT_TYPE_RX_TIMEOUT (0x3457) /**< radio driver RX timeout */
#define LORARIOT_TYPE_TX_TIMEOUT (0x3458) /**< radio driver TX timeout */
#define LORARIOT_TYPE_MAC_TIMEOUT (0x3459) /**< MAC timers timeout */
#define LORARIOT_TYPE_CALL (0x3460) /**< Command sent to the MAC */
#define LORARIOT_TYPE_LORAMAC_JOIN (0x3461) /**< MAC join event */
#define LORARIOT_TYPE_LORAMAC_TX_STATUS (0x3462) /**< MAC TX status */
#define LORARIOT_TYPE_LORAMAC_RX (0x3463) /**< Some data received */
#define LORARIOT_TYPE_LORAMAC_LINK_CHECK (0x3464) /**< Link check info received */
// PID of LoRaRIOT event loop.
extern kernel_pid_t lorariot_pid;
// Store data of LoRaRIOT controller.
typedef struct {
uint8_t caller_pid;
} lorariot_ctrl_t;
// Unique instance of `lorariot_ctrl_t`.
extern lorariot_ctrl_t lorariot;
// LoRaRIOT debug functions.
#ifdef NDEBUG
void lorariot_debug_status(const char *name, LoRaMacStatus_t status);
void lorariot_debug_status_ev(const char *name, LoRaMacEventInfoStatus_t status);
void lorariot_debug_mcps(Mcps_t code);
#else
#define lorariot_debug_status(id, status) ((void)0)
#define lorariot_debug_mcps(code) ((void)0)
#endif
/*
Print LoRaRIOT debug messages.
This file is based on "semtech-loramac" module from RIOT OS, under the
LGPLv2.1 license.
*/
#include "controller.h"
#ifndef NDEBUG
// Debug a LoRAMAC status code.
void lorariot_debug_status(const char *name, LoRaMacStatus_t status)
{
switch (status) {
case LORAMAC_STATUS_OK:
printf("[lorariot] %s: OK\n", name);
break;
case LORAMAC_STATUS_PARAMETER_INVALID:
printf("[lorariot] %s: invalid parameter\n", name);
break;
case LORAMAC_STATUS_BUSY:
printf("[lorariot] %s: busy\n", name);
break;
case LORAMAC_STATUS_DUTYCYCLE_RESTRICTED:
printf("[lorariot] %s: dutycycle restricted\n", name);
break;
default:
printf("[lorariot] %s: unknown status %d\n", name, status);
break;
}
}
// Debug a LoRAMAC status event code.
void lorariot_debug_status_ev(const char *name, LoRaMacEventInfoStatus_t status)
{
switch (status) {
case LORAMAC_EVENT_INFO_STATUS_OK:
printf("[lorariot] %s: OK\n", name);
break;
case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT:
case LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT:
case LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT:
printf("[lorariot] %s: TX / RX timeout\n", name);
break;
case LORAMAC_EVENT_INFO_STATUS_RX1_ERROR:
case LORAMAC_EVENT_INFO_STATUS_RX2_ERROR:
printf("[lorariot] %s: RX error\n", name);
break;
case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL:
printf("[lorariot] %s: join failed\n", name);
break;
case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL:
printf("[lorariot] %s: mic error\n", name);
break;
default:
printf("[lorariot] %s: unknown status %d\n", name, status);
break;
}
}
// Debug a LoRAMAC MCPS code.
void lorariot_debug_mcps(Mcps_t code)
{
switch (code) {
case MCPS_UNCONFIRMED:
printf("[lorariot] MCPS indication Unconfirmed\n");
break;
case MCPS_CONFIRMED:
printf("[lorariot] MCPS indication Confirmed\n");
break;
case MCPS_PROPRIETARY:
printf("[lorariot] MCPS indication Proprietary\n");
break;
case MCPS_MULTICAST:
printf("[lorariot] MCPS indication Multicast\n");
break;
}
}
#endif // !NDEBUG
......@@ -8,62 +8,97 @@ LGPLv2.1 license.
*/
/* MCPS-Indication event function */
static void mcps_indication(McpsIndication_t *indication)
// Handle a NetDev event.
void lorariot_event_cb(netdev_t *dev, netdev_event_t event)
{
DEBUG("[semtech-loramac] MCPS indication event\n");
if (indication->Status != LORAMAC_EVENT_INFO_STATUS_OK) {
DEBUG("[semtech-loramac] MCPS indication no OK\n");
return;
}
netdev_lora_rx_info_t packet_info;
msg_t msg;
msg.content.ptr = dev;
switch (event) {