LoRa: LoRaWANInterface refactored.

- Only internal changes, no functionality changes
- Some minor improvements to LoRaWanStack
pull/6411/head
Antti Kauppila 2018-03-12 13:30:00 +02:00
parent 32257858d0
commit a294aa028d
7 changed files with 336 additions and 339 deletions

View File

@ -28,14 +28,9 @@ inline LoRaWANStack& stk_obj()
return LoRaWANStack::get_lorawan_stack();
}
LoRaWANInterface::LoRaWANInterface(LoRaRadio& radio) : _link_check_requested(false)
LoRaWANInterface::LoRaWANInterface(LoRaRadio& radio)
{
// Pass mac_handlers to radio to the radio driver after
// binding radio driver to PHY layer
radio_events_t *events = stk_obj().bind_radio_driver(radio);
radio.lock();
radio.init_radio(events);
radio.unlock();
stk_obj().bind_radio_driver(radio);
}
LoRaWANInterface::~LoRaWANInterface()
@ -44,71 +39,17 @@ LoRaWANInterface::~LoRaWANInterface()
lorawan_status_t LoRaWANInterface::initialize(EventQueue *queue)
{
if(!queue) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
return stk_obj().initialize_mac_layer(queue);
}
lorawan_status_t LoRaWANInterface::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.
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;
return connect(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);
/**
*
* 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 connect(connection_params);
}
return stk_obj().connect();
}
lorawan_status_t LoRaWANInterface::connect(const lorawan_connect_t &connect)
{
lorawan_status_t mac_status;
if (connect.connect_type == LORAWAN_CONNECTION_OTAA) {
mac_status = stk_obj().join_request_by_otaa(connect);
} else if (connect.connect_type == LORAWAN_CONNECTION_ABP) {
mac_status = stk_obj().activation_by_personalization(connect);
} else {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
return mac_status;
return stk_obj().connect(connect);
}
lorawan_status_t LoRaWANInterface::disconnect()
@ -118,13 +59,12 @@ lorawan_status_t LoRaWANInterface::disconnect()
lorawan_status_t LoRaWANInterface::add_link_check_request()
{
_link_check_requested = true;
return stk_obj().set_link_check_request();
}
void LoRaWANInterface::remove_link_check_request()
{
_link_check_requested = false;
stk_obj().remove_link_check_request();
}
lorawan_status_t LoRaWANInterface::set_datarate(uint8_t data_rate)
@ -170,37 +110,17 @@ lorawan_status_t LoRaWANInterface::remove_channel_plan()
int16_t LoRaWANInterface::send(uint8_t port, const uint8_t* data,
uint16_t length, int flags)
{
if (_link_check_requested) {
// add a link check request with normal data, until the application
// explicitly removes it.
add_link_check_request();
}
return stk_obj().handle_tx(port, data, length, flags);
if (data) {
return stk_obj().handle_tx(port, data, length, flags);
} else {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
}
int16_t LoRaWANInterface::receive(uint8_t port, uint8_t* data, uint16_t length,
int flags)
{
if (data && length > 0) {
return stk_obj().handle_rx(port, data, length, flags);
} else {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
return stk_obj().handle_rx(port, data, length, flags);
}
lorawan_status_t LoRaWANInterface::add_app_callbacks(lorawan_app_callbacks_t *callbacks)
{
if (!callbacks || !callbacks->events) {
// Event Callback is mandatory
return LORAWAN_STATUS_PARAMETER_INVALID;
}
stk_obj().set_lora_callbacks(callbacks);
return LORAWAN_STATUS_OK;
return stk_obj().set_lora_callbacks(callbacks);
}

View File

@ -428,9 +428,6 @@ public:
* callbacks.
*/
virtual lorawan_status_t add_app_callbacks(lorawan_app_callbacks_t *callbacks);
private:
bool _link_check_requested;
};
#endif /* LORAWANINTERFACE_H_ */

View File

@ -85,10 +85,9 @@ lorawan_status_t LoRaWANStack::set_application_port(uint8_t port)
* Constructor and destructor *
****************************************************************************/
LoRaWANStack::LoRaWANStack()
: _loramac(_lora_time), _lora_phy(_lora_time),
_device_current_state(DEVICE_STATE_NOT_INITIALIZED), _mac_handlers(NULL),
_num_retry(1), _app_port(INVALID_PORT), _duty_cycle_on(MBED_CONF_LORA_DUTY_CYCLE_ON),
_queue(NULL)
: _loramac(),
_device_current_state(DEVICE_STATE_NOT_INITIALIZED), _num_retry(1),
_app_port(INVALID_PORT), _link_check_requested(false), _queue(NULL)
{
#ifdef MBED_CONF_LORA_APP_PORT
if (is_port_valid(MBED_CONF_LORA_APP_PORT)) {
@ -121,17 +120,82 @@ LoRaWANStack& LoRaWANStack::get_lorawan_stack()
return _lw_stack;
}
radio_events_t *LoRaWANStack::bind_radio_driver(LoRaRadio& radio)
void LoRaWANStack::bind_radio_driver(LoRaRadio& radio)
{
// Store pointer to callback routines inside MAC layer (non-IRQ safe)
_mac_handlers = _loramac.get_phy_event_handlers();
// passes the reference to radio driver down to PHY layer
//Move these to LoRaMAC class
radio_events_t *events = _loramac.get_phy_event_handlers();
_lora_phy.set_radio_instance(radio);
return _mac_handlers;
radio.lock();
radio.init_radio(events);
radio.unlock();
}
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.
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;
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);
/**
*
* 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 activation_by_personalization(connection_params);
}
}
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;
}
return mac_status;
}
lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue)
{
if(!queue) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
if (DEVICE_STATE_NOT_INITIALIZED != _device_current_state)
{
tr_debug("Initialized already");
@ -139,34 +203,19 @@ lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue)
}
tr_debug("Initializing MAC layer");
//store a pointer to Event Queue
_queue = queue;
#if defined(LORAWAN_COMPLIANCE_TEST)
_compliance_test.app_data_buffer = compliance_test_buffer;
#endif
_lora_time.activate_timer_subsystem(queue);
_loramac.initialize(&LoRaMacPrimitives, &_lora_phy, queue);
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);
mib_req.type = MIB_PUBLIC_NETWORK;
mib_req.param.enable_public_nwk = MBED_CONF_LORA_PUBLIC_NETWORK;
mib_set_request(&mib_req);
// Reset counters to zero. Will change in future with 1.1 support.
_lw_session.downlink_counter = 0;
_lw_session.uplink_counter = 0;
// Start loRaWAN state machine.
set_device_state(DEVICE_STATE_INIT);
return lora_state_machine();
return lora_state_machine(DEVICE_STATE_INIT);
}
uint16_t LoRaWANStack::check_possible_tx_size(uint16_t size)
@ -255,11 +304,6 @@ lorawan_status_t LoRaWANStack::set_confirmed_msg_retry(uint8_t count)
return LORAWAN_STATUS_OK;
}
void LoRaWANStack::set_device_state(device_states_t new_state)
{
_device_current_state = new_state;
}
/*!
* \brief MLME-Indication event function
*
@ -281,26 +325,27 @@ void LoRaWANStack::mlme_indication_handler(loramac_mlme_indication_t *mlmeIndica
}
}
void LoRaWANStack::set_lora_callbacks(lorawan_app_callbacks_t *cbs)
lorawan_status_t LoRaWANStack::set_lora_callbacks(lorawan_app_callbacks_t *cbs)
{
if (cbs) {
if (cbs->events) {
_callbacks.events = cbs->events;
}
if (cbs->link_check_resp) {
_callbacks.link_check_resp = cbs->link_check_resp;
}
if (cbs->battery_level) {
_callbacks.battery_level = cbs->battery_level;
}
if (!cbs || !cbs->events) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
_callbacks.events = cbs->events;
if (cbs->link_check_resp) {
_callbacks.link_check_resp = cbs->link_check_resp;
}
if (cbs->battery_level) {
_callbacks.battery_level = cbs->battery_level;
}
return LORAWAN_STATUS_OK;
}
lorawan_status_t LoRaWANStack::add_channels(const lorawan_channelplan_t &channel_plan)
{
// If device is not initialized, stop right away
if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
tr_error("Stack not initialized!");
return LORAWAN_STATUS_NOT_INITIALIZED;
@ -380,39 +425,12 @@ lorawan_status_t LoRaWANStack::set_channel_data_rate(uint8_t data_rate)
return mib_set_request(&mib_params);
}
void LoRaWANStack::commission_device(const lorawan_dev_commission_t &commission_data)
{
_lw_session.connection.connect_type = commission_data.connection.connect_type;
_lw_session.downlink_counter = commission_data.downlink_counter;
_lw_session.uplink_counter = commission_data.uplink_counter;
if (commission_data.connection.connect_type == LORAWAN_CONNECTION_OTAA) {
_lw_session.connection.connection_u.otaa.app_eui =
commission_data.connection.connection_u.otaa.app_eui;
_lw_session.connection.connection_u.otaa.app_key =
commission_data.connection.connection_u.otaa.app_key;
_lw_session.connection.connection_u.otaa.dev_eui =
commission_data.connection.connection_u.otaa.dev_eui;
_lw_session.connection.connection_u.otaa.nb_trials =
commission_data.connection.connection_u.otaa.nb_trials;
} else {
_lw_session.connection.connection_u.abp.dev_addr =
commission_data.connection.connection_u.abp.dev_addr;
_lw_session.connection.connection_u.abp.nwk_skey =
commission_data.connection.connection_u.abp.nwk_skey;
_lw_session.connection.connection_u.abp.app_skey =
commission_data.connection.connection_u.abp.app_skey;
}
}
/**
*
* Join OTAA
*/
lorawan_status_t LoRaWANStack::join_request_by_otaa(const lorawan_connect_t &params)
{
lorawan_dev_commission_t commission;
if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state)
{
tr_error("Stack not initialized!");
@ -421,21 +439,19 @@ lorawan_status_t LoRaWANStack::join_request_by_otaa(const lorawan_connect_t &par
tr_debug("Initiating OTAA");
commission.connection.connect_type = LORAWAN_CONNECTION_OTAA;
commission.connection.connection_u.otaa.dev_eui = params.connection_u.otaa.dev_eui;
commission.connection.connection_u.otaa.app_eui = params.connection_u.otaa.app_eui;
commission.connection.connection_u.otaa.app_key = params.connection_u.otaa.app_key;
commission.connection.connection_u.otaa.nb_trials = params.connection_u.otaa.nb_trials;
// 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.
commission.downlink_counter = 0;
commission.uplink_counter = 0;
_lw_session.downlink_counter = 0;
_lw_session.uplink_counter = 0;
_lw_session.connection.connect_type = LORAWAN_CONNECTION_OTAA;
commission_device(commission);
set_device_state(DEVICE_STATE_JOINING);
return lora_state_machine();
_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);
}
/**
@ -444,9 +460,6 @@ lorawan_status_t LoRaWANStack::join_request_by_otaa(const lorawan_connect_t &par
*/
lorawan_status_t LoRaWANStack::activation_by_personalization(const lorawan_connect_t &params)
{
lorawan_status_t status;
lorawan_dev_commission_t commission;
if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
tr_error("Stack not initialized!");
return LORAWAN_STATUS_NOT_INITIALIZED;
@ -454,36 +467,36 @@ lorawan_status_t LoRaWANStack::activation_by_personalization(const lorawan_conne
tr_debug("Initiating ABP");
commission.connection.connect_type = LORAWAN_CONNECTION_ABP;
commission.connection.connection_u.abp.dev_addr = params.connection_u.abp.dev_addr;
commission.connection.connection_u.abp.nwk_skey = params.connection_u.abp.nwk_skey;
commission.connection.connection_u.abp.app_skey = params.connection_u.abp.app_skey;
_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, so we try a last ditch effort here to restore correct
// frame counters. If that doesn't work, user must manually reset frame
// counters on their network server.
commission.downlink_counter = _lw_session.downlink_counter;
commission.uplink_counter = _lw_session.uplink_counter;
// memory storage.
//_lw_session.downlink_counter; //Get from NVM
//_lw_session.uplink_counter; //Get from NVM
tr_debug("Frame Counters. UpCnt=%lu, DownCnt=%lu",
commission.uplink_counter, commission.downlink_counter);
_lw_session.uplink_counter, _lw_session.downlink_counter);
commission_device(commission);
set_device_state(DEVICE_STATE_ABP_CONNECTING);
status = lora_state_machine();
return status;
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)
{
if (_link_check_requested) {
// add a link check request with normal data, until the application
// explicitly removes it.
set_link_check_request();
}
if (!_lw_session.active) {
return LORAWAN_STATUS_NO_ACTIVE_SESSIONS;
}
@ -577,8 +590,7 @@ int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
}
tr_info("RTS = %u bytes, PEND = %u", _tx_msg.f_buffer_size, _tx_msg.pending_size);
set_device_state(DEVICE_STATE_SEND);
status = lora_state_machine();
status = lora_state_machine(DEVICE_STATE_SEND);
// send user the length of data which is scheduled now.
// user should take care of the pending data.
@ -603,7 +615,7 @@ int16_t LoRaWANStack::handle_rx(const uint8_t port, uint8_t* data,
}
#endif
if (data == NULL) {
if (data == NULL || length == 0) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
@ -667,15 +679,6 @@ int16_t LoRaWANStack::handle_rx(const uint8_t port, uint8_t* data,
return base_size;
}
lorawan_status_t LoRaWANStack::mlme_request_handler(loramac_mlme_req_t *mlme_request)
{
if (mlme_request == NULL) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
return _loramac.mlme_request(mlme_request);
}
/** MLME-Confirm event function
*
* \param mlme_confirm Pointer to the confirm structure,
@ -693,14 +696,12 @@ void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm)
case MLME_JOIN:
if (mlme_confirm->status == LORAMAC_EVENT_INFO_STATUS_OK) {
// Status is OK, node has joined the network
set_device_state(DEVICE_STATE_JOINED);
if (lora_state_machine() != LORAWAN_STATUS_OK) {
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.
set_device_state(DEVICE_STATE_IDLE);
if (lora_state_machine() != LORAWAN_STATUS_IDLE) {
if (lora_state_machine(DEVICE_STATE_IDLE) != LORAWAN_STATUS_IDLE) {
tr_error("Lora state machine did not return DEVICE_STATE_IDLE !");
}
@ -950,7 +951,10 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
#endif
//5000ms
_loramac.LoRaMacSetTxTimer(5000);
set_device_state(DEVICE_STATE_COMPLIANCE_TEST);
//TODO: Should we call lora_state_machine here instead of just setting the state?
_device_current_state = DEVICE_STATE_COMPLIANCE_TEST;
// lora_state_machine(DEVICE_STATE_COMPLIANCE_TEST);
tr_debug("Compliance test activated.");
}
} else {
@ -976,8 +980,7 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
// Clear any compliance test message stuff before going back to normal operation.
memset(&_tx_msg, 0, sizeof(_tx_msg));
set_device_state(DEVICE_STATE_IDLE);
lora_state_machine();
lora_state_machine(DEVICE_STATE_IDLE);
break;
case 1: // (iii, iv)
_compliance_test.app_data_size = 2;
@ -1003,7 +1006,7 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
case 5: // (viii)
loramac_mlme_req_t mlme_req;
mlme_req.type = MLME_LINK_CHECK;
mlme_request_handler(&mlme_req);
_loramac.mlme_request(&mlme_req);
break;
case 6: // (ix)
loramac_mlme_req_t mlme_request;
@ -1027,14 +1030,14 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
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;
mlme_request_handler(&mlme_request);
_loramac.mlme_request(&mlme_request);
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_request_handler(&mlme_req);
_loramac.mlme_request(&mlme_req);
} else if (mcps_indication->buffer_size == 7) {
loramac_mlme_req_t mlme_req;
mlme_req.type = MLME_TXCW_1;
@ -1042,7 +1045,7 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
mlme_req.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_request_handler(&mlme_req);
_loramac.mlme_request(&mlme_req);
}
_compliance_test.state = 1;
break;
@ -1069,28 +1072,34 @@ lorawan_status_t LoRaWANStack::mib_get_request(loramac_mib_req_confirm_t *mib_ge
lorawan_status_t LoRaWANStack::set_link_check_request()
{
_link_check_requested = true;
if (!_callbacks.link_check_resp) {
tr_error("Must assign a callback function for link check request. ");
return LORAWAN_STATUS_PARAMETER_INVALID;
}
loramac_mlme_req_t mlme_req;
mlme_req.type = MLME_LINK_CHECK;
return mlme_request_handler(&mlme_req);
return _loramac.mlme_request(&mlme_req);
}
void LoRaWANStack::remove_link_check_request()
{
_link_check_requested = false;
}
lorawan_status_t LoRaWANStack::shutdown()
{
set_device_state(DEVICE_STATE_SHUTDOWN);
return lora_state_machine();
return lora_state_machine(DEVICE_STATE_SHUTDOWN);
}
lorawan_status_t LoRaWANStack::lora_state_machine()
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;
switch (_device_current_state) {
case DEVICE_STATE_SHUTDOWN:
/*
@ -1153,7 +1162,7 @@ lorawan_status_t LoRaWANStack::lora_state_machine()
mlme_req.req.join.nb_trials = _lw_session.connection.connection_u.otaa.nb_trials;
// Send join request to server.
status = mlme_request_handler(&mlme_req);
status = _loramac.mlme_request(&mlme_req);
if (status != LORAWAN_STATUS_OK) {
return status;
}
@ -1243,7 +1252,7 @@ lorawan_status_t LoRaWANStack::lora_state_machine()
}
}
// otherwise all done, put device in idle state
set_device_state(DEVICE_STATE_IDLE);
_device_current_state = DEVICE_STATE_IDLE;
break;
case DEVICE_STATE_IDLE:
//Do nothing

View File

@ -34,42 +34,7 @@ SPDX-License-Identifier: BSD-3-Clause
#include "lorastack/mac/LoRaMac.h"
#include "lorawan/system/lorawan_data_structures.h"
#include "LoRaRadio.h"
#ifdef MBED_CONF_LORA_PHY
#if MBED_CONF_LORA_PHY == 0
#include "lorawan/lorastack/phy/LoRaPHYEU868.h"
#define LoRaPHY_region LoRaPHYEU868
#elif MBED_CONF_LORA_PHY == 1
#include "lorawan/lorastack/phy/LoRaPHYAS923.h"
#define LoRaPHY_region LoRaPHYAS923
#elif MBED_CONF_LORA_PHY == 2
#include "lorawan/lorastack/phy/LoRaPHYAU915.h"
#define LoRaPHY_region LoRaPHYAU915;
#elif MBED_CONF_LORA_PHY == 3
#include "lorawan/lorastack/phy/LoRaPHYCN470.h"
#define LoRaPHY_region LoRaPHYCN470
#elif MBED_CONF_LORA_PHY == 4
#include "lorawan/lorastack/phy/LoRaPHYCN779.h"
#define LoRaPHY_region LoRaPHYCN779
#elif MBED_CONF_LORA_PHY == 5
#include "lorawan/lorastack/phy/LoRaPHYEU433.h"
#define LoRaPHY_region LoRaPHYEU433
#elif MBED_CONF_LORA_PHY == 6
#include "lorawan/lorastack/phy/LoRaPHYIN865.h"
#define LoRaPHY_region LoRaPHYIN865
#elif MBED_CONF_LORA_PHY == 7
#include "lorawan/lorastack/phy/LoRaPHYKR920.h"
#define LoRaPHY_region LoRaPHYKR920
#elif MBED_CONF_LORA_PHY == 8
#include "lorawan/lorastack/phy/LoRaPHYUS915.h"
#define LoRaPHY_region LoRaPHYUS915
#elif MBED_CONF_LORA_PHY == 9
#include "lorawan/lorastack/phy/LoRaPHYUS915Hybrid.h"
#define LoRaPHY_region LoRaPHYUS915Hybrid
#endif //MBED_CONF_LORA_PHY == VALUE
#else
#error "Must set LoRa PHY layer parameters."
#endif //MBED_CONF_LORA_PHY
#include "loraphy_target.h"
/**
* A mask for the network ID.
@ -103,15 +68,90 @@ public:
* MAC layer is totally detached from the PHY layer so the stack layer
* needs to play the role of an arbitrator. This API gets a radio driver
* object from the application (via LoRaWANInterface), binds it to the PHY
* layer and returns MAC layer callback handles which the radio driver will
* layer and initialises radio callback handles which the radio driver will
* use in order to report events.
*
* @param radio LoRaRadio object, i.e., the radio driver
*
* @return A list of callbacks from MAC layer that needs to
* be passed to radio driver
*/
radio_events_t *bind_radio_driver(LoRaRadio& radio);
void bind_radio_driver(LoRaRadio& radio);
/** Connect OTAA or ABP using Mbed-OS config system
*
* Connect by Over The Air Activation or Activation By Personalization.
* You need to configure the connection properly via the Mbed OS configuration
* system.
*
* When connecting via OTAA, the return code for success (LORAWAN_STATUS_CONNECT_IN_PROGRESS) is negative.
* However, this is not a real error. It tells you that the connection is in progress and you will
* be notified of the completion via an event. By default, after the Join Accept message
* is received, base stations may provide the node with a CF-List that replaces
* all user-configured channels except the Join/Default channels. A CF-List can
* configure a maximum of five channels other than the default channels.
*
* In case of ABP, the CONNECTED event is posted before the call to `connect()` returns.
* To configure more channels, we recommend that you use the `set_channel_plan()` API after the connection.
* By default, the PHY layers configure only the mandatory Join channels. The retransmission back-off restrictions
* on these channels are severe and you may experience long delays or even failures in the confirmed traffic.
* If you add more channels, the aggregated duty cycle becomes much more relaxed as compared to the Join (default) channels only.
*
* **NOTES ON RECONNECTION:**
* Currently, the Mbed OS LoRaWAN implementation does not support non-volatile
* memory storage. Therefore, the state and frame counters cannot be restored after
* a power cycle. However, if you use the `disconnect()` API to shut down the LoRaWAN
* protocol, the state and frame counters are saved. Connecting again would try to
* restore the previous session. According to the LoRaWAN 1.0.2 specification, the frame counters are always reset
* to zero for OTAA and a new Join request lets the network server know
* that the counters need a reset. The same is said about the ABP but there
* is no way to convey this information to the network server. For a network
* server, an ABP device is always connected. That's why storing the frame counters
* is important, at least for ABP. That's why we try to restore frame counters from
* session information after a disconnection.
*
* @return LORAWAN_STATUS_OK or LORAWAN_STATUS_CONNECT_IN_PROGRESS
* on success, or a negative error code on failure.
*/
lorawan_status_t connect();
/** Connect OTAA or ABP with parameters
*
* All connection parameters are chosen by the user and provided in the
* data structure passed down.
*
* When connecting via OTAA, the return code for success (LORAWAN_STATUS_CONNECT_IN_PROGRESS) is negative.
* However, this is not a real error. It tells you that connection is in progress and you will
* be notified of completion via an event. By default, after Join Accept message
* is received, base stations may provide the node with a CF-List which replaces
* all user-configured channels except the Join/Default channels. A CF-List can
* configure a maximum of five channels other than the default channels.
*
* In case of ABP, the CONNECTED event is posted before the call to `connect()` returns.
* To configure more channels, we recommend that you use the `set_channel_plan()` API after the connection.
* By default, the PHY layers configure only the mandatory Join
* channels. The retransmission back-off restrictions on these channels
* are severe and you may experience long delays or even
* failures in the confirmed traffic. If you add more channels, the aggregated duty
* cycle becomes much more relaxed as compared to the Join (default) channels only.
*
* **NOTES ON RECONNECTION:**
* Currently, the Mbed OS LoRaWAN implementation does not support non-volatile
* memory storage. Therefore, the state and frame counters cannot be restored after
* a power cycle. However, if you use the `disconnect()` API to shut down the LoRaWAN
* protocol, the state and frame counters are saved. Connecting again would try to
* restore the previous session. According to the LoRaWAN 1.0.2 specification, the frame counters are always reset
* to zero for OTAA and a new Join request lets the network server know
* that the counters need a reset. The same is said about the ABP but there
* is no way to convey this information to the network server. For a network
* server, an ABP device is always connected. That's why storing the frame counters
* is important, at least for ABP. That's why we try to restore frame counters from
* session information after a disconnection.
*
* @param connect Options for an end device connection to the gateway.
*
* @return LORAWAN_STATUS_OK or LORAWAN_STATUS_CONNECT_IN_PROGRESS,
* a negative error code on failure.
*/
lorawan_status_t connect(const lorawan_connect_t &connect);
/** End device initialization.
* @param queue A pointer to an EventQueue passed from the application.
@ -122,8 +162,9 @@ public:
/** Sets all callbacks for the application.
*
* @param callbacks A pointer to the structure carrying callbacks.
* @return LORAWAN_STATUS_OK on success, a negative error code on failure.
*/
void set_lora_callbacks(lorawan_app_callbacks_t *callbacks);
lorawan_status_t set_lora_callbacks(lorawan_app_callbacks_t *callbacks);
/** Adds channels to use.
*
@ -209,39 +250,6 @@ public:
*/
lorawan_status_t enable_adaptive_datarate(bool adr_enabled);
/** Commissions a LoRa device.
*
* @param commission_data A structure representing all the commission
* information.
*/
void commission_device(const lorawan_dev_commission_t &commission_data);
/** 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.
*/
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);
/** Send message to gateway
*
* @param port The application port number. Port numbers 0 and 224
@ -337,6 +345,13 @@ public:
*/
lorawan_status_t set_link_check_request();
/** Removes link check request sticky MAC command.
*
* Any already queued request may still get entertained. However, no new
* requests will be made.
*/
void remove_link_check_request();
/** Shuts down the LoRaWAN protocol.
*
* In response to the user call for disconnection, the stack shuts down itself.
@ -356,17 +371,8 @@ private:
/**
* State machine for stack controller layer.
* Needs to be wriggled for every state change
*/
lorawan_status_t lora_state_machine();
/**
* Sets the current state of the device.
* Every call to set_device_state() should precede with
* a call to lora_state_machine() in order to take the state change
* in effect.
*/
void set_device_state(device_states_t new_state);
lorawan_status_t lora_state_machine(device_states_t new_state);
/**
* Hands over the packet to Mac layer by posting an MCPS request.
@ -380,13 +386,6 @@ private:
*/
void mlme_indication_handler(loramac_mlme_indication_t *mlmeIndication);
/**
* Handles an MLME request coming from the upper layers and delegates
* it to the Mac layer, for example, a Join request goes as an MLME request
* to the Mac layer.
*/
lorawan_status_t mlme_request_handler(loramac_mlme_req_t *mlme_request);
/**
* Handles an MLME confirmation coming from the Mac layer and uses it to
* update the state for example, a Join Accept triggers an MLME confirmation,
@ -442,6 +441,32 @@ private:
*/
uint16_t check_possible_tx_size(uint16_t size);
/** 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.
*/
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);
private:
LoRaWANTimeHandler _lora_time;
@ -451,13 +476,13 @@ private:
device_states_t _device_current_state;
lorawan_app_callbacks_t _callbacks;
radio_events_t *_mac_handlers;
lorawan_session_t _lw_session;
loramac_tx_message_t _tx_msg;
loramac_rx_message_t _rx_msg;
uint8_t _num_retry;
uint8_t _app_port;
bool _duty_cycle_on;
bool _link_check_requested;
events::EventQueue *_queue;
#if defined(LORAWAN_COMPLIANCE_TEST)

View File

@ -1582,6 +1582,8 @@ lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel)
lorawan_status_t LoRaMac::initialize(loramac_primitives_t *primitives,
LoRaPHY *phy, EventQueue *queue)
{
_lora_time.activate_timer_subsystem(queue);
//store event queue pointer
ev_queue = queue;
@ -1649,6 +1651,16 @@ 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;
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);
return LORAWAN_STATUS_OK;
}

View File

@ -0,0 +1,58 @@
/**
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LORAPHY_TARGET
#define LORAPHY_TARGET
#ifdef MBED_CONF_LORA_PHY
#if MBED_CONF_LORA_PHY == 0
#include "lorawan/lorastack/phy/LoRaPHYEU868.h"
#define LoRaPHY_region LoRaPHYEU868
#elif MBED_CONF_LORA_PHY == 1
#include "lorawan/lorastack/phy/LoRaPHYAS923.h"
#define LoRaPHY_region LoRaPHYAS923
#elif MBED_CONF_LORA_PHY == 2
#include "lorawan/lorastack/phy/LoRaPHYAU915.h"
#define LoRaPHY_region LoRaPHYAU915;
#elif MBED_CONF_LORA_PHY == 3
#include "lorawan/lorastack/phy/LoRaPHYCN470.h"
#define LoRaPHY_region LoRaPHYCN470
#elif MBED_CONF_LORA_PHY == 4
#include "lorawan/lorastack/phy/LoRaPHYCN779.h"
#define LoRaPHY_region LoRaPHYCN779
#elif MBED_CONF_LORA_PHY == 5
#include "lorawan/lorastack/phy/LoRaPHYEU433.h"
#define LoRaPHY_region LoRaPHYEU433
#elif MBED_CONF_LORA_PHY == 6
#include "lorawan/lorastack/phy/LoRaPHYIN865.h"
#define LoRaPHY_region LoRaPHYIN865
#elif MBED_CONF_LORA_PHY == 7
#include "lorawan/lorastack/phy/LoRaPHYKR920.h"
#define LoRaPHY_region LoRaPHYKR920
#elif MBED_CONF_LORA_PHY == 8
#include "lorawan/lorastack/phy/LoRaPHYUS915.h"
#define LoRaPHY_region LoRaPHYUS915
#elif MBED_CONF_LORA_PHY == 9
#include "lorawan/lorastack/phy/LoRaPHYUS915Hybrid.h"
#define LoRaPHY_region LoRaPHYUS915Hybrid
#endif //MBED_CONF_LORA_PHY == VALUE
#else
#error "Must set LoRa PHY layer parameters."
#endif //MBED_CONF_LORA_PHY
#endif // LORAPHY_TARGET

View File

@ -1839,30 +1839,6 @@ typedef struct lorawan_session {
uint32_t downlink_counter;
} lorawan_session_t;
/** Commissioning data
*
* A structure for data in commission.
*/
typedef struct {
/** Connection information
*
* Saves information for etc. keys
*/
lorawan_connect_t connection;
/**
* LoRaWAN Up-link counter
*
* Related MIB type: LORA_MIB_UPLINK_COUNTER
*/
uint32_t uplink_counter;
/**
* LoRaWAN Down-link counter
*
* Related MIB type: LORA_MIB_DOWNLINK_COUNTER
*/
uint32_t downlink_counter;
} lorawan_dev_commission_t;
/** Structure containing the uplink status
*
*/