LV04-天猫蓝牙Mesh项目-02-进阶开发-09-实现配网器代码

本文主要是天猫蓝牙Mesh项目——进阶开发 实现配网器代码 的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows版本 windows11
Ubuntu版本 Ubuntu22.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
点击查看本文参考资料
分类 网址 说明
官方网站 阿里云 阿里云官网主页
阿里生活物联平台 生活物联网平台(飞燕平台)主页
AliGenie 天猫精灵开放平台AliGenie主页
阿里物联网平台 阿里物联网平台主页
Bluetooth 技术网站 蓝牙协议规范什么的可以来这里找
Telink Telink | Chips for a Smarter IoT (telink-semi.com)
Telink中文官网
开发手册 AliOS Things开发指南 AliOS Things开发指南,这里是最新版本,可以直接从官网找到
AliOS Things开发指南 AliOS Things应用开发指南,这里应该是3.3版本的完整开发文档
AliOS Things开发指南(3.0) AliOS Things应用开发指南,这里应该是3.0版本的完整开发文档
生活物联网平台开发文档 生活物联网平台(飞燕平台)开发文档
《设备端开发指南》
Wi-Fi IoT品类定义与功能开发 天猫精灵IoT开放平台——Wi-Fi IoT品类定义与功能开发
硬件平台 mk3080 WiFi开发板 WiFi开发板使用指南-阿里云开发者社区
esp8266开发板 一个教程:ESP8266-NodeMCU开发板详解-太极创客 (taichi-maker.com)
TLSR8258 Datasheet Datasheet for Telink BLE + IEEE802.15.4 MultiStandard Wireless SoC TLSR8258
参考资料 AliOS Things 3.0 应用开发指南 这个只是一篇参考文章,里面是一些环境搭建相关的,可以参考
IP知识百科 - 华为 (huawei.com) IP的一些相关知识点
点击查看相关文件下载
分类 网址 说明
蓝牙规范相关文档 Core Specification 5.2 核心规格 5.2,该规范定义了创建可互操作的Bluetooth 设备所需的技术。
《Core_v5.2.pdf》
Mesh Model(v1.1) 本Bluetooth 规范定义了模型(以及它们所需的状态和消息),这些模型用于在mesh 网络中的节点上执行基本功能,超出了Bluetooth Mesh 配置文件 规范中定义的基础模型。
本规范包括定义跨设备类型标准功能的通用模型,以及支持关键mesh 场景的模型,如照明控制、传感器、时间和场景。
《MshMDL_v1.1.pdf》
Mesh Profile(v1.0.1) 该Bluetooth 规范定义了基本要求,以实现可互操作的mesh 网络解决方案,用于Bluetooth 低能量无线技术。
《MshPRFv1.0.1.pdf》
Mesh Device Properties 本规范包含Bluetooth Mesh 配置文件 和Bluetooth Mesh 模型规范所要求的设备属性的定义。
但是跟之前的有些区别,我主要看的之前的版本:《MMeshDeviceProperties_v1.2.pdf》
GATT Specification Supplement GATT Specification Supplement | Bluetooth® Technology Website。
好像可以在线看:《GATT Specification Supplement》
Assigned Numbers GATT的一些类型定义可以在这里找。
AliOS Things alios-things/AliOS-Things Gitee上的AliOSThings SDK源码仓库
alibaba/AliOS-Things GitHub上的AliOSThings SDK源码仓库
天猫精灵蓝牙Mesh协议栈 alibaba-archive/genie-bt-mesh-stack GitHub上的天猫精灵蓝牙Mesh协议栈源码仓库。
之前是在alibaba/genie-bt-mesh-stack这个仓库。
写笔记的时候最新提交为faf523618a6a2560090fc423222b9db80984bb7a
蓝牙Mesh设备开发指南 阿里云生活服务平台开发手册——蓝牙设备开发一节中的内容

这一LV的笔记起始跟前面有所重叠,互相补充吧算是。前面我们知道天猫精灵智能音箱可以对泰凌微8258蓝牙模块进行配网,它使用的是静态OOB的方式,上一节,我们通过手机,使用nRF Mesh软件,让手机作为配网器,以无OOB的方式完成对模块的配网。这一节,我们在一个蓝牙模块上实现配网器功能,用它来给另一个蓝牙模块配网。为什么要实现配网器的代码?因为我们前面下载的阿里提供的协议栈实现的是未配网设备的功能,配网器的功能是天猫精灵智能音箱的。

一、网络层数据结构与算法

需要知道的是,arm架构的处理器中的数据是以小端模式进行存储,而网络传输的数据是以大端模式存储的,需要注意。

Tips:大端模式与小端模式:

小端模式:数据的低位放在低地址空间,数据的高位放在高地址空间。

大端模式:数据的高位放在低地址空间,数据的低位放在高地址空间

1. 先看一个函数

我们先看一个函数,就是邀请配网的这个函数:network/bluetooth/bt_mesh/src/prov.c:prov_invite()

image-20240106074405981

这里有一个我们需要了解的结构体,就是net_buf_simple。

2. 数据结构 net_buf_simple

2.1 定义是怎样的?

这个结构体定义在network/bluetooth/bt_common/include/net/buf.h中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/** @brief Simple network buffer representation.
*
* This is a simpler variant of the net_buf object (in fact net_buf uses
* net_buf_simple internally). It doesn't provide any kind of reference
* counting, user data, dynamic allocation, or in general the ability to
* pass through kernel objects such as FIFOs.
*
* The main use of this is for scenarios where the meta-data of the normal
* net_buf isn't needed and causes too much overhead. This could be e.g.
* when the buffer only needs to be allocated on the stack or when the
* access to and lifetime of the buffer is well controlled and constrained.
*
*/
struct net_buf_simple {
/** Pointer to the start of data in the buffer. */
u8_t *data;

/** Length of the data behind the data pointer. */
u16_t len;

/** Amount of data that this buffer can store. */
u16_t size;

/** Start of the data storage. Not to be accessed directly
* (the data pointer should be used instead).
*/
u8_t __buf[0] __net_buf_align;
}

各个成员的含义如下:

image-20240106121737109

2.2 net_buf_simple应用解析

这里就很有意思了,触及我的知识盲区,居然有一个0长度的数组,感觉看的不是很明白,我们下面放在代码中理解一下,首先是这里,定义了一个指针buf:

1
2
3
4
5
static void prov_invite(const u8_t *data)
{
struct net_buf_simple *buf = PROV_BUF(12);
//...
}

我们看一下这个PROV_BUF是什么:

1
2
3
4
5
6
7
8
#if defined(CONFIG_BT_MESH_PB_GATT)
#define PROV_BUF_HEADROOM 5
#else
#define PROV_BUF_HEADROOM 0
static struct net_buf_simple *rx_buf = NET_BUF_SIMPLE(65);
#endif

#define PROV_BUF(len) NET_BUF_SIMPLE(PROV_BUF_HEADROOM + len)

这里我们按没有定义CONFIG_BT_MESH_PB_GATT来算,也就是PROV_BUF_HEADROOM=0,这样我们将PROV_BUF展开可以看到:

1
#define PROV_BUF(12) NET_BUF_SIMPLE(12)

这个NET_BUF_SIMPLE是什么?我们继续往下追:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/** @def NET_BUF_SIMPLE
* @brief Define a net_buf_simple stack variable and get a pointer to it.
*
* This is a helper macro which is used to define a net_buf_simple object on
* the stack and the get a pointer to it as follows:
*
* struct net_buf_simple *my_buf = NET_BUF_SIMPLE(10);
*
* After creating the object it needs to be initialized by calling
* net_buf_simple_init().
*
* @param _size Maximum data storage for the buffer.
*
* @return Pointer to stack-allocated net_buf_simple object.
*/
#define NET_BUF_SIMPLE(_size) \
((struct net_buf_simple *)(&(struct { \
struct net_buf_simple buf; \
u8_t data[_size] __net_buf_align; \
}) { \
.buf.size = _size, \
}))

看起来好像还挺复杂的,我们先把参数传进去然后写成种基本可以辨别的样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
#define NET_BUF_SIMPLE(12)                        \
(
(struct net_buf_simple *)
(
&(struct {
struct net_buf_simple buf;
u8_t data[12] __net_buf_align;
})
{
.buf.size = 12, // 这里就很神奇,在定义这个结构体成员的时候直接把 buf 成员里面的 size成员直接初始化了,我还是第一次见这种方式。
}
)
)

惊呆了啊,这里居然直接把定义的结构体给初始化了,然后还把地址返回了,就像是定义了一个变量,然后将变量地址返回。后来查了一下,发现这里就是C语言中0长度数组的应用,也就是“可变数组”,我们总结一下:

image-20240106121134403

其实struct定义结构体的时候可以直接定义变量,甚至可以没有变量名,我们要知道变量名的意义其实就是帮助我们找到数据在内存中的位置,我们完全可以直接用指针指向这片内存而不需要变量名的。可以写一个实例看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>

#define __net_buf_align __attribute__ ((__aligned__(sizeof(int))))

struct net_buf_simple {
/** Pointer to the start of data in the buffer. */
unsigned char *data;
/** Length of the data behind the data pointer. */
unsigned short len;
/** Amount of data that this buffer can store. */
unsigned short size;

/** Start of the data storage. Not to be accessed directly
* (the data pointer should be used instead).
*/
unsigned char __buf[0];
};


#define NET_BUF_SIMPLE(_size) \
((struct net_buf_simple *)(&(struct { \
struct net_buf_simple buf; \
unsigned short data[_size] __net_buf_align; \
}) { \
.buf.size = _size, \
}))


int main(const int argc, const char *argv[])
{
printf("array test!\n");

struct net_buf_simple *buf = NET_BUF_SIMPLE(12);
int *p = NULL;

buf->data = buf->__buf;
buf->len = 0;

printf("buf = %p, sizeof(net_buf_simple)=%ld\n", buf, sizeof(struct net_buf_simple));
printf("buf->data = %p\n", buf->data);
printf("buf->__buf = %p\n", buf->__buf);
printf("buf->len = %d\n", buf->len);
printf("buf->size = %d\n", buf->size);

p = (int *)(&(struct {
int a;
}){.a = 10,});
printf("a = %d\n", *p);
return 0;
}

3. buf.h 分析

文件路径:genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/util/buf.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//四字节对齐宏
#define __net_buf_align __aligned(sizeof(int))

struct net_buf_simple {

u8_t *data; /** 指向缓冲区中数据开头的指针 */
u16_t len; /** 数据指针后面的剩余数据长度 */
u16_t size; /** 此缓冲区可以存储的数据量 */
u8_t __buf[0] __net_buf_align; /** 数据存储的起始地址。不直接访问(应使用数据指针)*/
};

#define NET_BUF_SIMPLE(_size) \
((struct net_buf_simple *)(&(struct { \
struct net_buf_simple buf; \ //
u8_t data[_size] __net_buf_align; \ //实例化的数据存储数组
}) { \
.buf.size = _size, \
}))

//初始化缓存区
static inline void net_buf_simple_init(struct net_buf_simple *buf,
size_t reserve_head)
{
buf->data = buf->__buf + reserve_head;
buf->len = 0;
}

//计算头部空间有多少
size_t net_buf_simple_headroom(struct net_buf_simple *buf)
{
return buf->data - buf->__buf;
}
//计算尾部空间有多少
size_t net_buf_simple_tailroom(struct net_buf_simple *buf)
{
return buf->size - net_buf_simple_headroom(buf) - buf->len;
}
//尾部追加(只增加剩余长度,实际未添加数据)
void *net_buf_simple_add(struct net_buf_simple *buf, size_t len)
{
//找到尾部指针
u8_t *tail = net_buf_simple_tail(buf);

NET_BUF_SIMPLE_DBG("buf %p len %zu", buf, len);
//判断是否越界
NET_BUF_SIMPLE_ASSERT(net_buf_simple_tailroom(buf) >= len);
//增加剩余长度
buf->len += len;
return tail;
}
//尾部添加小端32位数据
void net_buf_simple_add_le32(struct net_buf_simple *buf, u32_t val)
{
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
//大小端转换,cpu本身就是小端模式,所以这步什么都不做。
val = sys_cpu_to_le32(val);
//从尾指针拷贝要放入的数据(net_buf_simple_add 事先已经把剩余长度给改变了)
memcpy(net_buf_simple_add(buf, sizeof(val)), &val, sizeof(val));
}
//尾部添加大端32位数据
void net_buf_simple_add_be32(struct net_buf_simple *buf, u32_t val)
{
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
//大小端转换,cpu本身就是小端模式,所以这步要把4个字节颠倒存储。
val = sys_cpu_to_be32(val);
//从尾指针拷贝要放入的数据(net_buf_simple_add 事先已经把剩余长度给改变了)
memcpy(net_buf_simple_add(buf, sizeof(val)), &val, sizeof(val));
}
//头部追加(只增加剩余长度和修改了指针指向,实际未添加数据)
void *net_buf_simple_push(struct net_buf_simple *buf, size_t len)
{
NET_BUF_SIMPLE_DBG("buf %p len %zu", buf, len);

NET_BUF_SIMPLE_ASSERT(net_buf_simple_headroom(buf) >= len);

buf->data -= len; //当前指针指向向前偏移
buf->len += len; //增加剩余数据长度
return buf->data; //返回当前指针指向地址
}
//头部添加小端16位数据
void net_buf_simple_push_le16(struct net_buf_simple *buf, u16_t val)
{
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);

val = sys_cpu_to_le16(val);
memcpy(net_buf_simple_push(buf, sizeof(val)), &val, sizeof(val));
}
//头部添加大端16位数据
void net_buf_simple_push_be16(struct net_buf_simple *buf, u16_t val)
{
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);

val = sys_cpu_to_be16(val);
memcpy(net_buf_simple_push(buf, sizeof(val)), &val, sizeof(val));
}


//缓存区头部偏移操作
void *net_buf_simple_pull(struct net_buf_simple *buf, size_t len)
{
NET_BUF_SIMPLE_DBG("buf %p len %zu", buf, len);

NET_BUF_SIMPLE_ASSERT(buf->len >= len);

buf->len -= len; //减少剩余数据长度
return buf->data += len; //当前指针指向向后偏移
}
//头部读取小端16位数据
u16_t net_buf_simple_pull_le16(struct net_buf_simple *buf)
{
u16_t val;
//读取16位数据
val = UNALIGNED_GET((u16_t *)buf->data);
//缓存区头部指针偏移16位
net_buf_simple_pull(buf, sizeof(val));
//根据系统大小端转换
return sys_le16_to_cpu(val);
}
//头部读取大端16位数据
u16_t net_buf_simple_pull_be16(struct net_buf_simple *buf)
{
u16_t val;
//读取16位数据
val = UNALIGNED_GET((u16_t *)buf->data);
//缓存区头部指针偏移16位
net_buf_simple_pull(buf, sizeof(val));
//根据系统大小端转换
return sys_be16_to_cpu(val);
}

二、配网器功能分析

我们先来分析一下配网器需要实现哪些功能,我们下载的阿里提供的天猫精灵开发SDK使用的蓝牙Mesh协议栈是没有给我们写配网器的相关实现的,我们需要添加代码自己实现配网器功能,那配网器都需要实现哪些功能?我们简单分析一下:

image-20240107095929928

我们前面用手机给设备配网的时候看到,配网器需要自己生成一些密钥,例如网络密钥,app密钥等。我们还需要为每个元素分配地址,一般来说0x0001分配给配网器,后面累加的地址分配给元素。我们配网完成,连接好之后,需要存储一些节点的信息,例如节点的MAC地址,MAC地址通常会以UUID的格式存储在配网器中,这样若是某个设备断网,重新连接过来的时候,我们的配网器可以把之前分配给它的地址重新分配给它。具体的可以看后面的代码实现。

大概要有两个阶段:

  • 配网阶段:为设备分配单播地址、添加网络密钥(NetKey)等。通过配网,设备加入 BLE-MESH 网络,身份从未配网设备变为节点。

  • 配置阶段:为节点添加应用密钥(AppKey),并将应用密钥绑定到相应模型。配置期间,有些选项是可选的,比如为节点添加订阅地址、设置发布地址等。通过配置,该节点实际上可以向Provisioner 发送消息,也可以接收来自Provisioner的消息。

三、配网器实现

完整的修改可以看这里:feat:bt_provisioner工程实现配网器(支持配网器和节点的编译) · sumumm/my-genie-bt-mesh-stack@9e0c6e7 (github.com)

1. 工程修改

1.1 helloworld.mk

①、以helloworld工程为示例,修改helloworld.mk

点击查看详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
NAME := helloworld

$(NAME)_COMPONENTS += genie_app bluetooth.bt_host bluetooth.bt_mesh yloop cli

$(NAME)_INCLUDES += ../../../../genie_app \
../../../../genie_app/base \
../../../../genie_app/bluetooth/host \
../../../../genie_app/bluetooth/mesh

$(NAME)_SOURCES := helloworld.c

ifeq ($(HOST_MCU_FAMILY),ch6121)
bt_host_tinycrypt = 0
else ifeq ($(HOST_MCU_FAMILY),tg7100b)
bt_host_tinycrypt = 0
else
ble = 1
bt_mesh = 1
endif
en_bt_smp = 1

# Host configurations
GLOBAL_DEFINES += CONFIG_BLUETOOTH
ifeq ($(HOST_MCU_FAMILY),ch6121)
GLOBAL_DEFINES += CONFIG_BT_RX_BUF_LEN=252
GLOBAL_DEFINES += CONFIG_BT_L2CAP_TX_MTU=244
GLOBAL_DEFINES += CONFIG_BT_MESH_ADV_BLOCK
else ifeq ($(HOST_MCU_FAMILY),tg7100b)
GLOBAL_DEFINES += CONFIG_BT_RX_BUF_LEN=252
GLOBAL_DEFINES += CONFIG_BT_L2CAP_TX_MTU=244
GLOBAL_DEFINES += CONFIG_BT_MESH_ADV_BLOCK
else
GLOBAL_DEFINES += CONFIG_BT_SMP
GLOBAL_DEFINES += CONFIG_BT_HCI_VS_EXT
GLOBAL_DEFINES += CONFIG_BT_TINYCRYPT_ECC
endif
GLOBAL_DEFINES += CONFIG_BT_CONN
#GLOBAL_DEFINES += CONFIG_BT_CENTRAL
GLOBAL_DEFINES += CONFIG_BT_PERIPHERAL
#GLOBAL_DEFINES += CONFIG_BLE_50


# Mesh function select
GLOBAL_DEFINES += CONFIG_BT_MESH
GLOBAL_DEFINES += CONFIG_BT_MESH_PROV
GLOBAL_DEFINES += CONFIG_BT_MESH_PB_ADV
#关闭GATT代理(为了实现简单配网,减少开发难度)
#GLOBAL_DEFINES += CONFIG_BT_MESH_PB_GATT
GLOBAL_DEFINES += CONFIG_BT_MESH_PROXY
GLOBAL_DEFINES += CONFIG_BT_MESH_GATT_PROXY
GLOBAL_DEFINES += CONFIG_BT_MESH_RELAY
#GLOBAL_DEFINES += CONFIG_BT_MESH_FRIEND
#GLOBAL_DEFINES += CONFIG_BT_MESH_LOW_POWER
#GLOBAL_DEFINES += CONFIG_BT_MESH_SHELL
#GLOBAL_DEFINES += CONFIG_BT_MESH_BQB
#GLOBAL_DEFINES += CONFIG_BT_MESH_IV_UPDATE_TEST

# Mesh foundation model select
GLOBAL_DEFINES += CONFIG_BT_MESH_CFG_SRV
GLOBAL_DEFINES += CONFIG_BT_MESH_HEALTH_SRV

# Mesh debug message enable
#GLOBAL_DEFINES += USE_BT_MESH_CUSTOM_LOG
GLOBAL_DEFINES += GENIE_DEBUG_COLOR
GLOBAL_DEFINES += MESH_DEBUG_RX
GLOBAL_DEFINES += MESH_DEBUG_TX
GLOBAL_DEFINES += MESH_DEBUG_PROV

#GLOBAL_DEFINES += CONFIG_INIT_STACKS
#GLOBAL_DEFINES += CONFIG_PRINTK

GLOBAL_INCLUDES += ../

GLOBAL_DEFINES += PROJECT_SW_VERSION=0x00010000
GLOBAL_DEFINES += PROJECT_SECRET_KEY=\"00112233445566770011223344556677\"

MESH_MODEL_GEN_ONOFF_SRV = 1
MESH_MODEL_DIABLE_TRANS = 1
#MESH_MODEL_LIGHTNESS_SRV = 1
#MESH_MODEL_CTL_SRV = 1
#MESH_MODEL_VENDOR_SRV = 1

ALI_SIMPLE_MODLE = 1

GLOBAL_DEFINES += GENIE_OLD_AUTH
#定义一个配网器角色的宏,以便和未配网节点代码分开
GLOBAL_DEFINES += CONFIG_BT_MESH_ROLE_PROVISIONER
#开启DEBUG打印宏,方便调试
GLOBAL_DEFINES += CONFIG_BT_DEBUG_LOG

1.2 bt_mesh.mk

②、修改 genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/bt_mesh.mk

将:./src/prov.c \替换成./src/provisioner_prov.c \

点击查看详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
NAME := bt_mesh

$(NAME)_MBINS_TYPE := kernel
$(NAME)_VERSION := 1.0.0
$(NAME)_SUMMARY := BLE Mesh stack.

ifeq ($(bt_mesh_standalone_deploy),1)
GLOBAL_DEFINES += CONFIG_MESH_STACK_ALONE
$(NAME)_COMPONENTS += bluetooth.bt_mesh.util
else
$(NAME)_COMPONENTS += bluetooth.bt_common
endif

$(NAME)_COMPONENTS += bluetooth.bt_mesh.ref_impl

$(NAME)_INCLUDES += ./inc/ \
./inc/api/ \
./inc/api/mesh/ \
../../../genie_app/ \
../../../genie_app/base \
../../../genie_app/bluetooth/host \
../../../genie_app/bluetooth/mesh


$(NAME)_SOURCES := ./src/access.c \
./src/adv.c \
./src/beacon.c \
./src/crypto.c \
./src/cfg_srv.c \
./src/cfg_cli.c \
./src/health_srv.c \
./src/health_cli.c \
./src/main.c \
./src/net.c \
./src/provisioner_prov.c \
./src/proxy.c \
./src/transport.c \
./src/friend.c \
./src/lpn.c \
./src/shell.c


GLOBAL_INCLUDES += ./inc/ \
./inc/api


GLOBAL_DEFINES += CRC16_ENABLED

2. 初始化修改部分文件

这部分修改的都是协议栈的源码,需要注意用宏控制好。

2.1 net.h

①、文件路径:genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/inc/net.h

添加配网器代码:定义宏 CONFIG_BT_MESH_ROLE_PROVISIONER

点击查看详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//新增定义
#define CONFIG_BLE_MESH_PROVISIONER_APP_KEY_COUNT 3
#define CONFIG_BLE_MESH_PROVISIONER_SUBNET_COUNT 3

struct bt_mesh_net {
u32_t iv_index; /* Current IV Index */
u32_t seq:24, /* Next outgoing sequence number */
iv_update:1, /* 1 if IV Update in Progress */
ivu_initiator:1, /* IV Update initiated by us */
ivu_test:1, /* IV Update test mode */
pending_update:1, /* Update blocked by SDU in progress */
valid:1; /* 0 if unused */

s64_t last_update; /* Time since last IV Update change */

/* Local network interface */
struct k_work local_work;
sys_slist_t local_queue;

#if defined(CONFIG_BT_MESH_FRIEND)
/* Friend state, unique for each LPN that we're Friends for */
struct bt_mesh_friend frnd[CONFIG_BT_MESH_FRIEND_LPN_COUNT];
#endif

#if defined(CONFIG_BT_MESH_LOW_POWER)
struct bt_mesh_lpn lpn; /* Low Power Node state */
#endif

/* Timer to transition IV Update in Progress state */
struct k_delayed_work ivu_complete;

u8_t dev_key[16];

struct bt_mesh_app_key app_keys[CONFIG_BT_MESH_APP_KEY_COUNT];

struct bt_mesh_subnet sub[CONFIG_BT_MESH_SUBNET_COUNT];

struct bt_mesh_rpl rpl[CONFIG_BT_MESH_CRPL];

#if CONFIG_BT_MESH_ROLE_PROVISIONER
/* Application keys stored by provisioner */
struct bt_mesh_app_key *p_app_keys[CONFIG_BLE_MESH_PROVISIONER_APP_KEY_COUNT];
/* Next app_idx can be assigned */
uint16_t p_app_idx_next;

/* Network keys stored by provisioner */
struct bt_mesh_subnet *p_sub[CONFIG_BLE_MESH_PROVISIONER_SUBNET_COUNT];
/* Next net_idx can be assigned */
uint16_t p_net_idx_next;
#endif


};

2.2 main.h

②、文件路径:genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/inc/api/mesh/main.h

点击查看详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
struct bt_mesh_prov {

#ifdef CONFIG_BT_MESH_ROLE_NODE
const u8_t *uuid;
const char *uri;
bt_mesh_prov_oob_info_t oob_info;
u8_t public_key_type;
u8_t * static_val;
u8_t static_val_len;

u8_t output_size;
u16_t output_actions;

u8_t input_size;
u16_t input_actions;


int (*output_number)(bt_mesh_output_action_t act, u32_t num);
int (*output_string)(const char *str);
int (*input)(bt_mesh_input_action_t act, u8_t size);
void (*link_open)(bt_mesh_prov_bearer_t bearer);
void (*link_close)(bt_mesh_prov_bearer_t bearer);
void (*complete)(u16_t net_idx, u16_t addr);
void (*reset)(void);

#endif /* CONFIG_BLE_MESH_NODE */

#ifdef CONFIG_BT_MESH_ROLE_PROVISIONER

const uint8_t *uuid;
const char *uri;

bt_mesh_prov_oob_info_t oob_info;
u8_t public_key_type;

u8_t * static_val;
u8_t static_val_len;
u8_t output_size;
u16_t output_actions;
u8_t input_size;
u16_t input_actions;

uint16_t prov_unicast_addr;
uint16_t prov_start_address;
uint8_t prov_attention;
uint8_t prov_algorithm;

uint8_t prov_pub_key_oob;
uint8_t flags;
uint32_t iv_index;

int (*prov_pub_key_oob_cb)(void);
int (*prov_input_num)(uint8_t method, bt_mesh_output_action_t act, uint8_t size, uint8_t link_idx);
int (*prov_output_num)(uint8_t method, bt_mesh_input_action_t act, void *data, uint8_t size, uint8_t link_idx);

void (*link_open)(bt_mesh_prov_bearer_t bearer);
void (*link_close)(bt_mesh_prov_bearer_t bearer);
void (*complete)(uint16_t node_idx,uint16_t unicast_addr);
void (*reset)(void);
#endif /* CONFIG_BT_MESH_ROLE_PROVISIONER */

};

2.3 crypto.c

③、文件路径:genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/src/crypto.c

点击查看详情
1
2
3
4
5
6
7
8
//新添加
#ifdef CONFIG_BT_MESH_ROLE_PROVISIONER
int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
const uint8_t data[25], uint8_t out[33])
{
return bt_mesh_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
}
#endif

文件路径:genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/inc/mesh_crypto.h

点击查看详情
1
2
3
//新增
int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
const uint8_t data[25], uint8_t out[33]);

2.4 adv.c

④、文件路径:genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/src/adv.c

点击查看详情

在 bt_mesh_scan_cb() 函数里修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    if (adv_type == BT_LE_ADV_NONCONN_IND) {
switch (type) {
case BT_MESH_DATA_MESH_MESSAGE:
bt_mesh_net_recv(buf, rssi, BT_MESH_NET_IF_ADV);
break;
#if defined(CONFIG_BT_MESH_PB_ADV)
case BT_MESH_DATA_MESH_PROV:
//配网器接收
#ifdef CONFIG_BT_MESH_ROLE_PROVISIONER

bt_mesh_prov_adv_recv(buf);

#endif
//节点接收
#ifdef CONFIG_BT_MESH_ROLE_NODE
bt_mesh_pb_adv_recv(buf);

#endif

2.5 beacon.c

⑤、文件路径:genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/src/beacon.c

点击查看详情

在 bt_mesh_beacon_recv() 函数里修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//添加
#ifdef CONFIG_BT_MESH_ROLE_PROVISIONER
#include "provisioner_prov.h"
#endif


void bt_mesh_beacon_recv(struct net_buf_simple *buf)
{
u8_t type;
//BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len));

if (buf->len < 1) {
BT_ERR("Too short beacon");
return;
}

type = net_buf_simple_pull_u8(buf);
switch (type) {
case BEACON_TYPE_UNPROVISIONED:
BT_DBG("Ignoring unprovisioned device beacon");
#ifdef CONFIG_BT_MESH_ROLE_PROVISIONER
extern void provisioner_link_open(const uint8_t * uuid);
//发起配网
if(is_provisioning() == 0)
{
provisioner_link_open(buf->data);
}
#endif
break;
case BEACON_TYPE_SECURE:
secure_beacon_recv(buf);
break;
default:
BT_WARN("Unknown beacon type 0x%02x", type);
break;
}
}


#ifdef CONFIG_BT_MESH_ROLE_NODE //配网器不需要这个函数
static int unprovisioned_beacon_send(void)
{
#if defined(CONFIG_BT_MESH_PB_ADV)
const struct bt_mesh_prov *prov;
struct net_buf *buf;
u8_t uri_hash[16] = { 0 };
u16_t oob_info;

BT_DBG("");

buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, UNPROV_XMIT_COUNT,
UNPROV_XMIT_INT, K_NO_WAIT);
if (!buf) {
BT_ERR("Unable to allocate beacon buffer");
return -ENOBUFS;
}

prov = bt_mesh_prov_get();

net_buf_add_u8(buf, BEACON_TYPE_UNPROVISIONED);
net_buf_add_mem(buf, prov->uuid, 16);

/* for tmall ble profile, OOB info default is 0x0000
URI hash is optional */
if (prov->uri && bt_mesh_s1(prov->uri, uri_hash) == 0) {
oob_info = prov->oob_info | BT_MESH_PROV_OOB_URI;
} else {
oob_info = prov->oob_info;
}

net_buf_add_be16(buf, oob_info);
net_buf_add_mem(buf, uri_hash, 4);

bt_mesh_adv_send(buf, NULL, NULL);
net_buf_unref(buf);

if (prov->uri) {
size_t len;

buf = bt_mesh_adv_create(BT_MESH_ADV_URI, UNPROV_XMIT_COUNT,
UNPROV_XMIT_INT, K_NO_WAIT);
if (!buf) {
BT_ERR("Unable to allocate URI buffer");
return -ENOBUFS;
}

len = strlen(prov->uri);
if (net_buf_tailroom(buf) < len) {
BT_WARN("Too long URI to fit advertising data");
} else {
net_buf_add_mem(buf, prov->uri, len);
bt_mesh_adv_send(buf, NULL, NULL);
}

net_buf_unref(buf);
}

#endif /* CONFIG_BT_MESH_PB_ADV */
return 0;
}
#endif


static void beacon_send(struct k_work *work)
{
/* Don't send anything if we have an active provisioning link */
if (IS_ENABLED(CONFIG_BT_MESH_PROV) && bt_prov_active()) {
k_delayed_work_submit(&beacon_timer, unprov_beacon_interval_get());
return;
}

//BT_DBG("");

if (bt_mesh_is_provisioned()) {
update_beacon_observation();
secure_beacon_send();

/* Only resubmit if beaconing is still enabled */
if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED ||
bt_mesh.ivu_initiator) {
k_delayed_work_submit(&beacon_timer,
PROVISIONED_INTERVAL);
}
} else {
#ifdef CONFIG_BT_MESH_ROLE_NODE
unprovisioned_beacon_send(); //屏蔽
#endif
k_delayed_work_submit(&beacon_timer, unprov_beacon_interval_get());
}

}

2.6 main.c

⑥、文件路径:genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/src/main.c

点击查看详情

添加头文件:

1
2
3
#ifdef CONFIG_BT_MESH_ROLE_PROVISIONER
#include "provisioner_prov.h"
#endif

在 bt_mesh_init()函数里添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
int bt_mesh_init(const struct bt_mesh_prov *prov,
const struct bt_mesh_comp *comp)
{
int err;

#ifdef CONFIG_MESH_STACK_ALONE
bt_mesh_prepare();
#endif

err = bt_mesh_test();
if (err) {
return err;
}
//注册成分数据
err = bt_mesh_comp_register(comp);
if (err) {
return err;
}
//初始化配网信息
if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
#ifdef CONFIG_BT_MESH_ROLE_NODE
err = bt_mesh_prov_init(prov); //节点设备初始化
if (err) {
return err;
}
#endif
}

//网络层初始化
bt_mesh_net_init();
//传输层初始化
bt_mesh_trans_init();
//承载层初始化
bt_mesh_beacon_init();
//广播初始化
bt_mesh_adv_init();

//加些延时,需要给获得密钥一些时间
aos_msleep(3000);
if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {

#ifdef CONFIG_BT_MESH_ROLE_PROVISIONER
err = bt_mesh_provisioner_prov_init(prov); //配网器初始化

if (err) {
return err;
}
#endif
}

if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
bt_mesh_proxy_init();
}

return 0;
}

在 bt_mesh_provision() 函数里添加宏:

1
2
3
4
5
    if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
#ifdef CONFIG_BT_MESH_ROLE_NODE //添加宏
bt_mesh_prov_complete(net_idx, addr); //配网器不运行下边函数
#endif
}

2.7 genie_mesh.c

⑦、文件路径:genie-bt-mesh-stack-master/genie_app/bluetooth/mesh/genie_mesh.c

点击查看详情

在 genie_mesh_init() 函数里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void genie_mesh_init(void)
{
int ret;

BT_INFO(">>>init genie<<<");
//加载三元组
genie_tri_tuple_load();

//发送配网广播的数据
prov.uuid = genie_tri_tuple_get_uuid();
#ifdef GENIE_OLD_AUTH
prov.static_val = genie_tri_tuple_get_auth();
prov.static_val_len = STATIC_OOB_LENGTH;
#endif
//无OOB认证
prov.static_val = NULL;
prov.static_val_len = 0;

#ifdef CONFIG_BT_MESH_ROLE_PROVISIONER
//配网器单播地址0x0001、未配网节点分配的起始地址0x0005
prov.prov_unicast_addr = 0x0001;
prov.prov_start_address = 0x0005;
#endif

prov.complete = _prov_complete;
prov.reset = _prov_reset;
//成分数据初始化
comp.cid = CONFIG_CID_TAOBAO;
comp.pid = 0;
comp.vid = 1; // firmware version fir ota
comp.elem = elements;
comp.elem_count = get_vendor_element_num();
//HCI驱动初始化 蓝牙主机 <-> 蓝牙控制器
hci_driver_init();

//开启蓝牙
ret = bt_enable(_genie_mesh_ready);
if (ret) {
BT_INFO("init err %d", ret);
}
}
#endif

3. 配网器配网过程部分实现

3.1 provisioner_prov.h

配网器.h文件我们需要新建一个,放在这个目录下:network/bluetooth/bt_mesh/inc/provisioner_prov.h。

点击查看详情
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef PROVISIONER_PROV_H
#define PROVISIONER_PROV_H

#include <net/buf.h>
#include "mesh.h"

void provisioner_link_open(const uint8_t * uuid);
int is_provisioning(void);
int bt_prov_active(void);
void bt_mesh_prov_adv_recv(struct net_buf_simple *buf);
int bt_mesh_provisioner_prov_init(const struct bt_mesh_prov *prov_info);

#endif

3.2 provisioner_prov.c

配网器.c文件我们也需要新建,放在这个目录下:network/bluetooth/bt_mesh/src/provisioner_prov.c。

点击查看详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
#include <zephyr.h>
#include <errno.h>
#include <atomic.h>
#include <misc/util.h>
#include <misc/byteorder.h>

#include <net/buf.h>
#include <bluetooth.h>
#include <conn.h>
#include <api/mesh.h>
#include <uuid.h>
#include "genie_mesh_flash.h"

#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_PROV)
#include "common/log.h"

#ifdef MESH_DEBUG_PROV
#define ALI_PROV_TAG "\t[ALI_PROV]"
#define PROV_D(f, ...) printf("%d "ALI_PROV_TAG"[D] %s "f"\n", (u32_t)aos_now_ms(), __func__, ##__VA_ARGS__)
#else
#define PROV_D(f, ...)
#endif
#include "ecc.h"

