1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include "blecfg_pub.h"
6
7 #include "netmgr.h"
8
9 #define AP_INFO_MAX 8
10 #define BLE_UP_MTU 20
11
12 /*
13 使用event进行任务同步,约定如下:
14 event_flag bit0, 表示ssid与passwd已经设定,但还未确认是否正确
15 event_flag bit1, 表示ssid与passwd正确,已经接入ap
16 event_flag bit2, 表示三元组已经设定,但还未确认是否正确
17 event_flag bit3, 表示三元组正确,已经链接云端
18 */
19 #define LINK_EVT_WIFI_AVAIL 0x1
20 #define LINK_EVT_WIFI_CONNECTED 0x2
21 #define LINK_EVT_LINKSDK_AVAIL 0x4
22 #define LINK_EVT_LINKSDK_CONNECTED 0x8
23
24 static aos_event_t g_blecfg_event;
25
26
BleCfg_main_task(void * arg)27 static void BleCfg_main_task(void *arg)
28 {
29 BLECFG_STATE ret_ble;
30 aos_status_t ret_aos;
31 uint32_t event_flag;
32 int32_t wifi_ok = 0;
33 int32_t linksdk_ok = 0;
34
35 (void)arg;
36
37 while ( 1 ) {
38 event_flag = 0;
39 ret_aos = aos_event_get(&g_blecfg_event, 0xffffffff, AOS_EVENT_OR_CLEAR, &event_flag, AOS_WAIT_FOREVER);
40 if ( ret_aos != 0 ) {
41 BLECFG_LOG_ERROR("%s: blecfg evnet error, ret %d\r\n", __func__, ret_aos);
42 break;
43 }
44 BLECFG_LOG_INFO("%s: Event recieve,flag = %d \r\n", __func__, event_flag);
45
46 if ( event_flag & LINK_EVT_WIFI_AVAIL ) {
47 wifi_ok = 0;
48 BLECFG_LOG_INFO("%s: Wifi connecting...\r\n", __func__);
49 ret_ble = BleCfg_wifi_connect();
50 if ( ret_ble != BLECFG_SUCCESS ) {
51 continue;
52 }
53 BLECFG_LOG_INFO("%s: Wifi connect success.\r\n", __func__);
54 }
55
56 if ( event_flag & LINK_EVT_WIFI_CONNECTED ) {
57 wifi_ok = 1;
58 BLECFG_LOG_INFO("%s: Wifi connected.\r\n", __func__);
59 }
60
61 if ( event_flag & LINK_EVT_LINKSDK_AVAIL ) {
62 BLECFG_LOG_INFO("%s: Dev info available.\r\n", __func__);
63 if ( wifi_ok == 1 && linksdk_ok != 1 ) {
64 BLECFG_LOG_INFO("%s: Link to cloud...\r\n", __func__);
65 linksdk_ok = 0;
66 BleCfg_dev_connect();
67 }
68 }
69
70 if ( event_flag & LINK_EVT_LINKSDK_CONNECTED ) {
71 linksdk_ok = 1;
72 BLECFG_LOG_INFO("%s: Link to cloud success.\r\n", __func__);
73 }
74 }
75 }
76
77 /*
78 解析APP小程序下发的命令,目前命令格式如下
79 1. 配网命令: 标识位(2B)FFA0 + SSID len(1B)+ pwd len(1B)+ SSID str + pwd str,没有str结束符
80 2. 三元组设置命令: 标识位(2B)FFB0 + PK len(1B)+ DN len(1B)+ DS len(1B)+ PK str + DN str + DS str,没有str结束符
81 3. WIFI热点查询命令: 标识位(2B)FFC0
82 4. WIFI热点查询结果返回: 标识位(2B)FFD0
83 */
BleCfg_cmd_parse(uint8_t * buf,int32_t len)84 static void BleCfg_cmd_parse(uint8_t *buf, int32_t len)
85 {
86 enum {
87 PKT_TYPE_NETCFG, /* 配网命令的首个packet */
88 PKT_TYPE_DEVINFO, /* 配置设备三元组命令的首个packet */
89 PKT_TYPE_WIFIINFO, /* 设备扫描热点信息并上报的命令 */
90 PKT_TYPE_FOLLOWED /* 命令的后续packet,即需要多次buf合并成一个完整命令 */
91 } pkt_type;
92 static uint8_t *cmd_merge = NULL;
93 static int32_t recv_len = 0; /* 已经接收到的命令长度 */
94 static int32_t total_len = 0; /* 完整命令的长度 */
95 int8_t ssid_len, pwd_len;
96 int8_t pk_len, dn_len, ds_len;
97 int32_t ret, loop, ap_len, ap_offset, payload_len;
98 char *ap_buf, *ssid, *passwd, *pk, *dn, *ds;
99 char ble_note[BLE_UP_MTU + 1];
100 netmgr_wifi_ap_list_t *ap_info;
101
102 /*
103 BLECFG_LOG_INFO("%s payload: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
104 __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]);
105 BLECFG_LOG_INFO("%s payload: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
106 __func__, buf[10], buf[11], buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]);
107 */
108
109 /* 1. 一条命令可能分拆成多个ble包,所以先进行包合并 */
110 /* 1.1 判断包类型。
111 由于包内容都是字符串不会出现0xff。所以首字节0xff表示多个包组成命令的第一个包,非0xff表示后续包 */
112 if ( buf[0] == 0xff && buf[1] == 0xa0 ) {
113 pkt_type = PKT_TYPE_NETCFG;
114 }
115 else if( buf[0] == 0xff && buf[1] == 0xb0 ) {
116 pkt_type = PKT_TYPE_DEVINFO;
117 }
118 else if( buf[0] == 0xff && buf[1] == 0xc0 ) {
119 pkt_type = PKT_TYPE_WIFIINFO;
120 }
121 else if(cmd_merge != NULL) {
122 pkt_type = PKT_TYPE_FOLLOWED;
123 }
124 else {
125 BLECFG_LOG_ERROR("%s: NetConfig not config data recv\r\n", __func__);
126 return;
127 }
128
129 /* 1.2 判断是否为命令的第一个包,可能需要包合并,申请相关内存 */
130 if ( pkt_type != PKT_TYPE_FOLLOWED ) {
131 if ( cmd_merge != NULL ) {
132 /* 发生丢包了,抛弃前一次buffer */
133 BLECFG_LOG_ERROR("%s: NetConfig packet loss\r\n", __func__);
134 free(cmd_merge);
135 cmd_merge = NULL;
136 }
137
138 /* 申请buf_merge */
139 if ( pkt_type == PKT_TYPE_NETCFG ) {
140 /* APP下发的配网命令: 标识位(2B)FFA0 + SSID len(1B)+ pwd len(1B)+ SSID str + pwd str,没有str结束符 */
141 total_len = buf[2] + buf[3] + 4;
142 } else if ( pkt_type == PKT_TYPE_DEVINFO ) {
143 /* APP下发的三元组设置命令: 标识位(2B)FFA0 + PK len(1B)+ DN len(1B)+ DS len(1B)+ PK str + DN str + DS str,没有str结束符 */
144 total_len = buf[2] + buf[3] + buf[4] + 5;
145 } else {
146 /* 不需要merge流程 */
147 total_len = len;
148 }
149 cmd_merge = malloc(total_len);
150 if ( cmd_merge == NULL ) {
151 BLECFG_LOG_ERROR("%s: NetConfig malloc fail for cmd_merge\r\n", __func__);
152 return;
153 }
154 recv_len = 0;
155 }
156
157 /* 1.3 缓存包内容,本次buf copy写入 cmd_merge */
158 if ( len > total_len - recv_len) {
159 /* 发生丢包或错包,抛弃前一次buffer */
160 BLECFG_LOG_ERROR("%s: NetConfig packet error\r\n", __func__);
161 free(cmd_merge);
162 cmd_merge = NULL;
163 return;
164 }
165 memcpy(cmd_merge + recv_len, buf, len);
166 recv_len += len;
167 if (recv_len < total_len) {
168 /* 包不完整,等待后续重新进入本流程 */
169 BLECFG_LOG_INFO("%s: Waiting for next packet\r\n", __func__);
170 return;
171 }
172
173 /* 2. 命令已经完整接收,进入后续命令处理流程 */
174 if ( cmd_merge[0] == 0xff && cmd_merge[1] == 0xa0 ) {
175 /* 2.1 配网命令处理流程 */
176 /* APP下发的配网命令: 标识位(2B)FFA0 + SSID len(1B)+ pwd len(1B)+ SSID str + pwd str,没有str结束符 */
177 ssid_len = cmd_merge[2];
178 pwd_len = cmd_merge[3];
179
180 ssid = malloc(ssid_len + pwd_len + 2);
181 if ( ssid == NULL ) {
182 BLECFG_LOG_ERROR("%s: NetConfig malloc fail for ssid\r\n", __func__);
183 free(cmd_merge);
184 cmd_merge = NULL;
185 }
186 passwd = ssid + ssid_len + 1;
187
188 memcpy(ssid, cmd_merge + 4, ssid_len);
189 ssid[ssid_len] = 0;
190
191 memcpy(passwd, cmd_merge + 4 + ssid_len, pwd_len);
192 passwd[pwd_len] = 0;
193
194 ret = BleCfg_wifi_set(ssid, passwd);
195 if ( ret != BLECFG_SUCCESS ) {
196 BLECFG_LOG_ERROR("%s: NetConfig wifi set error\r\n", __func__);
197 }
198
199 aos_event_set(&g_blecfg_event, LINK_EVT_WIFI_AVAIL, AOS_EVENT_OR);
200
201 /* 消息接收完毕 */
202 BLECFG_LOG_INFO("%s: NetConf SSID = %s, PWD = %s\r\n", __func__, ssid, passwd);
203 free(ssid);
204 } else if ( cmd_merge[0] == 0xff && cmd_merge[1] == 0xb0 ) {
205 /* 2.2 三元组设置命令处理流程 */
206 /* APP下发的三元组设置命令: 标识位(2B)FFB0 + PK len(1B)+ DN len(1B)+ DS len(1B)+ PK str + DN str + DS str,没有str结束符 */
207 pk_len = cmd_merge[2];
208 dn_len = cmd_merge[3];
209 ds_len = cmd_merge[4];
210
211 pk = malloc(pk_len + dn_len + ds_len + 3);
212 if ( pk == NULL ) {
213 BLECFG_LOG_ERROR("%s: NetConfig malloc fail for pk\r\n", __func__);
214 free(cmd_merge);
215 cmd_merge = NULL;
216 }
217 dn = pk + pk_len + 1;
218 ds = dn + dn_len + 1;
219
220 memcpy(pk, cmd_merge + 5, pk_len);
221 pk[pk_len] = 0;
222
223 memcpy(dn, cmd_merge + 5 + pk_len, dn_len);
224 dn[dn_len] = 0;
225
226 memcpy(ds, cmd_merge + 5 + pk_len + dn_len, ds_len);
227 ds[ds_len] = 0;
228
229 ret = BleCfg_dev_set(pk, dn, ds);
230 if ( ret != BLECFG_SUCCESS ) {
231 BLECFG_LOG_ERROR("%s: NetConfig wifi set error\r\n", __func__);
232 }
233
234 aos_event_set(&g_blecfg_event, LINK_EVT_LINKSDK_AVAIL, AOS_EVENT_OR);
235
236 /* 消息接收完毕 */
237 BLECFG_LOG_INFO("%s: pk = %d, dn = %d, ds = %d\r\n", __func__, pk, dn, ds);
238 free(pk);
239 } else if ( cmd_merge[0] == 0xff && cmd_merge[1] == 0xc0 ) {
240 /* 2.3 WIFI热点查询命令处理流程 */
241 ap_info = malloc(AP_INFO_MAX*sizeof(*ap_info));
242 if ( ap_info == NULL ) {
243 BLECFG_LOG_ERROR("%s: Not enough memory, %d\r\n", __func__, AP_INFO_MAX*sizeof(*ap_info));
244 free(cmd_merge);
245 cmd_merge = NULL;
246 return;
247 }
248 memset(ap_info, 0, AP_INFO_MAX*sizeof(*ap_info));
249
250 ret = netmgr_wifi_scan_result(ap_info, AP_INFO_MAX, NETMGR_WIFI_SCAN_TYPE_FULL_MERGE);
251
252 for (loop = 0, ap_len = 0; loop < AP_INFO_MAX; loop++) {
253 if ( ap_info[loop].ssid == NULL || ap_info[loop].ssid[0] == 0 ) {
254 continue;
255 }
256 BLECFG_LOG_INFO("%s: ssid=%s ap_power=%d\r\n", __func__, ap_info[loop].ssid, ap_info[loop].ap_power);
257 ap_len += strlen(ap_info[loop].ssid) + 2; //+2 for '()'
258 }
259 ap_len += 1; //str end
260 BLECFG_LOG_INFO("%s: len of SSIDs is %d\r\n", __func__, ap_len);
261
262 ap_buf = malloc(ap_len);
263 if ( ap_buf == NULL ) {
264 BLECFG_LOG_ERROR("%s: Not enough memory, %d\r\n", __func__, ap_len);
265 free(cmd_merge);
266 cmd_merge = NULL;
267 free(ap_info);
268 return;
269 }
270
271 for (loop = 0, ap_offset = 0; loop < AP_INFO_MAX; loop++) {
272 if ( ap_info[loop].ssid == NULL || ap_info[loop].ssid[0] == 0 ) {
273 continue;
274 }
275 ap_buf[ap_offset++] = '(';
276 memcpy(&ap_buf[ap_offset], ap_info[loop].ssid, strlen(ap_info[loop].ssid));
277 ap_offset += strlen(ap_info[loop].ssid);
278 ap_buf[ap_offset++] = ')';
279 }
280 ap_buf[ap_offset] = 0;
281 BLECFG_LOG_INFO("%s: SSIDs Total = '%s'\r\n", __func__, ap_buf);
282
283 for (loop = 0, ap_offset = 0; loop < 16; loop++) {
284 memset(ble_note, 0, sizeof(ble_note));
285 ble_note[0] = 0xff;
286 ble_note[1] = 0xd0 + loop;
287
288 payload_len = ap_len - ap_offset > BLE_UP_MTU - 2 ? BLE_UP_MTU - 2 : ap_len - ap_offset;
289 if (payload_len == 0 || loop == 15) {
290 BleCfg_notificate(ble_note, 2);
291 BLECFG_LOG_INFO("%s: SSIDs End = 0x%x%x\r\n", __func__, ble_note[0], ble_note[1]);
292 break;
293 }
294 memcpy(&ble_note[2], &ap_buf[ap_offset], payload_len);
295 ap_offset += payload_len;
296 BleCfg_notificate(ble_note, BLE_UP_MTU);
297 BLECFG_LOG_INFO("%s: SSIDs in one MTU = 0x%x%x'%s'\r\n", __func__, ble_note[0], ble_note[1], &ble_note[2]);
298 }
299
300 /* 消息接收完毕 */
301 free(ap_info);
302 free(ap_buf);
303 }
304
305 /* 3. 命令交互完毕,释放命令缓存 */
306 free(cmd_merge);
307 cmd_merge = NULL;
308 }
309
BleCfg_dhcp_success()310 static void BleCfg_dhcp_success()
311 {
312 aos_status_t ret;
313 aos_task_t task_main;
314 uint8_t res = BLECFG_DHCP_SUCCESS;
315 char ipaddr[64] = {'0'};
316
317 BLECFG_LOG_INFO("Got IP\r\n");
318 BleCfg_notificate(&res, 1);
319
320 netmgr_wifi_get_ip_addr(ipaddr);
321 BleCfg_notificate(ipaddr, strlen(ipaddr));
322
323 /* 跳过ping步骤 */
324 res = BLECFG_PING_SUCCESS;
325 BleCfg_notificate(&res, 1);
326
327 /* 保存wifi信息 */
328 BleCfg_wifi_save();
329
330 aos_msleep(500);
331
332 /* ble断连,协议栈自动回到adv广播模式 */
333 //BleCfg_stack_disconnect();
334
335 aos_event_set(&g_blecfg_event, LINK_EVT_WIFI_CONNECTED, AOS_EVENT_OR);
336
337 }
338
BleCfg_link_success()339 static void BleCfg_link_success()
340 {
341 BLECFG_LOG_INFO("LINK SUCCESS\r\n");
342
343 /* 保存三元组信息 */
344 BleCfg_dev_save();
345
346 BleCfg_notificate("DEVSETOK", sizeof("DEVSETOK"));
347
348 aos_event_set(&g_blecfg_event, LINK_EVT_LINKSDK_CONNECTED, AOS_EVENT_OR);
349
350 }
351
352
353 /* 启动ble配置,等待用户通过小程序输入(可能是配网,也可能是配置三元组) */
BleCfg_run()354 BLECFG_STATE BleCfg_run()
355 {
356 BLECFG_STATE ret_ble;
357 aos_status_t ret_aos;
358
359 /* ble stack init */
360 ret_ble = BleCfg_stack_init(BleCfg_cmd_parse);
361 if (ret_ble) {
362 BLECFG_LOG_ERROR("%s: Ble config stack init error %d\r\n", __func__, ret_ble);
363 return ret_ble;
364 }
365
366 /* netmgr init */
367 ret_ble = BleCfg_netmgr_init(BleCfg_dhcp_success);
368 if (ret_ble) {
369 BLECFG_LOG_ERROR("%s: Ble config netmgr init error %d\r\n", __func__, ret_ble);
370 return ret_ble;
371 }
372
373 /* linksdk init */
374 ret_ble = BleCfg_linksdk_init(BleCfg_link_success);
375 if (ret_ble) {
376 BLECFG_LOG_ERROR("%s: Ble config linksdk init error %d\r\n", __func__, ret_ble);
377 return ret_ble;
378 }
379
380 ret_aos = aos_event_new(&g_blecfg_event, 0);
381 if(ret_aos != 0) {
382 BLECFG_LOG_ERROR("%s: event new failed, err=%d\r\n", __func__, ret_aos);
383 return -1;
384 }
385
386 /* netmgr init */
387 ret_aos = aos_task_new("blecfg_task", BleCfg_main_task, NULL, 6*1024);
388 if(ret_aos != 0) {
389 BLECFG_LOG_ERROR("%s: blecfg task new failed, err=%d\r\n", __func__, ret_aos);
390 return -1;
391 }
392
393 ret_ble = BleCfg_stack_start();
394 if (ret_ble) {
395 BLECFG_LOG_ERROR("%s: Ble config start error %d\r\n", __func__, ret_ble);
396 return ret_ble;
397 }
398
399 return BLECFG_SUCCESS;
400 }
401
402 /* 恢复上一次成功连接WiFi的ssid与password配置,若存在则直接完成配网,若不存在则报错 */
BleCfg_recovery_wifi()403 BLECFG_STATE BleCfg_recovery_wifi()
404 {
405 BLECFG_STATE ret;
406
407 ret = BleCfg_wifi_restore();
408 if (ret == BLECFG_SUCCESS) {
409 BLECFG_LOG_INFO("%s: Wifi info get from kv\r\n", __func__);
410 aos_event_set(&g_blecfg_event, LINK_EVT_WIFI_AVAIL, AOS_EVENT_OR);
411 }
412
413 return ret;
414 }
415
416 /* 恢复上一次成功连接云端的三元组信息,若存在则直接连云,若不存在则报错 */
BleCfg_recovery_devinfo()417 BLECFG_STATE BleCfg_recovery_devinfo()
418 {
419 BLECFG_STATE ret;
420
421 ret = BleCfg_dev_restore();
422 if (ret == BLECFG_SUCCESS) {
423 BLECFG_LOG_INFO("%s: Device information get from kv\r\n", __func__);
424 aos_event_set(&g_blecfg_event, LINK_EVT_LINKSDK_AVAIL, AOS_EVENT_OR);
425 }
426
427 return ret;
428 }
429
430
431