CBCentralManager — este clasa centrală a framework-ului Core Bluetooth în iOS, care gestionează scanarea, conectarea și interacțiunea cu dispozitivele periferice BLE. Core Bluetooth (iOS 5+, 2011) oferă o abstractizare de nivel înalt peste stiva BLE la nivel GATT, ascunzând dezvoltatorului detaliile Link Layer și HCI. CBCentralManager îndeplinește rolul Central: scanează eterul prin scanForPeripherals, inițioază conexiunea prin connect, descoperă servicii prin discoverServices și gestionează transferul de date. Conform Apple Developer Documentation (2024), CBCentralManager suportă până la 7 conexiuni BLE simultane pe dispozitive cu BLE 5.0.
Puncte cheie
CBCentralManager — este clasa principală Core Bluetooth pentru implementarea rolului Central în arhitectura BLE pe iOS. Gestionează înntregul ciclu de viață al conexiunii BLE: de la scanarea dispozitivelor care se publicită până la transferul de date și deconectare. CBCentralManager lucrează asincron prin delegatul CBCentralManagerDelegate, notificând aplicația despre evenimentele din stiva Bluetooth.
Inițializarea CBCentralManager pornește procesul de state restoration: managerul verifică starea Bluetooth pe dispozitiv și restabilește conexiunile anterioare dacă aplicația a fost închisă. Procesul de inițializare poate dura între 50 și 500 ms în funcție de starea Bluetooth. Aplicația trebuie să aștepte apelul centralManagerDidUpdateState înainte de a îNCEpe orice operațiuni BLE.
Arhitectura Core Bluetooth este construită pe modelul Delegation: CBCentralManager delegă procesarea evenimentelor (descoperirea dispozitivelor, conectare, erori) protocolului CBCentralManagerDelegate. Pentru lucrul cu un Peripheral specific se utilizează protocolul CBPeripheralDelegate, care notifică despre descoperirea serviciilor, caracteristicilor și primirea datelor. Acest model asincron asigură funcționarea neblocantă a UI-ului.
CBCentralManager trece prin mai multe stări care determină dacă stiva BLE este disponibilă pentru lucru. Starea este transmisă prin delegat: centralManagerDidUpdateState(_:). Dezvoltatorul trebuie să gestioneze toate stările — nu doar poweredOn, ci și cazurile când Bluetooth este oprit sau indisponibil.
| Stare | Semnificație | Acțiunea dezvoltatorului |
|---|---|---|
| .poweredOn | Bluetooth este pornit și pregătit | Începe scanarea |
| .poweredOff | Bluetooth este oprit | Afișează un alert utilizatorului |
| .unauthorized | Fără permisiune | Solicită permisiunea în Setări |
| .unsupported | Dispozitivul nu suportă BLE | Ascunde funcțiile BLE |
| .unknown | Stare nedefinită | Așteaptă următoarea actualizare |
| .resetting | Bluetooth se repornește | Așteaptă restabilirea |
Unauthorized state devine din ce în ce mai frecventă începând cu iOS 13+. De la această versiune, aplicația trebuie să aibă permisiunea NSBluetoothAlwaysUsageDescription în Info.plist. Fără ea, managerul central trece în starea .unauthorized, iar scanarea este imposibilă. Utilizatorul poate modifica permisiunea în orice moment în Settings > Privacy > Bluetooth.
scanForPeripherals(withServices:options:) — metoda principală pentru pornirea scanării. Parametrul withServices primește un array de UUID-uri ale serviciilor pentru filtrare: dacă se trimite nil, vor fi descoperite toate dispozitivele, ceea ce crește semnificativ consumul de energie. Se recomandă să filtrați întotdeauna după UUID-urile serviciilor de care are nevoie aplicația. Opțiunile de scanare includ CBCentralManagerScanOptionAllowDuplicatesKey (notificări repetate despre același dispozitiv).
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") // Serviciul Baterie
centralManager.scanForPeripherals(
withServices: [serviceUUID],
options: [
CBCentralManagerScanOptionAllowDuplicatesKey: false
]
)
}
}
La descoperirea unui dispozitiv, este apelat centralManager(_:didDiscover:advertisementData:rssi:). Parametrul advertisementData conține un dicționar complet al datelor pachetului de publicitate, inclusiv numele dispozitivului (CBAdvertisementDataLocalNameKey), UUID-urile serviciilor (CBAdvertisementDataServiceUUIDsKey) și datele producătorului (CBAdvertisementDataManufacturerDataKey). RSSI — nivelul semnalului în dBm, disponibil în momentul descoperirii.
connect(_:options:) — metoda pentru stabilirea conexiunii BLE cu Peripheral-ul descoperit. După apelul connect, iOS încearcă să se conecteze la dispozitiv. Conexiunea reușită este confirmată prin apelul centralManager(_:didConnect:), iar eroarea prin centralManager(_:didFailToConnect:error:). Opțiunile de conectare includ CBConnectPeripheralOptionNotifyOnConnectionKey, CBConnectPeripheralOptionNotifyOnDisconnectionKey și CBConnectPeripheralOptionNotifyOnNotificationKey pentru notificări în fundal.
// Conectare la dispozitiv BLE
func connectToPeripheral(
_ peripheral: CBPeripheral
) {
centralManager.connect(peripheral, options: nil)
// Setează delegat pentru Peripheral
peripheral.delegate = self
}
// Delegat: conexiune reușită
func centralManager(
_ central: CBCentralManager,
didConnect peripheral: CBPeripheral
) {
print("Conectat la " +
"\(peripheral.name ?? "unknown")")
// Începe descoperirea serviciilor
peripheral.discoverServices(nil)
}
// Delegat: eroare de conectare
func centralManager(
_ central: CBCentralManager,
didFailToConnect peripheral: CBPeripheral,
error: Error?
) {
print("Connection failed:
\(error?.localizedDescription ?? "")")
}
Timpul de expirare a conexiunii pe iOS este de 30 de secunde. Dacă în acest timp dispozitivul nu răspunde la cererea de conectare, este apelat didFailToConnect. Factorii care influențează expirarea: distanța până la dispozitiv, interferențele, dacă dispozitivul se publicită în acel moment. Înainte de conectare, asigurați-vă că dispozitivul este în modul connectable advertising (ADV_IND, nu ADV_NONCONN_IND).
După conectare trebuie descoperite serviciile (discoverServices) și caracteristicile (discoverCharacteristics) ale Peripheral-ului. Acesta este un pas obligatoriu înainte de citirea sau scrierea datelor. Procesul este asincron: discoverServices returnează rezultatul prin peripheral(_:didDiscoverServices:), iar discoverCharacteristics prin peripheral(_:didDiscoverCharacteristicsFor:error:).
Se recomandă să trimiteți în discoverServices un array de UUID-uri de interes, nu nil. Filtrarea accelerează descoperirea și economisește energie. Dacă serviciul nu este găsit, iOS va raporta un array gol. După descoperirea caracteristicilor, puteți citi valorile lor (readValue), vă puteți abona la notificări (setNotifyValue) sau scrie date (writeValue).
Un detaliu important: MTU este negociat automat după conectare. Pentru a obține MTU-ul curent, utilizați peripheral.maximumWriteValueLength(for: .withResponse) sau .withoutResponse. În iOS, MTU-ul maxim este de 512 octeți pentru dispozitivele BLE 5.0. Dacă trebuie să transferați date mai mari decât MTU, implementați fragmentarea la nivelul aplicației.
Scanarea în fundal a dispozitivelor BLE pe iOS necesită o configurare specială. Core Bluetooth suportă execuția în fundal, dar cu limitări semnificative. Pentru a funcționa în fundal, este necesar: să activați bluetooth-central în Background Modes în Capabilities ale proiectului, să inițializați CBCentralManager cu opțiunea CBCentralManagerOptionRestoreIdentifierKey pentru state restoration și să gestionați evenimentele managerului central la trecerea în fundal.
Limitările BLE în fundal în iOS: scanForPeripherals fără filtrare după UUID nu funcționează în fundal. Aplicația trebuie să specifice UUID-uri concrete ale serviciilor pentru scanare. iOS poate întârzia livrarea evenimentelor BLE pe o perioadă nedeterminată. Core Bluetooth reia automat scanarea la descoperirea unui dispozitiv potrivit, chiar dacă aplicația este în fundal. Expirarea scanării în fundal: iOS poate opri scanarea după 10–30 de minute pentru economisirea energiei.
State Restoration — mecanismul Core Bluetooth care permite restabilirea conexiunilor BLE după repornirea aplicației sau repornirea iOS. Pentru utilizare: specificați CBCentralManagerOptionRestoreIdentifierKey la inițializare, implementați centralManager(_:willRestoreState:) în delegat și restabiliți lista Peripheral-urilor conectate din dicționarul transmis. State Restoration este o funcționalitate critică pentru aplicațiile BLE care funcționează în fundal, cum ar fi trackerele de fitness sau dispozitivele medicale.
CBCentralManager generează erori în mai multe scenarii: conexiunea a eșuat (didFailToConnect), conexiunea a fost înreruptă (didDisconnectPeripheral), caracteristica nu este disponibilă pentru citire/scriere (didWriteValue error). Toate erorile Core Bluetooth sunt returnate prin obiectul Error cu domeniul CBErrorDomain. Cele mai frecvente coduri: CBErrorConnectionTimeout (0x04), CBErrorPeripheralDisconnected (0x07), CBErrorOperationNotSupported (0x0A).
Strategia de restabilire a conexiunii: la primirea didDisconnectPeripheral, verificați codul de eroare. Dacă eroarea este CBErrorConnectionTimeout sau CBErrorPeripheralDisconnected — programați reconectarea automată după 1–5 secunde. Dacă eroarea este CBErrorOperationNotSupported — înregistrați și nu încercați să repetați operațiunea. Pentru conexiunile critice (dispozitive medicale), utilizați exponential backoff cu un interval maxim de 60 de secunde.
// Gestionare deconectare cu reconectare automată
func centralManager(
_ central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?
) {
guard let error = error else {
return // Deconectare așteptată
}
print("Disconnected: \(error.localizedDescription)")
// Reconectare automată
if shouldAutoReconnect {
DispatchQueue.main.asyncAfter(
deadline: .now() + reconnectDelay
) {
central.connect(peripheral)
}
}
}
La dezvoltarea unei aplicații BLE fiabile pe iOS, luați în considerare: Core Bluetooth nu garantează livrarea tuturor pachetelor atunci când semnalul este slab. Pentru un transfer fiabil, utilizați writeType .withResponse (scriere confirmată) și abonați-vă la notificări (setNotifyValue) pentru a primi date de la Peripheral. Păstrați un jurnal al erorilor pentru a diagnostica problemele de conexiune în producție.
întrebări frecvente
Verificați starea managerului prin centralManagerDidUpdateState. Asigurați-vă că permisiunea NSBluetoothAlwaysUsageDescription există în Info.plist, Bluetooth este activat pe dispozitiv, iar dispozitivul periferic se publicită cu tipul corect (connectable advertising, nu non-connectable).
Pe dispozitivele cu BLE 5.0 (iPhone 8 și mai noi) — până la 7 conexiuni simultane. Pe dispozitivele mai vechi — până la 3–5. Numărul de dispozitive scanate este nelimitat, dar conexiunile active au o limită strictă stabilită de Bluetooth Controller.
Se recomandă scanarea cu filtru după UUID și oprirea scanării atunci când dispozitivul este găsit. Scanarea continuă consumă bateria: 1 oră de scanare neîntreruptă consumă aproximativ 10–15% din bateria iPhone. Utilizați temporizatoare și condiții pentru a opri scanarea.
CBCentralManager — pentru scanarea și conectarea la dispozitive BLE externe (rol Central). CBPeripheralManager — pentru ca dispozitivul iOS să acționeze ca periferic BLE (să publice servicii). O instanță poate fi doar într-un singur rol.
Implementați centralManager(_:didDisconnectPeripheral:error:). Dacă eroarea nu este nil — programați reconectarea automată cu exponential backoff (1 s → 2 s → 4 s → 8 s → max 60 s). Dacă eroarea este nil — dispozitivul s-a deconectat normal (de exemplu, utilizatorul a apăsat un buton pe dispozitiv).
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și