CBCentralManager — کلاس مرکزی فریمورک Core Bluetooth در iOS است که اسکن، اتصال و تعامل با دستگاههای پریفرال BLE را مدیریت میکند. Core Bluetooth (iOS 5+، 2011) یک لایه انتزاعی سطح بالا بر روی پشته BLE در سطح GATT ارائه میدهد و جزئیات Link Layer و HCI را از توسعهدهنده پنهان میکند. CBCentralManager نقش Central را ایفا میکند: اتر را از طریق scanForPeripherals اسکن میکند، اتصال را از طریق connect آغاز میکند، سرویسها را از طریق discoverServices کشف میکند و انتقال داده را مدیریت میکند. طبق Apple Developer Documentation (2024)، CBCentralManager تا 7 اتصال همزمان BLE را در دستگاههای دارای BLE 5.0 پشتیبانی میکند.
نکات کلیدی
CBCentralManager — کلاس اصلی Core Bluetooth برای پیادهسازی نقش Central در معماری BLE در iOS است. این کلاس کل چرخه حیات اتصال BLE را مدیریت میکند: از اسکن دستگاههای در حال تبلیغ تا انتقال داده و قطع اتصال. CBCentralManager به صورت ناهمزمان از طریق دلیگیت CBCentralManagerDelegate کار میکند و رویدادهای پشته Bluetooth را به برنامه اطلاع میدهد.
راهاندازی CBCentralManager فرآیند state restoration را آغاز میکند: مدیر وضعیت بلوتوث را در دستگاه بررسی میکند و اتصالات قبلی را در صورت بسته شدن برنامه بازیابی میکند. فرآیند راهاندازی بسته به وضعیت بلوتوث میتواند 50 تا 500 میلیثانیه طول بکشد. برنامه باید قبل از شروع هرگونه عملیات BLE منتظر فراخوانی centralManagerDidUpdateState بماند.
معماری Core Bluetooth بر اساس الگوی Delegation ساخته شده است: CBCentralManager پردازش رویدادها (کشف دستگاهها، اتصال، خطاها) را به پروتکل CBCentralManagerDelegate واگذار میکند. برای کار با یک Peripheral خاص از پروتکل CBPeripheralDelegate استفاده میشود که در مورد کشف سرویسها، ویژگیها و دریافت داده اطلاعرسانی میکند. این مدل ناهمزمان عملکرد غیرمسدودکننده UI را تضمین میکند.
CBCentralManager از چندین وضعیت عبور میکند که تعیین میکند آیا پشته BLE برای کار در دسترس است یا خیر. وضعیت از طریق دلیگیت منتقل میشود: centralManagerDidUpdateState(_:). توسعهدهنده باید همه وضعیتها را مدیریت کند — نه فقط poweredOn، بلکه مواردی که بلوتوث خاموش است یا در دسترس نیست.
| وضعیت | معنی | اقدام توسعهدهنده |
|---|---|---|
| .poweredOn | بلوتوث روشن و آماده است | شروع اسکن |
| .poweredOff | بلوتوث خاموش است | نمایش هشدار به کاربر |
| .unauthorized | بدون مجوز | درخواست مجوز در تنظیمات |
| .unsupported | دستگاه از BLE پشتیبانی نمیکند | مخفی کردن قابلیتهای BLE |
| .unknown | وضعیت نامشخص | منتظر بهروزرسانی بعدی |
| .resetting | بلوتوث در حال راهاندازی مجدد | منتظر بازیابی |
Unauthorized state از iOS 13+ به طور فزایندهای رایج میشود. از این نسخه به بعد، برنامه باید مجوز NSBluetoothAlwaysUsageDescription را در Info.plist داشته باشد. بدون آن، مدیر مرکزی به وضعیت .unauthorized میرود و اسکن غیرممکن است. کاربر میتواند در هر زمان مجوز را در Settings > Privacy > 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 با Peripheral کشف شده. پس از فراخوانی connect، iOS سعی میکند به دستگاه متصل شود. اتصال موفق با فراخوانی centralManager(_:didConnect:) و خطا با centralManager(_:didFailToConnect:error:) تأیید میشود. گزینههای اتصال شامل CBConnectPeripheralOptionNotifyOnConnectionKey، CBConnectPeripheralOptionNotifyOnDisconnectionKey و CBConnectPeripheralOptionNotifyOnNotificationKey برای اعلانهای پسزمینه است.
// اتصال به دستگاه BLE
func connectToPeripheral(
_ peripheral: CBPeripheral
) {
centralManager.connect(peripheral, options: nil)
// تنظیم دلیگیت برای Peripheral
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 فراخوانی میشود. عوامل مؤثر بر مهلت: فاصله تا دستگاه، تداخلات، اینکه آیا دستگاه در حال حاضر در حال تبلیغ است یا خیر. قبل از اتصال مطمئن شوید دستگاه در حالت connectable advertising است (ADV_IND، نه ADV_NONCONN_IND).
پس از اتصال باید سرویسها (discoverServices) و ویژگیها (discoverCharacteristics) Peripheral کشف شوند. این یک مرحله اجباری قبل از خواندن یا نوشتن داده است. فرآیند ناهمزمان است: discoverServices نتیجه را از طریق peripheral(_:didDiscoverServices:) و discoverCharacteristics از طریق peripheral(_:didDiscoverCharacteristicsFor:error:) برمیگرداند.
توصیه میشود به جای nil، آرایهای از UUIDهای مورد نظر به discoverServices ارسال شود. فیلتر کردن کشف را سرعت میبخشد و در انرژی صرفهجویی میکند. اگر سرویس یافت نشود، iOS یک آرایه خالی گزارش میدهد. پس از کشف ویژگیها، میتوان مقادیر آنها را خواند (readValue)، در اعلانها مشترک شد (setNotifyValue) یا داده نوشت (writeValue).
نکته مهم: MTU به صورت خودکار توافق میشود پس از اتصال. برای دریافت MTU فعلی از peripheral.maximumWriteValueLength(for: .withResponse) یا .withoutResponse استفاده کنید. در iOS حداکثر MTU برای دستگاههای BLE 5.0، 512 بایت است. اگر نیاز به انتقال داده بزرگتر از MTU دارید، fragmentation را در سطح برنامه پیادهسازی کنید.
اسکن پسزمینه دستگاههای BLE در iOS نیاز به پیکربندی ویژه دارد. Core Bluetooth از اجرای پسزمینه پشتیبانی میکند، اما با محدودیتهای قابل توجه. برای کار در پسزمینه لازم است: bluetooth-central را در Background Modes در Capabilities پروژه فعال کنید، CBCentralManager را با گزینه CBCentralManagerOptionRestoreIdentifierKey برای state restoration راهاندازی کنید و رویدادهای مدیر مرکزی را هنگام رفتن به پسزمینه پردازش کنید.
محدودیتهای BLE پسزمینه در iOS: scanForPeripherals بدون فیلتر UUID در پسزمینه کار نمیکند. برنامه باید UUIDهای خاص سرویسها را برای اسکن مشخص کند. iOS ممکن است تحویل رویدادهای BLE را به مدت نامحدود به تأخیر بیندازد. Core Bluetooth به طور خودکار اسکن را هنگام کشف دستگاه منطبق از سر میگیرد، حتی اگر برنامه در پسزمینه باشد. مهلت اسکن پسزمینه: iOS ممکن است برای صرفهجویی در انرژی پس از 10-30 دقیقه اسکن را متوقف کند.
State Restoration — مکانیزم Core Bluetooth که امکان بازیابی اتصالات BLE را پس از راهاندازی مجدد برنامه یا ریبوت iOS فراهم میکند. برای استفاده: CBCentralManagerOptionRestoreIdentifierKey را هنگام راهاندازی مشخص کنید، centralManager(_:willRestoreState:) را در دلیگیت پیادهسازی کنید و لیست Peripheralهای متصل را از دیکشنری ارسالی بازیابی کنید. State Restoration — عملکردی حیاتی برای برنامههای BLE فعال در پسزمینه مانند ردیابهای تناسب اندام یا دستگاههای پزشکی است.
CBCentralManager خطاهایی ایجاد میکند در چند سناریو: اتصال ناموفق (didFailToConnect)، قطع اتصال (didDisconnectPeripheral)، ویژگی برای خواندن/نوشتن در دسترس نیست (didWriteValue error). همه خطاهای Core Bluetooth از طریق شی Error با دامنه CBErrorDomain بازگردانده میشوند. رایجترین کدها: CBErrorConnectionTimeout (0x04)، CBErrorPeripheralDisconnected (0x07)، CBErrorOperationNotSupported (0x0A).
استراتژی بازیابی اتصال: هنگام دریافت didDisconnectPeripheral کد خطا را بررسی کنید. اگر خطا CBErrorConnectionTimeout یا CBErrorPeripheralDisconnected است — اتصال مجدد خودکار را پس از 1-5 ثانیه برنامهریزی کنید. اگر خطا CBErrorOperationNotSupported است — ثبت لاگ کنید و عملیات را تکرار نکنید. برای اتصالات حیاتی (دستگاههای پزشکی) از exponential 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 (نوشتن تأیید شده) استفاده کنید و برای دریافت داده از Peripheral در اعلانها (setNotifyValue) مشترک شوید. برای تشخیص مشکلات اتصال در محیط تولید، لاگ خطاها را نگه دارید.
سوالات متداول
وضعیت مدیر را از طریق centralManagerDidUpdateState بررسی کنید. مطمئن شوید مجوز NSBluetoothAlwaysUsageDescription در Info.plist وجود دارد، بلوتوث در دستگاه روشن است و دستگاه پریفرال با نوع صحیح (connectable advertising، نه non-connectable) در حال تبلیغ است.
در دستگاههای دارای BLE 5.0 (iPhone 8 و جدیدتر) — تا 7 اتصال همزمان. در دستگاههای قدیمیتر — تا 3-5. تعداد دستگاههای اسکن شده محدود نیست، اما اتصالات فعال دارای محدودیت سختی هستند که توسط Bluetooth Controller تعیین شده است.
توصیه میشود با فیلتر UUID اسکن کنید و پس از یافتن دستگاه اسکن را متوقف کنید. اسکن مداوم باتری را تخلیه میکند: 1 ساعت اسکن پیوسته حدود 10-15٪ از شارژ iPhone را مصرف میکند. از تایمرها و شرایط برای توقف اسکن استفاده کنید.
CBCentralManager — برای اسکن و اتصال به دستگاههای BLE خارجی (نقش Central). CBPeripheralManager — برای اینکه دستگاه iOS شما خود به عنوان پریفرال BLE عمل کند (سرویسها را تبلیغ کند). یک نمونه میتواند فقط در یک نقش باشد.
centralManager(_:didDisconnectPeripheral:error:) را پیادهسازی کنید. اگر خطا nil نیست — اتصال مجدد خودکار را با exponential backoff برنامهریزی کنید (1 ثانیه → 2 → 4 → 8 → حداکثر 60). اگر خطا nil است — دستگاه به طور عادی قطع شده است (مثلاً کاربر دکمهای روی دستگاه را فشار داده است).
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید