如何通过CoreBluetooth连接指定BLE设备?ESP32+iOS舵机控制需求
CoreBluetooth 连接指定ESP32 BLE设备示例
核心逻辑
要精准连接你的ESP32,优先通过自定义服务UUID(最可靠)、设备名称或设备UUID(单设备固定)过滤扫描结果,避免连接无关设备。以下是完整实现代码。
iOS 端代码实现
1. 基础配置与代理声明
import CoreBluetooth class BLEController: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate { private var centralManager: CBCentralManager! // 替换为你ESP32上定义的自定义服务UUID private let targetServiceUUID = CBUUID(string: "0000FFE0-0000-1000-8000-00805F9B34FB") // 可选:ESP32的设备UUID(可从iOS蓝牙设置→该设备→信息中获取) private let targetPeripheralUUID = UUID(uuidString: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX") private var connectedPeripheral: CBPeripheral? }
2. 初始化蓝牙管理器
override init() { super.init() // 主线程队列处理蓝牙回调 centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main) }
3. 蓝牙状态检查与扫描/连接触发
func centralManagerDidUpdateState(_ central: CBCentralManager) { switch central.state { case .poweredOn: // 方案1:直接通过设备UUID连接(适用于已配对过的设备) if let uuid = targetPeripheralUUID { if let peripheral = central.retrievePeripherals(withIdentifiers: [uuid]).first { central.connect(peripheral, options: nil) return } } // 方案2:按服务UUID扫描(只返回包含目标服务的设备,效率更高) central.scanForPeripherals(withServices: [targetServiceUUID], options: [ CBCentralManagerScanOptionAllowDuplicatesKey: false ]) case .poweredOff: print("蓝牙已关闭") default: print("蓝牙不可用") } }
4. 扫描结果过滤与连接
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { // 双重过滤:设备名称 + 服务UUID,确保精准匹配 let targetDeviceName = "ESP32_SERVO_CTRL" // 替换为你的ESP32设备名称 if peripheral.name == targetDeviceName || peripheral.services?.contains(where: { $0.uuid == targetServiceUUID }) == true { central.stopScan() connectedPeripheral = peripheral peripheral.delegate = self central.connect(peripheral, options: nil) } }
5. 连接成功后发现服务与特征
// 连接成功回调 func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { print("已连接到ESP32:\(peripheral.name ?? "未知设备")") // 发现目标服务 peripheral.discoverServices([targetServiceUUID]) } // 发现服务后查找舵机控制特征 func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { guard let services = peripheral.services, error == nil else { print("发现服务失败:\(error?.localizedDescription ?? "未知错误")") return } for service in services where service.uuid == targetServiceUUID { // 替换为你定义的舵机控制特征UUID let servoCharUUID = CBUUID(string: "0000FFE1-0000-1000-8000-00805F9B34FB") peripheral.discoverCharacteristics([servoCharUUID], for: service) } } // 发现特征后即可读写数据控制舵机 func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { guard let characteristics = service.characteristics, error == nil else { return } for char in characteristics where char.uuid == CBUUID(string: "0000FFE1-0000-1000-8000-00805F9B34FB") { // 示例:发送舵机控制指令,比如"1:90"表示舵机1转到90度 let cmd = "1:90".data(using: .utf8)! peripheral.writeValue(cmd, for: char, type: .withResponse) } }
ESP32 端配套代码(Arduino)
确保ESP32的BLE服务、特征UUID与iOS端完全匹配:
#include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> #include <Servo.h> // 与iOS端一致的UUID #define SERVICE_UUID "0000FFE0-0000-1000-8000-00805F9B34FB" #define CHARACTERISTIC_UUID "0000FFE1-0000-1000-8000-00805F9B34FB" Servo servo1; Servo servo2; BLEServer* pServer = NULL; BLECharacteristic* pCharacteristic = NULL; class MyCallbacks: public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { std::string value = pCharacteristic->getValue(); if (value.length() > 0) { // 解析指令格式:"舵机编号:角度" int servoNum = value[0] - '0'; int angle = atoi(value.substr(2).c_str()); switch(servoNum) { case 1: servo1.write(angle); break; case 2: servo2.write(angle); break; } } } }; void setup() { servo1.attach(2); // 舵机1接GPIO2 servo2.attach(4); // 舵机2接GPIO4 BLEDevice::init("ESP32_SERVO_CTRL"); // 与iOS端一致的设备名称 pServer = BLEDevice::createServer(); BLEService *pService = pServer->createService(SERVICE_UUID); pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ ); pCharacteristic->setCallbacks(new MyCallbacks()); pService->start(); // 广播服务UUID,让iOS能快速识别 BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->start(); } void loop() { delay(100); }
关键注意事项
- 权限配置:在iOS项目的
Info.plist中添加NSBluetoothAlwaysUsageDescription和NSBluetoothPeripheralUsageDescription,填写权限申请说明。 - 设备UUID特性:同一BLE设备在同一iOS设备上的UUID固定,但跨iOS设备会不同,因此优先用服务UUID或设备名称做跨设备兼容。
- 错误处理:需实现
didFailToConnectPeripheral、didDisconnectPeripheral等代理方法处理连接失败、断开重连场景。
内容的提问来源于stack exchange,提问作者MWD_NAME
相关产品推荐
相关产品推荐

