这是目录
- 一、项目概述
- 二、项目设计
- 三、程序设计
- 3.1、主任务设计
- 3.2、蓝牙数据解析
- 3.3、wifi连接
- 四、测试
- 4.1、连接测试
- 4.2、 重连测试
- 4.3 、停止测试
- 4.4 、功耗测试
本文使用环境:
主控:W800-KIT (开发板)
兼容:W800 W801 AIR101
开发环境:CDK
SDK:W801/W800的SDK(tls库)
我的联盛德问答社区主页
前文:
W801/W800-wifi-socket开发(一)-UDP
W801蓝牙收发数据与控制设计(一)-INDICATE
W801蓝牙收发数据与控制设计(二)-NOTIFY方式
本文github工程
这份代码包含前文的某些函数,所以可能会比较乱。
写在前面:
这个代码有很多地方都有BUG,有遇到的请联系我修改。比如未对传输的数据进行严格筛查,每次都要重新输入账户和密码,可以将数据写入flash。。。。因为只是一个基础的学习思路,所以并未深入完善代码。
一、项目概述
^^^^程序功能: 通过手机的蓝牙输入wifi密码和账户连接至路由器,使用开发板I连接电脑端的服务器(UDP协议,使用网络调试助手模拟),传输数据。同时手机端支持重连和停止连接。
^^^^本文是在前文的基础上完成的 。需要借鉴前文的配置。。。
二、项目设计
1、项目整体设计
^^^^整体流程如下所示。指令字符串必须严格执行,程序只判断每一串字符的前四个进行状态的选择。
连接WIFI指令的格式为:conn+账号+密码
。比如:conn+yyds+1234567890
注意:上述流程只是本文设计所用函数,并不是整个工程的流程图。
三、程序设计
3.1、主任务设计
^^^^主任务主要创建两个任务,一个用于蓝牙信息解析,一个用于wifi连接和数据发送。
//add by zxx satrt
//创建任务
void My_task(void)
{//蓝牙接收消息队列if(tls_os_queue_create(&ble_q, 32)!=TLS_OS_SUCCESS){printf("create queue fail\n");return;}//wifi连接消息队列if(tls_os_queue_create(&ble_wifi_q, 32)!=TLS_OS_SUCCESS){printf("create queue fail\n");return;}tls_os_task_create(NULL, NULL,my_ble_msg_task, //蓝牙接收任务NULL,(void *)MyBLETaskStk, /* task's stack start address */MYBLE_TASK_SIZE * sizeof(u32), /* task's stack size, unit:byte */MYBLE_TASK_PRIO,0);tls_os_task_create(NULL, NULL,my_ble_wifi_task, //wifi连接任务NULL,(void *)MyBLEWIFITaskStk, /* task's stack start address */MYBLE_TASK_SIZE * sizeof(u32), /* task's stack size, unit:byte */MYBLE_TASK_PRIO,0);
}
//add by zxx end
3.2、蓝牙数据解析
^^^^首先重新解析一下蓝牙接收的数据,这里因为要处理字符串,所以不再单字节进行处理,打开gatt_svr_chr_demo_access_func()
函数,做如下修改:
static int
gatt_svr_chr_demo_access_func(uint16_t conn_handle, uint16_t attr_handle,struct ble_gatt_access_ctxt *ctxt, void *arg)
{int i = 0;struct os_mbuf *om = ctxt->om;switch (ctxt->op) {case BLE_GATT_ACCESS_OP_WRITE_CHR:while(om) {if(g_ble_uart_output_fptr){g_ble_uart_output_fptr((uint8_t *)om->om_data, om->om_len);}else{//add by zxx start//print_bytes(om->om_data, om->om_len);//首字节为长度,需要添加一个'\0',所以字节长度加一ble_data[0] = om->om_len+1;//其他的原样复制memcpy(&ble_data[1],om->om_data,om->om_len);printf("rec: %s len:%d\n",om->om_data,om->om_len);//添加字符串结束符号ble_data[om->om_len+1] = '\0';if(om->om_len>0)tls_os_queue_send(ble_q,ble_data, 0);//add by zxx end}om = SLIST_NEXT(om, om_next);}return 0;default:assert(0);return BLE_ATT_ERR_UNLIKELY;}
}
^^^^定义一个全局变量,用于wifi的重连,手机端可以通过发送信息,改变该状态:
//全局变量,表示wifi的重连状态,0表示正常,1表示重新连接
u8 wifi_reconnect_state = 0;
^^^^蓝牙信息解析函数
//定义四种状态
#define MY_BLE_WIFI_STATE_START 1 //开始连接
#define MY_BLE_WIFI_STATE_STOP 2 //停止连接
#define MY_BLE_WIFI_STATE_RECONNECT 3 //重新连接
#define MY_BLE_WIFI_STATE_CONNECT 4 //连接wifi,并执行发送程序void my_ble_msg_task(void *sdata)
{u8 msg_state[4];u8 ble_wifi_state = 0;u8 *msg;demo_bt_enable();while(bt_adapter_state == WM_BT_STATE_OFF){tls_os_time_delay(5000 /HZ);}tls_os_time_delay(5000 /HZ);demo_ble_server_on();printf("ble ready ok \r\n");while(1){//接收手机发送的数据,注意是数据是按照字节进行的接收//msg[0]表示数据长度已经包含有'\0'tls_os_queue_receive(ble_q,&msg, 0, 0);printf("rev main:%s len:%d\n",&msg[1] ,msg[0]);//提取前4位,前四位为状态标志strncpy(msg_state,&msg[1],4);//判断前四位的状态if(!strncmp(msg_state,"star",4)) ble_wifi_state = MY_BLE_WIFI_STATE_START;else if(!strncmp(msg_state,"stop",4)) ble_wifi_state = MY_BLE_WIFI_STATE_STOP;else if(!strncmp(msg_state,"reco",4)) ble_wifi_state = MY_BLE_WIFI_STATE_RECONNECT;else if(!strncmp(msg_state,"conn",4)) {//conn命令至少应该是"conn+s+p'\0'" 九个字节if(msg[0] < 9) //小于9说明命令是错的{printf("conn err...\n");tls_ble_server_demo_api_send_notify_msg("conn err...",sizeof("conn err..."));ble_wifi_state = 0;}else ble_wifi_state = MY_BLE_WIFI_STATE_CONNECT;}else ble_wifi_state = 0;switch(ble_wifi_state){case MY_BLE_WIFI_STATE_CONNECT: tls_ble_server_demo_api_send_notify_msg("\'conn+ssid+pwd\'",sizeof("\'conn+ssid+pwd\'"));wifi_reconnect_state = 0; //重置tls_os_queue_send(ble_wifi_q,&msg[6], 0);break;case MY_BLE_WIFI_STATE_STOP: tls_ble_server_demo_api_send_notify_msg("stop connect",sizeof("stop connect"));wifi_reconnect_state = 1; //断开连接break;case MY_BLE_WIFI_STATE_RECONNECT: tls_ble_server_demo_api_send_notify_msg("start reconnect",sizeof("start reconnect"));wifi_reconnect_state = 1; //断开连接break;//只发送信息至手机端case MY_BLE_WIFI_STATE_START: tls_ble_server_demo_api_send_notify_msg("ready connect",sizeof("ready connect"));break;default: printf("ble_wifi_state is err \n");break;}}}
3.3、wifi连接
^^^^连接函数较为简单,使用消息队列等待蓝牙解析任务发送的数据,正确接收后,进入服务器连接,并循环发送数据。当接收重连指令后,会更新wifi_reconnect_state
,退出while发送程序,重连时,必须closesocket,否者无法正常绑定端口。
void my_ble_wifi_task(void *sdata)
{//密码和账户的数组,其实这里可以定义指针并使用malloc灵活申请,我图方便直接定义固定长度u8 ssid[50];u8 pwd[50];//测试发送数组u8 test_data[10] = {0,1,2,3,4,5,6,7,8,9};//消息队列接收u8 *msg;while(1){printf("wait connect..\n");//必须关闭socket,否者不能正常绑定端口close_udp_socket_demo();//消息队列,接收蓝牙解析任务传输的账号和密码tls_os_queue_receive(ble_wifi_q,&msg, 0, 0);printf("rev task:%s len:%d\n",msg,strlen(msg));//字符串的总长度 不带结束字符的长度u8 msg_len = strlen(msg); u8 ssid_size = 0; //账户的长度 不带结束字符//下列循环主要用于找出账户的长度for(int i=0; msg[i] != '\0'; i++){if(msg[i] != '+')ssid_size++;elsebreak;}//拷贝账户名memcpy(ssid,msg,ssid_size);//添加结束字符ssid[ssid_size] = '\0';//拷贝密码,注意要排除加号memcpy(pwd,&msg[ssid_size+1],msg_len-ssid_size-1); //排除掉+号//末尾加上结束字符pwd[msg_len-ssid_size-1] = '\0'; printf("ssid:%s len:%d pwd:%s len:%d \n",ssid,strlen(ssid),pwd,strlen(pwd));//连接WIFIdemo_connect_net(ssid,pwd);//延时tls_os_time_delay(3000);//连接服务器socket_udp_demo(1,10086,"192.168.1.87");//正常情况下发送程序,当wifi_reconnect_state为1时,表示重新连接while(0 == wifi_reconnect_state){udp_send_data_self(test_data,10);tls_os_time_delay(500);}}
}
^^^^上述程序中close_udp_socket_demo()
为自定义函数,在wm_udp_demo.c
文件中。
void close_udp_socket_demo(void)
{printf("close udp socket \n");closesocket(demo_udp->socket_num);
}
^^^^同时在wm_demo_console.h
申明。
extern void udp_send_data_self(u8 *data,int data_len);
extern void close_udp_socket_demo(void);#endif /*__WM_DEMO_CMD_H__*/
四、测试
^^^^在手机端提前设置好如下发送指令。
^^^^手机蓝牙APP如下:
4.1、连接测试
^^^^程序下载至开发板,点击账户+密码。程序运行正常,配网成功,并且正常和服务器发送数据。
服务器
4.2、 重连测试
^^^^点击重连后开发板断开连接,并等待新连接。
^^^^再次发送账户+密码指令。
4.3 、停止测试
^^^^点击停止,开发板断开连接