You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32 BLE Server如何识别连接的设备(苹果/微软等)

识别BLE连接设备类型的实现方案

针对你的ESP32 BLE Server项目,要识别苹果、微软等连接设备的类型,这里提供两种可靠的实现思路:

一、通过扫描请求/响应中的厂商特定数据识别(推荐)

苹果、微软等厂商的设备在BLE扫描阶段,通常会在扫描请求或响应中携带厂商特定数据(AD Type为0xFF),其中包含固定的厂商ID。我们可以通过捕获这些数据,关联到后续连接的设备地址,从而识别设备类型。

步骤与代码修改

  1. 添加广告回调类,捕获厂商数据
    实现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单元
            }
        }
    };
    
  2. 修改连接回调,匹配设备类型
    在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);
        }
    };
    
  3. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 10:54:18