前面已经分享过部分关于 RW007 模块如何更新的带 BLE 功能的方法,这里也再次分享一下在柿饼派上怎样更新 RW007 固件和更新 RW007 的驱动,并且测试 RW007 的 BLE 功能。

步骤一:柿饼派更新 RW007 的固件

在柿饼派上更新 RW007 的固件,可以参考官方提供的 RW007 通过 UDP_OTA 工具升级 RW007 固件的文档,进行操作。

1. RW007 模块需要和 PC 电脑连在同一个局域网

2. 打开升级工具配置升级

(1)双击运行 udp_ota.exe软件

3. 升级完成

等待进度条完成,然后重启板子。

步骤二:柿饼派修改 SDK 更新 RW007 的驱动

由于需要使用新版本的 RW007 模块的 BLE 功能,所以需要对应更新主机端柿饼派的 RW007 驱动,主要是替换SDKproject\firmware\packages目录下的rw007-latest目录先删除,然后拷贝提供的rw007-v2.0.1文件夹,即可完成替换更新RW007 的驱动。

替换驱动文件后,通过 env 编译柿饼派的固件,然后通过persimmon mod工具更新柿饼派的固件,即可。

步骤三:柿饼派测试 RW007 的 BLE 功能

当按照前面的步骤进行操作后,可以通过调试串口的 msh命令行进行调试。因为在RW007驱动包里面默认开启了相关的功能测试示例,可以在MSH命令行中通过rw007_ble查询。下面的内容来自于官方提供的 RW007 BLE 功能使用说明操作。

 1msh />rw007_ble2[rw007_ble command]34rw007_ble help5rw007_ble init central/peripheral              Note: init ble mode6rw007_ble get_addr                             Note: get ble address7rw007_ble update_params                        Note: update connect parameters(no support)8rw007_ble scan                                 Note: scan ble slave9rw007_ble stop_scan                            Note: stop scan
10rw007_ble connect xx:xx:xx:xx:xx:xx            Note: use slave addr to connect
11rw007_ble disconnect [conn_handle]             Note: disconnect slave
12rw007_ble get_server                           Note: discover all server(no support)
13rw007_ble get_char                             Note: discover all description(no support)
14rw007_ble get_disc                             Note: discover all characteristic(no support)
15rw007_ble mtu_exch                             Note: ble mtu exchange(no support)
16rw007_ble notify                               Note: enable ble notify(no support)
17rw007_ble write                                Note: ble write data(no support)
18rw007_ble read                                 Note: ble read data(no support)
19rw007_ble notify_change [conn_handle] [char_value] [UUID]   Note: ble notify configure by uuid
20rw007_ble write_uuid [conn_handle] [UUID] [data] Note: ble write data by uuid
21rw007_ble read_uuid                              Note: ble read data by uuid(no support)

BLE 功能初始化

BLE功能初始化函数,使用 BLE功能必须调用。

1.RW007BLE 设备初始化为主机设备。

1rw007_ble init central

测试示例

1msh />rw007_ble init central
2122 - ble_cmd_init
3start ble central
4msh />

2. RW007BLE 设备初始化为从机设备
注意:目前不支持使用从机模式。

1rw007_ble init peripheral

BLE 功能获取本机的BLE设备地址

由于BLE设备的地址分为public公共地址和random随机地址。

1rw007_ble get_addr

测试示例

1msh />rw007_ble get_addr
2273 - ble_cmd_get_addr
3msh />resp_type: 0, len: 12
4RW007_BLE_RSP_TYPE_ADDR_GET
5public_id_addr = 48:00:42:8c:47:c9
6random_id_addr = 00:04:5c:43:00:00

BLE 功能扫描设备

目前RW007BLE 功能支持通过 scan命令,扫描周围的BLE设备。

1.执行扫描周围BLE设备

1rw007_ble scan

测试示例:

1msh />rw007_ble scan
2176 - ble_cmd_scan
3msh />resp_type: 1, len: 65
4RW007_BLE_NTF_TYPE_DISCOVER
5received advertisement; event_type=0 rssi=-60 addr_type=0 addr=4c:ed:fb:00:04:b1
6resp_type: 1, len: 56

这里的 addr地址内容可以为后面连接设备使用,由于目前没有直接显示对应 BLE 设备的名称,需要先人工确定 BLE 设备的地址。

2.停止扫描周围BLE设备
该指令用于 RW007模块正在执行scan扫描操作过程中,马上停止扫描的动作,可以执行此命令。

1rw007_ble stop_scan

BLE 功能设备连接

目前 RW007 BLE 功能设备支持通过 BLE设备的类mac地址来连接设备,该命令仅支持主机模式去连接从机设备的类mac地址,连接成功后会有对应的conn_handle值,这个conn_handle值在其他功能沿用。

1rw007_ble connect xx:xx:xx:xx:xx:xx

测试示例

 1msh />rw007_ble connect 4c:ed:fb:00:04:b12198 - ble_cmd_connect3str_addr: 4c:ed:fb:00:04:b14mac addr: b1: 4: 0:fb:ed:4c5msh />resp_type: 1, len: 526RW007_BLE_NTF_TYPE_CONNECT7type: 0, status: 0, conn_handle: 189resp_type: 1, len: 44
10RW007_BLE_NTF_TYPE_CONNECT_DESC
11our_id_addr: c9:47:8c:42:00:48
12peer_id_addr: b1:04:00:fb:ed:4c

