600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > ESP32学习笔记(48)——WiFi蓝牙网关

ESP32学习笔记(48)——WiFi蓝牙网关

时间:2019-09-18 19:27:07

相关推荐

ESP32学习笔记(48)——WiFi蓝牙网关

一、项目简介

蓝牙网关又叫蓝牙探针,是采集蓝牙设备的蓝牙数据,通过 WIFI 等方式传至服务器的一款中继设备。如果类比的话,就如同 WIFI 网络中的无线 AP 的作用。WIFI 网络中无线 AP 是将 WIFI 设备接入网络,而蓝牙网络中的蓝牙网关,是将蓝牙设备接入网络。

项目特性:

采用 240MHz Xtensa 32-bit LX6 双核处理器支持 STA 工作模式支持 Smart Config/AirKiss 一键配网内嵌 Lwip 和 FreeRTOS支持 BLE 广播/扫描支持 Beacons 设备蓝牙广播上报功能

二、基本工作流程

Smart Config/AirKiss 一键配网,WIFI 连接路由器;通过 TCP 方式连接到指定 IP 地址服务器;扫描周围蓝牙设备广播数据;将采集蓝牙数据通过 TCP 方式发送到指定服务器;上电或按下网关按键发送蓝牙广播数据,时长5秒(默认)。

三、API接口

3.1 外设

LED灯按键蜂鸣器

3.2 Socket

3.3 WIFI

3.4 BLE

四、工程代码

GitCode:/qq_36347513/esp32-wifi_ble_gateway

将文件解压到 esp-idf/examples 目录下:

4.1 工程结构

4.2 一键配网

首先在main.capp_main()中初始化 WIFI 模块,然后创建一个network_task处理网络通信业务。

