Skip to content

Commit b560841

Browse files
Juha Heiskanenrlubos
authored andcommitted
samples: lwm2m_client: Client state machine and LTE event update
LwM2M client state machine updated that it handle LTE network registration status for suspending and Resume in same thread than RD client stop and Start. Signed-off-by: Juha Heiskanen <[email protected]>
1 parent c7ed9f3 commit b560841

File tree

4 files changed

+176
-76
lines changed

4 files changed

+176
-76
lines changed

applications/asset_tracker_v2/tests/lwm2m_codec/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ target_include_directories(app PRIVATE ${NRF_DIR}/include/)
5454
target_compile_options(app PRIVATE
5555
-DCONFIG_LWM2M_CLIENT_UTILS_LOCATION_ASSIST_OBJ_SUPPORT=y
5656
-DCONFIG_LWM2M_CLIENT_UTILS_SIGNAL_MEAS_INFO_OBJ_SUPPORT=y
57-
-DCONFIG_LWM2M_CLIENT_UTILS_NWK_REG_NOTIFICATION=n
5857
-DCONFIG_CLOUD_CODEC_MANUFACTURER="nordicsemi"
5958
-DCONFIG_LWM2M_IPSO_PUSH_BUTTON_INSTANCE_COUNT=2
6059
-DCONFIG_APP_EVENT_MANAGER_MAX_EVENT_CNT=32

applications/asset_tracker_v2/tests/lwm2m_integration/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ target_compile_options(app PRIVATE
5656
-DCONFIG_NET_SOCKETS_POSIX_NAMES=1
5757
-DCONFIG_LWM2M_CLIENT_UTILS_SECURITY_OBJ_SUPPORT=y
5858
-DCONFIG_LWM2M_CLIENT_UTILS_FIRMWARE_UPDATE_OBJ_SUPPORT=y
59-
-DCONFIG_LWM2M_CLIENT_UTILS_NWK_REG_NOTIFICATION=n
6059
-DCONFIG_CLOUD_CLIENT_ID_USE_CUSTOM=y
6160
-DCONFIG_CLOUD_CLIENT_ID="test"
6261
-DCONFIG_LWM2M_ENGINE_MESSAGE_HEADER_SIZE=48

samples/nrf9160/lwm2m_client/prj.conf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ CONFIG_LWM2M_SERVER_DEFAULT_PMIN=1
3434
CONFIG_LWM2M_SERVER_DEFAULT_PMAX=300
3535
CONFIG_LWM2M_CLIENT_UTILS=y
3636
CONFIG_LWM2M_CLIENT_UTILS_LOCATION_OBJ_SUPPORT=n
37-
CONFIG_LWM2M_CLIENT_UTILS_NWK_REG_NOTIFICATION=y
3837
CONFIG_LWM2M_IPSO_SUPPORT=y
3938

4039
# IPSO v1.1

samples/nrf9160/lwm2m_client/src/main.c

Lines changed: 176 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,25 @@ LOG_MODULE_REGISTER(app_lwm2m_client, CONFIG_APP_LOG_LEVEL);
5757
#define LWM2M_SECURITY_CERTIFICATE 2
5858
#define LWM2M_SECURITY_NO_SEC 3
5959

60+
/* Client State Machine states */
61+
static enum client_state {
62+
START, /* Start Connection to a server*/
63+
CONNECTING, /* LwM2M engine is connecting to server */
64+
BOOTSTRAP, /* LwM2M engine is doing a bootstrap */
65+
CONNECTED, /* LwM2M Client connection establisment to server */
66+
LTE_OFFLINE, /* LTE offline and LwM2M engine should be suspended */
67+
NETWORK_ERROR /* Client network error handling. Client stop and modem reset */
68+
} client_state = START;
69+
6070
static uint8_t endpoint_name[ENDPOINT_NAME_LEN + 1];
6171
static uint8_t imei_buf[IMEI_LEN + sizeof("\r\nOK\r\n")];
6272
static struct lwm2m_ctx client = {0};
6373
static bool reconnect;
64-
static int reconnection_counter;
65-
static struct k_sem lwm2m_restart;
74+
static K_SEM_DEFINE(state_mutex, 0, 1);
75+
static K_MUTEX_DEFINE(lte_mutex);
76+
static bool modem_connected_to_network;
6677
/* Enable session lifetime check for initial boot */
6778
static bool update_session_lifetime = true;
68-
static bool lwm2m_client_connected;
69-
70-
#if defined(CONFIG_LWM2M_CLIENT_UTILS_NWK_REG_NOTIFICATION)
71-
static bool lwm2m_stack_suspended;
72-
#endif
7379

7480
static void rd_client_event(struct lwm2m_ctx *client, enum lwm2m_rd_client_event client_event);
7581

@@ -315,86 +321,99 @@ static void rd_client_update_lifetime(int srv_obj_inst)
315321
update_session_lifetime = false;
316322
}
317323

324+
static void state_trigger_and_unlock(enum client_state new_state)
325+
{
326+
if (new_state != client_state) {
327+
client_state = new_state;
328+
k_sem_give(&state_mutex);
329+
}
330+
k_mutex_unlock(&lte_mutex);
331+
}
332+
333+
static void state_set_and_unlock(enum client_state new_state)
334+
{
335+
client_state = new_state;
336+
k_mutex_unlock(&lte_mutex);
337+
}
338+
318339
static void rd_client_event(struct lwm2m_ctx *client, enum lwm2m_rd_client_event client_event)
319340
{
341+
k_mutex_lock(&lte_mutex, K_FOREVER);
342+
343+
if (client_state == LTE_OFFLINE &&
344+
client_event != LWM2M_RD_CLIENT_EVENT_ENGINE_SUSPENDED) {
345+
LOG_DBG("Drop network event %d at LTE offline state", client_event);
346+
k_mutex_unlock(&lte_mutex);
347+
return;
348+
}
349+
320350
switch (client_event) {
321351
case LWM2M_RD_CLIENT_EVENT_NONE:
322352
/* do nothing */
353+
k_mutex_unlock(&lte_mutex);
323354
break;
324355

325356
case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE:
326357
LOG_DBG("Bootstrap registration failure!");
327-
k_sem_give(&lwm2m_restart);
358+
state_trigger_and_unlock(NETWORK_ERROR);
328359
break;
329360

330361
case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE:
331362
LOG_DBG("Bootstrap registration complete");
332-
lwm2m_client_connected = false;
333363
update_session_lifetime = true;
334-
reconnection_counter = 0;
364+
state_trigger_and_unlock(BOOTSTRAP);
335365
break;
336366

337367
case LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE:
338368
LOG_DBG("Bootstrap transfer complete");
369+
k_mutex_unlock(&lte_mutex);
339370
break;
340371

341372
case LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE:
342373
LOG_WRN("Registration failure!");
343-
lwm2m_client_connected = false;
344-
k_sem_give(&lwm2m_restart);
374+
state_trigger_and_unlock(NETWORK_ERROR);
345375
break;
346376

347377
case LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE:
348-
reconnection_counter = 0;
349-
lwm2m_client_connected = true;
350378
LOG_DBG("Registration complete");
351-
if (update_session_lifetime) {
352-
/* Read a current server lifetime value */
353-
rd_client_update_lifetime(client->srv_obj_inst);
354-
}
355-
356-
#if defined(CONFIG_APP_LWM2M_CONFORMANCE_TESTING)
357-
lwm2m_register_server_send_mute_cb();
358-
#endif
359-
/* Get current time and date */
360-
date_time_update_async(date_time_event_handler);
379+
state_trigger_and_unlock(CONNECTED);
361380
break;
362381

363382
case LWM2M_RD_CLIENT_EVENT_REG_UPDATE_FAILURE:
364383
LOG_DBG("Registration update failure!");
365-
lwm2m_client_connected = false;
366-
k_sem_give(&lwm2m_restart);
384+
state_trigger_and_unlock(NETWORK_ERROR);
367385
break;
368386

369387
case LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE:
370388
LOG_DBG("Registration update complete");
371-
lwm2m_client_connected = true;
389+
state_trigger_and_unlock(CONNECTED);
372390
break;
373391

374392
case LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE:
375393
LOG_DBG("Deregister failure!");
376394
reconnect = true;
377-
k_sem_give(&lwm2m_restart);
395+
state_trigger_and_unlock(NETWORK_ERROR);
378396
break;
379397

380398
case LWM2M_RD_CLIENT_EVENT_DISCONNECT:
381399
LOG_DBG("Disconnected");
382-
lwm2m_client_connected = false;
400+
state_set_and_unlock(START);
383401
break;
384402

385403
case LWM2M_RD_CLIENT_EVENT_QUEUE_MODE_RX_OFF:
386404
LOG_DBG("Queue mode RX window closed");
405+
k_mutex_unlock(&lte_mutex);
387406
break;
388407

389408
case LWM2M_RD_CLIENT_EVENT_ENGINE_SUSPENDED:
390409
LOG_DBG("LwM2M engine suspended");
410+
k_mutex_unlock(&lte_mutex);
391411
break;
392412

393413
case LWM2M_RD_CLIENT_EVENT_NETWORK_ERROR:
394414
LOG_ERR("LwM2M engine reported a network error.");
395415
reconnect = true;
396-
lwm2m_client_connected = false;
397-
k_sem_give(&lwm2m_restart);
416+
state_trigger_and_unlock(NETWORK_ERROR);
398417
break;
399418
}
400419
}
@@ -428,27 +447,56 @@ static void modem_connect(void)
428447
} while (ret < 0);
429448
}
430449

