Files
player/Project_App_Chat/App_Src/calc/ble_demo.c
2025-07-05 19:47:28 +08:00

708 lines
12 KiB
C

#include "stdint.h"
#include <stdio.h>
#include "at_host.h"
#include "string.h"
#include "stdlib.h"
#include "ble_demo.h"
//在同一个线程中调用则不需要加临界区
#if 0
# include "rthw.h"
# define IRQ_DISABLE() rt_base_t irq_stat=rt_hw_interrupt_disable( )
# define IRQ_ENABLE() rt_hw_interrupt_enable (irq_stat)
#else
# define IRQ_DISABLE()
# define IRQ_ENABLE()
#endif
/*------------------------buff相关操作函数---------------------------*/
//清空buff
static int buff_clear(ble_buff *buff);
//初始化buff
static void buff_init(ble_buff *buff)
{
buff->buff_len=BLE_BUFF_LEN;
buff_clear(buff);
}
//写入一个字节
static int buff_save_byte(ble_buff *buff,uint8_t data)
{
IRQ_DISABLE();
if (buff->buff_used<buff->buff_len)
{
buff->buff[buff->save_ptr]=data;
buff->buff_used++;
buff->save_ptr++;
if (buff->save_ptr>=buff->buff_len)
buff->save_ptr=0;
IRQ_ENABLE();
return 1;
}
IRQ_ENABLE();
return 0;
}
//读取一个字节
static int buff_read_byte(ble_buff *buff,uint8_t *data)
{
IRQ_DISABLE();
if (buff->buff_used)
{
*data=buff->buff[buff->read_ptr];
buff->buff_used--;
buff->read_ptr++;
if (buff->read_ptr>=buff->buff_len)
buff->read_ptr=0;
IRQ_ENABLE();
return 1;
}
IRQ_ENABLE();
return 0;
}
//查找buff中是否有指定字符
static int buff_find_char(ble_buff *buff,uint8_t data)
{
int ptr=buff->read_ptr;
int len=buff->buff_used;
while(len--)
{
if(data==buff->buff[ptr])
return 1;
ptr++;
if (ptr>=buff->buff_len)
ptr=0;
}
return 0;
}
//清空buff
static int buff_clear(ble_buff *buff)
{
IRQ_DISABLE();
buff->buff_used=0;
buff->read_ptr=0;
buff->save_ptr=0;
IRQ_ENABLE();
return 0;
}
/*------------------------buff相关操作函数End---------------------------*/
/*------------------------device相关操作函数---------------------------*/
//初始化蓝牙设备
int device_init(ble_device *device)
{
device->conn_handle=0;
device->linked=0;
memset(device->mac,0,6);
buff_init(&device->buff_recv);
return 1;
}
//设置此设备的mac地址
int device_set_mac(ble_device *device,uint8_t mac[6])
{
memcpy(device->mac,mac,6);
return 1;
}
//设置此设备的conn_handle
int device_set_handle(ble_device *device,uint16_t handle)
{
device->conn_handle=handle;
return 1;
}
//把数据存入设备缓冲
int device_save_buff(ble_device *device,uint8_t *buff,int size)
{
int ret=0;
while(size--)
{
if (buff_save_byte(&device->buff_recv,buff[ret])==0)
return ret;
ret++;
}
return ret;
}
//读取设备缓冲,直到遇到界定符
int device_read_buff(ble_device *device,uint8_t *buff,int buff_size,uint8_t end_par)
{
if(buff_find_char(&device->buff_recv,end_par)==0)
return 0;
int ret=0;
uint8_t t=0;
while(1)
{
if(buff_read_byte(&device->buff_recv,&t)==0)
return ret;
if(buff_size)
{
buff[ret]=t;
buff_size--;
ret++;
}
if(t==end_par)
return ret;
}
}
//读取设备缓冲,指定长度
int device_read_buff_by_len(ble_device *device,uint8_t *buff,int read_len)
{
int ret=0;
uint8_t t=0;
while(1)
{
if(buff_read_byte(&device->buff_recv,&t)==0)
return ret;
if(read_len)
{
buff[ret]=t;
read_len--;
ret++;
}
else
return ret;
}
}
/*------------------------device相关操作函数End---------------------------*/
/*--------------------------ble相关操作函数----------------------------*/
//添加通知消息
int ble_add_notice(ble_struct *ble,uint8_t *obj,int obj_size,uint8_t op,uint8_t *par,int par_size);
//连接事务改变
int ble_linked_change(ble_struct *ble,uint16_t handle,uint16_t state);
//收到数据
int ble_save_data(ble_struct *ble,uint16_t handle,uint8_t *data,int len);
//返回指定句柄的设备
ble_device *ble_find_device(ble_struct *ble,uint16_t handle);
//添加设备
int ble_add_device(ble_struct *ble,uint16_t handle);
//删除设备
int ble_sub_device(ble_struct *ble,uint16_t handle);
//ble初始化
void ble_init(ble_struct *ble)
{
at_init();
ble->mode='i';
ble->linked=0;
ble->notice_used=0;
for(int i=0;i<BLE_MAX_LINKED;i++)
{
device_init(&ble->device[i]);
}
at_clear_buff();
}
//处理通知消息
int ble_deal_notice(ble_struct *ble)
{
int len=0;
// uint8_t *data=malloc(100);
uint8_t data[100]={0};
len=at_get_return_line(data);
if(len==-1) {free(data);return 0;}
uint8_t *par=0;
int par_size=0;
uint8_t *obj=0;
int obj_size=0;
uint8_t op=0;
if(at_decode_line(data,len,&obj,&obj_size,&op,&par,&par_size)==-1)
{free(data);return 0;}
if(op==CMDAT_CMD_RET)
{
//命令返回消息,存储到通知缓冲区
ble_add_notice(ble,obj,obj_size,op,par,par_size);
}
else if(op==CMDAT_CMD_ACT)
{
//通知消息,进一步区分
if(obj[0]==0x01)
{
//连接事务改变
ble_linked_change(ble,*(uint16_t *)par,*(uint16_t *)(par+2));
}
else if(obj[0]==0x02)
{
//收到新数据
ble_save_data(ble,*(uint16_t *)par,par+2,par_size-2);
}
}
// free(data);
return 1;
}
//添加通知消息
int ble_add_notice(ble_struct *ble,uint8_t *obj,int obj_size,uint8_t op,uint8_t *par,int par_size)
{
uint8_t *notice=0;
if(ble->notice_used<BLE_MAX_NOTICE)
{
notice=ble->notice[ble->notice_used];
ble->notice_used++;
}
else
{
//通知缓冲区已满,舍弃掉最久远的
notice=ble->notice[ble->notice_used-1];
for(int i=0;i<ble->notice_used-1;i++)
{
memcpy(ble->notice[i],ble->notice[i+1],BLE_NOTICE_LEN);
}
}
notice[0]=obj_size;
memcpy(&notice[1],obj,obj_size);
notice=&notice[1+obj_size];
notice[0]=op;
notice++;
notice[0]=par_size;
memcpy(&notice[1],par,par_size);
return 1;
}
//获取通知消息
int ble_get_notice(ble_struct *ble,uint8_t *obj,int *obj_size,uint8_t *op,uint8_t *par,int *par_size)
{
if(ble->notice_used)
{
uint8_t *notice=ble->notice[0];
if(obj) memcpy(obj,&notice[1],notice[0]);
if(obj_size) *obj_size=notice[0];
if(op) *op=notice[1+notice[0]];
if(par) memcpy(par,&notice[1+notice[0]+1+1],notice[1+notice[0]+1]);
if(par_size) *par_size=notice[1+notice[0]+1];
for(int i=0;i<ble->notice_used-1;i++)
{
memcpy(ble->notice[i],ble->notice[i+1],BLE_NOTICE_LEN);
}
ble->notice_used--;
return 1;
}
return 0;
}
//连接事务改变
int ble_linked_change(ble_struct *ble,uint16_t handle,uint16_t state)
{
if(state==1)
{
//添加连接设备
ble_add_device(ble,handle);
}
else if(state==0)
{
//删除连接设备
ble_sub_device(ble,handle);
}
else
{
return 0;
}
return 1;
}
//收到数据
int ble_save_data(ble_struct *ble,uint16_t handle,uint8_t *data,int len)
{
ble_device *device=ble_find_device(ble,handle);
if(device)
{
return device_save_buff(device,data,len);
}
return 0;
}
//返回指定句柄的设备
ble_device *ble_find_device(ble_struct *ble,uint16_t handle)
{
if(handle==0) return 0;
for(int i=0;i<BLE_MAX_LINKED;i++)
{
if(ble->device[i].conn_handle==handle)
return &ble->device[i];
}
return 0;
}
//返回指定索引的蓝牙设备
ble_device *ble_find_device_by_index(ble_struct *ble,int index)
{
if(index<BLE_MAX_LINKED)
{
if(ble->device[index].conn_handle)
return &ble->device[index];
}
return 0;
}
//添加设备
int ble_add_device(ble_struct *ble,uint16_t handle)
{
if(handle==0) return 0;
for(int i=0;i<BLE_MAX_LINKED;i++)
{
ble_device *device=&ble->device[i];
if(device->conn_handle==0)
{
memcpy(device->mac,ble->conn_mac,6);
device->conn_handle=handle;
device->linked=1;
ble->linked++;
return 1;
}
}
return 0;
}
//删除设备
int ble_sub_device(ble_struct *ble,uint16_t handle)
{
if(handle==0) return 0;
for(int i=0;i<BLE_MAX_LINKED;i++)
{
ble_device *device=&ble->device[i];
if(device->conn_handle==handle)
{
device->conn_handle=0;
device->linked=0;
memset(device->mac,0,6);
buff_clear(&device->buff_recv);
ble->linked--;
return 1;
}
}
return 0;
}
//读取数据直到出现界定符
int ble_get_recv_data_by_end(ble_struct *ble,uint16_t handle,uint8_t *buff,int buff_size,uint8_t end_par)
{
ble_device *device=ble_find_device(ble,handle);
if (device)
{
return device_read_buff(device,buff,buff_size,end_par);
}
return 0;
}
//读取指定长度的数据
int ble_get_recv_data(ble_struct *ble,uint16_t handle,uint8_t *buff,int read_len)
{
ble_device *device=ble_find_device(ble,handle);
if (device)
{
return device_read_buff_by_len(device,buff,read_len);
}
return 0;
}
//获取命令返回
int ble_get_cmd_return(ble_struct *ble,uint8_t *buff,int *buff_size)
{
// rt_thread_delay(20);
do{
ble_deal_notice(ble);
}
while(ble_get_notice(ble,0,0,0,buff,buff_size)==0);
return 1;
}
//设置设备名称
int ble_set_name(ble_struct *ble,char *name)
{
uint8_t *data=ble->data_temp;
int size=0;
at_send_set(0x01,name,strlen(name));
if(ble_get_cmd_return(ble,data,&size)==1)
{
if(data[0]==1)
return 1;
}
return 0;
}
//获取设备mac地址
int ble_get_mac(ble_struct *ble,uint8_t mac[6])
{
uint8_t *data=ble->data_temp;
int size=0;
at_send_get(0x02,0,0);
if(ble_get_cmd_return(ble,data,&size)==1)
{
if(size==6)
{
memcpy(mac,data,6);
return 1;
}
}
return 0;
}
//重启
int ble_reboot(ble_struct *ble)
{
uint8_t *data=ble->data_temp;
int size=0;
int time_out=100;
do{
at_send_set(0x03,0,0);
rt_thread_delay(2);
ble_deal_notice(ble);
ble_get_notice(ble,0,0,0,data,&size);
if((size==1)&&(data[0]==1))
{
rt_thread_delay(100);
at_clear_buff();
return 1;
}
}
while(time_out--);
return 0;
}
//设置uuid
int ble_set_uuid(ble_struct *ble,uint8_t sub,uint8_t type,uint8_t *uuid)
{
uint8_t *data=ble->data_temp;
int size=0;
data[0]=sub;data[1]=type;
memcpy(&data[2],uuid,type/8);
at_send_set(0x05,data,2+type/8);
if(ble_get_cmd_return(ble,data,&size)==1)
{
if(data[0]==1)
return 1;
}
return 0;
}
//打开/关闭数据传输
int ble_set_data_transport(ble_struct *ble,uint8_t power)
{
uint8_t *data=ble->data_temp;
int size=0;
at_send_set(0x06,&power,1);
if(ble_get_cmd_return(ble,data,&size)==1)
{
if(data[0]==1)
return 1;
}
return 0;
}
//发送数据
int ble_send_data(ble_struct *ble,uint16_t handle,uint8_t *buff,int len)
{
uint8_t *data=ble->data_temp;
int size=0;
int pack_len=0;
while(len)
{
data[0]=handle;
data[1]=handle>>8;
if(len>20) pack_len=20;
else pack_len=len;
memcpy(&data[2],buff,pack_len);
at_send_set(0x07,data,pack_len+2);
if(ble_get_cmd_return(ble,data,&size)==1)
{
if(data[0]==1)
{
if (len==0)
return 1;
}
else
{
return 0;
}
}
else
return 0;
len-=pack_len;
buff+=pack_len;
}
return 0;
}
//设置为从机模式
int ble_set_slave(ble_struct *ble)
{
uint8_t *data=ble->data_temp;
int size=0;
at_send_set(0x10,0,0);
if(ble_get_cmd_return(ble,data,&size)==1)
{
if(data[0]==1)
{
ble->mode='s';
return 1;
}
}
return 0;
}
//设置为主机模式
int ble_set_host(ble_struct *ble)
{
uint8_t *data=ble->data_temp;
int size=0;
at_send_set(0x20,0,0);
if(ble_get_cmd_return(ble,data,&size)==1)
{
if(data[0]==1)
{
ble->mode='h';
return 1;
}
}
return 0;
}
//连接指定的从机
int ble_connect_by_mac(ble_struct *ble,uint8_t mac[6])
{
uint8_t *data=ble->data_temp;
int size=0;
at_send_set(0x21,mac,6);
if(ble_get_cmd_return(ble,data,&size)==1)
{
if(data[0]==1)
{
memcpy(ble->conn_mac,mac,6);
return 1;
}
}
return 0;
}
//断开指定的从机
int ble_discon_by_mac(ble_struct *ble,uint8_t mac[6])
{
uint8_t *data=ble->data_temp;
int size=0;
at_send_set(0x22,mac,6);
if(ble_get_cmd_return(ble,data,&size)==1)
{
if(data[0]==1)
return 1;
}
return 0;
}
//扫描
int ble_scan(ble_struct *ble,ble_mac_name mac[32],int *mac_num)
{
uint8_t *data=ble->data_temp;
int size=0;
*mac_num=0;
at_send_set(0x23,0,0);
rt_thread_delay(3500);
while(1)
{
if(ble_get_cmd_return(ble,data,&size)==1)
{
if(size==1)
{
if(data[0]==1)
return 1;
else
return 0;
}
else if(size>=7)
{
memcpy(mac[*mac_num].mac,data,6);
mac[*mac_num].rssi=data[6];
if(size>7)
{
int len=size-7;
memcpy(mac[*mac_num].name,data+7,len);
mac[*mac_num].name[len]=0;
}
else
mac[*mac_num].name[0]=0;
(*mac_num)++;
}
}
else
return 0;
}
}