Lora-net / SWL2001

LoRa Basics Modem LoRaWAN stack
BSD 3-Clause Clear License
104 stars 60 forks source link

Frequent store and forward uplinks if offline #66

Open benninger-mm opened 3 months ago

benninger-mm commented 3 months ago

I'm implementing a tracking device which will be moved in and out of the range of a LoRaWAN gateway multiple times a day. I'm using the store and forward service to ensure that the locations are being forwarded at a later point in time if the device was out of range.

During a couple of tests I noticed that the service retransmitted the first unacked packet 40 to 50 times during the first hour of being offline. This is considered a lot, especially, since this happens multiple times a day for my use case. Furthermore, if the function smtc_modem_set_nb_trans is used to set nb_trans to 3 (as suggested here) each packet is repeated 3 times which results in 120 to 150 LoRaWAN uplinks being transmitted during the first hour of being offline.

I traced back the issue to the function store_and_forward_flash_compute_next_delay_s which is implemented here. Unfortunately, this function cannot be altered, except for STORE_AND_FORWARD_DELAY_MAX_S.

The current implementation of store_and_forward_flash_compute_next_delay_s is rather simple. A random number between 1 and 5 is multiplied with the number of unacked packets (sending_try_cpt) to get the delay in seconds. The random numbers are currently centered around 3. Allowing a user to set this center manually via a define would already help in my case. I would prefer the random numbers to be centered around 600 seconds (10 minutes) since in that case the delay increases much faster. Alternatively, you could adjust the implementation such that a user can provide a custom implementation of the store_and_forward_flash_compute_next_delay_s function.

opeyrard commented 3 months ago

Hi, We will improve this in the next release. Feel free to make a proposal. Many thanks,

benninger-mm commented 3 months ago

Ok, thanks for the information.

I adjusted the store_and_forward_flash_compute_next_delay_s such that it uses an exponential backoff. This works fine for my application:

static uint32_t store_and_forward_flash_compute_next_delay_s( store_and_forward_flash_t* ctx )
{
    if( ctx->sending_try_cpt == 0 )
    {
        return 0;
    }
    // Exponential backoff (2^sending_try_cpt * 60s)
    uint32_t delay_s = (1 << ctx->sending_try_cpt) * 60;
    if( delay_s > STORE_AND_FORWARD_DELAY_MAX_S )
    {
        delay_s = STORE_AND_FORWARD_DELAY_MAX_S;
    }
    return delay_s + smtc_modem_hal_get_random_nb_in_range( 0, 60 );
}