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