mirror of https://github.com/ARMmbed/mbed-os.git
Adding ack expiry handling for class C
In Class C, rx timeout does not take place for RX2 windows, so if we have not received anything, we would be retrying but if the no. of retries are maxed out, and we have not recieved anything yet, we need a mechanism to tell the upper layer that this has happened.pull/6910/head
parent
b0ce443f5b
commit
2bc8e4e847
|
|
@ -435,7 +435,7 @@ lorawan_status_t LoRaWANStack::set_device_class(const device_class_t& device_cla
|
|||
if (device_class == CLASS_B) {
|
||||
return LORAWAN_STATUS_UNSUPPORTED;
|
||||
}
|
||||
_loramac.set_device_class(device_class);
|
||||
_loramac.set_device_class(device_class, mbed::callback(this, &LoRaWANStack::handle_ack_expiry_for_class_c));
|
||||
return LORAWAN_STATUS_OK;
|
||||
}
|
||||
|
||||
|
|
@ -564,7 +564,7 @@ void LoRaWANStack::process_transmission(void)
|
|||
_ctrl_flags |= TX_DONE_FLAG;
|
||||
|
||||
// In Class C, reception timeout never happens, so we handle the state
|
||||
// progression here
|
||||
// progression for TX_DONE in UNCONFIRMED case here
|
||||
if (_loramac.get_device_class() == CLASS_C) {
|
||||
_loramac.post_process_mcps_req();
|
||||
state_controller(DEVICE_STATE_STATUS_CHECK);
|
||||
|
|
@ -573,6 +573,14 @@ void LoRaWANStack::process_transmission(void)
|
|||
}
|
||||
}
|
||||
|
||||
void LoRaWANStack::handle_ack_expiry_for_class_c(void)
|
||||
{
|
||||
_ctrl_flags &= ~TX_DONE_FLAG;
|
||||
_ctrl_flags |= TX_ONGOING_FLAG;
|
||||
tr_error("Retries exhausted for Class C device");
|
||||
state_controller(DEVICE_STATE_STATUS_CHECK);
|
||||
}
|
||||
|
||||
void LoRaWANStack::process_reception(const uint8_t* const payload, uint16_t size,
|
||||
int16_t rssi, int8_t snr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -522,6 +522,8 @@ private:
|
|||
void make_tx_metadata_available(void);
|
||||
void make_rx_metadata_available(void);
|
||||
|
||||
void handle_ack_expiry_for_class_c(void);
|
||||
|
||||
private:
|
||||
LoRaMac _loramac;
|
||||
radio_events_t radio_events;
|
||||
|
|
|
|||
|
|
@ -641,8 +641,10 @@ void LoRaMac::handle_data_frame(const uint8_t* const payload,
|
|||
_mcps_indication.buffer_size = size - ptr_pos;
|
||||
}
|
||||
|
||||
check_to_disable_ack_timeout(_params.is_node_ack_requested, _device_class, _mcps_confirmation.ack_received,
|
||||
_params.ack_timeout_retry_counter, _params.max_ack_timeout_retries );
|
||||
// only stop act timer, if the ack is actuall recieved
|
||||
if (_mcps_confirmation.ack_received) {
|
||||
_lora_time.stop(_params.timers.ack_timeout_timer);
|
||||
}
|
||||
}
|
||||
|
||||
void LoRaMac::set_batterylevel_callback(mbed::Callback<uint8_t(void)> battery_level)
|
||||
|
|
@ -775,7 +777,7 @@ bool LoRaMac::continue_joining_process()
|
|||
|
||||
bool LoRaMac::continue_sending_process()
|
||||
{
|
||||
if (_params.ack_timeout_retry_counter >= _params.max_ack_timeout_retries) {
|
||||
if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) {
|
||||
_mac_commands.clear_command_buffer();
|
||||
_params.adr_ack_counter++;
|
||||
return false;
|
||||
|
|
@ -892,38 +894,20 @@ void LoRaMac::open_rx2_window()
|
|||
}
|
||||
}
|
||||
|
||||
void LoRaMac::check_to_disable_ack_timeout(bool node_ack_requested,
|
||||
device_class_t dev_class,
|
||||
bool ack_received,
|
||||
uint8_t ack_timeout_retries_counter,
|
||||
uint8_t ack_timeout_retries)
|
||||
{
|
||||
// There are three cases where we need to stop the AckTimeoutTimer:
|
||||
if( node_ack_requested == false ) {
|
||||
if( dev_class == CLASS_C ) {
|
||||
// FIRST CASE
|
||||
// We have performed an unconfirmed uplink in class c mode
|
||||
// and have received a downlink in RX1 or RX2.
|
||||
_lora_time.stop(_params.timers.ack_timeout_timer);
|
||||
}
|
||||
} else {
|
||||
if( ack_received == 1 ) {
|
||||
// SECOND CASE
|
||||
// We received an ACK for previously sent confirmable message
|
||||
_lora_time.stop(_params.timers.ack_timeout_timer);
|
||||
} else {
|
||||
// THIRD CASE
|
||||
// Max number of retries exceeded for confirmable message
|
||||
if( ack_timeout_retries_counter > ack_timeout_retries ) {
|
||||
_lora_time.stop(_params.timers.ack_timeout_timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoRaMac::on_ack_timeout_timer_event(void)
|
||||
{
|
||||
Lock lock(*this);
|
||||
|
||||
if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) {
|
||||
if (get_device_class() == CLASS_C) {
|
||||
// no need to use EventQueue as LoRaWANStack and LoRaMac are always
|
||||
// in same context
|
||||
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
||||
_ack_expiry_handler_for_class_c.call();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
tr_debug("ACK_TIMEOUT Elapses, Retrying ...");
|
||||
_lora_time.stop(_params.timers.ack_timeout_timer);
|
||||
|
||||
|
|
@ -1318,11 +1302,14 @@ device_class_t LoRaMac::get_device_class() const
|
|||
return _device_class;
|
||||
}
|
||||
|
||||
void LoRaMac::set_device_class(const device_class_t& device_class)
|
||||
void LoRaMac::set_device_class(const device_class_t& device_class,
|
||||
mbed::Callback<void(void)>ack_expiry_handler)
|
||||
{
|
||||
_device_class = device_class;
|
||||
_ack_expiry_handler_for_class_c = ack_expiry_handler;
|
||||
|
||||
if (CLASS_A == _device_class) {
|
||||
tr_debug("Changing device class to -> CLASS_A");
|
||||
_lora_phy.put_radio_to_sleep();
|
||||
} else if (CLASS_C == _device_class) {
|
||||
_params.is_node_ack_requested = false;
|
||||
|
|
@ -1334,8 +1321,11 @@ void LoRaMac::set_device_class(const device_class_t& device_class)
|
|||
&_params.rx_window2_config);
|
||||
}
|
||||
if (CLASS_C == _device_class) {
|
||||
tr_debug("Changing device class to -> CLASS_C");
|
||||
open_rx2_window();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void LoRaMac::setup_link_check_request()
|
||||
|
|
|
|||
|
|
@ -351,8 +351,10 @@ public:
|
|||
/**
|
||||
* @brief set_device_class Sets active device class.
|
||||
* @param device_class Device class to use.
|
||||
* @param ack_expiry_handler callback function to inform about ack expiry
|
||||
*/
|
||||
void set_device_class(const device_class_t& device_class);
|
||||
void set_device_class(const device_class_t& device_class,
|
||||
mbed::Callback<void(void)>ack_expiry_handler);
|
||||
|
||||
/**
|
||||
* @brief opens a continuous RX2 window for Class C devices
|
||||
|
|
@ -642,6 +644,13 @@ private:
|
|||
*/
|
||||
events::EventQueue *_ev_queue;
|
||||
|
||||
/**
|
||||
* Class C doesn't timeout in RX2 window as it is a continuous window.
|
||||
* We use this callback to inform the LoRaWANStack controller that the
|
||||
* system cannot do more retries.
|
||||
*/
|
||||
mbed::Callback<void(void)> _ack_expiry_handler_for_class_c;
|
||||
|
||||
/**
|
||||
* Structure to hold MCPS indication data.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue