#include #include "at_host.h" #include "string.h" #include "stdlib.h" #include "rtthread.h" #include "ble_demo.h" //在同一个线程中调用则不需要加临界区 #if 1 #include "rthw.h" #define IRQ_DISABLE() rt_enter_critical() #define IRQ_ENABLE() rt_exit_critical() #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_usedbuff_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---------------------------*/ static void ble_print_data(uint8_t *data,int len) { for(int i=0;imode='i'; ble->linked=0; for(int i=0;idevice[i]); } at_clear_buff(); ble->ret_event=rt_event_create("ble_ret", RT_IPC_FLAG_FIFO); ble->kno_event=rt_event_create("ble_kno", RT_IPC_FLAG_FIFO); rt_event_send(ble->kno_event,2); ble_service_on(ble); ble_reboot(ble); } //ble去初始化 void ble_deinit(ble_struct *ble) { if(ble==0) return ; ble_reboot(ble); ble_service_off(); at_deinit(); if(ble->ret_event) rt_event_delete(ble->ret_event); if(ble->kno_event) rt_event_delete(ble->kno_event); } // 设置回调函数 int ble_set_callback_linked_change(ble_struct *ble,void (*linked_change)(uint16_t handle,uint16_t state)) { ble->linked_change=linked_change; return 1; } int ble_set_callback_recv_data(ble_struct *ble,void (*recv_data)(uint16_t handle,uint8_t *data,int len)) { ble->recv_data=recv_data; return 1; } int ble_set_callback_user_irq(ble_struct *ble,void (*user_irq)(uint8_t *data,int len)) { ble->user_irq=user_irq; return 1; } //处理通知消息 int ble_deal_notice(ble_struct *ble) { if(ble==0) return 0; int len=0; uint8_t *data=ble->return_line; len=at_get_return_line(data); if(len==-1) { 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) { 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) { //收到新数据 if(ble->recv_data==0) ble_save_data(ble,*(uint16_t *)par,par+2,par_size-2); else ble->recv_data(*(uint16_t *)par,par+2,par_size-2); } else if(obj[0]==0xff) { // 用户中断 if(ble->user_irq) ble->user_irq(par,par_size); } } return 1; } //添加通知消息 int ble_add_notice(ble_struct *ble,uint8_t *obj,int obj_size,uint8_t op,uint8_t *par,int par_size) { notice_t *n=&ble->notice; if(ble->kno_event) { // 等待接收方查看通知 rt_uint32_t ev; rt_event_recv(ble->kno_event,0xffffffff,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,1000,&ev); } //ble_print_data(par,par_size); IRQ_DISABLE(); memcpy(n->obj,obj,obj_size); memcpy(n->par,par,par_size); n->obj_size=obj_size; n->par_size=par_size; IRQ_ENABLE(); if(ble->ret_event) { // 发送通知提醒接收方查看 rt_event_send(ble->ret_event,1); } return 1; } //获取通知消息,返回0失败 int ble_get_notice(ble_struct *ble,uint8_t *obj,int *obj_size,uint8_t *op,uint8_t *par,int *par_size) { rt_uint32_t ev; if(ble->ret_event) { if(rt_event_recv(ble->ret_event,0xffffffff,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,1000,&ev)==RT_EOK) { IRQ_DISABLE(); notice_t *n=&ble->notice; if(obj) memcpy(obj,n->obj,n->obj_size); if(obj_size) *obj_size=n->obj_size; if(par) memcpy(par,n->par,n->par_size); if(par_size) *par_size=n->par_size; n->obj_size=0; n->par_size=0; IRQ_ENABLE(); if(ble->kno_event) { // 通知已查看 rt_event_send(ble->kno_event,1); } 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; } // 调用用户回调函数 if(ble->linked_change) ble->linked_change(handle,state); 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) { //printf("%s:recved %d\r\n",__func__,len); 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;idevice[i].conn_handle==handle) return &ble->device[i]; } return 0; } //返回指定索引的蓝牙设备 ble_device *ble_find_device_by_index(ble_struct *ble,int index) { if(ble==0) return 0; if(indexdevice[index].conn_handle) return &ble->device[index]; } return 0; } //添加设备 int ble_add_device(ble_struct *ble,uint16_t handle) { if(handle==0) return 0; IRQ_DISABLE(); for(int i=0;idevice[i]; if(device->conn_handle==0) { memcpy(device->mac,ble->conn_mac,6); device->conn_handle=handle; device->linked=1; ble->linked++; IRQ_ENABLE(); return 1; } } IRQ_ENABLE(); return 0; } //删除设备 int ble_sub_device(ble_struct *ble,uint16_t handle) { if(handle==0) return 0; IRQ_DISABLE(); for(int i=0;idevice[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--; IRQ_ENABLE(); return 1; } } IRQ_ENABLE(); 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) { if(ble==0) return 0; 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) { if(ble==0) return 0; 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) { int ret=0; ret=ble_get_notice(ble,0,0,0,buff,buff_size); return ret; } //设置设备名称 int ble_set_name(ble_struct *ble,char *name) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; at_send_set_event(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]) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; at_send_get_event(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) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; int time_out=100; do{ at_send_set_event(0x03,0,0); rt_thread_delay(2); 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) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; data[0]=sub;data[1]=type; memcpy(&data[2],uuid,type/8); at_send_set_event(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) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; at_send_set_event(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) { if(ble==0) return 0; 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_event(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) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; at_send_set_event(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) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; at_send_set_event(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]) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; at_send_set_event(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]) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; at_send_set_event(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) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; *mac_num=0; at_send_set_event(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; } } //发送用户设置数据 int ble_user_cmd_set(ble_struct *ble,uint8_t *tx,int tx_len) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; at_send_set_event(0xff,tx,tx_len); if(ble_get_cmd_return(ble,data,&size)==1) { if(size==1) return 1; } return 0; } //发送用户获取数据,rx_len获取的数据长度,失败返回0 int ble_user_cmd_get(ble_struct *ble,uint8_t *tx,int tx_len,uint8_t *rx,int *rx_len) { if(ble==0) return 0; uint8_t *data=ble->data_temp; int size=0; int recv_len=0; uint8_t obj; int obj_size; at_send_get_event(0xff,tx,tx_len); while(1) { if(ble_get_notice(ble,&obj,&obj_size,0,data,&size)==1) { if(obj_size==0) return data[0]; else { if(recv_len==0) { if(size>*rx_len) recv_len=*rx_len; else recv_len=size; memcpy(rx,data,recv_len); //ble_print_data(rx,recv_len); *rx_len=recv_len; } } }else break; } return 0; } static int g_service_work; static int g_service_done=1; // ble 服务线程 static void ble_service_thread(void *t) { ble_struct *ble=t; g_service_done=0; int ev; while(g_service_work) { ev=at_get_event(); if(ev&CMDAT_EVENT_RECV) { ev&=~CMDAT_EVENT_RECV; while(ble_deal_notice(ble)==1); } if(ev&CMDAT_EVENT_USER) { ev&=~CMDAT_EVENT_USER; at_send_packet(); } if(ev) { } } g_service_done=1; } static int ble_service_on(void *t) { rt_err_t result = RT_EOK; rt_thread_t tid; // 保证线程没有被创建 if(g_service_done) { g_service_work=1; tid = rt_thread_create("ble_service_thread", ble_service_thread, t, 2048, 11, 10); if (tid != NULL && result == RT_EOK) rt_thread_startup(tid); return 0; } else { return -1; } } static int ble_service_off(void) { // 保证线程已经被创建 if(g_service_work) { g_service_work=0; at_send_user_event(0x04); while(g_service_done==0) { rt_thread_delay(10); } return 0; } else { return -1; } }