431-
#if defined(CONFIG_LWM2M_CLIENT_UTILS_NWK_REG_NOTIFICATION)
432-
static void lwm2m_lte_nwk_reg_update_state_cb(bool connected)
450+
static bool lte_connected(enum lte_lc_nw_reg_status nw_reg_status)
433451
{
434-
if (connected) {
435-
LOG_INF("LTE connected");
436-
if (lwm2m_stack_suspended) {
437-
if (lwm2m_engine_resume() == 0) {
438-
lwm2m_stack_suspended = false;
439-
}
440-
}
441-
} else {
442-
LOG_INF("LTE disconnected");
443-
if (!lwm2m_stack_suspended && lwm2m_client_connected) {
444-
if (lwm2m_engine_pause() == 0) {
445-
lwm2m_stack_suspended = true;
446-
lwm2m_client_connected = false;
447-
}
452+
if ((nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME) ||
453+
(nw_reg_status == LTE_LC_NW_REG_REGISTERED_ROAMING)) {
454+
return true;
455+
}
456+
457+
return false;
458+
}
459+
460+
static void lwm2m_lte_reg_handler_notify(enum lte_lc_nw_reg_status nw_reg_status)
461+
{
462+
bool lte_registered;
463+
464+
LOG_DBG("LTE NW status: %d", nw_reg_status);
465+
k_mutex_lock(&lte_mutex, K_FOREVER);
466+
lte_registered = lte_connected(nw_reg_status);
467+
if (lte_registered != modem_connected_to_network) {
468+
modem_connected_to_network = lte_registered;
469+
if (client_state != START && client_state != BOOTSTRAP) {
470+
k_sem_give(&state_mutex);
448471
}
449472
}
473+
k_mutex_unlock(&lte_mutex);
474+
}
475+
476+
static void lte_notify_handler(const struct lte_lc_evt *const evt)
477+
{
478+
switch (evt->type) {
479+
case LTE_LC_EVT_NW_REG_STATUS:
480+
lwm2m_lte_reg_handler_notify(evt->nw_reg_status);
481+
break;
482+
default:
483+
break;
484+
}
485+
}
486+
487+
static void suspend_lwm2m_engine(void)
488+
{
489+
int ret;
490+
491+
state_trigger_and_unlock(LTE_OFFLINE);
492+
ret = lwm2m_engine_pause();
493+
if (ret) {
494+
LOG_ERR("LwM2M engine pause fail %d", ret);
495+
reconnect = true;
496+
k_mutex_lock(&lte_mutex, K_FOREVER);
497+
state_trigger_and_unlock(NETWORK_ERROR);
498+
}
450499
}
451-
#endif /* CONFIG_LWM2M_CLIENT_UTILS_NWK_REG_NOTIFICATION */
452500

453501
void main(void)
454502
{
@@ -457,8 +505,6 @@ void main(void)
457505

458506
LOG_INF(APP_BANNER);
459507

460-
k_sem_init(&lwm2m_restart, 0, 1);
461-
462508
#if !defined(CONFIG_NRF_MODEM_LIB_SYS_INIT)
463509
ret = nrf_modem_lib_init(NORMAL_MODE);
464510
if (ret < 0) {
@@ -497,9 +543,7 @@ void main(void)
497543
return;
498544
}
499545

500-
#if defined(CONFIG_LWM2M_CLIENT_UTILS_NWK_REG_NOTIFICATION)
501-
lwm2m_lte_reg_handler_register(lwm2m_lte_nwk_reg_update_state_cb);
502-
#endif
546+
lte_lc_register_handler(lte_notify_handler);
503547

504548
ret = modem_info_init();
505549
if (ret < 0) {
@@ -534,7 +578,6 @@ void main(void)
534578
}
535579
#endif
536580

537-
reconnection_counter = 0;
538581
modem_connect();
539582

540583
#if defined(CONFIG_APP_GNSS)
@@ -570,32 +613,92 @@ void main(void)
570613
bootstrap_flags = 0;
571614
}
572615

573-
lwm2m_rd_client_start(&client, endpoint_name, bootstrap_flags, rd_client_event,
574-
NULL);
616+
k_mutex_lock(&lte_mutex, K_FOREVER);
575617

576-
/* Wait for restart event */
577-
k_sem_take(&lwm2m_restart, K_FOREVER);
618+
switch (client_state) {
619+
case START:
620+
LOG_INF("Client connect to server");
621+
state_set_and_unlock(CONNECTING);
622+
lwm2m_rd_client_start(&client, endpoint_name, bootstrap_flags,
623+
rd_client_event, NULL);
624+
break;
625+
626+
case BOOTSTRAP:
627+
state_set_and_unlock(BOOTSTRAP);
628+
LOG_INF("LwM2M is boosttrapping");
629+
break;
630+
631+
case CONNECTING:
632+
if (!modem_connected_to_network) {
633+
/* LTE connection down suspend LwM2M engine */
634+
suspend_lwm2m_engine();
635+
} else {
636+
LOG_INF("LwM2M is connecting to server");
637+
k_mutex_unlock(&lte_mutex);
638+
}
639+
break;
640+
case CONNECTED:
641+
if (!modem_connected_to_network) {
642+
/* LTE connection down suspend LwM2M engine */
643+
suspend_lwm2m_engine();
644+
} else {
645+
k_mutex_unlock(&lte_mutex);
646+
LOG_INF("LwM2M is connected to server");
647+
if (update_session_lifetime) {
648+
/* Read a current server lifetime value */
649+
rd_client_update_lifetime(client.srv_obj_inst);
650+
}
578651

579-
/* Stop the LwM2M engine. */
580-
lwm2m_rd_client_stop(&client, rd_client_event, false);
581652
#if defined(CONFIG_APP_LWM2M_CONFORMANCE_TESTING)
582-
k_work_cancel_delayable(&send_periodical_work);
583-
send_count = 0;
653+
lwm2m_register_server_send_mute_cb();
584654
#endif
655+
/* Get current time and date */
656+
date_time_update_async(date_time_event_handler);
657+
}
658+
break;
585659

586-
if (reconnect) {
587-
reconnect = false;
588-
reconnection_counter++;
589-
590-
LOG_INF("LwM2M restart requested. The sample will try to"
591-
" re-establish network connection.");
660+
case LTE_OFFLINE:
661+
if (modem_connected_to_network) {
662+
state_trigger_and_unlock(CONNECTING);
663+
LOG_INF("Resume LwM2M engine");
664+
ret = lwm2m_engine_resume();
665+
if (ret) {
666+
LOG_ERR("LwM2M engine Resume fail %d", ret);
667+
}
668+
} else {
669+
LOG_INF("LTE Offline");
670+
k_mutex_unlock(&lte_mutex);
671+
}
672+
break;
592673

593-
/* Try to reconnect to the network. */
594-
ret = lte_lc_offline();
595-
if (ret < 0) {
596-
LOG_ERR("Failed to put LTE link in offline state (%d)", ret);
674+
case NETWORK_ERROR:
675+
/* Stop the LwM2M engine. */
676+
state_trigger_and_unlock(START);
677+
lwm2m_rd_client_stop(&client, rd_client_event, false);
678+
679+
/* Set network state to start for blocking LTE */
680+
if (reconnect) {
681+
reconnect = false;
682+
683+
LOG_INF("LwM2M restart requested. The sample will try to"
684+
" re-establish network connection.");
685+
686+
/* Try to reconnect to the network. */
687+
ret = lte_lc_offline();
688+
if (ret < 0) {
689+
LOG_ERR("Failed to put LTE link in offline state (%d)",
690+
ret);
691+
}
692+
modem_connect();
597693
}
598-
modem_connect();
694+
#if defined(CONFIG_APP_LWM2M_CONFORMANCE_TESTING)
695+
k_work_cancel_delayable(&send_periodical_work);
696+
send_count = 0;
697+
#endif
698+
break;
599699
}
700+
701+
/* Wait for statmachine update event */
702+
k_sem_take(&state_mutex, K_FOREVER);
600703
}
601704
}

0 commit comments

Comments
 (0)