void app_main(void){ESP_ERROR_CHECK(nvs_flash_init());/*-------------------------- 外设驱初始化 ---------------------------*/···WIFI_Init();// WIFI模块初始化······/*-------------------------- 创建线程 ---------------------------*/···xTaskCreate(network_task, "network_task", 4096, NULL, 5, NULL);···}/**@brief 通信业务@param 无@return 无*/static void network_task(void *arg){while(1) // 任务都是一个无限循环,不能返回{HandleNetworkService();Delay(1000);// 1s}}

扫描二维码进行AirKiss一键配网

4.3 连接TCP服务器

user_socket.h中修改指定服务器的 IP 地址和端口:

network_task获取到 WIFI 状态已连接路由器成功后,调用Socket_Init()初始化socket通信,连接到指定 TCP 服务器。

成功连接 TCP 服务器后,发送一条内容为TEST的消息。

void HandleNetworkService(void){if(CONNECT_WIFI_FAIL == WIFI_Status()){return;}if(INIT_FAIL == g_isSocketInit){SetNetworkLedStatus(NO_NETWORK);s_isConnectServer = CONNECT_FAIL;g_isSocketInit = Socket_Init(); // 初始化socket通信}else if(INIT_SUCCESS == g_isSocketInit){if(CONNECT_FAIL == s_isConnectServer){SetNetworkLedStatus(IDLE);s_isConnectServer = CONNECT_SUCCESS;BLE_Scan();Socket_Send("TEST");ESP_LOGI(TAG, "socket send TEST\r\n");}// 接收服务器数据char recvDataBuf[MAX_RECV_BUF_SIZE] = {0};int recvDataLen = Socket_Receive(recvDataBuf); // 接收服务器数据if(recvDataLen > 0){handleSocketRecvData(recvDataBuf, recvDataLen);}}}

4.4 发送BLE扫描数据

首先在main.capp_main()中初始化 BLE 模块,然后创建一个monitor_task处理事件业务。

创建一个蓝牙消息队列MsgQueue_Init(g_pMsgQueue);和一个蓝牙 MAC 地址队列MacQueue_Init(g_pMacQueue);

创建蓝牙 MAC 地址过滤定时器CreateFilterMacTimer(),过滤短时间内同一 MAC 地址重复的蓝牙广播包。

void app_main(void){ESP_ERROR_CHECK(nvs_flash_init());/*-------------------------- 外设驱初始化 ---------------------------*/timers_init(); // 定时器驱动初始化(在此加入自定义定时器)···BLE_Init(); // 蓝牙模块初始化BLE_AdvertisingDataInit();BLE_Advertise();/*---------------------------- 队列初始化 -----------------------------*/g_pMsgQueue = (MsgQueue_t *)malloc(sizeof(MsgQueue_t));g_pMacQueue = (MacQueue_t *)malloc(sizeof(MacQueue_t));MsgQueue_Init(g_pMsgQueue);MacQueue_Init(g_pMacQueue);/*-------------------------- 创建线程 ---------------------------*/···xTaskCreate(monitor_task, "monitor_task", 4096, NULL, 4, NULL);···application_timers_start();}static void timers_init(void){esp_timer_init();// 使用定时器API函数,先调用接口初始化···CreateFilterMacTimer();}static void application_timers_start(void){···StartFilterMacTimer();}static void monitor_task(void *arg){while(1) // 任务都是一个无限循环,不能返回{HandleEventService();Delay(100); // 100ms}}

network_task获取到连接 TCP 服务器成功后,开启扫描BLE_Scan()

void HandleNetworkService(void){if(CONNECT_WIFI_FAIL == WIFI_Status()){return;}if(INIT_FAIL == g_isSocketInit){SetNetworkLedStatus(NO_NETWORK);s_isConnectServer = CONNECT_FAIL;g_isSocketInit = Socket_Init(); // 初始化socket通信}else if(INIT_SUCCESS == g_isSocketInit){if(CONNECT_FAIL == s_isConnectServer){···s_isConnectServer = CONNECT_SUCCESS;BLE_Scan();···}···}}

当扫描到蓝牙广播时,进去蓝牙事件处理函数bleEventHandler()处理扫描结果,将蓝牙广播设备的MAC 地址、设备名称、UUID、用户数据和RSSI等依次封装成消息,加入消息队列。

static void bleEventHandler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param){esp_err_t err;switch(event) {···/*--------------------------- 扫描 ---------------------------*/case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {//the unit of the duration is second, 0 means scan permanently// uint32_t duration = 0;// esp_ble_gap_start_scanning(duration);break;}case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT://scan start complete event to indicate scan start successfully or failedif((err = param->scan_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {ESP_LOGE(TAG, "Scan start failed: %s", esp_err_to_name(err));}break;case ESP_GAP_BLE_SCAN_RESULT_EVT: scanResultHandler(param);break;case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:if((err = param->scan_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS){ESP_LOGE(TAG, "Scan stop failed: %s", esp_err_to_name(err));}else {ESP_LOGI(TAG, "Stop scan successfully");}break;default:break;}}/**@brief 处理扫描结果@param 无@return 无*/static void scanResultHandler(esp_ble_gap_cb_param_t *pScanResult){bool result;uint8_array_t advData;uint8_array_t name;uint16_t uuid = 0;uint8_array_t uuidArray;uint8_array_t userData;uint8_t macAddr[ESP_BD_ADDR_LEN] = {0};int8_t rssi = 0;switch(pScanResult->scan_rst.search_evt) {case ESP_GAP_SEARCH_INQ_RES_EVT:// ESP_LOGI(TAG, "----------Device Found----------");advData.p_data = pScanResult->scan_rst.ble_adv;advData.size = pScanResult->scan_rst.adv_data_len + pScanResult->scan_rst.scan_rsp_len;// MAC地址memcpy(macAddr, pScanResult->scan_rst.bda, ESP_BD_ADDR_LEN);// esp_log_buffer_hex("Device address:", pScanResult->scan_rst.bda, ESP_BD_ADDR_LEN);// 设备名称result = BLE_GetNameFromAdv(&advData, &name);if(result == true){// ESP_LOGI(TAG, "searched Device Name Len %d", name.size);// esp_log_buffer_char(TAG, (char *)name.p_data, name.size);}// UUIDresult = BLE_GetUuidFromAdv(&advData, &uuidArray);if(result == true){uuid = U8ToU16LittleEndian(uuidArray.p_data);// ESP_LOGI(TAG, "searched uuid:%04x", uuid);}// 用户数据result = BLE_GetUserDataFromAdv(&advData, &userData);if(result == true){// esp_log_buffer_hex("searched user data:", userData.p_data, userData.size);}// RSSIrssi = pScanResult->scan_rst.rssi;// ESP_LOGI(TAG, "RSSI of packet:%d dbm", pScanResult->scan_rst.rssi);// 检查MAC地址不在待发送消息队列中if(!CheckMac(g_pMacQueue, macAddr) && ESP_BT_DEVICE_TYPE_BLE == pScanResult->scan_rst.dev_type){MacFilter_t *pMac;pMac =(MacFilter_t *)malloc(sizeof(MacFilter_t));memcpy(pMac->addr, pScanResult->scan_rst.bda, ESP_BD_ADDR_LEN); // MAC地址pMac->tick = esp_timer_get_time(); // 当前系统tick,用于过滤重复消息if(MacQueue_GetLength(g_pMacQueue) < MAX_MAC_NUM){MacQueue_PushElement(g_pMacQueue, *pMac); // 加入MAC队列}free(pMac);pMac = NULL;DataType_t *pMsg;pMsg =(DataType_t *)malloc(sizeof(DataType_t));// UUIDpMsg->uuid = uuid;// 广播内容pMsg->adv_data.size = advData.size;pMsg->adv_data.p_data = (uint8_t *)malloc(advData.size * sizeof(uint8_t));memcpy(pMsg->adv_data.p_data, advData.p_data, advData.size);// 信号强度pMsg->rssi = rssi;// MAC地址memcpy(pMsg->addr, pScanResult->scan_rst.bda, ESP_BD_ADDR_LEN);if(MsgQueue_GetLength(g_pMsgQueue) < MAX_MESSAGE_NUM){MsgQueue_PushElement(g_pMsgQueue, *pMsg); // 加入消息队列}else{free(pMsg->adv_data.p_data);pMsg->adv_data.p_data = NULL;}free(pMsg);pMsg = NULL;}break;default:break;}}

monitor_task中,从消息队列中提取消息发送到 TCP 服务端。

4.5 按键发送BLE广播

首先在main.capp_main()中初始化 BLE 模块,然后创建一个monitor_task处理事件业务。创建蓝牙广播停止的定时器CreateKeepAdvertisingTimer(),设备上电广播5秒。

void app_main(void){ESP_ERROR_CHECK(nvs_flash_init());/*-------------------------- 外设驱初始化 ---------------------------*/timers_init(); // 定时器驱动初始化(在此加入自定义定时器)···BLE_Init(); // 蓝牙模块初始化BLE_AdvertisingDataInit();BLE_Advertise();···/*-------------------------- 创建线程 ---------------------------*/···xTaskCreate(monitor_task, "monitor_task", 4096, NULL, 4, NULL);···application_timers_start();}static void timers_init(void){esp_timer_init();// 使用定时器API函数,先调用接口初始化CreateKeepAdvertisingTimer();···}static void application_timers_start(void){StartKeepAdvertisingTimer();···}static void monitor_task(void *arg){while(1) // 任务都是一个无限循环,不能返回{HandleEventService();Delay(100); // 100ms}}

当设备连接上 TCP 服务器时,按下按键通过socket发送消息。

void HandleEventService(void){// 网络连接成功if(CONNECT_SUCCESS == GetConnectServerStatus()){// 发送呼叫if(KEY_CALL_EVENT == GetKeyTriggerEvent()){Buzzer_Beep(SHORT);Socket_Send("CALL");ESP_LOGI(TAG, "socket send CALL\r\n");SetKeyTriggerEvent(0);return;}···}// 网络故障else{···}}

当设备没有连接上 TCP 服务器时,按下按键通过 BLE 广播发送消息。

void HandleEventService(void){// 网络连接成功if(CONNECT_SUCCESS == GetConnectServerStatus()){···}// 网络故障else{if(KEY_CALL_EVENT == GetKeyTriggerEvent()){Buzzer_Beep(SHORT);SetWarningLedStatus(CALL_WARNING);uint8_t data[6] = {0};data[0] = APP_COMPANY_IDENTIFIER_L;data[1] = APP_COMPANY_IDENTIFIER_H;data[2] = 0x11;data[3] = 0x22;data[4] = 0x33;data[5] = 0x44;BLE_SetManufacturerData(data, sizeof(data));BLE_Advertise();// 开启广播StartKeepAdvertisingTimer();SetKeyTriggerEvent(0);}}}

• 由 Leung 写于 年 5 月 17 日

• 参考:【IoT】BLE 蓝牙网关与蓝牙定位技术解析

【安信可PB-01/02模组专题③】ESP32-G WIFI蓝牙网关与PB02模组开发进行组网通讯

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。