Mesh Provisioner

Mesh Provisioner Sample 展示了如何使用 Mesh Provisioner 以及如何开发基于 Mesh Provisioner 的应用程序。

Mesh Provisioner 作为 mesh 网络的管理员,主要功能如下:

  • Mesh Device 入网时分发地址和密钥。

  • 管理各个节点。

环境需求

该示例支持以下开发工具包:

环境需求

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

该示例需要还需要另一个设备或多个设备运行 Mesh Device,作为网络中的节点。

更多要求,请参考 快速入门

硬件连线

请参考 快速入门 中的 EVB接口和模块

配置选项

  • 关于 LE 所需要的配置请查看 samples\bluetooth\mesh\mesh_provisioner\src\app_flags.h

  • 关于 Mesh 所需要的配置请查看 samples\bluetooth\mesh\mesh_provisioner\src\app_mesh_flags.h

编译和下载

该示例可以在 SDK 文件夹中找到:

Project file: samples\bluetooth\mesh\mesh_provisioner\proj\rtl87x2g\mdk

Project file: samples\bluetooth\mesh\mesh_provisioner\proj\rtl87x2g\gcc

编译和运行该示例请遵循以下步骤:

  1. 打开项目文件。

  2. 编译目标文件, 请参考 快速入门编译APP Image 中列出的步骤。

  3. 编译成功后,目录 samples\bluetooth\mesh\mesh_provisioner\proj\rtl87x2g\mdk\bin 下 会生成文件 app_MP_sdk_xxx.bin

  4. 下载 bin 到 EVB 板,请参考 快速入门MP Tool 中列出的步骤。

  5. 在 EVB 板上按下 reset 按钮,程序将开始运行。

测试验证

将示例工程烧录到 EVB 板后,可以使用另一个开发板运行 Mesh Device 工程相互进行测试。

准备阶段

  1. 准备一个 Mesh Provisioner,如有必要请使用 Debug Analyzer 工具获取日志。

  2. 准备一个或者多个 Mesh Device,如有必要请使用 Debug Analyzer 工具获取日志。

测试阶段

本节主要介绍 Mesh Provisioner 的测试部分和相关 User Command 的用法,方便用户前期学习,后期调试。 有关 User Command 的详细信息,请参阅 User Command Interface

用户可以使用任何串口助手软件与 EVB 板进行交互。有关 Mesh Provisioner 的详细用户命令,请参阅 mesh_cmd.cprovisioner_cmd.cclient_cmd.c

Provisioning

Provisioner 可以收集附近节点信息并显示出来,通过 dis 命令开关。

Mesh Device 信息收集

Step

Provisioner

说明

1

dis 1

显示周边 mesh device

2

dis 0

搜集到目标 device 的信息后(device UUID 或者 Bluetooth address),关闭搜索

Device 会在 Provisioning 中获得地址和网络密钥,成功后即加入网络,可以进行 mesh 通信。 使用 transport 层 ping 功能,即 tping 命令,进行网络层测试, 可以与网络中的任意节点互相发送和接收 transport 层的 ping/pong 消息。 Provisioner 也可以使用 configuration client 和指定的 device 进行通信,例如获取 composition data page 0。

PB-ADV Provisioning

Step

Provisioner

Device

说明

1

pbadvcon 000102030405

060708090a0b0c0d0e0f

发起对 UUID 为 000102030405060708090a0b0c0d0e0f 的设备的连接,

等待提示 PB-ADV bearer 是否成功建立

2

prov

等待提示 provisioning 流程结束

3

ls

查看 device 是否成功获得地址和密钥,假定地址为 0x0100

4

tping xffff

测试是否能互相进行网络层通信

5

cdg x100

获取 device 0x100 的 composition data page 0

PB-GATT Provisioning

Step

Provisioner

Device

说明

1

con ff0011223344

与对端蓝牙地址 0xff0011223344 的设备建立 LE link,等待提示成功建立

2

provdis

查询 provision service

3

provcmd 0 1

使能 provision CCCD

4

prov

等待提示 provisioning 流程结束

5

ls

查看 device 是否成功获得地址和密钥

6

tping xffff

测试是否能互相进行网络层通信

7

cdg x100

获取 device 0x100 的 composition data page 0

已经被 Provisioning 的 device,可以通过 nr 命令恢复到 Unprovisioned 状态。

密钥管理

已经被 Provisioning 的设备可以被 configuration client 配置。 例如添加 AppKey、绑定 AppKey 到 ping model 上。 然后 ping model 就可以发送 model 层的 ping 消息。

密钥管理

Step

Provisioner

Device

说明

1

aka x100 0 0

给目标节点 0x100 添加 AppKey 0,并绑定到 NetKey 0 上

2

ls

查看 device 是否成功添加 AppKey 0

3

mab x100 0 x5d 0

给目标节点 0x100 的第 0 个 element 的 model id 为 0x5d 的

ping model 绑定 AppKey 0

4

ls

查看 device 的 ping model 是否成功绑定 AppKey 0

5

ping xffff 3

测试 ping model control model

订阅配置

Provisioner 可以管理 device 的 model 订阅地址。 例如为 ping model 添加订阅地址。