BLE 功能设备断开连接

目前RW007BLE 功能设备支持主动断开从设备的连接。

1rw007_ble disconnect [conn_handle]

其中 conn_handleconnect连接时的需要一致。

1msh />rw007_ble disconnect 1
2341 - ble_cmd_disconnect
3msh />resp_type: 1, len: 52
4RW007_BLE_NTF_TYPE_DISCONN

BLE 功能写数据

目前RW007BLE 功能写数据,支持通过指定UUID来写对应的数据。

1rw007_ble write_uuid [conn_handle] [UUID] [data]

指令说明:[conn_handle]RW007连接设备时生成的对应值,[UUID]为对应 BLE设备的特征参数,[data]为需要发送的数据。

测试示例:

1msh />rw007_ble write_uuid 1 ffe1 Hello,RT-Thread....
2402 - ble_cmd_gattc_write_by_uuid
3write conn_hanle:1 uuid:ffe1 data:Hello,RT-Thread....
4write rc:0
5msh />

注意:目前已经支持通过 128 位的 UUID 进行写数据操作

测试示例:

1msh />rw007_ble write_uuid 1 ebe0ccbe7a0a4b0c8a1a6ff2997da3a6 00
2data: 00
3write conn_hanle:1 uuid:ebe0ccbe7a0a4b0c8a1a6ff2997da3a6
4write rc:0

说明:

测试示例中的 [conn_handle]为 1,[UUID]ebe0ccbe7a0a4b0c8a1a6ff2997da3a6,[data]0x00(这里是使用 hex 值)

BLE 功能更新notify 参数

目前 RW007 BLE 功能支持修改接收 notify参数。

1rw007_ble notify_change [conn_handle] [char_value] [UUID]

参数说明:

[conn_handle]RW007连接设备时生成的对应值

[char_value] 为配置参数,具体如下

10:disable indication&notification
21:enable notification,disable indication
32:enable indication, disable notification
43:enable indication &notification

[UUID]为对应 BLE设备的特征参数值。

BLE 功能关于广播包类型的说明

目前 RW007  BLE 功能中可以关于广播包 event的类型可以分为下面几种。

1/* Advertising report */
2#define BLE_HCI_ADV_RPT_EVTYPE_ADV_IND      (0)
3#define BLE_HCI_ADV_RPT_EVTYPE_DIR_IND      (1)
4#define BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND     (2)
5#define BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND  (3)
6#define BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP     (4)

广播包结构如下:

 1广播包结构描述:2struct ble_gap_disc_desc {3    uint8_t event_type;4    uint8_t length_data;5    ble_addr_t addr;6    int8_t rssi;7    uint8_t *data;89    /***
10     * LE direct advertising report fields; direct_addr is BLE_ADDR_ANY if
11     * direct address fields are not present.
12     */
13    ble_addr_t direct_addr;
14};
15
16通过event_type区分出不同的广播包类型,所有类型分为如下几种:
17/* Advertising report */
180 : 普通广播数据包
191 : 直接广播包
202 : 扫描请求包
213 : 不可连接广播指示
224 : 扫描响应数据包

因此,在设备的scan扫描回应中可以通过对应的event_type来判定是哪种广播包的类型。

RW007的驱动代码中,可以通过下面的event_type来判断是哪种类型的广播包,可以让用户自行实现对应功能。

 1case RW007_BLE_NTF_TYPE_DISC:2        {3            rt_kprintf("RW007_BLE_NTF_TYPE_DISCOVER\n");4            ....5            switch(event_type)6            {7                case BLE_HCI_ADV_RPT_EVTYPE_ADV_IND:89                    break;
10                case BLE_HCI_ADV_RPT_EVTYPE_DIR_IND:
11
12                    break;
13                case BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND:
14
15                    break;
16                case BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND:
17
18                    break;
19                case BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP:
20
21                    break;
22            }
23            ....
24        }

测试示例:

1.初始化 RW007BLE 功能为主机模式。

1msh /> rw007_ble init central
2263 - ble_cmd_init
3start ble central
4msh />

2.执行BLE扫描指令

 1msh />rw007_ble scan 2318 - ble_cmd_scan3msh />resp_type: 1, len: 834RW007_BLE_NTF_TYPE_DISCOVER5received advertisement; event_type=3 rssi=-56 addr_type=1 addr=41:ef:77:50:2b:296mfg_data = 1e ff 06 00 01 09 20 02 5b 5d cd 33 a4 8c c7 c5 36 ac de 12 ab 17 87 89 e1 84 e9 19 ec c4 ad 78resp_type: 1, len: 839RW007_BLE_NTF_TYPE_DISCOVER
10received advertisement; event_type=3 rssi=-65 addr_type=1 addr=3c:2e:33:ea:8d:aa
11mfg_data = 1e ff 06 00 01 09 20 02 28 4c cf 9b a7 f2 7d f6 c7 7e d9 54 ac dd 91 a6 ee 0d 22 43 e1 8f e3
12
13resp_type: 1, len: 83
14RW007_BLE_NTF_TYPE_DISCOVER
15received advertisement; event_type=3 rssi=-59 addr_type=1 addr=42:18:ab:80:5c:11
16mfg_data = 1e ff 06 00 01 09 20 02 eb bf cf 15 97 aa 50 7f a4 57 25 d9 21 35 71 eb 6f aa a1 56 5c d5 e2

