CBCentralManager คือคลาสหลักของเฟรมเวิร์ก Core Bluetooth ใน iOS ที่จัดการการสแกน การเชื่อมต่อ และการโต้ตอบกับอุปกรณ์ต่อพ่วง BLE Core Bluetooth (iOS 5+, 2011) ให้การมองเห็นในระดับสูงเหนือสแต็ก BLE ในระดับ GATT โดยซ่อนรายละเอียดของ Link Layer และ HCI จากนักพัฒนา CBCentralManager เรียกใช้บทบาท Central: มันสแกนคลื่นอากาศผ่าน scanForPeripherals เริ่มต้นการเชื่อมต่อผ่าน connect ค้นพบบริการผ่าน discoverServices และจัดการการถ่ายโอนข้อมูล ตามเอกสารสำหรับนักพัฒนาของ Apple (2024) CBCentralManager รองรับการเชื่อมต่อพร้อมกันสูงสุด 7 รายการไปยังอุปกรณ์ BLE บนอุปกรณ์ที่ใช้ BLE 5.0
ประเด็นสำคัญ
CBCentralManager คือคลาสหลักของ Core Bluetooth สำหรับการเรียกใช้บทบาท Central ในสถาปัตยกรรม BLE บน iOS มันจัดการวงจรชีวิตทั้งหมดของการเชื่อมต่อ BLE ตั้งแต่การสแกนอุปกรณ์ที่โฆษณาไปจนถึงการถ่ายโอนข้อมูลและการตัดการเชื่อมต่อ CBCentralManager ทำงานแบบอะซิงโครนัสผ่านตัวแทน CBCentralManagerDelegate โดยแจ้งให้แอปทราบเกี่ยวกับเหตุการณ์ในสแต็ก Bluetooth
การเริ่มต้น CBCentralManager จะเริ่มกระบวนการ state restoration: ผู้จัดการจะตรวจสอบสถานะ Bluetooth บนอุปกรณ์และกู้คืนการเชื่อมต่อก่อนหน้าหากแอปถูกปิด กระบวนการเริ่มต้นอาจใช้เวลา 50 ถึง 500 มิลลิวินาทีขึ้นอยู่กับสถานะ Bluetooth แอปต้องรอการเรียก centralManagerDidUpdateState ก่อนเริ่มดำเนินการ BLE ใดๆ
สถาปัตยกรรม Core Bluetooth สร้างขึ้นบนรูปแบบ Delegation: CBCentralManager มอบหมายการจัดการเหตุการณ์ (การค้นหาอุปกรณ์ การเชื่อมต่อ ข้อผิดพลาด) ให้กับโปรโตคอล CBCentralManagerDelegate สำหรับการทำงานกับอุปกรณ์ต่อพ่วงเฉพาะ จะใช้โปรโตคอล CBPeripheralDelegate ซึ่งแจ้งเกี่ยวกับบริการ คุณลักษณะ และข้อมูลที่ได้รับที่ค้นพบ โมเดลอะซิงโครนัสนี้รับประกันอินเทอร์เฟซผู้ใช้ที่ไม่บล็อก
CBCentralManager ผ่านหลายสถานะ ซึ่งกำหนดว่าสแต็ก BLE พร้อมใช้งานหรือไม่ สถานะจะถูกส่งผ่านตัวแทน: centralManagerDidUpdateState(_:) นักพัฒนาต้องจัดการทุกสถานะ — ไม่ใช่แค่ poweredOn แต่ยังรวมถึงกรณีที่ Bluetooth ปิดหรือไม่พร้อมใช้งาน
| สถานะ | ค่า | การดำเนินการของนักพัฒนา |
|---|---|---|
| .poweredOn | Bluetooth เปิดและพร้อม | เริ่มสแกน |
| .poweredOff | Bluetooth ปิด | แสดงการแจ้งเตือนแก่ผู้ใช้ |
| .unauthorized | ไม่มีสิทธิ์ | ขอสิทธิ์ในการตั้งค่า |
| .unsupported | อุปกรณ์ไม่รองรับ BLE | ซ่อนฟังก์ชัน BLE |
| .unknown | สถานะไม่ถูกกำหนด | รอการอัปเดตครั้งถัดไป |
| .resetting | Bluetooth กำลังรีสตาร์ท | รอการกู้คืน |
สถานะไม่ได้รับอนุญาต กำลังกลายเป็นเรื่องปกติมากขึ้นตั้งแต่ iOS 13+ เริ่มจากเวอร์ชันนี้ แอปต้องมีสิทธิ์ NSBluetoothAlwaysUsageDescription ใน Info.plist หากไม่มี ผู้จัดการส่วนกลางจะเปลี่ยนเป็นสถานะ .unauthorized และการสแกนจะเป็นไปไม่ได้ ผู้ใช้สามารถเปลี่ยนสิทธิ์ได้ในการตั้งค่า > ความเป็นส่วนตัว > Bluetooth ได้ตลอดเวลา
scanForPeripherals(withServices:options:) เป็นวิธีการหลักในการเริ่มการสแกน พารามิเตอร์ withServices ยอมรับอาร์เรย์ของ UUID บริการสำหรับการกรอง: หากส่ง nil อุปกรณ์ทั้งหมดจะถูกค้นพบ ซึ่งเพิ่มการใช้พลังงานอย่างมาก ขอแนะนำให้กรองตาม UUID บริการที่แอปต้องการเสมอ ตัวเลือกการสแกนรวมถึง CBCentralManagerScanOptionAllowDuplicatesKey (การแจ้งเตือนซ้ำเกี่ยวกับอุปกรณ์เดียวกัน)
import CoreBluetooth
class BLEController: NSObject,
CBCentralManagerDelegate {
private var centralManager: CBCentralManager!
override init() {
super.init()
centralManager =
CBCentralManager(
delegate: self,
queue: nil
)
}
func startScanning() {
let serviceUUID =
CBUUID("180F") // บริการแบตเตอรี่
centralManager.scanForPeripherals(
withServices: [serviceUUID],
options: [
CBCentralManagerScanOptionAllowDuplicatesKey: false
]
)
}
}
เมื่อค้นพบอุปกรณ์ จะเรียก centralManager(_:didDiscover:advertisementData:rssi:) พารามิเตอร์ advertisementData มีพจนานุกรมเต็มรูปแบบของข้อมูลแพ็กเก็ตโฆษณา รวมถึงชื่ออุปกรณ์ (CBAdvertisementDataLocalNameKey) UUID บริการ (CBAdvertisementDataServiceUUIDsKey) และข้อมูลผู้ผลิต (CBAdvertisementDataManufacturerDataKey) RSSI คือระดับสัญญาณในหน่วย dBm ที่มีอยู่ในขณะที่ค้นพบ
connect(_:options:) เป็นวิธีการสร้างการเชื่อมต่อ BLE กับอุปกรณ์ต่อพ่วงที่ค้นพบ หลังจากเรียก connect iOS จะพยายามเชื่อมต่อกับอุปกรณ์ การเชื่อมต่อที่สำเร็จจะได้รับการยืนยันผ่าน centralManager(_:didConnect:) ข้อผิดพลาดผ่าน centralManager(_:didFailToConnect:error:) ตัวเลือกการเชื่อมต่อรวมถึง CBConnectPeripheralOptionNotifyOnConnectionKey, CBConnectPeripheralOptionNotifyOnDisconnectionKey และ CBConnectPeripheralOptionNotifyOnNotificationKey สำหรับการแจ้งเตือนพื้นหลัง
// เชื่อมต่อกับอุปกรณ์ BLE
func connectToPeripheral(
_ peripheral: CBPeripheral
) {
centralManager.connect(peripheral, options: nil)
// ตั้งค่าตัวแทนสำหรับอุปกรณ์ต่อพ่วง
peripheral.delegate = self
}
// ตัวแทน: การเชื่อมต่อสำเร็จ
func centralManager(
_ central: CBCentralManager,
didConnect peripheral: CBPeripheral
) {
print("เชื่อมต่อกับ " +
"\(peripheral.name ?? "unknown")")
// เริ่มการค้นหาบริการ
peripheral.discoverServices(nil)
}
// ตัวแทน: ข้อผิดพลาดการเชื่อมต่อ
func centralManager(
_ central: CBCentralManager,
didFailToConnect peripheral: CBPeripheral,
error: Error?
) {
print("Connection failed:
\(error?.localizedDescription ?? "")")
}
การหมดเวลาการเชื่อมต่อ บน iOS คือ 30 วินาที หากอุปกรณ์ไม่ตอบสนองต่อคำขอเชื่อมต่อภายในเวลานี้ จะเรียก didFailToConnect การหมดเวลาได้รับผลกระทบจาก: ระยะทางไปยังอุปกรณ์ การรบกวน และอุปกรณ์กำลังโฆษณาอยู่หรือไม่ ก่อนเชื่อมต่อ ตรวจสอบให้แน่ใจว่าอุปกรณ์อยู่ในโหมดโฆษณาที่สามารถเชื่อมต่อได้ (ADV_IND ไม่ใช่ ADV_NONCONN_IND)
หลังจากการเชื่อมต่อ คุณต้องค้นหาบริการ (discoverServices) และคุณลักษณะ (discoverCharacteristics) ของอุปกรณ์ต่อพ่วง นี่เป็นขั้นตอนบังคับก่อนอ่านหรือเขียนข้อมูล กระบวนการเป็นแบบอะซิงโครนัส: discoverServices ส่งคืนผลลัพธ์ผ่าน peripheral(_:didDiscoverServices:) และ discoverCharacteristics ผ่าน peripheral(_:didDiscoverCharacteristicsFor:error:)
ขอแนะนำให้ส่งอาร์เรย์ของ UUID ที่เกี่ยวข้องไปยัง discoverServices แทน nil การกรองช่วยเร่งการค้นหาและประหยัดพลังงาน หากไม่พบบริการ iOS จะรายงานอาร์เรย์ว่าง หลังจากค้นพบคุณลักษณะ คุณสามารถอ่านค่า (readValue) สมัครรับการแจ้งเตือน (setNotifyValue) หรือเขียนข้อมูล (writeValue)
ความแตกต่างที่สำคัญ: MTU จะถูกเจรจาโดยอัตโนมัติ หลังจากการเชื่อมต่อ หากต้องการรับ MTU ปัจจุบัน ให้ใช้ peripheral.maximumWriteValueLength(for: .withResponse) หรือ .withoutResponse บน iOS MTU สูงสุดคือ 512 ไบต์สำหรับอุปกรณ์ BLE 5.0 หากคุณต้องการถ่ายโอนข้อมูลที่ใหญ่กว่า MTU ให้ใช้การแยกส่วนในระดับแอปพลิเคชัน
การสแกนพื้นหลัง ของอุปกรณ์ BLE บน iOS ต้องมีการกำหนดค่าพิเศษ Core Bluetooth รองรับการทำงานพื้นหลัง แต่มีข้อจำกัดที่สำคัญ ในการทำงานพื้นหลัง คุณต้อง: เปิดใช้งาน bluetooth-central ใน Background Modes ในความสามารถของโครงการ เริ่มต้น CBCentralManager ด้วยตัวเลือก CBCentralManagerOptionRestoreIdentifierKey สำหรับการกู้คืนสถานะ และจัดการเหตุการณ์ของผู้จัดการส่วนกลางเมื่อเปลี่ยนไปพื้นหลัง
ข้อจำกัด BLE พื้นหลังบน iOS: scanForPeripherals โดยไม่มีการกรอง UUID จะไม่ทำงานในพื้นหลัง แอปต้องระบุ UUID บริการที่เฉพาะเจาะจงสำหรับการสแกน iOS อาจชะลอการส่งมอบเหตุการณ์ BLE อย่างไม่มีกำหนด Core Bluetooth จะเริ่มการสแกนใหม่โดยอัตโนมัติเมื่อพบอุปกรณ์ที่ตรงกัน แม้ว่าแอปจะอยู่ในพื้นหลังก็ตาม การหมดเวลาสำหรับการสแกนพื้นหลัง: iOS อาจหยุดการสแกนหลังจาก 10–30 นาทีเพื่อประหยัดพลังงาน
State Restoration เป็นกลไกของ Core Bluetooth ที่ช่วยให้กู้คืนการเชื่อมต่อ BLE หลังจากรีสตาร์ทแอปหรือรีบูต iOS หากต้องการใช้: ระบุ CBCentralManagerOptionRestoreIdentifierKey ระหว่างการเริ่มต้น เรียกใช้ centralManager(_:willRestoreState:) ในตัวแทน และกู้คืนรายการอุปกรณ์ต่อพ่วงที่เชื่อมต่อจากพจนานุกรมที่ส่งผ่าน State Restoration เป็นฟังก์ชันที่สำคัญสำหรับแอป BLE ที่ทำงานในพื้นหลัง เช่น อุปกรณ์ติดตามการออกกำลังกายหรืออุปกรณ์ทางการแพทย์
CBCentralManager สร้างข้อผิดพลาด ในหลายสถานการณ์: การเชื่อมต่อล้มเหลว (didFailToConnect) การเชื่อมต่อขาด (didDisconnectPeripheral) คุณลักษณะไม่พร้อมใช้งานสำหรับการอ่าน/เขียน (ข้อผิดพลาด didWriteValue) ข้อผิดพลาด Core Bluetooth ทั้งหมดจะถูกส่งคืนผ่านวัตถุ Error ที่มีโดเมน CBErrorDomain รหัสที่พบบ่อยที่สุด: CBErrorConnectionTimeout (0x04), CBErrorPeripheralDisconnected (0x07), CBErrorOperationNotSupported (0x0A)
กลยุทธ์การกู้คืนการเชื่อมต่อ: เมื่อได้รับ didDisconnectPeripheral ให้ตรวจสอบรหัสข้อผิดพลาด หากข้อผิดพลาดคือ CBErrorConnectionTimeout หรือ CBErrorPeripheralDisconnected — กำหนดเวลาการเชื่อมต่อใหม่อัตโนมัติใน 1–5 วินาที หากข้อผิดพลาดคือ CBErrorOperationNotSupported — ให้บันทึกและไม่ลองดำเนินการซ้ำ สำหรับการเชื่อมต่อที่สำคัญ (อุปกรณ์ทางการแพทย์) ให้ใช้ backoff แบบเอกซ์โปเนนเชียลด้วยช่วงเวลาสูงสุด 60 วินาที
// จัดการการตัดการเชื่อมต่อด้วยการเชื่อมต่อใหม่อัตโนมัติ
func centralManager(
_ central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?
) {
guard let error = error else {
return // การตัดการเชื่อมต่อที่คาดหวัง
}
print("Disconnected: \(error.localizedDescription)")
// การเชื่อมต่อใหม่อัตโนมัติ
if shouldAutoReconnect {
DispatchQueue.main.asyncAfter(
deadline: .now() + reconnectDelay
) {
central.connect(peripheral)
}
}
}
เมื่อพัฒนาแอป BLE ที่แข็งแกร่งบน iOS โปรดทราบ: Core Bluetooth ไม่รับประกันการส่งแพ็กเก็ตทั้งหมดเมื่อสัญญาณอ่อน สำหรับการส่งที่เชื่อถือได้ ให้ใช้ writeType .withResponse (การเขียนที่ยืนยันแล้ว) และสมัครรับการแจ้งเตือน (setNotifyValue) เพื่อรับข้อมูลจากอุปกรณ์ต่อพ่วง เก็บบันทึกข้อผิดพลาดเพื่อวินิจฉัยปัญหาการเชื่อมต่อในการผลิต
คำถามที่พบบ่อย
ตรวจสอบสถานะของผู้จัดการผ่าน centralManagerDidUpdateState ตรวจสอบให้แน่ใจว่ามีสิทธิ์ NSBluetoothAlwaysUsageDescription ใน Info.plist Bluetooth เปิดอยู่บนอุปกรณ์ และอุปกรณ์ต่อพ่วงกำลังโฆษณาด้วยประเภทที่ถูกต้อง (โฆษณาที่เชื่อมต่อได้ ไม่ใช่แบบไม่สามารถเชื่อมต่อได้)
บนอุปกรณ์ที่ใช้ BLE 5.0 (iPhone 8 ขึ้นไป) — สูงสุด 7 การเชื่อมต่อพร้อมกัน บนอุปกรณ์รุ่นเก่า — สูงสุด 3–5 จำนวนอุปกรณ์ที่สแกนไม่มีจำกัด แต่การเชื่อมต่อที่ใช้งานอยู่มีขีดจำกัดที่กำหนดโดยตัวควบคุม Bluetooth
ขอแนะนำให้ สแกนด้วยการกรอง UUID และหยุดสแกนเมื่อพบอุปกรณ์ การสแกนอย่างต่อเนื่องทำให้แบตเตอรี่หมด: การสแกน 1 ชั่วโมงโดยไม่หยุดชะงักกินไฟประมาณ ~10–15% ของแบตเตอรี่ iPhone ใช้ตัวจับเวลาและเงื่อนไขเพื่อหยุดการสแกน
CBCentralManager สำหรับการสแกนและเชื่อมต่อกับอุปกรณ์ BLE ภายนอก (บทบาท Central) CBPeripheralManager สำหรับให้อุปกรณ์ iOS ของคุณทำหน้าที่เป็นอุปกรณ์ต่อพ่วง BLE (โฆษณาบริการ) หนึ่งอินสแตนซ์สามารถอยู่ในบทบาทเดียวเท่านั้น
เรียกใช้ centralManager(_:didDisconnectPeripheral:error:) หากข้อผิดพลาดไม่ใช่ nil — กำหนดเวลาการเชื่อมต่อใหม่อัตโนมัติด้วย backoff แบบเอกซ์โปเนนเชียล (1 วินาที → 2 วินาที → 4 วินาที → 8 วินาที → สูงสุด 60 วินาที) หากข้อผิดพลาดเป็น nil — อุปกรณ์ตัดการเชื่อมต่อตามปกติ (เช่น ผู้ใช้กดปุ่มบนอุปกรณ์)
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม