mirror of https://github.com/ARMmbed/mbed-os.git
Rejoin logic added
BE to LE fixes, missing MLME types added LoRaWAN 1.1 Features added (Some LoRaPhy impl missing still + some TODOs in code) - MLME confirm handling refactored - Rejoin handling missing - new CF_LIST mechanism missing (+resets involved) - NVM handling missing Rejoin logic addedfeature-lorawan-1-1
parent
0d3283e3a0
commit
ccc3675a6a
|
@ -79,7 +79,15 @@ LoRaWANStack::LoRaWANStack()
|
||||||
_device_mode_ind_ongoing(false),
|
_device_mode_ind_ongoing(false),
|
||||||
_new_class_type(CLASS_A),
|
_new_class_type(CLASS_A),
|
||||||
_automatic_uplink_ongoing(false),
|
_automatic_uplink_ongoing(false),
|
||||||
_queue(NULL)
|
_queue(NULL),
|
||||||
|
_rejoin_type1_send_period(MBED_CONF_LORA_REJOIN_TYPE1_SEND_PERIOD),
|
||||||
|
_rejoin_type1_stamp(0),
|
||||||
|
_rejoin_type0_counter(0),
|
||||||
|
_forced_datarate(DR_0),
|
||||||
|
_forced_period(0),
|
||||||
|
_forced_retry_count(0),
|
||||||
|
_forced_rejoin_type(REJOIN_REQUEST_TYPE0),
|
||||||
|
_forced_counter(0)
|
||||||
{
|
{
|
||||||
_tx_metadata.stale = true;
|
_tx_metadata.stale = true;
|
||||||
_rx_metadata.stale = true;
|
_rx_metadata.stale = true;
|
||||||
|
@ -768,6 +776,8 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size
|
||||||
_ctrl_flags &= ~TX_DONE_FLAG;
|
_ctrl_flags &= ~TX_DONE_FLAG;
|
||||||
_ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
|
_ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
|
||||||
|
|
||||||
|
_rejoin_type0_counter++;
|
||||||
|
|
||||||
_loramac.on_radio_rx_done(payload, size, rssi, snr, callback(this, &LoRaWANStack::mlme_confirm_handler));
|
_loramac.on_radio_rx_done(payload, size, rssi, snr, callback(this, &LoRaWANStack::mlme_confirm_handler));
|
||||||
|
|
||||||
if (_loramac.get_mlme_confirmation()->pending) {
|
if (_loramac.get_mlme_confirmation()->pending) {
|
||||||
|
@ -811,12 +821,26 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size
|
||||||
mlme_indication_handler();
|
mlme_indication_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (((_loramac.get_lora_time()->get_current_time()/1000) -
|
||||||
|
_rejoin_type1_stamp) > _rejoin_type1_send_period) {
|
||||||
|
_rejoin_type1_stamp = _loramac.get_lora_time()->get_current_time()/1000;
|
||||||
|
process_rejoin(REJOIN_REQUEST_TYPE1, false);
|
||||||
|
}
|
||||||
|
uint32_t max_time;
|
||||||
|
uint32_t max_count;
|
||||||
|
_loramac.get_rejoin_parameters(max_time, max_count);
|
||||||
|
if (_rejoin_type0_counter >= max_count) {
|
||||||
|
//This causes excactly same handling as a timeout
|
||||||
|
process_rejoin_type0();
|
||||||
|
}
|
||||||
|
|
||||||
core_util_atomic_flag_clear(&_rx_payload_in_use);
|
core_util_atomic_flag_clear(&_rx_payload_in_use);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaWANStack::process_reception_timeout(bool is_timeout)
|
void LoRaWANStack::process_reception_timeout(bool is_timeout)
|
||||||
{
|
{
|
||||||
rx_slot_t slot = _loramac.get_current_slot();
|
rx_slot_t slot = _loramac.get_current_slot();
|
||||||
|
_rejoin_type0_counter++;
|
||||||
|
|
||||||
// when is_timeout == false, a CRC error took place in the received frame
|
// when is_timeout == false, a CRC error took place in the received frame
|
||||||
// we treat that erroneous frame as no frame received at all, hence handle
|
// we treat that erroneous frame as no frame received at all, hence handle
|
||||||
|
@ -841,6 +865,24 @@ void LoRaWANStack::process_reception_timeout(bool is_timeout)
|
||||||
*/
|
*/
|
||||||
if (slot == RX_SLOT_WIN_2) {
|
if (slot == RX_SLOT_WIN_2) {
|
||||||
post_process_tx_no_reception();
|
post_process_tx_no_reception();
|
||||||
|
_loramac.post_process_mcps_req();
|
||||||
|
|
||||||
|
state_controller(DEVICE_STATE_STATUS_CHECK);
|
||||||
|
state_machine_run_to_completion();
|
||||||
|
|
||||||
|
if ((_loramac.get_lora_time()->get_current_time()/1000) -
|
||||||
|
_rejoin_type1_stamp > _rejoin_type1_send_period) {
|
||||||
|
_rejoin_type1_stamp = _loramac.get_lora_time()->get_current_time()/1000;
|
||||||
|
process_rejoin(REJOIN_REQUEST_TYPE1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t max_time;
|
||||||
|
uint32_t max_count;
|
||||||
|
_loramac.get_rejoin_parameters(max_time, max_count);
|
||||||
|
if (_rejoin_type0_counter >= max_count) {
|
||||||
|
//This causes excactly same handling as a timeout
|
||||||
|
process_rejoin_type0();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1043,6 +1085,13 @@ void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t& mlme_confirm)
|
||||||
if (_loramac.get_server_type() == LW1_1) {
|
if (_loramac.get_server_type() == LW1_1) {
|
||||||
_rekey_ind_needed = true;
|
_rekey_ind_needed = true;
|
||||||
_rekey_ind_counter = 0;
|
_rekey_ind_counter = 0;
|
||||||
|
// THIS IS NOT ALLOWED HERE!
|
||||||
|
// We might get JOIN_ACCEPT for rejoin type 1,
|
||||||
|
// which points to different server!
|
||||||
|
//reset_forced_rejoin();
|
||||||
|
} else {
|
||||||
|
_loramac.get_lora_time()->stop(_forced_timer);
|
||||||
|
_loramac.get_lora_time()->stop(_rejoin_type0_timer);
|
||||||
}
|
}
|
||||||
state_controller(DEVICE_STATE_CONNECTED);
|
state_controller(DEVICE_STATE_CONNECTED);
|
||||||
break;
|
break;
|
||||||
|
@ -1059,7 +1108,25 @@ void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t& mlme_confirm)
|
||||||
state_controller(DEVICE_STATE_JOINING);
|
state_controller(DEVICE_STATE_JOINING);
|
||||||
}
|
}
|
||||||
} else if (mlme_confirm.type == MLME_FORCE_REJOIN) {
|
} else if (mlme_confirm.type == MLME_FORCE_REJOIN) {
|
||||||
//TODO: handle this
|
if (join_req_type_t(mlme_confirm.rejoin_type) <= REJOIN_REQUEST_TYPE2 &&
|
||||||
|
_loramac.get_server_type() == LW1_1 ) {
|
||||||
|
_forced_datarate = mlme_confirm.datarate;
|
||||||
|
_forced_period = ((1 << mlme_confirm.period)*32 + (rand()%33))*1000;
|
||||||
|
_forced_retry_count = mlme_confirm.max_retries;
|
||||||
|
if (_forced_retry_count) {
|
||||||
|
_forced_retry_count += 1;
|
||||||
|
}
|
||||||
|
_forced_rejoin_type = join_req_type_t(mlme_confirm.rejoin_type);
|
||||||
|
// See LW 1.1 chapter 5.13 - RejoinType
|
||||||
|
if (join_req_type_t(mlme_confirm.rejoin_type) == REJOIN_REQUEST_TYPE1) {
|
||||||
|
_forced_rejoin_type = REJOIN_REQUEST_TYPE0;
|
||||||
|
}
|
||||||
|
reset_forced_rejoin();
|
||||||
|
process_rejoin(_forced_rejoin_type, true);
|
||||||
|
if (_forced_retry_count) {
|
||||||
|
_loramac.get_lora_time()->start(_forced_timer, _forced_period);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1341,4 +1408,61 @@ void LoRaWANStack::process_uninitialized_state(lorawan_status_t &op_status)
|
||||||
if (op_status == LORAWAN_STATUS_OK) {
|
if (op_status == LORAWAN_STATUS_OK) {
|
||||||
_device_current_state = DEVICE_STATE_IDLE;
|
_device_current_state = DEVICE_STATE_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MBED_CONF_LORA_VERSION == LORAWAN_VERSION_1_1) {
|
||||||
|
_loramac.get_lora_time()->init(_forced_timer,
|
||||||
|
mbed::callback(this, &LoRaWANStack::forced_timer_expiry));
|
||||||
|
|
||||||
|
_loramac.get_lora_time()->init(_rejoin_type0_timer,
|
||||||
|
mbed::callback(this, &LoRaWANStack::process_rejoin_type0));
|
||||||
|
|
||||||
|
_rejoin_type1_stamp = _loramac.get_lora_time()->get_current_time()/1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoRaWANStack::process_rejoin(join_req_type_t rejoin_type, bool is_forced)
|
||||||
|
{
|
||||||
|
if (_loramac.get_server_type() == LW1_1 ) {
|
||||||
|
_loramac.rejoin(rejoin_type, is_forced, _forced_datarate);
|
||||||
|
if (rejoin_type == REJOIN_REQUEST_TYPE0) {
|
||||||
|
_loramac.get_lora_time()->stop(_rejoin_type0_timer);
|
||||||
|
_rejoin_type0_counter = 0;
|
||||||
|
uint32_t max_time;
|
||||||
|
uint32_t max_count;
|
||||||
|
_loramac.get_rejoin_parameters(max_time, max_count);
|
||||||
|
_loramac.get_lora_time()->start(_rejoin_type0_timer, max_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoRaWANStack::reset_forced_rejoin()
|
||||||
|
{
|
||||||
|
_forced_counter = 0;
|
||||||
|
_loramac.get_lora_time()->stop(_forced_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoRaWANStack::forced_timer_expiry()
|
||||||
|
{
|
||||||
|
if (_loramac.get_server_type() == LW1_1 ) {
|
||||||
|
if (_forced_counter < _forced_retry_count) {
|
||||||
|
process_rejoin(_forced_rejoin_type, true);
|
||||||
|
_loramac.get_lora_time()->start(_forced_timer, _forced_period);
|
||||||
|
} else {
|
||||||
|
reset_forced_rejoin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoRaWANStack::process_rejoin_type0()
|
||||||
|
{
|
||||||
|
if (_loramac.get_server_type() == LW1_1 ) {
|
||||||
|
//stop in case counter was exceeded
|
||||||
|
_loramac.get_lora_time()->stop(_rejoin_type0_timer);
|
||||||
|
_rejoin_type0_counter = 0;
|
||||||
|
process_rejoin(REJOIN_REQUEST_TYPE0, false);
|
||||||
|
uint32_t max_time;
|
||||||
|
uint32_t max_count;
|
||||||
|
_loramac.get_rejoin_parameters(max_time, max_count);
|
||||||
|
_loramac.get_lora_time()->start(_rejoin_type0_timer, max_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -513,8 +513,17 @@ private:
|
||||||
void post_process_tx_with_reception(void);
|
void post_process_tx_with_reception(void);
|
||||||
void post_process_tx_no_reception(void);
|
void post_process_tx_no_reception(void);
|
||||||
|
|
||||||
|
void process_rejoin(join_req_type_t rejoin_type, bool is_forced);
|
||||||
|
void reset_forced_rejoin();
|
||||||
|
|
||||||
|
void forced_timer_expiry();
|
||||||
|
void process_rejoin_type0();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LoRaMac _loramac;
|
LoRaMac _loramac;
|
||||||
|
|
||||||
|
LoRaWANTimeHandler _lora_time;
|
||||||
|
|
||||||
radio_events_t radio_events;
|
radio_events_t radio_events;
|
||||||
device_states_t _device_current_state;
|
device_states_t _device_current_state;
|
||||||
lorawan_app_callbacks_t _callbacks;
|
lorawan_app_callbacks_t _callbacks;
|
||||||
|
@ -539,6 +548,17 @@ private:
|
||||||
uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD];
|
uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD];
|
||||||
events::EventQueue *_queue;
|
events::EventQueue *_queue;
|
||||||
lorawan_time_t _tx_timestamp;
|
lorawan_time_t _tx_timestamp;
|
||||||
|
uint32_t _rejoin_type1_send_period;
|
||||||
|
uint32_t _rejoin_type1_stamp;
|
||||||
|
timer_event_t _rejoin_type0_timer;
|
||||||
|
uint32_t _rejoin_type0_counter;
|
||||||
|
|
||||||
|
uint8_t _forced_datarate;
|
||||||
|
uint32_t _forced_period;
|
||||||
|
uint8_t _forced_retry_count;
|
||||||
|
join_req_type_t _forced_rejoin_type;
|
||||||
|
uint8_t _forced_counter;
|
||||||
|
timer_event_t _forced_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* LORAWANSTACK_H_ */
|
#endif /* LORAWANSTACK_H_ */
|
||||||
|
|
|
@ -66,6 +66,16 @@ using namespace mbed;
|
||||||
*/
|
*/
|
||||||
#define DOWN_LINK 1
|
#define DOWN_LINK 1
|
||||||
|
|
||||||
|
static void memcpy_convert_endianess(uint8_t *dst,
|
||||||
|
const uint8_t *src,
|
||||||
|
uint16_t size)
|
||||||
|
{
|
||||||
|
dst = dst + (size - 1);
|
||||||
|
while (size--) {
|
||||||
|
*dst-- = *src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LoRaMac::LoRaMac()
|
LoRaMac::LoRaMac()
|
||||||
: _lora_time(),
|
: _lora_time(),
|
||||||
_lora_phy(NULL),
|
_lora_phy(NULL),
|
||||||
|
@ -86,6 +96,8 @@ LoRaMac::LoRaMac()
|
||||||
_prev_qos_level(LORAWAN_DEFAULT_QOS),
|
_prev_qos_level(LORAWAN_DEFAULT_QOS),
|
||||||
_demod_ongoing(false)
|
_demod_ongoing(false)
|
||||||
{
|
{
|
||||||
|
_params.rejoin_forced = false;
|
||||||
|
_params.forced_datarate = DR_0;
|
||||||
_params.is_rx_window_enabled = true;
|
_params.is_rx_window_enabled = true;
|
||||||
_params.max_ack_timeout_retries = 1;
|
_params.max_ack_timeout_retries = 1;
|
||||||
_params.ack_timeout_retry_counter = 1;
|
_params.ack_timeout_retry_counter = 1;
|
||||||
|
@ -118,11 +130,6 @@ const loramac_mcps_indication_t *LoRaMac::get_mcps_indication() const
|
||||||
return &_mcps_indication;
|
return &_mcps_indication;
|
||||||
}
|
}
|
||||||
|
|
||||||
const loramac_mlme_confirm_t *LoRaMac::get_mlme_confirmation() const
|
|
||||||
{
|
|
||||||
return &_mlme_confirmation;
|
|
||||||
}
|
|
||||||
|
|
||||||
const loramac_mlme_indication_t *LoRaMac::get_mlme_indication() const
|
const loramac_mlme_indication_t *LoRaMac::get_mlme_indication() const
|
||||||
{
|
{
|
||||||
return &_mlme_indication;
|
return &_mlme_indication;
|
||||||
|
@ -184,18 +191,7 @@ loramac_event_info_status_t LoRaMac::handle_join_accept_frame(const uint8_t *pay
|
||||||
uint32_t mic_rx = 0;
|
uint32_t mic_rx = 0;
|
||||||
server_type_t stype = LW1_0_2;
|
server_type_t stype = LW1_0_2;
|
||||||
|
|
||||||
//Store server type to local so that invalid join accept of rejoin request won't affect the orig. type.
|
|
||||||
if ( (((_params.rx_buffer[11] >> 7) & 0x01) == 1) && MBED_CONF_LORA_VERSION == LORAWAN_VERSION_1_1) {
|
|
||||||
stype = LW1_1;
|
|
||||||
} else {
|
|
||||||
stype = LW1_0_2;
|
|
||||||
//Server does not support LW 1.1 so we need to unset JS keys
|
|
||||||
memcpy(_params.keys.js_intkey, _params.keys.nwk_key, sizeof(_params.keys.nwk_skey));
|
|
||||||
memcpy(_params.keys.js_enckey, _params.keys.nwk_key, sizeof(_params.keys.nwk_skey));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *decrypt_key = NULL;
|
uint8_t *decrypt_key = NULL;
|
||||||
uint8_t *mic_key = _params.keys.js_intkey; //in case of LW1.0.2 js_intkey == nwk_key == app_key
|
|
||||||
|
|
||||||
if (_params.join_request_type == JOIN_REQUEST) {
|
if (_params.join_request_type == JOIN_REQUEST) {
|
||||||
decrypt_key = _params.keys.nwk_key;
|
decrypt_key = _params.keys.nwk_key;
|
||||||
|
@ -203,6 +199,13 @@ loramac_event_info_status_t LoRaMac::handle_join_accept_frame(const uint8_t *pay
|
||||||
decrypt_key = _params.keys.js_enckey;
|
decrypt_key = _params.keys.js_enckey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 != _lora_crypto.decrypt_join_frame(payload + 1, size - 1,
|
||||||
|
decrypt_key, APPKEY_KEY_LENGTH,
|
||||||
|
_params.rx_buffer + 1)) {
|
||||||
|
return LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL;
|
||||||
|
}
|
||||||
|
_params.rx_buffer[0] = payload[0];
|
||||||
|
|
||||||
//Store server type to local so that invalid join accept of rejoin request won't affect the orig. type.
|
//Store server type to local so that invalid join accept of rejoin request won't affect the orig. type.
|
||||||
if ( (((_params.rx_buffer[11] >> 7) & 0x01) == 1) && MBED_CONF_LORA_VERSION == LORAWAN_VERSION_1_1) {
|
if ( (((_params.rx_buffer[11] >> 7) & 0x01) == 1) && MBED_CONF_LORA_VERSION == LORAWAN_VERSION_1_1) {
|
||||||
stype = LW1_1;
|
stype = LW1_1;
|
||||||
|
@ -213,18 +216,14 @@ loramac_event_info_status_t LoRaMac::handle_join_accept_frame(const uint8_t *pay
|
||||||
memcpy(_params.keys.js_enckey, _params.keys.nwk_key, sizeof(_params.keys.nwk_skey));
|
memcpy(_params.keys.js_enckey, _params.keys.nwk_key, sizeof(_params.keys.nwk_skey));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != _lora_crypto.decrypt_join_frame(payload + 1, size - 1,
|
|
||||||
decrypt_key, APPKEY_KEY_LENGTH,
|
|
||||||
_params.rx_buffer + 1)) {
|
|
||||||
return LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t payload_start = 1;
|
uint8_t payload_start = 1;
|
||||||
uint8_t mic_start = 0;
|
uint8_t mic_start = 0;
|
||||||
uint8_t args_size = 0;
|
uint8_t args_size = 0;
|
||||||
uint8_t args[16];
|
uint8_t args[16];
|
||||||
|
|
||||||
|
uint8_t *mic_key = _params.keys.js_intkey; //in case of LW1.0.2 js_intkey == nwk_key == app_key
|
||||||
|
|
||||||
if (stype == LW1_0_2) {
|
if (stype == LW1_0_2) {
|
||||||
_params.rx_buffer[0] = payload[0];
|
|
||||||
mic_start = size - LORAMAC_MFR_LEN;
|
mic_start = size - LORAMAC_MFR_LEN;
|
||||||
|
|
||||||
memcpy(args, _params.rx_buffer + 1, 6);
|
memcpy(args, _params.rx_buffer + 1, 6);
|
||||||
|
@ -232,16 +231,20 @@ loramac_event_info_status_t LoRaMac::handle_join_accept_frame(const uint8_t *pay
|
||||||
args_size = 8;
|
args_size = 8;
|
||||||
} else {
|
} else {
|
||||||
//MIC calculation needs more params, so we move the payload a bit
|
//MIC calculation needs more params, so we move the payload a bit
|
||||||
_params.rx_buffer[0] = (uint8_t)_params.join_request_type;
|
memmove(_params.rx_buffer + 11, _params.rx_buffer, size);
|
||||||
memcpy(_params.rx_buffer + 11, _params.rx_buffer, size - LORAMAC_MFR_LEN);
|
_params.rx_buffer[0] = _params.join_request_type; // JoinReqType
|
||||||
memcpy(_params.rx_buffer + 1, _params.keys.app_eui, 8);
|
memcpy_convert_endianess(_params.rx_buffer + 1, _params.keys.app_eui, 8); // JoinEUI
|
||||||
memcpy(_params.rx_buffer + 9, (uint8_t *) &_params.dev_nonce, 2);
|
_params.rx_buffer[9] = _params.dev_nonce & 0xFF; // DevNonce
|
||||||
mic_start = size - LORAMAC_MFR_LEN + 11;
|
_params.rx_buffer[10] = (_params.dev_nonce >> 8) & 0xFF;
|
||||||
|
size += 11;
|
||||||
|
|
||||||
|
mic_start = size - LORAMAC_MFR_LEN;
|
||||||
payload_start += 11;
|
payload_start += 11;
|
||||||
|
|
||||||
memcpy(args, _params.rx_buffer + payload_start, 3);
|
memcpy(args, _params.rx_buffer + payload_start, 3);
|
||||||
memcpy(args + 3, _params.keys.app_eui, 8);
|
memcpy_convert_endianess(args + 3, _params.keys.app_eui, 8);
|
||||||
memcpy(args + 3 + 8, (uint8_t *) &_params.dev_nonce, 2);
|
args[3+8] = _params.dev_nonce & 0xFF;
|
||||||
|
args[3+9] = (_params.dev_nonce >> 8) & 0xFF;
|
||||||
args_size = 13;
|
args_size = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,7 +746,6 @@ void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK;
|
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK;
|
||||||
_mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_params.last_channel_idx = _params.channel;
|
_params.last_channel_idx = _params.channel;
|
||||||
|
@ -826,7 +828,6 @@ void LoRaMac::on_radio_tx_timeout(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
|
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
|
||||||
_mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
|
|
||||||
|
|
||||||
_mac_commands.clear_command_buffer();
|
_mac_commands.clear_command_buffer();
|
||||||
|
|
||||||
|
@ -849,14 +850,8 @@ void LoRaMac::on_radio_rx_timeout(bool is_timeout)
|
||||||
|
|
||||||
if (_params.rx_slot == RX_SLOT_WIN_1) {
|
if (_params.rx_slot == RX_SLOT_WIN_1) {
|
||||||
if (_params.is_node_ack_requested == true) {
|
if (_params.is_node_ack_requested == true) {
|
||||||
_mcps_confirmation.status = is_timeout ?
|
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT :
|
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
|
|
||||||
}
|
}
|
||||||
_mlme_confirmation.status = is_timeout ?
|
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT :
|
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
|
|
||||||
|
|
||||||
if (_device_class != CLASS_C) {
|
if (_device_class != CLASS_C) {
|
||||||
if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) {
|
if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) {
|
||||||
_lora_time.stop(_params.timers.rx_window2_timer);
|
_lora_time.stop(_params.timers.rx_window2_timer);
|
||||||
|
@ -864,14 +859,8 @@ void LoRaMac::on_radio_rx_timeout(bool is_timeout)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_params.is_node_ack_requested == true) {
|
if (_params.is_node_ack_requested == true) {
|
||||||
_mcps_confirmation.status = is_timeout ?
|
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT :
|
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_mlme_confirmation.status = is_timeout ?
|
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT :
|
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1574,7 +1563,10 @@ lorawan_status_t LoRaMac::prepare_join(const lorawan_connect_t *params, bool is_
|
||||||
_params.keys.nwk_key = params->connection_u.otaa.app_key;
|
_params.keys.nwk_key = params->connection_u.otaa.app_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != _lora_crypto.compute_join_server_keys(_params.keys.nwk_key, APPKEY_KEY_LENGTH, _params.keys.dev_eui,
|
uint8_t converted_eui[8];
|
||||||
|
memcpy_convert_endianess(converted_eui, _params.keys.dev_eui, 8);
|
||||||
|
|
||||||
|
if (0 != _lora_crypto.compute_join_server_keys(_params.keys.nwk_key, APPKEY_KEY_LENGTH, converted_eui,
|
||||||
_params.keys.js_intkey, _params.keys.js_enckey)) {
|
_params.keys.js_intkey, _params.keys.js_enckey)) {
|
||||||
return LORAWAN_STATUS_CRYPTO_FAIL;
|
return LORAWAN_STATUS_CRYPTO_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -1649,7 +1641,10 @@ lorawan_status_t LoRaMac::prepare_join(const lorawan_connect_t *params, bool is_
|
||||||
_params.keys.nwk_key = _params.keys.app_key;
|
_params.keys.nwk_key = _params.keys.app_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != _lora_crypto.compute_join_server_keys(_params.keys.nwk_key, APPKEY_KEY_LENGTH, _params.keys.dev_eui,
|
uint8_t converted_eui[8];
|
||||||
|
memcpy_convert_endianess(converted_eui, _params.keys.dev_eui, 8);
|
||||||
|
|
||||||
|
if (0 != _lora_crypto.compute_join_server_keys(_params.keys.nwk_key, APPKEY_KEY_LENGTH, converted_eui,
|
||||||
_params.keys.js_intkey, _params.keys.js_enckey)) {
|
_params.keys.js_intkey, _params.keys.js_enckey)) {
|
||||||
return LORAWAN_STATUS_CRYPTO_FAIL;
|
return LORAWAN_STATUS_CRYPTO_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -1700,23 +1695,15 @@ lorawan_status_t LoRaMac::join(bool is_otaa)
|
||||||
return send_join_request();
|
return send_join_request();
|
||||||
}
|
}
|
||||||
|
|
||||||
lorawan_status_t LoRaMac::rejoin(join_req_type_t rejoin_type)
|
lorawan_status_t LoRaMac::rejoin(join_req_type_t rejoin_type, bool is_forced, uint8_t datarate)
|
||||||
{
|
{
|
||||||
_params.join_request_type = rejoin_type;
|
_params.join_request_type = rejoin_type;
|
||||||
|
_params.rejoin_forced = is_forced;
|
||||||
|
_params.forced_datarate = datarate;
|
||||||
|
|
||||||
return send_join_request();
|
return send_join_request();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void memcpy_convert_endianess(uint8_t *dst,
|
|
||||||
const uint8_t *src,
|
|
||||||
uint16_t size)
|
|
||||||
{
|
|
||||||
dst = dst + (size - 1);
|
|
||||||
while (size--) {
|
|
||||||
*dst-- = *src++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr,
|
lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr,
|
||||||
loramac_frame_ctrl_t *fctrl,
|
loramac_frame_ctrl_t *fctrl,
|
||||||
const uint8_t fport,
|
const uint8_t fport,
|
||||||
|
@ -1970,7 +1957,11 @@ lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel)
|
||||||
int8_t tx_power = 0;
|
int8_t tx_power = 0;
|
||||||
|
|
||||||
tx_config.channel = channel;
|
tx_config.channel = channel;
|
||||||
tx_config.datarate = _params.sys_params.channel_data_rate;
|
if (_params.rejoin_forced) {
|
||||||
|
tx_config.datarate = _params.forced_datarate;
|
||||||
|
} else {
|
||||||
|
tx_config.datarate = _params.sys_params.channel_data_rate;
|
||||||
|
}
|
||||||
tx_config.tx_power = _params.sys_params.channel_tx_power;
|
tx_config.tx_power = _params.sys_params.channel_tx_power;
|
||||||
tx_config.max_eirp = _params.sys_params.max_eirp;
|
tx_config.max_eirp = _params.sys_params.max_eirp;
|
||||||
tx_config.antenna_gain = _params.sys_params.antenna_gain;
|
tx_config.antenna_gain = _params.sys_params.antenna_gain;
|
||||||
|
@ -1978,8 +1969,6 @@ lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel)
|
||||||
|
|
||||||
_lora_phy->tx_config(&tx_config, &tx_power, &_params.timers.tx_toa);
|
_lora_phy->tx_config(&tx_config, &tx_power, &_params.timers.tx_toa);
|
||||||
|
|
||||||
_mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
|
||||||
|
|
||||||
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
||||||
_mcps_confirmation.data_rate = _params.sys_params.channel_data_rate;
|
_mcps_confirmation.data_rate = _params.sys_params.channel_data_rate;
|
||||||
_mcps_confirmation.tx_power = tx_power;
|
_mcps_confirmation.tx_power = tx_power;
|
||||||
|
@ -2008,6 +1997,11 @@ void LoRaMac::reset_mcps_indication()
|
||||||
_mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
_mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoRaWANTimeHandler *LoRaMac::get_lora_time()
|
||||||
|
{
|
||||||
|
return &_lora_time;
|
||||||
|
}
|
||||||
|
|
||||||
lorawan_status_t LoRaMac::initialize(EventQueue *queue,
|
lorawan_status_t LoRaMac::initialize(EventQueue *queue,
|
||||||
mbed::Callback<void(void)>scheduling_failure_handler)
|
mbed::Callback<void(void)>scheduling_failure_handler)
|
||||||
{
|
{
|
||||||
|
@ -2233,3 +2227,9 @@ uint8_t LoRaMac::get_current_adr_ack_limit()
|
||||||
{
|
{
|
||||||
return _lora_phy->get_adr_ack_limit();
|
return _lora_phy->get_adr_ack_limit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoRaMac::get_rejoin_parameters(uint32_t& max_time, uint32_t& max_count)
|
||||||
|
{
|
||||||
|
max_time = _lora_phy->get_rejoin_max_time();
|
||||||
|
max_count = _lora_phy->get_rejoin_max_count();
|
||||||
|
}
|
||||||
|
|
|
@ -196,6 +196,13 @@ public:
|
||||||
*/
|
*/
|
||||||
lorawan_status_t multicast_channel_unlink(multicast_params_t *channel_param);
|
lorawan_status_t multicast_channel_unlink(multicast_params_t *channel_param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get_rejoin_parameters Gets current rejoin parameters
|
||||||
|
* @param max_time Current rejoin max time
|
||||||
|
* @param max_count Current rejoin max count
|
||||||
|
*/
|
||||||
|
void get_rejoin_parameters(uint32_t& max_time, uint32_t& max_count);
|
||||||
|
|
||||||
/** Binds phy layer to MAC.
|
/** Binds phy layer to MAC.
|
||||||
*
|
*
|
||||||
* @param phy LoRaPHY object
|
* @param phy LoRaPHY object
|
||||||
|
@ -353,9 +360,11 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief rejoin Rejoins the network
|
* @brief rejoin Rejoins the network
|
||||||
* @param rejoin_type Rejoin type indicates the rejoin message payload
|
* @param rejoin_type Rejoin type indicates the rejoin message payload
|
||||||
|
* @param is_forced Indicates if the function was called because of ForceRejoinReq
|
||||||
|
* @param datarate In case of forced rejoin, datarate to be used for Rejoin request
|
||||||
* @return LORAWAN_STATUS_OK or a negative error code on failure.
|
* @return LORAWAN_STATUS_OK or a negative error code on failure.
|
||||||
*/
|
*/
|
||||||
lorawan_status_t rejoin(join_req_type_t rejoin_type);
|
lorawan_status_t rejoin(join_req_type_t rejoin_type, bool is_forced = false, uint8_t datarate = DR_0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MAC operations upon successful transmission
|
* MAC operations upon successful transmission
|
||||||
|
@ -402,7 +411,6 @@ public:
|
||||||
*/
|
*/
|
||||||
const loramac_mcps_confirm_t *get_mcps_confirmation() const;
|
const loramac_mcps_confirm_t *get_mcps_confirmation() const;
|
||||||
const loramac_mcps_indication_t *get_mcps_indication() const;
|
const loramac_mcps_indication_t *get_mcps_indication() const;
|
||||||
const loramac_mlme_confirm_t *get_mlme_confirmation() const;
|
|
||||||
const loramac_mlme_indication_t *get_mlme_indication() const;
|
const loramac_mlme_indication_t *get_mlme_indication() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -470,6 +478,8 @@ public:
|
||||||
void unlock(void) { }
|
void unlock(void) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
LoRaWANTimeHandler *get_lora_time();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Queries the LoRaMAC the maximum possible FRMPayload size to send.
|
* @brief Queries the LoRaMAC the maximum possible FRMPayload size to send.
|
||||||
|
@ -626,7 +636,6 @@ private:
|
||||||
* Resets MAC primitive blocks
|
* Resets MAC primitive blocks
|
||||||
*/
|
*/
|
||||||
void reset_mcps_confirmation(void);
|
void reset_mcps_confirmation(void);
|
||||||
void reset_mlme_confirmation(void);
|
|
||||||
void reset_mcps_indication(void);
|
void reset_mcps_indication(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -143,6 +143,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui
|
||||||
switch (payload[mac_index++]) {
|
switch (payload[mac_index++]) {
|
||||||
case SRV_MAC_RESET_CONF: {
|
case SRV_MAC_RESET_CONF: {
|
||||||
loramac_mlme_confirm_t mlme_conf;
|
loramac_mlme_confirm_t mlme_conf;
|
||||||
|
mlme_conf.type = MLME_RESET;
|
||||||
mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
|
mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
|
||||||
mlme_conf.version = payload[mac_index++] & 0x0F;
|
mlme_conf.version = payload[mac_index++] & 0x0F;
|
||||||
confirm_handler(mlme_conf);
|
confirm_handler(mlme_conf);
|
||||||
|
@ -150,6 +151,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui
|
||||||
break;
|
break;
|
||||||
case SRV_MAC_LINK_CHECK_ANS: {
|
case SRV_MAC_LINK_CHECK_ANS: {
|
||||||
loramac_mlme_confirm_t mlme_conf;
|
loramac_mlme_confirm_t mlme_conf;
|
||||||
|
mlme_conf.type = MLME_LINK_CHECK;
|
||||||
mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
|
mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
|
||||||
mlme_conf.demod_margin = payload[mac_index++];
|
mlme_conf.demod_margin = payload[mac_index++];
|
||||||
mlme_conf.nb_gateways = payload[mac_index++];
|
mlme_conf.nb_gateways = payload[mac_index++];
|
||||||
|
@ -305,6 +307,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui
|
||||||
break;
|
break;
|
||||||
case SRV_MAC_REKEY_CONF: {
|
case SRV_MAC_REKEY_CONF: {
|
||||||
loramac_mlme_confirm_t mlme_conf;
|
loramac_mlme_confirm_t mlme_conf;
|
||||||
|
mlme_conf.type = MLME_REKEY;
|
||||||
mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
|
mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
|
||||||
mlme_conf.version = payload[mac_index++] & 0x0F;
|
mlme_conf.version = payload[mac_index++] & 0x0F;
|
||||||
confirm_handler(mlme_conf);
|
confirm_handler(mlme_conf);
|
||||||
|
|
|
@ -39,6 +39,9 @@ SPDX-License-Identifier: BSD-3-Clause
|
||||||
#define GPS_EPOCH_DIFF_WITH_UTC 315964800
|
#define GPS_EPOCH_DIFF_WITH_UTC 315964800
|
||||||
#define CHANNELS_IN_MASK 16
|
#define CHANNELS_IN_MASK 16
|
||||||
|
|
||||||
|
#define DEVICE_DOES_NOT_SUPPORT_TIME 0
|
||||||
|
#define DEVICE_SUPPORTS_TIME 1
|
||||||
|
|
||||||
LoRaPHY::LoRaPHY()
|
LoRaPHY::LoRaPHY()
|
||||||
: _radio(NULL),
|
: _radio(NULL),
|
||||||
_lora_time(NULL),
|
_lora_time(NULL),
|
||||||
|
@ -690,7 +693,7 @@ uint8_t LoRaPHY::update_rejoin_params(uint32_t max_time, uint32_t max_count)
|
||||||
//These will be taken into use at next rejoin "cycle"
|
//These will be taken into use at next rejoin "cycle"
|
||||||
_rejoin_max_time = max_time;
|
_rejoin_max_time = max_time;
|
||||||
_rejoin_max_count = max_count;
|
_rejoin_max_count = max_count;
|
||||||
return 1;
|
return DEVICE_SUPPORTS_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaPHY::restore_default_channels()
|
void LoRaPHY::restore_default_channels()
|
||||||
|
@ -1513,4 +1516,13 @@ uint8_t LoRaPHY::apply_DR_offset(int8_t dr, int8_t dr_offset)
|
||||||
return datarate;
|
return datarate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t LoRaPHY::get_rejoin_max_time() const
|
||||||
|
{
|
||||||
|
return _rejoin_max_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t LoRaPHY::get_rejoin_max_count() const
|
||||||
|
{
|
||||||
|
return _rejoin_max_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -604,6 +604,18 @@ public: //Verifiers
|
||||||
*/
|
*/
|
||||||
void set_adr_ack_delay(const uint16_t& value);
|
void set_adr_ack_delay(const uint16_t& value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getRejoin_max_time Getter for current rejoin max time
|
||||||
|
* @return Current rejoin max time in seconds
|
||||||
|
*/
|
||||||
|
uint32_t get_rejoin_max_time() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get_rejoin_max_count Getter for current rejoin max count
|
||||||
|
* @return Current rejoin max count
|
||||||
|
*/
|
||||||
|
uint32_t get_rejoin_max_count() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LoRaPHY();
|
LoRaPHY();
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,10 @@
|
||||||
"rejoin-default-max-count": {
|
"rejoin-default-max-count": {
|
||||||
"help": "LW1.1 only! Maximum amount of messages which can be sent between Rejoin requests.",
|
"help": "LW1.1 only! Maximum amount of messages which can be sent between Rejoin requests.",
|
||||||
"value": 1000
|
"value": 1000
|
||||||
|
},
|
||||||
|
"rejoin-type1-send-period": {
|
||||||
|
"help": "Rejoin type 1 sending period. NOTE: Rejoin message will be sent when this period has expired. Default is 1 week",
|
||||||
|
"value": 604800
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -553,14 +553,6 @@ typedef enum {
|
||||||
* A TX timeout occurred.
|
* A TX timeout occurred.
|
||||||
*/
|
*/
|
||||||
LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT,
|
LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT,
|
||||||
/*!
|
|
||||||
* An RX timeout occurred on receive window 1.
|
|
||||||
*/
|
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT,
|
|
||||||
/*!
|
|
||||||
* An RX timeout occurred on receive window 2.
|
|
||||||
*/
|
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT,
|
|
||||||
/*!
|
/*!
|
||||||
* An RX error occurred on receive window 1.
|
* An RX error occurred on receive window 1.
|
||||||
*/
|
*/
|
||||||
|
@ -1458,6 +1450,15 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
multicast_params_t *multicast_channels;
|
multicast_params_t *multicast_channels;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief rejoin_forced Boolean indicating if rejoin is forced. See ForceRejoinReq LW 1.1 spec ch 5.13
|
||||||
|
*/
|
||||||
|
bool rejoin_forced;
|
||||||
|
/*!
|
||||||
|
* \brief forced_datarate See ForceRejoinReq LW 1.1 spec ch 5.13
|
||||||
|
*/
|
||||||
|
uint8_t forced_datarate;
|
||||||
|
|
||||||
} loramac_protocol_params;
|
} loramac_protocol_params;
|
||||||
|
|
||||||
#endif /* LORAWAN_SYSTEM_LORAWAN_DATA_STRUCTURES_H_ */
|
#endif /* LORAWAN_SYSTEM_LORAWAN_DATA_STRUCTURES_H_ */
|
||||||
|
|
Loading…
Reference in New Issue