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