1 /*
2 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7
8 #include <api/mesh.h>
9 #include <aos/debug.h>
10 #include <aos/kernel.h>
11 #include <aos/kv.h>
12 #include <aos/ble.h>
13 #include <bt_errno.h>
14 #include <mesh.h>
15 #include "mesh_node.h"
16 #include "mesh_model/mesh_model.h"
17
18 #ifdef CONFIG_BT_MESH_PROVISIONER
19 #include "provisioner_prov.h"
20 #include "provisioner_main.h"
21 #include "provisioner_proxy.h"
22 #endif
23
24 #define COMMON_SUB_ADDR 0xF000
25 #define COMMON_PUB_ADDR 0xF001
26 #define TIMEOUT 402
27
28 static uint8_t dev_uuid[16];
29 static uint8_t g_static_data[16] = { 0 };
30
31 #define TAG "BT_MESH_NODE"
32
33 #ifdef BT_MESH_BEACON_RSSI_REPORT
34 typedef struct {
35 uint8_t mac[6];
36 uint8_t rssi;
37 uint8_t rssi_calibration;
38 } beacon_rssi_data;
39
40 typedef struct {
41 uint8_t front;
42 uint8_t rear;
43 uint8_t length;
44 beacon_rssi_data data[16];
45 } rssi_data_queue;
46 #endif
47 typedef void (*node_event_cb)(uint16_t event, void *p_arg);
48
49 typedef struct _mesh_node {
50 const struct bt_mesh_comp *comp;
51 model_event_cb user_model_cb;
52 uint8_t init_flag;
53 #ifdef CONFIG_BT_MESH_PROVISIONER
54 provisioner_cb user_provisioner_cb;
55 k_timer_t add_appkey_timer;
56 uint32_t add_appkey_timeout;
57 uint8_t app_key_add_retry;
58 uint16_t auto_add_appkey_idx;
59 #else
60 prov_event_cb user_prov_cb;
61 k_timer_t auto_config_timer;
62 uint32_t auto_config_timeout;
63 uint8_t app_key_add_flag:1;
64 uint8_t auto_config_retry;
65 uint8_t auto_config_ack_flag;
66 uint8_t auto_config_status;
67 uint16_t prov_addr;
68 bt_mesh_input_action_t input_act;
69 uint8_t input_size;
70 #endif
71
72 #ifdef BT_MESH_BEACON_RSSI_REPORT
73 uint8_t rssi_report_enable:1;
74 k_timer_t beacon_rssi_timer;
75 rssi_data_queue rssi_queue;
76 #endif
77 uint8_t node_provisioned;
78 health_srv_cb health_cb;
79 } mesh_node;
80
81 mesh_node g_mesh_node;
82
83 #ifdef BT_MESH_BEACON_RSSI_REPORT
84 static int init_rssi_report();
85 #endif
86
87 extern void bt_mesh_store_mod_bind(struct bt_mesh_model *mod);
88 extern void bt_mesh_store_mod_sub(struct bt_mesh_model *mod);
89 extern void bt_mesh_store_mod_pub(struct bt_mesh_model *mod);
90 extern u16_t *bt_mesh_model_find_group(struct bt_mesh_model *mod, u16_t addr);
91 extern int bt_mesh_store_mod_pending_check();
92
93 #ifndef CONFIG_BT_MESH_PROVISIONER
94
report_auto_config_status(uint16_t dst_addr,uint8_t status)95 static int report_auto_config_status(uint16_t dst_addr, uint8_t status)
96 {
97 #ifdef CONFIG_BT_MESH_MODEL_VENDOR_SRV
98 static uint8_t tid = 0;
99 struct bt_mesh_model *vnd_model = ble_mesh_model_find(0, BT_MESH_MODEL_VND_MODEL_SRV, CONFIG_CID_TAOBAO);
100
101 if (!vnd_model) {
102 return -1;
103 }
104
105 vnd_model_msg vnd_msg = { 0 };
106 vnd_msg.netkey_idx = 0;
107 vnd_msg.appkey_idx = 0;
108 vnd_msg.dst_addr = dst_addr;
109 vnd_msg.tid = tid++;
110 vnd_msg.model = vnd_model;
111 vnd_msg.opid = VENDOR_OP_ATTR_MESH_AUTOCONFIG_STATUS;
112 vnd_msg.len = 1;
113 vnd_msg.data = (uint8_t *)&status;
114 return ble_mesh_vendor_srv_model_msg_send(&vnd_msg);
115 #else
116 return 0;
117 #endif
118 }
auto_config_timeout_cb(void * timer,void * arg)119 static void auto_config_timeout_cb(void *timer, void *arg)
120 {
121 int16_t ret;
122
123 k_timer_stop(&g_mesh_node.auto_config_timer);
124
125 if (!bt_mesh_store_mod_pending_check()) {
126 g_mesh_node.auto_config_status = BT_MESH_AUTO_CONFIG_SUCCEED;
127 g_mesh_node.node_provisioned = 1;
128
129 if (g_mesh_node.auto_config_ack_flag) {
130 ret = report_auto_config_status(g_mesh_node.prov_addr, g_mesh_node.auto_config_status);
131
132 if (ret) {
133 LOGE(TAG, "report auto config status faild");
134 }
135 }
136
137 ret = aos_kv_setint("AUTO_CONFIG", BT_MESH_AUTO_CONFIG_SUCCEED);
138
139 if (ret) {
140 LOGE(TAG, "save auto config status faild");
141 }
142
143 #ifdef BT_MESH_BEACON_RSSI_REPORT
144
145 if (g_mesh_node.rssi_report_enable) {
146 init_rssi_report();
147 }
148
149 #endif
150 } else {
151 LOGI(TAG, "store is pending");
152
153 if (g_mesh_node.auto_config_retry) {
154 k_timer_start(&g_mesh_node.auto_config_timer, g_mesh_node.auto_config_timeout);
155 g_mesh_node.auto_config_retry--;
156 }
157 }
158 }
159 #endif
160
161 #ifdef CONFIG_BT_MESH_PROVISIONER
162
163 static uint16_t last_addr;
164
165 static struct bt_mesh_prov node_prov = {
166 .uuid = dev_uuid,
167 .link_open = NULL,
168 .link_close = NULL,
169 .complete = NULL,
170 .reset = NULL,
171 .static_val = g_static_data,
172 .static_val_len = 0,
173 .input_size = 0,
174 .input_actions = 0,
175 .input = NULL,
176 .output_size = 0,
177 .output_actions = 0,
178 .output_number = NULL,
179 .output_string = NULL,
180 };
181 #else
182 static void link_open(bt_mesh_prov_bearer_t bearer);
183 static void link_close(bt_mesh_prov_bearer_t bearer);
184 static void prov_complete(uint16_t net_idx, uint16_t addr);
185 static void prov_reset(void);
186 static int output_number(bt_mesh_output_action_t action, bt_u32_t number);
187 static int output_string(const char *str);
188 static int node_input(bt_mesh_input_action_t act, u8_t size);
189
190 static struct bt_mesh_prov node_prov = {
191 .uuid = dev_uuid,
192 .link_open = link_open,
193 .link_close = link_close,
194 .complete = prov_complete,
195 .reset = prov_reset,
196 .static_val = g_static_data,
197 .static_val_len = 0,
198 .input_size = 0,
199 .input_actions = 0,
200 .input = node_input,
201 .output_size = 0,
202 .output_actions = 0,
203 .output_number = output_number,
204 .output_string = output_string,
205 };
206 #endif
207
208 typedef struct auto_config_t {
209 uint16_t mod_id;
210 uint16_t cid;
211 uint16_t appkey_idx;
212 uint16_t sub_addr;
213 uint16_t pub_addr;
214 } auto_config_t;
215
node_config(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)216 static void node_config(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data)
217 {
218 auto_config_t *config = user_data;
219
220 if (!config) {
221 return;
222 }
223
224 if (!vnd && (mod->id == BT_MESH_MODEL_ID_CFG_SRV || mod->id == BT_MESH_MODEL_ID_CFG_CLI ||
225 mod->id == BT_MESH_MODEL_ID_HEALTH_SRV || mod->id == BT_MESH_MODEL_ID_HEALTH_CLI)) {
226 return;
227 }
228
229 if (!vnd) {
230 if (config->mod_id != 0xffff && config->mod_id != mod->id) {
231 return;
232 }
233 } else {
234 if ((config->mod_id != 0xffff && config->cid != 0xffff) &&
235 (config->mod_id != mod->vnd.id || config->cid != mod->vnd.company)) {
236 return;
237 }
238 }
239
240 bt_mesh_mod_bind(mod, config->appkey_idx);
241
242 bt_mesh_mod_sub_add(mod, config->sub_addr);
243
244 bt_mesh_mod_pub_set(mod, config->pub_addr);
245 }
246
auto_config(auto_config_t * config)247 static int16_t auto_config(auto_config_t *config)
248 {
249 if (!config) {
250 return -EINVAL;
251 }
252
253 LOGD(TAG, "bind appkey:%04x sub addr:%04x pub addr:%04x", config->appkey_idx, config->sub_addr, config->pub_addr);
254 extern void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd,
255 bool primary, void *user_data),
256 void *user_data);
257 bt_mesh_model_foreach(node_config, config);
258
259 return 0;
260 }
261
262 #ifdef CONFIG_BT_MESH_PROVISIONER
ble_mesh_node_appkey_add(uint16_t netkey_idx,uint16_t appkey_idx,uint16_t unicast_addr)263 int ble_mesh_node_appkey_add(uint16_t netkey_idx, uint16_t appkey_idx, uint16_t unicast_addr)
264 {
265 const uint8_t *app_key;
266 int16_t ret;
267
268 app_key = bt_mesh_provisioner_local_app_key_get(netkey_idx, appkey_idx);
269
270 if (NULL == app_key) {
271 return -1;
272 }
273
274 ret = bt_mesh_cfg_app_key_add(0, unicast_addr, netkey_idx, appkey_idx, app_key, NULL);
275
276 if (ret && TIMEOUT != ret) {
277 LOGE(TAG, "mesh appkey add set status send fail %d", ret);
278 return ret;
279 }
280
281 return 0;
282 }
283
ble_mesh_node_model_autoconfig(uint16_t netkey_idx,uint16_t appkey_idx,uint16_t addr,model_auto_config_t auto_conf)284 int ble_mesh_node_model_autoconfig(uint16_t netkey_idx, uint16_t appkey_idx, uint16_t addr,
285 model_auto_config_t auto_conf)
286 {
287 #ifdef CONFIG_BT_MESH_MODEL_VENDOR_SRV
288 static uint8_t tid = 0;
289 struct bt_mesh_model *vendor_model;
290 vnd_model_msg vnd_msg = { 0 };
291 int16_t ret;
292 uint16_t send_data;
293 vendor_model = ble_mesh_model_find(0, BT_MESH_MODEL_VND_MODEL_CLI, BT_MESH_MODEL_VND_COMPANY_ID);
294
295 if (!vendor_model) {
296 return -1;
297 }
298
299 send_data = auto_conf.sub_addr;
300 vnd_msg.netkey_idx = netkey_idx;
301 vnd_msg.appkey_idx = appkey_idx;
302 vnd_msg.dst_addr = addr;
303 vnd_msg.tid = tid++;
304 vnd_msg.model = vendor_model;
305 vnd_msg.len = 2;
306 vnd_msg.opid = VENDOR_OP_ATTR_MESH_AUTOCONFIG;
307 vnd_msg.data = (uint8_t *)&send_data;
308
309 ret = ble_mesh_vendor_cli_model_msg_send(&vnd_msg);
310
311 if (ret) {
312 return -1;
313 }
314 #endif
315 return 0;
316 }
317
add_appkey_timeout_cb(void * timer,void * arg)318 static void add_appkey_timeout_cb(void *timer, void *arg)
319 {
320 int16_t ret;
321 k_timer_stop(&g_mesh_node.add_appkey_timer);
322
323 if (g_mesh_node.app_key_add_retry) {
324 ret = ble_mesh_node_appkey_add(0, g_mesh_node.auto_add_appkey_idx, last_addr);
325
326 if (ret) {
327 LOGE(TAG, "add appkey send faild");
328 } else {
329 g_mesh_node.app_key_add_retry--;
330 k_timer_start(&g_mesh_node.add_appkey_timer, g_mesh_node.add_appkey_timeout);
331 }
332
333 } else {
334 LOGE(TAG, "add appkey faild");
335 }
336 }
337
provisioner_node_cb(mesh_provisioner_event_en event,void * p_arg)338 static void provisioner_node_cb(mesh_provisioner_event_en event, void *p_arg)
339 {
340 switch (event) {
341 // provisioner message
342
343 case BT_MESH_EVENT_PROV_COMP: {
344 if (p_arg) {
345 mesh_node_t *node = (mesh_node_t *)p_arg;
346 uint8_t auto_add_appkey = 0;
347 extern int ble_mesh_provisioner_get_add_appkey_flag(u16_t unicast_addr);
348 auto_add_appkey = ble_mesh_provisioner_get_add_appkey_flag(node->prim_unicast);
349
350 if (auto_add_appkey) {
351 g_mesh_node.app_key_add_retry = DEF_ADD_APPKEY_RETRY;
352 g_mesh_node.add_appkey_timeout = DEF_ADD_APPKEY_TIMEOUT;
353 g_mesh_node.auto_add_appkey_idx = 0;
354 last_addr = node->prim_unicast;
355 k_timer_start(&g_mesh_node.add_appkey_timer, DEF_ADD_APPKEY_DELAY);
356 }
357 }
358 } break;
359
360 default:
361 break;
362 }
363
364 if (g_mesh_node.user_provisioner_cb) {
365 g_mesh_node.user_provisioner_cb(event, p_arg);
366 }
367 }
368
369 #else
370
371 // __attribute__((unused)) static const char *bearer2str(int bearer)
bearer2str(int bearer)372 static const char *bearer2str(int bearer)
373 {
374 switch (bearer) {
375 case BT_MESH_PROV_ADV:
376 return "PB-ADV";
377
378 case BT_MESH_PROV_GATT:
379 return "PB-GATT";
380
381 default:
382 return "unknown";
383 }
384 }
385
link_open(bt_mesh_prov_bearer_t bearer)386 static void link_open(bt_mesh_prov_bearer_t bearer)
387 {
388 LOGI(TAG, "Provisioning link opened on %s\n", bearer2str(bearer));
389 }
390
link_close(bt_mesh_prov_bearer_t bearer)391 static void link_close(bt_mesh_prov_bearer_t bearer)
392 {
393 LOGI(TAG, "Provisioning link closed on %s\n", bearer2str(bearer));
394 }
395
prov_complete(uint16_t net_idx,uint16_t addr)396 static void prov_complete(uint16_t net_idx, uint16_t addr)
397 {
398 LOGI(TAG, "provisioning complete netid %d, primary element address 0x%x", net_idx, addr);
399 mesh_node_local_t node_info;
400 node_info.prim_unicast = addr;
401 g_mesh_node.auto_config_status = BT_MESH_AUTO_CONFIG_NOT_START;
402 g_mesh_node.app_key_add_flag = 0;
403
404 if (g_mesh_node.user_prov_cb) {
405 g_mesh_node.user_prov_cb(BT_MESH_EVENT_NODE_PROV_COMP, &node_info);
406 }
407 }
408
prov_reset(void)409 static void prov_reset(void)
410 {
411 LOGD(TAG, "Node Reset");
412 bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
413
414 if (g_mesh_node.user_prov_cb) {
415 g_mesh_node.user_prov_cb(BT_MESH_EVENT_NODE_REST, NULL);
416 }
417 }
418
output_number(bt_mesh_output_action_t action,bt_u32_t number)419 static int output_number(bt_mesh_output_action_t action, bt_u32_t number)
420 {
421 LOGI(TAG, "OOB Number: %u\n", number);
422 return 0;
423 }
424
output_string(const char * str)425 static int output_string(const char *str)
426 {
427 LOGI(TAG, "OOB String: %s\n", str);
428 return 0;
429 }
430
node_input(bt_mesh_input_action_t act,u8_t size)431 static int node_input(bt_mesh_input_action_t act, u8_t size)
432 {
433 switch (act) {
434 case BT_MESH_ENTER_NUMBER: {
435 LOGI(TAG, "Enter a number (max %u digits) with: input-num <num>\n", size);
436
437 if (g_mesh_node.user_prov_cb) {
438 g_mesh_node.user_prov_cb(BT_MESH_EVENT_NODE_OOB_INPUT_NUM, &size);
439 }
440 } break;
441
442 case BT_MESH_ENTER_STRING: {
443 LOGI(TAG, "Enter a string (max %u chars) with: input-str <str>\n", size);
444
445 if (g_mesh_node.user_prov_cb) {
446 g_mesh_node.user_prov_cb(BT_MESH_EVENT_NODE_OOB_INPUT_STRING, &size);
447 }
448 } break;
449
450 default: {
451 LOGI(TAG, "Unknown input action %u (size %u) requested!\n", act, size);
452 return -EINVAL;
453 } break;
454 }
455
456 g_mesh_node.input_act = act;
457 g_mesh_node.input_size = size;
458 return 0;
459 }
460
461 #ifdef BT_MESH_BEACON_RSSI_REPORT
is_rssi_data_queue_empty(rssi_data_queue * queue)462 static bool is_rssi_data_queue_empty(rssi_data_queue *queue)
463 {
464 return queue->front == queue->rear;
465 }
466
is_rssi_data_queue_full(rssi_data_queue * queue)467 static bool is_rssi_data_queue_full(rssi_data_queue *queue)
468 {
469 if ((queue->rear + 1) % 16 == queue->front) {
470 return true;
471 } else {
472 return false;
473 }
474 }
475
get_rssi_data(rssi_data_queue * queue)476 static beacon_rssi_data *get_rssi_data(rssi_data_queue *queue)
477 {
478 if (is_rssi_data_queue_empty(queue)) {
479 return NULL;
480 } else {
481 beacon_rssi_data *data = &queue->data[queue->front];
482 queue->front = (queue->front + 1) % 16;
483 return data;
484 }
485 }
486
put_rssi_data(rssi_data_queue * queue,const uint8_t * mac,int8_t rssi,int8_t rssi_calibration)487 static int put_rssi_data(rssi_data_queue *queue, const uint8_t *mac, int8_t rssi, int8_t rssi_calibration)
488 {
489 if (is_rssi_data_queue_full(queue)) {
490 return -1;
491 }
492
493 memcpy(queue->data[queue->rear].mac, mac, 6);
494 queue->data[queue->rear].rssi = rssi;
495 queue->data[queue->rear].rssi_calibration = rssi_calibration;
496 queue->rear = (queue->rear + 1) % 16;
497 return 0;
498 }
499
data_complent_u8(int8_t data)500 static uint8_t data_complent_u8(int8_t data)
501 {
502 uint8_t out;
503
504 if (data <= 0) {
505 out = data;
506 } else {
507 uint8_t in = -data;
508 out = ~in + 1;
509 }
510
511 return out;
512 }
513
beacon_rssi_cb(const struct adv_addr_t * addr,s8_t rssi,u8_t adv_type,void * user_data,uint16_t len)514 static void beacon_rssi_cb(const struct adv_addr_t *addr, s8_t rssi, u8_t adv_type, void *user_data, uint16_t len)
515 {
516 if (!g_mesh_node.node_provisioned) {
517 return;
518 }
519
520 if (!user_data || !len) {
521 return;
522 }
523
524 struct net_buf_simple *buf = (struct net_buf_simple *)user_data;
525
526 uint8_t data_len = net_buf_simple_pull_u8(buf);
527
528 if (!data_len) {
529 return;
530 }
531
532 uint8_t opid = net_buf_simple_pull_u8(buf);
533
534 if (0x02 != opid) {
535 return;
536 }
537
538 int8_t rssi_calibration = net_buf_simple_pull_u8(buf);
539
540 put_rssi_data(&g_mesh_node.rssi_queue, addr->val, data_complent_u8(rssi), data_complent_u8(rssi_calibration));
541 }
542
rssi_repot_timeout(void * timer,void * args)543 void rssi_repot_timeout(void *timer, void *args)
544 {
545 beacon_rssi_data *data = NULL;
546 k_timer_start(&g_mesh_node.beacon_rssi_timer, RSSI_BEACON_REPORT_PERIOD);
547 data = get_rssi_data(&g_mesh_node.rssi_queue);
548
549 if (!data) {
550 return;
551 }
552
553 struct bt_mesh_model *vendor_model;
554
555 vendor_model = ble_mesh_model_find(0, BT_MESH_MODEL_VND_MODEL_SRV, CONFIG_CID_TAOBAO);
556
557 if (!vendor_model || !vendor_model->pub || BT_MESH_ADDR_UNASSIGNED == vendor_model->pub->addr) {
558 return;
559 }
560
561 vnd_model_msg vnd_data = { 0 };
562 uint8_t rssi_data[60];
563 snprintf((char *)rssi_data, sizeof(rssi_data), "rssi%02x,%02x,%02x%02x%02x%02x%02x%02x", data->rssi,
564 data->rssi_calibration, data->mac[5], data->mac[4], data->mac[3], data->mac[2], data->mac[1],
565 data->mac[0]);
566 vnd_data.netkey_idx = 0;
567 vnd_data.appkey_idx = 0;
568 vnd_data.dst_addr = vendor_model->pub->addr;
569 vnd_data.model = vendor_model;
570 vnd_data.opid = VENDOR_OP_ATTR_TRANS_MSG;
571 vnd_data.data = rssi_data;
572 vnd_data.retry = 0;
573 vnd_data.len = strlen((char *)rssi_data);
574 ble_mesh_vendor_srv_model_msg_send(&vnd_data);
575 }
576
init_rssi_report()577 static int init_rssi_report()
578 {
579 int16_t ret;
580 ret = bt_mesh_vnd_adv_set_cb(beacon_rssi_cb);
581
582 if (ret) {
583 return ret;
584 }
585
586 g_mesh_node.rssi_queue.front = 0;
587 g_mesh_node.rssi_queue.rear = 0;
588 g_mesh_node.rssi_queue.length = 16;
589 k_timer_init(&g_mesh_node.beacon_rssi_timer, rssi_repot_timeout, NULL);
590 k_timer_start(&g_mesh_node.beacon_rssi_timer, RSSI_BEACON_REPORT_PERIOD);
591 return 0;
592 }
593 #endif
594
ble_mesh_node_OOB_input_string(const char * str)595 int ble_mesh_node_OOB_input_string(const char *str)
596 {
597 if (!g_mesh_node.init_flag) {
598 return -1;
599 }
600
601 int16_t ret;
602
603 if (g_mesh_node.input_act != BT_MESH_ENTER_STRING) {
604 LOGE(TAG, "A string hasn't been requested!\n");
605 return -1;
606 }
607
608 if (strlen(str) < g_mesh_node.input_size) {
609 LOGE(TAG, "Too short input (%u characters required)\n", g_mesh_node.input_size);
610 return -1;
611 }
612
613 ret = bt_mesh_input_string(str);
614
615 if (ret) {
616 LOGE(TAG, "String input failed (err %d)\n", ret);
617 return -1;
618 }
619
620 g_mesh_node.input_act = BT_MESH_NO_INPUT;
621
622 return 0;
623 }
624
ble_mesh_node_OOB_input_num(uint32_t num)625 int ble_mesh_node_OOB_input_num(uint32_t num)
626 {
627 if (!g_mesh_node.init_flag) {
628 return -1;
629 }
630
631 int16_t ret;
632
633 if (g_mesh_node.input_act != BT_MESH_ENTER_STRING) {
634 LOGE(TAG, "A num hasn't been requested!\n");
635 return -1;
636 }
637
638 ret = bt_mesh_input_number(num);
639
640 if (ret) {
641 LOGE(TAG, "num input failed (err %d)\n", ret);
642 return -1;
643 }
644
645 g_mesh_node.input_act = BT_MESH_NO_INPUT;
646
647 return 0;
648 }
649
650 #endif
651
node_model_message_cb(mesh_model_event_en event,void * p_arg)652 static void node_model_message_cb(mesh_model_event_en event, void *p_arg)
653 {
654 int ret;
655
656 switch (event) {
657 #ifdef CONFIG_BT_MESH_PROVISIONER
658
659 case BT_MESH_MODEL_CFG_APPKEY_STATUS: {
660 if (p_arg) {
661 model_message message = *(model_message *)p_arg;
662 uint8_t status = message.status_data->data[0];
663
664 k_timer_stop(&g_mesh_node.add_appkey_timer);
665
666 if (status) {
667 if (g_mesh_node.app_key_add_retry) {
668 ret = ble_mesh_node_appkey_add(0, g_mesh_node.auto_add_appkey_idx, last_addr);
669
670 if (ret) {
671 LOGE(TAG, "add appkey faild");
672 } else {
673 g_mesh_node.app_key_add_retry--;
674 }
675
676 } else {
677 LOGE(TAG, "add appkey faild");
678 }
679 }
680 }
681 } break;
682 #else
683
684 case BT_MESH_MODEL_CFG_APP_KEY_ADD: {
685 #if defined(CONFIG_BT_MESH_MODEL_VENDOR_SRV)
686 if (p_arg) {
687 appkey_status *add_status = (appkey_status *)p_arg;
688
689 if (!add_status->status) {
690 if (g_mesh_node.app_key_add_flag) {
691 break;
692 }
693
694 g_mesh_node.app_key_add_flag = 1;
695 auto_config_t config = {
696 .appkey_idx = add_status->appkey_idx,
697 .sub_addr = COMMON_SUB_ADDR,
698 .pub_addr = COMMON_PUB_ADDR,
699 .mod_id = BT_MESH_MODEL_VND_MODEL_SRV,
700 .cid = BT_MESH_MODEL_VND_COMPANY_ID,
701 };
702
703 auto_config(&config);
704 }
705 }
706 #endif
707 } break;
708
709 case BT_MESH_MODEL_VENDOR_MESH_AUTOCONFIG: {
710 if (p_arg && BT_MESH_AUTO_CONFIG_START != g_mesh_node.auto_config_status) {
711 // uint8_t tid;
712 int16_t ret;
713 model_message *msg = (model_message *)p_arg;
714
715 if (!g_mesh_node.app_key_add_flag) {
716 g_mesh_node.auto_config_status = BT_MESH_AUTO_CONFIG_FAILD;
717
718 if (BT_MESH_ADDR_IS_UNICAST(msg->dst_addr)) {
719 ret = report_auto_config_status(msg->source_addr, g_mesh_node.auto_config_status);
720
721 if (ret) {
722 LOGE(TAG, "report auto config status faild");
723 }
724 }
725
726 return;
727 }
728
729 if (BT_MESH_ADDR_IS_UNICAST(msg->dst_addr)) {
730 g_mesh_node.auto_config_ack_flag = 1;
731 } else {
732 g_mesh_node.auto_config_ack_flag = 0;
733 }
734
735 if (BT_MESH_AUTO_CONFIG_SUCCEED == g_mesh_node.auto_config_status) {
736 if (g_mesh_node.auto_config_ack_flag) {
737 ret = report_auto_config_status(msg->source_addr, g_mesh_node.auto_config_status);
738
739 if (ret) {
740 LOGE(TAG, "report auto config status faild");
741 }
742
743 return;
744 } else {
745 return;
746 }
747 }
748
749 g_mesh_node.auto_config_status = BT_MESH_AUTO_CONFIG_START;
750
751 net_buf_simple_pull_u8(msg->ven_data.user_data);
752 auto_config_t config = { 0 };
753 config.appkey_idx = 0;
754 config.sub_addr = net_buf_simple_pull_le16(msg->ven_data.user_data);
755 config.pub_addr = 0; // net_buf_simple_pull_le16(msg->ven_data.user_data);
756 config.mod_id = 0xffff;
757 config.cid = 0xffff;
758 ret = auto_config(&config);
759
760 if (ret) {
761 g_mesh_node.auto_config_status = BT_MESH_AUTO_CONFIG_FAILD;
762 ret = aos_kv_setint("AUTO_CONFIG", BT_MESH_AUTO_CONFIG_FAILD);
763
764 if (ret) {
765 LOGE(TAG, "save auto config status faild");
766 }
767 }
768
769 if (!ret) {
770 g_mesh_node.prov_addr = msg->source_addr;
771 g_mesh_node.auto_config_retry = DEF_AUTOCONFIG_STORE_CHECK_RETRY;
772 g_mesh_node.auto_config_timeout = DEF_AUTOCONFIG_STORE_CHECK_TIMEOUT;
773 k_timer_start(&g_mesh_node.auto_config_timer, g_mesh_node.auto_config_timeout);
774 }
775 }
776
777 }
778
779 break;
780
781 case BT_MESH_MODEL_VENDOR_MESH_AUTOCONFIG_GET: {
782 if (p_arg) {
783 model_message *message = (model_message *)p_arg;
784
785 if (!bt_mesh_store_mod_pending_check()) {
786 ret = report_auto_config_status(message->source_addr, g_mesh_node.auto_config_status);
787
788 if (ret) {
789 LOGE(TAG, "report auto config status faild");
790 }
791 }
792 }
793 } break;
794 #endif
795 case BT_MESH_MODEL_CFG_RST_STATUS: {
796 ret = aos_kv_setint("AUTO_CONFIG", BT_MESH_AUTO_CONFIG_NOT_START);
797 if (ret) {
798 LOGE(TAG, "save auto config status faild");
799 }
800 } break;
801 default:
802 break;
803 }
804
805 if (g_mesh_node.user_model_cb) {
806 g_mesh_node.user_model_cb(event, p_arg);
807 }
808 }
809
node_attention_on(struct bt_mesh_model * model)810 void node_attention_on(struct bt_mesh_model *model)
811 {
812 if (g_mesh_node.health_cb.att_on) {
813 g_mesh_node.health_cb.att_on();
814 }
815 }
816
node_attention_off(struct bt_mesh_model * model)817 void node_attention_off(struct bt_mesh_model *model)
818 {
819 if (g_mesh_node.health_cb.att_off) {
820 g_mesh_node.health_cb.att_off();
821 }
822 }
823
824 struct bt_mesh_health_srv_cb g_health_cb = {
825 .attn_on = node_attention_on,
826 .attn_off = node_attention_off,
827 };
828
ble_mesh_node_init(node_config_t * param)829 int ble_mesh_node_init(node_config_t *param)
830 {
831 if (!param) {
832 return -1;
833 }
834
835 const struct bt_mesh_comp *mesh_comp = ble_mesh_model_get_comp_data();
836
837 if (!mesh_comp || (NODE != param->role && PROVISIONER != param->role)) {
838 return -1;
839 }
840
841 g_mesh_node.comp = mesh_comp;
842
843 if (param->node_oob.static_oob_data) {
844 memcpy(g_static_data, param->node_oob.static_oob_data, 16);
845 node_prov.static_val_len = 16;
846 }
847
848 if (ACTION_NUM == param->node_oob.input_action && param->node_oob.input_max_size > 0) {
849 node_prov.input_actions = BT_MESH_ENTER_NUMBER;
850 node_prov.input_size = param->node_oob.input_max_size;
851 } else if (ACTION_STR == param->node_oob.input_action && param->node_oob.input_max_size > 0) {
852 node_prov.input_actions = BT_MESH_ENTER_STRING;
853 node_prov.input_size = param->node_oob.input_max_size;
854 } else {
855 node_prov.input_actions = BT_MESH_NO_INPUT;
856 node_prov.input_size = 0;
857 }
858
859 if (ACTION_NUM == param->node_oob.output_action && param->node_oob.output_max_size > 0) {
860 node_prov.output_actions = BT_MESH_DISPLAY_NUMBER;
861 node_prov.output_size = param->node_oob.output_max_size;
862 } else if (ACTION_STR == param->node_oob.output_action && param->node_oob.output_max_size > 0) {
863 node_prov.output_actions = BT_MESH_DISPLAY_STRING;
864 node_prov.output_size = param->node_oob.output_max_size;
865 } else {
866 node_prov.output_actions = BT_MESH_NO_OUTPUT;
867 node_prov.output_size = 0;
868 }
869
870 if (PROVISIONER == param->role) {
871 #ifdef CONFIG_BT_MESH_PROVISIONER
872 int ret;
873 provisioner_cb app_cb;
874
875 if (!param->provisioner_config ||
876 mesh_comp->elem_count > (param->provisioner_config->config.unicast_addr_start -
877 param->provisioner_config->config.unicast_addr_local)) {
878 return -EINVAL;
879 }
880
881 app_cb = param->provisioner_config->config.cb;
882 param->provisioner_config->config.cb = provisioner_node_cb;
883 ret = ble_mesh_provisioner_init(¶m->provisioner_config->config);
884
885 if (ret) {
886 return ret;
887 }
888
889 uint16_t appkey_idx = 0;
890 const ble_mesh_provisioner_t *prov_comp = ble_mesh_provisioner_get_provisioner_data();
891
892 if (!prov_comp) {
893 return ret;
894 }
895
896 dev_addr_t dev_addr;
897 ret = ble_stack_get_local_addr(&dev_addr);
898
899 if (ret) {
900 return ret;
901 }
902
903 memcpy(dev_uuid, param->dev_uuid, 16);
904 memcpy(dev_uuid, dev_addr.val, 6);
905
906 ret = bt_mesh_init(&node_prov, mesh_comp, prov_comp->provisioner);
907
908 if (ret) {
909 return ret;
910 }
911
912 ret = ble_stack_setting_load();
913
914 if (ret) {
915 return ret;
916 }
917
918 ret = ble_mesh_provisioner_enable();
919
920 if (ret && (ret != -EALREADY)) {
921 return ret;
922 }
923
924 bt_mesh_provisioner_local_provision();
925
926 k_timer_init(&g_mesh_node.add_appkey_timer, add_appkey_timeout_cb, NULL);
927
928 g_mesh_node.user_provisioner_cb = app_cb;
929 //add appkey 0
930 ret = bt_mesh_provisioner_local_app_key_add(NULL, 0, &appkey_idx);
931
932 if (ret < 0 && -EEXIST != ret) {
933 return ret;
934 } else if (0 == ret || -EEXIST == ret) {
935 //bind all model to appkey0
936 extern u16_t bt_mesh_primary_addr(void);
937 bt_mesh_cfg_app_key_add(0, bt_mesh_primary_addr(), 0, appkey_idx,
938 bt_mesh_provisioner_local_app_key_get(0, appkey_idx), NULL);
939 auto_config_t config = {
940 .appkey_idx = appkey_idx,
941 .sub_addr = param->provisioner_config->local_sub,
942 .pub_addr = param->provisioner_config->local_pub,
943 .mod_id = 0xffff,
944 .cid = 0xffff,
945 };
946 auto_config(&config);
947 }
948
949 g_mesh_node.node_provisioned = 1;
950 #else
951 return -1;
952 #endif
953 } else {
954 #ifndef CONFIG_BT_MESH_PROVISIONER
955 int ret;
956
957 g_mesh_node.user_prov_cb = param->user_prov_cb;
958
959 ret = bt_mesh_init(&node_prov, mesh_comp, NULL);
960
961 if (ret) {
962 return ret;
963 }
964
965 ret = ble_stack_setting_load();
966
967 if (ret) {
968 return ret;
969 }
970
971 ret = ble_stack_set_name((char *)param->dev_name);
972
973 if (ret) {
974 return ret;
975 }
976
977 dev_addr_t dev_addr;
978 ret = ble_stack_get_local_addr(&dev_addr);
979
980 if (ret) {
981 return ret;
982 }
983
984 memcpy(dev_uuid, param->dev_uuid, 16);
985 memcpy(dev_uuid, dev_addr.val, 6);
986
987 /* This will be a no-op if settings_load() loaded provisioning info */
988 bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
989
990 k_timer_init(&g_mesh_node.auto_config_timer, auto_config_timeout_cb, NULL);
991 g_mesh_node.node_provisioned = bt_mesh_is_provisioned();
992
993 if (g_mesh_node.node_provisioned) {
994 int auto_config_status = 0;
995 ret = aos_kv_getint("AUTO_CONFIG", &auto_config_status);
996 if (ret) {
997 g_mesh_node.auto_config_status = BT_MESH_AUTO_CONFIG_NOT_START;
998 } else {
999 g_mesh_node.auto_config_status = auto_config_status;
1000 }
1001 } else {
1002 g_mesh_node.node_provisioned = BT_MESH_AUTO_CONFIG_NOT_START;
1003 }
1004
1005 extern struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx);
1006
1007 if (!bt_mesh_app_key_find(0)) {
1008 g_mesh_node.app_key_add_flag = 0;
1009 } else {
1010 g_mesh_node.app_key_add_flag = 1;
1011 }
1012
1013 #ifdef BT_MESH_BEACON_RSSI_REPORT
1014 g_mesh_node.rssi_report_enable = param->rssi_report_enable;
1015
1016 if (g_mesh_node.node_provisioned && g_mesh_node.rssi_report_enable) {
1017 init_rssi_report();
1018 }
1019
1020 #endif
1021 #else
1022 return -1;
1023 #endif
1024 }
1025
1026 ble_mesh_model_set_cb(node_model_message_cb);
1027
1028 extern int mesh_event_port_init();
1029 mesh_event_port_init();
1030
1031 if (param->health_cb && (param->health_cb->att_on || param->health_cb->att_off)) {
1032 extern int health_srv_cb_register(struct bt_mesh_health_srv_cb * health_cb);
1033
1034 if (health_srv_cb_register(&g_health_cb)) {
1035 LOGE(TAG, "register health srv cb faild");
1036 }
1037
1038 g_mesh_node.health_cb.att_on = param->health_cb->att_on;
1039 g_mesh_node.health_cb.att_off = param->health_cb->att_off;
1040 }
1041
1042 g_mesh_node.user_model_cb = param->user_model_cb;
1043 g_mesh_node.init_flag = 1;
1044
1045 return g_mesh_node.node_provisioned;
1046 }
1047