3.观察event_type=可以确定是哪种广播包类型。

 1RW007_BLE_NTF_TYPE_DISCOVER2received advertisement; event_type=0 rssi=-64 addr_type=1 addr=61:63:46:c3:49:993mfg_data = 02 01 1a 02 0a 0c 0b ff 4c 00 10 06 00 19 1d 6d 63 18 45resp_type: 1, len: 526RW007_BLE_NTF_TYPE_DISCOVER7received advertisement; event_type=4 rssi=-64 addr_type=1 addr=61:63:46:c3:49:998mfg_data = 9
10resp_type: 1, len: 73
11RW007_BLE_NTF_TYPE_DISCOVER
12received advertisement; event_type=0 rssi=-73 addr_type=0 addr=91:21:52:00:4e:b8
13mfg_data = 14 ff 4c 00 07 0f 00 02 20 91 21 52 00 4e b8 f5 58 58 3c 39 00

BLE 功能读数据

目前 RW007支持通过 UUID 读取数据的功能

1rw007_ble read_uuid [conn_handle] [UUID]

参数说明:

[conn_handle]RW007连接设备时生成的对应值

[UUID]为对应 BLE设备的特征参数。

测试示例:

1msh />rw007_ble read_uuid 1 2a24
2read conn_hanle:1 uuid:2a24
3read rc:0
4msh />ble data input packet resp_type: 0, len: 18
5RW007_BLE_RSP_TYPE_READ
6connect:1 attr_handle:14 uuid: 24 2a  read data:
700000000: 4C 59 57 53 44 30 33 4D 4D 43 00                 LYWSD03MMC.

说明:这里的 [conn_handle]为 1,[UUID]2a24,读取到的数据为 BLE 设备的名称。

目前 RW007 模块已经支持读取 128 位的 UUID 的功能。

测试示例:

1msh />rw007_ble read_uuid 1 ebe0ccbe7a0a4b0c8a1a6ff2997da3a6
2read conn_hanle:1 uuid:ebe0ccbe7a0a4b0c8a1a6ff2997da3a6
3read rc:0
4msh />ble data input packet resp_type: 0, len: 22
5RW007_BLE_RSP_TYPE_READ
6connect:1 attr_handle:51 uuid: a6 a3 7d 99 f2 6f 1a 8a 0c 4b 0a 7a be cc e0 eb  read data:
700000000: 00

说明:这里的 [conn_handle]为 1,[UUID] 为128位的 ebe0ccbe7a0a4b0c8a1a6ff2997da3a6,读取到的数据值为 00

步骤四:柿饼派读取米家蓝牙温湿度计数据显示在界面上

感谢能坚持看到这里的每一个你,下面将会通过添加编写部分功能代码和创建 UI 工程,实现柿饼派读取米家温湿度计数据显示在界面上的功能。接下来会贴一部分实现代码和代码说明,可能会有点乏味,但是尽可能把实现步骤描述得具体些,避免采坑。

1. 添加测试文件,参考代码

2. 编译固件,验证功能

3. 创建 UI 工程,简单布局

4. c-js 之间互通说明

5. UI 工程修改,验证功能

1.添加测试代码

在官方提供的 SDK中的project\firmware\applications目录下添加ble_example.c文件,然后参考project\firmware\packages\rw007-v2.0.1\src\ble_cmd_rw007.c文件,主要拷贝几个对应的函数。通过前面的可以了解到,需要(1)RW007 初始化为 BLE 主机模式 (2)RW007 连接米家蓝牙温湿度计2代设备 (3)RW007 通过 UUID 读取米家蓝牙温湿度计2代设备的数据 ,所以需要参考 BLE功能初始化、连接、通过 UUID 读取数据的功能实现函数。

(1)在ble_example.c中添加 RW007 初始化为BLE主机模式的函数

 1static int ble_example_init(void)2{3    rt_kprintf("ble_example_init\n");4    rt_uint8_t roles = 0;5    roles = RW007_BLE_INIT_ROLE_CENTRAL;67    rw007_ble_init(roles);89    rw007_ble_resp_handle_cb_reg(rw007_ble_resp_handle);
10    rw007_ble_ntf_handle_cb_reg(rw007_ble_ntf_handle);
11    return 0;
12
13}

