@@ -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+
6070static uint8_t endpoint_name [ENDPOINT_NAME_LEN + 1 ];
6171static uint8_t imei_buf [IMEI_LEN + sizeof ("\r\nOK\r\n" )];
6272static struct lwm2m_ctx client = {0 };
6373static 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 */
6778static 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
7480static 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+
318339static 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
453501void 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