Model 订阅配置

Step

Provisioner

Device

说明

1

msa x100 0 x5d xc000

给目标节点 0x100 的第 0 个 element 的 model id 为 0x5d 的

ping model 添加 subscribe address 0xc000

2

ls

查看 device 的 model 是否成功添加 subscribe address 0xc000

3

ping xc000 3

测试 device 是否订阅 0xc000

Friendship

已经被 Provisioning 的 low power node 设备可以开始建立 friendship。

Friendship

Step

Friend Node

Low Power Node

说明

1

fninit 1 5

lpninit 1

初始化 friend node,支持与 1 个 LPN node 建立 friendship 且 queue 大小为 5,

初始化 LPN node,支持与 1 个 friend node 建立 friendship

2

lpnreq 0 0

等待提示 friendship 建立结果

3

tping xffff 3

发现 tping 耗时会变长

Remote Provisioning

已经被 Provisioning 的 remote provisioning server 设备可以帮助收集其附近节点信息并传递给 remote provisioning client。

RPR 信息收集

Step

Provisioner

RPR server

说明

1

rpsst x100 10 20

指示 RPR server 搜索其周边 mesh device

2

rpssp x100 0

搜集到目标 device 的信息后(device UUID 或者 Bluetooth address),

指示其关闭搜索

Remote Provisioning

Step

Provisioner

RPR server

说明

1

rplop x100 0

x00010203040506070

8090a0b0c0d0e0f 10

指示 RPR server 发起对 000102030405060708090a0b0c0d0e0f 的

连接,等待 RPR server 提示是否成功建立

2

prov

等待提示 provisioning 流程结束

3

ls

查看 device 是否成功获得地址和密钥

4

tping xffff

测试是否能互相进行网络层通信

5

cdg x101

获取 device 0x101 的 composition data page 0

Device Key Refresh

Step

Provisioner

RPR server

说明

1

rplod x100 0 0

发起对 RPR server 的连接,并指示该程序为 device key refresh

2

rprdk

启动 refresh device key 流程

Node Address Refresh

Step

Provisioner

RPR server

说明

1

rplod x100 0 1

发起对 RPR server 的连接,并指示该程序为 node address refresh

2

rprna x103

启动 refresh node address 流程

Composition Data Refresh

Step

Provisioner

RPR server

说明

1

pids x21

为 composition page 128 设置新数据

2

rplod x103 0 2

发起对 RPR server 的连接,并指示该程序为 composition data refresh

3

rprcd

启动 refresh composition data 流程

Directed Forwarding

已经被 Provisioning 的设备想要使用 directed forwarding 功能可以参考以下流程,需要先配置 directed forwarding control state,将已经配置好 AppKey 的 model 的 publish policy 方式设置为 directed forwarding。

Directed Forwarding

Step

Provisioner

Device

说明

1

dcs x100 0 0 1 1 1 1 1

使能 device 的 directed forwarding control state

2

dpps x100 0 1 x100 x5d

将 ping model 的 publish policy 设置为 directed forwarding 方式

3

ping x1 3

ping 的同时会自动触发 path discovery 流程

4

dfpdis 0 x1 0 0

也可以主动触发 path discovery 流程

5

dfpsol 0 x100

主动触发 path solicitation 流程

6

dfpdupt 0 x100

x120 1

主动触发 path dependents update 流程

7

fta x100 0 0 1 1 x200

2 x300 2 1 1

通过 directed forwarding model 添加 fixed path

8

ftda x100 0 0 x200 x300

1 1 x700 10 x220 1

通过 directed forwarding model 添加 fixed path 的 dependents 信息

Subnet Bridge

节点同时处于 net 0 (NetKey index 为 0)和 net 1 (NetKey index 为 1)网络时, subnet bridge client 可以通过 subnet bridge model 为节点配置 subnet bridge table, 配置后节点可以将 net 0 的 message 转发到 net 1。 注意,桥接的消息在转发时会使用对应的 NetKey 加密,但是 AppKey 不会改变, 发送与接收消息的节点需要 AppKey 一致才可以正确解密 Access layer 的数据。

Subnet Bridge

Step

Provisioner

Device

说明

1

bta x100 0 1 0 1 x102 x103

为 0x100 节点配置 subnet bridge table, 0x102 (net 0) –> 0x103 (net 1)

Binary Large Object Transfer

已经被 Provisioning 的设备可以参考以下流程使用 BLOB models 进行传输。

BLOB Transfer

Step

Provisioner

Device

说明

1

mab x100 0 x1400ffff 0

为 0x100 节点 blob transfer server 添加 AppKey 0

2

btsi

0x1100000000000011

10 3

初始化 blob transfer server

3

btccr 0 2 1 x100

启动 capability retrieve 流程

4

btcbt x100 0 2

0x1100000000000011

2000 1 1 0 1 x100

启动 blob transfer 流程

5

btctc

0x1100000000000011

1 x100

取消 blob transfer 流程

Device Firmware Update

请参考 Bluetooth Mesh OTA。

代码介绍

本章的主要目的是帮助用户熟悉 Mesh Provisioner 相关的开发流程。本章将按照以下几个部分进行介绍:

源码路径

  • Project directory: sdk\samples\bluetooth\mesh\mesh_provisioner\proj

  • Source code directory: sdk\samples\bluetooth\mesh\mesh_provisioner\src

Mesh Provisioner 应用程序项目中的源文件结构如下所示。

└── Project: mesh_provisioner
    └── secure_only_app
        ├── Device                           includes startup code
        ├── CMSE Library                     Non-secure callable lib
        ├── lib                              includes all binary symbol files that user application is built on
            ├── ROM_NS.lib
            ├── rtl87x2g_sdk.lib
            ├── rtl87x2g_io.lib
            ├── gap_utils.lib
            ├── mesh_prov.lib
            └── lowerstack.lib
        ├── io                               includes all peripheral drivers and module code used by the application
        ├── profile                          includes LE profiles or services used by the application
        ├── model                            includes mesh models used by the application
        ├── dfu                              includes dfu source code used by the application
        └── APP                              includes the mesh_provisioner user application implementation
            ├── main.c                       includes the io, os, platform, le host and mesh stack initialization
            ├── app_task.c                   includes app task initialization and main loop
            ├── provisioner_app.c            includes provisioner application code
            ├── mesh_sdk.c                   includes mesh sdk version record
            ├── mesh_cmd.c                   includes mesh user commands
            ├── provisioner_cmd.c            includes provisioner user commands
            ├── test_cmd.c                   includes test user commands
            ├── client_cmd.c                 includes client user commands
            ├── delay_msg_rsp.c              includes delay message response
            ├── ping_app.c                   includes ping model application code
            ├── generic_client_app.c         includes generic client model application code
            ├── light_client_app.c           includes light client model application code
            ├── datatrans_client_app.c       includes datatrans client model application code
            ├── rmt_prov_client_app.c        includes remote provisioning client model application code
            ├── blob_client_app.c            includes blob client model application code
            ├── dfu_distributor_app.c        includes dfu distributor application code
            └── dfu_initiator_app.c          includes dfu Initiator application code

其中,mesh_prov.lib 根据 Mesh Protocol 版本分为 V1.0V1.1, 用户可以根据所需 feature 选择合适的 lib。

Library file: subsys\bluetooth\mesh\chips\rtl87x2g\lib\v1_0\mdk\mesh_prov.lib, subsys\bluetooth\mesh\chips\rtl87x2g\lib\v1_0\gcc\mesh_prov.a

Header file: subsys\bluetooth\mesh\chips\rtl87x2g\lib\v1_0\mesh_config.h

Library file: subsys\bluetooth\mesh\chips\rtl87x2g\lib\v1_1\mdk\mesh_prov.lib, subsys\bluetooth\mesh\chips\rtl87x2g\lib\v1_1\gcc\mesh_prov.a

Header file: subsys\bluetooth\mesh\chips\rtl87x2g\lib\v1_1\mesh_config.h

初始化

当 EVB 板 reset 时,main() 函数会执行,初始化流程如下:

int main(void)
{
    extern uint32_t random_seed_value;
    srand(random_seed_value);
    board_init();
    driver_init();
    le_gap_init(APP_MAX_LINKS);
    gap_lib_init();
    app_le_gap_init();
    app_le_profile_init();
    mesh_stack_init();
    pwr_mgr_init();
    task_init();
    os_sched_start();

    return 0;
}

相比于网络中其他节点,Provisioner 在初始化时就需要为自己分配 Mesh 地址以及部分 Keys,示例如下。

void mesh_stack_init(void)
{
    ......
    /** init mesh stack */
    mesh_init();

    /** configure provisioner */
    mesh_node.node_state = PROV_NODE;
    mesh_node.unicast_addr = bt_addr[0] % 99 + 1;
    const uint8_t net_key[] = MESH_NET_KEY;
    const uint8_t net_key1[] = MESH_NET_KEY1;
    const uint8_t app_key[] = MESH_APP_KEY;
    const uint8_t app_key1[] = MESH_APP_KEY1;
    uint16_t net_key_index = net_key_add(0, net_key);
    app_key_add(net_key_index, 0, app_key);
    uint8_t net_key_index1 = net_key_add(1, net_key1);
    app_key_add(net_key_index1, 1, app_key1);
    mesh_model_bind_all_key();
    ......
}

os_sched_start() 调用之后, app_main_task() 会得到调度,Mesh message 相关的处理如下:

#define EVENT_MESH                    0x80
......

void app_main_task(void *p_param)
{
    ......
    mesh_start(EVENT_MESH, EVENT_IO_TO_APP, evt_queue_handle, io_queue_handle);
    ......

    while (true)
    {
        if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true)
        {
            if (event == EVENT_IO_TO_APP)
            {
                ......
            }
            else if (event == EVENT_MESH)
            {
                mesh_inner_msg_handle(event);
            }
            else
            {
                ......
            }
        }
    }
}

网络管理

Provisioner 做为网络管理员,需要对加入网络中的所有节点进行管理, 包括 Provisioning 流程,Configuration models 的配置过程,以及后续的消息交互。