#include "port/mesh_hal_ble.h"
#include "mesh_crypto.h"
#include "adv.h"
#include "mesh.h"
#include "net.h"
#include "access.h"
#include "foundation.h"
#include "proxy.h"
#include <mesh/main.h>


#include "bt_mesh_custom_log.h"

#ifdef CONFIG_BT_MESH_ROLE_PROVISIONER
#include "provisioner_prov.h"
#include "tri_tuple_default.h"

/* 4 transmissions, 20ms interval */
#define PROV_XMIT_COUNT 0
#define PROV_XMIT_INT 20

#define AUTH_METHOD_NO_OOB 0x00
#define AUTH_METHOD_STATIC 0x01
#define AUTH_METHOD_OUTPUT 0x02
#define AUTH_METHOD_INPUT 0x03

#define OUTPUT_OOB_BLINK 0x00
#define OUTPUT_OOB_BEEP 0x01
#define OUTPUT_OOB_VIBRATE 0x02
#define OUTPUT_OOB_NUMBER 0x03
#define OUTPUT_OOB_STRING 0x04

#define INPUT_OOB_PUSH 0x00
#define INPUT_OOB_TWIST 0x01
#define INPUT_OOB_NUMBER 0x02
#define INPUT_OOB_STRING 0x03

#define PROV_ERR_NONE 0x00
#define PROV_ERR_NVAL_PDU 0x01
#define PROV_ERR_NVAL_FMT 0x02
#define PROV_ERR_UNEXP_PDU 0x03
#define PROV_ERR_CFM_FAILED 0x04
#define PROV_ERR_RESOURCES 0x05
#define PROV_ERR_DECRYPT 0x06
#define PROV_ERR_UNEXP_ERR 0x07
#define PROV_ERR_ADDR 0x08

#define PROV_INVITE 0x00
#define PROV_CAPABILITIES 0x01
#define PROV_START 0x02
#define PROV_PUB_KEY 0x03
#define PROV_INPUT_COMPLETE 0x04
#define PROV_CONFIRM 0x05
#define PROV_RANDOM 0x06
#define PROV_DATA 0x07
#define PROV_FAILED 0x09
#define PROV_COMPLETE 0x08

#define PROV_ALG_P256 0x00

#define GPCF(gpc) (gpc & 0x03)
#define GPC_START(last_seg) (((last_seg) << 2) | 0x00)
#define GPC_ACK 0x01
#define GPC_CONT(seg_id) (((seg_id) << 2) | 0x02)
#define GPC_CTL(op) (((op) << 2) | 0x03)

#define START_PAYLOAD_MAX 20
#define CONT_PAYLOAD_MAX 23

#define START_LAST_SEG(gpc) (gpc >> 2)
#define CONT_SEG_INDEX(gpc) (gpc >> 2)

#define BEARER_CTL(gpc) (gpc >> 2)
#define LINK_OPEN 0x00
#define LINK_ACK 0x01
#define LINK_CLOSE 0x02

#define CLOSE_REASON_SUCCESS 0x00
#define CLOSE_REASON_TIMEOUT 0x01
#define CLOSE_REASON_FAILED 0x02

#define PROV_BUF(len) NET_BUF_SIMPLE(PROV_BUF_HEADROOM + len)


#define XACT_SEG_DATA(_seg) (&link.rx.buf->data[20 + ((_seg - 1) * 23)])
#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))

#define XACT_NVAL 0xff

enum {
REMOTE_PUB_KEY, /* Remote key has been received */
LOCAL_PUB_KEY, /* Local public key is available */
LINK_ACTIVE, /* Link has been opened */
WAIT_GEN_DHKEY, /* Waiting for remote public key to generate DHKey */
HAVE_DHKEY, /* DHKey has been calcualted */
SEND_CONFIRM, /* Waiting to send Confirm value */
WAIT_NUMBER, /* Waiting for number input from user */
WAIT_STRING, /* Waiting for string input from user */

NUM_FLAGS,
};


#define BLE_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
#define BLE_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
#define BLE_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
#define BLE_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)

#define BLE_MESH_ADDR_UNASSIGNED 0x0000
#define BLE_MESH_ADDR_ALL_NODES 0xffff
#define BLE_MESH_ADDR_PROXIES 0xfffc
#define BLE_MESH_ADDR_FRIENDS 0xfffd
#define BLE_MESH_ADDR_RELAYS 0xfffe


#define BLE_MESH_KEY_PRIMARY 0x0000
#define BLE_MESH_KEY_ANY 0xffff

#define BLE_MESH_NODE_IDENTITY_STOPPED 0x00
#define BLE_MESH_NODE_IDENTITY_RUNNING 0x01
#define BLE_MESH_NODE_IDENTITY_NOT_SUPPORTED 0x02

#define BLE_MESH_IVU_MIN_HOURS 96
#define BLE_MESH_IVU_HOURS (BLE_MESH_IVU_MIN_HOURS / CONFIG_BLE_MESH_IVU_DIVIDER)
#define BLE_MESH_IVU_TIMEOUT K_HOURS(BLE_MESH_IVU_HOURS)



//节点名字最大长度
#define BLE_MESH_NODE_NAME_SIZE 31
//最大连接节点数
#define CONFIG_BLE_MESH_MAX_PROV_NODES 5

/* Each node information stored by provisioner */
struct bt_mesh_node {
/* Device information */
uint8_t addr[6]; /* Node device address */
uint8_t addr_type; /* Node device address type */
uint8_t dev_uuid[16]; /* Node Device UUID */
uint16_t oob_info; /* Node OOB information */

/* Provisioning information */
uint16_t unicast_addr; /* Node unicast address */
uint8_t element_num; /* Node element number */
uint16_t net_idx; /* Node NetKey Index */
uint8_t flags; /* Node key refresh flag and iv update flag */
uint32_t iv_index; /* Node IV Index */
uint8_t dev_key[16]; /* Node device key */

/* Additional information */
char name[BLE_MESH_NODE_NAME_SIZE + 1]; /* Node name */
uint16_t comp_length; /* Length of Composition Data */
uint8_t *comp_data; /* Value of Composition Data */
} __packed;


struct prov_link {
ATOMIC_DEFINE(flags, NUM_FLAGS);
#if defined(CONFIG_BT_MESH_PB_GATT)
bt_mesh_conn_t conn; /* GATT connection */
#endif
uint8_t uuid[16]; /* check if device is being provisioned*/
u8_t dhkey[32]; /* Calculated DHKey */
u8_t expect; /* Next expected PDU */

uint8_t element_num;

u8_t oob_method;
u8_t oob_action;
u8_t oob_size;

u8_t conf[16]; /* Remote Confirmation */
u8_t rand[16]; /* Local Random */
u8_t auth[16]; /* Authentication Value */

u8_t conf_salt[16]; /* ConfirmationSalt */
u8_t conf_key[16]; /* ConfirmationKey */
u8_t conf_inputs[145]; /* ConfirmationInputs */
u8_t prov_salt[16]; /* Provisioning Salt */

u8_t local_conf[16]; /* Local Confirmation */
uint16_t assign_addr; /* Application assigned address for the device */
uint16_t unicast_addr; /* unicast address allocated for device */
uint8_t ki_flags; /* Key refresh flag and iv update flag */
uint32_t iv_index; /* IV Index */
#if defined(CONFIG_BT_MESH_PB_ADV)
u32_t id; /* Link ID */
bool linking; /* Linking is being establishing */
uint16_t send_link_close; /* Link close is being sent flag */
uint8_t pending_ack; /* Decide which transaction id ack is pending */
uint8_t expect_ack_for; /* Transaction ACK expected for provisioning pdu */
uint8_t tx_pdu_type; /* The current transmitted Provisioning PDU type */

struct {
u8_t id; /* Transaction ID */
u8_t prev_id; /* Previous Transaction ID */
u8_t seg; /* Bit-field of unreceived segments */
u8_t last_seg; /* Last segment (to check length) */
u8_t fcs; /* Expected FCS value */
struct net_buf_simple *buf;
} rx;

struct {
/* Start timestamp of the transaction */
s64_t start;

/* Transaction id*/
u8_t id;

/* Pending outgoing buffer(s) */
struct net_buf *buf[3];

/* Retransmit timer */
struct k_delayed_work retransmit;
} tx;
#endif
};



struct bt_mesh_prov_ctx {
/* Primary element address of Provisioner */
uint16_t primary_addr;

/* Provisioning bearers used by Provisioner */
bt_mesh_prov_bearer_t bearers;

/* Current number of PB-ADV provisioned devices simultaneously */
uint8_t pba_count;

/* Current number of PB-GATT provisioned devices simultaneously */
uint8_t pbg_count;

/* Current unicast address going to allocated */
uint16_t curr_alloc_addr;

/* Current net_idx going to be used in provisioning data */
uint16_t curr_net_idx;

/* Current flags going to be used in provisioning data */
uint8_t curr_flags;

/* Current iv_index going to be used in provisioning data */
uint16_t curr_iv_index;

/* Length of Static OOB value */
uint8_t static_oob_len;

/* Static OOB value */
uint8_t static_oob_val[16];

/* Offset of the device uuid to be matched, based on zero */
uint8_t match_offset;

/* Length of the device uuid to be matched (start from the match_offset) */
uint8_t match_length;

/* Value of the device uuid to be matched */
uint8_t match_value[16];

/* Indicate when received uuid_match adv_pkts, can provision it at once */
bool prov_after_match;

#if defined(CONFIG_BLE_MESH_PB_ADV)
/* Mutex used to protect the PB-ADV procedure */
bt_mesh_mutex_t pb_adv_lock;

/* Mutex used to protect the adv buf during PB-ADV procedure */
bt_mesh_mutex_t pb_buf_lock;
#endif

#if defined(CONFIG_BLE_MESH_PB_GATT)
/* Mutex used to protect the PB-GATT procedure */
bt_mesh_mutex_t pb_gatt_lock;
#endif


};

struct prov_rx {
u32_t link_id;
u8_t xact_id;
u8_t gpc;
};

#define BLE_MESH_KEY_UNUSED 0xffff
#define CONFIG_BLE_MESH_SUBNET_COUNT 3
#define CONFIG_BLE_MESH_PROVISIONER_APP_KEY_COUNT 3

extern struct bt_mesh_net bt_mesh;

#if defined(CONFIG_BT_MESH_PB_ADV)
#define ADV_BUF_SIZE 65

static struct prov_adv_buf {
struct net_buf_simple buf;
} adv_buf;

static uint8_t adv_buf_data[ADV_BUF_SIZE];
#endif /* CONFIG_BT_MESH_PB_ADV */


static struct bt_mesh_prov_ctx prov_ctx;
static struct prov_link link;
static const struct bt_mesh_prov *prov;


static uint16_t addr;
static uint32_t seq;
static uint8_t provisoner_devkey[16];
static mesh_netkey_para_t g_netkey;
static mesh_appkey_para_t appkey;
static u32_t seq;
static u16_t addr;


static struct bt_mesh_node mesh_nodes[CONFIG_BLE_MESH_MAX_PROV_NODES];
uint8_t filter_uuid[] = {0xa8,0x01};

#define RETRANSMIT_TIMEOUT K_MSEC(500)
#define BUF_TIMEOUT K_MSEC(400)
#define TRANSACTION_TIMEOUT K_SECONDS(30)

#if defined(CONFIG_BT_MESH_PB_GATT)
#define PROV_BUF_HEADROOM 5
#else
#define PROV_BUF_HEADROOM 0
static struct net_buf_simple *rx_buf = NET_BUF_SIMPLE(65);
#endif



static void close_link(u8_t err, u8_t reason);
static void free_segments(void);
int bt_mesh_pb_gatt_close(bt_mesh_conn_t conn);
static inline int prov_send(struct net_buf_simple *buf);
static void send_pub_key(uint8_t oob);
static struct net_buf *adv_buf_create(void);


//配网器通过网络索引获取网络密钥
const uint8_t *bt_mesh_provisioner_net_key_get(uint16_t net_idx)
{
struct bt_mesh_subnet *sub = NULL;
int i;

BT_DBG("%s", __func__);

for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
sub = bt_mesh.p_sub[i];
BT_INFO("sub->net_idx = %u",sub->net_idx);
if (sub && sub->net_idx == net_idx) {
if (sub->kr_flag) {
return sub->keys[1].net;
} else {
return sub->keys[0].net;
}
}
}

return NULL;
}