由于在初始化函数中,需要注册两个回调函数rw007_ble_resp_handlerw007_ble_ntf_handle,所以也要从project\firmware\packages\rw007-v2.0.1\src\ble_cmd_rw007.c文件中对应拷贝过来。

  1static void rw007_ble_resp_handle(rt_uint16_t resp_type, void *data, rt_uint16_t size)2{3    switch(resp_type)4    {5        case RW007_BLE_RSP_TYPE_INIT:6            rt_kprintf("RW007_BLE_RSP_TYPE_INIT\n");7            break;8        case RW007_BLE_RSP_TYPE_ADDR_GET:9            rt_kprintf("RW007_BLE_RSP_TYPE_ADDR_GET\n");10            ble_get_addr *get_addr = (ble_get_addr *)data;11            rt_kprintf("public_id_addr = %02x:%02x:%02x:%02x:%02x:%02x\n", get_addr->public_id_addr[5], get_addr->public_id_addr[4],12                                                                           get_addr->public_id_addr[3], get_addr->public_id_addr[2],13                                                                           get_addr->public_id_addr[1], get_addr->public_id_addr[0]);14            rt_kprintf("random_id_addr = %02x:%02x:%02x:%02x:%02x:%02x\n", get_addr->random_id_addr[5], get_addr->random_id_addr[4],15                                                                           get_addr->random_id_addr[3], get_addr->random_id_addr[2],16                                                                           get_addr->random_id_addr[1], get_addr->random_id_addr[0]);17            break;18        case RW007_BLE_RSP_TYPE_CONN_INFO_GET:19            rt_kprintf("RW007_BLE_RSP_TYPE_CONN_INFO_GET\n");20            break;21        case RW007_BLE_RSP_TYPE_CONN_UPD_PARAMS:22            rt_kprintf("RW007_BLE_RSP_TYPE_CONN_UPD_PARAMS\n");23            break;24        case RW007_BLE_RSP_TYPE_SCAN:25            rt_kprintf("RW007_BLE_RSP_TYPE_SCAN\n");26            break;27        case RW007_BLE_RSP_TYPE_CONNECT:28            rt_kprintf("RW007_BLE_RSP_TYPE_CONNECT\n");29            break;30        case RW007_BLE_RSP_TYPE_DISCONN:31            rt_kprintf("RW007_BLE_RSP_TYPE_DISCONN\n");32            break;33        case RW007_BLE_RSP_TYPE_GATT_DIS_FULL:34            rt_kprintf("RW007_BLE_RSP_TYPE_GATT_DIS_FULL\n");35            break;36        case RW007_BLE_RSP_TYPE_GATTC_SRV:37            rt_kprintf("RW007_BLE_RSP_TYPE_GATTC_SRV\n");38            break;39        case RW007_BLE_RSP_TYPE_GATTC_CHR:40            rt_kprintf("RW007_BLE_RSP_TYPE_GATTC_CHR\n");41            break;42        case RW007_BLE_RSP_TYPE_GATTC_DSC:43            rt_kprintf("RW007_BLE_RSP_TYPE_GATTC_DSC\n");44            break;45        case RW007_BLE_RSP_TYPE_MTU_EXCHANGE:46            rt_kprintf("RW007_BLE_RSP_TYPE_MTU_EXCHANGE\n");47            break;48        case RW007_BLE_RSP_TYPE_NOTIFY:49            rt_kprintf("RW007_BLE_RSP_TYPE_NOTIFY\n");50            break;51        case RW007_BLE_RSP_TYPE_WRITE:52            rt_kprintf("RW007_BLE_RSP_TYPE_WRITE\n");53            break;54        case RW007_BLE_RSP_TYPE_READ:55            rt_kprintf("RW007_BLE_RSP_TYPE_READ\n");56            break;57        default:58            rt_kprintf("error response\n");59            break;60    }61}62// recv slave notity handle63static void rw007_ble_ntf_handle(rt_uint16_t ntf_type, void *data, rt_uint16_t size)64{65    switch(ntf_type)66    {67        case RW007_BLE_NTF_TYPE_CONN_UPD:68            rt_kprintf("RW007_BLE_NTF_TYPE_CONN_UPD\n");69            break;70        case RW007_BLE_NTF_TYPE_CONN_UPD_PARAMS:71            rt_kprintf("RW007_BLE_NTF_TYPE_CONN_UPD_PARAMS\n");72            break;73        case RW007_BLE_NTF_TYPE_DISC:74        {75            struct rw007_ble_gap_event_discov *disc_desc = RT_NULL;76            char *dicover_data = RT_NULL;7778            rt_kprintf("RW007_BLE_NTF_TYPE_DISCOVER\n");7980            disc_desc = (struct rw007_ble_gap_event_discov *)data;81            dicover_data = (char*)(disc_desc + 1);8283            switch(disc_desc->discov_type)84            {85                case BLE_HCI_ADV_RPT_EVTYPE_ADV_IND:8687                    break;88                case BLE_HCI_ADV_RPT_EVTYPE_DIR_IND:8990                    break;91                case BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND:9293                    break;94                case BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND:9596                    break;97                case BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP:9899                    break;
