1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #define LOG_MODULE_NAME net_lwm2m_shell
7 #define LOG_LEVEL	CONFIG_LWM2M_LOG_LEVEL
8 
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
11 
12 #include <stddef.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include <zephyr/kernel.h>
18 #include <zephyr/net/lwm2m.h>
19 #include <zephyr/shell/shell.h>
20 
21 #include <lwm2m_engine.h>
22 #include <lwm2m_util.h>
23 
24 #define LWM2M_HELP_CMD "LwM2M commands"
25 #define LWM2M_HELP_SEND "send PATHS\nLwM2M SEND operation\n"
26 #define LWM2M_HELP_EXEC "exec PATH [PARAM]\nExecute a resource\n"
27 #define LWM2M_HELP_READ "read PATH [OPTIONS]\nRead value from LwM2M resource\n" \
28 	"-x \tRead value as hex stream (default)\n" \
29 	"-s \tRead value as string\n" \
30 	"-b \tRead value as bool (1/0)\n" \
31 	"-uX\tRead value as uintX_t\n" \
32 	"-sX\tRead value as intX_t\n" \
33 	"-f \tRead value as float\n" \
34 	"-t \tRead value as time_t\n"
35 #define LWM2M_HELP_WRITE "write PATH [OPTIONS] VALUE\nWrite into LwM2M resource\n" \
36 	"-s \tWrite value as string (default)\n" \
37 	"-b \tWrite value as bool\n" \
38 	"-uX\tWrite value as uintX_t\n" \
39 	"-sX\tWrite value as intX_t\n" \
40 	"-f \tWrite value as float\n" \
41 	"-t \tWrite value as time_t\n"
42 #define LWM2M_HELP_CREATE "create PATH\nCreate object or resource instance\n"
43 #define LWM2M_HELP_DELETE "delete PATH\nDelete object or resource instance\n"
44 #define LWM2M_HELP_START "start EP_NAME [BOOTSTRAP FLAG]\n" \
45 	"Start the LwM2M RD (Registration / Discovery) Client\n" \
46 	"-b \tSet the bootstrap flag (default 0)\n"
47 #define LWM2M_HELP_STOP "stop [OPTIONS]\nStop the LwM2M RD (De-register) Client\n" \
48 	"-f \tForce close the connection\n"
49 #define LWM2M_HELP_UPDATE "Trigger Registration Update of the LwM2M RD Client\n"
50 #define LWM2M_HELP_PAUSE "LwM2M engine thread pause"
51 #define LWM2M_HELP_RESUME "LwM2M engine thread resume"
52 #define LWM2M_HELP_LOCK "Lock the LwM2M registry"
53 #define LWM2M_HELP_UNLOCK "Unlock the LwM2M registry"
54 #define LWM2M_HELP_CACHE "cache PATH NUM\nEnable data cache for resource\n" \
55 	"PATH is LwM2M path\n" \
56 	"NUM how many elements to cache\n" \
57 
send_cb(enum lwm2m_send_status status)58 static void send_cb(enum lwm2m_send_status status)
59 {
60 	LOG_INF("SEND status: %d\n", status);
61 }
62 
cmd_send(const struct shell * sh,size_t argc,char ** argv)63 static int cmd_send(const struct shell *sh, size_t argc, char **argv)
64 {
65 	int ret = 0;
66 	struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx();
67 	int path_cnt = argc - 1;
68 	struct lwm2m_obj_path lwm2m_path_list[CONFIG_LWM2M_COMPOSITE_PATH_LIST_SIZE];
69 
70 	if (!ctx) {
71 		shell_error(sh, "no lwm2m context yet\n");
72 		return -ENOEXEC;
73 	}
74 
75 	if (argc < 2) {
76 		shell_error(sh, "no path(s)\n");
77 		shell_help(sh);
78 		return -EINVAL;
79 	}
80 
81 	if (path_cnt > CONFIG_LWM2M_COMPOSITE_PATH_LIST_SIZE) {
82 		return -E2BIG;
83 	}
84 
85 	for (int i = 0; i < path_cnt; i++) {
86 		const char *p = argv[1 + i];
87 		/* translate path -> path_obj */
88 		ret = lwm2m_string_to_path(p, &lwm2m_path_list[i], '/');
89 		if (ret < 0) {
90 			return ret;
91 		}
92 	}
93 
94 	ret = lwm2m_send_cb(ctx, lwm2m_path_list, path_cnt, send_cb);
95 
96 	if (ret < 0) {
97 		shell_error(sh, "can't do send operation, request failed (%d)\n", ret);
98 		return -ENOEXEC;
99 	}
100 	return 0;
101 }
102 
cmd_exec(const struct shell * sh,size_t argc,char ** argv)103 static int cmd_exec(const struct shell *sh, size_t argc, char **argv)
104 {
105 	struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx();
106 
107 	if (!ctx) {
108 		shell_error(sh, "no lwm2m context yet\n");
109 		return -ENOEXEC;
110 	}
111 
112 	const char *pathstr = argv[1];
113 	struct lwm2m_obj_path path;
114 	int ret = lwm2m_string_to_path(pathstr, &path, '/'); /* translate path -> path_obj */
115 
116 	if (ret < 0) {
117 		shell_error(sh, "Illegal path (PATH %s)\n", pathstr);
118 		return -EINVAL;
119 	}
120 
121 	struct lwm2m_engine_res *res = lwm2m_engine_get_res(&path);
122 
123 	if (res == NULL) {
124 		shell_error(sh, "Resource not found\n");
125 		return -EINVAL;
126 	}
127 
128 	if (!res->execute_cb) {
129 		shell_error(sh, "No execute callback\n!");
130 		return -EINVAL;
131 	}
132 
133 	/* 0: exec, 1:<path> 2:[<param>] */
134 	char *param = (argc == 3) ? argv[2] : NULL;
135 	size_t param_len = param ? strlen(param) + 1 : 0;
136 
137 	ret = res->execute_cb(path.obj_inst_id, param, param_len);
138 	if (ret < 0) {
139 		shell_error(sh, "returned (err %d)\n", ret);
140 		return -ENOEXEC;
141 	}
142 
143 	return 0;
144 }
145 
cmd_read(const struct shell * sh,size_t argc,char ** argv)146 static int cmd_read(const struct shell *sh, size_t argc, char **argv)
147 {
148 	struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx();
149 
150 	if (!ctx) {
151 		shell_error(sh, "no lwm2m context yet\n");
152 		return -ENOEXEC;
153 	}
154 
155 	if (argc < 2) {
156 		shell_error(sh, "no arguments or path(s)\n");
157 		shell_help(sh);
158 		return -EINVAL;
159 	}
160 	const char *dtype = "-x"; /* default */
161 	const char *pathstr = argv[1];
162 	int ret = 0;
163 	struct lwm2m_obj_path path;
164 
165 	ret = lwm2m_string_to_path(pathstr, &path, '/');
166 	if (ret < 0) {
167 		return ret;
168 	}
169 
170 	if (argc > 2) { /* read + path + options(data type) */
171 		dtype = argv[2];
172 	}
173 	if (strcmp(dtype, "-x") == 0) {
174 		const char *buff;
175 		uint16_t buff_len = 0;
176 
177 		ret = lwm2m_get_res_buf(&path, (void **)&buff,
178 					NULL, &buff_len, NULL);
179 		if (ret != 0) {
180 			goto out;
181 		}
182 		shell_hexdump(sh, buff, buff_len);
183 	} else if (strcmp(dtype, "-s") == 0) {
184 		const char *buff;
185 		uint16_t buff_len = 0;
186 
187 		ret = lwm2m_get_res_buf(&path, (void **)&buff,
188 					NULL, &buff_len, NULL);
189 		if (ret != 0) {
190 			goto out;
191 		}
192 		shell_print(sh, "%.*s\n", buff_len, buff);
193 	} else if (strcmp(dtype, "-s8") == 0) {
194 		int8_t temp = 0;
195 
196 		ret = lwm2m_get_s8(&path, &temp);
197 		if (ret != 0) {
198 			goto out;
199 		}
200 		shell_print(sh, "%d\n", temp);
201 	} else if (strcmp(dtype, "-s16") == 0) {
202 		int16_t temp = 0;
203 
204 		ret = lwm2m_get_s16(&path, &temp);
205 		if (ret != 0) {
206 			goto out;
207 		}
208 		shell_print(sh, "%d\n", temp);
209 	} else if (strcmp(dtype, "-s32") == 0) {
210 		int32_t temp = 0;
211 
212 		ret = lwm2m_get_s32(&path, &temp);
213 		if (ret != 0) {
214 			goto out;
215 		}
216 		shell_print(sh, "%d\n", temp);
217 	} else if (strcmp(dtype, "-s64") == 0) {
218 		int64_t temp = 0;
219 
220 		ret = lwm2m_get_s64(&path, &temp);
221 		if (ret != 0) {
222 			goto out;
223 		}
224 		shell_print(sh, "%lld\n", temp);
225 	} else if (strcmp(dtype, "-u8") == 0) {
226 		uint8_t temp = 0;
227 
228 		ret = lwm2m_get_u8(&path, &temp);
229 		if (ret != 0) {
230 			goto out;
231 		}
232 		shell_print(sh, "%d\n", temp);
233 	} else if (strcmp(dtype, "-u16") == 0) {
234 		uint16_t temp = 0;
235 
236 		ret = lwm2m_get_u16(&path, &temp);
237 		if (ret != 0) {
238 			goto out;
239 		}
240 		shell_print(sh, "%d\n", temp);
241 	} else if (strcmp(dtype, "-u32") == 0) {
242 		uint32_t temp = 0;
243 
244 		ret = lwm2m_get_u32(&path, &temp);
245 		if (ret != 0) {
246 			goto out;
247 		}
248 		shell_print(sh, "%d\n", temp);
249 	} else if (strcmp(dtype, "-f") == 0) {
250 		double temp = 0;
251 
252 		ret = lwm2m_get_f64(&path, &temp);
253 		if (ret != 0) {
254 			goto out;
255 		}
256 		shell_print(sh, "%f\n", temp);
257 	} else if (strcmp(dtype, "-b") == 0) {
258 		bool temp;
259 
260 		ret = lwm2m_get_bool(&path, &temp);
261 		if (ret != 0) {
262 			goto out;
263 		}
264 		shell_print(sh, "%d\n", temp);
265 	} else if (strcmp(dtype, "-t") == 0) {
266 		time_t temp;
267 
268 		ret = lwm2m_get_time(&path, &temp);
269 		if (ret != 0) {
270 			goto out;
271 		}
272 		shell_print(sh, "%lld\n", temp);
273 	} else {
274 		shell_error(sh, "can't recognize data type %s\n", dtype);
275 		shell_help(sh);
276 		return -EINVAL;
277 	}
278 	return 0;
279 out:
280 	shell_error(sh, "can't do read operation, request failed (err %d)\n", ret);
281 	return -EINVAL;
282 }
283 
cmd_write(const struct shell * sh,size_t argc,char ** argv)284 static int cmd_write(const struct shell *sh, size_t argc, char **argv)
285 {
286 	struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx();
287 
288 	if (!ctx) {
289 		shell_error(sh, "no lwm2m context yet\n");
290 		return -ENOEXEC;
291 	}
292 
293 	if (argc < 3) {
294 		shell_error(sh, "no arguments or path(s)\n");
295 		shell_help(sh);
296 		return -EINVAL;
297 	}
298 
299 	int ret = 0;
300 	const char *pathstr = argv[1];
301 	const char *dtype;
302 	char *value;
303 	struct lwm2m_obj_path path;
304 
305 	ret = lwm2m_string_to_path(pathstr, &path, '/');
306 	if (ret < 0) {
307 		return ret;
308 	}
309 
310 	if (argc == 4) { /* write path options value */
311 		dtype = argv[2];
312 		value = argv[3];
313 	} else { /* write path value */
314 		dtype = "-s";
315 		value = argv[2];
316 	}
317 
318 	if (strcmp(dtype, "-s") == 0) {
319 		ret = lwm2m_set_string(&path, value);
320 	} else if (strcmp(dtype, "-f") == 0) {
321 		double new = 0;
322 
323 		ret = lwm2m_atof(value, &new); /* Convert string -> float */
324 		if (ret == 0) {
325 			ret = lwm2m_set_f64(&path, new);
326 		}
327 	} else { /* All the types using stdlib funcs*/
328 		char *e;
329 
330 		if (strcmp(dtype, "-s8") == 0) {
331 			ret = lwm2m_set_s8(&path, strtol(value, &e, 10));
332 		} else if (strcmp(dtype, "-s16") == 0) {
333 			ret = lwm2m_set_s16(&path, strtol(value, &e, 10));
334 		} else if (strcmp(dtype, "-s32") == 0) {
335 			ret = lwm2m_set_s32(&path, strtol(value, &e, 10));
336 		} else if (strcmp(dtype, "-s64") == 0) {
337 			ret = lwm2m_set_s64(&path, strtoll(value, &e, 10));
338 		} else if (strcmp(dtype, "-u8") == 0) {
339 			ret = lwm2m_set_u8(&path, strtoul(value, &e, 10));
340 		} else if (strcmp(dtype, "-u16") == 0) {
341 			ret = lwm2m_set_u16(&path, strtoul(value, &e, 10));
342 		} else if (strcmp(dtype, "-u32") == 0) {
343 			ret = lwm2m_set_u32(&path, strtoul(value, &e, 10));
344 		} else if (strcmp(dtype, "-b") == 0) {
345 			ret = lwm2m_set_bool(&path, strtoul(value, &e, 10));
346 		} else if (strcmp(dtype, "-t") == 0) {
347 			ret = lwm2m_set_time(&path, strtoll(value, &e, 10));
348 		} else {
349 			shell_error(sh, "can't recognize data type %s\n",
350 				    dtype);
351 			shell_help(sh);
352 			return -EINVAL;
353 		}
354 		if (*e != '\0') {
355 			shell_error(sh, "Invalid number: %s\n", value);
356 			shell_help(sh);
357 			return -EINVAL;
358 		}
359 	}
360 
361 	if (ret < 0) {
362 		shell_error(
363 			sh,
364 			"can't do write operation, request failed (err %d)\n",
365 			ret);
366 		return -ENOEXEC;
367 	}
368 
369 	return 0;
370 }
371 
cmd_create_or_delete(const struct shell * sh,bool delete,size_t argc,char ** argv)372 static int cmd_create_or_delete(const struct shell *sh, bool delete, size_t argc, char **argv)
373 {
374 	struct lwm2m_obj_path path;
375 	int ret;
376 
377 	if (argc < 2) {
378 		shell_error(sh, "No object ID given\n");
379 		shell_help(sh);
380 		return -EINVAL;
381 	}
382 
383 	ret = lwm2m_string_to_path(argv[1], &path, '/');
384 	if (ret < 0) {
385 		shell_error(sh, "failed to read path (%d)\n", ret);
386 		return -ENOEXEC;
387 	}
388 
389 	if (delete) {
390 		switch (path.level) {
391 		case LWM2M_PATH_LEVEL_RESOURCE_INST:
392 			ret = lwm2m_delete_res_inst(&path);
393 			break;
394 		case LWM2M_PATH_LEVEL_OBJECT_INST:
395 			ret = lwm2m_delete_object_inst(&path);
396 			break;
397 		default:
398 			return -ENOEXEC;
399 		}
400 	} else {
401 		switch (path.level) {
402 		case LWM2M_PATH_LEVEL_RESOURCE_INST:
403 			ret = lwm2m_create_res_inst(&path);
404 			break;
405 		case LWM2M_PATH_LEVEL_OBJECT_INST:
406 			ret = lwm2m_create_object_inst(&path);
407 			break;
408 		default:
409 			return -ENOEXEC;
410 		}
411 	}
412 
413 	if (ret < 0) {
414 		shell_error(sh, "operation failed, %d\n", ret);
415 		return -ENOEXEC;
416 	}
417 
418 	return 0;
419 }
420 
cmd_create(const struct shell * sh,size_t argc,char ** argv)421 static int cmd_create(const struct shell *sh, size_t argc, char **argv)
422 {
423 	return cmd_create_or_delete(sh, false, argc, argv);
424 }
425 
cmd_delete(const struct shell * sh,size_t argc,char ** argv)426 static int cmd_delete(const struct shell *sh, size_t argc, char **argv)
427 {
428 	return cmd_create_or_delete(sh, true, argc, argv);
429 }
430 
cmd_start(const struct shell * sh,size_t argc,char ** argv)431 static int cmd_start(const struct shell *sh, size_t argc, char **argv)
432 {
433 	struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx();
434 
435 	if (!ctx) {
436 		shell_error(sh, "no lwm2m context yet\n");
437 		return -ENOEXEC;
438 	}
439 	uint32_t bootstrap_flag = 0;
440 
441 	if (argc == 3) {
442 		shell_error(sh, "no specifier or value\n");
443 		shell_help(sh);
444 		return -EINVAL;
445 	} else if (argc == 4) {
446 		if (strcmp(argv[2], "-b") != 0) {
447 			shell_error(sh, "unknown specifier %s\n", argv[2]);
448 			shell_help(sh);
449 			return -EINVAL;
450 		}
451 
452 		char *e;
453 
454 		bootstrap_flag = strtol(argv[3], &e, 10);
455 		if (*e != '\0') {
456 			shell_error(sh, "Invalid number: %s\n", argv[3]);
457 			shell_help(sh);
458 			return -EINVAL;
459 		}
460 	}
461 	int ret = lwm2m_rd_client_start(ctx, argv[1], bootstrap_flag,
462 					ctx->event_cb, ctx->observe_cb);
463 	if (ret < 0) {
464 		shell_error(
465 			sh,
466 			"can't do start operation, request failed (err %d)\n",
467 			ret);
468 		return -ENOEXEC;
469 	}
470 	return 0;
471 }
472 
cmd_stop(const struct shell * sh,size_t argc,char ** argv)473 static int cmd_stop(const struct shell *sh, size_t argc, char **argv)
474 {
475 	struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx();
476 
477 	if (!ctx) {
478 		shell_error(sh, "no lwm2m context yet\n");
479 		return -ENOEXEC;
480 	}
481 	bool forcefully = true;
482 
483 	if (argc == 2) {
484 		if (strcmp(argv[1], "-f") != 0) {
485 			shell_error(sh, "can't recognize specifier %s\n",
486 				    argv[1]);
487 			shell_help(sh);
488 			return -EINVAL;
489 		}
490 		forcefully = false;
491 	}
492 	int ret = lwm2m_rd_client_stop(ctx, ctx->event_cb, forcefully);
493 
494 	if (ret < 0) {
495 		shell_error(
496 			sh,
497 			"can't do stop operation, request failed (err %d)\n",
498 			ret);
499 		return -ENOEXEC;
500 	}
501 	return 0;
502 }
503 
cmd_update(const struct shell * sh,size_t argc,char ** argv)504 static int cmd_update(const struct shell *sh, size_t argc, char **argv)
505 {
506 	ARG_UNUSED(argc);
507 	ARG_UNUSED(argv);
508 	struct lwm2m_ctx *ctx = lwm2m_rd_client_ctx();
509 
510 	if (!ctx) {
511 		shell_error(sh, "no lwm2m context yet\n");
512 		return -ENOEXEC;
513 	}
514 	lwm2m_rd_client_update();
515 	return 0;
516 }
517 
cmd_pause(const struct shell * sh,size_t argc,char ** argv)518 static int cmd_pause(const struct shell *sh, size_t argc, char **argv)
519 {
520 	ARG_UNUSED(sh);
521 	ARG_UNUSED(argc);
522 	ARG_UNUSED(argv);
523 
524 	return lwm2m_engine_pause();
525 }
526 
cmd_resume(const struct shell * sh,size_t argc,char ** argv)527 static int cmd_resume(const struct shell *sh, size_t argc, char **argv)
528 {
529 	ARG_UNUSED(sh);
530 	ARG_UNUSED(argc);
531 	ARG_UNUSED(argv);
532 
533 	return lwm2m_engine_resume();
534 }
535 
cmd_lock(const struct shell * sh,size_t argc,char ** argv)536 static int cmd_lock(const struct shell *sh, size_t argc, char **argv)
537 {
538 	ARG_UNUSED(sh);
539 	ARG_UNUSED(argc);
540 	ARG_UNUSED(argv);
541 
542 	lwm2m_registry_lock();
543 	return 0;
544 }
545 
cmd_unlock(const struct shell * sh,size_t argc,char ** argv)546 static int cmd_unlock(const struct shell *sh, size_t argc, char **argv)
547 {
548 	ARG_UNUSED(sh);
549 	ARG_UNUSED(argc);
550 	ARG_UNUSED(argv);
551 
552 	lwm2m_registry_unlock();
553 	return 0;
554 }
555 
cmd_cache(const struct shell * sh,size_t argc,char ** argv)556 static int cmd_cache(const struct shell *sh, size_t argc, char **argv)
557 {
558 #if (K_HEAP_MEM_POOL_SIZE > 0)
559 	int rc;
560 	int elems;
561 	struct lwm2m_time_series_elem *cache;
562 	struct lwm2m_obj_path obj_path;
563 
564 	if (argc != 3) {
565 		shell_error(sh, "wrong parameters\n");
566 		return -EINVAL;
567 	}
568 
569 	/* translate path -> path_obj */
570 	rc = lwm2m_string_to_path(argv[1], &obj_path, '/');
571 	if (rc < 0) {
572 		return rc;
573 	}
574 
575 	if (obj_path.level < 3) {
576 		shell_error(sh, "Path string not correct\n");
577 		return -EINVAL;
578 	}
579 
580 	if (lwm2m_cache_entry_get_by_object(&obj_path)) {
581 		shell_error(sh, "Cache already enabled for %s\n", argv[1]);
582 		return -ENOEXEC;
583 	}
584 
585 	elems = atoi(argv[2]);
586 	if (elems < 1) {
587 		shell_error(sh, "Size must be 1 or more (given %d)\n", elems);
588 		return -EINVAL;
589 	}
590 
591 	cache = k_malloc(sizeof(struct lwm2m_time_series_elem) * elems);
592 	if (!cache) {
593 		shell_error(sh, "Out of memory\n");
594 		return -ENOEXEC;
595 	}
596 
597 	rc = lwm2m_enable_cache(&obj_path, cache, elems);
598 	if (rc) {
599 		shell_error(sh, "lwm2m_enable_cache(%u/%u/%u/%u, %p, %d) returned %d\n",
600 			    obj_path.obj_id, obj_path.obj_inst_id, obj_path.res_id,
601 			    obj_path.res_inst_id, cache, elems, rc);
602 		k_free(cache);
603 		return -ENOEXEC;
604 	}
605 
606 	return 0;
607 #else
608 	shell_error(sh, "No heap configured\n");
609 	return -ENOEXEC;
610 #endif
611 }
612 
613 SHELL_STATIC_SUBCMD_SET_CREATE(
614 	sub_lwm2m,
615 	SHELL_COND_CMD_ARG(CONFIG_LWM2M_VERSION_1_1, send, NULL,
616 			   LWM2M_HELP_SEND, cmd_send, 1, 9),
617 	SHELL_CMD_ARG(exec, NULL, LWM2M_HELP_EXEC, cmd_exec, 2, 1),
618 	SHELL_CMD_ARG(read, NULL, LWM2M_HELP_READ, cmd_read, 2, 1),
619 	SHELL_CMD_ARG(write, NULL, LWM2M_HELP_WRITE, cmd_write, 3, 1),
620 	SHELL_CMD_ARG(create, NULL, LWM2M_HELP_CREATE, cmd_create, 2, 0),
621 	SHELL_CMD_ARG(delete, NULL, LWM2M_HELP_DELETE, cmd_delete, 2, 0),
622 	SHELL_CMD_ARG(cache, NULL, LWM2M_HELP_CACHE, cmd_cache, 3, 0),
623 	SHELL_CMD_ARG(start, NULL, LWM2M_HELP_START, cmd_start, 2, 2),
624 	SHELL_CMD_ARG(stop, NULL, LWM2M_HELP_STOP, cmd_stop, 1, 1),
625 	SHELL_CMD_ARG(update, NULL, LWM2M_HELP_UPDATE, cmd_update, 1, 0),
626 	SHELL_CMD_ARG(pause, NULL, LWM2M_HELP_PAUSE, cmd_pause, 1, 0),
627 	SHELL_CMD_ARG(resume, NULL, LWM2M_HELP_RESUME, cmd_resume, 1, 0),
628 	SHELL_CMD_ARG(lock, NULL, LWM2M_HELP_LOCK, cmd_lock, 1, 0),
629 	SHELL_CMD_ARG(unlock, NULL, LWM2M_HELP_UNLOCK, cmd_unlock, 1, 0),
630 
631 	SHELL_SUBCMD_SET_END);
632 SHELL_COND_CMD_ARG_REGISTER(CONFIG_LWM2M_SHELL, lwm2m, &sub_lwm2m,
633 			    LWM2M_HELP_CMD, NULL, 1, 0);
634