net: lwm2m: Add LwM2M shell commands for start&stop

Added start, stop and update to the shell.
Refactored the event_cb of the rd_client_info struct into the ctx,
as it was needed in the shell script.

Signed-off-by: Ola Tangen Kulseng <ola.kulseng@nordicsemi.no>
This commit is contained in:
Ola Tangen Kulseng 2022-06-15 15:57:35 +02:00 committed by Carles Cufí
parent 3e50624e39
commit 38628f409e
3 changed files with 205 additions and 54 deletions

View file

@ -105,6 +105,19 @@ enum lwm2m_observe_event {
typedef void (*lwm2m_observe_cb_t)(enum lwm2m_observe_event event, struct lwm2m_obj_path *path,
void *user_data);
struct lwm2m_ctx;
enum lwm2m_rd_client_event;
/**
* @brief Asynchronous RD client event callback
*
* @param[in] ctx LwM2M context generating the event
* @param[in] event LwM2M RD client event code
*/
typedef void (*lwm2m_ctx_event_cb_t)(struct lwm2m_ctx *ctx,
enum lwm2m_rd_client_event event);
/**
* @brief LwM2M context structure to maintain information for a single
* LwM2M connection.
@ -192,6 +205,8 @@ struct lwm2m_ctx {
*/
lwm2m_observe_cb_t observe_cb;
lwm2m_ctx_event_cb_t event_cb;
/** Validation buffer. Used as a temporary buffer to decode the resource
* value before validation. On successful validation, its content is
* copied into the actual resource buffer.
@ -1211,15 +1226,6 @@ enum lwm2m_rd_client_event {
*/
#define LWM2M_RD_CLIENT_FLAG_BOOTSTRAP BIT(0)
/**
* @brief Asynchronous RD client event callback
*
* @param[in] ctx LwM2M context generating the event
* @param[in] event LwM2M RD client event code
*/
typedef void (*lwm2m_ctx_event_cb_t)(struct lwm2m_ctx *ctx,
enum lwm2m_rd_client_event event);
/**
* @brief Start the LwM2M RD (Registration / Discovery) Client
*

View file

@ -113,7 +113,6 @@ struct lwm2m_rd_client_info {
char ep_name[CLIENT_EP_LEN];
char server_ep[CLIENT_EP_LEN];
lwm2m_ctx_event_cb_t event_cb;
bool use_bootstrap : 1;
bool trigger_update : 1;
@ -200,8 +199,8 @@ static void set_sm_state(uint8_t sm_state)
/* TODO: add locking? */
client.engine_state = sm_state;
if (event > LWM2M_RD_CLIENT_EVENT_NONE && client.event_cb) {
client.event_cb(client.ctx, event);
if (event > LWM2M_RD_CLIENT_EVENT_NONE && client.ctx->event_cb) {
client.ctx->event_cb(client.ctx, event);
}
}
@ -241,8 +240,8 @@ static void sm_handle_timeout_state(struct lwm2m_message *msg,
set_sm_state(sm_state);
if (event > LWM2M_RD_CLIENT_EVENT_NONE && client.event_cb) {
client.event_cb(client.ctx, event);
if (event > LWM2M_RD_CLIENT_EVENT_NONE && client.ctx->event_cb) {
client.ctx->event_cb(client.ctx, event);
}
}
@ -267,8 +266,8 @@ static void sm_handle_failure_state(enum sm_engine_state sm_state)
lwm2m_engine_context_close(client.ctx);
set_sm_state(sm_state);
if (event > LWM2M_RD_CLIENT_EVENT_NONE && client.event_cb) {
client.event_cb(client.ctx, event);
if (event > LWM2M_RD_CLIENT_EVENT_NONE && client.ctx->event_cb) {
client.ctx->event_cb(client.ctx, event);
}
}
@ -1190,7 +1189,7 @@ int lwm2m_rd_client_start(struct lwm2m_ctx *client_ctx, const char *ep_name,
client.ctx->sock_fd = -1;
client.ctx->fault_cb = socket_fault_cb;
client.ctx->observe_cb = observe_cb;
client.event_cb = event_cb;
client.ctx->event_cb = event_cb;
client.use_bootstrap = flags & LWM2M_RD_CLIENT_FLAG_BOOTSTRAP;
set_sm_state(ENGINE_INIT);
@ -1213,7 +1212,7 @@ int lwm2m_rd_client_stop(struct lwm2m_ctx *client_ctx,
return -EPERM;
}
client.event_cb = event_cb;
client.ctx->event_cb = event_cb;
if (sm_is_registered() && deregister) {
set_sm_state(ENGINE_DEREGISTER);

View file

@ -4,39 +4,47 @@
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_MODULE_NAME net_lwm2m_shell
#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zephyr/kernel.h>
#include <zephyr/net/lwm2m.h>
#include <zephyr/shell/shell.h>
#include <lwm2m_engine.h>
#include <lwm2m_util.h>
#define LWM2M_HELP_CMD "LwM2M commands"
#define LWM2M_HELP_SEND "LwM2M SEND operation\nsend [OPTION]... [PATH]...\n" \
"-n\tSend as non-confirmable\n" \
"-n\t Send as non-confirmable\n" \
"Paths are inserted without leading '/'\n" \
"Root-level operation is unsupported"
#define LWM2M_HELP_EXEC "Execute a resource\nexec[PATH]\n"
#define LWM2M_HELP_READ "Read value from LwM2M resource\nread [PATH] [OPTIONS]...\n" \
#define LWM2M_HELP_EXEC "Execute a resource\nexec PATH\n"
#define LWM2M_HELP_READ "Read value from LwM2M resource\nread PATH [OPTIONS]\n" \
"-s \tRead value as string(default)\n" \
"-b \tRead value as bool (1/0)\n" \
"-uX\tRead value as uintX_t\n" \
"-sX\tRead value as intX_t\n" \
"-f \tRead value as float\n"
#define LWM2M_HELP_WRITE "Write into LwM2M resource\nwrite [PATH] [OPTIONS]... [VALUE]\n" \
"-f \tRead value as float\n"
#define LWM2M_HELP_WRITE "Write into LwM2M resource\nwrite PATH [OPTIONS] VALUE\n" \
"-s \tValue as string(default)\n" \
"-b \tValue as bool\n" \
"-uX\tValue as uintX_t\n" \
"-sX\tValue as intX_t\n" \
"-f \tValue as float\n"
"-f \tValue as float\n"
#define LWM2M_HELP_START "Start the LwM2M RD (Registration / Discovery) Client\n" \
"start EP_NAME [OPTIONS] [BOOTSTRAP FLAG]\n" \
"-b \tSet the bootstrap flag (default 0)\n"
#define LWM2M_HELP_STOP "Stop the LwM2M RD (De-register) Client\nstop [OPTIONS]\n" \
"-f \tForce close the connection\n"
#define LWM2M_HELP_UPDATE "Trigger Registration Update of the LwM2M RD Client\n"
static int cmd_send(const struct shell *sh, size_t argc, char **argv)
{
@ -78,7 +86,7 @@ static int cmd_send(const struct shell *sh, size_t argc, char **argv)
}
ret = lwm2m_engine_send(ctx, (const char **)&(argv[ignore_cnt]),
path_cnt, confirmable);
path_cnt, confirmable);
if (ret < 0) {
shell_error(sh, "can't do send operation, request failed\n");
return -ENOEXEC;
@ -94,8 +102,8 @@ static int cmd_exec(const struct shell *sh, size_t argc, char **argv)
shell_error(sh, "no lwm2m context yet\n");
return -ENOEXEC;
}
int ignore_cnt = 2; /* Subcmd + PATH */
int ignore_cnt = 2; /* Subcmd + PATH */
const char *pathstr = argv[1];
struct lwm2m_obj_path path;
int ret = lwm2m_string_to_path(pathstr, &path, '/'); /* translate path -> path_obj */
@ -106,6 +114,7 @@ static int cmd_exec(const struct shell *sh, size_t argc, char **argv)
}
struct lwm2m_engine_res *res = lwm2m_engine_get_res(&path);
if (ret < 0) {
shell_error(sh, "Resource not found (err %d)\n", ret);
return -EINVAL;
@ -116,8 +125,9 @@ static int cmd_exec(const struct shell *sh, size_t argc, char **argv)
return -EINVAL;
}
ret = res->execute_cb(path.obj_inst_id, argv[ignore_cnt], argc-ignore_cnt);
if (ret<0) {
ret = res->execute_cb(path.obj_inst_id, argv[ignore_cnt],
argc - ignore_cnt);
if (ret < 0) {
shell_error(sh, "returned (err %d)\n", ret);
return -ENOEXEC;
}
@ -149,71 +159,102 @@ static int cmd_read(const struct shell *sh, size_t argc, char **argv)
if (strcmp(dtype, "-s") == 0) {
const char *buff;
uint16_t buff_len = 0;
uint8_t buff_flags;
ret = lwm2m_engine_get_res_data(pathstr, (void **)&buff, &buff_len, &buff_flags);
ret = lwm2m_engine_get_res_buf(pathstr, (void **)&buff,
&buff_len, NULL, NULL);
if (ret != 0) {
goto out;
}
shell_print(sh, "%s\n", buff);
} else if (strcmp(dtype, "-s8") == 0) {
int8_t temp = 0;
ret = lwm2m_engine_get_s8(pathstr, &temp);
if (ret != 0) {
goto out;
}
shell_print(sh, "%d\n", temp);
} else if (strcmp(dtype, "-s16") == 0) {
int16_t temp = 0;
ret = lwm2m_engine_get_s16(pathstr, &temp);
if (ret != 0) {
goto out;
}
shell_print(sh, "%d\n", temp);
} else if (strcmp(dtype, "-s32") == 0) {
int32_t temp = 0;
ret = lwm2m_engine_get_s32(pathstr, &temp);
if (ret != 0) {
goto out;
}
shell_print(sh, "%d\n", temp);
} else if (strcmp(dtype, "-s64") == 0) {
int64_t temp = 0;
ret = lwm2m_engine_get_s64(pathstr, &temp);
if (ret != 0) {
goto out;
}
shell_print(sh, "%lld\n", temp);
} else if (strcmp(dtype, "-u8") == 0) {
uint8_t temp = 0;
ret = lwm2m_engine_get_u8(pathstr, &temp);
if (ret != 0) {
goto out;
}
shell_print(sh, "%d\n", temp);
} else if (strcmp(dtype, "-u16") == 0) {
uint16_t temp = 0;
ret = lwm2m_engine_get_u16(pathstr, &temp);
if (ret != 0) {
goto out;
}
shell_print(sh, "%d\n", temp);
} else if (strcmp(dtype, "-u32") == 0) {
uint32_t temp = 0;
ret = lwm2m_engine_get_u32(pathstr, &temp);
if (ret != 0) {
goto out;
}
shell_print(sh, "%d\n", temp);
} else if (strcmp(dtype, "-u64") == 0) {
uint64_t temp = 0;
ret = lwm2m_engine_get_u64(pathstr, &temp);
if (ret != 0) {
goto out;
}
shell_print(sh, "%lld\n", temp);
} else if (strcmp(dtype, "-f") == 0) {
double temp = 0;
ret = lwm2m_engine_get_float(pathstr, &temp);
if (ret != 0) {
goto out;
}
shell_print(sh, "%f\n", temp);
} else if (strcmp(dtype, "-b") == 0) {
bool temp;
ret = lwm2m_engine_get_bool(pathstr, &temp);
if (ret != 0) {
goto out;
}
shell_print(sh, "%d\n", temp);
} else {
shell_error(sh, "can't recognize data type %s\n", dtype);
shell_help(sh);
return -EINVAL;
}
if (ret < 0) {
shell_error(sh, "can't do read operation, request failed (err %d)\n", ret);
return -EINVAL;
}
return 0;
out:
shell_error(sh, "can't do read operation, request failed (err %d)\n", ret);
return -EINVAL;
}
static int cmd_write(const struct shell *sh, size_t argc, char **argv)
@ -253,27 +294,37 @@ static int cmd_write(const struct shell *sh, size_t argc, char **argv)
ret = lwm2m_engine_set_float(pathstr, &new);
} else { /* All the types using stdlib funcs*/
char *e;
if (strcmp(dtype, "-s8") == 0) {
ret = lwm2m_engine_set_s8(pathstr, strtol(value, &e, 10));
ret = lwm2m_engine_set_s8(pathstr,
strtol(value, &e, 10));
} else if (strcmp(dtype, "-s16") == 0) {
ret = lwm2m_engine_set_s16(pathstr, strtol(value, &e, 10));
ret = lwm2m_engine_set_s16(pathstr,
strtol(value, &e, 10));
} else if (strcmp(dtype, "-s32") == 0) {
ret = lwm2m_engine_set_s32(pathstr, strtol(value, &e, 10));
ret = lwm2m_engine_set_s32(pathstr,
strtol(value, &e, 10));
} else if (strcmp(dtype, "-s64") == 0) {
ret = lwm2m_engine_set_s64(pathstr, strtoll(value, &e, 10));
ret = lwm2m_engine_set_s64(pathstr,
strtoll(value, &e, 10));
} else if (strcmp(dtype, "-u8") == 0) {
ret = lwm2m_engine_set_u8(pathstr, strtoul(value, &e, 10));
ret = lwm2m_engine_set_u8(pathstr,
strtoul(value, &e, 10));
} else if (strcmp(dtype, "-u16") == 0) {
ret = lwm2m_engine_set_u16(pathstr, strtoul(value, &e, 10));
ret = lwm2m_engine_set_u16(pathstr,
strtoul(value, &e, 10));
} else if (strcmp(dtype, "-u32") == 0) {
ret = lwm2m_engine_set_u32(pathstr, strtoul(value, &e, 10));
ret = lwm2m_engine_set_u32(pathstr,
strtoul(value, &e, 10));
} else if (strcmp(dtype, "-u64") == 0) {
ret = lwm2m_engine_set_u64(pathstr, strtoull(value, &e, 10));
ret = lwm2m_engine_set_u64(pathstr,
strtoull(value, &e, 10));
} else if (strcmp(dtype, "-b") == 0) {
ret = lwm2m_engine_set_bool(pathstr, strtoul(value, &e, 10));
ret = lwm2m_engine_set_bool(pathstr,
strtoul(value, &e, 10));
} else {
shell_error(sh, "can't recognize data type %s\n", dtype);
shell_error(sh, "can't recognize data type %s\n",
dtype);
shell_help(sh);
return -EINVAL;
}
@ -285,18 +336,113 @@ static int cmd_write(const struct shell *sh, size_t argc, char **argv)
}
if (ret < 0) {
shell_error(sh, "can't do write operation, request failed (err %d)\n", ret);
shell_error(
sh,
"can't do write operation, request failed (err %d)\n",
ret);
return -ENOEXEC;
}
return 0;
}
static int cmd_start(const struct shell *sh, size_t argc, char **argv)
{
struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx();
SHELL_STATIC_SUBCMD_SET_CREATE(sub_lwm2m,
SHELL_COND_CMD_ARG(CONFIG_LWM2M_VERSION_1_1, send, NULL, LWM2M_HELP_SEND, cmd_send, 1, 9),
if (!ctx) {
shell_error(sh, "no lwm2m context yet\n");
return -ENOEXEC;
}
uint32_t bootstrap_flag = 0;
if (argc == 3) {
shell_error(sh, "no specifier or value\n");
shell_help(sh);
return -EINVAL;
} else if (argc == 4) {
if (strcmp(argv[2], "-b") != 0) {
shell_error(sh, "unknown specifier %s\n", argv[2]);
shell_help(sh);
return -EINVAL;
}
char *e;
bootstrap_flag = strtol(argv[3], &e, 10);
if (*e != '\0') {
shell_error(sh, "Invalid number: %s\n", argv[3]);
shell_help(sh);
return -EINVAL;
}
}
int ret = lwm2m_rd_client_start(ctx, argv[1], bootstrap_flag,
ctx->event_cb, ctx->observe_cb);
if (ret < 0) {
shell_error(
sh,
"can't do start operation, request failed (err %d)\n",
ret);
return -ENOEXEC;
}
return 0;
}
static int cmd_stop(const struct shell *sh, size_t argc, char **argv)
{
struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx();
if (!ctx) {
shell_error(sh, "no lwm2m context yet\n");
return -ENOEXEC;
}
bool forcefully = true;
if (argc == 2) {
if (strcmp(argv[1], "-f") != 0) {
shell_error(sh, "can't recognize specifier %s\n",
argv[1]);
shell_help(sh);
return -EINVAL;
}
forcefully = false;
}
int ret = lwm2m_rd_client_stop(ctx, ctx->event_cb, forcefully);
if (ret < 0) {
shell_error(
sh,
"can't do stop operation, request failed (err %d)\n",
ret);
return -ENOEXEC;
}
return 0;
}
static int cmd_update(const struct shell *sh, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx();
if (!ctx) {
shell_error(sh, "no lwm2m context yet\n");
return -ENOEXEC;
}
lwm2m_rd_client_update();
return 0;
}
SHELL_STATIC_SUBCMD_SET_CREATE(
sub_lwm2m,
SHELL_COND_CMD_ARG(CONFIG_LWM2M_VERSION_1_1, send, NULL,
LWM2M_HELP_SEND, cmd_send, 1, 9),
SHELL_CMD_ARG(exec, NULL, LWM2M_HELP_EXEC, cmd_exec, 2, 9),
SHELL_CMD_ARG(read, NULL, LWM2M_HELP_READ, cmd_read, 2, 1),
SHELL_CMD_ARG(write, NULL, LWM2M_HELP_WRITE, cmd_write, 3, 1),
SHELL_CMD_ARG(start, NULL, LWM2M_HELP_START, cmd_start, 2, 2),
SHELL_CMD_ARG(stop, NULL, LWM2M_HELP_STOP, cmd_stop, 1, 1),
SHELL_CMD_ARG(update, NULL, LWM2M_HELP_UPDATE, cmd_update, 1, 0),
SHELL_SUBCMD_SET_END);
SHELL_COND_CMD_ARG_REGISTER(CONFIG_LWM2M_SHELL, lwm2m, &sub_lwm2m, LWM2M_HELP_CMD, NULL, 1, 0);
SHELL_COND_CMD_ARG_REGISTER(CONFIG_LWM2M_SHELL, lwm2m, &sub_lwm2m,
LWM2M_HELP_CMD, NULL, 1, 0);