100            }
101
102             rt_kprintf("received advertisement; event_type=%d rssi=%d addr_type=%d addr=",
103                                                                    disc_desc->discov_type,
104                                                                    disc_desc->rssi,
105                                                                    disc_desc->addr_type);
106            rt_kprintf("%02x:%02x:%02x:%02x:%02x:%02x\n", disc_desc->addr[5], disc_desc->addr[4],
107                                                          disc_desc->addr[3], disc_desc->addr[2],
108                                                          disc_desc->addr[1], disc_desc->addr[0]);
109            rt_kprintf("mfg_data = ");
110            for (int i = 0; i < disc_desc->length_data; i++)
111            {
112                rt_kprintf("%02x ", dicover_data[i]);
113            }
114            rt_kprintf("\n\n");
115            break;
116        }
117        case RW007_BLE_NTF_TYPE_CONNECT:
118        {
119            struct rw007_ble_gap_event_connect *connect_event;
120            struct rw007_ble_conn_desc *conn_desc;
121
122            rt_kprintf("RW007_BLE_NTF_TYPE_CONNECT\n");
123
124            connect_event = (struct rw007_ble_gap_event_connect *)data;
125            conn_desc = (struct rw007_ble_conn_desc*)(connect_event + 1);
126
127            rt_kprintf("connect event status: %d, conn_handle: %d\n", connect_event->status, connect_event->conn_handle);
128            rt_kprintf("our_id_type:%d our_id_addr: ", conn_desc->our_id_type);
129            _print_addr(conn_desc->our_id_addr);
130            rt_kprintf("\npeer_id_type:%d peer_id_addr: ", conn_desc->peer_id_type);
131            _print_addr(conn_desc->peer_id_addr);
132            rt_kprintf("\nconn_itv:%d, conn_latency:%d, conn_suptout:%d, role:%d\n", conn_desc->conn_itvl,
133                                conn_desc->conn_latency, conn_desc->supervision_timeout, conn_desc->role);
134            break;
135        }
136        case RW007_BLE_NTF_TYPE_DISCONN:
137            rt_kprintf("RW007_BLE_NTF_TYPE_DISCONN\n");
138            break;
139        case RW007_BLE_NTF_TYPE_MTU_EXCHANGE:
140            rt_kprintf("RW007_BLE_NTF_TYPE_MTU_EXCHANGE\n");
141            break;
142        case RW007_BLE_NTF_TYPE_DISC_COMPLETE:
143            rt_kprintf("RW007_BLE_NTF_TYPE_DISC_COMPLETE\n");
144            break;
145        case RW007_BLE_NTF_TYPE_ADV_COMPLETE:
146            rt_kprintf("RW007_BLE_NTF_TYPE_ADV_COMPLETE\n");
147            break;
148        case RW007_BLE_NTF_TYPE_SUBSCRIBE:
149            rt_kprintf("RW007_BLE_NTF_TYPE_SUBSCRIBE\n");
150            break;
151        case RW007_BLE_NTF_TYPE_NOTIFY_RX:
152            {
153             struct rw007_ble_gap_event_notify_rx *notify_rx;
154
155             rt_kprintf("RW007_BLE_NTF_TYPE_NOTIFY_RX\n");
156
157             notify_rx = (struct rw007_ble_gap_event_notify_rx *)data;
158             rt_kprintf("conn_handle:%d, attr_handle:%d, rcv (%s) length:%d, data:\n",
159                        notify_rx->conn_handle, notify_rx->attr_handle,
160                        notify_rx->indication ? "indication" : "notification", notify_rx->length_data);
161             hex_dump((const rt_uint8_t *)(notify_rx + 1), notify_rx->length_data);
162            break;
163        }
164        default:
165            rt_kprintf("error notify\n");
166            break;
167    }
168}

(2) 添加 RW007连接米家蓝牙温湿度计2代设备的实现函数

 1tatic int ble_example_connect(void)2{3    rt_kprintf("ble_example_connect\n");4    ble_addr_t addr;5    addr.type = RW007_BLE_ADDR_PUBLIC;67    rt_kprintf("str_addr: %s\n", "A4:C1:38:35:52:94");89    _hexstrtoaddr("A4:C1:38:35:52:94", addr.val);
10
11    rt_kprintf("mac addr: %2x:%2x:%2x:%2x:%2x:%2x\n", addr.val[0], addr.val[1],
12                                                          addr.val[2], addr.val[3],
13                                                          addr.val[4], addr.val[5]);
14
15    rw007_ble_connect(&addr);
16    return 0;
17}

说明:前面已经通过 BLE 测试和手机的 BLE 调试助手可以知道米家蓝牙温湿度计2代设备的 mac 地址为A4:C1:38:35:52:94,所以这里直接固定设备的mac地址用于连接。

(3)RW007 通过 UUID 读取米家蓝牙温湿度计2代设备的数据
 由于前面通过 BLE 测试连接上米家蓝牙温湿度计2代设备后,会主动收到来自米家蓝牙温湿度计2代设备的温湿度数据的notify,并在rw007_ble_ntf_handle函数中打印输出,现在需要解析接收到的温湿度数据,在rw007_ble_ntf_handle的函数中添加解析数据的功能。

