W801/W800-wifi-socket开发(二)-UDP蓝牙控制wifi连接

本文使用环境:
主控: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++;
			else
				break;
		}
		//拷贝账户名
		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));
		//连接WIFI
		demo_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 、停止测试

^^^^点击停止,开发板断开连接
在这里插入图片描述

4.4 、功耗测试

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37280428/article/details/124269213
今日推荐