Skip to content

Commit

Permalink
application: serial_lte_modem: Allow auto-connect for LwM2M
Browse files Browse the repository at this point in the history
For the use case of FOTA with lwm2m_carrier,
.Enable auto-connect after FOTA image is applied.
.Enable auto-connect on all kinds of reset.
.Add AT#XCARRIER="auto-connect","read|write"[,<auto-connect-flag>]
 to control YES/NO of auto-connect.

Dependence: libmodem v2.4.2

Signed-off-by: Jun Qing Zou <jun.qing.zou@nordicsemi.no>
  • Loading branch information
junqingzou committed Aug 14, 2023
1 parent 1899750 commit ff4a9f8
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 3 deletions.
14 changes: 14 additions & 0 deletions applications/serial_lte_modem/doc/CARRIER_AT_commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Syntax

The ``<cmd>`` command is a string, and can be used as follows:

* ``AT#XCARRIER="auto_connect","read|write"[,<auto-connect-flag>]``
* ``AT#XCARRIER="app_data"[,<data>]``
* ``AT#XCARRIER="battery_level",<battery_level>``
* ``AT#XCARRIER="battery_status",<battery_status>``
Expand Down Expand Up @@ -107,6 +108,19 @@ The response syntax depends on the commands used.
Examples
~~~~~~~~

::

AT#XCARRIER="auto_connect","read"
#XCARRIER: auto_connect 1
OK

AT#XCARRIER="auto_connect","write",0
OK

AT#XCARRIER="auto_connect","read"
#XCARRIER: auto_connect 0
OK

::

AT#XCARRIER="time","read"
Expand Down
62 changes: 59 additions & 3 deletions applications/serial_lte_modem/src/lwm2m_carrier/slm_at_carrier.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@
#include <zephyr/logging/log.h>
#include <modem/nrf_modem_lib.h>
#include "slm_at_host.h"
#include "slm_settings.h"
#include "slm_util.h"

LOG_MODULE_REGISTER(slm_carrier, CONFIG_SLM_LOG_LEVEL);

