ESP32 BLE Server如何识别连接的设备(苹果/微软等)
识别BLE连接设备类型的实现方案
针对你的ESP32 BLE Server项目,要识别苹果、微软等连接设备的类型,这里提供两种可靠的实现思路:
一、通过扫描请求/响应中的厂商特定数据识别(推荐)
苹果、微软等厂商的设备在BLE扫描阶段,通常会在扫描请求或响应中携带厂商特定数据(AD Type为0xFF),其中包含固定的厂商ID。我们可以通过捕获这些数据,关联到后续连接的设备地址,从而识别设备类型。
步骤与代码修改
添加广告回调类,捕获厂商数据
实现BLEAdvertisingCallbacks来解析扫描请求中的厂商数据,将设备地址与厂商类型映射存储:#include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> #include <map> BLEServer* pServer = nullptr; BLECharacteristic* pCharacteristic = nullptr; bool deviceConnected = false; // 存储设备地址到厂商类型的映射 std::map<std::string, std::string> deviceManufacturerMap; // 蓝牙联盟分配的厂商ID:苹果0x004C,微软0x0006 #define APPLE_MANUFACTURER_ID 0x004C #define MICROSOFT_MANUFACTURER_ID 0x0006 class MyAdvertisingCallbacks : public BLEAdvertisingCallbacks { void onScanRequest(BLEAdvertising* pAdvertising, BLEAddress& address, uint8_t* data, uint8_t len) { // 遍历AD数据包,查找厂商特定数据 for (int i = 0; i < len; ) { uint8_t adType = data[i]; uint8_t adLen = data[i+1]; if (adType == 0xFF) { // 厂商特定数据的AD类型标识 // 厂商ID是小端序存储,需要转换为大端序 uint16_t manufacturerId = (data[i+3] << 8) | data[i+2]; std::string deviceAddr = address.toString(); if (manufacturerId == APPLE_MANUFACTURER_ID) { deviceManufacturerMap[deviceAddr] = "Apple"; } else if (manufacturerId == MICROSOFT_MANUFACTURER_ID) { deviceManufacturerMap[deviceAddr] = "Microsoft"; } break; } i += adLen + 2; // 移动到下一个AD单元 } } };修改连接回调,匹配设备类型
在MyServerCallbacks的onConnect方法中,通过连接设备的地址查找之前存储的厂商信息:class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected = true; // 获取连接设备的蓝牙地址 BLEAddress clientAddr = pServer->getPeerAddress(); std::string addrStr = clientAddr.toString(); // 查找对应厂商类型 auto it = deviceManufacturerMap.find(addrStr); if (it != deviceManufacturerMap.end()) { Serial.print("Connected device type: "); Serial.println(it->second.c_str()); // 这里可根据设备类型执行自定义逻辑,比如调整MIDI数据格式 } else { Serial.println("Unknown device type"); } }; void onDisconnect(BLEServer* pServer) { deviceConnected = false; // 断开连接后清除该设备的映射记录(可选) BLEAddress clientAddr = pServer->getPeerAddress(); std::string addrStr = clientAddr.toString(); deviceManufacturerMap.erase(addrStr); } };在setup中绑定广告回调
启动BLE广告前,设置自定义的广告回调:void setup() { Serial.begin(115200); BLEDevice::init("MIDI_BOX"); pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); BLEService *pService = pServer->createService(SERVICE_UUID); pCharacteristic = pService->createCharacteristic( MIDI_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_WRITE_NR ); pCharacteristic->addDescriptor(new BLE2902()); pCharacteristic->setCallbacks(new MyCallbacks()); pService->start(); BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->setScanResponse(true); pAdvertising->setMinPreferred(0x0); // 绑定广告回调 pAdvertising->setCallbacks(new MyAdvertisingCallbacks()); BLEDevice::startAdvertising(); };
二、通过设备名称或特征服务辅助识别
如果部分设备未携带厂商数据,可通过设备名称关键字或支持的特定服务来判断:
- 苹果设备名称通常包含"iPhone"、"iPad"、"Mac"等
- 微软设备名称可能包含"Windows"、"Surface"等
修改onConnect方法获取设备名称:
void onConnect(BLEServer* pServer) { deviceConnected = true; BLEAddress clientAddr = pServer->getPeerAddress(); std::string deviceName = BLEDevice::getName(clientAddr); if (deviceName.find("iPhone") != std::string::npos || deviceName.find("iPad") != std::string::npos || deviceName.find("Mac") != std::string::npos) { Serial.println("Connected device is Apple"); } else if (deviceName.find("Windows") != std::string::npos || deviceName.find("Surface") != std::string::npos) { Serial.println("Connected device is Microsoft"); } else { Serial.println("Unknown device"); } }
注意事项
- 厂商数据的方式准确性更高,不受用户修改设备名称的影响
- 若设备未在扫描请求中携带厂商数据,可尝试在
onAdvertisementReceived回调中捕获广告包中的厂商数据 - 厂商ID可参考蓝牙联盟官方的厂商ID列表
内容的提问来源于stack exchange,提问作者Ben Ayed Ahmed
相关产品推荐
相关产品推荐