#if defined(CONFIG_BT_MESH_PB_ADV)
//发送重传
static void buf_sent(int err, void *user_data)
{
//如果发送缓存为空,则返回
if (!link.tx.buf[0]) {
return;
}
//如果不为空,启动重传
k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
}

static struct bt_mesh_send_cb buf_sent_cb = {
.end = buf_sent,
};
//初始化缓存区
static void prov_buf_init(struct net_buf_simple *buf, u8_t type)
{
net_buf_simple_init(buf, PROV_BUF_HEADROOM);
net_buf_simple_add_u8(buf, type);
}


//可靠发送缓存数据
static void send_reliable(void)
{
int i;

link.tx.start = k_uptime_get();

for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
struct net_buf *buf = link.tx.buf[i];

if (!buf) {
break;
}

if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
bt_mesh_adv_send(buf, NULL, NULL);
} else {
bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
}
}
}
//取消发送
static void prov_clear_tx(void)
{

k_delayed_work_cancel(&link.tx.retransmit);
//清除缓存
free_segments();
}
//发送PB-ADV广播
static int bearer_ctl_send(u8_t op, void *data, u8_t data_len)
{
struct net_buf *buf;

printf("发送%s op 0x%02x data_len %u\r\n",op == 0 ? "连接":op == 1 ? "应答" : op == 2 ? "断开" : NULL , op, data_len);

prov_clear_tx();

buf = adv_buf_create();
if (!buf) {
return -ENOBUFS;
}
//包头填充
net_buf_add_be32(buf, link.id);
/* Transaction ID, always 0 for Bearer messages */
net_buf_add_u8(buf, 0x00);
net_buf_add_u8(buf, GPC_CTL(op));
net_buf_add_mem(buf, data, data_len);

link.tx.buf[0] = buf;
//可靠发送
send_reliable();
//如果是关闭操作还需修改一些其它标志
if (op == LINK_CLOSE) {
uint8_t reason = *(uint8_t *)data;
link.send_link_close = ((reason & BIT_MASK(2)) << 1) | BIT(0);
link.tx.id = 0;
}

return 0;
}

//配网器删除节点
int bt_mesh_provisioner_remove_node(const uint8_t uuid[16])
{
int i;

BT_DBG("%s", __func__);

if (uuid == NULL) {
BT_ERR("Invalid device uuid");
return 0;
}

for (i = 0; i < ARRAY_SIZE(mesh_nodes); i++) {
if (!memcmp(mesh_nodes[i].dev_uuid, uuid, 16)) {

memset(&mesh_nodes[i],0,sizeof(mesh_nodes[i]));
}
}

return 0;
}
//通过UUID找到节点
static struct bt_mesh_node *provisioner_find_node_with_uuid(const uint8_t uuid[16], uint16_t *index)
{
int i;

BT_DBG("%s", __func__);

if (uuid == NULL) {
BT_ERR("Invalid device uuid");
return NULL;
}

for (i = 0; i < ARRAY_SIZE(mesh_nodes); i++) {
if (!memcmp(mesh_nodes[i].dev_uuid, uuid, 16)) {
if (index) {
*index = i;
}
return &mesh_nodes[i];
}
}

return NULL;
}


//节点是否连接
int node_is_connected(const uint8_t *uuid)
{
if(uuid == NULL)
{
printf("UUID错误\r\n");
return -1;
}
for(int i = 0; i < CONFIG_BLE_MESH_MAX_PROV_NODES;i++)
{
if(memcmp(&mesh_nodes[i].dev_uuid[0],uuid,16) == 0)
{
printf("已经建立过连接\r\n");
return 1;
}
}

return 0;

}
//广播包过滤uuid
int adv_filter_uuid(const uint8_t * uuid)
{
if(uuid == NULL)
{
printf("uuid 错误\r\n");
return -1;
}
if(memcmp(filter_uuid,uuid,sizeof(filter_uuid)) == 0)
{
printf("找到未配网设备\r\n");
return 0;
}

return 1;
}

//获得网络层缓存区
static struct net_buf_simple *bt_mesh_pba_get_buf(void)
{
struct net_buf_simple *buf = &adv_buf.buf;

buf->len = 0;
buf->data = adv_buf_data;
*(&buf->__buf[0]) = adv_buf_data;
buf->size = 65;

return buf;
}


//建立连接
void provisioner_link_open(const uint8_t * uuid)
{
//先判断UUID是否合法
if(node_is_connected(uuid) || adv_filter_uuid(uuid))
{
return ;
}

if(atomic_test_bit(link.flags, LINK_ACTIVE))
{
printf("已经在配网阶段\r\n");
return;
}

printf("生成随机数\r\n");
//随机生成一个连接ID
bt_mesh_rand(&link.id,sizeof(link.id));
//发起配网操作
bearer_ctl_send(LINK_OPEN,(void *)uuid, 16);
printf("发起配网\r\n");
//应用层触发开始配网事件
genie_event(GENIE_EVT_SDK_MESH_PROV_START,&link.id);


/* Set LINK_ACTIVE just to be in compatibility with current Zephyr code */
atomic_set_bit(link.flags, LINK_ACTIVE);

if (prov->link_open) {
prov->link_open(BT_MESH_PROV_ADV);
}

link.expect = PROV_INVITE;


return;
}
//发送邀请
static void send_invite(void)
{
//实例化网络层缓存buf,实际为局部结构体变量
struct net_buf_simple *buf = PROV_BUF(2);
//初始化缓存头部类型
prov_buf_init(buf, PROV_INVITE);
//添加连接超时
net_buf_simple_add_u8(buf, 0);
//等待连接时间记录到本地
link.conf_inputs[0] = 0;
//发送缓存
if (prov_send(buf)) {
BT_ERR("Failed to send Provisioning Invite");
close_link(PROV_ERR_NVAL_PDU, CLOSE_REASON_FAILED);
return;
}
printf("已发出邀请\r\n");
//下次预期接收配网能力
link.expect = PROV_CAPABILITIES;
}

//释放实例化缓存
static void free_segments(void)
{
int i;

for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
struct net_buf *buf = link.tx.buf[i];

if (!buf) {
break;
}

link.tx.buf[i] = NULL;
/* Mark as canceled */
BT_MESH_ADV(buf)->busy = 0;
net_buf_unref(buf);
}
}


//复位连接
static void reset_link(void)
{
prov_clear_tx();

if (prov->link_close) {
prov->link_close(BT_MESH_PROV_ADV);
}

/* Clear everything except the retransmit delayed work config */
memset(&link, 0, offsetof(struct prov_link, tx.retransmit));

link.rx.prev_id = XACT_NVAL;

if (bt_mesh_pub_key_get()) {
atomic_set_bit(link.flags, LOCAL_PUB_KEY);
}

#if defined(CONFIG_BT_MESH_PB_GATT)
link.rx.buf = bt_mesh_proxy_get_buf();
#else
net_buf_simple_init(rx_buf, 0);
link.rx.buf = rx_buf;
#endif

/* Disable Attention Timer if it was set */
if (link.conf_inputs[0]) {
bt_mesh_attention(NULL, 0);
}
}


//创建广播
static struct net_buf *adv_buf_create(void)
{
struct net_buf *buf;

buf = bt_mesh_adv_create(BT_MESH_ADV_PROV, PROV_XMIT_COUNT,
PROV_XMIT_INT, BUF_TIMEOUT);
if (!buf) {
BT_ERR("Out of provisioning buffers");
return NULL;
}

return buf;
}

static u8_t pending_ack = XACT_NVAL;
//响应完成回调用
static void ack_complete(u16_t duration, int err, void *user_data)
{
BT_DBG("xact %u complete", (u8_t)pending_ack);
pending_ack = XACT_NVAL;
}
//发送响应
static void gen_prov_ack_send(u8_t xact_id)
{
static const struct bt_mesh_send_cb cb = {
.start = ack_complete,
};
const struct bt_mesh_send_cb *complete;
struct net_buf *buf;

BT_DBG("pending_ack = %u,xact_id %u",pending_ack,xact_id);

if (pending_ack == xact_id) {
BT_DBG("Not sending duplicate ack");
return;
}
//创建广播包缓存
buf = adv_buf_create();
if (!buf) {
return;
}

if (pending_ack == XACT_NVAL) {
pending_ack = xact_id;
complete = &cb;
} else {
complete = NULL;
}

net_buf_add_be32(buf, link.id);
net_buf_add_u8(buf, xact_id);
net_buf_add_u8(buf, GPC_ACK);
//发送响应广播
bt_mesh_adv_send(buf, complete, NULL);
//释放缓存
net_buf_unref(buf);
}



//计算最后包号
static u8_t last_seg(u8_t len)
{
//如果小于20个字节 就一包数据
if (len <= START_PAYLOAD_MAX) {
return 0;
}
//否则超过20个字节就要分包(len -= 20)
len -= START_PAYLOAD_MAX;
//一包数据传23个字节(第一包额外加了一些包头所以是20个字节)
return 1 + (len / CONT_PAYLOAD_MAX); // 1 + (len / 23)
}
//下一个传输编号
static inline u8_t next_transaction_id(void)
{
if (link.tx.id > 0x7F) {
link.tx.id = 0x0;
}
return link.tx.id++;
}
//发送广播
static int prov_send_adv(struct net_buf_simple *msg)
{
struct net_buf *start, *buf;
u8_t seg_len, seg_id;
u8_t xact_id;


//PROV_D("len %u: %s", msg->len, bt_hex(msg->data, msg->len));

//清除发送缓存
prov_clear_tx();
//创建广播包缓存
start = adv_buf_create();
if (!start) {
return -ENOBUFS;
}
//下一个传输编号
xact_id = next_transaction_id();
net_buf_add_be32(start, link.id);
net_buf_add_u8(start, xact_id);

net_buf_add_u8(start, GPC_START(last_seg(msg->len)));
net_buf_add_be16(start, msg->len);
net_buf_add_u8(start, bt_mesh_fcs_calc(msg->data, msg->len));

link.tx.buf[0] = start;

seg_len = min(msg->len, START_PAYLOAD_MAX);
// printf("seg 0 len %u: %s", seg_len, bt_hex(msg->data, seg_len));
net_buf_add_mem(start, msg->data, seg_len);
net_buf_simple_pull(msg, seg_len);
printf("发送: 传输标号 = %u\r\n",xact_id);
buf = start;
//将所以数据写入缓存
for (seg_id = 1; msg->len > 0; seg_id++) {
if (seg_id >= ARRAY_SIZE(link.tx.buf)) {
BT_ERR("Too big message");
free_segments();
return -E2BIG;
}

buf = adv_buf_create();
if (!buf) {
free_segments();
return -ENOBUFS;
}

link.tx.buf[seg_id] = buf;

seg_len = min(msg->len, CONT_PAYLOAD_MAX);

printf("seg_id %u len %u: %s\r\n", seg_id, seg_len,
bt_hex(msg->data, seg_len));

net_buf_add_be32(buf, link.id);
net_buf_add_u8(buf, xact_id);
net_buf_add_u8(buf, GPC_CONT(seg_id));
net_buf_add_mem(buf, msg->data, seg_len);
net_buf_simple_pull(msg, seg_len);
}
//可靠发送
send_reliable();

return 0;
}

#endif /* CONFIG_BT_MESH_PB_ADV */

#if defined(CONFIG_BT_MESH_PB_GATT)
static int prov_send_gatt(struct net_buf_simple *msg)
{
if (!link.conn) {
return -ENOTCONN;
}

return bt_mesh_proxy_send(link.conn, BT_MESH_PROXY_PROV, msg);
}
#endif /* CONFIG_BT_MESH_PB_GATT */

static inline int prov_send(struct net_buf_simple *buf)
{
#if defined(CONFIG_BT_MESH_PB_GATT)
if (link.conn) {
return prov_send_gatt(buf);
}
#endif
#if defined(CONFIG_BT_MESH_PB_ADV)
//进入到这里发送
return prov_send_adv(buf);
#else
return 0;
#endif
}

//发送配网失败消息
static void prov_send_fail_msg(u8_t err)
{
struct net_buf_simple *buf = PROV_BUF(2);

prov_buf_init(buf, PROV_FAILED);
net_buf_simple_add_u8(buf, err);
prov_send(buf);
}

static void prov_invite(const u8_t *data)
{
printf("prov_invite\r\n");
}