/**@brief LwM2M Carrier operations. */
enum slm_carrier_operation {
/* LTE auto-connect operation for LwM2M Carrier */
CARRIER_OP_AUTO_CONNECT,
/* Carrier AppData Operation */
CARRIER_OP_APPDATA_SEND,
/* Carrier Device Operation */
Expand Down Expand Up @@ -54,6 +57,7 @@ struct carrier_op_list {
static int m_mem_free;

/** forward declaration of cmd handlers **/
static int do_carrier_auto_connect(void);
static int do_carrier_appdata_send(void);
static int do_carrier_device_battery_level(void);
static int do_carrier_device_battery_status(void);
Expand All @@ -76,6 +80,7 @@ static int do_carrier_request_link_up(void);

/**@brief SLM AT Command list type. */
static struct carrier_op_list op_list[CARRIER_OP_MAX] = {
{CARRIER_OP_AUTO_CONNECT, "auto_connect", do_carrier_auto_connect},
{CARRIER_OP_APPDATA_SEND, "app_data", do_carrier_appdata_send},
{CARRIER_OP_DEVICE_BATTERY_LEVEL, "battery_level", do_carrier_device_battery_level},
{CARRIER_OP_DEVICE_BATTERY_STATUS, "battery_status", do_carrier_device_battery_status},
Expand All @@ -99,11 +104,17 @@ static struct carrier_op_list op_list[CARRIER_OP_MAX] = {

#define SLM_CARRIER_OP_STR_MAX (sizeof("battery_status") + 1)

/* Global variables and functions defined in different files. */
struct k_work_delayable reconnect_work;

/* Global variables defined in different files. */
extern int32_t auto_connect;
extern struct k_work_q slm_work_q;
extern struct at_param_list at_param_list;
extern uint8_t data_buf[SLM_MAX_MESSAGE_SIZE];

/* Global functions defined in different files. */
int lte_auto_connect(void);

static void print_err(const lwm2m_carrier_event_t *evt)
{
const lwm2m_carrier_event_error_t *err = evt->data.error;
Expand Down Expand Up @@ -178,15 +189,26 @@ static void on_event_app_data(const lwm2m_carrier_event_t *event)
data_send(data_buf, app_data->buffer_len);
}

static void reconnect_wk(struct k_work *work)
{
(void)lte_auto_connect();
}

int lwm2m_carrier_event_handler(const lwm2m_carrier_event_t *event)
{
int err = 0;
static bool fota_started;

switch (event->type) {
case LWM2M_CARRIER_EVENT_LTE_LINK_UP:
LOG_DBG("LWM2M_CARRIER_EVENT_LTE_LINK_UP");
/* AT+CFUN=1 to be issued. */
err = -1;
if (fota_started) {
fota_started = false;
k_work_reschedule(&reconnect_work, K_MSEC(100));
} else {
/* AT+CFUN=1 to be issued. */
err = -1;
}
break;
case LWM2M_CARRIER_EVENT_LTE_LINK_DOWN:
LOG_DBG("LWM2M_CARRIER_EVENT_LTE_LINK_DOWN");
Expand All @@ -209,6 +231,7 @@ int lwm2m_carrier_event_handler(const lwm2m_carrier_event_t *event)
break;
case LWM2M_CARRIER_EVENT_FOTA_START:
LOG_DBG("LWM2M_CARRIER_EVENT_FOTA_START");
fota_started = true;
break;
case LWM2M_CARRIER_EVENT_FOTA_SUCCESS:
LOG_DBG("LWM2M_CARRIER_EVENT_FOTA_SUCCESS");
Expand Down Expand Up @@ -759,6 +782,37 @@ static int do_carrier_request_link_up(void)
return lwm2m_carrier_request(LWM2M_CARRIER_REQUEST_LINK_UP);
}

/* AT#XCARRIER="auto_connect","read|write"[,<auto-connect-flag>] */
static int do_carrier_auto_connect(void)
{
int ret = 0;
int flag;
char operation[6];
size_t size = sizeof(operation);

ret = util_string_get(&at_param_list, 2, operation, &size);
if (ret) {
return ret;
}

if (slm_util_cmd_casecmp(operation, "READ")) {
rsp_send("\r\n#XCARRIER: auto_connect %d\r\n", auto_connect);
} else if (slm_util_cmd_casecmp(operation, "WRITE")) {
ret = at_params_int_get(&at_param_list, 3, &flag);
if (ret) {
return ret;
}
if (flag == 0 || flag == 1) {
auto_connect = flag;
(void)slm_settings_auto_connect_save();
} else {
ret = -EINVAL;
}
}

return ret;
}

/**@brief API to handle Carrier AT command
*/
int handle_at_carrier(enum at_cmd_type cmd_type)
Expand Down Expand Up @@ -787,6 +841,8 @@ int handle_at_carrier(enum at_cmd_type cmd_type)

int slm_at_carrier_init(void)
{
k_work_init_delayable(&reconnect_work, reconnect_wk);

return 0;
}

Expand Down
49 changes: 49 additions & 0 deletions applications/serial_lte_modem/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ static struct k_work_delayable indicate_work;
/* global variable used across different files */
struct k_work_q slm_work_q;

/* global variable defined in different files */
extern int32_t auto_connect;

/* global functions defined in different files */
int poweron_uart(void);

Expand All @@ -47,6 +50,18 @@ static void indicate_wk(struct k_work *work);

BUILD_ASSERT(CONFIG_SLM_WAKEUP_PIN >= 0, "Wake up pin not configured");

NRF_MODEM_LIB_ON_INIT(lwm2m_init_hook, on_modem_lib_init, NULL);

static void on_modem_lib_init(int ret, void *ctx)
{
ARG_UNUSED(ctx);

/** ret: Zero on success, a positive value @em nrf_modem_dfu when executing
* Modem firmware updates, and negative errno on other failures.
*/
LOG_INF("lib_modem init: %d", ret);
}

#if defined(CONFIG_NRF_MODEM_LIB_ON_FAULT_APPLICATION_SPECIFIC)
static void on_modem_failure_shutdown(struct k_work *item);
static void on_modem_failure_reinit(struct k_work *item);
Expand Down Expand Up @@ -333,6 +348,39 @@ static void handle_mcuboot_swap_ret(void)
}
}

int lte_auto_connect(void)
{
int err = 0;

#if defined(CONFIG_SLM_CARRIER)
int stat;

if (!auto_connect) {
return 0;
}
err = nrf_modem_at_scanf("AT+CEREG?", "+CEREG: %d", &stat);
if (err != 1 || (stat == 1 || stat == 5)) {
return 0;
}

LOG_INF("auto connect");
#if defined(CONFIG_LWM2M_CARRIER_SERVER_BINDING_N)
err = nrf_modem_at_printf("AT%%XSYSTEMMODE=0,1,0,0");
if (err) {
LOG_ERR("Failed to configure RAT: %d", err);
return err;
}
#endif /* CONFIG_LWM2M_CARRIER_SERVER_BINDING_N */
err = nrf_modem_at_printf("AT+CFUN=1");
if (err) {
LOG_ERR("Failed to turn on radio: %d", err);
return err;
}
#endif /* CONFIG_SLM_CARRIER */

return err;
}

int start_execute(void)
{
int err;
Expand All @@ -351,6 +399,7 @@ int start_execute(void)
k_work_queue_start(&slm_work_q, slm_wq_stack_area,
K_THREAD_STACK_SIZEOF(slm_wq_stack_area),
SLM_WQ_PRIORITY, NULL);
(void)lte_auto_connect();

return 0;
}
Expand Down
21 changes: 21 additions & 0 deletions applications/serial_lte_modem/src/slm_settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ enum fota_stage fota_stage = FOTA_STAGE_INIT; /* FOTA: stage of FOTA process */
enum fota_status fota_status; /* FOTA: OK/Error status */
int32_t fota_info; /* FOTA: failure cause in case of error or download percentage*/

int32_t auto_connect = 1; /* Auto connect network at startup or after FOTA update */

bool uart_configured; /* UART: first-time configured */
struct uart_config slm_uart; /* UART: config */

Expand All @@ -48,6 +50,11 @@ static int settings_set(const char *name, size_t len, settings_read_cb read_cb,
return -EINVAL;
if (read_cb(cb_arg, &fota_info, len) > 0)
return 0;
} else if (!strcmp(name, "auto_connect")) {
if (len != sizeof(auto_connect))
return -EINVAL;
if (read_cb(cb_arg, &auto_connect, len) > 0)
return 0;
} else if (!strcmp(name, "uart_configured")) {
if (len != sizeof(uart_configured))
return -EINVAL;
Expand Down Expand Up @@ -147,6 +154,20 @@ void slm_settings_fota_init(void)
fota_info = 0;
}

int slm_settings_auto_connect_save(void)
{
int ret;

/* Write a single serialized value to persisted storage (if it has changed value). */
ret = settings_save_one("slm/auto_connect", &(auto_connect), sizeof(auto_connect));
if (ret) {
LOG_ERR("save slm/auto_connect failed: %d", ret);
return ret;
}

return 0;
}

int slm_settings_uart_save(void)
{
int ret;
Expand Down
7 changes: 7 additions & 0 deletions applications/serial_lte_modem/src/slm_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ void slm_settings_fota_init(void);
*/
int slm_settings_fota_save(void);

/**
* @brief Saves the auto-connect settings to NVM.
*
* @retval 0 on success, nonzero otherwise.
*/
int slm_settings_auto_connect_save(void);

/**
* @brief Saves the UART settings to NVM.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ nRF9160: Serial LTE modem
* ``#XMODEMRESET`` AT command to reset the modem while keeping the application running.
It is expected to be used during modem firmware update, which now only requires a reset of the modem.
* DTLS connection identifier support to the ``#XSSOCKETOPT`` and ``#XUDPCLI`` AT commands.
* An ``auto_connect`` operation in the ``#XCARRIER`` carrier command.
The operation controls automatic registration of UE to LTE network.

* Updated:

Expand Down

0 comments on commit ff4a9f8

Please sign in to comment.