LoRaWANStack is made independent of MAC sublayers

- Only internal changes, no API has been broke.
- Tested by manually running Green tea tests
pull/6411/head
Antti Kauppila 2018-03-16 13:12:50 +02:00
parent b63c98e103
commit 6b54478af4
9 changed files with 517 additions and 1708 deletions

View File

@ -45,10 +45,6 @@ using namespace mbed;
using namespace events;
#if defined(LORAWAN_COMPLIANCE_TEST)
/**
*
* User application data buffer size if compliance test is used
*/
#if (MBED_CONF_LORA_PHY == 0 || MBED_CONF_LORA_PHY == 4 || MBED_CONF_LORA_PHY == 6 || MBED_CONF_LORA_PHY == 7)
#define LORAWAN_COMPLIANCE_TEST_DATA_SIZE 16
#elif (MBED_CONF_LORA_PHY == 1 || MBED_CONF_LORA_PHY == 2 || MBED_CONF_LORA_PHY == 8 || MBED_CONF_LORA_PHY == 9)
@ -134,39 +130,33 @@ lorawan_status_t LoRaWANStack::connect()
lorawan_connect_t connection_params;
if (MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION) {
static uint8_t dev_eui[] = MBED_CONF_LORA_DEVICE_EUI;
static uint8_t app_eui[] = MBED_CONF_LORA_APPLICATION_EUI;
static uint8_t app_key[] = MBED_CONF_LORA_APPLICATION_KEY;
/**
*
* OTAA join
*/
connection_params.connect_type = LORAWAN_CONNECTION_OTAA;
connection_params.connection_u.otaa.app_eui = app_eui;
connection_params.connection_u.otaa.dev_eui = dev_eui;
connection_params.connection_u.otaa.app_key = app_key;
connection_params.connection_u.otaa.nb_trials = MBED_CONF_LORA_NB_TRIALS;
//TODO: LoRaWANStack don't need to know these values, move to LoRaMac (or below)
#if (1 == MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION)
static uint8_t dev_eui[] = MBED_CONF_LORA_DEVICE_EUI;
static uint8_t app_eui[] = MBED_CONF_LORA_APPLICATION_EUI;
static uint8_t app_key[] = MBED_CONF_LORA_APPLICATION_KEY;
return join_request_by_otaa(connection_params);
} else {
static uint8_t nwk_skey[] = MBED_CONF_LORA_NWKSKEY;
static uint8_t app_skey[] = MBED_CONF_LORA_APPSKEY;
static uint32_t dev_addr = MBED_CONF_LORA_DEVICE_ADDRESS;
static uint32_t nwk_id = (MBED_CONF_LORA_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK);
connection_params.connect_type = LORAWAN_CONNECTION_OTAA;
connection_params.connection_u.otaa.app_eui = app_eui;
connection_params.connection_u.otaa.dev_eui = dev_eui;
connection_params.connection_u.otaa.app_key = app_key;
connection_params.connection_u.otaa.nb_trials = MBED_CONF_LORA_NB_TRIALS;
/**
*
* ABP connection
*/
connection_params.connect_type = LORAWAN_CONNECTION_ABP;
connection_params.connection_u.abp.nwk_id = nwk_id;
connection_params.connection_u.abp.dev_addr = dev_addr;
connection_params.connection_u.abp.nwk_skey = nwk_skey;
connection_params.connection_u.abp.app_skey = app_skey;
return join_request_by_otaa(connection_params);
#else
static uint8_t nwk_skey[] = MBED_CONF_LORA_NWKSKEY;
static uint8_t app_skey[] = MBED_CONF_LORA_APPSKEY;
static uint32_t dev_addr = MBED_CONF_LORA_DEVICE_ADDRESS;
static uint32_t nwk_id = (MBED_CONF_LORA_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK);
return activation_by_personalization(connection_params);
}
connection_params.connect_type = LORAWAN_CONNECTION_ABP;
connection_params.connection_u.abp.nwk_id = nwk_id;
connection_params.connection_u.abp.dev_addr = dev_addr;
connection_params.connection_u.abp.nwk_skey = nwk_skey;
connection_params.connection_u.abp.app_skey = app_skey;
return activation_by_personalization(connection_params);
#endif
}
lorawan_status_t LoRaWANStack::connect(const lorawan_connect_t &connect)
@ -315,14 +305,7 @@ lorawan_status_t LoRaWANStack::enable_adaptive_datarate(bool adr_enabled)
return LORAWAN_STATUS_NOT_INITIALIZED;
}
//return _loramac.enable_adaptive_datarate(adr_enabled);
loramac_mib_req_confirm_t adr_mib_params;
adr_mib_params.type = MIB_ADR;
adr_mib_params.param.is_adr_enable = adr_enabled;
return mib_set_request(&adr_mib_params);
return _loramac.enable_adaptive_datarate(adr_enabled);
}
lorawan_status_t LoRaWANStack::set_channel_data_rate(uint8_t data_rate)
@ -333,23 +316,9 @@ lorawan_status_t LoRaWANStack::set_channel_data_rate(uint8_t data_rate)
return LORAWAN_STATUS_NOT_INITIALIZED;
}
loramac_mib_req_confirm_t mib_params;
mib_params.type = MIB_ADR;
if (mib_get_request(&mib_params) != LORAWAN_STATUS_OK) {
tr_error("Cannot set data rate. Please turn off ADR first.");
return LORAWAN_STATUS_PARAMETER_INVALID;
}
mib_params.type = MIB_CHANNELS_DATARATE;
mib_params.param.channel_data_rate = data_rate;
return mib_set_request(&mib_params);
return _loramac.set_channel_data_rate(data_rate);
}
/**
*
* Join OTAA
*/
lorawan_status_t LoRaWANStack::join_request_by_otaa(const lorawan_connect_t &params)
{
if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state)
@ -375,10 +344,6 @@ lorawan_status_t LoRaWANStack::join_request_by_otaa(const lorawan_connect_t &par
return lora_state_machine(DEVICE_STATE_JOINING);
}
/**
*
* Connect ABP
*/
lorawan_status_t LoRaWANStack::activation_by_personalization(const lorawan_connect_t &params)
{
if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
@ -435,16 +400,10 @@ int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
}
#endif
//TODO: Stack MUST know joining status!!!!
loramac_mib_req_confirm_t mib_req;
lorawan_status_t status;
mib_req.type = MIB_NETWORK_JOINED;
status = mib_get_request(&mib_req);
if (status == LORAWAN_STATUS_OK) {
if (mib_req.param.is_nwk_joined == false) {
return LORAWAN_STATUS_NO_NETWORK_JOINED;
}
if (_loramac.nwk_joined() == false) {
return LORAWAN_STATUS_NO_NETWORK_JOINED;
}
status = set_application_port(port);
@ -454,8 +413,8 @@ int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
return status;
}
if (flags == 0
|| (flags & MSG_FLAG_MASK) == (MSG_CONFIRMED_FLAG|MSG_UNCONFIRMED_FLAG)) {
if (flags == 0 ||
(flags & MSG_FLAG_MASK) == (MSG_CONFIRMED_FLAG|MSG_UNCONFIRMED_FLAG)) {
tr_error("CONFIRMED and UNCONFIRMED are mutually exclusive for send()");
return LORAWAN_STATUS_PARAMETER_INVALID;
}
@ -552,19 +511,8 @@ int16_t LoRaWANStack::handle_rx(const uint8_t port, uint8_t* data,
return base_size;
}
/** MLME-Confirm event function
*
* \param mlme_confirm Pointer to the confirm structure,
* containing confirm attributes.
*/
void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm)
{
if (NULL == mlme_confirm) {
tr_error("mlme_confirm: struct [in] is null!");
MBED_ASSERT(0);
return;
}
switch (mlme_confirm->req_type) {
case MLME_JOIN:
if (mlme_confirm->status == LORAMAC_EVENT_INFO_STATUS_OK) {
@ -613,37 +561,13 @@ void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm)
}
}
lorawan_status_t LoRaWANStack::mcps_request_handler(loramac_mcps_req_t *mcps_request)
{
if (mcps_request == NULL) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
return _loramac.mcps_request(mcps_request);
}
/** MCPS-Confirm event function
*
* \param mcps_confirm Pointer to the confirm structure,
* containing confirm attributes.
*/
void LoRaWANStack::mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm)
{
if (mcps_confirm == NULL) {
tr_error("mcps_confirm: struct [in] is null!");
MBED_ASSERT(0);
return;
}
if (mcps_confirm->status != LORAMAC_EVENT_INFO_STATUS_OK) {
// Couldn't schedule packet, ack not recieved in CONFIRMED case
// or some other error happened. Discard buffer, unset the tx-ongoing
// flag and let the application know
_loramac.reset_ongoing_tx();
tr_error("mcps_confirm_handler: Error code = %d", mcps_confirm->status);
// If sending timed out, we have a special event for that
if (mcps_confirm->status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT) {
if (_callbacks.events) {
const int ret = _queue->call(_callbacks.events, TX_TIMEOUT);
@ -651,11 +575,10 @@ void LoRaWANStack::mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm)
(void)ret;
}
return;
} if (mcps_confirm->status == LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT) {
} else if (mcps_confirm->status == LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT) {
tr_debug("Did not receive Ack");
}
// Otherwise send a general TX_ERROR event
if (_callbacks.events) {
const int ret = _queue->call(_callbacks.events, TX_ERROR);
MBED_ASSERT(ret != 0);
@ -664,20 +587,11 @@ void LoRaWANStack::mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm)
return;
}
// If No errors encountered, let's proceed with the status.
// CONFIRMED needs special handling because of acks
if (mcps_confirm->req_type == MCPS_CONFIRMED) {
// In confirmed case, we need to check if we have received the Ack or not.
// This is actually just being paranoid about ack because LoRaMac.cpp doesn't
// call this callback until an ack is received.
if (mcps_confirm->ack_received) {
if (mcps_confirm->req_type == MCPS_CONFIRMED &&
mcps_confirm->ack_received) {
tr_debug("Ack received.");
}
}
// This part is common to both CONFIRMED and UNCONFIRMED.
// Tell the application about successful transmission and store
// data rate plus frame counter.
_lw_session.uplink_counter = mcps_confirm->ul_frame_counter;
_loramac.set_tx_ongoing(false);
if (_callbacks.events) {
@ -687,18 +601,8 @@ void LoRaWANStack::mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm)
}
}
/** MCPS-Indication event function
*
* \param mcps_indication Pointer to the indication structure,
* containing indication attributes.
*/
void LoRaWANStack::mcps_indication_handler(loramac_mcps_indication_t *mcps_indication)
{
if (mcps_indication == NULL) {
tr_error("mcps_indication: struct [in] is null.");
return;
}
if (mcps_indication->status != LORAMAC_EVENT_INFO_STATUS_OK) {
if (_callbacks.events) {
const int ret = _queue->call(_callbacks.events, RX_ERROR);
@ -721,6 +625,7 @@ void LoRaWANStack::mcps_indication_handler(loramac_mcps_indication_t *mcps_indic
break;
}
//TODO:
// Check Multicast
// Check Port
// Check Datarate
@ -741,80 +646,63 @@ void LoRaWANStack::mcps_indication_handler(loramac_mcps_indication_t *mcps_indic
if (mcps_indication->is_data_recvd == true) {
switch (mcps_indication->port) {
case 224:
case 224: {
#if defined(LORAWAN_COMPLIANCE_TEST)
tr_debug("Compliance test command received.");
compliance_test_handler(mcps_indication);
tr_debug("Compliance test command received.");
compliance_test_handler(mcps_indication);
#else
tr_debug("Compliance test disabled.");
tr_info("Compliance test disabled.");
#endif
break;
default:
if (is_port_valid(mcps_indication->port) == true ||
mcps_indication->type == MCPS_PROPRIETARY) {
// Valid message arrived.
_rx_msg.type = LORAMAC_RX_MCPS_INDICATION;
_rx_msg.msg.mcps_indication.buffer_size = mcps_indication->buffer_size;
_rx_msg.msg.mcps_indication.port = mcps_indication->port;
// no copy, just set the pointer for the user
_rx_msg.msg.mcps_indication.buffer = mcps_indication->buffer;
// Notify application about received frame..
tr_debug("Received %d bytes", _rx_msg.msg.mcps_indication.buffer_size);
_rx_msg.receive_ready = true;
if (_callbacks.events) {
const int ret = _queue->call(_callbacks.events, RX_DONE);
MBED_ASSERT(ret != 0);
(void)ret;
}
loramac_mib_req_confirm_t mib_req;
mib_req.type = MIB_DEVICE_CLASS;
mib_get_request(&mib_req);
// If fPending bit is set we try to generate an empty packet
// with CONFIRMED flag set. We always set a CONFIRMED flag so
// that we could retry a certain number of times if the uplink
// failed for some reason
if (mcps_indication->fpending_status && mib_req.param.dev_class != CLASS_C) {
handle_tx(mcps_indication->port, NULL, 0, MSG_CONFIRMED_FLAG, true);
}
// Class C and node received a confirmed message so we need to
// send an empty packet to acknowledge the message.
// This scenario is unspecified by LoRaWAN 1.0.2 specification,
// but version 1.1.0 says that network SHALL not send any new
// confirmed messages until ack has been sent
if (mib_req.param.dev_class == CLASS_C && mcps_indication->type == MCPS_CONFIRMED) {
handle_tx(mcps_indication->port, NULL, 0, MSG_CONFIRMED_FLAG, true);
}
} else {
// Invalid port, ports 0, 224 and 225-255 are reserved.
break;
}
default: {
if (is_port_valid(mcps_indication->port) == true ||
mcps_indication->type == MCPS_PROPRIETARY) {
// Valid message arrived.
_rx_msg.type = LORAMAC_RX_MCPS_INDICATION;
_rx_msg.msg.mcps_indication.buffer_size = mcps_indication->buffer_size;
_rx_msg.msg.mcps_indication.port = mcps_indication->port;
_rx_msg.msg.mcps_indication.buffer = mcps_indication->buffer;
// Notify application about received frame..
tr_debug("Received %d bytes", _rx_msg.msg.mcps_indication.buffer_size);
_rx_msg.receive_ready = true;
if (_callbacks.events) {
const int ret = _queue->call(_callbacks.events, RX_DONE);
MBED_ASSERT(ret != 0);
(void)ret;
}
//TODO: below if clauses can be combined,
// because those are calling same function with same parameters
// If fPending bit is set we try to generate an empty packet
// with CONFIRMED flag set. We always set a CONFIRMED flag so
// that we could retry a certain number of times if the uplink
// failed for some reason
if (_loramac.get_device_class() != CLASS_C && mcps_indication->fpending_status) {
handle_tx(mcps_indication->port, NULL, 0, MSG_CONFIRMED_FLAG, true);
}
// Class C and node received a confirmed message so we need to
// send an empty packet to acknowledge the message.
// This scenario is unspecified by LoRaWAN 1.0.2 specification,
// but version 1.1.0 says that network SHALL not send any new
// confirmed messages until ack has been sent
if (_loramac.get_device_class() == CLASS_C && mcps_indication->type == MCPS_CONFIRMED) {
handle_tx(mcps_indication->port, NULL, 0, MSG_CONFIRMED_FLAG, true);
}
} else {
// Invalid port, ports 0, 224 and 225-255 are reserved.
}
break;
}
break;
}
}
}
lorawan_status_t LoRaWANStack::mib_set_request(loramac_mib_req_confirm_t *mib_set_params)
{
if (NULL == mib_set_params) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
return _loramac.mib_set_request_confirm(mib_set_params);
}
lorawan_status_t LoRaWANStack::mib_get_request(loramac_mib_req_confirm_t *mib_get_params)
{
if(NULL == mib_get_params) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
return _loramac.mib_get_request_confirm(mib_get_params);
}
lorawan_status_t LoRaWANStack::set_link_check_request()
{
_link_check_requested = true;
@ -823,9 +711,8 @@ lorawan_status_t LoRaWANStack::set_link_check_request()
return LORAWAN_STATUS_PARAMETER_INVALID;
}
loramac_mlme_req_t mlme_req;
mlme_req.type = MLME_LINK_CHECK;
return _loramac.mlme_request(&mlme_req);
_loramac.setup_link_check_request();
return LORAWAN_STATUS_OK;
}
void LoRaWANStack::remove_link_check_request()
@ -838,17 +725,17 @@ lorawan_status_t LoRaWANStack::shutdown()
return lora_state_machine(DEVICE_STATE_SHUTDOWN);
}
lorawan_status_t LoRaWANStack::set_device_class(const device_class_t device_class)
lorawan_status_t LoRaWANStack::set_device_class(const device_class_t& device_class)
{
loramac_mib_req_confirm_t mib_req;
mib_req.type = MIB_DEVICE_CLASS;
mib_req.param.dev_class = device_class;
return mib_set_request(&mib_req);
if (device_class == CLASS_B) {
return LORAWAN_STATUS_UNSUPPORTED;
}
_loramac.set_device_class(device_class);
return LORAWAN_STATUS_OK;
}
lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
{
loramac_mib_req_confirm_t mib_req;
lorawan_status_t status = LORAWAN_STATUS_DEVICE_OFF;
_device_current_state = new_state;
@ -860,19 +747,13 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
* Radio will be put to sleep by the APIs underneath
*/
drop_channel_list();
// Shutdown LoRaMac
_loramac.disconnect();
// Stop sending messages and set joined status to false.
#if defined(LORAWAN_COMPLIANCE_TEST)
_loramac.LoRaMacStopTxTimer();
#endif
mib_req.type = MIB_NETWORK_JOINED;
mib_req.param.is_nwk_joined = false;
mib_set_request(&mib_req);
_loramac.set_nwk_joined(false);
// reset buffers to original state
_loramac.reset_ongoing_tx(true);
_rx_msg.msg.mcps_indication.buffer = NULL;
@ -880,7 +761,6 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
_rx_msg.prev_read_size = 0;
_rx_msg.msg.mcps_indication.buffer_size = 0;
// disable the session
_lw_session.active = false;
tr_debug("LoRaWAN protocol has been shut down.");
@ -892,7 +772,6 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
status = LORAWAN_STATUS_DEVICE_OFF;
break;
case DEVICE_STATE_NOT_INITIALIZED:
// Device is disconnected.
status = LORAWAN_STATUS_DEVICE_OFF;
break;
case DEVICE_STATE_INIT:
@ -900,25 +779,13 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
break;
case DEVICE_STATE_JOINING:
if (_lw_session.connection.connect_type == LORAWAN_CONNECTION_OTAA) {
/*
* OTAA join
*/
tr_debug("Send Join-request..");
loramac_mlme_req_t mlme_req;
mlme_req.type = MLME_JOIN;
mlme_req.req.join.dev_eui = _lw_session.connection.connection_u.otaa.dev_eui;
mlme_req.req.join.app_eui = _lw_session.connection.connection_u.otaa.app_eui;
mlme_req.req.join.app_key = _lw_session.connection.connection_u.otaa.app_key;
mlme_req.req.join.nb_trials = _lw_session.connection.connection_u.otaa.nb_trials;
// Send join request to server.
status = _loramac.mlme_request(&mlme_req);
status = _loramac.join_by_otaa(_lw_session.connection.connection_u.otaa);
if (status != LORAWAN_STATUS_OK) {
return status;
}
// Otherwise request was successful and OTAA connect is in
//progress
return LORAWAN_STATUS_CONNECT_IN_PROGRESS;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
@ -926,9 +793,9 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
break;
case DEVICE_STATE_JOINED:
tr_debug("Join OK!");
// Session is now active
_lw_session.active = true;
// Tell the application that we are connected
if (_callbacks.events) {
const int ret = _queue->call(_callbacks.events, CONNECTED);
MBED_ASSERT(ret != 0);
@ -937,34 +804,13 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
status = LORAWAN_STATUS_OK;
break;
case DEVICE_STATE_ABP_CONNECTING:
/*
* ABP connection
*/
mib_req.type = MIB_NET_ID;
mib_req.param.net_id = _lw_session.connection.connection_u.abp.nwk_id;
mib_set_request(&mib_req);
mib_req.type = MIB_DEV_ADDR;
mib_req.param.dev_addr = _lw_session.connection.connection_u.abp.dev_addr;
mib_set_request(&mib_req);
_loramac.join_by_abp(_lw_session.connection.connection_u.abp);
mib_req.type = MIB_NWK_SKEY;
mib_req.param.nwk_skey = _lw_session.connection.connection_u.abp.nwk_skey;
mib_set_request(&mib_req);
mib_req.type = MIB_APP_SKEY;
mib_req.param.app_skey = _lw_session.connection.connection_u.abp.app_skey;
mib_set_request(&mib_req);
mib_req.type = MIB_NETWORK_JOINED;
mib_req.param.is_nwk_joined = true;
mib_set_request(&mib_req);
tr_debug("ABP Connection OK!");
// tell the application we are okay
// if users provide wrong keys, it's their responsibility
// there is no way to test ABP authentication success
status = LORAWAN_STATUS_OK;
// Session is now active
_lw_session.active = true;
if (_callbacks.events) {
const int ret = _queue->call(_callbacks.events, CONNECTED);
@ -973,7 +819,6 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
}
break;
case DEVICE_STATE_SEND:
// If a transmission is ongoing, don't interrupt
if (_loramac.tx_ongoing()) {
status = LORAWAN_STATUS_OK;
} else {
@ -1002,20 +847,17 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
break;
}
}
// otherwise all done, put device in idle state
_device_current_state = DEVICE_STATE_IDLE;
break;
case DEVICE_STATE_IDLE:
//Do nothing
status = LORAWAN_STATUS_IDLE;
break;
#if defined(LORAWAN_COMPLIANCE_TEST)
case DEVICE_STATE_COMPLIANCE_TEST:
//Device is in compliance test mode
tr_debug("Device is in compliance test mode.");
//5000ms
_loramac.LoRaMacSetTxTimer(5000);
_loramac.LoRaMacSetTxTimer(5000); //ms
if (_compliance_test.running == true) {
send_compliance_test_frame_to_mac();
}
@ -1104,11 +946,15 @@ lorawan_status_t LoRaWANStack::send_compliance_test_frame_to_mac()
return mcps_request_handler(&mcps_req);
}
/** Compliance testing function
*
* \param mcps_indication Pointer to the indication structure,
* containing indication attributes.
*/
lorawan_status_t LoRaWANStack::mcps_request_handler(loramac_mcps_req_t *mcps_request)
{
if (mcps_request == NULL) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
return _loramac.mcps_request(mcps_request);
}
void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indication)
{
if (_compliance_test.running == false) {
@ -1128,10 +974,7 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
_compliance_test.running = true;
_compliance_test.state = 1;
loramac_mib_req_confirm_t mib_req;
mib_req.type = MIB_ADR;
mib_req.param.is_adr_enable = true;
mib_set_request(&mib_req);
_loramac.enable_adaptive_datarate(true);
#if MBED_CONF_LORA_PHY == 0
_loramac.LoRaMacTestSetDutyCycleOn(false);
@ -1154,10 +997,8 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
_compliance_test.downlink_counter = 0;
_compliance_test.running = false;
loramac_mib_req_confirm_t mib_req;
mib_req.type = MIB_ADR;
mib_req.param.is_adr_enable = MBED_CONF_LORA_ADR_ON;
mib_set_request(&mib_req);
_loramac.enable_adaptive_datarate(MBED_CONF_LORA_ADR_ON);
#if MBED_CONF_LORA_PHY == 0
_loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON);
#endif
@ -1191,13 +1032,10 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
send_compliance_test_frame_to_mac();
break;
case 5: // (viii)
loramac_mlme_req_t mlme_req;
mlme_req.type = MLME_LINK_CHECK;
_loramac.mlme_request(&mlme_req);
_loramac.setup_link_check_request();
break;
case 6: // (ix)
loramac_mlme_req_t mlme_request;
loramac_mib_req_confirm_t mib_request;
loramac_mlme_req_t mlme_req;
// Disable TestMode and revert back to normal operation
_compliance_test.is_tx_confirmed = true;
@ -1206,32 +1044,26 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
_compliance_test.downlink_counter = 0;
_compliance_test.running = false;
mib_request.type = MIB_ADR;
mib_request.param.is_adr_enable = MBED_CONF_LORA_ADR_ON;
mib_set_request(&mib_request);
_loramac.enable_adaptive_datarate(MBED_CONF_LORA_ADR_ON);
#if MBED_CONF_LORA_PHY == 0
_loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON);
#endif
mlme_request.type = MLME_JOIN;
mlme_request.req.join.dev_eui = _lw_session.connection.connection_u.otaa.dev_eui;
mlme_request.req.join.app_eui = _lw_session.connection.connection_u.otaa.app_eui;
mlme_request.req.join.app_key = _lw_session.connection.connection_u.otaa.app_key;
mlme_request.req.join.nb_trials = _lw_session.connection.connection_u.otaa.nb_trials;
_loramac.mlme_request(&mlme_request);
_loramac.join_by_otaa(_lw_session.connection.connection_u.otaa);
break;
case 7: // (x)
if (mcps_indication->buffer_size == 3) {
loramac_mlme_req_t mlme_req;
mlme_req.type = MLME_TXCW;
mlme_req.req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
mlme_req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
_loramac.mlme_request(&mlme_req);
} else if (mcps_indication->buffer_size == 7) {
loramac_mlme_req_t mlme_req;
mlme_req.type = MLME_TXCW_1;
mlme_req.req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
mlme_req.req.cw_tx_mode.frequency = (uint32_t)((mcps_indication->buffer[3] << 16) | (mcps_indication->buffer[4] << 8)
mlme_req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
mlme_req.cw_tx_mode.frequency = (uint32_t)((mcps_indication->buffer[3] << 16) | (mcps_indication->buffer[4] << 8)
| mcps_indication->buffer[5]) * 100;
mlme_req.req.cw_tx_mode.power = mcps_indication->buffer[6];
mlme_req.cw_tx_mode.power = mcps_indication->buffer[6];
_loramac.mlme_request(&mlme_req);
}
_compliance_test.state = 1;

View File

@ -371,7 +371,7 @@ public:
* LORAWAN_STATUS_UNSUPPORTED is requested class is not supported,
* or other negative error code if request failed.
*/
lorawan_status_t set_device_class(const device_class_t device_class);
lorawan_status_t set_device_class(const device_class_t& device_class);
private:
LoRaWANStack();
@ -401,13 +401,6 @@ private:
*/
void mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm);
/**
* Handles an MCPS request while attempting to hand over a packet from
* upper layers to Mac layer. For example in response to send_frame_to_mac(),
* an MCPS request is generated.
*/
lorawan_status_t mcps_request_handler(loramac_mcps_req_t *mcps_request);
/**
* Handles an MCPS confirmation coming from the Mac layer in response to an
* MCPS request. We take appropriate actions in response to the confirmation,
@ -424,16 +417,6 @@ private:
*/
void mcps_indication_handler(loramac_mcps_indication_t *mcps_indication);
/**
* Sets a MIB request, i.e., update a particular parameter etc.
*/
lorawan_status_t mib_set_request(loramac_mib_req_confirm_t *mib_set_params);
/**
* Requests the MIB to inquire about a particular parameter.
*/
lorawan_status_t mib_get_request(loramac_mib_req_confirm_t *mib_get_params);
/**
* Sets up user application port
*/
@ -488,6 +471,11 @@ private:
*/
void compliance_test_handler(loramac_mcps_indication_t *mcps_indication);
/**
* Used only for compliance testing
*/
lorawan_status_t mcps_request_handler(loramac_mcps_req_t *mcps_request);
/**
* Used only for compliance testing
*/

View File

@ -78,7 +78,7 @@ using namespace events;
LoRaMac::LoRaMac()
: _lora_phy(_lora_time), mac_commands()
: _lora_phy(_lora_time), mac_commands(), _is_nwk_joined(false)
{
//radio_events_t RadioEvents;
_params.keys.dev_eui = NULL;
@ -98,7 +98,6 @@ LoRaMac::LoRaMac()
_params.dl_frame_counter = 0;
_params.is_ul_frame_counter_fixed = false;
_params.is_rx_window_enabled = true;
_params.is_nwk_joined = false;
_params.adr_ack_counter = 0;
_params.is_node_ack_requested = false;
_params.is_srv_ack_requested = false;
@ -187,7 +186,7 @@ void LoRaMac::on_radio_tx_done( void )
lorawan_time_t cur_time = _lora_time.get_current_time( );
loramac_mlme_confirm_t mlme_confirm = mlme.get_confirmation();
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
_lora_phy.put_radio_to_sleep();
} else {
open_continuous_rx2_window();
@ -197,11 +196,11 @@ void LoRaMac::on_radio_tx_done( void )
if(_params.is_rx_window_enabled == true) {
_lora_time.start(_params.timers.rx_window1_timer, _params.rx_window1_delay);
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
_lora_time.start(_params.timers.rx_window2_timer, _params.rx_window2_delay);
}
if ((_params.dev_class == CLASS_C ) ||
if ((_device_class == CLASS_C ) ||
(_params.is_node_ack_requested == true)) {
_lora_time.start(_params.timers.ack_timeout_timer,
_params.rx_window2_delay + _lora_phy.get_ack_timeout());
@ -230,7 +229,7 @@ void LoRaMac::on_radio_tx_done( void )
// Update last tx done time for the current channel
tx_done_params.channel = _params.channel;
tx_done_params.joined = _params.is_nwk_joined;
tx_done_params.joined = _is_nwk_joined;
tx_done_params.last_tx_done_time = cur_time;
_lora_phy.set_last_tx_done(&tx_done_params);
@ -301,7 +300,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
mcps.get_indication().dl_frame_counter = 0;
mcps.get_indication().type = MCPS_UNCONFIRMED;
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
_lora_phy.put_radio_to_sleep();
}
@ -312,7 +311,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
switch (mac_hdr.bits.mtype) {
case FRAME_TYPE_JOIN_ACCEPT:
if (_params.is_nwk_joined == true) {
if (_is_nwk_joined) {
mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR;
prepare_rx_done_abort();
return;
@ -380,7 +379,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
_lora_phy.apply_cf_list(&cflist);
mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK;
_params.is_nwk_joined = true;
_is_nwk_joined = true;
} else {
mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
}
@ -660,7 +659,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
}
// Verify if we need to disable the AckTimeoutTimer
check_to_disable_ack_timeout(_params.is_node_ack_requested, _params.dev_class, mcps.get_confirmation().ack_received,
check_to_disable_ack_timeout(_params.is_node_ack_requested, _device_class, mcps.get_confirmation().ack_received,
_params.ack_timeout_retry_counter, _params.max_ack_timeout_retries );
if(_params.timers.ack_timeout_timer.timer_id == 0) {
@ -672,7 +671,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
void LoRaMac::on_radio_tx_timeout( void )
{
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
_lora_phy.put_radio_to_sleep();
} else {
open_continuous_rx2_window();
@ -687,7 +686,7 @@ void LoRaMac::on_radio_tx_timeout( void )
void LoRaMac::on_radio_rx_error( void )
{
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
_lora_phy.put_radio_to_sleep();
}
@ -698,7 +697,7 @@ void LoRaMac::on_radio_rx_error( void )
mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) {
_lora_time.stop(_params.timers.rx_window2_timer);
_params.flags.bits.mac_done = 1;
@ -711,19 +710,19 @@ void LoRaMac::on_radio_rx_error( void )
mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
_params.flags.bits.mac_done = 1;
}
}
if (_params.dev_class == CLASS_C) {
if (_device_class == CLASS_C) {
open_continuous_rx2_window();
}
}
void LoRaMac::on_radio_rx_timeout(void)
{
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
_lora_phy.put_radio_to_sleep();
}
@ -733,7 +732,7 @@ void LoRaMac::on_radio_rx_timeout(void)
}
mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT;
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time ) >= _params.rx_window2_delay) {
_lora_time.stop(_params.timers.rx_window2_timer);
_params.flags.bits.mac_done = 1;
@ -746,12 +745,12 @@ void LoRaMac::on_radio_rx_timeout(void)
mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
_params.flags.bits.mac_done = 1;
}
}
if (_params.dev_class == CLASS_C) {
if (_device_class == CLASS_C) {
open_continuous_rx2_window();
}
}
@ -936,7 +935,7 @@ void LoRaMac::on_mac_state_check_timer_event(void)
if (_params.flags.bits.mcps_ind == 1) {
_params.flags.bits.mcps_ind = 0;
if (_params.dev_class == CLASS_C) {
if (_device_class == CLASS_C) {
// Activate RX2 window for Class C
open_continuous_rx2_window();
}
@ -1003,7 +1002,7 @@ void LoRaMac::on_rx_window1_timer_event(void)
_params.rx_window1_config.is_rx_continuous = false;
_params.rx_window1_config.rx_slot = _params.rx_slot;
if (_params.dev_class == CLASS_C) {
if (_device_class == CLASS_C) {
_lora_phy.put_radio_to_standby();
}
@ -1024,7 +1023,7 @@ void LoRaMac::on_rx_window2_timer_event(void)
_params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported;
_params.rx_window2_config.rx_slot = RX_SLOT_WIN_2;
if (_params.dev_class != CLASS_C) {
if (_device_class != CLASS_C) {
_params.rx_window2_config.is_rx_continuous = false;
} else {
// Setup continuous listening for class c
@ -1082,7 +1081,7 @@ void LoRaMac::on_ack_timeout_timer_event(void)
_params.is_ack_retry_timeout_expired = true;
_params.mac_state &= ~LORAMAC_ACK_REQ;
}
if (_params.dev_class == CLASS_C) {
if (_device_class == CLASS_C) {
_params.flags.bits.mac_done = 1;
}
}
@ -1172,7 +1171,7 @@ lorawan_status_t LoRaMac::schedule_tx(void)
nextChan.current_datarate = _params.sys_params.channel_data_rate;
_params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON;
nextChan.dc_enabled = _params.is_dutycycle_on;
nextChan.joined = _params.is_nwk_joined;
nextChan.joined = _is_nwk_joined;
nextChan.last_aggregate_tx_time = _params.timers.aggregated_last_tx_time;
// Select channel
@ -1211,7 +1210,7 @@ lorawan_status_t LoRaMac::schedule_tx(void)
_params.sys_params.max_sys_rx_error,
&_params.rx_window2_config);
if (_params.is_nwk_joined == false) {
if (!_is_nwk_joined) {
_params.rx_window1_delay = _params.sys_params.join_accept_delay1
+ _params.rx_window1_config.window_offset;
_params.rx_window2_delay = _params.sys_params.join_accept_delay2
@ -1236,7 +1235,7 @@ void LoRaMac::calculate_backOff(uint8_t channel)
{
backoff_params_t backoff_params;
backoff_params.joined = _params.is_nwk_joined;
backoff_params.joined = _is_nwk_joined;
_params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON;
backoff_params.dc_enabled = _params.is_dutycycle_on;
backoff_params.channel = channel;
@ -1255,7 +1254,7 @@ void LoRaMac::calculate_backOff(uint8_t channel)
void LoRaMac::reset_mac_parameters(void)
{
_params.is_nwk_joined = false;
_is_nwk_joined = false;
// Counters
_params.ul_frame_counter = 0;
@ -1308,6 +1307,29 @@ uint8_t LoRaMac::get_default_tx_datarate()
return _lora_phy.get_default_tx_datarate();
}
lorawan_status_t LoRaMac::enable_adaptive_datarate(bool adr_enabled)
{
_params.sys_params.adr_on = adr_enabled;
return LORAWAN_STATUS_OK;
}
lorawan_status_t LoRaMac::set_channel_data_rate(uint8_t data_rate)
{
if (_params.sys_params.adr_on) {
tr_error("Cannot set data rate. Please turn off ADR first.");
return LORAWAN_STATUS_PARAMETER_INVALID;
}
if (_lora_phy.verify_tx_datarate(data_rate, false) == true) {
_params.sys_params.channel_data_rate = data_rate;
} else {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
return LORAWAN_STATUS_OK;
}
bool LoRaMac::tx_ongoing()
{
return _ongoing_tx_msg.tx_ongoing;
@ -1390,18 +1412,13 @@ int16_t LoRaMac::prepare_ongoing_tx(uint8_t port, const uint8_t* data,
lorawan_status_t LoRaMac::send_ongoing_tx()
{
lorawan_status_t status;
loramac_mib_req_confirm_t mib_get_params;
if (_params.mac_state != LORAMAC_IDLE) {
return LORAWAN_STATUS_BUSY;
}
int8_t datarate = get_default_tx_datarate();
int8_t datarate = _params.sys_params.channel_data_rate;
mib_get_params.type = MIB_CHANNELS_DATARATE;
if(mib_get_request_confirm(&mib_get_params) == LORAWAN_STATUS_OK) {
datarate = mib_get_params.param.channel_data_rate;
}
// TODO: The comment is different than the code???
// Apply the minimum possible datarate.
// Some regions have limitations for the minimum datarate.
@ -1447,6 +1464,103 @@ lorawan_status_t LoRaMac::send_ongoing_tx()
return status;
}
device_class_t LoRaMac::get_device_class() const
{
return _device_class;
}
void LoRaMac::set_device_class(const device_class_t& device_class)
{
_device_class = device_class;
if (CLASS_A == _device_class) {
// Set the radio into sleep to setup a defined state
_lora_phy.put_radio_to_sleep();
} else if (CLASS_C == _device_class) {
// Set the is_node_ack_requested indicator to default
_params.is_node_ack_requested = false;
// Set the radio into sleep mode in case we are still in RX mode
_lora_phy.put_radio_to_sleep();
// Compute Rx2 windows parameters in case the RX2 datarate has changed
_lora_phy.compute_rx_win_params(
_params.sys_params.rx2_channel.datarate,
_params.sys_params.min_rx_symb,
_params.sys_params.max_sys_rx_error,
&_params.rx_window2_config);
}
if (CLASS_C == _device_class) {
open_continuous_rx2_window();
}
}
void LoRaMac::setup_link_check_request()
{
mlme.reset_confirmation();
mlme.get_confirmation().req_type = MLME_LINK_CHECK;
_params.flags.bits.mlme_req = 1;
mac_commands.add_mac_command(MOTE_MAC_LINK_CHECK_REQ, 0, 0);
}
lorawan_status_t LoRaMac::join_by_otaa(const lorawan_connect_otaa_t& otaa_join)
{
if (LORAMAC_IDLE != _params.mac_state) {
return LORAWAN_STATUS_BUSY;
}
mlme.reset_confirmation();
mlme.get_confirmation().req_type = MLME_JOIN;
_params.flags.bits.mlme_req = 1;
// if ((_params.mac_state & LORAMAC_TX_DELAYED) == LORAMAC_TX_DELAYED) {
// return LORAWAN_STATUS_BUSY;
// }
if ((otaa_join.dev_eui == NULL)
|| (otaa_join.app_eui == NULL)
|| (otaa_join.app_key == NULL)
|| (otaa_join.nb_trials == 0)) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
_params.keys.dev_eui = otaa_join.dev_eui;
_params.keys.app_eui = otaa_join.app_eui;
_params.keys.app_key = otaa_join.app_key;
_params.max_join_request_trials = otaa_join.nb_trials;
if (!_lora_phy.verify_nb_join_trials(otaa_join.nb_trials)) {
// Value not supported, get default
_params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS;
}
// Reset variable JoinRequestTrials
_params.join_request_trial_counter = 0;
reset_mac_parameters();
_params.sys_params.channel_data_rate =
_lora_phy.get_alternate_DR(_params.join_request_trial_counter + 1);
loramac_mhdr_t machdr;
machdr.value = 0;
machdr.bits.mtype = FRAME_TYPE_JOIN_REQ;
return send(&machdr, 0, NULL, 0);
}
void LoRaMac::join_by_abp(const lorawan_connect_abp_t& abp_join)
{
_params.net_id = abp_join.nwk_id;
_params.dev_addr = abp_join.dev_addr;
memcpy(_params.keys.nwk_skey, abp_join.nwk_skey,
sizeof(_params.keys.nwk_skey));
memcpy(_params.keys.app_skey, abp_join.app_skey,
sizeof(_params.keys.app_skey));
set_nwk_joined(true);
}
static void memcpy_convert_endianess(uint8_t *dst, const uint8_t *src,
uint16_t size)
{
@ -1513,7 +1627,7 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr,
_params.is_node_ack_requested = true;
//Intentional fallthrough
case FRAME_TYPE_DATA_UNCONFIRMED_UP: {
if (_params.is_nwk_joined == false) {
if (!_is_nwk_joined) {
// No network has been joined yet
return LORAWAN_STATUS_NO_NETWORK_JOINED;
}
@ -1664,7 +1778,7 @@ lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel)
_lora_time.start(_params.timers.mac_state_check_timer,
MAC_STATE_CHECK_TIMEOUT);
if (_params.is_nwk_joined == false) {
if (!_is_nwk_joined) {
_params.join_request_trial_counter++;
}
@ -1694,9 +1808,6 @@ lorawan_status_t LoRaMac::initialize(loramac_primitives_t *primitives,
// Activate MCPS subsystem
mcps.activate_mcps_subsystem();
// Activate MIB subsystem
mib.activate_mib_subsystem(&_lora_phy);
// Activate channel planning subsystem
channel_plan.activate_channelplan_subsystem(&_lora_phy);
@ -1704,7 +1815,7 @@ lorawan_status_t LoRaMac::initialize(loramac_primitives_t *primitives,
_params.flags.value = 0;
_params.dev_class = CLASS_A;
_device_class = CLASS_A;
_params.mac_state = LORAMAC_IDLE;
_params.join_request_trial_counter = 0;
@ -1746,15 +1857,10 @@ lorawan_status_t LoRaMac::initialize(loramac_primitives_t *primitives,
// Store the current initialization time
_params.timers.mac_init_time = _lora_time.get_current_time();
loramac_mib_req_confirm_t mib_req;
_params.sys_params.adr_on = MBED_CONF_LORA_ADR_ON;
mib_req.type = MIB_ADR;
mib_req.param.is_adr_enable = MBED_CONF_LORA_ADR_ON;
mib_set_request_confirm(&mib_req);
mib_req.type = MIB_PUBLIC_NETWORK;
mib_req.param.enable_public_nwk = MBED_CONF_LORA_PUBLIC_NETWORK;
mib_set_request_confirm(&mib_req);
_params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK;
_lora_phy.setup_public_network_mode(MBED_CONF_LORA_PUBLIC_NETWORK);
return LORAWAN_STATUS_OK;
}
@ -1772,7 +1878,7 @@ void LoRaMac::disconnect()
_lora_phy.put_radio_to_sleep();
// Reset internal state
_params.is_nwk_joined = false;
_is_nwk_joined = false;
_params.is_ack_retry_timeout_expired = false;
_params.is_rx_window_enabled = true;
_params.is_node_ack_requested = false;
@ -1825,6 +1931,16 @@ uint8_t LoRaMac::query_tx_possible(uint8_t size)
return current_payload_size;
}
bool LoRaMac::nwk_joined()
{
return _is_nwk_joined;
}
void LoRaMac::set_nwk_joined(bool joined)
{
_is_nwk_joined = joined;
}
lorawan_status_t LoRaMac::add_channel_plan(const lorawan_channelplan_t& plan)
{
// Validate if the MAC is in a correct state
@ -1851,18 +1967,7 @@ lorawan_status_t LoRaMac::remove_channel_plan()
lorawan_status_t LoRaMac::get_channel_plan(lorawan_channelplan_t& plan)
{
// Request Mib to get channels
loramac_mib_req_confirm_t mib_confirm;
memset(&mib_confirm, 0, sizeof(mib_confirm));
mib_confirm.type = MIB_CHANNELS;
lorawan_status_t status = mib.get_request(&mib_confirm, &_params);
if (status != LORAWAN_STATUS_OK) {
return status;
}
return channel_plan.get_plan(plan, &mib_confirm);
return channel_plan.get_plan(plan, _lora_phy.get_phy_channels());
}
lorawan_status_t LoRaMac::remove_single_channel(uint8_t id)
@ -1937,6 +2042,26 @@ lorawan_status_t LoRaMac::multicast_channel_unlink(
return LORAWAN_STATUS_OK;
}
void LoRaMac::bind_radio_driver(LoRaRadio& radio)
{
radio_events.tx_done = mbed::callback(this, &LoRaMac::handle_tx_done);
radio_events.rx_done = mbed::callback(this, &LoRaMac::handle_rx_done);
radio_events.rx_error = mbed::callback(this, &LoRaMac::handle_rx_error);
radio_events.tx_timeout = mbed::callback(this, &LoRaMac::handle_tx_timeout);
radio_events.rx_timeout = mbed::callback(this, &LoRaMac::handle_rx_timeout);
_lora_phy.set_radio_instance(radio);
radio.lock();
radio.init_radio(&radio_events);
radio.unlock();
}
#if defined(LORAWAN_COMPLIANCE_TEST)
/***************************************************************************
* Compliance testing *
**************************************************************************/
lorawan_status_t LoRaMac::mlme_request( loramac_mlme_req_t *mlmeRequest )
{
if (LORAMAC_IDLE != _params.mac_state) {
@ -1950,50 +2075,16 @@ lorawan_status_t LoRaMac::mlme_request( loramac_mlme_req_t *mlmeRequest )
lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN;
if (MLME_LINK_CHECK == mlmeRequest->type) {
status = mac_commands.add_mac_command(MOTE_MAC_LINK_CHECK_REQ, 0, 0);
} else if (MLME_JOIN == mlmeRequest->type) {
if ((_params.mac_state & LORAMAC_TX_DELAYED) == LORAMAC_TX_DELAYED) {
return LORAWAN_STATUS_BUSY;
}
if ((mlmeRequest->req.join.dev_eui == NULL)
|| (mlmeRequest->req.join.app_eui == NULL)
|| (mlmeRequest->req.join.app_key == NULL)
|| (mlmeRequest->req.join.nb_trials == 0)) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
_params.keys.dev_eui = mlmeRequest->req.join.dev_eui;
_params.keys.app_eui = mlmeRequest->req.join.app_eui;
_params.keys.app_key = mlmeRequest->req.join.app_key;
_params.max_join_request_trials = mlmeRequest->req.join.nb_trials;
if (!_lora_phy.verify_nb_join_trials(mlmeRequest->req.join.nb_trials)) {
// Value not supported, get default
_params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS;
}
// Reset variable JoinRequestTrials
_params.join_request_trial_counter = 0;
reset_mac_parameters();
_params.sys_params.channel_data_rate =
_lora_phy.get_alternate_DR(_params.join_request_trial_counter + 1);
loramac_mhdr_t machdr;
machdr.value = 0;
machdr.bits.mtype = FRAME_TYPE_JOIN_REQ;
status = send(&machdr, 0, NULL, 0);
} else if (MLME_TXCW == mlmeRequest->type) {
if (MLME_TXCW == mlmeRequest->type) {
mlme.set_tx_continuous_wave(_params.channel, _params.sys_params.channel_data_rate, _params.sys_params.channel_tx_power,
_params.sys_params.max_eirp, _params.sys_params.antenna_gain, mlmeRequest->req.cw_tx_mode.timeout);
_params.sys_params.max_eirp, _params.sys_params.antenna_gain, mlmeRequest->cw_tx_mode.timeout);
_lora_time.start(_params.timers.mac_state_check_timer,
MAC_STATE_CHECK_TIMEOUT);
_params.mac_state |= LORAMAC_TX_RUNNING;
status = LORAWAN_STATUS_OK;
} else if (MLME_TXCW_1 == mlmeRequest->type) {
mlme.set_tx_continuous_wave(0, 0, mlmeRequest->req.cw_tx_mode.power, 0, 0, mlmeRequest->req.cw_tx_mode.timeout);
mlme.set_tx_continuous_wave(0, 0, mlmeRequest->cw_tx_mode.power, 0, 0, mlmeRequest->cw_tx_mode.timeout);
_lora_time.start(_params.timers.mac_state_check_timer,
MAC_STATE_CHECK_TIMEOUT);
@ -2074,40 +2165,6 @@ lorawan_status_t LoRaMac::mcps_request( loramac_mcps_req_t *mcpsRequest )
return status;
}
lorawan_status_t LoRaMac::mib_get_request_confirm( loramac_mib_req_confirm_t *mibGet )
{
return mib.get_request(mibGet, &_params);
}
lorawan_status_t LoRaMac::mib_set_request_confirm( loramac_mib_req_confirm_t *mibSet )
{
lorawan_status_t status = mib.set_request(mibSet, &_params);
if (LORAWAN_STATUS_OK == status && CLASS_C == _params.dev_class && (MIB_DEVICE_CLASS == mibSet->type ||
(MIB_RX2_CHANNEL == mibSet->type && _params.is_nwk_joined))) {
open_continuous_rx2_window();
}
return status;
}
void LoRaMac::bind_radio_driver(LoRaRadio& radio)
{
radio_events.tx_done = mbed::callback(this, &LoRaMac::handle_tx_done);
radio_events.rx_done = mbed::callback(this, &LoRaMac::handle_rx_done);
radio_events.rx_error = mbed::callback(this, &LoRaMac::handle_rx_error);
radio_events.tx_timeout = mbed::callback(this, &LoRaMac::handle_tx_timeout);
radio_events.rx_timeout = mbed::callback(this, &LoRaMac::handle_rx_timeout);
_lora_phy.set_radio_instance(radio);
radio.lock();
radio.init_radio(&radio_events);
radio.unlock();
}
#if defined(LORAWAN_COMPLIANCE_TEST)
/***************************************************************************
* Compliance testing *
**************************************************************************/
lorawan_status_t LoRaMac::LoRaMacSetTxTimer( uint32_t TxDutyCycleTime )
{
_lora_time.start(tx_next_packet_timer, TxDutyCycleTime);

View File

@ -43,12 +43,11 @@
#include "lorawan/system/LoRaWANTimer.h"
#include "lorastack/phy/LoRaPHY.h"
#include "lorawan/system/lorawan_data_structures.h"
#include "lorastack/mac/LoRaMacCommand.h"
#include "LoRaMacCommand.h"
#include "events/EventQueue.h"
#include "lorastack/mac/LoRaMacMlme.h"
#include "lorastack/mac/LoRaMacMcps.h"
#include "lorastack/mac/LoRaMacMib.h"
#include "lorastack/mac/LoRaMacChannelPlan.h"
#include "LoRaMacMlme.h"
#include "LoRaMacMcps.h"
#include "LoRaMacChannelPlan.h"
#include "loraphy_target.h"
class LoRaMac {
@ -107,6 +106,18 @@ public:
*/
uint8_t query_tx_possible(uint8_t size);
/**
* @brief nwk_joined Checks if device has joined to network
* @return True if joined to network, false otherwise
*/
bool nwk_joined();
/**
* @brief set_nwk_joined This is used for ABP mode for which real joining does not happen
* @param joined True if device has joined in network, false otherwise
*/
void set_nwk_joined(bool joined);
/**
* @brief Adds a channel plan to the system.
*
@ -198,155 +209,6 @@ public:
*/
lorawan_status_t multicast_channel_unlink(multicast_params_t *channel_param);
/**
* @brief Get parameter values from MIB service.
*
* @details The MAC information base service to get the attributes of the LoRaMac layer.
*
* The following code-snippet shows how to use the API to get the
* parameter `AdrEnable`, defined by the enumeration type
* \ref MIB_ADR.
*
* @code
*
* loramac_mib_req_confirm_t mib_get;
* mib_get.type = MIB_ADR;
*
* if (mib_get_request_confirm(&mib_get) == LORAWAN_STATUS_OK) {
* // LoRaMAC updated the parameter mibParam.AdrEnable
* }
*
* @endcode
*
* @param [in] mib_get The MIB-GET request to perform. Refer to
* \ref loramac_mib_req_confirm_t.
*
* @return `lorawan_status_t` The status of the operation.
* The possible values are:
* \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAWAN_STATUS_PARAMETER_INVALID
*/
lorawan_status_t mib_get_request_confirm(loramac_mib_req_confirm_t *mib_get);
/**
* @brief Set attributes for MAC layer using MIB service.
*
* @details The MAC information base service to set the attributes of the LoRaMac layer.
*
* The following code-snippet shows how to use the API to set the
* parameter `adr_enable`, defined by the enumeration type
* \ref MIB_ADR.
*
* @code
*
* loramac_mib_req_confirm_t mib_set;
* mib_set.Type = MIB_ADR;
* mib_set.param.adr_enable = true;
*
* if (mib_set_request_confirm(&mib_set) == LORAWAN_STATUS_OK) {
* // LoRaMAC updated the parameter
* }
*
* @endcode
*
* @param [in] mib_set The MIB-SET request to perform. Refer to
* \ref loramac_mib_req_confirm_t.
*
* @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAWAN_STATUS_PARAMETER_INVALID
*/
lorawan_status_t mib_set_request_confirm(loramac_mib_req_confirm_t *mib_set);
/**
* @brief Set forth an MLME request.
*
* @details The MAC layer management entity handles the management services. The
* following code-snippet shows how to use the API to perform a
* network join request.
*
* @code
*
* static uint8_t dev_eui[] =
* {
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
* };
* static uint8_t app_eui[] =
* {
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
* };
* static uint8_t app_key[] =
* {
* 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
* 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
* };
*
* loramac_mlme_req_t mlme_req;
* mlme_req.Type = MLME_JOIN;
* mlme_req.req.join.dev_eui = dev_eui;
* mlme_req.req.join.app_eui = app_eui;
* mlme_req.req.join.app_key = app_key;
*
* if (LoRaMacMlmeRequest(&mlme_req) == LORAWAN_STATUS_OK) {
* // Service started successfully. Waiting for the Mlme-Confirm event
* }
*
* @endcode
*
* @param [in] request The MLME request to perform.
* Refer to \ref loramac_mlme_req_t.
*
* @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAWAN_STATUS_PARAMETER_INVALID
* \ref LORAWAN_STATUS_NO_NETWORK_JOINED
* \ref LORAWAN_STATUS_LENGTH_ERROR
* \ref LORAWAN_STATUS_DEVICE_OFF
*/
lorawan_status_t mlme_request(loramac_mlme_req_t *request);
/**
* @brief Set forth an MCPS request.
*
* @details The MAC Common Part Sublayer handles the data services. The following
* code-snippet shows how to use the API to send an unconfirmed
* LoRaMAC frame.
*
* @code
*
* uint8_t buffer[] = {1, 2, 3};
*
* loramac_mcps_req_t request;
* request.type = MCPS_UNCONFIRMED;
* request.fport = 1;
* request.f_buffer = buffer;
* request.f_buffer_size = sizeof(buffer);
*
* if (mcps_request(&request) == LORAWAN_STATUS_OK) {
* // Service started successfully. Waiting for the MCPS-Confirm event
* }
*
* @endcode
*
* @param [in] request The MCPS request to perform.
* Refer to \ref loramac_mcps_req_t.
*
* @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAWAN_STATUS_PARAMETER_INVALID
* \ref LORAWAN_STATUS_NO_NETWORK_JOINED
* \ref LORAWAN_STATUS_LENGTH_ERROR
* \ref LORAWAN_STATUS_DEVICE_OFF
*/
lorawan_status_t mcps_request(loramac_mcps_req_t *request);
/** Binds radio driver to PHY layer.
*
* MAC layer is totally detached from the PHY layer so the stack layer
@ -427,6 +289,27 @@ public:
*/
uint8_t get_default_tx_datarate();
/**
* @brief enable_adaptive_datarate Enables or disables adaptive datarate.
* @param adr_enabled Flag indicating is adr enabled or disabled.
* @return LORAWAN_STATUS_OK or a negative error code on failure.
*/
lorawan_status_t enable_adaptive_datarate(bool adr_enabled);
/** Sets up the data rate.
*
* `set_datarate()` first verifies whether the data rate given is valid or not.
* If it is valid, the system sets the given data rate to the channel.
*
* @param data_rate The intended data rate, for example DR_0 or DR_1.
* Note that the macro DR_* can mean different
* things in different regions.
*
* @return LORAWAN_STATUS_OK if everything goes well, otherwise
* a negative error code.
*/
lorawan_status_t set_channel_data_rate(uint8_t data_rate);
/**
* @brief tx_ongoing Check whether a prepare is done or not.
* @return True if prepare_ongoing_tx is called, false otherwise.
@ -465,6 +348,38 @@ public:
*/
lorawan_status_t send_ongoing_tx();
/**
* @brief device_class Returns active device class
* @return Device class in use.
*/
device_class_t get_device_class() const;
/**
* @brief set_device_class Sets active device class.
* @param device_class Device class to use.
*/
void set_device_class(const device_class_t& device_class);
/**
* @brief setup_link_check_request Adds link check request command
* to be put on next outgoing message (when it fits)
*/
void setup_link_check_request();
/**
* @brief join_by_otaa Sends OTAA join message
* @param otaa_join Joining parameters
*
* @return LORAWAN_STATUS_OK or a negative error code on failure.
*/
lorawan_status_t join_by_otaa(const lorawan_connect_otaa_t& otaa_join);
/**
* @brief join_by_abp Sets up ABP connectivity parameters.
* @param abp_join Connectivity parameters.
*/
void join_by_abp(const lorawan_connect_abp_t& abp_join);
private:
/**
* Function to be executed on Radio Tx Done event
@ -613,11 +528,6 @@ private:
*/
LoRaMacMcps mcps;
/**
* MCPS subsystem handle
*/
LoRaMacMib mib;
/**
* Channel planning subsystem
*/
@ -645,9 +555,69 @@ private:
loramac_tx_message_t _ongoing_tx_msg;
bool _is_nwk_joined;
device_class_t _device_class;
#if defined(LORAWAN_COMPLIANCE_TEST)
public: // Test interface
/**
* @brief Set forth an MLME request.
*
* @details The MAC layer management entity handles the management services.
*
* @param [in] request The MLME request to perform.
* Refer to \ref loramac_mlme_req_t.
*
* @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAWAN_STATUS_PARAMETER_INVALID
* \ref LORAWAN_STATUS_NO_NETWORK_JOINED
* \ref LORAWAN_STATUS_LENGTH_ERROR
* \ref LORAWAN_STATUS_DEVICE_OFF
*/
lorawan_status_t mlme_request(loramac_mlme_req_t *request);
/**
* @brief Set forth an MCPS request.
*
* @details The MAC Common Part Sublayer handles the data services. The following
* code-snippet shows how to use the API to send an unconfirmed
* LoRaMAC frame.
*
* @code
*
* uint8_t buffer[] = {1, 2, 3};
*
* loramac_mcps_req_t request;
* request.type = MCPS_UNCONFIRMED;
* request.fport = 1;
* request.f_buffer = buffer;
* request.f_buffer_size = sizeof(buffer);
*
* if (mcps_request(&request) == LORAWAN_STATUS_OK) {
* // Service started successfully. Waiting for the MCPS-Confirm event
* }
*
* @endcode
*
* @param [in] request The MCPS request to perform.
* Refer to \ref loramac_mcps_req_t.
*
* @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAWAN_STATUS_PARAMETER_INVALID
* \ref LORAWAN_STATUS_NO_NETWORK_JOINED
* \ref LORAWAN_STATUS_LENGTH_ERROR
* \ref LORAWAN_STATUS_DEVICE_OFF
*/
lorawan_status_t mcps_request(loramac_mcps_req_t *request);
/**
* \brief LoRaMAC set tx timer.
*

View File

@ -77,12 +77,8 @@ lorawan_status_t LoRaMacChannelPlan::set_plan(const lorawan_channelplan_t& plan)
}
lorawan_status_t LoRaMacChannelPlan::get_plan(lorawan_channelplan_t& plan,
const loramac_mib_req_confirm_t* mib_confirm)
const channel_params_t* channel_list)
{
if (mib_confirm == NULL) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
uint8_t max_num_channels;
uint16_t *channel_mask;
uint8_t count = 0;
@ -103,12 +99,12 @@ lorawan_status_t LoRaMacChannelPlan::get_plan(lorawan_channelplan_t& plan,
// otherwise add them to the channel_plan struct
plan.channels[count].id = i;
plan.channels[count].ch_param.frequency = mib_confirm->param.channel_list[i].frequency;
plan.channels[count].ch_param.dr_range.value = mib_confirm->param.channel_list[i].dr_range.value;
plan.channels[count].ch_param.dr_range.fields.min = mib_confirm->param.channel_list[i].dr_range.fields.min;
plan.channels[count].ch_param.dr_range.fields.max = mib_confirm->param.channel_list[i].dr_range.fields.max;
plan.channels[count].ch_param.band = mib_confirm->param.channel_list[i].band;
plan.channels[count].ch_param.rx1_frequency = mib_confirm->param.channel_list[i].rx1_frequency;
plan.channels[count].ch_param.frequency = channel_list[i].frequency;
plan.channels[count].ch_param.dr_range.value = channel_list[i].dr_range.value;
plan.channels[count].ch_param.dr_range.fields.min = channel_list[i].dr_range.fields.min;
plan.channels[count].ch_param.dr_range.fields.max = channel_list[i].dr_range.fields.max;
plan.channels[count].ch_param.band = channel_list[i].band;
plan.channels[count].ch_param.rx1_frequency = channel_list[i].rx1_frequency;
count++;
}

View File

@ -30,7 +30,6 @@ SPDX-License-Identifier: BSD-3-Clause
#include "lorawan/system/lorawan_data_structures.h"
#include "lorastack/phy/LoRaPHY.h"
#include "lorastack/mac/LoRaMacMib.h"
class LoRaMacChannelPlan {
@ -77,12 +76,12 @@ public:
* @param plan a reference to application provided channel plan structure
* which gets filled in with active channel plan data.
*
* @param mib_confirm pointer to MIB request structure containing channel information
* @param channel_list pointer to structure containing channel information
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t get_plan(lorawan_channelplan_t& plan, const loramac_mib_req_confirm_t *mib_confirm);
lorawan_status_t get_plan(lorawan_channelplan_t& plan, const channel_params_t* channel_list);
/** Remove the active channel plan
*

View File

@ -1,434 +0,0 @@
/**
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRaWAN stack layer that controls both MAC and PHY underneath
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: BSD-3-Clause
*/
#include "lorastack/mac/LoRaMac.h"
#include "lorastack/mac/LoRaMacMib.h"
LoRaMacMib::LoRaMacMib()
: _lora_phy(NULL)
{
}
LoRaMacMib::~LoRaMacMib()
{
}
void LoRaMacMib::activate_mib_subsystem(LoRaPHY *phy)
{
_lora_phy = phy;
}
lorawan_status_t LoRaMacMib::set_request(loramac_mib_req_confirm_t *mibSet,
loramac_protocol_params *params)
{
if (mibSet == NULL || _lora_phy == NULL) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
lorawan_status_t status = LORAWAN_STATUS_OK;
switch (mibSet->type) {
case MIB_DEVICE_CLASS: {
params->dev_class = mibSet->param.dev_class;
switch (params->dev_class) {
case CLASS_A: {
// Set the radio into sleep to setup a defined state
_lora_phy->put_radio_to_sleep();
break;
}
case CLASS_B: {
status = LORAWAN_STATUS_UNSUPPORTED;
break;
}
case CLASS_C: {
// Set the is_node_ack_requested indicator to default
params->is_node_ack_requested = false;
// Set the radio into sleep mode in case we are still in RX mode
_lora_phy->put_radio_to_sleep();
// Compute Rx2 windows parameters in case the RX2 datarate has changed
_lora_phy->compute_rx_win_params(
params->sys_params.rx2_channel.datarate,
params->sys_params.min_rx_symb,
params->sys_params.max_sys_rx_error,
&params->rx_window2_config);
break;
}
}
break;
}
case MIB_NETWORK_JOINED: {
params->is_nwk_joined = mibSet->param.is_nwk_joined;
break;
}
case MIB_ADR: {
params->sys_params.adr_on = mibSet->param.is_adr_enable;
break;
}
case MIB_NET_ID: {
params->net_id = mibSet->param.net_id;
break;
}
case MIB_DEV_ADDR: {
params->dev_addr = mibSet->param.dev_addr;
break;
}
case MIB_NWK_SKEY: {
if (mibSet->param.nwk_skey != NULL) {
memcpy(params->keys.nwk_skey, mibSet->param.nwk_skey,
sizeof(params->keys.nwk_skey));
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_APP_SKEY: {
if (mibSet->param.app_skey != NULL) {
memcpy(params->keys.app_skey, mibSet->param.app_skey,
sizeof(params->keys.app_skey));
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_PUBLIC_NETWORK: {
params->is_nwk_public = mibSet->param.enable_public_nwk;
_lora_phy->setup_public_network_mode(params->is_nwk_public);
break;
}
case MIB_REPEATER_SUPPORT: {
params->is_repeater_supported = mibSet->param.enable_repeater_support;
break;
}
case MIB_RX2_CHANNEL: {
if (_lora_phy->verify_rx_datarate(mibSet->param.rx2_channel.datarate) == true) {
params->sys_params.rx2_channel = mibSet->param.rx2_channel;
if ((params->dev_class == CLASS_C)
&& (params->is_nwk_joined == true)) {
// We can only compute the RX window parameters directly, if we are already
// in class c mode and joined. We cannot setup an RX window in case of any other
// class type.
// Set the radio into sleep mode in case we are still in RX mode
_lora_phy->put_radio_to_sleep();
// Compute Rx2 windows parameters
_lora_phy->compute_rx_win_params(
params->sys_params.rx2_channel.datarate,
params->sys_params.min_rx_symb,
params->sys_params.max_sys_rx_error,
&params->rx_window2_config);
}
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_RX2_DEFAULT_CHANNEL: {
if (_lora_phy->verify_rx_datarate(mibSet->param.rx2_channel.datarate) == true) {
params->sys_params.rx2_channel = mibSet->param.default_rx2_channel;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_CHANNELS_DEFAULT_MASK:
case MIB_CHANNELS_MASK: {
// channel masks must not be tempered with.
// They should be manipulated only on request with certain
// APIs like add_channel() and remove_channel()
// You should be able to get these MIB parameters, not set
status = LORAWAN_STATUS_SERVICE_UNKNOWN;
break;
}
case MIB_CHANNELS_NB_REP: {
if ((mibSet->param.channel_nb_rep >= 1)
&& (mibSet->param.channel_nb_rep <= 15)) {
params->sys_params.retry_num = mibSet->param.channel_nb_rep;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_MAX_RX_WINDOW_DURATION: {
params->sys_params.max_rx_win_time = mibSet->param.max_rx_window;
break;
}
case MIB_RECEIVE_DELAY_1: {
params->sys_params.recv_delay1 = mibSet->param.recv_delay1;
break;
}
case MIB_RECEIVE_DELAY_2: {
params->sys_params.recv_delay2 = mibSet->param.recv_delay2;
break;
}
case MIB_JOIN_ACCEPT_DELAY_1: {
params->sys_params.join_accept_delay1 = mibSet->param.join_accept_delay1;
break;
}
case MIB_JOIN_ACCEPT_DELAY_2: {
params->sys_params.join_accept_delay2 = mibSet->param.join_accept_delay2;
break;
}
case MIB_CHANNELS_DEFAULT_DATARATE: {
if (_lora_phy->verify_tx_datarate(mibSet->param.default_channel_data_rate, true)) {
params->sys_params.channel_data_rate = mibSet->param.default_channel_data_rate;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_CHANNELS_DATARATE: {
if (_lora_phy->verify_tx_datarate(mibSet->param.channel_data_rate, false) == true) {
params->sys_params.channel_data_rate = mibSet->param.channel_data_rate;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_CHANNELS_DEFAULT_TX_POWER: {
if (_lora_phy->verify_tx_power(mibSet->param.default_channel_tx_pwr)) {
params->sys_params.channel_tx_power = mibSet->param.default_channel_tx_pwr;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_CHANNELS_TX_POWER: {
if (_lora_phy->verify_tx_power(mibSet->param.channel_tx_pwr)) {
params->sys_params.channel_tx_power = mibSet->param.channel_tx_pwr;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_UPLINK_COUNTER: {
params->ul_frame_counter = mibSet->param.ul_frame_counter;
break;
}
case MIB_DOWNLINK_COUNTER: {
params->dl_frame_counter = mibSet->param.dl_frame_counter;
break;
}
case MIB_SYSTEM_MAX_RX_ERROR: {
params->sys_params.max_sys_rx_error = mibSet->param.max_rx_sys_error;
break;
}
case MIB_MIN_RX_SYMBOLS: {
params->sys_params.min_rx_symb = mibSet->param.min_rx_symb;
break;
}
case MIB_ANTENNA_GAIN: {
params->sys_params.antenna_gain = mibSet->param.antenna_gain;
break;
}
case MIB_DEFAULT_ANTENNA_GAIN:
{
params->sys_params.antenna_gain = mibSet->param.default_antenna_gain;
break;
}
default:
status = LORAWAN_STATUS_SERVICE_UNKNOWN;
break;
}
return status;
}
lorawan_status_t LoRaMacMib::get_request(loramac_mib_req_confirm_t *mibGet,
loramac_protocol_params *params)
{
lorawan_status_t status = LORAWAN_STATUS_OK;
rx2_channel_params rx2_channel;
if( mibGet == NULL )
{
return LORAWAN_STATUS_PARAMETER_INVALID;
}
switch( mibGet->type )
{
case MIB_DEVICE_CLASS:
{
mibGet->param.dev_class = params->dev_class;
break;
}
case MIB_NETWORK_JOINED:
{
mibGet->param.is_nwk_joined = params->is_nwk_joined;
break;
}
case MIB_ADR:
{
mibGet->param.is_adr_enable = params->sys_params.adr_on;
break;
}
case MIB_NET_ID:
{
mibGet->param.net_id = params->net_id;
break;
}
case MIB_DEV_ADDR:
{
mibGet->param.dev_addr = params->dev_addr;
break;
}
case MIB_NWK_SKEY:
{
mibGet->param.nwk_skey =params->keys.nwk_skey;
break;
}
case MIB_APP_SKEY:
{
mibGet->param.app_skey = params->keys.app_skey;
break;
}
case MIB_PUBLIC_NETWORK:
{
mibGet->param.enable_public_nwk = params->is_nwk_public;
break;
}
case MIB_REPEATER_SUPPORT:
{
mibGet->param.enable_repeater_support = params->is_repeater_supported;
break;
}
case MIB_CHANNELS:
{
mibGet->param.channel_list = _lora_phy->get_phy_channels();
break;
}
case MIB_RX2_CHANNEL:
{
mibGet->param.rx2_channel = params->sys_params.rx2_channel;
break;
}
case MIB_RX2_DEFAULT_CHANNEL:
{
rx2_channel.datarate = _lora_phy->get_default_rx2_datarate();
rx2_channel.frequency = _lora_phy->get_default_rx2_frequency();
mibGet->param.rx2_channel = rx2_channel;
break;
}
case MIB_CHANNELS_DEFAULT_MASK:
{
mibGet->param.default_channel_mask = _lora_phy->get_channel_mask(true);
break;
}
case MIB_CHANNELS_MASK:
{
mibGet->param.channel_mask = _lora_phy->get_channel_mask(false);
break;
}
case MIB_CHANNELS_NB_REP:
{
mibGet->param.channel_nb_rep = params->sys_params.retry_num;
break;
}
case MIB_MAX_RX_WINDOW_DURATION:
{
mibGet->param.max_rx_window = params->sys_params.max_rx_win_time;
break;
}
case MIB_RECEIVE_DELAY_1:
{
mibGet->param.recv_delay1 = params->sys_params.recv_delay1;
break;
}
case MIB_RECEIVE_DELAY_2:
{
mibGet->param.recv_delay2 = params->sys_params.recv_delay2;
break;
}
case MIB_JOIN_ACCEPT_DELAY_1:
{
mibGet->param.join_accept_delay1 = params->sys_params.join_accept_delay1;
break;
}
case MIB_JOIN_ACCEPT_DELAY_2:
{
mibGet->param.join_accept_delay2 = params->sys_params.join_accept_delay2;
break;
}
case MIB_CHANNELS_DEFAULT_DATARATE:
{
mibGet->param.default_channel_data_rate = _lora_phy->get_default_tx_datarate();
break;
}
case MIB_CHANNELS_DATARATE:
{
mibGet->param.channel_data_rate = params->sys_params.channel_data_rate;
break;
}
case MIB_CHANNELS_DEFAULT_TX_POWER:
{
mibGet->param.default_channel_tx_pwr = _lora_phy->get_default_tx_power();
break;
}
case MIB_CHANNELS_TX_POWER:
{
mibGet->param.channel_tx_pwr = params->sys_params.channel_tx_power;
break;
}
case MIB_UPLINK_COUNTER:
{
mibGet->param.ul_frame_counter = params->ul_frame_counter;
break;
}
case MIB_DOWNLINK_COUNTER:
{
mibGet->param.dl_frame_counter = params->dl_frame_counter;
break;
}
case MIB_MULTICAST_CHANNEL:
{
mibGet->param.multicast_list = params->multicast_channels;
break;
}
case MIB_SYSTEM_MAX_RX_ERROR:
{
mibGet->param.max_rx_sys_error = params->sys_params.max_sys_rx_error;
break;
}
case MIB_MIN_RX_SYMBOLS:
{
mibGet->param.min_rx_symb = params->sys_params.min_rx_symb;
break;
}
case MIB_ANTENNA_GAIN:
{
mibGet->param.antenna_gain = params->sys_params.antenna_gain;
break;
}
case MIB_DEFAULT_ANTENNA_GAIN:
{
mibGet->param.default_antenna_gain = params->sys_params.antenna_gain;
break;
}
default:
status = LORAWAN_STATUS_SERVICE_UNKNOWN;
break;
}
return status;
}

View File

@ -1,100 +0,0 @@
/**
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRaWAN stack layer that controls both MAC and PHY underneath
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MBED_OS_LORAWAN_MAC_MIB_H_
#define MBED_OS_LORAWAN_MAC_MIB_H_
#include "lorawan/system/lorawan_data_structures.h"
#include "lorastack/phy/LoRaPHY.h"
// forward declaration
class LoRaMac;
class LoRaMacMib {
public:
/** Constructor
*
* Sets local handles to NULL. These handles will be set when the subsystem
* is activated by the MAC layer.
*/
LoRaMacMib();
/** Destructor
*
* Does nothing
*/
~LoRaMacMib();
/** Activating MLME subsystem
*
* Stores pointers to MAC and PHY layer handles
*
* @param phy pointer to PHY layer
*/
void activate_mib_subsystem(LoRaPHY *phy);
/** Sets up a MIB Request
*
* Used to configure MAC protocol parameters using appropriate
* key/value pair in the MIB request structure. Use this API to set
* any system wide configurable parameter exposed by MIB service.
*
* @param mibSet [in] pointer to MIB request structure
* @param params pointer to MAC protocol parameters which will be modified
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t set_request(loramac_mib_req_confirm_t *mibSet,
loramac_protocol_params *params);
/** Provides access to the given MIB parameter
*
* Used to extract information about system wide MAC protocol parameters
* which are exposed by MIB service.
*
* @param mibGet [out] pointer to MIB request structure which will be filled in
* @param params pointer to MAC protocol parameters
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t get_request(loramac_mib_req_confirm_t *mibGet,
loramac_protocol_params *params);
private:
/**
* Pointer PHY handle
*/
LoRaPHY *_lora_phy;
};
#endif /* MBED_OS_LORAWAN_MAC_MIB_H_ */

View File

@ -55,21 +55,6 @@ typedef uint32_t lorawan_time_t;
#define MSG_MULTICAST_FLAG 0x04
#define MSG_PROPRIETARY_FLAG 0x08
/**
* A macro to test a if a bit is on in a channel mask or not.
*/
//#define MASK_BIT_TEST(mask, bit) (mask & (1U << bit))
//#define MASK_BIT_TEST(mask, bit) ((mask)[(bit) / 16] & (1U << ((bit) % 16)))
/**
* A macro to clear a bit in a channel mask.
*/
//#define MASK_BIT_CLEAR(mask, bit) (mask &= ~(1 << bit))
/**
* A macro to clear a bit in a channel mask.
*/
//#define MASK_BIT_SET(mask, bit) (mask |= (1 << bit))
/**
* Bit mask for message flags
*/
@ -762,62 +747,6 @@ typedef enum {
MCPS_PROPRIETARY,
} mcps_type_t;
/*!
* LoRaMAC MCPS-Request structure.
*/
typedef struct {
/*!
* MCPS-Request type.
*/
mcps_type_t type;
/*!
* Frame port field. Must be set if the payload is not empty. Use the
* application-specific frame port values: [1...223].
*
* LoRaWAN Specification V1.0.2, chapter 4.3.2.
*/
uint8_t fport;
/*!
* Uplink datarate, if ADR is off.
*/
int8_t data_rate;
/*!
* The number of trials to transmit the frame, if the LoRaMAC layer did not
* receive an acknowledgment. The MAC performs a datarate adaptation
* according to the LoRaWAN Specification V1.0.2, chapter 18.4, as in
* the following table:
*
* Transmission nb | Data Rate
* ----------------|-----------
* 1 (first) | DR
* 2 | DR
* 3 | max(DR-1,0)
* 4 | max(DR-1,0)
* 5 | max(DR-2,0)
* 6 | max(DR-2,0)
* 7 | max(DR-3,0)
* 8 | max(DR-3,0)
*
* Note that if nb_trials is set to 1 or 2, the MAC will not decrease
* the datarate, if the LoRaMAC layer did not receive an acknowledgment.
*/
uint8_t nb_trials;
/** Payload data
*
* A pointer to the buffer of the frame payload.
*/
void *f_buffer;
/** Payload size
*
* The size of the frame payload.
*/
uint16_t f_buffer_size;
} loramac_mcps_req_t;
/*!
* LoRaMAC MCPS-Confirm.
*/
@ -1025,29 +954,6 @@ typedef struct {
uint8_t power;
} mlme_cw_tx_mode_t;
/*!
* LoRaMAC MLME-Request structure.
*/
typedef struct {
/*!
* MLME-Request type.
*/
mlme_type_t type;
/*!
* MLME-Request parameters.
*/
union {
/*!
* MLME-Request parameters for a join request.
*/
mlme_join_req_t join;
/*!
* MLME-Request parameters for TX continuous mode request.
*/
mlme_cw_tx_mode_t cw_tx_mode;
} req;
} loramac_mlme_req_t;
/*!
* LoRaMAC MLME-Confirm primitive.
@ -1091,465 +997,6 @@ typedef struct {
mlme_type_t indication_type;
} loramac_mlme_indication_t;
/*!
* LoRa MAC Information Base (MIB).
*
* The following table lists the MIB parameters and the related attributes:
*
* Attribute | Get | Set
* --------------------------------- | :-: | :-:
* \ref MIB_DEVICE_CLASS | YES | YES
* \ref MIB_NETWORK_JOINED | YES | YES
* \ref MIB_ADR | YES | YES
* \ref MIB_NET_ID | YES | YES
* \ref MIB_DEV_ADDR | YES | YES
* \ref MIB_NWK_SKEY | YES | YES
* \ref MIB_APP_SKEY | YES | YES
* \ref MIB_PUBLIC_NETWORK | YES | YES
* \ref MIB_REPEATER_SUPPORT | YES | YES
* \ref MIB_CHANNELS | YES | NO
* \ref MIB_RX2_CHANNEL | YES | YES
* \ref MIB_CHANNELS_MASK | YES | YES
* \ref MIB_CHANNELS_DEFAULT_MASK | YES | YES
* \ref MIB_CHANNELS_NB_REP | YES | YES
* \ref MIB_MAX_RX_WINDOW_DURATION | YES | YES
* \ref MIB_RECEIVE_DELAY_1 | YES | YES
* \ref MIB_RECEIVE_DELAY_2 | YES | YES
* \ref MIB_JOIN_ACCEPT_DELAY_1 | YES | YES
* \ref MIB_JOIN_ACCEPT_DELAY_2 | YES | YES
* \ref MIB_CHANNELS_DATARATE | YES | YES
* \ref MIB_CHANNELS_DEFAULT_DATARATE| YES | YES
* \ref MIB_CHANNELS_TX_POWER | YES | YES
* \ref MIB_CHANNELS_DEFAULT_TX_POWER| YES | YES
* \ref MIB_UPLINK_COUNTER | YES | YES
* \ref MIB_DOWNLINK_COUNTER | YES | YES
* \ref MIB_MULTICAST_CHANNEL | YES | NO
* \ref MIB_SYSTEM_MAX_RX_ERROR | YES | YES
* \ref MIB_MIN_RX_SYMBOLS | YES | YES
* \ref MIB_ANTENNA_GAIN | YES | YES
* \ref MIB_DEFAULT_ANTENNA_GAIN | YES | YES
*
* The following table provides links to the function implementations of the
* related MIB primitives:
*
* Primitive | Function
* ---------------- | :---------------------:
* MIB-Set | LoRaMacMibSetRequestConfirm
* MIB-Get | LoRaMacMibGetRequestConfirm
*/
typedef enum {
/*!
* LoRaWAN device class.
*
* LoRaWAN Specification V1.0.2.
*/
MIB_DEVICE_CLASS,
/*!
* LoRaWAN Network joined attribute.
*
* LoRaWAN Specification V1.0.2.
*/
MIB_NETWORK_JOINED,
/*!
* Adaptive data rate.
*
* LoRaWAN Specification V1.0.2, chapter 4.3.1.1.
*
* [true: ADR enabled, false: ADR disabled].
*/
MIB_ADR,
/*!
* Network identifier.
*
* LoRaWAN Specification V1.0.2, chapter 6.1.1.
*/
MIB_NET_ID,
/*!
* End-device address.
*
* LoRaWAN Specification V1.0.2, chapter 6.1.1.
*/
MIB_DEV_ADDR,
/*!
* Network session key.
*
* LoRaWAN Specification V1.0.2, chapter 6.1.3.
*/
MIB_NWK_SKEY,
/*!
* Application session key.
*
* LoRaWAN Specification V1.0.2, chapter 6.1.4.
*/
MIB_APP_SKEY,
/*!
* Set the network type to public or private.
*
* LoRaWAN Regional Parameters V1.0.2rB.
*
* [true: public network, false: private network]
*/
MIB_PUBLIC_NETWORK,
/*!
* Support the operation with repeaters.
*
* LoRaWAN Regional Parameters V1.0.2rB.
*
* [true: repeater support enabled, false: repeater support disabled]
*/
MIB_REPEATER_SUPPORT,
/*!
* Communication channels. A GET request will return a
* pointer that references the first entry of the channel list. The
* list is of size LORA_MAX_NB_CHANNELS.
*
* LoRaWAN Regional Parameters V1.0.2rB.
*/
MIB_CHANNELS,
/*!
* Set receive window 2 channel.
*
* LoRaWAN Specification V1.0.2, chapter 3.3.1.
*/
MIB_RX2_CHANNEL,
/*!
* Set receive window 2 channel.
*
* LoRaWAN Specification V1.0.2, chapter 3.3.2.
*/
MIB_RX2_DEFAULT_CHANNEL,
/*!
* LoRaWAN channels mask.
*
* LoRaWAN Regional Parameters V1.0.2rB.
*/
MIB_CHANNELS_MASK,
/*!
* LoRaWAN default channels mask.
*
* LoRaWAN Regional Parameters V1.0.2rB.
*/
MIB_CHANNELS_DEFAULT_MASK,
/*!
* Set the number of repetitions on a channel.
*
* LoRaWAN Specification V1.0.2, chapter 5.2.
*/
MIB_CHANNELS_NB_REP,
/*!
* The maximum receive window duration in [ms].
*
* LoRaWAN Specification V1.0.2, chapter 3.3.3.
*/
MIB_MAX_RX_WINDOW_DURATION,
/*!
* The receive delay 1 in [ms].
*
* LoRaWAN Regional Parameters V1.0.2rB.
*/
MIB_RECEIVE_DELAY_1,
/*!
* The receive delay 2 in [ms].
*
* LoRaWAN Regional Parameters V1.0.2rB.
*/
MIB_RECEIVE_DELAY_2,
/*!
* The join accept delay 1 in [ms].
*
* LoRaWAN Regional Parameters V1.0.2rB.
*/
MIB_JOIN_ACCEPT_DELAY_1,
/*!
* The join accept delay 2 in [ms].
*
* LoRaWAN Regional Parameters V1.0.2rB.
*/
MIB_JOIN_ACCEPT_DELAY_2,
/*!
* The default data rate of a channel.
*
* LoRaWAN Regional Parameters V1.0.2rB.
*
* The allowed ranges are region-specific. Please refer to \ref DR_0 to \ref DR_15 for details.
*/
MIB_CHANNELS_DEFAULT_DATARATE,
/*!
* The data rate of a channel.
*
* LoRaWAN Regional Parameters V1.0.2rB.
*
* The allowed ranges are region-specific. Please refer to \ref DR_0 to \ref DR_15 for details.
*/
MIB_CHANNELS_DATARATE,
/*!
* The transmission power of a channel.
*
* LoRaWAN Regional Parameters V1.0.2rB.
*
* The allowed ranges are region-specific. Please refer to \ref TX_POWER_0 to \ref TX_POWER_15 for details.
*/
MIB_CHANNELS_TX_POWER,
/*!
* The transmission power of a channel.
*
* LoRaWAN Regional Parameters V1.0.2rB.
*
* The allowed ranges are region-specific. Please refer to \ref TX_POWER_0 to \ref TX_POWER_15 for details.
*/
MIB_CHANNELS_DEFAULT_TX_POWER,
/*!
* LoRaWAN uplink counter.
*
* LoRaWAN Specification V1.0.2, chapter 4.3.1.5.
*/
MIB_UPLINK_COUNTER,
/*!
* LoRaWAN downlink counter.
*
* LoRaWAN Specification V1.0.2, chapter 4.3.1.5.
*/
MIB_DOWNLINK_COUNTER,
/*!
* Multicast channels. A GET request will return a pointer to the first
* entry of the multicast channel linked list. If the pointer is equal to
* NULL, the list is empty.
*/
MIB_MULTICAST_CHANNEL,
/*!
* System overall timing error in milliseconds.
* [-SystemMaxRxError : +SystemMaxRxError]
* Default: +/-10 ms
*/
MIB_SYSTEM_MAX_RX_ERROR,
/*!
* The minimum number of symbols required to detect an RX frame.
* Default: 6 symbols
*/
MIB_MIN_RX_SYMBOLS,
/*!
* The antenna gain of the node. The default value is region-specific.
* The antenna gain is used to calculate the TX power of the node.
* The formula is:
* radioTxPower = ( int8_t )floor( maxEirp - antennaGain )
*/
MIB_ANTENNA_GAIN,
/*!
* Default antenna gain of the node. Default value is region specific.
* The antenna gain is used to calculate the TX power of the node.
* The formula is:
* radioTxPower = ( int8_t )floor( maxEirp - antennaGain )
*/
MIB_DEFAULT_ANTENNA_GAIN
} mib_type_t;
/*!
* LoRaMAC MIB parameters.
*/
typedef union {
/*!
* LoRaWAN device class.
*
* Related MIB type: \ref MIB_DEVICE_CLASS
*/
device_class_t dev_class;
/*!
* LoRaWAN network joined attribute
*
* Related MIB type: \ref MIB_NETWORK_JOINED
*/
bool is_nwk_joined;
/*!
* Activation state of ADR
*
* Related MIB type: \ref MIB_ADR
*/
bool is_adr_enable;
/*!
* Network identifier
*
* Related MIB type: \ref MIB_NET_ID
*/
uint32_t net_id;
/*!
* End-device address
*
* Related MIB type: \ref MIB_DEV_ADDR
*/
uint32_t dev_addr;
/*!
* Network session key
*
* Related MIB type: \ref MIB_NWK_SKEY
*/
uint8_t *nwk_skey;
/*!
* Application session key
*
* Related MIB type: \ref MIB_APP_SKEY
*/
uint8_t *app_skey;
/*!
* Enable or disable a public network
*
* Related MIB type: \ref MIB_PUBLIC_NETWORK
*/
bool enable_public_nwk;
/*!
* Enable or disable repeater support
*
* Related MIB type: \ref MIB_REPEATER_SUPPORT
*/
bool enable_repeater_support;
/*!
* LoRaWAN channel
*
* Related MIB type: \ref MIB_CHANNELS
*/
channel_params_t* channel_list;
/*!
* Channel for the receive window 2
*
* Related MIB type: \ref MIB_RX2_CHANNEL
*/
rx2_channel_params rx2_channel;
/*!
* Channel for the receive window 2
*
* Related MIB type: \ref MIB_RX2_DEFAULT_CHANNEL
*/
rx2_channel_params default_rx2_channel;
/*!
* Channel mask
*
* Related MIB type: \ref MIB_CHANNELS_MASK
*/
uint16_t* channel_mask;
/*!
* Default channel mask
*
* Related MIB type: \ref MIB_CHANNELS_DEFAULT_MASK
*/
uint16_t* default_channel_mask;
/*!
* Number of frame repetitions
*
* Related MIB type: \ref MIB_CHANNELS_NB_REP
*/
uint8_t channel_nb_rep;
/*!
* Maximum receive window duration
*
* Related MIB type: \ref MIB_MAX_RX_WINDOW_DURATION
*/
uint32_t max_rx_window;
/*!
* Receive delay 1
*
* Related MIB type: \ref MIB_RECEIVE_DELAY_1
*/
uint32_t recv_delay1;
/*!
* Receive delay 2
*
* Related MIB type: \ref MIB_RECEIVE_DELAY_2
*/
uint32_t recv_delay2;
/*!
* Join accept delay 1
*
* Related MIB type: \ref MIB_JOIN_ACCEPT_DELAY_1
*/
uint32_t join_accept_delay1;
/*!
* Join accept delay 2
*
* Related MIB type: \ref MIB_JOIN_ACCEPT_DELAY_2
*/
uint32_t join_accept_delay2;
/*!
* Channels data rate
*
* Related MIB type: \ref MIB_CHANNELS_DEFAULT_DATARATE
*/
int8_t default_channel_data_rate;
/*!
* Channels data rate
*
* Related MIB type: \ref MIB_CHANNELS_DATARATE
*/
int8_t channel_data_rate;
/*!
* Channels TX power
*
* Related MIB type: \ref MIB_CHANNELS_DEFAULT_TX_POWER
*/
int8_t default_channel_tx_pwr;
/*!
* Channels TX power
*
* Related MIB type: \ref MIB_CHANNELS_TX_POWER
*/
int8_t channel_tx_pwr;
/*!
* LoRaWAN uplink counter
*
* Related MIB type: \ref MIB_UPLINK_COUNTER
*/
uint32_t ul_frame_counter;
/*!
* LoRaWAN downlink counter
*
* Related MIB type: \ref MIB_DOWNLINK_COUNTER
*/
uint32_t dl_frame_counter;
/*!
* Multicast channel
*
* Related MIB type: \ref MIB_MULTICAST_CHANNEL
*/
multicast_params_t* multicast_list;
/*!
* System overall timing error in milliseconds
*
* Related MIB type: \ref MIB_SYSTEM_MAX_RX_ERROR
*/
uint32_t max_rx_sys_error;
/*!
* Minimum required number of symbols to detect an RX frame
*
* Related MIB type: \ref MIB_MIN_RX_SYMBOLS
*/
uint8_t min_rx_symb;
/*!
* Antenna gain
*
* Related MIB type: \ref MIB_ANTENNA_GAIN
*/
float antenna_gain;
/*!
* Default antenna gain
*
* Related MIB type: \ref MIB_DEFAULT_ANTENNA_GAIN
*/
float default_antenna_gain;
} mib_params_t;
/*!
* LoRaMAC MIB-RequestConfirm structure
*/
typedef struct {
/*!
* MIB-Request type
*/
mib_type_t type;
/*!
* MLME-RequestConfirm parameters
*/
mib_params_t param;
}loramac_mib_req_confirm_t;
/** LoRaMAC status.
*
*/
@ -1830,14 +1277,10 @@ typedef struct lorawan_session {
lorawan_connect_t connection;
/**
* LoRaWAN uplink counter
*
* Related MIB type: LORA_MIB_UPLINK_COUNTER
*/
uint32_t uplink_counter;
/**
* LoRaWAN downlink counter
*
* Related MIB type: LORA_MIB_DOWNLINK_COUNTER
*/
uint32_t downlink_counter;
} lorawan_session_t;
@ -2051,11 +1494,6 @@ typedef struct {
typedef struct {
/*!
* Actual device class
*/
device_class_t dev_class;
/*!
* Holds the type of current Receive window slot
*/
@ -2288,6 +1726,69 @@ typedef struct lora_channelplan {
} lorawan_channelplan_t;
#if defined(LORAWAN_COMPLIANCE_TEST)
typedef struct {
/*!
* MLME-Request type.
*/
mlme_type_t type;
mlme_cw_tx_mode_t cw_tx_mode;
} loramac_mlme_req_t;
typedef struct {
/*!
* MCPS-Request type.
*/
mcps_type_t type;
/*!
* Frame port field. Must be set if the payload is not empty. Use the
* application-specific frame port values: [1...223].
*
* LoRaWAN Specification V1.0.2, chapter 4.3.2.
*/
uint8_t fport;
/*!
* Uplink datarate, if ADR is off.
*/
int8_t data_rate;
/*!
* The number of trials to transmit the frame, if the LoRaMAC layer did not
* receive an acknowledgment. The MAC performs a datarate adaptation
* according to the LoRaWAN Specification V1.0.2, chapter 18.4, as in
* the following table:
*
* Transmission nb | Data Rate
* ----------------|-----------
* 1 (first) | DR
* 2 | DR
* 3 | max(DR-1,0)
* 4 | max(DR-1,0)
* 5 | max(DR-2,0)
* 6 | max(DR-2,0)
* 7 | max(DR-3,0)
* 8 | max(DR-3,0)
*
* Note that if nb_trials is set to 1 or 2, the MAC will not decrease
* the datarate, if the LoRaMAC layer did not receive an acknowledgment.
*/
uint8_t nb_trials;
/** Payload data
*
* A pointer to the buffer of the frame payload.
*/
void *f_buffer;
/** Payload size
*
* The size of the frame payload.
*/
uint16_t f_buffer_size;
} loramac_mcps_req_t;
/** LoRaWAN compliance tests support data
*
*/