static void prov_capabilities(const u8_t *data)
{
printf("接收到配网能力\r\n");
struct net_buf_simple *buf = PROV_BUF(6);
uint16_t algorithms = 0U, output_action = 0U, input_action = 0U;
uint8_t element_num = 0U, pub_key_oob = 0U, static_oob = 0U,
output_size = 0U, input_size = 0U;
uint8_t auth_method = 0U, auth_action = 0U, auth_size = 0U;

element_num = data[0];
BT_INFO("Elements: 0x%02x", element_num);
if (!element_num) {
BT_ERR("Invalid element number %d", element_num);
goto fail;
}
//元素个数
link.element_num = element_num;

algorithms = sys_get_be16(&data[1]);
BT_INFO("Algorithms: 0x%04x", algorithms);
if (algorithms != BIT(PROV_ALG_P256)) {
BT_ERR("Invalid algorithms 0x%04x", algorithms);
goto fail;
}
//配网能力标志检查
pub_key_oob = data[3];
BT_INFO("Public Key Type: 0x%02x", pub_key_oob);
if (pub_key_oob > 0x01) {
BT_ERR("Invalid public key type 0x%02x", pub_key_oob);
goto fail;
}

pub_key_oob = ((prov->prov_pub_key_oob &&
prov->prov_pub_key_oob_cb) ? pub_key_oob : 0x00);

static_oob = data[4];
BT_INFO("Static OOB Type: 0x%02x", static_oob);
if (static_oob > 0x01) {
BT_ERR("Invalid Static OOB type 0x%02x", static_oob);
goto fail;
}
static_oob = (prov_ctx.static_oob_len ? static_oob : 0x00);

output_size = data[5];
BT_INFO("Output OOB Size: 0x%02x", output_size);
if (output_size > 0x08) {
BT_ERR("Invalid Output OOB size %d", output_size);
goto fail;
}

output_action = sys_get_be16(&data[6]);
BT_INFO("Output OOB Action: 0x%04x", output_action);
if (output_action > 0x1f) {
BT_ERR("Invalid Output OOB action 0x%04x", output_action);
goto fail;
}

/* Provisioner select output action */
if (prov->prov_input_num && output_size) {
output_action = __builtin_ctz(output_action);
} else {
output_size = 0x0;
output_action = 0x0;
}

input_size = data[8];
BT_INFO("Input OOB Size: 0x%02x", input_size);
if (input_size > 0x08) {
BT_ERR("Invalid Input OOB size %d", input_size);
goto fail;
}

input_action = sys_get_be16(&data[9]);
BT_INFO("Input OOB Action: 0x%04x", input_action);
if (input_action > 0x0f) {
BT_ERR("Invalid Input OOB action 0x%04x", input_action);
goto fail;
}

#if 0
/* Make sure received pdu is ok and cancel the timeout timer */
if (bt_mesh_atomic_test_and_clear_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_cancel(&link.timeout);
}
#endif

/* Provisioner select input action */
if (prov->prov_output_num && input_size) {
input_action = __builtin_ctz(input_action);
} else {
input_size = 0x0;
input_action = 0x0;
}

if (static_oob) {
/* if static oob is valid, just use static oob */
auth_method = AUTH_METHOD_STATIC;
auth_action = 0x00;
auth_size = 0x00;
} else {
if (!output_size && !input_size) {
auth_method = AUTH_METHOD_NO_OOB;
auth_action = 0x00;
auth_size = 0x00;
} else if (!output_size && input_size) {
auth_method = AUTH_METHOD_INPUT;
auth_action = (uint8_t)input_action;
auth_size = input_size;
} else {
auth_method = AUTH_METHOD_OUTPUT;
auth_action = (uint8_t)output_action;
auth_size = output_size;
}
}

/* Store provisioning capabilities value in conf_inputs */
//保存要发送的参数到 conf_inputs 里,以便后期用来生成“配网佐料”
memcpy(&link.conf_inputs[1], data, 11);
//填充配网阶段参数
prov_buf_init(buf, PROV_START);
net_buf_simple_add_u8(buf, prov->prov_algorithm);
net_buf_simple_add_u8(buf, pub_key_oob);
net_buf_simple_add_u8(buf, auth_method);
net_buf_simple_add_u8(buf, auth_action);
net_buf_simple_add_u8(buf, auth_size);
//复制到认证数据里计算认证时用
memcpy(&link.conf_inputs[12], &buf->data[1], 5);
//发送provsisioning start
if (prov_send(buf)) {
BT_ERR("Failed to send Provisioning Start");
goto fail;
}

link.oob_method = auth_method;
link.oob_action = auth_action;
link.oob_size = auth_size;

/** After prov start sent, use OOB to get remote public key.
* And we just follow the procedure in Figure 5.15 of Section
* 5.4.2.3 of Mesh Profile Spec.
*/
#if 1
if (pub_key_oob) {
if (prov->prov_pub_key_oob_cb()) {
BT_ERR("Failed to notify input OOB Public Key");
goto fail;
}
}
#endif

/** If using PB-ADV, need to listen for transaction ack,
* after ack is received, provisioner can send public key.
*/
#if defined(CONFIG_BT_MESH_PB_ADV)

link.expect_ack_for = PROV_START;
return;

#endif /* CONFIG_BT_MESH_PB_ADV */
//发送交换公钥
send_pub_key(pub_key_oob);
return;

fail:
close_link(PROV_ERR_CFM_FAILED,CLOSE_REASON_FAILED);
return;
}

//oob认证数据生成(无oob只能填充0)
static int prov_auth(u8_t method, u8_t action, u8_t size)
{

switch (method) {
case AUTH_METHOD_STATIC:
if (action || size) {
return -EINVAL;
}
memcpy(link.auth + 16 - prov->static_val_len,
prov->static_val, prov->static_val_len);
memset(link.auth, 0, sizeof(link.auth) - prov->static_val_len);
return 0;
//只支持无OOB
case AUTH_METHOD_NO_OOB:
if (action || size) {
return -EINVAL;
}

memset(link.auth, 0, sizeof(link.auth));
return 0;

case AUTH_METHOD_OUTPUT:
case AUTH_METHOD_INPUT:


default:
return -EINVAL;
}
}

static void prov_start(const u8_t *data)
{
printf("prov_start\r\n");
}


//发送认证
static void send_confirm(void)
{
struct net_buf_simple *buf = PROV_BUF(17);
uint8_t *conf = NULL;

BT_INFO("ConfInputs[0] %s", bt_hex(link.conf_inputs, 64));
BT_INFO("ConfInputs[64] %s", bt_hex(&link.conf_inputs[64], 64));
BT_INFO("ConfInputs[128] %s", bt_hex(&link.conf_inputs[128], 17));
//生成Confirmation salt 认证佐料
if (bt_mesh_prov_conf_salt(link.conf_inputs, link.conf_salt)) {
BT_ERR("Unable to generate confirmation salt");
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
return;
}

BT_INFO("ConfirmationSalt: %s", bt_hex(link.conf_salt, 16));
//共享密钥和认证佐料生成认证密钥
if (bt_mesh_prov_conf_key(link.dhkey, link.conf_salt, link.conf_key)) {
BT_ERR("Unable to generate confirmation key");
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
return;
}

BT_INFO("ConfirmationKey: %s", bt_hex(link.conf_key, 16));
//生成随机值
if (bt_mesh_rand(link.rand, 16)) {
BT_ERR("Unable to generate random number");
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
return;
}

BT_INFO("LocalRandom: %s", bt_hex(link.rand, 16));

prov_buf_init(buf, PROV_CONFIRM);

conf = net_buf_simple_add(buf, 16);
//认证密钥、随机值和oob数据(这里为0)生成确认值直接写入到了buf
if (bt_mesh_prov_conf(link.conf_key, link.rand, link.auth,conf)) {
BT_ERR("Unable to generate confirmation value");
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
return;
}
//拷贝确认值到本地存储
memcpy(link.local_conf, conf, 16);
//打印要发送得认证数据
BT_INFO("********************************************");
BT_INFO("link.conf_key: %s", bt_hex(link.conf_key, 16));
BT_INFO("link.rand: %s", bt_hex(link.rand, 16));
BT_INFO("conf_verify: %s", bt_hex(conf, 16));
BT_INFO("********************************************");
//发送确认值
if (prov_send(buf)) {
BT_ERR("Failed to send Provisioning Confirm");
close_link(PROV_ERR_RESOURCES, CLOSE_REASON_FAILED);
return;
}

link.expect = PROV_CONFIRM;
}





//共享密钥生成回调函数
static void prov_dh_key_cb(const u8_t key[32])
{
BT_INFO("DHkey 地址:%p", key);
if (!key) {
BT_ERR("DHKey generation failed");
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
return;
}

sys_memcpy_swap(link.dhkey, key, 32);

BT_INFO("DHkey: %s", bt_hex(link.dhkey, 32));

atomic_set_bit(link.flags, HAVE_DHKEY);

if (prov_auth(link.oob_method,
link.oob_action, link.oob_size) < 0) {
BT_ERR("Failed to authenticate");
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
}
if (link.oob_method == AUTH_METHOD_OUTPUT ||
link.oob_method == AUTH_METHOD_INPUT) {
return;
}
//如果下次预期的PDU不是输入比较,那就发送认证值
if (link.expect != PROV_INPUT_COMPLETE) {
send_confirm();
}

return;
}
//生成共享密钥
static void prov_gen_dh_key()
{
uint8_t pub_key[64] = {0};

/* Copy device public key in little-endian for bt_mesh_dh_key_gen().
* X and Y halves are swapped independently.
*/
sys_memcpy_swap(&pub_key[0], &link.conf_inputs[81], 32);
sys_memcpy_swap(&pub_key[32], &link.conf_inputs[113], 32);
//Diffie-Hellman Key
if (bt_mesh_dh_key_gen(pub_key, prov_dh_key_cb)) {
BT_ERR("Failed to generate DHKey");
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
return;
}
}

//发送公钥
static void send_pub_key(uint8_t oob)
{
struct net_buf_simple *buf = PROV_BUF(65);
const u8_t *key;

key = bt_mesh_pub_key_get();
if (!key) {
BT_ERR("No public key available");
close_link(PROV_ERR_RESOURCES, CLOSE_REASON_FAILED);
return;
}

BT_INFO("Local Public Key: %s\r\n", bt_hex(key, 64));
atomic_set_bit(link.flags, LOCAL_PUB_KEY);
prov_buf_init(buf, PROV_PUB_KEY);

/* Swap X and Y halves independently to big-endian */
sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
//存储公钥到conf_inputs里
memcpy(&link.conf_inputs[17], &buf->data[1], 64);

prov_send(buf);

if (!oob) {
BT_INFO("进入!oob link.expect = PROV_PUB_KEY");
link.expect = PROV_PUB_KEY;
} else {
BT_INFO("没有进入link.expect = PROV_PUB_KEY");
/** Have already got device public key. If next is to
* send confirm(not wait for input complete), need to
* wait for transactiona ack for public key then send
* provisioning confirm pdu.
*/
#if defined(CONFIG_BLE_MESH_PB_ADV)
// if (idx < CONFIG_BLE_MESH_PBA_SAME_TIME) {
// link.expect_ack_for = PROV_PUB_KEY;
// return;
// }
#endif /* CONFIG_BLE_MESH_PB_ADV */

/* If remote public key has been read, then start to generate DHkey,
* otherwise wait for device oob public key.
*/
if (atomic_test_bit(link.flags, REMOTE_PUB_KEY)) {
prov_gen_dh_key();
} else {
atomic_set_bit(link.flags, WAIT_GEN_DHKEY);
}
}

}

static void prov_pub_key(const u8_t *data)
{
BT_INFO("Remote Public Key: %s", bt_hex(data, 64));

//拷贝对方设备公钥
memcpy(&link.conf_inputs[81], data, 64);

if (!atomic_test_bit(link.flags, LOCAL_PUB_KEY)) {
/* Clear retransmit timer */
#if defined(CONFIG_BT_MESH_PB_ADV)
prov_clear_tx();
#endif
atomic_set_bit(link.flags, REMOTE_PUB_KEY);
BT_WARN("Waiting for local public key");
return;
}
prov_gen_dh_key();
//send_pub_key();
}


