diff --git a/features/lorawan/LoRaWANStack.cpp b/features/lorawan/LoRaWANStack.cpp index 4045b6c677..299955b117 100644 --- a/features/lorawan/LoRaWANStack.cpp +++ b/features/lorawan/LoRaWANStack.cpp @@ -79,7 +79,15 @@ LoRaWANStack::LoRaWANStack() _device_mode_ind_ongoing(false), _new_class_type(CLASS_A), _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; _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 &= ~RETRY_EXHAUSTED_FLAG; + _rejoin_type0_counter++; + _loramac.on_radio_rx_done(payload, size, rssi, snr, callback(this, &LoRaWANStack::mlme_confirm_handler)); 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(); } + 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); } void LoRaWANStack::process_reception_timeout(bool is_timeout) { rx_slot_t slot = _loramac.get_current_slot(); + _rejoin_type0_counter++; // 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 @@ -841,6 +865,24 @@ void LoRaWANStack::process_reception_timeout(bool is_timeout) */ if (slot == RX_SLOT_WIN_2) { 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) { _rekey_ind_needed = true; _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); break; @@ -1059,7 +1108,25 @@ void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t& mlme_confirm) state_controller(DEVICE_STATE_JOINING); } } 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) { _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); + } } diff --git a/features/lorawan/LoRaWANStack.h b/features/lorawan/LoRaWANStack.h index 45f4e2c7bf..e48856851e 100644 --- a/features/lorawan/LoRaWANStack.h +++ b/features/lorawan/LoRaWANStack.h @@ -513,8 +513,17 @@ private: void post_process_tx_with_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: LoRaMac _loramac; + + LoRaWANTimeHandler _lora_time; + radio_events_t radio_events; device_states_t _device_current_state; lorawan_app_callbacks_t _callbacks; @@ -539,6 +548,17 @@ private: uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD]; events::EventQueue *_queue; 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_ */ diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index b28e738e3f..a6e352498d 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -66,6 +66,16 @@ using namespace mbed; */ #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() : _lora_time(), _lora_phy(NULL), @@ -86,6 +96,8 @@ LoRaMac::LoRaMac() _prev_qos_level(LORAWAN_DEFAULT_QOS), _demod_ongoing(false) { + _params.rejoin_forced = false; + _params.forced_datarate = DR_0; _params.is_rx_window_enabled = true; _params.max_ack_timeout_retries = 1; _params.ack_timeout_retry_counter = 1; @@ -118,11 +130,6 @@ const loramac_mcps_indication_t *LoRaMac::get_mcps_indication() const 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 { 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; 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 *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) { 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; } + 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. if ( (((_params.rx_buffer[11] >> 7) & 0x01) == 1) && MBED_CONF_LORA_VERSION == LORAWAN_VERSION_1_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)); } - 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 mic_start = 0; uint8_t args_size = 0; 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) { - _params.rx_buffer[0] = payload[0]; mic_start = size - LORAMAC_MFR_LEN; 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; } else { //MIC calculation needs more params, so we move the payload a bit - _params.rx_buffer[0] = (uint8_t)_params.join_request_type; - memcpy(_params.rx_buffer + 11, _params.rx_buffer, size - LORAMAC_MFR_LEN); - memcpy(_params.rx_buffer + 1, _params.keys.app_eui, 8); - memcpy(_params.rx_buffer + 9, (uint8_t *) &_params.dev_nonce, 2); - mic_start = size - LORAMAC_MFR_LEN + 11; + memmove(_params.rx_buffer + 11, _params.rx_buffer, size); + _params.rx_buffer[0] = _params.join_request_type; // JoinReqType + memcpy_convert_endianess(_params.rx_buffer + 1, _params.keys.app_eui, 8); // JoinEUI + _params.rx_buffer[9] = _params.dev_nonce & 0xFF; // DevNonce + _params.rx_buffer[10] = (_params.dev_nonce >> 8) & 0xFF; + size += 11; + + mic_start = size - LORAMAC_MFR_LEN; payload_start += 11; memcpy(args, _params.rx_buffer + payload_start, 3); - memcpy(args + 3, _params.keys.app_eui, 8); - memcpy(args + 3 + 8, (uint8_t *) &_params.dev_nonce, 2); + memcpy_convert_endianess(args + 3, _params.keys.app_eui, 8); + args[3+8] = _params.dev_nonce & 0xFF; + args[3+9] = (_params.dev_nonce >> 8) & 0xFF; args_size = 13; } @@ -743,7 +746,6 @@ void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp) } } else { _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK; - _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT; } _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; - _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT; _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.is_node_ack_requested == true) { - _mcps_confirmation.status = is_timeout ? - LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT : - LORAMAC_EVENT_INFO_STATUS_RX1_ERROR; + _mcps_confirmation.status = 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 (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) { _lora_time.stop(_params.timers.rx_window2_timer); @@ -864,14 +859,8 @@ void LoRaMac::on_radio_rx_timeout(bool is_timeout) } } else { if (_params.is_node_ack_requested == true) { - _mcps_confirmation.status = is_timeout ? - LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT : - LORAMAC_EVENT_INFO_STATUS_RX2_ERROR; + _mcps_confirmation.status = 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; } - 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)) { 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; } - 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)) { return LORAWAN_STATUS_CRYPTO_FAIL; } @@ -1700,23 +1695,15 @@ lorawan_status_t LoRaMac::join(bool is_otaa) 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.rejoin_forced = is_forced; + _params.forced_datarate = datarate; 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, loramac_frame_ctrl_t *fctrl, const uint8_t fport, @@ -1970,7 +1957,11 @@ lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel) int8_t tx_power = 0; 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.max_eirp = _params.sys_params.max_eirp; 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); - _mlme_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.tx_power = tx_power; @@ -2008,6 +1997,11 @@ void LoRaMac::reset_mcps_indication() _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR; } +LoRaWANTimeHandler *LoRaMac::get_lora_time() +{ + return &_lora_time; +} + lorawan_status_t LoRaMac::initialize(EventQueue *queue, mbed::Callbackscheduling_failure_handler) { @@ -2233,3 +2227,9 @@ uint8_t LoRaMac::get_current_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(); +} diff --git a/features/lorawan/lorastack/mac/LoRaMac.h b/features/lorawan/lorastack/mac/LoRaMac.h index 3cb6eeda8d..b1ec1ccf08 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.h +++ b/features/lorawan/lorastack/mac/LoRaMac.h @@ -196,6 +196,13 @@ public: */ 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. * * @param phy LoRaPHY object @@ -353,9 +360,11 @@ public: /** * @brief rejoin Rejoins the network * @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. */ - 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 @@ -402,7 +411,6 @@ public: */ const loramac_mcps_confirm_t *get_mcps_confirmation() 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; /** @@ -470,6 +478,8 @@ public: void unlock(void) { } #endif + LoRaWANTimeHandler *get_lora_time(); + private: /** * @brief Queries the LoRaMAC the maximum possible FRMPayload size to send. @@ -626,7 +636,6 @@ private: * Resets MAC primitive blocks */ void reset_mcps_confirmation(void); - void reset_mlme_confirmation(void); void reset_mcps_indication(void); /** diff --git a/features/lorawan/lorastack/mac/LoRaMacCommand.cpp b/features/lorawan/lorastack/mac/LoRaMacCommand.cpp index 6e7d68199c..90d95ee602 100644 --- a/features/lorawan/lorastack/mac/LoRaMacCommand.cpp +++ b/features/lorawan/lorastack/mac/LoRaMacCommand.cpp @@ -143,6 +143,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui switch (payload[mac_index++]) { case SRV_MAC_RESET_CONF: { loramac_mlme_confirm_t mlme_conf; + mlme_conf.type = MLME_RESET; mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK; mlme_conf.version = payload[mac_index++] & 0x0F; confirm_handler(mlme_conf); @@ -150,6 +151,7 @@ lorawan_status_t LoRaMacCommand::process_mac_commands(const uint8_t *payload, ui break; case SRV_MAC_LINK_CHECK_ANS: { loramac_mlme_confirm_t mlme_conf; + mlme_conf.type = MLME_LINK_CHECK; mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK; mlme_conf.demod_margin = 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; case SRV_MAC_REKEY_CONF: { loramac_mlme_confirm_t mlme_conf; + mlme_conf.type = MLME_REKEY; mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK; mlme_conf.version = payload[mac_index++] & 0x0F; confirm_handler(mlme_conf); diff --git a/features/lorawan/lorastack/phy/LoRaPHY.cpp b/features/lorawan/lorastack/phy/LoRaPHY.cpp index bad19aa9ff..ffb6586e10 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHY.cpp @@ -39,6 +39,9 @@ SPDX-License-Identifier: BSD-3-Clause #define GPS_EPOCH_DIFF_WITH_UTC 315964800 #define CHANNELS_IN_MASK 16 +#define DEVICE_DOES_NOT_SUPPORT_TIME 0 +#define DEVICE_SUPPORTS_TIME 1 + LoRaPHY::LoRaPHY() : _radio(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" _rejoin_max_time = max_time; _rejoin_max_count = max_count; - return 1; + return DEVICE_SUPPORTS_TIME; } void LoRaPHY::restore_default_channels() @@ -1513,4 +1516,13 @@ uint8_t LoRaPHY::apply_DR_offset(int8_t dr, int8_t dr_offset) 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; +} diff --git a/features/lorawan/lorastack/phy/LoRaPHY.h b/features/lorawan/lorastack/phy/LoRaPHY.h index f43c812c4c..dfaaa9650f 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.h +++ b/features/lorawan/lorastack/phy/LoRaPHY.h @@ -604,6 +604,18 @@ public: //Verifiers */ 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: LoRaPHY(); diff --git a/features/lorawan/mbed_lib.json b/features/lorawan/mbed_lib.json index 9537608c60..eece668d97 100644 --- a/features/lorawan/mbed_lib.json +++ b/features/lorawan/mbed_lib.json @@ -116,6 +116,10 @@ "rejoin-default-max-count": { "help": "LW1.1 only! Maximum amount of messages which can be sent between Rejoin requests.", "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 } } } diff --git a/features/lorawan/system/lorawan_data_structures.h b/features/lorawan/system/lorawan_data_structures.h index 26254e1453..b982aaeed9 100644 --- a/features/lorawan/system/lorawan_data_structures.h +++ b/features/lorawan/system/lorawan_data_structures.h @@ -553,14 +553,6 @@ typedef enum { * A TX timeout occurred. */ 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. */ @@ -1458,6 +1450,15 @@ typedef struct { */ 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; #endif /* LORAWAN_SYSTEM_LORAWAN_DATA_STRUCTURES_H_ */