#include "ble_demo.h" #include "at_host.h" #include "rtthread.h" #include "stdlib.h" #include "string.h" #include // 在同一个线程中调用则不需要加临界区 #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_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---------------------------*/ static void ble_print_data(uint8_t *data, int len) { for (int i = 0; i < len; i++) { printf("%02X ", data[i]); } printf("\r\n"); } /*--------------------------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); static int ble_service_on(void *t); static int ble_service_off(void); // ble初始化 void ble_init(ble_struct *ble) { if (ble == 0) return; memset(ble, 0, sizeof(ble_struct)); at_init(); ble->mode = 'i'; ble->linked = 0; for (int i = 0; i < BLE_MAX_LINKED; i++) { device_init(&ble->device[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; 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 (ble == 0) return 0; 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; IRQ_DISABLE(); 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++; 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; 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--; 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; } }