LoRa: Moved connect logic from LoRaWANStack to LoRaMac class

- Internal change only
pull/6566/head
Antti Kauppila 2018-04-09 11:08:29 +03:00
parent 1310392d1b
commit fa062fff76
5 changed files with 161 additions and 183 deletions

View File

@ -122,56 +122,72 @@ void LoRaWANStack::bind_radio_driver(LoRaRadio& radio)
lorawan_status_t LoRaWANStack::connect()
{
// connection attempt without parameters.
// System tries to look for configuration in mbed_lib.json that can be
// overridden by mbed_app.json. However, if none of the json files are
// available (highly unlikely), we still fallback to some default parameters.
// Check lorawan_data_structure for fallback defaults.
if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
tr_error("Stack not initialized!");
return LORAWAN_STATUS_NOT_INITIALIZED;
}
lorawan_connect_t connection_params;
lorawan_status_t status = _loramac.prepare_join(NULL, MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION);
//TODO: LoRaWANStack don't need to know these values, move to LoRaMac (or below)
#if MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION
const static uint8_t dev_eui[] = MBED_CONF_LORA_DEVICE_EUI;
const static uint8_t app_eui[] = MBED_CONF_LORA_APPLICATION_EUI;
const static uint8_t app_key[] = MBED_CONF_LORA_APPLICATION_KEY;
if (LORAWAN_STATUS_OK != status) {
return status;
}
connection_params.connect_type = LORAWAN_CONNECTION_OTAA;
connection_params.connection_u.otaa.app_eui = const_cast<uint8_t *>(app_eui);
connection_params.connection_u.otaa.dev_eui = const_cast<uint8_t *>(dev_eui);
connection_params.connection_u.otaa.app_key = const_cast<uint8_t *>(app_key);
connection_params.connection_u.otaa.nb_trials = MBED_CONF_LORA_NB_TRIALS;
return join_request_by_otaa(connection_params);
#else
const static uint8_t nwk_skey[] = MBED_CONF_LORA_NWKSKEY;
const static uint8_t app_skey[] = MBED_CONF_LORA_APPSKEY;
const static uint32_t dev_addr = MBED_CONF_LORA_DEVICE_ADDRESS;
const static uint32_t nwk_id = (MBED_CONF_LORA_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK);
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 = const_cast<uint8_t *>(nwk_skey);
connection_params.connection_u.abp.app_skey = const_cast<uint8_t *>(app_skey);
return activation_by_personalization(connection_params);
#endif
return handle_connect(MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION);
}
lorawan_status_t LoRaWANStack::connect(const lorawan_connect_t &connect)
{
lorawan_status_t mac_status;
if (connect.connect_type == LORAWAN_CONNECTION_OTAA) {
mac_status = join_request_by_otaa(connect);
} else if (connect.connect_type == LORAWAN_CONNECTION_ABP) {
mac_status = activation_by_personalization(connect);
} else {
return LORAWAN_STATUS_PARAMETER_INVALID;
if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
tr_error("Stack not initialized!");
return LORAWAN_STATUS_NOT_INITIALIZED;
}
return mac_status;
if (!(connect.connect_type == LORAWAN_CONNECTION_OTAA) &&
!(connect.connect_type == LORAWAN_CONNECTION_ABP)) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
bool is_otaa = (connect.connect_type == LORAWAN_CONNECTION_OTAA);
lorawan_status_t status = _loramac.prepare_join(&connect, is_otaa);
if (LORAWAN_STATUS_OK != status) {
return status;
}
return handle_connect(is_otaa);
}
lorawan_status_t LoRaWANStack::handle_connect(bool is_otaa)
{
device_states_t new_state;
if (is_otaa) {
tr_debug("Initiating OTAA");
// As mentioned in the comment above, in 1.0.2 spec, counters are always set
// to zero for new connection. This section is common for both normal and
// connection restore at this moment. Will change in future with 1.1 support.
_lw_session.downlink_counter = 0;
_lw_session.uplink_counter = 0;
new_state = DEVICE_STATE_JOINING;
} else {
// If current state is SHUTDOWN, device may be trying to re-establish
// communication. In case of ABP specification is meddled about frame counters.
// It says to reset counters to zero but there is no mechanism to tell the
// network server that the device was disconnected or restarted.
// At the moment, this implementation does not support a non-volatile
// memory storage.
//_lw_session.downlink_counter; //Get from NVM
//_lw_session.uplink_counter; //Get from NVM
tr_debug("Initiating ABP");
tr_debug("Frame Counters. UpCnt=%lu, DownCnt=%lu",
_lw_session.uplink_counter, _lw_session.downlink_counter);
new_state = DEVICE_STATE_ABP_CONNECTING;
}
return lora_state_machine(new_state);
}
lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue)
@ -315,61 +331,6 @@ lorawan_status_t LoRaWANStack::set_channel_data_rate(uint8_t data_rate)
return _loramac.set_channel_data_rate(data_rate);
}
lorawan_status_t LoRaWANStack::join_request_by_otaa(const lorawan_connect_t &params)
{
if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state)
{
tr_error("Stack not initialized!");
return LORAWAN_STATUS_NOT_INITIALIZED;
}
tr_debug("Initiating OTAA");
// As mentioned in the comment above, in 1.0.2 spec, counters are always set
// to zero for new connection. This section is common for both normal and
// connection restore at this moment. Will change in future with 1.1 support.
_lw_session.downlink_counter = 0;
_lw_session.uplink_counter = 0;
_lw_session.connection.connect_type = LORAWAN_CONNECTION_OTAA;
_lw_session.connection.connection_u.otaa.dev_eui = params.connection_u.otaa.dev_eui;
_lw_session.connection.connection_u.otaa.app_eui = params.connection_u.otaa.app_eui;
_lw_session.connection.connection_u.otaa.app_key = params.connection_u.otaa.app_key;
_lw_session.connection.connection_u.otaa.nb_trials = params.connection_u.otaa.nb_trials;
return lora_state_machine(DEVICE_STATE_JOINING);
}
lorawan_status_t LoRaWANStack::activation_by_personalization(const lorawan_connect_t &params)
{
if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
tr_error("Stack not initialized!");
return LORAWAN_STATUS_NOT_INITIALIZED;
}
tr_debug("Initiating ABP");
_lw_session.connection.connect_type = LORAWAN_CONNECTION_ABP;
_lw_session.connection.connection_u.abp.dev_addr = params.connection_u.abp.dev_addr;
_lw_session.connection.connection_u.abp.nwk_skey = params.connection_u.abp.nwk_skey;
_lw_session.connection.connection_u.abp.app_skey = params.connection_u.abp.app_skey;
// If current state is SHUTDOWN, device may be trying to re-establish
// communication. In case of ABP specification is meddled about frame counters.
// It says to reset counters to zero but there is no mechanism to tell the
// network server that the device was disconnected or restarted.
// At the moment, this implementation does not support a non-volatile
// memory storage.
//_lw_session.downlink_counter; //Get from NVM
//_lw_session.uplink_counter; //Get from NVM
tr_debug("Frame Counters. UpCnt=%lu, DownCnt=%lu",
_lw_session.uplink_counter, _lw_session.downlink_counter);
return lora_state_machine(DEVICE_STATE_ABP_CONNECTING);
}
int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
uint16_t length, uint8_t flags, bool null_allowed)
{
@ -512,12 +473,10 @@ void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm)
switch (mlme_confirm->req_type) {
case MLME_JOIN:
if (mlme_confirm->status == LORAMAC_EVENT_INFO_STATUS_OK) {
// Status is OK, node has joined the network
if (lora_state_machine(DEVICE_STATE_JOINED) != LORAWAN_STATUS_OK) {
tr_error("Lora state machine did not return LORAWAN_STATUS_OK");
}
} else {
// Join attempt failed.
if (lora_state_machine(DEVICE_STATE_IDLE) != LORAWAN_STATUS_IDLE) {
tr_error("Lora state machine did not return DEVICE_STATE_IDLE !");
}
@ -531,8 +490,6 @@ void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm)
break;
case MLME_LINK_CHECK:
if (mlme_confirm->status == LORAMAC_EVENT_INFO_STATUS_OK) {
// Check DemodMargin
// Check NbGateways
#if defined(LORAWAN_COMPLIANCE_TEST)
if (_compliance_test.running == true) {
_compliance_test.link_check = true;
@ -541,7 +498,6 @@ void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm)
} else
#endif
{
// normal operation as oppose to compliance testing
if (_callbacks.link_check_resp) {
const int ret = _queue->call(_callbacks.link_check_resp,
mlme_confirm->demod_margin,
@ -776,10 +732,10 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
status = LORAWAN_STATUS_OK;
break;
case DEVICE_STATE_JOINING:
if (_lw_session.connection.connect_type == LORAWAN_CONNECTION_OTAA) {
if (_lw_session.connect_type == LORAWAN_CONNECTION_OTAA) {
tr_debug("Send Join-request..");
status = _loramac.join_by_otaa(_lw_session.connection.connection_u.otaa);
status = _loramac.join(true);
if (status != LORAWAN_STATUS_OK) {
return status;
}
@ -803,7 +759,7 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
break;
case DEVICE_STATE_ABP_CONNECTING:
_loramac.join_by_abp(_lw_session.connection.connection_u.abp);
_loramac.join(false);
tr_debug("ABP Connection OK!");
@ -1030,7 +986,7 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
#if MBED_CONF_LORA_PHY == 0
_loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON);
#endif
_loramac.join_by_otaa(_lw_session.connection.connection_u.otaa);
_loramac.join(true);
break;
case 7: // (x)
if (mcps_indication->buffer_size == 3) {

View File

@ -35,11 +35,6 @@ SPDX-License-Identifier: BSD-3-Clause
#include "lorawan/system/lorawan_data_structures.h"
#include "LoRaRadio.h"
/**
* A mask for the network ID.
*/
#define LORAWAN_NETWORK_ID_MASK ( uint32_t )0xFE000000
class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> {
private:
/** End-device states.
@ -422,31 +417,10 @@ private:
*/
lorawan_status_t set_application_port(uint8_t port);
/** End device OTAA join.
*
* Based on the LoRaWAN standard 1.0.2.
* Join the network using the Over The Air Activation (OTAA) procedure.
*
* @param params The `lorawan_connect_t` type structure.
*
* @return LORAWAN_STATUS_OK or
* LORAWAN_STATUS_CONNECT_IN_PROGRESS on success,
* or a negative error code on failure.
/**
* Handles connection internally
*/
lorawan_status_t join_request_by_otaa(const lorawan_connect_t &params);
/** End device ABP join.
*
* Based on the LoRaWAN standard 1.0.2.
* Join the network using the Activation By Personalization (ABP) procedure.
*
* @param params The `lorawan_connect_t` type structure.
*
* @return LORAWAN_STATUS_OK or
* LORAWAN_STATUS_CONNECT_IN_PROGRESS on success,
* or a negative error code on failure.
*/
lorawan_status_t activation_by_personalization(const lorawan_connect_t &params);
lorawan_status_t handle_connect(bool is_otaa);
private:

View File

@ -76,6 +76,11 @@ using namespace events;
*/
#define DOWN_LINK 1
/**
* A mask for the network ID.
*/
#define LORAWAN_NETWORK_ID_MASK ( uint32_t )0xFE000000
LoRaMac::LoRaMac()
: _lora_phy(_lora_time), mac_commands(), _is_nwk_joined(false)
@ -1412,8 +1417,85 @@ void LoRaMac::setup_link_check_request()
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)
lorawan_status_t LoRaMac::prepare_join(const lorawan_connect_t *params, bool is_otaa)
{
if (params) {
if (is_otaa) {
// if ((params->connection_u.otaa.dev_eui == NULL) ||
// (params->connection_u.otaa.app_eui == NULL) ||
// (params->connection_u.otaa.app_key == NULL) ||
// (params->connection_u.otaa.nb_trials == 0)) {
// return LORAWAN_STATUS_PARAMETER_INVALID;
// }
_params.keys.dev_eui = params->connection_u.otaa.dev_eui;
_params.keys.app_eui = params->connection_u.otaa.app_eui;
_params.keys.app_key = params->connection_u.otaa.app_key;
_params.max_join_request_trials = params->connection_u.otaa.nb_trials;
if (!_lora_phy.verify_nb_join_trials(params->connection_u.otaa.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);
} else {
_params.net_id = params->connection_u.abp.nwk_id;
_params.dev_addr = params->connection_u.abp.dev_addr;
memcpy(_params.keys.nwk_skey, params->connection_u.abp.nwk_skey,
sizeof(_params.keys.nwk_skey));
memcpy(_params.keys.app_skey, params->connection_u.abp.app_skey,
sizeof(_params.keys.app_skey));
}
} else {
#if MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION
const static uint8_t dev_eui[] = MBED_CONF_LORA_DEVICE_EUI;
const static uint8_t app_eui[] = MBED_CONF_LORA_APPLICATION_EUI;
const static uint8_t app_key[] = MBED_CONF_LORA_APPLICATION_KEY;
_params.keys.app_eui = const_cast<uint8_t *>(app_eui);
_params.keys.dev_eui = const_cast<uint8_t *>(dev_eui);
_params.keys.app_key = const_cast<uint8_t *>(app_key);
_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);
#else
const static uint8_t nwk_skey[] = MBED_CONF_LORA_NWKSKEY;
const static uint8_t app_skey[] = MBED_CONF_LORA_APPSKEY;
_params.net_id = (MBED_CONF_LORA_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK);
_params.dev_addr = MBED_CONF_LORA_DEVICE_ADDRESS;
memcpy(_params.keys.nwk_skey, nwk_skey,
sizeof(_params.keys.nwk_skey));
memcpy(_params.keys.app_skey, app_skey,
sizeof(_params.keys.app_skey));
#endif
}
return LORAWAN_STATUS_OK;
}
lorawan_status_t LoRaMac::join(bool is_otaa)
{
if (!is_otaa) {
set_nwk_joined(true);
return LORAWAN_STATUS_OK;
}
if (LORAMAC_IDLE != _params.mac_state) {
return LORAWAN_STATUS_BUSY;
}
@ -1423,53 +1505,12 @@ lorawan_status_t LoRaMac::join_by_otaa(const lorawan_connect_otaa_t& otaa_join)
_mlme_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)
{

View File

@ -364,18 +364,20 @@ public:
void setup_link_check_request();
/**
* @brief join_by_otaa Sends OTAA join message
* @param otaa_join Joining parameters
* @brief prepare_join prepares arguments to be ready for join() call.
* @param params Join parameters to use, if NULL, the default will be used.
* @param is_otaa True if joining is to be done using OTAA, false for ABP.
*
* @return LORAWAN_STATUS_OK or a negative error code on failure.
*/
lorawan_status_t join_by_otaa(const lorawan_connect_otaa_t& otaa_join);
lorawan_status_t prepare_join(const lorawan_connect_t *params, bool is_otaa = true);
/**
* @brief join_by_abp Sets up ABP connectivity parameters.
* @param abp_join Connectivity parameters.
* @brief join Joins the network.
* @param is_otaa True if joining is to be done using OTAA, false for ABP.
* @return LORAWAN_STATUS_OK or a negative error code on failure.
*/
void join_by_abp(const lorawan_connect_abp_t& abp_join);
lorawan_status_t join(bool is_otaa = true);
private:
/**

View File

@ -1277,7 +1277,12 @@ typedef struct lorawan_session {
*/
bool active;
lorawan_connect_t connection;
/*!
* Select the connection type, either LORAWAN_CONNECTION_OTAA
* or LORAWAN_CONNECTION_ABP.
*/
uint8_t connect_type;
/**
* LoRaWAN uplink counter
*/