static void prov_input_complete(const u8_t *data)
{
send_confirm();
}
//收到对方确认值进入
static void prov_confirm(const u8_t *data)
{
BT_INFO("Remote Confirm: %s", bt_hex(data, 16));

struct net_buf_simple *buf = PROV_BUF(17);

/* NOTE: The Bluetooth SIG recommends that potentially vulnerable mesh provisioners
* restrict the authentication procedure and not accept provisioning random and
* provisioning confirmation numbers from a remote peer that are the same as those
* selected by the local device (CVE-2020-26560).
*/
//本地确认值和对方 确认值要不一样
if (!memcmp(data, link.local_conf, 16)) {
BT_ERR("Confirmation value is identical to ours, rejecting.");
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
return;
}


memcpy(link.conf, data, 16);
//如果标志位已经有共享密钥,发送认证值标志位也置位
if (atomic_test_bit(link.flags, HAVE_DHKEY)) {
#if defined(CONFIG_BLE_MESH_PB_ADV)
prov_clear_tx(idx);
#endif
atomic_set_bit(link.flags, SEND_CONFIRM);
}
//发送随机值
prov_buf_init(buf, PROV_RANDOM);

net_buf_simple_add_mem(buf, link.rand, 16);

if (prov_send(buf)) {
BT_ERR("Failed to send Provisioning Random");
close_link(PROV_ERR_CFM_FAILED, CLOSE_REASON_FAILED);
return;
}

link.expect = PROV_RANDOM;
}
//发送配网数据
static void send_prov_data(void)
{
struct net_buf_simple *buf = PROV_BUF(34);
uint16_t prev_addr = 0;
uint16_t max_addr = 0;
struct bt_mesh_node *node = NULL;
const uint8_t *netkey = NULL;
uint8_t session_key[16] = {0};
uint8_t nonce[13] = {0};
uint8_t pdu[25] = {0};
int err = 0;
//生成会话密钥
err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
if (err) {
BT_ERR("Failed to generate session key");
goto fail;
}
BT_INFO("SessionKey: %s", bt_hex(session_key, 16));
//生成一次性随机值
err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
if (err) {
BT_ERR("Failed to generate session nonce");
goto fail;
}
BT_INFO("Nonce: %s", bt_hex(nonce, 13));

/* Assign provisioning data for the device. Currently all provisioned devices
* will be added to the primary subnet, and may add an API to choose to which
* subnet will the device be provisioned later.
*/
#if 1
//获得网络密钥
netkey = bt_mesh_provisioner_net_key_get(prov_ctx.curr_net_idx);
BT_INFO("获取网络密钥 netkey: %p",netkey);
if (!netkey) {
BT_ERR("No NetKey for provisioning data");
goto fail;
}
memcpy(pdu, netkey, 16);
sys_put_be16(prov_ctx.curr_net_idx, &pdu[16]);
pdu[18] = prov_ctx.curr_flags;
sys_put_be32(prov_ctx.curr_iv_index, &pdu[19]);


/**
* The Provisioner must not reuse unicast addresses that have been
* allocated to a device and sent in a Provisioning Data PDU until
* the Provisioner receives an Unprovisioned Device beacon or
* Service Data for the Mesh Provisioning Service from that same
* device, identified using the Device UUID of the device.
*/

/* 检查此设备是否为重新配置的设备 */
node = provisioner_find_node_with_uuid(link.uuid,NULL);
if (node) {
if (link.element_num <= node->element_num) {
/**
* If the device is provisioned before, but the element number of
* the device is bigger now, then we treat it as a new device.
*/
prev_addr = node->unicast_addr;
}
bt_mesh_provisioner_remove_node(link.uuid);
}

max_addr = 0x7FFF;

if (BLE_MESH_ADDR_IS_UNICAST(prev_addr)) {
sys_put_be16(prev_addr, &pdu[23]);
link.unicast_addr = prev_addr;
} else {
uint16_t alloc_addr = BLE_MESH_ADDR_UNASSIGNED;

if (BLE_MESH_ADDR_IS_UNICAST(link.assign_addr)) {
alloc_addr = link.assign_addr;
} else {
/* If this device to be provisioned is a new device */
if (prov_ctx.curr_alloc_addr == BLE_MESH_ADDR_UNASSIGNED) {
BT_ERR("Not enough unicast address to be allocated");
goto fail;
}
alloc_addr = prov_ctx.curr_alloc_addr;
}

if (alloc_addr + link.element_num - 1 > max_addr) {
BT_ERR("Not enough unicast address for the device");
goto fail;
}
#if 0
/* Make sure the assigned unicast address is not identical with any unicast
* address of other nodes. And make sure the address is not identical with
* any unicast address of Provisioner.
*/
if (bt_mesh_provisioner_check_is_addr_dup(alloc_addr, link.element_num, true)) {
BT_ERR("Duplicate assigned address 0x%04x", alloc_addr);
goto fail;
}
#endif
sys_put_be16(alloc_addr, &pdu[23]);
link.unicast_addr = alloc_addr;
}
#endif
prov_buf_init(buf, PROV_DATA);
//配网数据加密
err = bt_mesh_prov_encrypt(session_key, nonce, pdu, net_buf_simple_add(buf, 33));
if (err) {
BT_ERR("Failed to encrypt provisioning data");
goto fail;
}
//发送加密后的配网数据
if (prov_send(buf)) {
BT_ERR("Failed to send Provisioning Data");
goto fail;
}

/**
* We update the next unicast address to be allocated here because if
* Provisioner is provisioning two devices at the same time, we need
* to assign the unicast address for them correctly. Hence we should
* not update the prov_ctx.curr_alloc_addr after the proper provisioning
* complete pdu is received.
*/
#if 1
if (!BLE_MESH_ADDR_IS_UNICAST(prev_addr)) {
if (BLE_MESH_ADDR_IS_UNICAST(link.assign_addr)) {
/* Even if the unicast address of the node is assigned by the
* application, we will also update the prov_ctx.curr_alloc_addr
* here, in case Users use the two methods together (i.e. allocate
* the unicast address for the node internally and assign the
* unicast address for the node from application).
*/
if (prov_ctx.curr_alloc_addr < link.assign_addr + link.element_num) {
prov_ctx.curr_alloc_addr = link.assign_addr + link.element_num;
}
} else {
prov_ctx.curr_alloc_addr += link.element_num;
if (prov_ctx.curr_alloc_addr > max_addr) {
/* No unicast address will be used for further provisioning */
prov_ctx.curr_alloc_addr = 0;
}
}
#if 0
/* Store the available unicast address range to flash */
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_prov_info(prov_ctx.primary_addr, prov_ctx.curr_alloc_addr);
}
#endif
}


link.ki_flags = prov_ctx.curr_flags;
link.iv_index = prov_ctx.curr_iv_index;

#endif
link.expect = PROV_COMPLETE;
return;

fail:
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
return;
}


//接收到对方随机值进入
static void prov_random(const u8_t *data)
{
uint8_t conf_verify[16] = {0};
//双方随机值比较 不一样才对
if (!memcmp(data, link.rand, 16)) {
BT_ERR("Random value is identical to ours, rejecting.");
goto fail;
}
//通过未配网设备发来的随机数生成确认值
if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) {
BT_ERR("Failed to calculate confirmation verification");
goto fail;
}
//拿未配网设备发来的确认值和配网器通过随机数生成的确认值是否相等
if (memcmp(conf_verify, link.conf, 16)) {
BT_ERR("Invalid confirmation value");
BT_INFO("Received: %s", bt_hex(link.conf, 16));
BT_INFO("Calculated: %s", bt_hex(conf_verify, 16));
goto fail;
}



/** After provisioner receives provisioning random from device,
* and successfully check the confirmation, the following
* should be done:
* 1. bt_mesh_calloc memory for prov_salt
* 2. calculate prov_salt
* 3. prepare provisioning data and send
*/
//生成配网佐料 -> link.prov_salt
if (bt_mesh_prov_salt(link.conf_salt, link.rand, data,link.prov_salt)) {
BT_ERR("Failed to generate ProvisioningSalt");
goto fail;
}

BT_INFO("ProvisioningSalt: %s", bt_hex(link.prov_salt, 16));
//发送配网数据
send_prov_data();
return;

fail:
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
return;
}

static void prov_data(const u8_t *data)
{
printf("prov_data\r\n");
}
//收到配网完成进入
static void prov_complete(const u8_t *data)
{
uint8_t device_key[16] = {0};
uint16_t net_idx = 0U;
//uint16_t index = 0U;
int err = 0;
//int i;


//设备密钥
err = bt_mesh_dev_key(link.dhkey, link.prov_salt, device_key);
if (err) {
BT_ERR("Failed to generate device key");
close_link(PROV_ERR_NONE, CLOSE_REASON_FAILED);
return;
}


net_idx = prov_ctx.curr_net_idx;

//保存节点数据
/*
err = bt_mesh_provisioner_provision(&link[idx].addr, link[idx].uuid, link[idx].oob_info,
link[idx].unicast_addr, link[idx].element_num, net_idx,
link[idx].ki_flags, link[idx].iv_index, device_key, &index);


if (prov->prov_complete) {
prov->prov_complete(index, link[idx].uuid, link[idx].unicast_addr,
link[idx].element_num, net_idx);
}


for (i = 0; i < ARRAY_SIZE(unprov_dev); i++) {
if (!memcmp(unprov_dev[i].uuid, link[idx].uuid, 16) &&
(unprov_dev[i].flags & RM_AFTER_PROV)) {
memset(&unprov_dev[i], 0, sizeof(struct unprov_dev_queue));
break;
}
}
*/
close_link(PROV_ERR_NONE, CLOSE_REASON_SUCCESS);
}

static void prov_failed(const u8_t *data)
{
BT_WARN("Error: 0x%02x", data[0]);
close_link(PROV_ERR_NONE, CLOSE_REASON_FAILED);
}

static const struct {
void (*func)(const u8_t *data);
u16_t len;
} prov_handlers[] = {
{ prov_invite, 1 },
{ prov_capabilities, 11 },
{ prov_start, 5, },
{ prov_pub_key, 64 },
{ prov_input_complete, 0 },
{ prov_confirm, 16 },
{ prov_random, 16 },
{ prov_data, 33 },
{ prov_complete, 0 },
{ prov_failed, 1 },
};

static void close_link(u8_t err, u8_t reason)
{
//PROV_D(", 10--->0");
BT_INFO("close link 10--->0");
#if defined(CONFIG_BT_MESH_PB_GATT)
if (link.conn) {
bt_mesh_pb_gatt_close(link.conn);
return;
}
#endif

#if defined(CONFIG_BT_MESH_PB_ADV)
if (err) {
prov_send_fail_msg(err);
}

link.rx.seg = 0;
bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
#endif

atomic_clear_bit(link.flags, LINK_ACTIVE);

/* Disable Attention Timer if it was set */
if (link.conf_inputs[0]) {
bt_mesh_attention(NULL, 0);
}
}

#if defined(CONFIG_BT_MESH_PB_ADV)
static void prov_retransmit(struct k_work *work)
{
int i;

printf("");

if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
BT_WARN("Link not active");
return;
}

if (k_uptime_get() - link.tx.start > TRANSACTION_TIMEOUT) {
BT_WARN("Giving up transaction");
reset_link();
return;
}

if (link.send_link_close & BIT(0)) {
//uint8_t reason = (link.send_link_close >> 1) & BIT_MASK(2);
uint16_t count = (link.send_link_close >> 3);
if (count >= 2) {
reset_link();
return;
}
link.send_link_close += BIT(3);
}

for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
struct net_buf *buf = link.tx.buf[i];

if (!buf) {
break;
}

if (BT_MESH_ADV(buf)->busy) {
continue;
}

printf("%u bytes: %s\r\n", buf->len, bt_hex(buf->data, buf->len));

if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
bt_mesh_adv_send(buf, NULL, NULL);
} else {
bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
}

}
}



static void link_ack(struct prov_rx *rx, struct net_buf_simple *buf)
{

if (buf->len) {
BT_ERR("Invalid Link ACK length %d", buf->len);
close_link(PROV_ERR_NVAL_PDU, CLOSE_REASON_FAILED);
return;
}

if (link.expect == PROV_CAPABILITIES) {
BT_INFO("Link ACK is already received");
return;
}
//发送邀请
send_invite();
}

static void link_close(struct prov_rx *rx, struct net_buf_simple *buf)
{
//printf("len %u", buf->len);
printf("关闭连接\r\n");
reset_link();
}

