lorawan: services: add Class C session handling

The new functions are required for Multicast Class C session setup.

Signed-off-by: Martin Jäger <martin@libre.solar>
This commit is contained in:
Martin Jäger 2022-10-16 12:20:10 +02:00 committed by Fabio Baltieri
parent 1f25531d7c
commit a4c13fc584
3 changed files with 92 additions and 0 deletions

View file

@ -174,6 +174,12 @@ static int clock_sync_app_time_req(void)
uint8_t tx_pos = 0;
uint8_t tx_buf[6];
if (lorawan_services_class_c_active() > 0) {
/* avoid disturbing the session and causing potential package loss */
LOG_DBG("AppTimeReq not sent because of active class C session");
return -EBUSY;
}
tx_buf[tx_pos++] = CLOCK_SYNC_CMD_APP_TIME;
tx_pos += clock_sync_serialize_device_time(tx_buf + tx_pos,
sizeof(tx_buf) - tx_pos);

View file

@ -35,6 +35,10 @@ static struct k_work_q services_workq;
static struct k_work_delayable uplink_work;
/* Number of active class C sessions and mutex to protect access to session info */
static uint8_t active_class_c_sessions;
static struct k_mutex session_mutex;
/* single-linked list (with pointers) and array for implementation of priority queue */
static struct service_uplink_msg messages[10];
static sys_slist_t msg_list;
@ -160,6 +164,56 @@ int lorawan_services_reschedule_work(struct k_work_delayable *dwork, k_timeout_t
return k_work_reschedule_for_queue(&services_workq, dwork, delay);
}
int lorawan_services_class_c_start(void)
{
int ret;
k_mutex_lock(&session_mutex, K_FOREVER);
if (active_class_c_sessions == 0) {
ret = lorawan_set_class(LORAWAN_CLASS_C);
if (ret == 0) {
LOG_DBG("Switched to class C");
active_class_c_sessions++;
ret = active_class_c_sessions;
}
} else {
active_class_c_sessions++;
ret = active_class_c_sessions;
}
k_mutex_unlock(&session_mutex);
return ret;
}
int lorawan_services_class_c_stop(void)
{
int ret = 0;
k_mutex_lock(&session_mutex, K_FOREVER);
if (active_class_c_sessions == 1) {
ret = lorawan_set_class(LORAWAN_CLASS_A);
if (ret == 0) {
LOG_DBG("Reverted to class A");
active_class_c_sessions--;
}
} else if (active_class_c_sessions > 1) {
active_class_c_sessions--;
ret = active_class_c_sessions;
}
k_mutex_unlock(&session_mutex);
return ret;
}
int lorawan_services_class_c_active(void)
{
return active_class_c_sessions;
}
static int lorawan_services_init(void)
{
@ -173,6 +227,8 @@ static int lorawan_services_init(void)
k_work_init_delayable(&uplink_work, uplink_handler);
k_mutex_init(&session_mutex);
k_thread_name_set(&services_workq.thread, "lorawan_services");
return 0;

View file

@ -58,4 +58,34 @@ int lorawan_services_schedule_uplink(uint8_t port, uint8_t *data, uint8_t len, u
int lorawan_services_reschedule_work(struct k_work_delayable *dwork, k_timeout_t delay);
/**
* @brief Start a class C session
*
* If there is already an ongoing class C session, only the internal counter of
* active sessions is incremented.
*
* @returns Number of active sessions if successful or negative errno otherwise.
*/
int lorawan_services_class_c_start(void);
/**
* @brief Stop class C session and revert to class A
*
* If there is more than one class C session ongoing, only the internal counter
* of active sessions is decremented.
*
* @returns Number of active sessions if successful or negative errno otherwise.
*/
int lorawan_services_class_c_stop(void);
/**
* @brief Retrieve number of active sessions
*
* Can be used to determine if sessions are ongoing and avoid disturbing an
* ongoing session by sending out unnecessary messages.
*
* @returns Number of active class C sessions.
*/
int lorawan_services_class_c_active(void);
#endif /* ZEPHYR_SUBSYS_LORAWAN_SERVICES_LORAWAN_SERVICES_H_ */