c case RW007_BLE_NTF_TYPE_NOTIFY_RX: { struct rw007_ble_gap_event_notify_rx *notify_rx; char cRes[50] = {0}; ¨K60K

(4) 添加通过命令启动函数,测试功能

 1static int ble_example_start(void)2{3    ble_example_init();4    rt_thread_delay(1000);5    ble_example_connect();6    rt_thread_delay(5000);7    return 0;89}
10MSH_CMD_EXPORT(ble_example_start,ble_example_start)

说明:这里加了一些延时是考虑到连接设备需要一些时间。

(5)编译固件,烧录验证功能
编译固件,给柿饼派升级固件后,通过在调试串口 msh中输入ble_example_start命令进行启动,启动后便会连接米家蓝牙温湿度计2代设备,并把获取到温湿度数据进行解析,打印出来。

 1msh />ble_example_start2ble_example_init3ble_example_connect4str_addr: A4:C1:38:35:52:945mac addr: 94:52:35:38:c1:a46ble data input packet resp_type: 1, len: 467RW007_BLE_NTF_TYPE_CONNECT8connect event status: 0, conn_handle: 19our_id_type:0 our_id_addr: 48:00:42:8c:47:c9
10peer_id_type:0 peer_id_addr: a4:c1:38:35:52:94
11conn_itv:80, conn_latency:0, conn_suptout:256, role:0
12ble data input packet resp_type: 1, len: 13
13RW007_BLE_NTF_TYPE_NOTIFY_RX
14conn_handle:1, attr_handle:54, rcv (notification) length:5, data:
1500000000: 47 0B 3B B9 0A                                   G.;..
16temp=2887 mC,hum=59%,v_bat=2745mV
17cres=temp=2887mC,hum=59%,v_bat=2745mV

添加把数据传递到界面的实现函数(C-To-JS)

通过前面的步骤,已经成功解析到了米家蓝牙温湿度计2代设备的温湿度数据,现在需要把这些数据显示到 LCD 屏上,需要在 SDK 中参考示例代码中的docs\src\PersimM3_JS_GUI_C_TransData\js_message_test.c进行数据的封装传到GUI 中。

(1)创建 module并初始化

需要创建添加module初始化便于 JS 中导入该模块。

 1static js_object_t js_message_obj = JS_ECMA_VALUE_UNDEFINED;2static void js_message_info_free(void *native)3{4    js_message_obj = JS_ECMA_VALUE_UNDEFINED;5    rt_kprintf("==> js_message_obj = JS_ECMA_VALUE_UNDEFINED;\n");6}78static const js_object_native_info_t js_message_info =9{
10    .free_cb = js_message_info_free
11};
12
13
14js_object_t example_module_init(void)
15{
16    js_object_t obj = js_create_object();
17
18    if (js_resolve_error(obj))
19        return js_create_null();
20    rt_kprintf("==> module_init\n");
21
22    js_message_obj = obj;
23    js_emitter(js_message_obj, js_create_undefined());
24    js_set_property_native_pointer(js_message_obj, "_free_cb", NULL, &js_message_info);
25
26    return obj;
27}
28JS_MODULE(example_module,example_module_init)

注意:这里的example_module在 js 中

(2)封装数据传输函数
在 C代码层到JS脚本层主要是通过事件监听机制异步上报数据或触发JS逻辑主动到C层取数据;当前异步机制是通过GUI的消息队列实现,先往GUI的消息队列发送消息,然后GUI收到对应消息后触发监听回调,所以需要js_message_send_datajs_callback_message函数,可以直接从示例代码中拷贝过来使用。

 1static rt_bool_t js_message_send_data(const char *name, js_object_t data)2{3    rt_bool_t ret = RT_FALSE;45    if (js_context_lock() != RT_EOK)6        return ret;7    rt_kprintf("==> js_message_send_data start\n");8     if (js_object_is_object(js_message_obj))9     {
10        js_object_t msg = js_create_object();
11        if (!js_resolve_error(msg))
12        {
13            js_set_string_property_value(msg, "name", name);
14            js_set_property_value(msg, "data", data);
15
16            ret = js_send_callback_func(js_callback_message, msg);
17            js_release_object(msg);
18        }
19    }
20    rt_kprintf("==> js_message_send_data end\n");
21    js_context_unlock();
22
23    return ret;
24}
 1static rt_bool_t js_callback_message(js_object_t args)2{3    if (js_context_lock() != RT_EOK)4        return RT_FALSE;56    rt_kprintf("==> js_callback_message start\n");7    if (js_object_is_object(js_message_obj))8    {9        js_object_t msg_name = js_get_property_value(args, "name");
10        js_object_t msg_data = js_get_property_value(args, "data");
11        char str_buf[JS_STRING_BUFFER_SIZE];
12        char *name = js_object_to_string(msg_name, str_buf, JS_STRING_BUFFER_SIZE);
13        if (name)
14        {
15            js_event_emit(js_message_obj, name, &msg_data, 1);
16            if (name != str_buf)
17                JS_FREE(name);
18        }
19        js_release_object(msg_data);
20        js_release_object(msg_name);
21    }
22    js_release_object(args);
23    rt_kprintf("==> js_callback_message end\n");
24    js_context_unlock();
25
26    return RT_TRUE;
27}

(3)在解析数据后把数据传到界面显示
rw007_ble_ntf_handle的函数中添加把解析数据后把数据传到界面显示的功能,只需要使用js_message_send_data函数进行传输数据即可。

 1        case RW007_BLE_NTF_TYPE_NOTIFY_RX:2            {3             struct rw007_ble_gap_event_notify_rx *notify_rx;4             char cRes[50] = {0};56             rt_kprintf("RW007_BLE_NTF_TYPE_NOTIFY_RX\n");78             notify_rx = (struct rw007_ble_gap_event_notify_rx *)data;9             rt_kprintf("conn_handle:%d, attr_handle:%d, rcv (%s) length:%d, data:\n",
10                        notify_rx->conn_handle, notify_rx->attr_handle,
11                        notify_rx->indication ? "indication" : "notification", notify_rx->length_data);
12             hex_dump((const rt_uint8_t *)(notify_rx + 1), notify_rx->length_data);
13
14             int32_t temp = 0xffff;
15             int hum = 0xff;
16             int32_t v_bat = 0xffff;
17
18             rt_uint8_t *ptr = (const rt_uint8_t *)(notify_rx + 1);
19
20             //Here to get mi tempture data
21             temp = 0xffff & ptr[1];
22             temp = temp << 8;
23             temp = temp | ptr[0];
24             hum = ptr[2];
25             v_bat = 0xffff & ptr[4];
26             v_bat = v_bat << 8;
27             v_bat = v_bat | ptr[3];
28             rt_kprintf("temp=%d mC,hum=%d%,v_bat=%dmV\n", temp, hum, v_bat);
29             memset(cRes,0,sizeof(cRes));
30             sprintf(cRes,"temp=%dmC,hum=%d%%,v_bat=%dmV", temp, hum, v_bat);
31             rt_kprintf("cres=%s \n",cRes);
32
33            if (js_context_lock() == RT_EOK)
34            {
35                js_object_t value =string_to_js_object(cRes);
36                js_message_send_data("mi_data", value);
37                rt_kprintf("value:%s\n", value);
38                js_release_object(value);
39                js_context_unlock();
40            }
41
42            break;
43        }

说明:

需要注意js_message_send_data("mi_data", value);这里的mi_data,后面UI界面中将通过这个属性来接收数据。

(4)编译固件,烧录程序。
根据前面的步骤操作,这里柿饼派的固件已经准备好了,下面需要创建 UI 工程进行界面显示米家蓝牙温湿度计2代设备的温湿度数据。

创建 UI 工程显示米家蓝牙温湿度计2代设备的温湿度数据

关于UI界面工程的创建,这里不做具体说明,可以参考 SDK 目录下docs\2-PersimM3_UI_Quick_Start.pdf文档的操作,这里只说明核心部分的操作。

(1) UI 工程界面控件布局
由于这里只做数据显示,所以仅需要放置几个 Label控件,为了美观些这里也特意放置了一些图标和设置背景图片。

(2) JS 代码的编写

主要通过require导入example_module,这里的example_module是前面C代码中初始化过的,然后通过this.example_module.on("mi_data",function(data){});进行数据解析,并把数据更新到UI界面中。这里的mi_data也是需要与C代码中配对使用的。

 1var page = {23    /* 此方法在第一次显示窗体前发生 */4    onLoad: function (event) {5        this.example_module = require("example_module");6        console.dir(this.example_module);7        var that = this;8        function insertStr(soure, start, newStr) {9            return soure.slice(0, start) + newStr + soure.slice(start);
10        }
11
12        this.example_module.on("mi_data",function(data){
13
14            //temp=3205mC,hum=54%,v_bat=2766mV
15            //data_length:32
16            s_l1 = data.indexOf(',')
17            temp_data =data.substring(0,s_l1)
18            temp_value_l = temp_data.indexOf('=')
19            temp_value1 = temp_data.substring(temp_value_l+1,temp_data.length -2 )
20            temp_value=insertStr(temp_value1,2,".");
21            s_l2 = data.lastIndexOf(',')
22            hum_value = data.substring(s_l1+5,s_l2)
23            vbat_data =  data.substring(s_l2+7,data.length -2)
24            vbat_value=insertStr(vbat_data,1,".");
25            that.setData({temp_value : temp_value+'℃'});
26            that.setData({hum_value : hum_value});
27            that.setData({bat_value : vbat_value+'V'});
28        });
29    },
30
31    /* 此方法展示窗体后发生 */
32    onResume: function (event) {
33
34    },
35
36    /* 当前页状态变化为显示时触发 */
37    onShow: function (event) {
38
39    },
40
41    /* 当前页状态变化为隐藏时触发 */
42    onHide: function (event) {
43
44    },
45
46    /* 此方法关闭窗体前发生 */
47    onExit: function (event) {
48
49    },
50};
51
52Page(page);
53
54page = 0;

(3) 下载 UI 工程到柿饼派,体验效果

UI 工程下载完成后,在 调试串口的msh命令行中输入ble_example_start,然后观察UI界面的效果。

 1msh />ble_example_start2ble_example_init3ble_example_connect4str_addr: A4:C1:38:35:52:945mac addr: 94:52:35:38:c1:a46ble data input packet resp_type: 1, len: 467RW007_BLE_NTF_TYPE_CONNECT8connect event status: 0, conn_handle: 19our_id_type:0 our_id_addr: 48:00:42:8c:47:c9
10peer_id_type:0 peer_id_addr: a4:c1:38:35:52:94
11conn_itv:80, conn_latency:0, conn_suptout:256, role:0
12msh />ble data input packet resp_type: 1, len: 13
13RW007_BLE_NTF_TYPE_NOTIFY_RX
14conn_handle:1, attr_handle:54, rcv (notification) length:5, data:
1500000000: 28 0B 42 A9 0A                                   (.B..
16temp=2856 mC,hum=66%,v_bat=2729mV
17cres=temp=2856mC,hum=66%,v_bat=2729mV
18==> js_message_send_data start
19==> js_message_send_data end
20value:
21==> js_callback_message start
22==> js_callback_message end

此时,柿饼派的界面就显示米家蓝牙温湿度计2代设备的温湿度和电量的数据。

总结

经过这次使用柿饼派上的 RW007 WIFI 模块学习 BLE 功能的使用和读取米家温湿度计数据显示在界面上的过程中,学会 RW007 上如何使用 BLE 功能和巩固了柿饼派JS与C 之间的数据交互的操作,在这次仅是使用了BLE 的初始化和连接功能,希望在后面使用更多的功能制作更多有趣的作品与大家分享。

????RW007资料链接:

奶牛网盘 https://realthread.cowtransfer.com/s/274a38fde4b543

????RW007购买链接:

https://item.taobao.com/item.htm?&id=587364858221

口令(复制至X宝打开):5嘻6bLxXVYVZEv嘻 https://m.tb.cn/h.4rai8N8?sm=35e672  RW007 高速WIFI模块 SPI  物联网 透传模块 无线模块

你可以添加微信17775982065为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群!

???????????? 点击阅读原文进入官网

【RW007系列综合实战3】柿饼派上怎样更新RW007固件和驱动?相关推荐

  1. 【RW007系列综合实战1】STM32+RW007实现BLE透传功能

    本期文章将分为5篇连载,前2篇将围绕模块功能详解展开,其后3篇将为大家讲解基于RW007相关DEMO的实现,文章目录如下: 今天我们将使用STM32F411-NUCLEO通过 RW007 BLE 功能 ...

  2. 【RW007系列综合实战2】使用RW007模块连接小米蓝牙温湿度计2代

    本期文章将分为5篇连载,前2篇将围绕模块功能详解展开,其后3篇将为大家讲解基于RW007相关DEMO的实现,文章目录如下,目前是第4篇: 通过前面的几篇分享文章,基本上知道RW007高速WIFI模块可 ...

  3. 柿饼派通过RW007的BLE 功能读取米家蓝牙温湿度计数据

    ## 前言 一直在关注 RT-Thread 的柿饼派和 RW007 模块,听说最近新版的 RW007 模块支持 BLE 功能了,于是便向客服咨询在柿饼派上的  RW007 模块是否也支持 BLE 功能 ...

  4. 【QA单】柿饼派及柿饼M3模块相关QA(持续更新....)

    PersimmonUI是以C++编写的,是RT-Thread上一款现代化图形UI库. Q:现在的新版柿饼派和旧版的有什么区别,可以在之前旧版上使用 SDK 开发么? A: 之前旧版的需要与淘宝客服联系 ...

  5. Golang语言快速上手到综合实战(Go语言、Beego框架、高并发聊天室、豆瓣电影爬虫) 下载

    下载Golang语言快速上手到综合实战(Go语言.Beego框架.高并发聊天室.豆瓣电影爬虫) 下载地址:请加QQ:397245854 Go是Google开发的一种编译型,可并行化,并具有垃圾回收功能 ...

  6. 小白都能学会的Python基础 第五讲:综合实战1 - 商业实战之德勤笔试题

    1.华小智系列 - Python基础(案例版) <Python基础>目录 第五讲:综合实战1 - 商业实战之德勤笔试题 1.德勤笔试题分析 2.笔试题讲解 3.课程相关资源 第五讲:综合实 ...

  7. 小白都能学会的Python基础 第六讲:综合实战2 - 大数据分词与词云图绘制

    1.华小智系列 - Python基础(案例版) <Python基础>目录 第六讲:综合实战2 - 大数据分词与词云图绘制 1.大数据分词技巧 2.词频统计技巧 3.词云图绘制 4.微博词云 ...

  8. 小白都能学会的Python基础 第七讲:综合实战3 - 文字识别、人脸识别实战

    1.华小智系列 - Python基础(案例版) <Python基础>目录 第七讲:综合实战3 - 文字识别.人脸识别实战 1.Python图片文字识别(OCR) 2.Python人脸识别( ...

  9. [转]C#综合揭秘——细说多线程(上)

    C#综合揭秘--细说多线程(上) 引言 本文主要从线程的基础用法,CLR线程池当中工作者线程与I/O线程的开发,并行操作PLINQ等多个方面介绍多线程的开发. 其中委托的BeginInvoke方法以及 ...

最新文章

  1. Html5版本的全套股票行情图开源了,附带实现技术简介
  2. C++井字棋游戏,DOS界面版
  3. 【python 10】python 魔术方法
  4. Oracle bug 使用max或min函数into到一个char类型报字符缓冲区太小的错误
  5. 灾备中心服务器辐射,数据中心和灾备中心的相同点以及不同点
  6. python中常用的os模块
  7. RedHat_Linux环境下防火墙配置初级入门
  8. 页脚保持在未满屏页面的底部
  9. AAA 及 RADIUS/HWTACACS 协议配置
  10. 电脑硬件名称 中英文对照
  11. 阿里云OSS上传图片教程-附案例
  12. 打印机打印的时候会打印计算机用户,打印机打印的时候出现administrator是什么意思...
  13. 安装Ofiice2016 错误提示“检查您的internet连接是否工作正常”等
  14. ”左行右立“折寿探秘
  15. 硬盘坏道数据恢复-硬盘开盘数据恢复-天伟数据恢复
  16. 在OpenGL中创建一个球体动画,使球体在窗口内做自由落体运动,并在撞击地面后能够返回原来高度
  17. LinkedList 类 的简单应用
  18. 如何制作linux iso镜像
  19. mac系统启动spring项目报错
  20. 深入浅出Mysql - 优化篇(锁)

热门文章

  1. java-php-net-python-税务申报系统ssh计算机毕业设计程序
  2. Springboot实现拦截器功能
  3. 标梵互动智建中健健身整合营销方案
  4. cors nginx 怎么解决_NGINX配置跨域CORS支持的正确方式
  5. php 模拟鼠标点击,Python全局模拟鼠标点击操作(以至善网无聊评价点击作为案例)...
  6. 什么是政微助手?政微助手是干什么用的?
  7. 搜索和推荐中的精度和召回(recall)分别是什么意思?
  8. GTK+实现linux聊天室代码详解-clientr端
  9. .Net Core 简单的Hangfire部署Demo
  10. 好奇,什么水平才能任教清华计算机系?