static void gen_prov_ctl(struct prov_rx *rx, struct net_buf_simple *buf)
{
BT_INFO("配网器接收到: op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->len);

switch (BEARER_CTL(rx->gpc)) {
case LINK_OPEN:

break;
case LINK_ACK:
if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
return;
}

link_ack(rx, buf);
break;
case LINK_CLOSE:
if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
return;
}

link_close(rx, buf);
break;
default:
BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc));
return;
}
}

static void prov_msg_recv(void)
{
u8_t type = link.rx.buf->data[0];

BT_INFO("type 0x%02x len %u", type, link.rx.buf->len);
BT_INFO("data %s", bt_hex(link.rx.buf->data, link.rx.buf->len));

if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
BT_ERR("Incorrect FCS");
return;
}

if (type != PROV_FAILED && type != link.expect) {
BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
/* added for NODE/PROV/BV-10-C in PTS 7.4.1*/
link.expect = PROV_FAILED;
return;
}

if (type >= ARRAY_SIZE(prov_handlers)) {
BT_ERR("Unknown provisioning PDU type 0x%02x", type);
close_link(PROV_ERR_NVAL_PDU, CLOSE_REASON_FAILED);
return;
}

if (1 + prov_handlers[type].len != link.rx.buf->len) {
BT_ERR("Invalid length %u for type 0x%02x",
link.rx.buf->len, type);
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
return;
}

gen_prov_ack_send(link.rx.id);
link.rx.prev_id = link.rx.id;
link.rx.id = 0;


prov_handlers[type].func(&link.rx.buf->data[1]);
}

static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
{
u8_t seg = CONT_SEG_INDEX(rx->gpc);

//printf("分包len %u, seg_index %u\r\n", buf->len, seg);

if (!link.rx.seg && link.rx.prev_id == rx->xact_id) {
BT_DBG("Resending ack");
gen_prov_ack_send(rx->xact_id);
return;
}

if (rx->xact_id != link.rx.id) {
BT_WARN("Data for unknown transaction (%u != %u)",
rx->xact_id, link.rx.id);
return;
}

if (seg > link.rx.last_seg) {
BT_ERR("Invalid segment index %u", seg);
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
return;
} else if (seg == link.rx.last_seg) {
u8_t expect_len;

expect_len = (link.rx.buf->len - 20 -
(23 * (link.rx.last_seg - 1)));
if (expect_len != buf->len) {
BT_ERR("Incorrect last seg len: %u != %u",
expect_len, buf->len);
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
return;
}
}

if (!(link.rx.seg & MESH_BIT(seg))) {
BT_DBG("Ignoring already received segment");
return;
}

memcpy(XACT_SEG_DATA(seg), buf->data, buf->len);
XACT_SEG_RECV(seg);

if (!link.rx.seg) {
prov_msg_recv();
}
}

static void gen_prov_ack(struct prov_rx *rx, struct net_buf_simple *buf)
{
//printf("应答包\r\n");
uint8_t ack_type = 0U, pub_key_oob = 0U;

BT_DBG("len %u", buf->len);

if (!link.tx.buf[0]) {
return;
}

if (!link.tx.id) {
return;
}

if (rx->xact_id == (link.tx.id - 1)) {
prov_clear_tx();

ack_type = link.expect_ack_for;
switch (ack_type) {
case PROV_START:
pub_key_oob = link.conf_inputs[13];
send_pub_key(pub_key_oob);
break;
case PROV_PUB_KEY:
prov_gen_dh_key();
break;
default:
break;
}
link.expect_ack_for = 0x00;
}
}

static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
{
if (link.rx.seg) {
BT_DBG("Got Start while there are unreceived segments");
return;
}

if (link.rx.prev_id == rx->xact_id) {
BT_DBG("Resending ack");
gen_prov_ack_send(rx->xact_id);
return;
}

link.rx.buf->len = net_buf_simple_pull_be16(buf);
link.rx.id = rx->xact_id;
link.rx.fcs = net_buf_simple_pull_u8(buf);

BT_INFO("len %u last_seg %u total_len %u fcs 0x%02x", buf->len,
START_LAST_SEG(rx->gpc), link.rx.buf->len, link.rx.fcs);

if (link.rx.buf->len < 1) {
BT_ERR("Ignoring zero-length provisioning PDU");
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
return;
}

if (link.rx.buf->len > link.rx.buf->size) {
BT_ERR("Too large provisioning PDU (%u bytes)(%u size)",
link.rx.buf->len,link.rx.buf->size);
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
return;
}

if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->len <= 20) {
BT_ERR("Too small total length for multi-segment PDU");
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
return;
}

link.rx.seg = (1 << (START_LAST_SEG(rx->gpc) + 1)) - 1;
link.rx.last_seg = START_LAST_SEG(rx->gpc);
memcpy(link.rx.buf->data, buf->data, buf->len);
XACT_SEG_RECV(0);

if (!link.rx.seg) {
prov_msg_recv();
}
}

static const struct {
void (*const func)(struct prov_rx *rx, struct net_buf_simple *buf);
const u8_t require_link;
const u8_t min_len;
} gen_prov[] = {
{ gen_prov_start, true, 3 },
{ gen_prov_ack, true, 0 },
{ gen_prov_cont, true, 0 },
{ gen_prov_ctl, true, 0 },
};

static void gen_prov_recv(struct prov_rx *rx, struct net_buf_simple *buf)
{
//printf("GPCF(rx->gpc) = %d\r\n",GPCF(rx->gpc));
if (buf->len < gen_prov[GPCF(rx->gpc)].min_len) {
BT_ERR("Too short GPC message type %u", GPCF(rx->gpc));
return;
}

if (!atomic_test_bit(link.flags, LINK_ACTIVE) &&
gen_prov[GPCF(rx->gpc)].require_link) {
//BT_INFO("Ignoring message that requires active link");
return;
}

gen_prov[GPCF(rx->gpc)].func(rx, buf);
}

void bt_mesh_prov_adv_recv(struct net_buf_simple *buf)
{
struct prov_rx rx;

rx.link_id = net_buf_simple_pull_be32(buf);


if (buf->len < 2) {
BT_WARN("Too short provisioning packet (len %u)", buf->len);
close_link(PROV_ERR_NVAL_PDU, CLOSE_REASON_FAILED);
return;
}

rx.xact_id = net_buf_simple_pull_u8(buf);
rx.gpc = net_buf_simple_pull_u8(buf);

gen_prov_recv(&rx, buf);

}
#endif /* CONFIG_BT_MESH_PB_ADV */


int bt_prov_active(void)
{
return atomic_test_bit(link.flags, LINK_ACTIVE);
}

void bt_mesh_prov_reset(void)
{
if (prov->reset) {
prov->reset();
}
}

int net_key_init(void)
{

//初始化设备密钥,这里用三元组的 secret 作为配网器设备密钥
stringtohex(DEFAULT_SECRET, provisoner_devkey, 16);
bt_mesh_rand(&g_netkey.key[0],16);
seq = 0;
addr = 0;
g_netkey.net_index = 0;
g_netkey.flag = 0;
g_netkey.ivi = 0;
BT_INFO("g_netkey:%s", bt_hex(g_netkey.key,16));
bt_mesh_provision(g_netkey.key, g_netkey.net_index, g_netkey.flag, g_netkey.ivi, seq, addr, provisoner_devkey);


/* Dynamically added appkey & netkey will use these key_idx */
//下一个APP索引和NET索引
bt_mesh.p_app_idx_next = 0x0000;
bt_mesh.p_net_idx_next = 0x0001;

//BT_INFO("netkey:%s", bt_hex(netkey.key,16));
//初始化应用密钥
bt_mesh_rand(&appkey.key[0],16);
appkey.net_index = 0;
appkey.key_index = 0;
appkey.flag = 0;

extern void genie_appkey_register(u16_t net_idx, u16_t app_idx, const u8_t val[16], bool update);
genie_appkey_register(appkey.net_index, appkey.key_index, appkey.key, appkey.flag);
BT_INFO("appkey:%s", bt_hex(appkey.key,16));

return 0;
}


int is_provisioning(void)
{

return atomic_test_bit(link.flags, LINK_ACTIVE);
}
//通过网络索引获取网络密钥
struct bt_mesh_subnet *bt_mesh_provisioner_subnet_get(uint16_t net_idx)
{
struct bt_mesh_subnet *sub = NULL;
int i;

BT_DBG("%s", __func__);

if (net_idx == BLE_MESH_KEY_ANY) {
return bt_mesh.p_sub[0];
}

for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
sub = bt_mesh.p_sub[i];
if (sub && sub->net_idx == net_idx) {
return sub;
}
}

return NULL;
}
//初始化配网器配网信息
int bt_mesh_provisioner_init_prov_info(void)
{
if (prov_ctx.primary_addr == BLE_MESH_ADDR_UNASSIGNED) {
/* If unicast address of primary element of Provisioner has not been set
* before, then the following initialization procedure will be used.
*/
if (prov == NULL) {
BT_ERR("No provisioning context provided");
return -EINVAL;
}

if (!BLE_MESH_ADDR_IS_UNICAST(prov->prov_unicast_addr) ||
!BLE_MESH_ADDR_IS_UNICAST(prov->prov_start_address)) {
BT_ERR("Invalid address, own 0x%04x, start 0x%04x",
prov->prov_unicast_addr, prov->prov_start_address);
return -EINVAL;
}
//获取成分数据
const struct bt_mesh_comp *comp = bt_mesh_comp_get();
if (!comp) {
BT_ERR("Invalid composition data");
return -EINVAL;
}

if (prov->prov_unicast_addr + comp->elem_count > prov->prov_start_address) {
BT_WARN("Too small start address 0x%04x, update to 0x%04x",
prov->prov_start_address, prov->prov_unicast_addr + comp->elem_count);
prov_ctx.curr_alloc_addr = prov->prov_unicast_addr + comp->elem_count;
} else {
prov_ctx.curr_alloc_addr = prov->prov_start_address;
}

/* Update primary element address with the initialized value here. */
prov_ctx.primary_addr = prov->prov_unicast_addr;

//if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
// bt_mesh_store_prov_info(prov_ctx.primary_addr, prov_ctx.curr_alloc_addr);
//}
}

prov_ctx.curr_net_idx = BLE_MESH_KEY_PRIMARY;
struct bt_mesh_subnet *sub = bt_mesh_provisioner_subnet_get(BLE_MESH_KEY_PRIMARY);
prov_ctx.curr_flags = bt_mesh_net_flags(sub);
prov_ctx.curr_iv_index = bt_mesh.iv_index;

return 0;
}
//配网器初始化
int bt_mesh_provisioner_prov_init(const struct bt_mesh_prov *prov_info)
{
BT_INFO("配网器初始化");
const uint8_t *key = NULL;

if (!prov_info) {
BT_ERR("No provisioning context provided");
return -EINVAL;
}
//获得公钥
key = bt_mesh_pub_key_get();
if (!key) {
BT_ERR("Failed to generate Public Key");
return -EIO;
}

prov = prov_info;

prov_ctx.primary_addr = BLE_MESH_ADDR_UNASSIGNED;

if (prov->static_val && prov->static_val_len) {
prov_ctx.static_oob_len = prov->static_val_len > 16 ? 16 : prov->static_val_len;
memcpy(prov_ctx.static_oob_val, prov->static_val, prov_ctx.static_oob_len);
}
//网络密钥初始化
net_key_init();
//配网器配网信息初始化
bt_mesh_provisioner_init_prov_info();
#if defined(CONFIG_BT_MESH_PB_ADV)

//struct prov_adv_buf *adv = &adv_buf;
//adv->buf.size = ADV_BUF_SIZE;
//adv->buf.__buf = adv_buf_data + ADV_BUF_SIZE;
//初始化重传计数器
k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
//初始化上次接收ID和接收缓存
link.rx.prev_id = XACT_NVAL;
link.rx.buf = bt_mesh_pba_get_buf();

#endif/*CONFIG_BT_MESH_PB_ADV*/


return 0;
}
#endif

四、测试现象

上面的代码可能还是有bug,而且仅仅是实现了配网器功能,没有自组网,没有任何控制功能:

image-20240107111752251

反正看打印信息,是存在配网器对未配网设备进行配网的过程的,但是最后好像是没有配成功,因为我看到右侧的配网器一直能发现未配网设备,左侧的未配网设备也是一直和配网器配网,最终出现内存不足的情况,具体的bug没有去查,因为毕竟目前还是在做嵌入式开发,蓝牙这块暂时没有相关的需求,这几篇笔记也仅仅是想简单了解一下蓝牙,后续有需求再深入研究吧。