3. SIG Mesh DEMO使用说明

3.1. 概述

遵守蓝牙SIG Mesh协议,基于蓝牙5 ble实现网内节点间通讯,具体功能如下:

  • 支持 NLC profile;

  • 支持 DFU 远程升级(暂支持bd19/AC632N);

  • 全节点类型支持(Relay/Proxy/Friend/Low Power);

  • 支持以PB-GATT方式入网(手机APP配网,支持”nRF Mesh”安卓和苹果最新版本);

  • 支持以PB-ADV方式入网(“天猫精灵”配网);

  • 支持设备上电自配网(不用配网就可实现设备在同一网内,支持加密key自定义);

  • 节点relay/beacon功能可修改;

  • 节点地址自定义/信息断电保存/Reset为未配网状态;

  • 节点发布(Publish)和订阅(Subscribe)地址可修改;

  • 支持蓝牙SIG既有Models和用户自定义Vendor Models。

    支持的板级: br25、bd19、br34、br23

    支持的芯片: AC636N、AC632N、AC638N、AC635N

3.2. 工程配置

代码工程:apps/mesh/board/bd19/AC632N_mesh.cbp

▾ mesh/

   ▾ api/

       feature_correct.h

       mesh_config_common.c //mesh部分参数的定义

       model_api.c //model应用函数合集

       model_api.h //demo应用定义合集

   ▾ board/

     ▾ bd19/

         board_ac632n_demo.c

         board_ac632n_demo_cfg.h

         board_ac632n_demo_global_build_cfg.h

         board_ac632n_distributor.c

         board_ac632n_distributor_cfg.h

         board_ac632n_distributor_global_build_cfg.h

         board_ac632n_target_node.c

         board_ac632n_target_node_cfg.h

         board_ac632n_target_node_global_build_cfg.h

         board_config.h

   ▾ examples/

       AliGenie_fan.c

       AliGenie_light.c

       AliGenie_socket.c

       ambient_light_sensor_nlc.c

       basic_lightness_ctrl_nlc.c

       basic_scene_selector_nlc.c

       dfu_distributor_demo.c

       dfu_target_demo.c

       dimming_control_nlc.c

       energy_monitor_nlc.c

       generic_onoff_client.c

       generic_onoff_server.c

       light_lightness_server.c

       light_occupacy_observer_nlc.c

       light_occupacy_sensor_nlc.c

       provisionee.c

       provisioner.c

       tencent_mesh.c

       TUYA_light.c

       vendor_client.c

       vendor_server.c

   ▾ mesh_dfu/

       mesh_dfu_app_cmd_protocol.c

       mesh_distributor_loader.c

       mesh_target_node_ota.c

在api/model_api.h下,通过配置CONFIG_MESH_MODEL选择相应例子,SDK提供了21个应用实例。默认选择SIG_MESH_GENERIC_ONOFF_CLIENT,即位于examples/generic_onoff_client.c下的例子。

//< Detail in "MshPRT_v1.1"
#define SIG_MESH_GENERIC_ONOFF_CLIENT       0  // examples/generic_onoff_client.c
#define SIG_MESH_GENERIC_ONOFF_SERVER       1  // examples/generic_onoff_server.c
#define SIG_MESH_VENDOR_CLIENT              2  // examples/vendor_client.c
#define SIG_MESH_VENDOR_SERVER              3  // examples/vendor_server.c
#define SIG_MESH_ALIGENIE_LIGHT             4  // examples/AliGenie_light.c
#define SIG_MESH_ALIGENIE_SOCKET            5  // examples/AliGenie_socket.c
#define SIG_MESH_ALIGENIE_FAN               6  // examples/AliGenie_fan.c
#define SIG_MESH_LIGHT_LIGHTNESS_SERVER     7  // examples/light_lightness_server.c
#define SIG_MESH_TUYA_LIGHT                 8  // examples/TUYA_light.c
#define SIG_MESH_TENCENT_MESH               9  // examples/tecent_mesh.c
#define SIG_MESH_PROVISIONER                10 // examples/provisioner.c
#define SIG_MESH_PROVISIONEE                11 // examples/provisionee.c

#define SIG_MESH_OCCUPACY_SENSOR_NLC        12 // examples/light_occupacy_sensor_nlc.c
#define SIG_MESH_SENSOR_OBSEVER_NLC         13 // examples/light_occupacy_observer_nlc.c
#define SIG_MESH_BASIC_LIGHTNESS_CTRL_NLC   14 // examples/basic_lightness_crtl_nlc.c
#define SIG_MESH_DIMMING_CONTROL_NLC        15 // examples/dimming_control_nlc.c
#define SIG_MESH_ENERGY_MONITOR_NLC         16 // examples/energy_monitor_nlc.c
#define SIG_MESH_BASIC_SCENE_SELECTOR_NLC   17 // examples/basic_scene_selector_nlc.c
#define SIG_MESH_AMBIENT_LIGHT_SENSOR_NLC   18 // examples/ambient_light_sensor_nlc.c
#define SIG_MESH_DFU_DISTRIBUTOR_DEMO       19 // examples/dfu_distributor_demo.c
#define SIG_MESH_DFU_TARGET_DEMO            20 // examples/dfu_target_demo.c
// more...

//< Config which example will use in <examples>
#define CONFIG_MESH_MODEL                   SIG_MESH_GENERIC_ONOFF_CLIENT

3.2.1. Mesh配置

在api/mesh_config_common.c下,可以自由配置网络和节点特性,例如LPN/Friend节点特性、Proxy下配网前后广播interval、节点信息传递时广播interval和duration等。

如下举例了节点信息传递时广播interval和duration的配置,和PB-GATT下配网前后广播interval的配置。

/**
* @brief Config adv bearer hardware param when node send messages
*/
/*-----------------------------------------------------------*/
const u16 config_bt_mesh_node_msg_adv_interval = ADV_SCAN_UNIT(10); // unit: ms
const u16 config_bt_mesh_node_msg_adv_duration = 50; // unit: ms

/**
* @brief Config proxy connectable adv hardware param
*/
/*-----------------------------------------------------------*/
const u16 config_bt_mesh_proxy_unprovision_adv_interval = ADV_SCAN_UNIT(30); // unit: ms
const u16 config_bt_mesh_proxy_pre_node_adv_interval = ADV_SCAN_UNIT(10); // unit: ms
_WEAK_
const u16 config_bt_mesh_proxy_node_adv_interval = ADV_SCAN_UNIT(300); // unit: ms
注意: 在常量前加上"_WEAK_"的声明, 代表这个常量可以在其它文件重定义. 如果想某一配置私有化到某一实例, 应该在该文件下在该配置前加上"_WEAK_"声明, 并在所在实例文件里重定义该常量配置.

3.2.2. board配置

在board/xxxx/board_config.h下,可以根据不同封装选择不同board,以AC63X为例:

1、默认选择CONFIG_BOARD_AC632X_DEMO作为目标板:

/**
*  板级配置选择
*/
#define CONFIG_BOARD_AC632N_DEMO

2、应用SIG_MESH_DFU_DISTRIBUTOR_DEMO功能,选择CONFIG_BOARD_AC632N_DISTRIBUT作为目标板:

/**
*  板级配置选择
*/
#define CONFIG_BOARD_AC632N_DISTRIBUTOR

3、应用SIG_MESH_DFU_TARGET_DEMO功能,选择CONFIG_BOARD_AC632N_TARGET作为目标板:

/**
*  板级配置选择
*/
#define CONFIG_BOARD_AC632N_TARGET

3.3. 应用实例

3.3.1. SIG Generic OnOff Client

1、简介

该实例通过手机“nRF Mesh”进行配网

-> 设备名称:OnOff_cli

-> Node Features:Proxy + Relay

-> Authentication方式:NO OOB

-> Elements个数:1

-> Model:Configuration Server + Health Server + Generic On Off Client

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

使用 PB4 作为AD按键

设备名称为“OnOff_cli”,MAC地址为“11:22:33:44:55:66”

-> api/model_api.h
#define CONFIG_MESH_MODEL                   SIG_MESH_GENERIC_ONOFF_CLIENT

-> board/xxxx/board_xxxx_demo_cfg.h
#define TCFG_UART0_TX_PORT                   IO_PORTA_00
#define TCFG_UART0_BAUDRATE                  1000000
#define TCFG_ADKEY_ENABLE                    ENABLE_THIS_MOUDLE //是否使能AD按键
#define TCFG_ADKEY_PORT                      IO_PORTB_04 //注意选择的IO口是否支持AD功能
#define TCFG_ADKEY_AD_CHANNEL                AD_CH_PB4

-> examples/generic_onoff_client.c
#define BLE_DEV_NAME             'O', 'n', 'O', 'f', 'f', '_', 'c', 'l', 'i'
#define CUR_DEVICE_MAC_ADDR      0x112233445566

如果想用默认的蓝牙广播名称,应不使用配置工具来配置蓝牙广播名称。

对于MAC地址,如果想不同设备在第一次上电时使用随机值,可以按照以下操作,将NULL传入 bt_mac_addr_set函数

如果想用配置工具配置MAC地址,应不调用bt_mac_addr_set函数。

-> examples/generic_onoff_client.c
void bt_ble_init(void)
{
     u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
     bt_mac_addr_set(NULL);
}

2).编译工程并下载到目标板,接好串口,接好AD按键,上电或者复位设备

3).使用手机APP“nRF Mesh”进行配网,详细操作请 ->点击这里<-

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server   #SIG Model ID: 0x0000

      Health Server       #SIG Model ID: 0x0002

      Generic On Off Client  #SIG Model ID: 0x1001

4).此时按下按键,就能将开关信息Publish到Group地址0xC000了,如果结合下一小节 SIG Generic OnOff Server,就能控制这个server设备led灯的亮和灭了

3、代码解读

3.3.2. SIG Generic OnOff Server

1、简介

该实例通过手机“nRF Mesh”进行配网

-> 设备名称:OnOff_srv

-> Node Features:Proxy + Relay

-> Authentication方式:NO OOB

-> Elements个数:1

-> Model:Configuration Server + Health Server + Generic On Off Server

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

使用PA1控制LED灯

设备名称为“OnOff_srv”,MAC地址为“85:22:33:44:55:67”

-> api/model_api.h
#define CONFIG_MESH_MODEL                   SIG_MESH_GENERIC_ONOFF_SERVER

-> board/xxxx/board_xxxx_demo_cfg.h
#define TCFG_UART0_TX_PORT                   IO_PORTA_00
#define TCFG_UART0_BAUDRATE                  1000000

-> examples/generic_onoff_server.c
#define BLE_DEV_NAME             'O', 'n', 'O', 'f', 'f', '_', 's', 'r', 'v'
#define CUR_DEVICE_MAC_ADDR      0x852233445567
const u8 led_use_port[] = {
    IO_PORTA_01,
};

如果想用默认的蓝牙广播名称,应不使用配置工具来配置蓝牙广播名称。

对于MAC地址,如果想不同设备在第一次上电时使用随机值,可以按照以下操作,将NULL传入 bt_mac_addr_set函数

如果想用配置工具配置MAC地址,应不调用bt_mac_addr_set函数

-> examples/generic_onoff_server.c
void bt_ble_init(void)
{
     u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
     bt_mac_addr_set(NULL);
}

2).编译工程并下载到目标板,接好串口,接好演示用LED灯,上电或者复位设备

3).使用手机APP“nRF Mesh”进行配网,详细操作请 ->点击这里<-

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server   #SIG Model ID: 0x0000

      Health Server    #SIG Model ID: 0x0002

      Generic On Off Server  #SIG Model ID: 0x1000

4).结合上一小节 SIG Generic OnOff Client ,此时如果Client设备按下按键,那么本机的LED灯就会 亮或者灭了

3、代码解读

3.3.3. SIG AliGenie Socket

1、简介

该实例按照阿里巴巴“*IoT开放平台*”关于“*天猫精灵蓝牙mesh软件基础规范*”,根据“硬件品类规范”描述自己为一个“*插座*”,通过“天猫精灵”语音输入进行发现连接(配网)和控制设备。

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

使用PA1控制LED灯(模拟插座的开和关的操作)

设备名称为“AG-Socket”

三元组(MAC地址、ProductID、Secret)在天猫精灵开发者网站申请

-> api/model_api.h
#define CONFIG_MESH_MODEL                   SIG_MESH_ALIGENIE_SOCKET

-> board/xxxx/board_xxxx_demo_cfg.h
#define TCFG_UART0_TX_PORT                   IO_PORTA_00
#define TCFG_UART0_BAUDRATE                  1000000

-> examples/AliGenie_socket.c
#define BLE_DEV_NAME             'A', 'G', '-', 'S', 'o', 'c', 'k', 'e', 't'
*//< 三元组(本例以个人名义申请的插座类三元组)*
#define CUR_DEVICE_MAC_ADDR          0x28fa7a42bf0d
#define PRODUCT_ID                   12623
#define DEVICE_SECRET                "753053e923f30c9f0bc4405cf13ebda6"
const u8 led_use_port[] = {
    IO_PORTA_01,
};

对于MAC地址,本例中一定要按照三元组里面的MAC地址传入到bt_mac_addr_set函数里

-> examples/AliGenie_socket.c
void bt_ble_init(void)
{
     u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
     bt_mac_addr_set(bt_addr);
}

2).编译工程并下载到目标板,接好串口,接好演示用LED灯,上电或者复位设备

3).天猫精灵连接到互联网上

①.上电“天猫精灵”,长按设备上的语音按键,让设备进入待连接状态

②.手机应用商店下载“天猫精灵”APP,APP上个人中心登陆

③.打开手机“WLAN”,将“天猫精灵”通过手机热点连接到互联网上

详细操作请 ->点击这里<-

4).通过天猫精灵进行配网和控制

①.配网对话

用户:“天猫精灵,搜索设备”

天猫精灵:“发现一个智能插座,是否连接”

用户:“连接”

天猫精灵:“连接成功。。。 。。。”

②.语音控制插座命令(可通过 IoT开放平台 添加自定义语音命令)

命令:“天猫精灵,打开插座” 效果:开发板上LED灯打开

命令:“天猫精灵,关闭插座” 效果:开发板上LED灯关闭

3、代码解读

1).配网

关键在于如何设置在天猫精灵开发者网站申请下来的三元组

①.天猫精灵开发者网站申请三元组,并填到下面文件相应宏定义处

例如申请到的三元组如下:

Product ID(十进制)

Device Secret:

Mac 地址

12623

753053e923f30c9f0bc4405cf13ebda6

28fa7a42bf0d

则按下面规则填写,MAC前要加上0x,Secret要用双引号包住

-> examples/AliGenie_socket.c
//< 三元组(本例以个人名义申请的插座类三元组)
#define CUR_DEVICE_MAC_ADDR          0x28fa7a42bf0d
#define PRODUCT_ID                   12623
#define DEVICE_SECRET                "753053e923f30c9f0bc4405cf13ebda6"

②.建立Element和Model

按照*插座软件规范*,要建立一个element,两个model

Element

Model

属性名称

Primary

Generic On/Off Server 0x1000

开关

Primary

Vendor Model 0x01A80000

故障上报

Element

Model

属性名称 |

Primary

Generic On/Off Server 0x1000

开关 |

Primary

Vendor Model 0x01A80000

故障上报/ 定时控制开关 |

相应代码操作如下:

  • 结构体elements注册了一个primary element = SIG root_models + Vendor_server_models

  • 结构体root_models = Cfg_Server + Generic_OnOff_Server

  • 结构体vendor_server_models = Vendor_Client_Model + Vendor_Server_Model

//< Basic_Cfg_Server + Generic_OnOff_Server*
static struct bt_mesh_model root_models[] = {
    BT_MESH_MODEL_CFG_SRV(&cfg_srv),
    BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, &gen_onoff_pub_srv, &onoff_state[0]),
};
//< Vendor_Client + Vendor_Server*
static struct bt_mesh_model vendor_server_models[] = {
    BT_MESH_MODEL_VND(BT_COMP_ID_LF, BT_MESH_VENDOR_MODEL_ID_CLI, NULL, NULL, NULL),
    BT_MESH_MODEL_VND(BT_COMP_ID_LF, BT_MESH_VENDOR_MODEL_ID_SRV, vendor_srv_op, NULL, &onoff_state[0]),
};
//< Only primary element*
static struct bt_mesh_elem elements[] = {
    BT_MESH_ELEM(0, root_models, vendor_server_models),  // primary element*
    // second element*
    // ...
    ...*
};

2).用户数据处理

①.SIG Generic OnOff Server回调

结构体root_models里的Generic_OnOff_Server注册了回调gen_onoff_srv_op来对用户数据进行处理

当收到BT_MESH_MODEL_OP_GEN_ONOFF_GET等注册消息时,就会调用gen_onoff_get等对应的回 调函数进行用户数据处理

static const struct bt_mesh_model_op gen_onoff_srv_op[] = {
    { BT_MESH_MODEL_OP_GEN_ONOFF_GET, 0, gen_onoff_get },
    { BT_MESH_MODEL_OP_GEN_ONOFF_SET, 2, gen_onoff_set },
    { BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2, gen_onoff_set_unack },
    BT_MESH_MODEL_OP_END,
};

②.Vendor Model回调

结构体vendor_srv_op里的Vendor_Server_Model注册了回调vendor_srv_op来对用户数据进行处理

当收到VENDOR_MSG_ATTR_GET等注册消息时,就会调用vendor_attr_get等对应的回 调函数进行 用户数据处理

static const struct bt_mesh_model_op vendor_srv_op[] = {
    { VENDOR_MSG_ATTR_GET, ACCESS_OP_SIZE, vendor_attr_get },
    { VENDOR_MSG_ATTR_SET, ACCESS_OP_SIZE, vendor_attr_set },
    BT_MESH_MODEL_OP_END,
};

3.3.4. SIG AliGenie Light

1、简介

该实例按照阿里巴巴“ IoT开放平台 ”关于“*天猫精灵蓝牙mesh软件基础规范*”,根据“硬件品类规范”描述自己为一个“”,通过“天猫精灵”语音输入进行发现连接(配网)和控制设备。

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

使用 PA1 控制LED灯(模拟灯的开和关的操作)

设备名称为“AG-Light”

三元组(MAC地址、ProductID、Secret)在天猫精灵开发者网站申请

-> api/model_api.h
#define CONFIG_MESH_MODEL                   SIG_MESH_ALIGENIE_LIGHT

-> board/xxxx/board_xxxx_demo_cfg.h
#define TCFG_UART0_TX_PORT                   IO_PORTA_00
#define TCFG_UART0_BAUDRATE                  1000000

-> examples/AliGenie_light.c
#define BLE_DEV_NAME             'A', 'G', '-', 'L', 'i', 'g', 'h', 't'
*//< 三元组(本例以个人名义申请的插座类三元组)*
#define CUR_DEVICE_MAC_ADDR          0x18146c110001
#define PRODUCT_ID                   7218909
#define DEVICE_SECRET                "aab00b61998063e62f98ff04c9a787d4"
const u8 led_use_port[] = {
    IO_PORTA_01,
};

对于MAC地址,本例中一定要按照三元组里面的MAC地址传入到bt_mac_addr_set函数里

-> examples/AliGenie_light.c
void bt_ble_init(void)
{
     u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
     bt_mac_addr_set(bt_addr);
}

2).编译工程并下载到目标板,接好串口,接好演示用LED灯,上电或者复位设备

3).天猫精灵连接到互联网上

①.上电“天猫精灵”,长按设备上的语音按键,让设备进入待连接状态

②.手机应用商店下载“天猫精灵”APP,APP上个人中心登陆

③.打开手机“WLAN”,将“天猫精灵”通过手机热点连接到互联网上

详细操作请 ->点击这里<-

4).通过天猫精灵进行配网和控制

①.配网对话 用户:“天猫精灵,搜索设备”

天猫精灵:“发现一个智能灯,是否连接”

用户:“连接”

天猫精灵:“连接成功。。。 。。。”

②.语音控制插座命令(可通过“ IoT开放平台 ”添加自定义语音命令)

命令:“天猫精灵,开灯” 效果:开发板上LED灯打开

命令:“天猫精灵,关灯” 效果:开发板上LED灯关闭

3、代码解读

1).配网

关键在于如何设置在天猫精灵开发者网站申请下来的三元组

①.天猫精灵开发者网站申请三元组,并填到下面文件相应宏定义处

例如申请到的三元组如下:

Product ID(十进制)

Device Secret:

Mac 地址

7218909

aab00b61998063e62f98ff04c9a787d4

18146c110001

则按下面规则填写,MAC前要加上0x,Secret要用双引号包住

-> examples/AliGenie_light.c
//< 三元组(本例以个人名义申请的灯具类三元组)
#define CUR_DEVICE_MAC_ADDR          0x18146c110001
#define PRODUCT_ID                   7218909
#define DEVICE_SECRET                "aab00b61998063e62f98ff04c9a787d4"

②.建立Element和Model

按照*灯具件规范*,要建立一个element,三个model

Element

Model

属性名称 |

Primary

Generic On/Off Server 0x1000

开关 |

Primary

Light_Lightness_Server 0x1300

亮度 |

Primary

Vendor Model 0x01A80000

故障上报/ 定时控制开关 |

相应代码操作如下:

  • 结构体elements注册了一个primary element = SIG root_models + Vendor_server_models

  • 结构体root_models = Cfg_Server + Generic_OnOff_Server + Light_Lightness_Server

  • 结构体vendor_server_models = Vendor_Client_Model + Vendor_Server_Model

//< Basic_Cfg_Server + Generic_OnOff_Server
static struct bt_mesh_model root_models[] = {
    BT_MESH_MODEL_CFG_SRV(&cfg_srv),
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, &gen_onoff_pub_srv, &onoff_state[0]),
BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, light_lightness_srv_op, &gen_onoff_pub_srv, &light),
};
//< Vendor_Client + Vendor_Server
static struct bt_mesh_model vendor_server_models[] = {
    BT_MESH_MODEL_VND(BT_COMP_ID_LF, BT_MESH_VENDOR_MODEL_ID_CLI, NULL, NULL, NULL),
    BT_MESH_MODEL_VND(BT_COMP_ID_LF, BT_MESH_VENDOR_MODEL_ID_SRV, vendor_srv_op, NULL, &onoff_state[0]),
};
//< Only primary element
static struct bt_mesh_elem elements[] = {
    BT_MESH_ELEM(0, root_models, vendor_server_models),  // primary element*
    // second element*
    // ...
    ...*
};

2).用户数据处理

①.SIG Generic OnOff Server回调

结构体root_models里的Generic_OnOff_Server注册了回调gen_onoff_srv_op来对用户数据进行处理

当收到BT_MESH_MODEL_OP_GEN_ONOFF_GET等注册消息时,就会调用gen_onoff_get等对应的回 调函数进行用户数据处理

static const struct bt_mesh_model_op gen_onoff_srv_op[] = {
    { BT_MESH_MODEL_OP_GEN_ONOFF_GET, 0, gen_onoff_get },
    { BT_MESH_MODEL_OP_GEN_ONOFF_SET, 2, gen_onoff_set },
    { BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2, gen_onoff_set_unack },
    BT_MESH_MODEL_OP_END,

};

②.Vendor Model回调

结构体vendor_server_models里的Vendor_Server_Model注册了回调vendor_srv_op来对用户数据进行处 理

当收到VENDOR_MSG_ATTR_GET等注册消息时,就会调用vendor_attr_get等对应的回 调函数进行 用户数据处理

static const struct bt_mesh_model_op vendor_srv_op[] = {
    { VENDOR_MSG_ATTR_GET, ACCESS_OP_SIZE, vendor_attr_get },
    { VENDOR_MSG_ATTR_SET, ACCESS_OP_SIZE, vendor_attr_set },
    BT_MESH_MODEL_OP_END,
};

③.Light_Lightness_Server回调

结构体vendor_server_models里的Light_Lightness_Server注册了回调vendor_srv_op来对用户数据进行处 理

当收到BT_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET等注册消息时,就会调用vendor_attr_get等对 应的回调函数进行用户数据处理

static const struct bt_mesh_model_op light_lightness_srv_op[] = {
    { BT_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET, 0 ,lightness_get },
{ BT_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET, 0, lightness_set },
{ BT_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET_UNACK, 0, lightness_set_unack },
    BT_MESH_MODEL_OP_END,
};

3.3.5. SIG AliGenie Fan

1、简介

该实例按照阿里巴巴“ IoT开放平台 ”关于“*天猫精灵蓝牙mesh软件基础规范*”,根据“硬件品类规范”描述自己为一个“风扇”,通过“天猫精灵”语音输入进行发现连接(配网)和控制设备。

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

使用 PA1 控制LED灯(模拟风扇的开和关的操作)

设备名称为“AG-Fan”

三元组(MAC地址、ProductID、Secret)在天猫精灵开发者网站申请

-> api/model_api.h
#define CONFIG_MESH_MODEL                   SIG_MESH_ALIGENIE_SOCKET

-> board/xxxx/board_xxxx_demo_cfg.h
#define TCFG_UART0_TX_PORT                   IO_PORT_DP
#define TCFG_UART0_BAUDRATE                1000000

-> examples/AliGenie_fan.c
#define BLE_DEV_NAME             'A', 'G', '-', 'F', 'a', 'n'
//< 三元组(本例以个人名义申请的风扇类三元组)
#define CUR_DEVICE_MAC_ADDR          0x27fa7af002a0
#define PRODUCT_ID                   7809508
#define DEVICE_SECRET                "d2729d5f3898079fa7b697c76a7bfe8e"
const u8 led_use_port[] = {
    IO_PORTA_01,
};

对于MAC地址,本例中一定要按照三元组里面的MAC地址传入到bt_mac_addr_set函数里

-> examples/AliGenie_fan.c
void bt_ble_init(void)
{
     u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
     bt_mac_addr_set(bt_addr);
}

2).编译工程并下载到目标板,接好串口,接好演示用LED灯(用于指示风扇开关状态和风速),上电或者复位设备

3).天猫精灵连接到互联网上

①.上电“天猫精灵”,长按设备上的语音按键,让设备进入待连接状态

②.手机应用商店下载“天猫精灵”APP,APP上个人中心登陆

③.打开手机“WLAN”,将“天猫精灵”通过手机热点连接到互联网上

详细操作请 ->点击这里<-

4).通过天猫精灵进行配网和控制

①.配网对话

用户:“天猫精灵,搜索设备”

天猫精灵:“发现一个风扇,是否连接”

用户:“连接”

天猫精灵:“连接成功。。。 。。。”

②.语音控制插座命令(可通过“ IoT开放平台 ”添加自定义语音命令)

命令:“天猫精灵,打开风扇” 效果:开发板上LED灯打开

命令:“天猫精灵,风扇调到2挡” 效果:开发板上LED灯亮度改变

命令:“天猫精灵,关闭风扇” 效果:开发板上LED灯关闭

3、代码解读

1).配网

关键在于如何设置在天猫精灵开发者网站申请下来的三元组

①.天猫精灵开发者网站申请三元组,并填到下面文件相应宏定义处

例如申请到的三元组如下:

Product ID(十进制)

Device Secret:

Mac 地址

7809508

d2729d5f3898079fa7b697c76a7bfe8e

27fa7af002a0

则按下面规则填写,MAC前要加上0x,Secret要用双引号包住

-> examples/AliGenie_fan.c
//< 三元组(本例以个人名义申请的风扇类三元组)
#define CUR_DEVICE_MAC_ADDR          0x27fa7af002a0
#define PRODUCT_ID                   7809508
#define DEVICE_SECRET                "d2729d5f3898079fa7b697c76a7bfe8e"

②.建立Element和Model

按照*风扇软件规范*,要建立一个element,两个model

Element

Model

属性名称 |

Primary

Generic On/Off Server 0x1000

开关 |

Primary

Vendor Model 0x01A80000

调整风速档位/ 定时控制开关 |

相应代码操作如下:

  • 结构体elements注册了一个primary element = SIG root_models + Vendor_server_models

  • 结构体root_models = Cfg_Server + Generic_OnOff_Server

  • 结构体vendor_server_models = Vendor_Client_Model + Vendor_Server_Model

//< Basic_Cfg_Server + Generic_OnOff_Server
static struct bt_mesh_model root_models[] = {
    BT_MESH_MODEL_CFG_SRV(&cfg_srv),
    BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, &gen_onoff_pub_srv, &onoff_state[0]),
};

//< Vendor_Client + Vendor_Server
static struct bt_mesh_model vendor_server_models[] = {
    BT_MESH_MODEL_VND(BT_COMP_ID_LF, BT_MESH_VENDOR_MODEL_ID_CLI, NULL, NULL, NULL),
    BT_MESH_MODEL_VND(BT_COMP_ID_LF, BT_MESH_VENDOR_MODEL_ID_SRV, vendor_srv_op, NULL, &onoff_state[0]),
};

//< Only primary element
static struct bt_mesh_elem elements[] = {
    BT_MESH_ELEM(0, root_models, vendor_server_models),  // primary element*
    // second element*
    // ...
    ...*
};

2).用户数据处理

①.SIG Generic OnOff Server回调

结构体root_models里的Generic_OnOff_Server注册了回调gen_onoff_srv_op来对用户数据进行处理

当收到BT_MESH_MODEL_OP_GEN_ONOFF_GET等注册消息时,就会调用gen_onoff_get等对应的回 调函数进行用户数据处理

static const struct bt_mesh_model_op gen_onoff_srv_op[] = {
    { BT_MESH_MODEL_OP_GEN_ONOFF_GET, 0, gen_onoff_get },
    { BT_MESH_MODEL_OP_GEN_ONOFF_SET, 2, gen_onoff_set },
    { BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2, gen_onoff_set_unack },
    BT_MESH_MODEL_OP_END,
};

②.Vendor Model回调

结构体vendor_srv_op里的Vendor_Server_Model注册了回调vendor_srv_op来对用户数据进行处理

当收到VENDOR_MSG_ATTR_GET等注册消息时, 就会调用vendor_attr_get等对应的回调函数进行用户数据处理

static const struct bt_mesh_model_op vendor_srv_op[] = {
    { VENDOR_MSG_ATTR_GET, ACCESS_OP_SIZE, vendor_attr_get },
    { VENDOR_MSG_ATTR_SET, ACCESS_OP_SIZE, vendor_attr_set },
    BT_MESH_MODEL_OP_END,
};

3.3.6. SIG Vendor Client

1、简介

该实例会自动进行配网。

-> 设备名称: Vd_cli

-> Node Features: Proxy

-> Authentication方式: NO OOB

-> Elements个数: 1

->Root model: Configuration Server + Configuration Client

->Vendor model: Vendor_Client_Model

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

使用 PB4 作为AD按键端口,将PB4与ADKEY相连

设备名称为“Vd_cli” , “Node”地址为“0x0001”, “Group”地址为“0xc000”,MAC地址为“33:22:33:44:55:66”

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_VENDOR_CLIENT

> board/xxxx/board_xxxx_demo_cfg.h
#define TCFG_UART0_TX_PORT                    IO_PORTA_00
#define TCFG_UART0_BAUDRATE                   1000000

-> examples/vendor_client.c
#define BLE_DEV_NAME                        'V', 'd',  '_', 'c', 'l', 'i'
#define CUR_DEVICE_MAC_ADDR                 0x332233445566
const u8 led_use_port[] = {
        IO_PORTA_01,
};

3).编译工程并下载到目标板上,接好串口,PB4接好AD_key,上电或者复位设备

4).此时按下按键,就能把开关信息Publish到Group地址0xC000了,结合下一小节 SIG Vendor Server, 就可以控制server设备上的LED灯的亮灭了

3、代码解读

1).配网流程

1.配置节点信息与元素组成

int bt_mesh_init(const struct bt_mesh_prov *prov,const struct bt_mesh_comp *comp);
// parameters:
// 本实例中的prov:
static const struct bt_mesh_prov prov = {
                  uuid = dev_uuid,
                  output_size = 0,
                  output_actions = 0,
                  output_number = 0,
                  complete = prov_complete,
                  .reset = prov_reset,
                  };
// 本实例中的comp:
static const struct bt_mesh_comp composition = {
                  .cid = BT_COMP_ID_LF,
                  .elem = elements,
                  .elem_count = ARRAY_SIZE(elements),
                  };
// return 返回值:
int , 返回0代表成功, 其他代表出错

2.配置节点地址与网络通信密钥

int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
                              u8_t flags, u32_t iv_index, u16_t addr,
                              const u8_t dev_key[16]);
        parameters:
                  addr      节点地址
                  net_key   网络密钥, 用于保护网络层的通信
                  net_idx   net_key网络密钥的索引
                  dev_key   设备密钥, 用于保护节点和配置客户端之间的通信
        return_value:

int , 返回0代表成功, 其他代表出错

3.为节点添加app_key

添加的AppKey必须与NetKey成对使用,AppKey用于对接收和发送的消息进行身份验证和加密

int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
                                    u16_t key_app_idx, const u8_t app_key[16],
                                    u8_t *status);
        parameters:
                  addr           节点地址
                  app_key        应用密钥, 用于保护上层传输层的通信
                  key_app_idx    app_key的索引
        return_value:
                  int , 返回0代表成功, 其他代表出错

4.小结

本实例中配置的net_key/dev_key/app_key必须与server的相同否则无法正常进行通信

2).model配置

1.将model绑定到该节点添加的app_key,将应用密钥与元素的模型绑定在一起

int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,u16_t mod_app_idx, u16_t mod_id, u16_t cid,u8_t *status);
parameters:
        addr           节点地址
        elem_addr      配置为该模型的元素地址
        mod_id         模型的标识本例中的mod_id: BT_MESH_VENDOR_MODEL_ID_CLI
        key_app_idx    app_key的索引
        cid            公司标识符
return_value:
        int 

2.为model添加publish行为,配置模型的发布状态

int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,u16_t mod_id, u16_t cid,struct bt_mesh_cfg_mod_pub *pub, u8_t *status);
        parameters:
                    addr        本节点的地址, 即node_addr
                    elem_addr   配置为pub中的发送属性的元素地址
                    pub         pub结构体存放publish行为的相关属性
                                本实例中的pub结构体:
                                struct bt_mesh_cfg_mod_pub pub;
                    pub.addr = dst_addr;     //publish的目的地址
                    pub.app_idx = app_idx;   //app_key的索引
                    pub.cred_flag = 0;       //friendship的凭证标志
                    pub.ttl = 7;             //生命周期, 决定能被relay的次数
                    pub.period = 0;          //定期状态发布的周期
                    pub.transmit = 0;        //每次 publish msg的重传次数(高3位) + 重传输之间50ms的步骤数(低5位)

            status       请求消息的状态

3).节点行为

  1. client的Publish行为

当按键按下时进入 input_key_handle 函数,该函数会获取按键的键值和按键的状态,进行按键处理

void input_key_handler(u8 key_status, u8 key_number)

根据按键的不同状态 input_key_handle 函数会将相应的状态信息(点击为1,长按为0)通过结构体struct _switch *sw传入client_publish函数

static void client_publish(struct switch *sw)

client_publish 函数会对要发送的msg进行处理,接下来会详细介绍client_publish中主要函数的作用及msg的构成

首先 client_publish 函数根据key_number获取存在mod_cli_sw结构体里相应的 vendor_model,这个 vendor_model 的发送属性在上一节的 bt_mesh_cfg_mod_pub_set_vnd 函数里已经进行了配置之后使用bt_mesh_model_msg_init函数初始化一个结构体msg并存入3字节的操作码

void bt_mesh_model_msg_init(struct net_buf_simple *msg, u32_t opcode);

接下来会使用buffer_add_u8_at_tail函数添加一个状态值到msg尾部,用于server端控制LED状态

u8 *buffer_add_u8_at_tail(void *buf, u8 val);

然后使用buffer_memset函数将msg中剩下的空的部分用0x02填满,msg剩下的空的部分可以也可以由用户自定义内容

void *buffer_memset(struct net_buf_simple *buf, u8 val, u32 len);

之后就用bt_mesh_model_publish把包含msg的信息发送出去

int bt_mesh_model_publish(struct bt_mesh_model *model);
  1. client的回调函数

结构体vendor_client_models里的BT_MESH_VENDOR_MODEL_ID_CLI注册了vendor_cli_op来进行数据处理

当收到对面的ack msg并匹配上BT_MESH_VENDOR_MODEL_OP_STATUS时就会调用 vendor_status回调函数对数据进行处理

static const struct bt_mesh_model_op vendor_cli_op[] = {
{
    BT_MESH_VENDOR_MODEL_OP_STATUS, ACCESS_OP_SIZE, vendor_status },
    BT_MESH_MODEL_OP_END,
};

vendor_status 函数的功能:显示作为ack msg的发送方server端的地址及其所受到client控制的情况

static void vendor_status(struct bt_mesh_model *model,
                      struct bt_mesh_msg_ctx *ctx,
                      struct net_buf_simple *buf)

3.3.7. SIG Vendor Server

1、简介

该实例会自动进行配网。

-> 设备名称: Vd_srv

-> Node Features: Proxy

-> Authentication方式: NO OOB

-> Elements个数: 1

-> Root model: Configuration Server + Configuration Client

-> Vendor model: Vendor_Server_Model

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

使用 PB4 作为AD按键端口,将PA1与LED相连

设备名称为“Vd_srv” , “Node”地址为“0x0002”, “Group”地址为“0xc000”,MAC地址为“44:22:33:44:55:66”

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_VENDOR_SERVER

> board/xxxx/board_xxxx_demo_cfg.h
#define TCFG_UART0_TX_PORT                    IO_PORTA_00
#define TCFG_UART0_BAUDRATE                   1000000

-> examples/vendor_server.c
#define BLE_DEV_NAME                        'V', 'd',  '_', 's', r', 'v'
#define CUR_DEVICE_MAC_ADDR                 0x442233445566
const u8 led_use_port[] = {
        IO_PORTA_01,
};

2).编译工程并下载到目标板上,接好串口,接好 LED 灯,PB4接好AD_key,上电或者复位设备

3).此时若 client 端按下按键,server 设备上的 LED 灯就会根据按键的点击还是长按而点亮或熄灭了

3、代码解读

1).配网流程

  1. 配置节点的信息与元素组成

    int bt_mesh_init(const struct bt_mesh_prov *prov,
                     const struct bt_mesh_comp *comp);
    parameters:
       prov  节点的配置信息
            本实例中的prov: static const struct bt_mesh_prov prov = {
                    .uuid = dev_uuid,
                    .output_size = 0,
                    .output_actions = 0,
                    .output_number = 0,
                    .complete = prov_complete,
                    .reset = prov_reset,
                    };
    comp  节点的元素组成
            本实例中的comp: static const struct bt_mesh_comp composition = {
                    .cid = BT_COMP_ID_LF,
                    .elem = elements,
                    .elem_count = ARRAY_SIZE(elements),
                    };
    return :
                    int , 返回0代表成功, 其他代表出错
    
  2. 配置节点地址与网络通信密钥

int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
                      u8_t flags, u32_t iv_index, u16_t addr,
                      const u8_t dev_key[16]);
parameters:
          addr      节点地址
          net_key   网络密钥, 用于保护网络层的通信
          net_idx   net_key的索引
          dev_key   设备密钥 用于保护节点和配置客户端之间的通信.
return_value:
                int , 返回0代表成功, 其他代表出错
  1. 为节点添加app_key

添加的AppKey必须与NetKey成对使用,AppKey用于对接收和发送的消息进行身份验证和加密

int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
                            u16_t key_app_idx, const u8_t app_key[16],
                            u8_t *status);
parameters:
          addr           节点地址
          key_app_idx    app_key的索引
          app_key        应用密钥, 用于保护上层传输层的通信
          status         请求消息的状态
return_value:
           int 
  1. 小结

本实例中配置的net_key/dev_key/app_key必须与server的相同否则无法正常进行通信

2).model配置

  1. 将model绑定到该节点添加的app_key, 将应用密钥与元素的模式绑定在一起

    int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
                                   u16_t mod_app_idx, u16_t mod_id, u16_t cid,
                                   u8_t *status);
    parameters:
                addr             节点地址
                elem_addr        配置为该模型的元素地址
                mod_id           模型的标识
                                 本例中的mod_id: BT_MESH_VENDOR_MODEL_ID_CLI
                key_app_idx      app_key的索引
                cid              公司标识符
                status           请求消息的状态
    return_value:
          int 
    
  2. 为model添加Subscription地址

配置模型的订阅地址,用于接收 client 端 publish 的msg

int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
                                u16_t sub_addr, u16_t mod_id, u16_t cid,
                                u8_t *status);
parameters:
            addr         本节点的地址
            elem_addr    元素地址, 此处填入订阅控制信息对应元素的地址
            sub_addr     订阅的地址
            mod_id       模型的标识
            status       请求消息的状态

return_value:
      int 

3).节点行为

  1. server的回调函数

结构体 vendor_client_models 里的 BT_MESH_VENDOR_MODEL_ID_CLI 注册了 vendor_cli_op 来进行数据处理

当收到对面的ack并匹配上 BT_MESH_VENDOR_MODEL_OP_STATUS 时就会调用 vendor_set 回调函数对数据进行处理

static void vendor_set(struct bt_mesh_model *model,
                        struct bt_mesh_msg_ctx *ctx,
                        struct net_buf_simple *buf)

vendor_set 函数中使用 buffer_pull_u8_from_head 函数提取msg中存放的led状态信息

u8 buffer_pull_u8_from_head(void *buf);

之后使用 gpio_pin_write 函数进行点灯或者灭灯操作

void gpio_pin_write(u8_t led_index, u8_t onoff)

parameters:
            led_index     GPIO口的索引
            onoff         LED的亮灭状态

进行点灯操作后要组织信息作为ack反馈给 client 端,首先使用 bt_mesh_model_msg_init 函数

初始化一个 net_buf_simple 类型对象 ack_msg 并在其中添加3字节的操作码

void bt_mesh_model_msg_init(struct net_buf_simple *msg, u32_t opcode)

之后使用 buffer_add_u8_at_tail 函数在 ack_msg 函数的尾部添加LED的状态

u8 *buffer_add_u8_at_tail(void *buf, u8 val);

然后使用 buffer_memset 函数将 ack_msg 填满

void *buffer_memset(struct net_buf_simple *buf, u8 val, u32 len);

最后就使用 bt_mesh_model_send 函数将反馈信息发送给 client 端

int bt_mesh_model_send(struct bt_mesh_model *model,
                       struct bt_mesh_msg_ctx *ctx,
                       struct net_buf_simple *msg,
                       const struct bt_mesh_send_cb *cb,
                       void *cb_data);
parameters:
           model      发送信息所属的模型
           ctx        消息的环境信息, 包括通信的密钥, 生命周期, 远端地址等
           msg        反馈信息ack_msg
           cb         可选的消息发送的回调, 此实例为空
           cb_data    要传递给回调的用户数据, 此实例为空

3.3.8. SIG Provisioner

1、简介

该实例为SIG mesh中的配网者,充当“nRF mesh app”的角色,通过“PB-ADV”的方式完成组网。

-> 设备名称:Provisioner

-> Elements个数:1

-> Model:Configuration Server + Configuration Client + Generic On Off Client

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

使用 PB4 作为AD按键

设备名称为“Provisioner”,MAC地址为“11:22:33:44:00:00”

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_PROVISIONER

-> board/xxxx/board_xxxx_demo_cfg.h
#define TCFG_UART0_TX_PORT                   IO_PORTA_00
#define TCFG_UART0_BAUDRATE                  1000000
#define TCFG_ADKEY_ENABLE                    ENABLE_THIS_MOUDLE //是否使能AD按键
#define TCFG_ADKEY_PORT                      IO_PORTB_04 //注意选择的IO口是否支持AD功能
#define TCFG_ADKEY_AD_CHANNEL                AD_CH_PB4

-> examples/provisioner.c
#define BLE_DEV_NAME             'P', 'r', 'o', 'v', 'i', 's', 'i', 'o', 'n', 'e', 'r'
#define CUR_DEVICE_MAC_ADDR      0x112233440000

配网者支持配网节点个数为3,支持子网个数为3,支持app_key个数为3

对于MAC地址,如果想不同设备在第一次上电时使用随机值,可以按照以下操作,将NULL传入 bt_mac_addr_set函数

如果想用配置工具配置MAC地址,应不调用bt_mac_addr_set函数

-> examples/provisioner.c
void bt_ble_init(void)
{
    u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
    bt_mac_addr_set(NULL);
     mesh_setup(mesh_init);
}

配置好需要进行配网的节点设备的uuid,本实例中与该节点设备的mac地址进行对应

-> examples/provisioner.c
#define PROVISIONEE_DEVICE_MAC_ADDR         0x112233445566
static const u8_t match_dev_uuid[16] = {MAC_TO_LITTLE_ENDIAN(PROVISIONEE_DEVICE_MAC_ADDR)};

2).编译工程并下载到目标板,接好串口,PB4接好AD_key,上电或者复位设备

3).此时按下按键K5,就能对设备进行配网了,如果结合下一小节 SIG Provisionee,就能对设备进行配网和控制led灯的亮和灭了

3、代码解读

3.3.9. SIG Provisionee

1、简介

该实例为SIG mesh中的节点角色,可以通过“PB-ADV”/“PB-GATT”的方式完成组网。

-> 设备名称:Provisionee

-> Elements个数:1

-> Model:Configuration Server + Generic On Off Server

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

使用 PA1 控制LED灯

设备名称为“Provisionee”,MAC地址为“11:22:33:44:55:66”

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_PROVISIONEE

-> board/xxxx/board_xxxx_demo_cfg.h
#define TCFG_UART0_TX_PORT                   IO_PORTA_00
#define TCFG_UART0_BAUDRATE                  1000000
#define TCFG_ADKEY_ENABLE                    ENABLE_THIS_MOUDLE //是否使能AD按键
#define TCFG_ADKEY_PORT                      IO_PORTB_04 //注意选择的IO口是否支持AD功能
#define TCFG_ADKEY_AD_CHANNEL                AD_CH_PB4

-> examples/provisionee.c
#define BLE_DEV_NAME             'P', 'r', 'o', 'v', 'i', 's', 'i', 'o', 'n', 'e', 'e'
#define CUR_DEVICE_MAC_ADDR      0x112233445566

如果想用默认的蓝牙广播名称,应不使用配置工具来配置蓝牙广播名称。

对于MAC地址,如果想不同设备在第一次上电时使用随机值,可以按照以下操作,将NULL传入 bt_mac_addr_set函数

如果想用配置工具配置MAC地址,应不调用bt_mac_addr_set函数

-> examples/provisionee.c
void bt_ble_init(void)
{
    u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
    bt_mac_addr_set(NULL);
}

2).编译工程并下载到目标板,接好串口,PA1接好LED,PB4接好AD_key,上电或者复位设备

3).如果结合上一小节 SIG Provisioner,此时provisioner按下按键K5,就能对provisionee进行配网和控制led灯的亮和灭了

3、代码解读

3.3.10. SIG NLC Profile

1、简介

该实例为SIG mesh中的蓝牙网络照明控制(NLC),是一套蓝牙Mesh配置文件,用于标准化灯具、传感器和控制设备的接口。

NLC 是无线照明控制的全栈标准,涵盖无线电层、协议层和设备层的标准化,实现了无线照明控制的多厂商互操作性和大规模应用。

NLC 配置文件定义了以下设备类型的标准:

-> 环境光传感器:对应实例为 SIG_MESH_AMBIENT_LIGHT_SENSOR_NLC

-> 基本亮度控制器:对应实例为 SIG_MESH_BASIC_LIGHTNESS_CTRL_NLC

-> 基本场景选择器:对应实例为 SIG_MESH_BASIC_SCENE_SELECTOR_NLC

-> 调光控制器:对应实例为 SIG_MESH_DIMMING_CONTROL_NLC

-> 能源监控器:对应实例为 SIG_MESH_ENERGY_MONITOR_NLC

-> 占用传感器:对应实例为 SIG_MESH_OCCUPACY_SENSOR_NLC

所有实例都可通过手机“nRF Mesh”进行配网.

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

使用 PA1 控制LED灯

-> board/xxxx/board_xxxx_demo_cfg.h
#define TCFG_UART0_TX_PORT                   IO_PORTA_00
#define TCFG_UART0_BAUDRATE                  1000000
#define TCFG_ADKEY_ENABLE                    ENABLE_THIS_MOUDLE //是否使能AD按键
#define TCFG_ADKEY_PORT                      IO_PORTB_04 //注意选择的IO口是否支持AD功能
#define TCFG_ADKEY_AD_CHANNEL                AD_CH_PB4

如果想用默认的蓝牙广播名称,应不使用配置工具来配置蓝牙广播名称。

对于MAC地址,如果想不同设备在第一次上电时使用随机值,可以按照以下操作,将NULL传入 bt_mac_addr_set函数

如果想用配置工具配置MAC地址,应不调用bt_mac_addr_set函数

void bt_ble_init(void)
{
    u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
    bt_mac_addr_set(NULL);
}

2.1).环境光传感器

-> Elements个数:1

-> Model:Configuration Server + Health Server + Sensor Server

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_AMBIENT_LIGHT_SENSOR_NLC

-> examples/ambient_light_sensor_nlc.c
#define BLE_DEV_NAME             'A', 'm', 'b', 'i', 'e', 'n', 't', 'L', 'i', 'g', 'h', 't', 'S', 'e', 'n', 's', 'o', 'r', 'N', 'l', 'c'
#define CUR_DEVICE_MAC_ADDR      0x112233445575

/** Ambient Light Sensor NLC Profile 1.0 */
#define BT_MESH_NLC_PROFILE_ID_AMBIENT_LIGHT_SENSOR 0x1600
// composition page 2
static const uint8_t cmp2_elem_offset1[1] = {0};
static const struct bt_mesh_comp2_record comp_rec[1] = {
  {
    .id = BT_MESH_NLC_PROFILE_ID_AMBIENT_LIGHT_SENSOR,
    .version.x = 1,
    .version.y = 0,
    .version.z = 0,
    .elem_offset_cnt = 1,
    .elem_offset = cmp2_elem_offset1,
    .data_len = 0
  }
};
static const struct bt_mesh_comp2 comp_p2 = {
    .record_cnt = 1,
    .record = comp_rec
};

2.2).编译工程并下载到目标板,接好串口,PA1接好LED,PB4接好AD_key,上电或者复位设备

2.3).使用手机APP“nRF Mesh”进行配网,以‘OnOff_srv’为演示参考,详细操作请 ->点击这里<-

分别bind app_keyset publish addrset Subscribe addr。

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server    #SIG Model ID: 0x0000

      Health Server    #SIG Model ID: 0x0002

      Sensor Server    #SIG Model ID: 0x1100

      Sensor Setup Server    #SIG Model ID: 0x1101

3.1).基本亮度控制器:

-> Elements个数:2

-> Element1:Configuration Server + Health Server +

Generic Level Server + Generic OnOff Server + Generic Default Transition Timer Server +

Generic Power On Off Server + Generic Power On Off Setup Server +

Light Lightness Server + Light Lightness Setup Server + Scene Server + Scene Setup Server

-> Element2: Generic On Off Server + Light LC Server + Light LC Setup Server

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_BASIC_LIGHTNESS_CTRL_NLC

-> examples/basic_lightness_crtl_nlc.c
#define BLE_DEV_NAME             'B', 'a', 's', 'i', 'c', 'L', 'i', 'g', 'h', 't', 'n', 'e', 's', 's', 'C', 't', 'r', 'l', 'N', 'l', 'c'
#define CUR_DEVICE_MAC_ADDR      0x112233445571

/** Basic Lightness Controller NLC Profile 1.0 */
#define BT_MESH_NLC_PROFILE_ID_BASIC_LIGHTNESS_CONTROLLER 0x1601
// composition page 2
static const uint8_t cmp2_elem_offset1[1] = {0};
static const struct bt_mesh_comp2_record comp_rec[1] = {
  {
    .id = BT_MESH_NLC_PROFILE_ID_BASIC_LIGHTNESS_CONTROLLER,
    .version.x = 1,
    .version.y = 0,
    .version.z = 0,
    .elem_offset_cnt = 1,
    .elem_offset = cmp2_elem_offset1,
    .data_len = 0
  }
};
static const struct bt_mesh_comp2 comp_p2 = {
    .record_cnt = 1,
    .record = comp_rec
};

3.2).编译工程并下载到目标板,接好串口,PA1接好LED,PB4接好AD_key,上电或者复位设备

3.3).使用手机APP“nRF Mesh”进行配网,以‘OnOff_srv’为演示参考,详细操作请 ->点击这里<-

分别bind app_keyset publish addrset Subscribe addr。

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server    #SIG Model ID: 0x0000

      Health Server    #SIG Model ID: 0x0002

      Generic Level Server   #SIG Model ID: 0x1002

      Generic OnOff Server   #SIG Model ID: 0x1000

      Generic Default Transition Timer Server   #SIG Model ID: 0x1004

      Generic Power On Off Server   #SIG Model ID: 0x1006

      Generic Power On Off Setup Server   #SIG Model ID: 0x1006

      Light Lightness Server   #SIG Model ID: 0x1300

      Light Lightness Setup Server   #SIG Model ID: 0x1301

      Scene Server   #SIG Model ID: 0x1203

      Scene Setup Server   #SIG Model ID: 0x1204

  ▾ Element

      Generic OnOff Server    #SIG Model ID: 0x1000

      Light LC Server     #SIG Model ID: 0x130F

      Light LC Setup Server   #SIG Model ID: 0x1310

3.4).如果结合小节 调光控制器,可以控制基本亮度控制器的led灯逐渐变亮或逐渐变暗。

4.1).基本场景选择器

-> Elements个数:1

-> Model:Configuration Server + Health Server + Scene Client

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_BASIC_SCENE_SELECTOR_NLC

-> examples/basic_scene_selector_nlc.c
#define BLE_DEV_NAME             'B', 'a', 's', 'i', 'c', 'S', 'c', 'e', 'n', 'e', 'S', 'e', 'l', 'N', 'l', 'c'
#define CUR_DEVICE_MAC_ADDR      0x112233445573

/** Basic Scene Selector NLC Profile 1.0 */
#define BT_MESH_NLC_PROFILE_ID_BASIC_SCENE_SELECTOR 0x1602
// composition page 2
static const uint8_t cmp2_elem_offset1[1] = {0};
static const struct bt_mesh_comp2_record comp_rec[1] = {
  {
    .id = BT_MESH_NLC_PROFILE_ID_BASIC_SCENE_SELECTOR,
    .version.x = 1,
    .version.y = 0,
    .version.z = 0,
    .elem_offset_cnt = 1,
    .elem_offset = cmp2_elem_offset1,
    .data_len = 0
  }
};
static const struct bt_mesh_comp2 comp_p2 = {
    .record_cnt = 1,
    .record = comp_rec
};

4.2).编译工程并下载到目标板,接好串口,PA1接好LED,PB4接好AD_key,上电或者复位设备

4.3).使用手机APP“nRF Mesh”进行配网,以‘OnOff_srv’为演示参考,详细操作请 ->点击这里<-

分别bind app_keyset publish addrset Subscribe addr。

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server    #SIG Model ID: 0x0000

      Health Server    #SIG Model ID: 0x0002

      Scene Client    #SIG Model ID: 0x1205

5.1).调光控制器

-> Elements个数:1

-> Model:Configuration Server + Health Server + Generic Level Client

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_DIMMING_CONTROL_NLC

-> examples/dimming_control_nlc.c
#define BLE_DEV_NAME             'D', 'i', 'm', 'm', 'i', 'n', 'g', 'C', 't', 'r', 'l', 'N', 'l', 'c'
#define CUR_DEVICE_MAC_ADDR      0x112233445570

/** Dimming Control NLC Profile 1.0 */
#define BT_MESH_NLC_PROFILE_ID_DIMMING_CONTROL 0x1603
// composition page 2
static const uint8_t cmp2_elem_offset1[1] = {0};
static const struct bt_mesh_comp2_record comp_rec[1] = {
  {
    .id = BT_MESH_NLC_PROFILE_ID_DIMMING_CONTROL,
    .version.x = 1,
    .version.y = 0,
    .version.z = 0,
    .elem_offset_cnt = 1,
    .elem_offset = cmp2_elem_offset1,
    .data_len = 0
  }
};
static const struct bt_mesh_comp2 comp_p2 = {
    .record_cnt = 1,
    .record = comp_rec
};

5.2).编译工程并下载到目标板,接好串口,PA1接好LED,PB4接好AD_key,上电或者复位设备

5.3).使用手机APP“nRF Mesh”进行配网,以‘OnOff_srv’为演示参考,详细操作请 ->点击这里<-

分别bind app_keyset publish addrset Subscribe addr。

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server    #SIG Model ID: 0x0000

      Health Server    #SIG Model ID: 0x0002

      Generic Level Client   #SIG Model ID: 0x1003

5.4).如果结合小节 基本亮度控制器,调光控制器完成配网并且设置发布地址后按下按键K1,控制基本亮度控制器的led灯逐渐变亮;按下按键K2,控制基本亮度控制器的led灯逐渐变暗。

6.1).能源监控器

-> Elements个数:1

-> Model:Configuration Server + Health Server + Sensor Server + Sensor Setup Server

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_ENERGY_MONITOR_NLC

-> examples/energy_monitor_nlc.c
#define BLE_DEV_NAME             'E', 'n', 'e', 'r', 'g', 'y', 'M', 'o', 'n', 'i', 't', 'o', 'r', 'N', 'l', 'c'
#define CUR_DEVICE_MAC_ADDR      0x112233445572

/** Energy Monitor NLC Profile 1.0 */
#define BT_MESH_NLC_PROFILE_ID_ENERGY_MONITOR 0x1604
// composition page 2
static const uint8_t cmp2_elem_offset1[1] = {0};
static const struct bt_mesh_comp2_record comp_rec[1] = {
  {
    .id = BT_MESH_NLC_PROFILE_ID_ENERGY_MONITOR,
    .version.x = 1,
    .version.y = 0,
    .version.z = 0,
    .elem_offset_cnt = 1,
    .elem_offset = cmp2_elem_offset1,
    .data_len = 0
  }
};
static const struct bt_mesh_comp2 comp_p2 = {
    .record_cnt = 1,
    .record = comp_rec
};

6.2).编译工程并下载到目标板,接好串口,PA1接好LED,PB4接好AD_key,上电或者复位设备

6.3).使用手机APP“nRF Mesh”进行配网,以‘OnOff_srv’为演示参考,详细操作请 ->点击这里<-

分别bind app_keyset publish addrset Subscribe addr。

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server    #SIG Model ID: 0x0000

      Health Server    #SIG Model ID: 0x0002

      Sensor Server    #SIG Model ID: 0x1100

      Sensor Setup Server #SIG Model ID: 0x1101

7.1).占用传感器

-> Elements个数:1

-> Model:Configuration Server + Health Server + Sensor Server + Sensor Setup Server

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_OCCUPACY_SENSOR_NLC

-> examples/light_occupacy_sensor_nlc.c
#define BLE_DEV_NAME             'L', 'i', 'g', 'h', 't', 'O', 'c', 'c', 'p', 'a', 'c', 'y', 'S', 'e', 'n', 's', 'o', 'r', 'N', 'l', 'c'
#define CUR_DEVICE_MAC_ADDR      0x762233445566

/** Occupancy Sensor NLC Profile 1.0 */
#define BT_MESH_NLC_PROFILE_ID_OCCUPANCY_SENSOR 0x1605
// composition page 2
static const uint8_t cmp2_elem_offset1[1] = {0};
static const struct bt_mesh_comp2_record comp_rec[1] = {
  {
    .id = BT_MESH_NLC_PROFILE_ID_OCCUPANCY_SENSOR,
    .version.x = 1,
    .version.y = 0,
    .version.z = 0,
    .elem_offset_cnt = 1,
    .elem_offset = cmp2_elem_offset1,
    .data_len = 0
  }
};
static const struct bt_mesh_comp2 comp_p2 = {
    .record_cnt = 1,
    .record = comp_rec
};

7.2).编译工程并下载到目标板,接好串口,PA1接好LED,PB4接好AD_key,上电或者复位设备

7.3).使用手机APP“nRF Mesh”进行配网,以‘OnOff_srv’为演示参考,详细操作请 ->点击这里<-

分别bind app_keyset publish addrset Subscribe addr。

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server    #SIG Model ID: 0x0000

      Health Server    #SIG Model ID: 0x0002

      Sensor Server    #SIG Model ID: 0x1100

      Sensor Setup Server #SIG Model ID: 0x1101

7.4).如果结合小节 占用传感器监测,此时 占用传感器 设备点击k2会定时发送当前占用模型状态, 占用传感器监测 设备在完成配网和消息订阅后可以持续收到占用模型状态信息。

8.1).占用传感器监测

-> Elements个数:1

-> Model:Configuration Server + Health Server + Sensor Client

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_SENSOR_OBSEVER_NLC

-> examples/light_occupacy_observer_nlc.c
#define BLE_DEV_NAME             'L', 'i', 'g', 'h', 't', 'O', 'c', 'c', 'p', 'a', 'c', 'y', 'O', 'b', 's', 'e', 'r', 'v', 'e', 'r'
#define CUR_DEVICE_MAC_ADDR      0x992233445567

// composition data page
static const struct bt_mesh_comp comp = {
    .cid = BT_COMP_ID_LF,
    .elem = elements,
    .elem_count = ARRAY_SIZE(elements),
};

8.2).编译工程并下载到目标板,接好串口,PA1接好LED,PB4接好AD_key,上电或者复位设备

8.3).使用手机APP“nRF Mesh”进行配网,以‘OnOff_srv’为演示参考,详细操作请 ->点击这里<-

分别bind app_keyset publish addrset Subscribe addr。

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server    #SIG Model ID: 0x0000

      Health Server    #SIG Model ID: 0x0002

      Sensor Client    #SIG Model ID: 0x1102

8.4).如果结合小节 占用传感器,此时 占用传感器 设备点击k2会定时发送当前占用模型状态, 占用传感器监测 设备在完成配网和消息订阅后可以持续收到占用模型状态信息。

3、代码解读

3.3.11. SIG DFU Distributor

1、简介

该实例为SIG mesh dfu中的分发器角色,可以通过手机“nRF Mesh”完成组网。

分发器向目标节点提供新的固件映像,并监视固件更新的进度。

-> 设备名称:DFU_dist_demo

-> Elements个数:1

-> Model:Configuration Server + Health Server +

Blob Transfer Client + Firmware Update Client + Blob Transfer Server + Firmware Distribution Server

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_DFU_DISTRIBUTOR_DEMO

-> board/bd19/board_config.h
/**
*  板级配置选择
*/
#define CONFIG_BOARD_AC632N_DISTRIBUTOR

-> board/bd19/board_ac632n_distributor_global_build_cfg.h
#define CONFIG_RESERVED_AREA1_LEN                           0x3C000   //可升级的bin size为240K

-> examples/dfu_distributor_demo.c
#define BLE_DEV_NAME             'D', 'F', 'U', '_', 'd', 'i', 's', 't', '_', 'd', 'e', 'm', 'o'
#define CUR_DEVICE_MAC_ADDR      0xbb2233445567

如果想用默认的蓝牙广播名称,应不使用配置工具来配置蓝牙广播名称。

对于MAC地址,如果想不同设备在第一次上电时使用随机值,可以按照以下操作,将NULL传入 bt_mac_addr_set函数

如果想用配置工具配置MAC地址,应不调用bt_mac_addr_set函数

-> examples/dfu_distributor_demo.c
void bt_ble_init(void)
{
    u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
    bt_mac_addr_set(NULL);
}

2).编译工程并下载到目标板,接好串口,上电或者复位设备

3).使用手机APP“nRF Mesh”进行配网,以‘OnOff_srv’为演示参考,详细操作请 ->点击这里<-

分别bind app_key。

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server    #SIG Model ID: 0x0000

      Health Server    #SIG Model ID: 0x0002

      Blob Transfer Client   #SIG Model ID: 0x1401

      Firmware Update client #SIG Model ID: 0x1403

      Blob Transfer Server #SIG Model ID: 0x1400

      Firmware Distribution Server #SIG Model ID: 0x1404

4).如果结合小节 SIG DFU Target,可以完成单播DFU或多播DFU,即 1个 distributor + 多个 target的dfu环境,具体可看下一章节。

3、代码解读

3.3.12. SIG DFU Target

1、简介

该实例为SIG mesh dfu中的目标角色,可以通过手机“nRF Mesh”完成组网。

目标节点角色接收固件更新。

-> 设备名称:DFU_target_demo

-> Elements个数:1

-> Model:Configuration Server + Health Server + Blob Transfer Server + Firmware Update Server

2、实际操作

1).基本配置

使用 IO_PORTA_00 作为串口debug脚,波特率为1000000

-> api/model_api.h
#define CONFIG_MESH_MODEL                    SIG_MESH_TARGET_DEMO

-> board/bd19/board_config.h
/**
*  板级配置选择
*/
#define CONFIG_BOARD_AC632N_TARGET

-> examples/dfu_target_demo.c
#define BLE_DEV_NAME             'D', 'F', 'U', '_', 't', 'a', 'r', 'g', 'e', 't', '_', 'd', 'e', 'm', 'o'
#define CUR_DEVICE_MAC_ADDR      0x632233445567

如果想用默认的蓝牙广播名称,应不使用配置工具来配置蓝牙广播名称。

对于MAC地址,如果想不同设备在第一次上电时使用随机值,可以按照以下操作,将NULL传入 bt_mac_addr_set函数

如果想用配置工具配置MAC地址,应不调用bt_mac_addr_set函数

-> examples/dfu_target_demo.c
void bt_ble_init(void)
{
    u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
    bt_mac_addr_set(NULL);
}

2).编译工程并下载到目标板,接好串口,上电或者复位设备

3).使用手机APP“nRF Mesh”进行配网,以‘OnOff_srv’为演示参考,详细操作请 ->点击这里<-

分别bind app_key。

配网完成后节点结构如下:

▾ Elements

  ▾ Element

      Configuration Server    #SIG Model ID: 0x0000

      Health Server    #SIG Model ID: 0x0002

      Blob Transfer Server #SIG Model ID: 0x1400

      Firmware Update Server #SIG Model ID: 0x1402

4).如果结合小节 SIG DFU Distributor,可以完成单播DFU或多播DFU,即 1个 distributor + 多个 target的dfu环境,具体操作流程如下:

4.1).对target设置“0x0011”的地址配网(对于多台设备,则配网地址逐1累加,方便添加后续升级设备,目前支持同时升级设备数为10);

将“Blob Transfer Server”和“Firmware Update Server”绑定app key;

在“subscriptions”下点击“subscribe”将设备订阅到一个组里,如0xC001。

4.2).target端接上设备log,点击开发板K1键,设备会打印”Current composition data hash: 0xXXX”,记录下该数据,用于后续APP输入参数。(注意:对于有相同元素的设备只需操作一次)

4.1).distributor端通过手机”nRF mesh app”配网完成,

并将“Blob Transfer Client”“Firmware Update Client”“Blob Transfer Server”和“Firmware Distribution Server”绑定app key;

4.2).使用“jieli mesh dfu app”对distributor进行连接,APP安装包下载请 ->点击这里<-

APP使用详细操作请 ->点击这里<-

4.3).“jieli mesh dfu app”可以与distributor端一直处于连接状态,这样可以随时获取DFU状态。DFU完成后,distributor端会通知target端更新bin文件。

4.4).至此,mesh dfu流程完成。

3、代码解读