1 /** @file
2 * @brief Bluetooth Mesh shell
3 *
4 */
5
6 /*
7 * Copyright (c) 2017 Intel Corporation
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #include "syscfg/syscfg.h"
13
14 #if MYNEWT_VAL(BLE_MESH_SHELL)
15
16 #include <stdlib.h>
17 #include <ctype.h>
18 #include <errno.h>
19 #include "shell/shell.h"
20 #include "console/console.h"
21 #include "mesh/mesh.h"
22 #include "mesh/main.h"
23 #include "mesh/glue.h"
24 #include "mesh/testing.h"
25
26 /* Private includes for raw Network & Transport layer access */
27 #include "net.h"
28 #include "access.h"
29 #include "mesh_priv.h"
30 #include "lpn.h"
31 #include "transport.h"
32 #include "foundation.h"
33 #include "testing.h"
34 #include "settings.h"
35
36 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
37 #include "mesh/model_srv.h"
38 #include "mesh/model_cli.h"
39 #include "light_model.h"
40 #endif
41
42 /* This should be higher priority (lower value) than main task priority */
43 #define BLE_MESH_SHELL_TASK_PRIO 126
44 #define BLE_MESH_SHELL_STACK_SIZE 768
45
46 OS_TASK_STACK_DEFINE(g_blemesh_shell_stack, BLE_MESH_SHELL_STACK_SIZE);
47
48 struct os_task mesh_shell_task;
49 static struct os_eventq mesh_shell_queue;
50
51 #define CID_NVAL 0xffff
52 #define CID_VENDOR 0x05C3
53
54 /* Vendor Model data */
55 #define VND_MODEL_ID_1 0x1234
56
57 /* Default net, app & dev key values, unless otherwise specified */
58 static const u8_t default_key[16] = {
59 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
60 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
61 };
62
63 static struct {
64 u16_t local;
65 u16_t dst;
66 u16_t net_idx;
67 u16_t app_idx;
68 } net = {
69 .local = BT_MESH_ADDR_UNASSIGNED,
70 .dst = BT_MESH_ADDR_UNASSIGNED,
71 };
72
73 static struct bt_mesh_cfg_srv cfg_srv = {
74 .relay = BT_MESH_RELAY_DISABLED,
75 .beacon = BT_MESH_BEACON_ENABLED,
76 #if MYNEWT_VAL(BLE_MESH_FRIEND)
77 .frnd = BT_MESH_FRIEND_DISABLED,
78 #else
79 .frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
80 #endif
81 #if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
82 .gatt_proxy = BT_MESH_GATT_PROXY_DISABLED,
83 #else
84 .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
85 #endif
86
87 .default_ttl = 7,
88
89 /* 3 transmissions with 20ms interval */
90 .net_transmit = BT_MESH_TRANSMIT(2, 20),
91 .relay_retransmit = BT_MESH_TRANSMIT(2, 20),
92 };
93
94 #define CUR_FAULTS_MAX 4
95
96 static u8_t cur_faults[CUR_FAULTS_MAX];
97 static u8_t reg_faults[CUR_FAULTS_MAX * 2];
98
get_faults(u8_t * faults,u8_t faults_size,u8_t * dst,u8_t * count)99 static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
100 {
101 u8_t i, limit = *count;
102
103 for (i = 0, *count = 0; i < faults_size && *count < limit; i++) {
104 if (faults[i]) {
105 *dst++ = faults[i];
106 (*count)++;
107 }
108 }
109 }
110
fault_get_cur(struct bt_mesh_model * model,u8_t * test_id,u16_t * company_id,u8_t * faults,u8_t * fault_count)111 static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
112 u16_t *company_id, u8_t *faults, u8_t *fault_count)
113 {
114 printk("Sending current faults\n");
115 *test_id = 0x00;
116 *company_id = CID_VENDOR;
117 get_faults(cur_faults, sizeof(cur_faults), faults, fault_count);
118 return 0;
119 }
120
fault_get_reg(struct bt_mesh_model * model,u16_t cid,u8_t * test_id,u8_t * faults,u8_t * fault_count)121 static int fault_get_reg(struct bt_mesh_model *model, u16_t cid,
122 u8_t *test_id, u8_t *faults, u8_t *fault_count)
123 {
124 if (cid != CID_VENDOR) {
125 printk("Faults requested for unknown Company ID 0x%04x\n", cid);
126 return -EINVAL;
127 }
128
129 printk("Sending registered faults\n");
130 *test_id = 0x00;
131 get_faults(reg_faults, sizeof(reg_faults), faults, fault_count);
132 return 0;
133 }
134
fault_clear(struct bt_mesh_model * model,uint16_t cid)135 static int fault_clear(struct bt_mesh_model *model, uint16_t cid)
136 {
137 if (cid != CID_VENDOR) {
138 return -EINVAL;
139 }
140
141 memset(reg_faults, 0, sizeof(reg_faults));
142 return 0;
143 }
144
fault_test(struct bt_mesh_model * model,uint8_t test_id,uint16_t cid)145 static int fault_test(struct bt_mesh_model *model, uint8_t test_id,
146 uint16_t cid)
147 {
148 if (cid != CID_VENDOR) {
149 return -EINVAL;
150 }
151
152 if (test_id != 0x00) {
153 return -EINVAL;
154 }
155
156 return 0;
157 }
158
159 static const struct bt_mesh_health_srv_cb health_srv_cb = {
160 .fault_get_cur = fault_get_cur,
161 .fault_get_reg = fault_get_reg,
162 .fault_clear = fault_clear,
163 .fault_test = fault_test,
164 };
165
166 static struct bt_mesh_health_srv health_srv = {
167 .cb = &health_srv_cb,
168 };
169
170 static struct bt_mesh_model_pub health_pub;
171
health_pub_init(void)172 static void health_pub_init(void)
173 {
174 health_pub.msg = BT_MESH_HEALTH_FAULT_MSG(CUR_FAULTS_MAX);
175 }
176 #if MYNEWT_VAL(BLE_MESH_CFG_CLI)
177
178 static struct bt_mesh_cfg_cli cfg_cli = {
179 };
180
181 #endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */
182
183 #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
show_faults(u8_t test_id,u16_t cid,u8_t * faults,size_t fault_count)184 void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
185 {
186 size_t i;
187
188 if (!fault_count) {
189 printk("Health Test ID 0x%02x Company ID 0x%04x: no faults\n",
190 test_id, cid);
191 return;
192 }
193
194 printk("Health Test ID 0x%02x Company ID 0x%04x Fault Count %zu:\n",
195 test_id, cid, fault_count);
196
197 for (i = 0; i < fault_count; i++) {
198 printk("\t0x%02x\n", faults[i]);
199 }
200 }
201
health_current_status(struct bt_mesh_health_cli * cli,u16_t addr,u8_t test_id,u16_t cid,u8_t * faults,size_t fault_count)202 static void health_current_status(struct bt_mesh_health_cli *cli, u16_t addr,
203 u8_t test_id, u16_t cid, u8_t *faults,
204 size_t fault_count)
205 {
206 printk("Health Current Status from 0x%04x\n", addr);
207 show_faults(test_id, cid, faults, fault_count);
208 }
209
210 static struct bt_mesh_health_cli health_cli = {
211 .current_status = health_current_status,
212 };
213
214 #endif /* MYNEWT_VAL(BLE_MESH_HEALTH_CLI) */
215
216 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
217 static struct bt_mesh_gen_model_cli gen_onoff_cli;
218 static struct bt_mesh_model_pub gen_onoff_cli_pub;
219 static struct bt_mesh_model_pub gen_onoff_srv_pub;
220 static struct bt_mesh_gen_model_cli gen_level_cli;
221 static struct bt_mesh_model_pub gen_level_cli_pub;
222 static struct bt_mesh_model_pub gen_level_srv_pub;
223 static struct bt_mesh_model_pub light_lightness_pub;
224 static struct bt_mesh_gen_onoff_srv gen_onoff_srv = {
225 .get = light_model_gen_onoff_get,
226 .set = light_model_gen_onoff_set,
227 };
228 static struct bt_mesh_gen_level_srv gen_level_srv = {
229 .get = light_model_gen_level_get,
230 .set = light_model_gen_level_set,
231 };
232 static struct bt_mesh_light_lightness_srv light_lightness_srv = {
233 .get = light_model_light_lightness_get,
234 .set = light_model_light_lightness_set,
235 };
236
bt_mesh_set_gen_onoff_srv_cb(int (* get)(struct bt_mesh_model * model,u8_t * state),int (* set)(struct bt_mesh_model * model,u8_t state))237 void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state),
238 int (*set)(struct bt_mesh_model *model, u8_t state))
239 {
240 gen_onoff_srv.get = get;
241 gen_onoff_srv.set = set;
242 }
243
bt_mesh_set_gen_level_srv_cb(int (* get)(struct bt_mesh_model * model,s16_t * level),int (* set)(struct bt_mesh_model * model,s16_t level))244 void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
245 int (*set)(struct bt_mesh_model *model, s16_t level))
246 {
247 gen_level_srv.get = get;
248 gen_level_srv.set = set;
249 }
250
bt_mesh_set_light_lightness_srv_cb(int (* get)(struct bt_mesh_model * model,s16_t * level),int (* set)(struct bt_mesh_model * model,s16_t level))251 void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
252 int (*set)(struct bt_mesh_model *model, s16_t level))
253 {
254 light_lightness_srv.get = get;
255 light_lightness_srv.set = set;
256 }
257 #endif
258
259 static struct bt_mesh_model root_models[] = {
260 BT_MESH_MODEL_CFG_SRV(&cfg_srv),
261 BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
262 #if MYNEWT_VAL(BLE_MESH_CFG_CLI)
263 BT_MESH_MODEL_CFG_CLI(&cfg_cli),
264 #endif
265 #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
266 BT_MESH_MODEL_HEALTH_CLI(&health_cli),
267 #endif
268 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
269 BT_MESH_MODEL_GEN_ONOFF_SRV(&gen_onoff_srv, &gen_onoff_srv_pub),
270 BT_MESH_MODEL_GEN_ONOFF_CLI(&gen_onoff_cli, &gen_onoff_cli_pub),
271 BT_MESH_MODEL_GEN_LEVEL_SRV(&gen_level_srv, &gen_level_srv_pub),
272 BT_MESH_MODEL_GEN_LEVEL_CLI(&gen_level_cli, &gen_level_cli_pub),
273 BT_MESH_MODEL_LIGHT_LIGHTNESS_SRV(&light_lightness_srv, &light_lightness_pub),
274 #endif
275 };
276
277 static struct bt_mesh_model vnd_models[] = {
278 BT_MESH_MODEL_VND(CID_VENDOR, VND_MODEL_ID_1,
279 BT_MESH_MODEL_NO_OPS, NULL, NULL),
280 };
281
282 static struct bt_mesh_elem elements[] = {
283 BT_MESH_ELEM(0, root_models, vnd_models),
284 };
285
286 static const struct bt_mesh_comp comp = {
287 .cid = CID_VENDOR,
288 .elem = elements,
289 .elem_count = ARRAY_SIZE(elements),
290 };
291
hex2val(char c)292 static u8_t hex2val(char c)
293 {
294 if (c >= '0' && c <= '9') {
295 return c - '0';
296 } else if (c >= 'a' && c <= 'f') {
297 return c - 'a' + 10; // 10:byte alignment
298 } else if (c >= 'A' && c <= 'F') {
299 return c - 'A' + 10; // 10:byte alignment
300 } else {
301 return 0;
302 }
303 }
304
hex2bin(const char * hex,u8_t * bin,size_t bin_len)305 static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len)
306 {
307 size_t len = 0;
308
309 while (*hex && len < bin_len) {
310 bin[len] = hex2val(*hex++) << 4; // 4:byte alignment
311
312 if (!*hex) {
313 len++;
314 break;
315 }
316
317 bin[len++] |= hex2val(*hex++);
318 }
319
320 return len;
321 }
322
prov_complete(u16_t net_idx,u16_t addr)323 static void prov_complete(u16_t net_idx, u16_t addr)
324 {
325 printk("Local node provisioned, net_idx 0x%04x address 0x%04x\n",
326 net_idx, addr);
327 net.local = addr;
328 net.net_idx = net_idx,
329 net.dst = addr;
330 }
331
prov_node_added(u16_t net_idx,u16_t addr,u8_t num_elem)332 static void prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
333 {
334 printk("Node provisioned, net_idx 0x%04x address "
335 "0x%04x elements %d", net_idx, addr, num_elem);
336 net.net_idx = net_idx,
337 net.dst = addr;
338 }
339
prov_input_complete(void)340 static void prov_input_complete(void)
341 {
342 printk("Input complete");
343 }
344
prov_reset(void)345 static void prov_reset(void)
346 {
347 printk("The local node has been reset and needs reprovisioning\n");
348 }
349
output_number(bt_mesh_output_action_t action,uint32_t number)350 static int output_number(bt_mesh_output_action_t action, uint32_t number)
351 {
352 printk("OOB Number: %lu\n", number);
353 return 0;
354 }
355
output_string(const char * str)356 static int output_string(const char *str)
357 {
358 printk("OOB String: %s\n", str);
359 return 0;
360 }
361
362 static bt_mesh_input_action_t input_act;
363 static u8_t input_size;
364
cmd_input_num(int argc,char * argv[])365 static int cmd_input_num(int argc, char *argv[])
366 {
367 int err;
368
369 if (argc < 2) { // 2:Number of parameters
370 return -EINVAL;
371 }
372
373 if (input_act != BT_MESH_ENTER_NUMBER) {
374 printk("A number hasn't been requested!\n");
375 return 0;
376 }
377
378 if (strlen(argv[1]) < input_size) {
379 printk("Too short input (%u digits required)\n",
380 input_size);
381 return 0;
382 }
383
384 long ret = strtoul(argv[1], NULL, 10);
385 if (ret == 0) {
386 printk("strtoul error!\n");
387 }
388 err = bt_mesh_input_number(ret); // 10:byte alignment
389 if (err) {
390 printk("Numeric input failed (err %d)\n", err);
391 return 0;
392 }
393
394 input_act = BT_MESH_NO_INPUT;
395 return 0;
396 }
397
398 struct shell_cmd_help cmd_input_num_help = {
399 NULL, "<number>", NULL
400 };
401
cmd_input_str(int argc,char * argv[])402 static int cmd_input_str(int argc, char *argv[])
403 {
404 int err;
405
406 if (argc < 2) { // 2:Number of parameters
407 return -EINVAL;
408 }
409
410 if (input_act != BT_MESH_ENTER_STRING) {
411 printk("A string hasn't been requested!\n");
412 return 0;
413 }
414
415 if (strlen(argv[1]) < input_size) {
416 printk("Too short input (%u characters required)\n",
417 input_size);
418 return 0;
419 }
420
421 err = bt_mesh_input_string(argv[1]);
422 if (err) {
423 printk("String input failed (err %d)\n", err);
424 return 0;
425 }
426
427 input_act = BT_MESH_NO_INPUT;
428 return 0;
429 }
430
431 struct shell_cmd_help cmd_input_str_help = {
432 NULL, "<string>", NULL
433 };
434
input(bt_mesh_input_action_t act,u8_t size)435 static int input(bt_mesh_input_action_t act, u8_t size)
436 {
437 switch (act) {
438 case BT_MESH_ENTER_NUMBER:
439 printk("Enter a number (max %u digits) with: input-num <num>\n",
440 size);
441 break;
442
443 case BT_MESH_ENTER_STRING:
444 printk("Enter a string (max %u chars) with: input-str <str>\n",
445 size);
446 break;
447
448 default:
449 printk("Unknown input action %u (size %u) requested!\n",
450 act, size);
451 return -EINVAL;
452 }
453
454 input_act = act;
455 input_size = size;
456 return 0;
457 }
458
bearer2str(bt_mesh_prov_bearer_t bearer)459 static const char *bearer2str(bt_mesh_prov_bearer_t bearer)
460 {
461 switch (bearer) {
462 case BT_MESH_PROV_ADV:
463 return "PB-ADV";
464
465 case BT_MESH_PROV_GATT:
466 return "PB-GATT";
467
468 default:
469 return "unknown";
470 }
471 }
472
link_open(bt_mesh_prov_bearer_t bearer)473 static void link_open(bt_mesh_prov_bearer_t bearer)
474 {
475 printk("Provisioning link opened on %s\n", bearer2str(bearer));
476 }
477
link_close(bt_mesh_prov_bearer_t bearer)478 static void link_close(bt_mesh_prov_bearer_t bearer)
479 {
480 printk("Provisioning link closed on %s\n", bearer2str(bearer));
481 }
482
483 static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
484
485 static u8_t static_val[16];
486
487 static struct bt_mesh_prov prov = {
488 .uuid = dev_uuid,
489 .link_open = link_open,
490 .link_close = link_close,
491 .complete = prov_complete,
492 .node_added = prov_node_added,
493 .reset = prov_reset,
494 .static_val = NULL,
495 .static_val_len = 0,
496 .output_size = MYNEWT_VAL(BLE_MESH_OOB_OUTPUT_SIZE),
497 .output_actions = MYNEWT_VAL(BLE_MESH_OOB_OUTPUT_ACTIONS),
498 .output_number = output_number,
499 .output_string = output_string,
500 .input_size = MYNEWT_VAL(BLE_MESH_OOB_INPUT_SIZE),
501 .input_actions = MYNEWT_VAL(BLE_MESH_OOB_INPUT_ACTIONS),
502 .input = input,
503 .input_complete = prov_input_complete,
504 };
505
cmd_static_oob(int argc,char * argv[])506 static int cmd_static_oob(int argc, char *argv[])
507 {
508 if (argc < 2) { // 2:Number of parameters
509 prov.static_val = NULL;
510 prov.static_val_len = 0;
511 } else {
512 prov.static_val_len = hex2bin(argv[1], static_val, 16); // 16:bin_len
513
514 if (prov.static_val_len) {
515 prov.static_val = static_val;
516 } else {
517 prov.static_val = NULL;
518 }
519 }
520
521 if (prov.static_val) {
522 printk("Static OOB value set (length %u)\n",
523 prov.static_val_len);
524 } else {
525 printk("Static OOB value cleared\n");
526 }
527
528 return 0;
529 }
530
531 struct shell_cmd_help cmd_static_oob_help = {
532 NULL, "[val: 1-16 hex values]", NULL
533 };
534
cmd_uuid(int argc,char * argv[])535 static int cmd_uuid(int argc, char *argv[])
536 {
537 u8_t uuid[16];
538 size_t len;
539
540 if (argc < 2) { // 2:Number of parameters
541 return -EINVAL;
542 }
543
544 len = hex2bin(argv[1], uuid, sizeof(uuid));
545 if (len < 1) {
546 return -EINVAL;
547 }
548
549 memcpy(dev_uuid, uuid, len);
550 memset(dev_uuid + len, 0, sizeof(dev_uuid) - len);
551 printk("Device UUID set\n");
552 return 0;
553 }
554
555 struct shell_cmd_help cmd_uuid_help = {
556 NULL, "<UUID: 1-16 hex values>", NULL
557 };
558
cmd_reset(int argc,char * argv[])559 static int cmd_reset(int argc, char *argv[])
560 {
561 bt_mesh_reset();
562 printk("Local node reset complete\n");
563 return 0;
564 }
565
str2u8(const char * str)566 static u8_t str2u8(const char *str)
567 {
568 if (isdigit(str[0])) {
569 return strtoul(str, NULL, 0);
570 }
571
572 return (!strcmp(str, "on") || !strcmp(str, "enable"));
573 }
574
str2bool(const char * str)575 static bool str2bool(const char *str)
576 {
577 return str2u8(str);
578 }
579
580 #if MYNEWT_VAL(BLE_MESH_LOW_POWER)
cmd_lpn(int argc,char * argv[])581 static int cmd_lpn(int argc, char *argv[])
582 {
583 static bool enabled;
584 int err;
585
586 if (argc < 2) { // 2:Number of parameters
587 printk("%s\n", enabled ? "enabled" : "disabled");
588 return 0;
589 }
590
591 if (str2bool(argv[1])) {
592 if (enabled) {
593 printk("LPN already enabled\n");
594 return 0;
595 }
596
597 err = bt_mesh_lpn_set(true);
598 if (err) {
599 printk("Enabling LPN failed (err %d)\n", err);
600 } else {
601 enabled = true;
602 }
603 } else {
604 if (!enabled) {
605 printk("LPN already disabled\n");
606 return 0;
607 }
608
609 err = bt_mesh_lpn_set(false);
610 if (err) {
611 printk("Enabling LPN failed (err %d)\n", err);
612 } else {
613 enabled = false;
614 }
615 }
616
617 return 0;
618 }
619
cmd_poll(int argc,char * argv[])620 static int cmd_poll(int argc, char *argv[])
621 {
622 int err;
623 err = bt_mesh_lpn_poll();
624 if (err) {
625 printk("Friend Poll failed (err %d)\n", err);
626 }
627
628 return 0;
629 }
630
lpn_cb(u16_t friend_addr,bool established)631 static void lpn_cb(u16_t friend_addr, bool established)
632 {
633 if (established) {
634 printk("Friendship (as LPN) established to Friend 0x%04x\n",
635 friend_addr);
636 } else {
637 printk("Friendship (as LPN) lost with Friend 0x%04x\n",
638 friend_addr);
639 }
640 }
641
642 struct shell_cmd_help cmd_lpn_help = {
643 NULL, "<value: off, on>", NULL
644 };
645
646 #endif /* MESH_LOW_POWER */
647
check_pub_addr_unassigned(void)648 static int check_pub_addr_unassigned(void)
649 {
650 #ifdef ARCH_sim
651 return 0;
652 #else
653 uint8_t zero_addr[BLE_DEV_ADDR_LEN] = { 0 };
654 return memcmp(MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR),
655 zero_addr, BLE_DEV_ADDR_LEN) == 0;
656 #endif
657 }
658
cmd_mesh_init(int argc,char * argv[])659 int cmd_mesh_init(int argc, char *argv[])
660 {
661 int err;
662 ble_addr_t addr;
663
664 if (check_pub_addr_unassigned()) {
665 /* Use NRPA */
666 err = ble_hs_id_gen_rnd(1, &addr);
667 assert(err == 0);
668 err = ble_hs_id_set_rnd(addr.val);
669 assert(err == 0);
670 err = bt_mesh_init(addr.type, &prov, &comp);
671 } else {
672 err = bt_mesh_init(0, &prov, &comp);
673 }
674
675 if (err) {
676 printk("Mesh initialization failed (err %d)\n", err);
677 }
678
679 printk("Mesh initialized\n");
680
681 if (IS_ENABLED(CONFIG_SETTINGS)) {
682 settings_load();
683 }
684
685 if (bt_mesh_is_provisioned()) {
686 printk("Mesh network restored from flash\n");
687 } else {
688 printk("Use \"pb-adv on\" or \"pb-gatt on\" to enable"
689 " advertising\n");
690 }
691
692 #if MYNEWT_VAL(BLE_MESH_LOW_POWER)
693 bt_mesh_lpn_set_cb(lpn_cb);
694 #endif
695 return 0;
696 }
697
698 #if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
cmd_ident(int argc,char * argv[])699 static int cmd_ident(int argc, char *argv[])
700 {
701 int err;
702 err = bt_mesh_proxy_identity_enable();
703 if (err) {
704 printk("Failed advertise using Node Identity (err %d)\n", err);
705 }
706
707 return 0;
708 }
709 #endif /* MESH_GATT_PROXY */
710
cmd_dst(int argc,char * argv[])711 static int cmd_dst(int argc, char *argv[])
712 {
713 if (argc < 2) { // 2:Number of parameters
714 printk("Destination address: 0x%04x%s\n", net.dst,
715 net.dst == net.local ? " (local)" : "");
716 return 0;
717 }
718
719 if (!strcmp(argv[1], "local")) {
720 net.dst = net.local;
721 } else {
722 net.dst = strtoul(argv[1], NULL, 0);
723 }
724
725 printk("Destination address set to 0x%04x%s\n", net.dst,
726 net.dst == net.local ? " (local)" : "");
727 return 0;
728 }
729
730 struct shell_cmd_help cmd_dst_help = {
731 NULL, "[destination address]", NULL
732 };
733
cmd_netidx(int argc,char * argv[])734 static int cmd_netidx(int argc, char *argv[])
735 {
736 if (argc < 2) { // 2:Number of parameters
737 printk("NetIdx: 0x%04x\n", net.net_idx);
738 return 0;
739 }
740
741 net.net_idx = strtoul(argv[1], NULL, 0);
742 printk("NetIdx set to 0x%04x\n", net.net_idx);
743 return 0;
744 }
745
746 struct shell_cmd_help cmd_netidx_help = {
747 NULL, "[NetIdx]", NULL
748 };
749
cmd_appidx(int argc,char * argv[])750 static int cmd_appidx(int argc, char *argv[])
751 {
752 if (argc < 2) { // 2:Number of parameters
753 printk("AppIdx: 0x%04x\n", net.app_idx);
754 return 0;
755 }
756
757 net.app_idx = strtoul(argv[1], NULL, 0);
758 printk("AppIdx set to 0x%04x\n", net.app_idx);
759 return 0;
760 }
761
762 struct shell_cmd_help cmd_appidx_help = {
763 NULL, "[AppIdx]", NULL
764 };
765
cmd_net_send(int argc,char * argv[])766 static int cmd_net_send(int argc, char *argv[])
767 {
768 struct os_mbuf *msg = NET_BUF_SIMPLE(32);
769 struct bt_mesh_msg_ctx ctx = {
770 .send_ttl = BT_MESH_TTL_DEFAULT,
771 .net_idx = net.net_idx,
772 .addr = net.dst,
773 .app_idx = net.app_idx,
774
775 };
776 struct bt_mesh_net_tx tx = {
777 .ctx = &ctx,
778 .src = net.local,
779 .xmit = bt_mesh_net_transmit_get(),
780 .sub = bt_mesh_subnet_get(net.net_idx),
781 };
782 size_t len;
783 int err = 0;
784
785 if (argc < 2) { // 2:Number of parameters
786 err = -EINVAL;
787 goto done;
788 }
789
790 if (!tx.sub) {
791 printk("No matching subnet for NetKey Index 0x%04x\n",
792 net.net_idx);
793 goto done;
794 }
795
796 net_buf_simple_init(msg, 0);
797 len = hex2bin(argv[1], msg->om_data, net_buf_simple_tailroom(msg) - 4); // 4:byte alignment
798 net_buf_simple_add(msg, len);
799 err = bt_mesh_trans_send(&tx, msg, NULL, NULL);
800 if (err) {
801 printk("Failed to send (err %d)\n", err);
802 }
803
804 done:
805 os_mbuf_free_chain(msg);
806 return err;
807 }
808
809 struct shell_cmd_help cmd_net_send_help = {
810 NULL, "<hex string>", NULL
811 };
812
cmd_rpl_clear(int argc,char * argv[])813 static int cmd_rpl_clear(int argc, char *argv[])
814 {
815 bt_mesh_rpl_clear();
816 return 0;
817 }
818
819 #if MYNEWT_VAL(BLE_MESH_LOW_POWER)
cmd_lpn_subscribe(int argc,char * argv[])820 static int cmd_lpn_subscribe(int argc, char *argv[])
821 {
822 u16_t address;
823
824 if (argc < 2) { // 2:Number of parameters
825 return -EINVAL;
826 }
827
828 address = strtoul(argv[1], NULL, 0);
829 printk("address 0x%04x", address);
830 bt_mesh_lpn_group_add(address);
831 return 0;
832 }
833
834 struct shell_cmd_help cmd_lpn_subscribe_help = {
835 NULL, "<addr>", NULL
836 };
837
cmd_lpn_unsubscribe(int argc,char * argv[])838 static int cmd_lpn_unsubscribe(int argc, char *argv[])
839 {
840 u16_t address;
841
842 if (argc < 2) { // 2:Number of parameters
843 return -EINVAL;
844 }
845
846 address = strtoul(argv[1], NULL, 0);
847 printk("address 0x%04x", address);
848 bt_mesh_lpn_group_del(&address, 1);
849 return 0;
850 }
851
852 struct shell_cmd_help cmd_lpn_unsubscribe_help = {
853 NULL, "<addr>", NULL
854 };
855 #endif
856
857 #if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST)
cmd_iv_update(int argc,char * argv[])858 static int cmd_iv_update(int argc, char *argv[])
859 {
860 if (bt_mesh_iv_update()) {
861 printk("Transitioned to IV Update In Progress state\n");
862 } else {
863 printk("Transitioned to IV Update Normal state\n");
864 }
865
866 printk("IV Index is 0x%08lx\n", bt_mesh.iv_index);
867 return 0;
868 }
869
cmd_iv_update_test(int argc,char * argv[])870 static int cmd_iv_update_test(int argc, char *argv[])
871 {
872 bool enable;
873
874 if (argc < 2) { // 2:Number of parameters
875 return -EINVAL;
876 }
877
878 enable = str2bool(argv[1]);
879 if (enable) {
880 printk("Enabling IV Update test mode\n");
881 } else {
882 printk("Disabling IV Update test mode\n");
883 }
884
885 bt_mesh_iv_update_test(enable);
886 return 0;
887 }
888
889 struct shell_cmd_help cmd_iv_update_test_help = {
890 NULL, "<value: off, on>", NULL
891 };
892 #endif
893
894 #if MYNEWT_VAL(BLE_MESH_CFG_CLI)
895
cmd_timeout(int argc,char * argv[])896 int cmd_timeout(int argc, char *argv[])
897 {
898 s32_t timeout;
899
900 if (argc < 2) { // 2:Number of parameters
901 timeout = bt_mesh_cfg_cli_timeout_get();
902 if (timeout == K_FOREVER) {
903 printk("Message timeout: forever\n");
904 } else {
905 printk("Message timeout: %lu seconds\n",
906 timeout / 1000); // 1000:time unit
907 }
908
909 return 0;
910 }
911
912 timeout = strtol(argv[1], NULL, 0);
913 if (timeout < 0 || timeout > (INT32_MAX / 1000)) { // 1000:time unit
914 timeout = K_FOREVER;
915 } else {
916 timeout = timeout * 1000; // 1000:time unit
917 }
918
919 bt_mesh_cfg_cli_timeout_set(timeout);
920
921 if (timeout == K_FOREVER) {
922 printk("Message timeout: forever\n");
923 } else {
924 printk("Message timeout: %lu seconds\n",
925 timeout / 1000);
926 }
927
928 return 0;
929 }
930
931 struct shell_cmd_help cmd_timeout_help = {
932 NULL, "[timeout in seconds]", NULL
933 };
934
cmd_get_comp(int argc,char * argv[])935 static int cmd_get_comp(int argc, char *argv[])
936 {
937 struct os_mbuf *comp = NET_BUF_SIMPLE(32);
938 u8_t status, page = 0x00;
939 int err = 0;
940
941 if (argc > 1) {
942 page = strtol(argv[1], NULL, 0);
943 }
944
945 net_buf_simple_init(comp, 0);
946 err = bt_mesh_cfg_comp_data_get(net.net_idx, net.dst, page,
947 &status, comp);
948 if (err) {
949 printk("Getting composition failed (err %d)\n", err);
950 goto done;
951 }
952
953 if (status != 0x00) {
954 printk("Got non-success status 0x%02x\n", status);
955 goto done;
956 }
957
958 printk("Got Composition Data for 0x%04x:\n", net.dst);
959 printk("\tCID 0x%04x\n", net_buf_simple_pull_le16(comp));
960 printk("\tPID 0x%04x\n", net_buf_simple_pull_le16(comp));
961 printk("\tVID 0x%04x\n", net_buf_simple_pull_le16(comp));
962 printk("\tCRPL 0x%04x\n", net_buf_simple_pull_le16(comp));
963 printk("\tFeatures 0x%04x\n", net_buf_simple_pull_le16(comp));
964
965 while (comp->om_len > 4) { // 4:Analyzing conditions
966 u8_t sig, vnd;
967 u16_t loc;
968 int i;
969 loc = net_buf_simple_pull_le16(comp);
970 sig = net_buf_simple_pull_u8(comp);
971 vnd = net_buf_simple_pull_u8(comp);
972 printk("\n\tElement @ 0x%04x:\n", loc);
973
974 if (comp->om_len < ((sig * 2) + (vnd * 4))) { // 4:byte alignment, 2:byte alignment
975 printk("\t\t...truncated data!\n");
976 break;
977 }
978
979 if (sig) {
980 printk("\t\tSIG Models:\n");
981 } else {
982 printk("\t\tNo SIG Models\n");
983 }
984
985 for (i = 0; i < sig; i++) {
986 u16_t mod_id = net_buf_simple_pull_le16(comp);
987 printk("\t\t\t0x%04x\n", mod_id);
988 }
989
990 if (vnd) {
991 printk("\t\tVendor Models:\n");
992 } else {
993 printk("\t\tNo Vendor Models\n");
994 }
995
996 for (i = 0; i < vnd; i++) {
997 u16_t cid = net_buf_simple_pull_le16(comp);
998 u16_t mod_id = net_buf_simple_pull_le16(comp);
999 printk("\t\t\tCompany 0x%04x: 0x%04x\n", cid, mod_id);
1000 }
1001 }
1002
1003 done:
1004 os_mbuf_free_chain(comp);
1005 return err;
1006 }
1007
1008 struct shell_cmd_help cmd_get_comp_help = {
1009 NULL, "[page]", NULL
1010 };
1011
cmd_beacon(int argc,char * argv[])1012 static int cmd_beacon(int argc, char *argv[])
1013 {
1014 u8_t status;
1015 int err;
1016
1017 if (argc < 2) { // 2:Number of parameters
1018 err = bt_mesh_cfg_beacon_get(net.net_idx, net.dst, &status);
1019 } else {
1020 u8_t val = str2u8(argv[1]);
1021 err = bt_mesh_cfg_beacon_set(net.net_idx, net.dst, val,
1022 &status);
1023 }
1024
1025 if (err) {
1026 printk("Unable to send Beacon Get/Set message (err %d)\n", err);
1027 return 0;
1028 }
1029
1030 printk("Beacon state is 0x%02x\n", status);
1031 return 0;
1032 }
1033
1034 struct shell_cmd_help cmd_beacon_help = {
1035 NULL, "[val: off, on]", NULL
1036 };
1037
cmd_ttl(int argc,char * argv[])1038 static int cmd_ttl(int argc, char *argv[])
1039 {
1040 u8_t ttl;
1041 int err;
1042
1043 if (argc < 2) { // 2:Number of parameters
1044 err = bt_mesh_cfg_ttl_get(net.net_idx, net.dst, &ttl);
1045 } else {
1046 u8_t val = strtoul(argv[1], NULL, 0);
1047 err = bt_mesh_cfg_ttl_set(net.net_idx, net.dst, val, &ttl);
1048 }
1049
1050 if (err) {
1051 printk("Unable to send Default TTL Get/Set (err %d)\n", err);
1052 return 0;
1053 }
1054
1055 printk("Default TTL is 0x%02x\n", ttl);
1056 return 0;
1057 }
1058
1059 struct shell_cmd_help cmd_ttl_help = {
1060 NULL, "[ttl: 0x00, 0x02-0x7f]", NULL
1061 };
1062
cmd_friend(int argc,char * argv[])1063 static int cmd_friend(int argc, char *argv[])
1064 {
1065 u8_t frnd;
1066 int err;
1067
1068 if (argc < 2) { // 2:Number of parameters
1069 err = bt_mesh_cfg_friend_get(net.net_idx, net.dst, &frnd);
1070 } else {
1071 u8_t val = str2u8(argv[1]);
1072 err = bt_mesh_cfg_friend_set(net.net_idx, net.dst, val, &frnd);
1073 }
1074
1075 if (err) {
1076 printk("Unable to send Friend Get/Set (err %d)\n", err);
1077 return 0;
1078 }
1079
1080 printk("Friend is set to 0x%02x\n", frnd);
1081 return 0;
1082 }
1083
1084 struct shell_cmd_help cmd_friend_help = {
1085 NULL, "[val: off, on]", NULL
1086 };
1087
cmd_gatt_proxy(int argc,char * argv[])1088 static int cmd_gatt_proxy(int argc, char *argv[])
1089 {
1090 u8_t proxy;
1091 int err;
1092
1093 if (argc < 2) { // 2:Number of parameters
1094 err = bt_mesh_cfg_gatt_proxy_get(net.net_idx, net.dst, &proxy);
1095 } else {
1096 u8_t val = str2u8(argv[1]);
1097 err = bt_mesh_cfg_gatt_proxy_set(net.net_idx, net.dst, val,
1098 &proxy);
1099 }
1100
1101 if (err) {
1102 printk("Unable to send GATT Proxy Get/Set (err %d)\n", err);
1103 return 0;
1104 }
1105
1106 printk("GATT Proxy is set to 0x%02x\n", proxy);
1107 return 0;
1108 }
1109
1110 struct shell_cmd_help cmd_gatt_proxy_help = {
1111 NULL, "[val: off, on]", NULL
1112 };
1113
cmd_relay(int argc,char * argv[])1114 static int cmd_relay(int argc, char *argv[])
1115 {
1116 u8_t relay, transmit;
1117 int err;
1118
1119 if (argc < 2) { // 2:Number of parameters
1120 err = bt_mesh_cfg_relay_get(net.net_idx, net.dst, &relay,
1121 &transmit);
1122 } else {
1123 u8_t val = str2u8(argv[1]);
1124 u8_t count, interval, new_transmit;
1125
1126 if (val) {
1127 if (argc > 2) { // 2:Number of parameters
1128 count = strtoul(argv[2], NULL, 0); // 2:Number of parameters
1129 } else {
1130 count = 2; // 2:value of count
1131 }
1132
1133 if (argc > 3) { // 3:Number of parameters
1134 interval = strtoul(argv[3], NULL, 0); // 3:Number of parameters
1135 } else {
1136 interval = 20; // 20:value of interval
1137 }
1138
1139 new_transmit = BT_MESH_TRANSMIT(count, interval);
1140 } else {
1141 new_transmit = 0;
1142 }
1143
1144 err = bt_mesh_cfg_relay_set(net.net_idx, net.dst, val,
1145 new_transmit, &relay, &transmit);
1146 }
1147
1148 if (err) {
1149 printk("Unable to send Relay Get/Set (err %d)\n", err);
1150 return 0;
1151 }
1152
1153 printk("Relay is 0x%02x, Transmit 0x%02x (count %u interval %ums)\n",
1154 relay, transmit, BT_MESH_TRANSMIT_COUNT(transmit),
1155 BT_MESH_TRANSMIT_INT(transmit));
1156 return 0;
1157 }
1158
1159 struct shell_cmd_help cmd_relay_help = {
1160 NULL, "[val: off, on] [count: 0-7] [interval: 0-32]", NULL
1161 };
1162
cmd_net_key_add(int argc,char * argv[])1163 static int cmd_net_key_add(int argc, char *argv[])
1164 {
1165 u8_t key_val[16];
1166 u16_t key_net_idx;
1167 u8_t status;
1168 int err;
1169
1170 if (argc < 2) { // 2:Number of parameters
1171 return -EINVAL;
1172 }
1173
1174 key_net_idx = strtoul(argv[1], NULL, 0);
1175
1176 if (argc > 2) { // 2:Number of parameters
1177 size_t len;
1178 len = hex2bin(argv[3], key_val, sizeof(key_val)); // 3:Number of parameters
1179 memset(key_val, 0, sizeof(key_val) - len);
1180 } else {
1181 memcpy(key_val, default_key, sizeof(key_val));
1182 }
1183
1184 err = bt_mesh_cfg_net_key_add(net.net_idx, net.dst, key_net_idx,
1185 key_val, &status);
1186 if (err) {
1187 printk("Unable to send NetKey Add (err %d)\n", err);
1188 return 0;
1189 }
1190
1191 if (status) {
1192 printk("NetKeyAdd failed with status 0x%02x\n", status);
1193 } else {
1194 printk("NetKey added with NetKey Index 0x%03x\n", key_net_idx);
1195 }
1196
1197 return 0;
1198 }
1199
1200 struct shell_cmd_help cmd_net_key_add_help = {
1201 NULL, "<NetKeyIndex> [val]", NULL
1202 };
1203
cmd_app_key_add(int argc,char * argv[])1204 static int cmd_app_key_add(int argc, char *argv[])
1205 {
1206 u8_t key_val[16];
1207 u16_t key_net_idx, key_app_idx;
1208 u8_t status;
1209 int err;
1210
1211 if (argc < 3) { // 3:Number of parameters
1212 return -EINVAL;
1213 }
1214
1215 key_net_idx = strtoul(argv[1], NULL, 0);
1216 key_app_idx = strtoul(argv[2], NULL, 0); // 2:Number of parameters
1217
1218 if (argc > 3) { // 3:Number of parameters
1219 size_t len;
1220 len = hex2bin(argv[3], key_val, sizeof(key_val)); // 3:Number of parameters
1221 memset(key_val, 0, sizeof(key_val) - len);
1222 } else {
1223 memcpy(key_val, default_key, sizeof(key_val));
1224 }
1225
1226 err = bt_mesh_cfg_app_key_add(net.net_idx, net.dst, key_net_idx,
1227 key_app_idx, key_val, &status);
1228 if (err) {
1229 printk("Unable to send App Key Add (err %d)\n", err);
1230 return 0;
1231 }
1232
1233 if (status) {
1234 printk("AppKeyAdd failed with status 0x%02x\n", status);
1235 } else {
1236 printk("AppKey added, NetKeyIndex 0x%04x AppKeyIndex 0x%04x\n",
1237 key_net_idx, key_app_idx);
1238 }
1239
1240 return 0;
1241 }
1242
1243 struct shell_cmd_help cmd_app_key_add_help = {
1244 NULL, "<NetKeyIndex> <AppKeyIndex> [val]", NULL
1245 };
1246
cmd_mod_app_bind(int argc,char * argv[])1247 static int cmd_mod_app_bind(int argc, char *argv[])
1248 {
1249 u16_t elem_addr, mod_app_idx, mod_id, cid;
1250 u8_t status;
1251 int err;
1252
1253 if (argc < 4) { // 4:Number of parameters
1254 return -EINVAL;
1255 }
1256
1257 elem_addr = strtoul(argv[1], NULL, 0);
1258 mod_app_idx = strtoul(argv[2], NULL, 0); // 2:Number of parameters
1259 mod_id = strtoul(argv[3], NULL, 0); // 3:Number of parameters
1260
1261 if (argc > 4) { // 4:Number of parameters
1262 cid = strtoul(argv[4], NULL, 0); // 4:Number of parameters
1263 err = bt_mesh_cfg_mod_app_bind_vnd(net.net_idx, net.dst,
1264 elem_addr, mod_app_idx,
1265 mod_id, cid, &status);
1266 } else {
1267 err = bt_mesh_cfg_mod_app_bind(net.net_idx, net.dst, elem_addr,
1268 mod_app_idx, mod_id, &status);
1269 }
1270
1271 if (err) {
1272 printk("Unable to send Model App Bind (err %d)\n", err);
1273 return 0;
1274 }
1275
1276 if (status) {
1277 printk("Model App Bind failed with status 0x%02x\n", status);
1278 } else {
1279 printk("AppKey successfully bound\n");
1280 }
1281
1282 return 0;
1283 }
1284
1285 struct shell_cmd_help cmd_mod_app_bind_help = {
1286 NULL, "<addr> <AppIndex> <Model ID> [Company ID]", NULL
1287 };
1288
cmd_mod_sub_add(int argc,char * argv[])1289 static int cmd_mod_sub_add(int argc, char *argv[])
1290 {
1291 u16_t elem_addr, sub_addr, mod_id, cid;
1292 u8_t status;
1293 int err;
1294
1295 if (argc < 4) { // 4:Number of parameters
1296 return -EINVAL;
1297 }
1298
1299 elem_addr = strtoul(argv[1], NULL, 0);
1300 sub_addr = strtoul(argv[2], NULL, 0); // 2:Number of parameters
1301 mod_id = strtoul(argv[3], NULL, 0); // 3:Number of parameters
1302
1303 if (argc > 4) { // 4:Number of parameters
1304 cid = strtoul(argv[4], NULL, 0); // 4:Number of parameters
1305 err = bt_mesh_cfg_mod_sub_add_vnd(net.net_idx, net.dst,
1306 elem_addr, sub_addr, mod_id,
1307 cid, &status);
1308 } else {
1309 err = bt_mesh_cfg_mod_sub_add(net.net_idx, net.dst, elem_addr,
1310 sub_addr, mod_id, &status);
1311 }
1312
1313 if (err) {
1314 printk("Unable to send Model Subscription Add (err %d)\n", err);
1315 return 0;
1316 }
1317
1318 if (status) {
1319 printk("Model Subscription Add failed with status 0x%02x\n",
1320 status);
1321 } else {
1322 printk("Model subscription was successful\n");
1323 }
1324
1325 return 0;
1326 }
1327
1328 struct shell_cmd_help cmd_mod_sub_add_help = {
1329 NULL, "<elem addr> <sub addr> <Model ID> [Company ID]", NULL
1330 };
1331
cmd_mod_sub_del(int argc,char * argv[])1332 static int cmd_mod_sub_del(int argc, char *argv[])
1333 {
1334 u16_t elem_addr, sub_addr, mod_id, cid;
1335 u8_t status;
1336 int err;
1337
1338 if (argc < 4) { // 4:Number of parameters
1339 return -EINVAL;
1340 }
1341
1342 elem_addr = strtoul(argv[1], NULL, 0);
1343 sub_addr = strtoul(argv[2], NULL, 0); // 2:Number of parameters
1344 mod_id = strtoul(argv[3], NULL, 0); // 3:Number of parameters
1345
1346 if (argc > 4) { // 4:Number of parameters
1347 cid = strtoul(argv[4], NULL, 0); // 4:Number of parameters
1348 err = bt_mesh_cfg_mod_sub_del_vnd(net.net_idx, net.dst,
1349 elem_addr, sub_addr, mod_id,
1350 cid, &status);
1351 } else {
1352 err = bt_mesh_cfg_mod_sub_del(net.net_idx, net.dst, elem_addr,
1353 sub_addr, mod_id, &status);
1354 }
1355
1356 if (err) {
1357 printk("Unable to send Model Subscription Delete (err %d)\n",
1358 err);
1359 return 0;
1360 }
1361
1362 if (status) {
1363 printk("Model Subscription Delete failed with status 0x%02x\n",
1364 status);
1365 } else {
1366 printk("Model subscription deltion was successful\n");
1367 }
1368
1369 return 0;
1370 }
1371
1372 struct shell_cmd_help cmd_mod_sub_del_help = {
1373 NULL, "<elem addr> <sub addr> <Model ID> [Company ID]", NULL
1374 };
1375
cmd_mod_sub_add_va(int argc,char * argv[])1376 static int cmd_mod_sub_add_va(int argc, char *argv[])
1377 {
1378 u16_t elem_addr, sub_addr, mod_id, cid;
1379 u8_t label[16];
1380 u8_t status;
1381 size_t len;
1382 int err;
1383
1384 if (argc < 4) { // 4:Number of parameters
1385 return -EINVAL;
1386 }
1387
1388 elem_addr = strtoul(argv[1], NULL, 0);
1389 len = hex2bin(argv[2], label, sizeof(label)); // 2:Number of parameters
1390 memset(label + len, 0, sizeof(label) - len);
1391 mod_id = strtoul(argv[3], NULL, 0); // 3:Number of parameters
1392
1393 if (argc > 4) { // 4:Number of parameters
1394 cid = strtoul(argv[4], NULL, 0); // 4:Number of parameters
1395 err = bt_mesh_cfg_mod_sub_va_add_vnd(net.net_idx, net.dst,
1396 elem_addr, label, mod_id,
1397 cid, &sub_addr, &status);
1398 } else {
1399 err = bt_mesh_cfg_mod_sub_va_add(net.net_idx, net.dst,
1400 elem_addr, label, mod_id,
1401 &sub_addr, &status);
1402 }
1403
1404 if (err) {
1405 printk("Unable to send Mod Sub VA Add (err %d)\n", err);
1406 return 0;
1407 }
1408
1409 if (status) {
1410 printk("Mod Sub VA Add failed with status 0x%02x\n",
1411 status);
1412 } else {
1413 printk("0x%04x subscribed to Label UUID %s (va 0x%04x)\n",
1414 elem_addr, argv[2], sub_addr);
1415 }
1416
1417 return 0;
1418 }
1419
1420 struct shell_cmd_help cmd_mod_sub_add_va_help = {
1421 NULL, "<elem addr> <Label UUID> <Model ID> [Company ID]", NULL
1422 };
1423
cmd_mod_sub_del_va(int argc,char * argv[])1424 static int cmd_mod_sub_del_va(int argc, char *argv[])
1425 {
1426 u16_t elem_addr, sub_addr, mod_id, cid;
1427 u8_t label[16];
1428 u8_t status;
1429 size_t len;
1430 int err;
1431
1432 if (argc < 4) { // 4:Number of parameters
1433 return -EINVAL;
1434 }
1435
1436 elem_addr = strtoul(argv[1], NULL, 0);
1437 len = hex2bin(argv[2], label, sizeof(label)); // 2:Number of parameters
1438 memset(label + len, 0, sizeof(label) - len);
1439 mod_id = strtoul(argv[3], NULL, 0); // 3:Number of parameters
1440
1441 if (argc > 4) { // 4:Number of parameters
1442 cid = strtoul(argv[4], NULL, 0); // 4:Number of parameters
1443 err = bt_mesh_cfg_mod_sub_va_del_vnd(net.net_idx, net.dst,
1444 elem_addr, label, mod_id,
1445 cid, &sub_addr, &status);
1446 } else {
1447 err = bt_mesh_cfg_mod_sub_va_del(net.net_idx, net.dst,
1448 elem_addr, label, mod_id,
1449 &sub_addr, &status);
1450 }
1451
1452 if (err) {
1453 printk("Unable to send Model Subscription Delete (err %d)\n",
1454 err);
1455 return 0;
1456 }
1457
1458 if (status) {
1459 printk("Model Subscription Delete failed with status 0x%02x\n",
1460 status);
1461 } else {
1462 printk("0x%04x unsubscribed from Label UUID %s (va 0x%04x)\n",
1463 elem_addr, argv[2], sub_addr);
1464 }
1465
1466 return 0;
1467 }
1468
1469 struct shell_cmd_help cmd_mod_sub_del_va_help = {
1470 NULL, "<elem addr> <Label UUID> <Model ID> [Company ID]", NULL
1471 };
1472
mod_pub_get(u16_t addr,u16_t mod_id,u16_t cid)1473 static int mod_pub_get(u16_t addr, u16_t mod_id, u16_t cid)
1474 {
1475 struct bt_mesh_cfg_mod_pub pub;
1476 u8_t status;
1477 int err;
1478
1479 if (cid == CID_NVAL) {
1480 err = bt_mesh_cfg_mod_pub_get(net.net_idx, net.dst, addr,
1481 mod_id, &pub, &status);
1482 } else {
1483 err = bt_mesh_cfg_mod_pub_get_vnd(net.net_idx, net.dst, addr,
1484 mod_id, cid, &pub, &status);
1485 }
1486
1487 if (err) {
1488 printk("Model Publication Get failed (err %d)\n", err);
1489 return 0;
1490 }
1491
1492 if (status) {
1493 printk("Model Publication Get failed (status 0x%02x)\n",
1494 status);
1495 return 0;
1496 }
1497
1498 printk("Model Publication for Element 0x%04x, Model 0x%04x:\n"
1499 "\tPublish Address: 0x%04x\n"
1500 "\tAppKeyIndex: 0x%04x\n"
1501 "\tCredential Flag: %u\n"
1502 "\tPublishTTL: %u\n"
1503 "\tPublishPeriod: 0x%02x\n"
1504 "\tPublishRetransmitCount: %u\n"
1505 "\tPublishRetransmitInterval: %ums\n",
1506 addr, mod_id, pub.addr, pub.app_idx, pub.cred_flag, pub.ttl,
1507 pub.period, BT_MESH_PUB_TRANSMIT_COUNT(pub.transmit),
1508 BT_MESH_PUB_TRANSMIT_INT(pub.transmit));
1509 return 0;
1510 }
1511
mod_pub_set(u16_t addr,u16_t mod_id,u16_t cid,char * argv[])1512 static int mod_pub_set(u16_t addr, u16_t mod_id, u16_t cid, char *argv[])
1513 {
1514 struct bt_mesh_cfg_mod_pub pub;
1515 u8_t status, count;
1516 u16_t interval;
1517 int err;
1518 pub.addr = strtoul(argv[0], NULL, 0);
1519 pub.app_idx = strtoul(argv[1], NULL, 0);
1520 pub.cred_flag = str2bool(argv[2]); // 2:parameters 2
1521 pub.ttl = strtoul(argv[3], NULL, 0); // 3:parameters 3
1522 pub.period = strtoul(argv[4], NULL, 0); // 4:parameters 4
1523 count = strtoul(argv[5], NULL, 0); // 5:parameters 5
1524 if (count > 7) { // 7:Analyzing conditions
1525 printk("Invalid retransmit count\n");
1526 return -EINVAL;
1527 }
1528
1529 interval = strtoul(argv[6], NULL, 0); // 6:parameters 6
1530 if (interval > (31 * 50) || (interval % 50)) { // 31:byte alignment, 50:byte alignment
1531 printk("Invalid retransmit interval %u\n", interval);
1532 return -EINVAL;
1533 }
1534
1535 pub.transmit = BT_MESH_PUB_TRANSMIT(count, interval);
1536
1537 if (cid == CID_NVAL) {
1538 err = bt_mesh_cfg_mod_pub_set(net.net_idx, net.dst, addr,
1539 mod_id, &pub, &status);
1540 } else {
1541 err = bt_mesh_cfg_mod_pub_set_vnd(net.net_idx, net.dst, addr,
1542 mod_id, cid, &pub, &status);
1543 }
1544
1545 if (err) {
1546 printk("Model Publication Set failed (err %d)\n", err);
1547 return 0;
1548 }
1549
1550 if (status) {
1551 printk("Model Publication Set failed (status 0x%02x)\n",
1552 status);
1553 } else {
1554 printk("Model Publication successfully set\n");
1555 }
1556
1557 return 0;
1558 }
1559
cmd_mod_pub(int argc,char * argv[])1560 static int cmd_mod_pub(int argc, char *argv[])
1561 {
1562 u16_t addr, mod_id, cid;
1563
1564 if (argc < 3) { // 3:Number of parameters
1565 return -EINVAL;
1566 }
1567
1568 addr = strtoul(argv[1], NULL, 0);
1569 mod_id = strtoul(argv[2], NULL, 0); // 2: parameters 2
1570 argc -= 3; // 3:byte alignment
1571 argv += 3; // 3:byte alignment
1572
1573 if (argc == 1 || argc == 8) { // 8:parameters 8
1574 cid = strtoul(argv[0], NULL, 0);
1575 argc--;
1576 argv++;
1577 } else {
1578 cid = CID_NVAL;
1579 }
1580
1581 if (argc > 0) {
1582 if (argc < 7) { // 7:Number of parameters
1583 return -EINVAL;
1584 }
1585
1586 return mod_pub_set(addr, mod_id, cid, argv);
1587 } else {
1588 return mod_pub_get(addr, mod_id, cid);
1589 }
1590 }
1591
1592 struct shell_cmd_help cmd_mod_pub_help = {
1593 NULL, "<addr> <mod id> [cid] [<PubAddr> <AppKeyIndex> <cred> <ttl> <period> <count> <interval>]", NULL
1594 };
1595
hb_sub_print(struct bt_mesh_cfg_hb_sub * sub)1596 static void hb_sub_print(struct bt_mesh_cfg_hb_sub *sub)
1597 {
1598 printk("Heartbeat Subscription:\n"
1599 "\tSource: 0x%04x\n"
1600 "\tDestination: 0x%04x\n"
1601 "\tPeriodLog: 0x%02x\n"
1602 "\tCountLog: 0x%02x\n"
1603 "\tMinHops: %u\n"
1604 "\tMaxHops: %u\n",
1605 sub->src, sub->dst, sub->period, sub->count,
1606 sub->min, sub->max);
1607 }
1608
hb_sub_get(int argc,char * argv[])1609 static int hb_sub_get(int argc, char *argv[])
1610 {
1611 struct bt_mesh_cfg_hb_sub sub;
1612 u8_t status;
1613 int err;
1614 err = bt_mesh_cfg_hb_sub_get(net.net_idx, net.dst, &sub, &status);
1615 if (err) {
1616 printk("Heartbeat Subscription Get failed (err %d)\n", err);
1617 return 0;
1618 }
1619
1620 if (status) {
1621 printk("Heartbeat Subscription Get failed (status 0x%02x)\n",
1622 status);
1623 } else {
1624 hb_sub_print(&sub);
1625 }
1626
1627 return 0;
1628 }
1629
hb_sub_set(int argc,char * argv[])1630 static int hb_sub_set(int argc, char *argv[])
1631 {
1632 struct bt_mesh_cfg_hb_sub sub;
1633 u8_t status;
1634 int err;
1635 sub.src = strtoul(argv[1], NULL, 0);
1636 sub.dst = strtoul(argv[2], NULL, 0); // 2: parameters 2
1637 sub.period = strtoul(argv[3], NULL, 0); // 3: parameters 3
1638 err = bt_mesh_cfg_hb_sub_set(net.net_idx, net.dst, &sub, &status);
1639 if (err) {
1640 printk("Heartbeat Subscription Set failed (err %d)\n", err);
1641 return 0;
1642 }
1643
1644 if (status) {
1645 printk("Heartbeat Subscription Set failed (status 0x%02x)\n",
1646 status);
1647 } else {
1648 hb_sub_print(&sub);
1649 }
1650
1651 return 0;
1652 }
1653
cmd_hb_sub(int argc,char * argv[])1654 static int cmd_hb_sub(int argc, char *argv[])
1655 {
1656 if (argc > 1) {
1657 if (argc < 4) { // 4:Number of parameters
1658 return -EINVAL;
1659 }
1660
1661 return hb_sub_set(argc, argv);
1662 } else {
1663 return hb_sub_get(argc, argv);
1664 }
1665 }
1666
1667 struct shell_cmd_help cmd_hb_sub_help = {
1668 NULL, "<src> <dst> <period>", NULL
1669 };
1670
hb_pub_get(int argc,char * argv[])1671 static int hb_pub_get(int argc, char *argv[])
1672 {
1673 struct bt_mesh_cfg_hb_pub pub;
1674 u8_t status;
1675 int err;
1676 err = bt_mesh_cfg_hb_pub_get(net.net_idx, net.dst, &pub, &status);
1677 if (err) {
1678 printk("Heartbeat Publication Get failed (err %d)\n", err);
1679 return 0;
1680 }
1681
1682 if (status) {
1683 printk("Heartbeat Publication Get failed (status 0x%02x)\n",
1684 status);
1685 return 0;
1686 }
1687
1688 printk("Heartbeat publication:\n");
1689 printk("\tdst 0x%04x count 0x%02x period 0x%02x\n",
1690 pub.dst, pub.count, pub.period);
1691 printk("\tttl 0x%02x feat 0x%04x net_idx 0x%04x\n",
1692 pub.ttl, pub.feat, pub.net_idx);
1693 return 0;
1694 }
1695
hb_pub_set(int argc,char * argv[])1696 static int hb_pub_set(int argc, char *argv[])
1697 {
1698 struct bt_mesh_cfg_hb_pub pub;
1699 u8_t status;
1700 int err;
1701 pub.dst = strtoul(argv[1], NULL, 0);
1702 pub.count = strtoul(argv[2], NULL, 0);
1703 pub.period = strtoul(argv[3], NULL, 0);
1704 pub.ttl = strtoul(argv[4], NULL, 0);
1705 pub.feat = strtoul(argv[5], NULL, 0);
1706 pub.net_idx = strtoul(argv[5], NULL, 0);
1707 err = bt_mesh_cfg_hb_pub_set(net.net_idx, net.dst, &pub, &status);
1708 if (err) {
1709 printk("Heartbeat Publication Set failed (err %d)\n", err);
1710 return 0;
1711 }
1712
1713 if (status) {
1714 printk("Heartbeat Publication Set failed (status 0x%02x)\n",
1715 status);
1716 } else {
1717 printk("Heartbeat publication successfully set\n");
1718 }
1719
1720 return 0;
1721 }
1722
cmd_hb_pub(int argc,char * argv[])1723 static int cmd_hb_pub(int argc, char *argv[])
1724 {
1725 if (argc > 1) {
1726 if (argc < 7) { // 7:Number of parameters
1727 return -EINVAL;
1728 }
1729
1730 return hb_pub_set(argc, argv);
1731 } else {
1732 return hb_pub_get(argc, argv);
1733 }
1734 }
1735
1736 struct shell_cmd_help cmd_hb_pub_help = {
1737 NULL, "<dst> <count> <period> <ttl> <features> <NetKeyIndex>", NULL
1738 };
1739
1740 #endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */
1741
1742 #if MYNEWT_VAL(BLE_MESH_PROV)
cmd_pb(bt_mesh_prov_bearer_t bearer,int argc,char * argv[])1743 static int cmd_pb(bt_mesh_prov_bearer_t bearer, int argc, char *argv[])
1744 {
1745 int err;
1746
1747 if (argc < 2) { // 2:Number of parameters
1748 return -EINVAL;
1749 }
1750
1751 if (str2bool(argv[1])) {
1752 err = bt_mesh_prov_enable(bearer);
1753 if (err) {
1754 printk("Failed to enable %s (err %d)\n",
1755 bearer2str(bearer), err);
1756 } else {
1757 printk("%s enabled\n", bearer2str(bearer));
1758 }
1759 } else {
1760 err = bt_mesh_prov_disable(bearer);
1761 if (err) {
1762 printk("Failed to disable %s (err %d)\n",
1763 bearer2str(bearer), err);
1764 } else {
1765 printk("%s disabled\n", bearer2str(bearer));
1766 }
1767 }
1768
1769 return 0;
1770 }
1771
1772 struct shell_cmd_help cmd_pb_help = {
1773 NULL, "<val: off, on>", NULL
1774 };
1775
1776 #endif
1777
1778 #if MYNEWT_VAL(BLE_MESH_PB_ADV)
cmd_pb_adv(int argc,char * argv[])1779 static int cmd_pb_adv(int argc, char *argv[])
1780 {
1781 return cmd_pb(BT_MESH_PROV_ADV, argc, argv);
1782 }
1783
1784 #if MYNEWT_VAL(BLE_MESH_PROVISIONER)
cmd_provision_adv(int argc,char * argv[])1785 static int cmd_provision_adv(int argc, char *argv[])
1786 {
1787 u8_t uuid[16];
1788 u8_t attention_duration;
1789 u16_t net_idx;
1790 u16_t addr;
1791 size_t len;
1792 int err;
1793 len = hex2bin(argv[1], uuid, sizeof(uuid));
1794 (void)memset(uuid + len, 0, sizeof(uuid) - len);
1795 net_idx = strtoul(argv[2], NULL, 0);
1796 addr = strtoul(argv[3], NULL, 0);
1797 attention_duration = strtoul(argv[4], NULL, 0);
1798 err = bt_mesh_provision_adv(uuid, net_idx, addr, attention_duration);
1799 if (err) {
1800 printk("Provisioning failed (err %d)", err);
1801 }
1802
1803 return 0;
1804 }
1805
1806 struct shell_cmd_help cmd_provision_adv_help = {
1807 NULL, "<UUID> <NetKeyIndex> <addr> <AttentionDuration>", NULL
1808 };
1809 #endif /* CONFIG_BT_MESH_PROVISIONER */
1810
1811 #endif /* CONFIG_BT_MESH_PB_ADV */
1812
1813 #if MYNEWT_VAL(BLE_MESH_PB_GATT)
cmd_pb_gatt(int argc,char * argv[])1814 static int cmd_pb_gatt(int argc, char *argv[])
1815 {
1816 return cmd_pb(BT_MESH_PROV_GATT, argc, argv);
1817 }
1818 #endif /* CONFIG_BT_MESH_PB_GATT */
1819
cmd_provision(int argc,char * argv[])1820 static int cmd_provision(int argc, char *argv[])
1821 {
1822 u16_t net_idx, addr;
1823 u32_t iv_index;
1824 int err;
1825
1826 if (argc < 3) { // 3:Number of parameters
1827 return -EINVAL;
1828 }
1829
1830 net_idx = strtoul(argv[1], NULL, 0);
1831 addr = strtoul(argv[2], NULL, 0); // 2:Number of parameters
1832
1833 if (argc > 3) { // 3:Number of parameters
1834 iv_index = strtoul(argv[3], NULL, 0); // 3:parameters 3
1835 } else {
1836 iv_index = 0;
1837 }
1838
1839 err = bt_mesh_provision(default_key, net_idx, 0, iv_index, addr,
1840 default_key);
1841 if (err) {
1842 printk("Provisioning failed (err %d)\n", err);
1843 }
1844
1845 return 0;
1846 }
1847
1848 struct shell_cmd_help cmd_provision_help = {
1849 NULL, "<NetKeyIndex> <addr> [IVIndex]", NULL
1850 };
1851
1852 #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
1853
cmd_fault_get(int argc,char * argv[])1854 static int cmd_fault_get(int argc, char *argv[])
1855 {
1856 u8_t faults[32];
1857 size_t fault_count;
1858 u8_t test_id;
1859 u16_t cid;
1860 int err;
1861
1862 if (argc < 2) { // 2:Number of parameters
1863 return -EINVAL;
1864 }
1865
1866 cid = strtoul(argv[1], NULL, 0);
1867 fault_count = sizeof(faults);
1868 err = bt_mesh_health_fault_get(net.net_idx, net.dst, net.app_idx, cid,
1869 &test_id, faults, &fault_count);
1870 if (err) {
1871 printk("Failed to send Health Fault Get (err %d)\n", err);
1872 } else {
1873 show_faults(test_id, cid, faults, fault_count);
1874 }
1875
1876 return 0;
1877 }
1878
1879 struct shell_cmd_help cmd_fault_get_help = {
1880 NULL, "<Company ID>", NULL
1881 };
1882
cmd_fault_clear(int argc,char * argv[])1883 static int cmd_fault_clear(int argc, char *argv[])
1884 {
1885 u8_t faults[32];
1886 size_t fault_count;
1887 u8_t test_id;
1888 u16_t cid;
1889 int err;
1890
1891 if (argc < 2) { // 2:Number of parameters
1892 return -EINVAL;
1893 }
1894
1895 cid = strtoul(argv[1], NULL, 0);
1896 fault_count = sizeof(faults);
1897 err = bt_mesh_health_fault_clear(net.net_idx, net.dst, net.app_idx,
1898 cid, &test_id, faults, &fault_count);
1899 if (err) {
1900 printk("Failed to send Health Fault Clear (err %d)\n", err);
1901 } else {
1902 show_faults(test_id, cid, faults, fault_count);
1903 }
1904
1905 return 0;
1906 }
1907
1908 struct shell_cmd_help cmd_fault_clear_help = {
1909 NULL, "<Company ID>", NULL
1910 };
1911
cmd_fault_clear_unack(int argc,char * argv[])1912 static int cmd_fault_clear_unack(int argc, char *argv[])
1913 {
1914 u16_t cid;
1915 int err;
1916
1917 if (argc < 2) { // 2:Number of parameters
1918 return -EINVAL;
1919 }
1920
1921 cid = strtoul(argv[1], NULL, 0);
1922 err = bt_mesh_health_fault_clear(net.net_idx, net.dst, net.app_idx,
1923 cid, NULL, NULL, NULL);
1924 if (err) {
1925 printk("Health Fault Clear Unacknowledged failed (err %d)\n",
1926 err);
1927 }
1928
1929 return 0;
1930 }
1931
1932 struct shell_cmd_help cmd_fault_clear_unack_help = {
1933 NULL, "<Company ID>", NULL
1934 };
1935
cmd_fault_test(int argc,char * argv[])1936 static int cmd_fault_test(int argc, char *argv[])
1937 {
1938 u8_t faults[32];
1939 size_t fault_count;
1940 u8_t test_id;
1941 u16_t cid;
1942 int err;
1943
1944 if (argc < 3) { // 3:Number of parameters
1945 return -EINVAL;
1946 }
1947
1948 cid = strtoul(argv[1], NULL, 0);
1949 test_id = strtoul(argv[2], NULL, 0); // 2:Number of parameters
1950 fault_count = sizeof(faults);
1951 err = bt_mesh_health_fault_test(net.net_idx, net.dst, net.app_idx,
1952 cid, test_id, faults, &fault_count);
1953 if (err) {
1954 printk("Failed to send Health Fault Test (err %d)\n", err);
1955 } else {
1956 show_faults(test_id, cid, faults, fault_count);
1957 }
1958
1959 return 0;
1960 }
1961
1962 struct shell_cmd_help cmd_fault_test_help = {
1963 NULL, "<Company ID> <Test ID>", NULL
1964 };
1965
cmd_fault_test_unack(int argc,char * argv[])1966 static int cmd_fault_test_unack(int argc, char *argv[])
1967 {
1968 u16_t cid;
1969 u8_t test_id;
1970 int err;
1971
1972 if (argc < 3) { // 3:Number of parameters
1973 return -EINVAL;
1974 }
1975
1976 cid = strtoul(argv[1], NULL, 0);
1977 test_id = strtoul(argv[2], NULL, 0); // 2:Number of parameters
1978 err = bt_mesh_health_fault_test(net.net_idx, net.dst, net.app_idx,
1979 cid, test_id, NULL, NULL);
1980 if (err) {
1981 printk("Health Fault Test Unacknowledged failed (err %d)\n",
1982 err);
1983 }
1984
1985 return 0;
1986 }
1987
1988 struct shell_cmd_help cmd_fault_test_unack_help = {
1989 NULL, "<Company ID> <Test ID>", NULL
1990 };
1991
cmd_period_get(int argc,char * argv[])1992 static int cmd_period_get(int argc, char *argv[])
1993 {
1994 u8_t divisor;
1995 int err;
1996 err = bt_mesh_health_period_get(net.net_idx, net.dst, net.app_idx,
1997 &divisor);
1998 if (err) {
1999 printk("Failed to send Health Period Get (err %d)\n", err);
2000 } else {
2001 printk("Health FastPeriodDivisor: %u\n", divisor);
2002 }
2003
2004 return 0;
2005 }
2006
cmd_period_set(int argc,char * argv[])2007 static int cmd_period_set(int argc, char *argv[])
2008 {
2009 u8_t divisor, updated_divisor;
2010 int err;
2011
2012 if (argc < 2) { // 2:Number of parameters
2013 return -EINVAL;
2014 }
2015
2016 divisor = strtoul(argv[1], NULL, 0);
2017 err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx,
2018 divisor, &updated_divisor);
2019 if (err) {
2020 printk("Failed to send Health Period Set (err %d)\n", err);
2021 } else {
2022 printk("Health FastPeriodDivisor: %u\n", updated_divisor);
2023 }
2024
2025 return 0;
2026 }
2027
2028 struct shell_cmd_help cmd_period_set_help = {
2029 NULL, "<divisor>", NULL
2030 };
2031
cmd_period_set_unack(int argc,char * argv[])2032 static int cmd_period_set_unack(int argc, char *argv[])
2033 {
2034 u8_t divisor;
2035 int err;
2036
2037 if (argc < 2) { // 2:Number of parameters
2038 return -EINVAL;
2039 }
2040
2041 divisor = strtoul(argv[1], NULL, 0);
2042 err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx,
2043 divisor, NULL);
2044 if (err) {
2045 printk("Failed to send Health Period Set (err %d)\n", err);
2046 }
2047
2048 return 0;
2049 }
2050
2051 struct shell_cmd_help cmd_period_set_unack_help = {
2052 NULL, "<divisor>", NULL
2053 };
2054
cmd_attention_get(int argc,char * argv[])2055 static int cmd_attention_get(int argc, char *argv[])
2056 {
2057 u8_t attention;
2058 int err;
2059 err = bt_mesh_health_attention_get(net.net_idx, net.dst, net.app_idx,
2060 &attention);
2061 if (err) {
2062 printk("Failed to send Health Attention Get (err %d)\n", err);
2063 } else {
2064 printk("Health Attention Timer: %u\n", attention);
2065 }
2066
2067 return 0;
2068 }
2069
cmd_attention_set(int argc,char * argv[])2070 static int cmd_attention_set(int argc, char *argv[])
2071 {
2072 u8_t attention, updated_attention;
2073 int err;
2074
2075 if (argc < 2) { // 2:Number of parameters
2076 return -EINVAL;
2077 }
2078
2079 attention = strtoul(argv[1], NULL, 0);
2080 err = bt_mesh_health_attention_set(net.net_idx, net.dst, net.app_idx,
2081 attention, &updated_attention);
2082 if (err) {
2083 printk("Failed to send Health Attention Set (err %d)\n", err);
2084 } else {
2085 printk("Health Attention Timer: %u\n", updated_attention);
2086 }
2087
2088 return 0;
2089 }
2090
2091 struct shell_cmd_help cmd_attention_set_help = {
2092 NULL, "<timer>", NULL
2093 };
2094
cmd_attention_set_unack(int argc,char * argv[])2095 static int cmd_attention_set_unack(int argc, char *argv[])
2096 {
2097 u8_t attention;
2098 int err;
2099
2100 if (argc < 2) { // 2:Number of parameters
2101 return -EINVAL;
2102 }
2103
2104 attention = strtoul(argv[1], NULL, 0);
2105 err = bt_mesh_health_attention_set(net.net_idx, net.dst, net.app_idx,
2106 attention, NULL);
2107 if (err) {
2108 printk("Failed to send Health Attention Set (err %d)\n", err);
2109 }
2110
2111 return 0;
2112 }
2113
2114 struct shell_cmd_help cmd_attention_set_unack_help = {
2115 NULL, "<timer>", NULL
2116 };
2117
2118 #endif /* MYNEWT_VAL(BLE_MESH_HEALTH_CLI) */
2119
cmd_add_fault(int argc,char * argv[])2120 static int cmd_add_fault(int argc, char *argv[])
2121 {
2122 u8_t fault_id;
2123 u8_t i;
2124
2125 if (argc < 2) { // 2:Number of parameters
2126 return -EINVAL;
2127 }
2128
2129 fault_id = strtoul(argv[1], NULL, 0);
2130 if (!fault_id) {
2131 printk("The Fault ID must be non-zero!\n");
2132 return -EINVAL;
2133 }
2134
2135 for (i = 0; i < sizeof(cur_faults); i++) {
2136 if (!cur_faults[i]) {
2137 cur_faults[i] = fault_id;
2138 break;
2139 }
2140 }
2141
2142 if (i == sizeof(cur_faults)) {
2143 printk("Fault array is full. Use \"del-fault\" to clear it\n");
2144 return 0;
2145 }
2146
2147 for (i = 0; i < sizeof(reg_faults); i++) {
2148 if (!reg_faults[i]) {
2149 reg_faults[i] = fault_id;
2150 break;
2151 }
2152 }
2153
2154 if (i == sizeof(reg_faults)) {
2155 printk("No space to store more registered faults\n");
2156 }
2157
2158 bt_mesh_fault_update(&elements[0]);
2159 return 0;
2160 }
2161
2162 struct shell_cmd_help cmd_add_fault_help = {
2163 NULL, "<Fault ID>", NULL
2164 };
2165
cmd_del_fault(int argc,char * argv[])2166 static int cmd_del_fault(int argc, char *argv[])
2167 {
2168 u8_t fault_id;
2169 u8_t i;
2170
2171 if (argc < 2) { // 2:Number of parameters
2172 memset(cur_faults, 0, sizeof(cur_faults));
2173 printk("All current faults cleared\n");
2174 bt_mesh_fault_update(&elements[0]);
2175 return 0;
2176 }
2177
2178 fault_id = strtoul(argv[1], NULL, 0);
2179 if (!fault_id) {
2180 printk("The Fault ID must be non-zero!\n");
2181 return -EINVAL;
2182 }
2183
2184 for (i = 0; i < sizeof(cur_faults); i++) {
2185 if (cur_faults[i] == fault_id) {
2186 cur_faults[i] = 0;
2187 printk("Fault cleared\n");
2188 }
2189 }
2190
2191 bt_mesh_fault_update(&elements[0]);
2192 return 0;
2193 }
2194
2195 struct shell_cmd_help cmd_del_fault_help = {
2196 NULL, "[Fault ID]", NULL
2197 };
2198
2199 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
cmd_gen_onoff_get(int argc,char * argv[])2200 static int cmd_gen_onoff_get(int argc, char *argv[])
2201 {
2202 u8_t state;
2203 int err;
2204 err = bt_mesh_gen_onoff_get(net.net_idx, net.dst, net.app_idx,
2205 &state);
2206 if (err) {
2207 printk("Failed to send Generic OnOff Get (err %d)\n", err);
2208 } else {
2209 printk("Gen OnOff State %d\n", state);
2210 }
2211
2212 return 0;
2213 }
2214
cmd_gen_onoff_set(int argc,char * argv[])2215 static int cmd_gen_onoff_set(int argc, char *argv[])
2216 {
2217 u8_t state;
2218 u8_t val;
2219 int err;
2220
2221 if (argc < 2) { // 2:Number of parameters
2222 return -EINVAL;
2223 }
2224
2225 val = strtoul(argv[1], NULL, 0);
2226 err = bt_mesh_gen_onoff_set(net.net_idx, net.dst, net.app_idx,
2227 val, &state);
2228 if (err) {
2229 printk("Failed to send Generic OnOff Get (err %d)\n", err);
2230 } else {
2231 printk("Gen OnOff State %d\n", state);
2232 }
2233
2234 return 0;
2235 }
2236
2237 struct shell_cmd_help cmd_gen_onoff_set_help = {
2238 NULL, "<0|1>", NULL
2239 };
2240
cmd_gen_onoff_set_unack(int argc,char * argv[])2241 static int cmd_gen_onoff_set_unack(int argc, char *argv[])
2242 {
2243 u8_t val;
2244 int err;
2245
2246 if (argc < 2) { // 2:Number of parameters
2247 return -EINVAL;
2248 }
2249
2250 val = strtoul(argv[1], NULL, 0);
2251 err = bt_mesh_gen_onoff_set(net.net_idx, net.dst, net.app_idx,
2252 val, NULL);
2253 if (err) {
2254 printk("Failed to send Generic OnOff Get (err %d)\n", err);
2255 }
2256
2257 return 0;
2258 }
2259
2260 struct shell_cmd_help cmd_gen_onoff_set_unack_help = {
2261 NULL, "<0|1>", NULL
2262 };
2263
cmd_gen_level_get(int argc,char * argv[])2264 static int cmd_gen_level_get(int argc, char *argv[])
2265 {
2266 s16_t state;
2267 int err;
2268 err = bt_mesh_gen_level_get(net.net_idx, net.dst, net.app_idx,
2269 &state);
2270 if (err) {
2271 printk("Failed to send Generic Level Get (err %d)\n", err);
2272 } else {
2273 printk("Gen Level State %d\n", state);
2274 }
2275
2276 return 0;
2277 }
2278
cmd_gen_level_set(int argc,char * argv[])2279 static int cmd_gen_level_set(int argc, char *argv[])
2280 {
2281 s16_t state;
2282 s16_t val;
2283 int err;
2284
2285 if (argc < 2) { // 2:Number of parameters
2286 return -EINVAL;
2287 }
2288
2289 val = (s16_t)strtoul(argv[1], NULL, 0);
2290 err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
2291 val, &state);
2292 if (err) {
2293 printk("Failed to send Generic Level Get (err %d)\n", err);
2294 } else {
2295 printk("Gen Level State %d\n", state);
2296 }
2297
2298 return 0;
2299 }
2300
2301 struct shell_cmd_help cmd_gen_level_set_help = {
2302 NULL, "<level>", NULL
2303 };
2304
cmd_gen_level_set_unack(int argc,char * argv[])2305 static int cmd_gen_level_set_unack(int argc, char *argv[])
2306 {
2307 s16_t val;
2308 int err;
2309
2310 if (argc < 2) { // 2:Number of parameters
2311 return -EINVAL;
2312 }
2313
2314 val = (s16_t)strtoul(argv[1], NULL, 0);
2315 err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
2316 val, NULL);
2317 if (err) {
2318 printk("Failed to send Generic Level Get (err %d)\n", err);
2319 }
2320
2321 return 0;
2322 }
2323
2324 struct shell_cmd_help cmd_gen_level_set_unack_help = {
2325 NULL, "<level>", NULL
2326 };
2327
2328 #endif /* MYNEWT_VAL(BLE_MESH_SHELL_MODELS) */
2329
cmd_print_credentials(int argc,char * argv[])2330 static int cmd_print_credentials(int argc, char *argv[])
2331 {
2332 bt_test_print_credentials();
2333 return 0;
2334 }
2335
print_comp_elem(struct bt_mesh_elem * elem,bool primary)2336 static void print_comp_elem(struct bt_mesh_elem *elem,
2337 bool primary)
2338 {
2339 struct bt_mesh_model *mod;
2340 int i;
2341 printk("Loc: %u\n", elem->loc);
2342 printk("Model count: %u\n", elem->model_count);
2343 printk("Vnd model count: %u\n", elem->vnd_model_count);
2344
2345 for (i = 0; i < elem->model_count; i++) {
2346 mod = &elem->models[i];
2347 printk(" Model: %u\n", i);
2348 printk(" ID: 0x%04x\n", mod->id);
2349 printk(" Opcode: 0x%08lx\n", mod->op->opcode);
2350 }
2351
2352 for (i = 0; i < elem->vnd_model_count; i++) {
2353 mod = &elem->vnd_models[i];
2354 printk(" Vendor model: %u\n", i);
2355 printk(" Company: 0x%04x\n", mod->vnd.company);
2356 printk(" ID: 0x%04x\n", mod->vnd.id);
2357 printk(" Opcode: 0x%08lx\n", mod->op->opcode);
2358 }
2359 }
2360
cmd_print_composition_data(int argc,char * argv[])2361 static int cmd_print_composition_data(int argc, char *argv[])
2362 {
2363 const struct bt_mesh_comp *comp;
2364 int i;
2365 comp = bt_mesh_comp_get();
2366 printk("CID: %u\n", comp->cid);
2367 printk("PID: %u\n", comp->pid);
2368 printk("VID: %u\n", comp->vid);
2369
2370 for (i = 0; i < comp->elem_count; i++) {
2371 print_comp_elem(&comp->elem[i], i == 0);
2372 }
2373
2374 return 0;
2375 }
2376
2377 static const struct shell_cmd mesh_commands[] = {
2378 {
2379 .sc_cmd = "init",
2380 .sc_cmd_func = cmd_mesh_init,
2381 .help = NULL,
2382 },
2383 #if MYNEWT_VAL(BLE_MESH_PB_ADV)
2384 {
2385 .sc_cmd = "pb-adv",
2386 .sc_cmd_func = cmd_pb_adv,
2387 .help = &cmd_pb_help,
2388 },
2389 #if MYNEWT_VAL(BLE_MESH_PROVISIONER)
2390 {
2391 .sc_cmd = "provision-adv",
2392 .sc_cmd_func = cmd_provision_adv,
2393 .help = &cmd_provision_adv_help,
2394 },
2395 #endif
2396 #endif
2397 #if MYNEWT_VAL(BLE_MESH_PB_GATT)
2398 {
2399 .sc_cmd = "pb-gatt",
2400 .sc_cmd_func = cmd_pb_gatt,
2401 .help = &cmd_pb_help,
2402 },
2403 #endif
2404 {
2405 .sc_cmd = "reset",
2406 .sc_cmd_func = cmd_reset,
2407 .help = NULL,
2408 },
2409 {
2410 .sc_cmd = "uuid",
2411 .sc_cmd_func = cmd_uuid,
2412 .help = &cmd_uuid_help,
2413 },
2414 {
2415 .sc_cmd = "input-num",
2416 .sc_cmd_func = cmd_input_num,
2417 .help = &cmd_input_num_help,
2418 },
2419 {
2420 .sc_cmd = "input-str",
2421 .sc_cmd_func = cmd_input_str,
2422 .help = &cmd_input_str_help,
2423 },
2424 {
2425 .sc_cmd = "static-oob",
2426 .sc_cmd_func = cmd_static_oob,
2427 .help = &cmd_static_oob_help,
2428 },
2429 {
2430 .sc_cmd = "provision",
2431 .sc_cmd_func = cmd_provision,
2432 .help = &cmd_provision_help,
2433 },
2434 #if MYNEWT_VAL(BLE_MESH_LOW_POWER)
2435 {
2436 .sc_cmd = "lpn",
2437 .sc_cmd_func = cmd_lpn,
2438 .help = &cmd_lpn_help,
2439 },
2440 {
2441 .sc_cmd = "poll",
2442 .sc_cmd_func = cmd_poll,
2443 .help = NULL,
2444 },
2445 #endif
2446 #if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
2447 {
2448 .sc_cmd = "ident",
2449 .sc_cmd_func = cmd_ident,
2450 .help = NULL,
2451 },
2452 #endif
2453 {
2454 .sc_cmd = "dst",
2455 .sc_cmd_func = cmd_dst,
2456 .help = &cmd_dst_help,
2457 },
2458 {
2459 .sc_cmd = "netidx",
2460 .sc_cmd_func = cmd_netidx,
2461 .help = &cmd_netidx_help,
2462 },
2463 {
2464 .sc_cmd = "appidx",
2465 .sc_cmd_func = cmd_appidx,
2466 .help = &cmd_appidx_help,
2467 },
2468
2469 /* Commands which access internal APIs, for testing only */
2470 {
2471 .sc_cmd = "net-send",
2472 .sc_cmd_func = cmd_net_send,
2473 .help = &cmd_net_send_help,
2474 },
2475 #if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST)
2476 {
2477 .sc_cmd = "iv-update",
2478 .sc_cmd_func = cmd_iv_update,
2479 .help = NULL,
2480 },
2481 {
2482 .sc_cmd = "iv-update-test",
2483 .sc_cmd_func = cmd_iv_update_test,
2484 .help = &cmd_iv_update_test_help,
2485 },
2486 #endif
2487 {
2488 .sc_cmd = "rpl-clear",
2489 .sc_cmd_func = cmd_rpl_clear,
2490 .help = NULL,
2491 },
2492 #if MYNEWT_VAL(BLE_MESH_LOW_POWER)
2493 {
2494 .sc_cmd = "lpn-subscribe",
2495 .sc_cmd_func = cmd_lpn_subscribe,
2496 .help = &cmd_lpn_subscribe_help,
2497 },
2498 {
2499 .sc_cmd = "lpn-unsubscribe",
2500 .sc_cmd_func = cmd_lpn_unsubscribe,
2501 .help = &cmd_lpn_unsubscribe_help,
2502 },
2503 #endif
2504 {
2505 .sc_cmd = "print-credentials",
2506 .sc_cmd_func = cmd_print_credentials,
2507 .help = NULL,
2508 },
2509 {
2510 .sc_cmd = "print-composition-data",
2511 .sc_cmd_func = cmd_print_composition_data,
2512 .help = NULL,
2513 },
2514
2515 #if MYNEWT_VAL(BLE_MESH_CFG_CLI)
2516 /* Configuration Client Model operations */
2517 {
2518 .sc_cmd = "timeout",
2519 .sc_cmd_func = cmd_timeout,
2520 .help = &cmd_timeout_help,
2521 },
2522 {
2523 .sc_cmd = "get-comp",
2524 .sc_cmd_func = cmd_get_comp,
2525 .help = &cmd_get_comp_help,
2526 },
2527 {
2528 .sc_cmd = "beacon",
2529 .sc_cmd_func = cmd_beacon,
2530 .help = &cmd_beacon_help,
2531 },
2532 {
2533 .sc_cmd = "ttl",
2534 .sc_cmd_func = cmd_ttl,
2535 .help = &cmd_ttl_help,
2536 },
2537 {
2538 .sc_cmd = "friend",
2539 .sc_cmd_func = cmd_friend,
2540 .help = &cmd_friend_help,
2541 },
2542 {
2543 .sc_cmd = "gatt-proxy",
2544 .sc_cmd_func = cmd_gatt_proxy,
2545 .help = &cmd_gatt_proxy_help,
2546 },
2547 {
2548 .sc_cmd = "relay",
2549 .sc_cmd_func = cmd_relay,
2550 .help = &cmd_relay_help,
2551 },
2552 {
2553 .sc_cmd = "net-key-add",
2554 .sc_cmd_func = cmd_net_key_add,
2555 .help = &cmd_net_key_add_help,
2556 },
2557 {
2558 .sc_cmd = "app-key-add",
2559 .sc_cmd_func = cmd_app_key_add,
2560 .help = &cmd_app_key_add_help,
2561 },
2562 {
2563 .sc_cmd = "mod-app-bind",
2564 .sc_cmd_func = cmd_mod_app_bind,
2565 .help = &cmd_mod_app_bind_help,
2566 },
2567 {
2568 .sc_cmd = "mod-pub",
2569 .sc_cmd_func = cmd_mod_pub,
2570 .help = &cmd_mod_pub_help,
2571 },
2572 {
2573 .sc_cmd = "mod-sub-add",
2574 .sc_cmd_func = cmd_mod_sub_add,
2575 .help = &cmd_mod_sub_add_help,
2576 },
2577 {
2578 .sc_cmd = "mod-sub-del",
2579 .sc_cmd_func = cmd_mod_sub_del,
2580 .help = &cmd_mod_sub_del_help,
2581 },
2582 {
2583 .sc_cmd = "mod-sub-add-va",
2584 .sc_cmd_func = cmd_mod_sub_add_va,
2585 .help = &cmd_mod_sub_add_va_help,
2586 },
2587 {
2588 .sc_cmd = "mod-sub-del-va",
2589 .sc_cmd_func = cmd_mod_sub_del_va,
2590 .help = &cmd_mod_sub_del_va_help,
2591 },
2592 {
2593 .sc_cmd = "hb-sub",
2594 .sc_cmd_func = cmd_hb_sub,
2595 .help = &cmd_hb_sub_help,
2596 },
2597 {
2598 .sc_cmd = "hb-pub",
2599 .sc_cmd_func = cmd_hb_pub,
2600 .help = &cmd_hb_pub_help,
2601 },
2602 #endif
2603
2604 #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
2605 /* Health Client Model Operations */
2606 {
2607 .sc_cmd = "fault-get",
2608 .sc_cmd_func = cmd_fault_get,
2609 .help = &cmd_fault_get_help,
2610 },
2611 {
2612 .sc_cmd = "fault-clear",
2613 .sc_cmd_func = cmd_fault_clear,
2614 .help = &cmd_fault_clear_help,
2615 },
2616 {
2617 .sc_cmd = "fault-clear-unack",
2618 .sc_cmd_func = cmd_fault_clear_unack,
2619 .help = &cmd_fault_clear_unack_help,
2620 },
2621 {
2622 .sc_cmd = "fault-test",
2623 .sc_cmd_func = cmd_fault_test,
2624 .help = &cmd_fault_test_help,
2625 },
2626 {
2627 .sc_cmd = "fault-test-unack",
2628 .sc_cmd_func = cmd_fault_test_unack,
2629 .help = &cmd_fault_test_unack_help,
2630 },
2631 {
2632 .sc_cmd = "period-get",
2633 .sc_cmd_func = cmd_period_get,
2634 .help = NULL,
2635 },
2636 {
2637 .sc_cmd = "period-set",
2638 .sc_cmd_func = cmd_period_set,
2639 .help = &cmd_period_set_help,
2640 },
2641 {
2642 .sc_cmd = "period-set-unack",
2643 .sc_cmd_func = cmd_period_set_unack,
2644 .help = &cmd_period_set_unack_help,
2645 },
2646 {
2647 .sc_cmd = "attention-get",
2648 .sc_cmd_func = cmd_attention_get,
2649 .help = NULL,
2650 },
2651 {
2652 .sc_cmd = "attention-set",
2653 .sc_cmd_func = cmd_attention_set,
2654 .help = &cmd_attention_set_help,
2655 },
2656 {
2657 .sc_cmd = "attention-set-unack",
2658 .sc_cmd_func = cmd_attention_set_unack,
2659 .help = &cmd_attention_set_unack_help,
2660 },
2661 #endif
2662
2663 /* Health Server Model Operations */
2664 {
2665 .sc_cmd = "add-fault",
2666 .sc_cmd_func = cmd_add_fault,
2667 .help = &cmd_add_fault_help,
2668 },
2669 {
2670 .sc_cmd = "del-fault",
2671 .sc_cmd_func = cmd_del_fault,
2672 .help = &cmd_del_fault_help,
2673 },
2674
2675 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
2676 /* Generic Client Model Operations */
2677 {
2678 .sc_cmd = "gen-onoff-get",
2679 .sc_cmd_func = cmd_gen_onoff_get,
2680 .help = NULL,
2681 },
2682 {
2683 .sc_cmd = "gen-onoff-set",
2684 .sc_cmd_func = cmd_gen_onoff_set,
2685 .help = &cmd_gen_onoff_set_help,
2686 },
2687 {
2688 .sc_cmd = "gen-onoff-set-unack",
2689 .sc_cmd_func = cmd_gen_onoff_set_unack,
2690 .help = &cmd_gen_onoff_set_unack_help,
2691 },
2692 {
2693 .sc_cmd = "gen-level-get",
2694 .sc_cmd_func = cmd_gen_level_get,
2695 .help = NULL,
2696 },
2697 {
2698 .sc_cmd = "gen-level-set",
2699 .sc_cmd_func = cmd_gen_level_set,
2700 .help = &cmd_gen_level_set_help,
2701 },
2702 {
2703 .sc_cmd = "gen-level-set-unack",
2704 .sc_cmd_func = cmd_gen_level_set_unack,
2705 .help = &cmd_gen_level_set_unack_help,
2706 },
2707 #endif
2708
2709 { 0 },
2710 };
2711
mesh_shell_thread(void * args)2712 static void mesh_shell_thread(void *args)
2713 {
2714 while (1) {
2715 os_eventq_run(&mesh_shell_queue);
2716 }
2717 }
2718
bt_mesh_shell_task_init(void)2719 static void bt_mesh_shell_task_init(void)
2720 {
2721 os_eventq_init(&mesh_shell_queue);
2722 os_task_init(&mesh_shell_task, "mesh_sh", mesh_shell_thread, NULL,
2723 BLE_MESH_SHELL_TASK_PRIO, OS_WAIT_FOREVER, g_blemesh_shell_stack,
2724 BLE_MESH_SHELL_STACK_SIZE);
2725 }
2726 #endif
2727
ble_mesh_shell_init(void)2728 void ble_mesh_shell_init(void)
2729 {
2730 #if (MYNEWT_VAL(BLE_MESH_SHELL))
2731 /* Initialize health pub message */
2732 health_pub_init();
2733 /* Shell and other mesh clients should use separate task to
2734 avoid deadlocks with mesh message processing queue */
2735 bt_mesh_shell_task_init();
2736 shell_evq_set(&mesh_shell_queue);
2737 shell_register("mesh", mesh_commands);
2738 #endif
2739 }