CBPeripheral: mi ez, metódusok és a BLE-periféria kezelése iOS-ben

Szerző: IT Sectr Megjelenés: 2026-07-16 Olvasási idő: 10 perc

CBPeripheral — a Core Bluetooth keretrendszer osztálya, amely egy távoli BLE-eszközt képvisel iOS-ben. Minden CBPeripheral objektum magába foglalja az UUID-t, nevet, RSSI-t és a csatlakoztatott BLE-eszköz GATT-szolgáltatásainak hierarchiáját. A fejlesztő kizárólag a CBPeripheral-en keresztül lép kapcsolatba a perifériával: szolgáltatások felderítése (discoverServices:), jellemzők olvasása (readValueForCharacteristic:), adatok írása (writeValue:forCharacteristic:type:) és értesítésekre való feliratkozás (setNotifyValue:forCharacteristic:). A Apple Developer, 2026 szerint a CBPeripheral — a központi objektum az összes BLE-perifériával végzett művelethez, amelyet a CBCentralManager ad vissza az eszköz észlelésekor vagy csatlakozásakor.

Főbb pontok

  • CBPeripheral — Core Bluetooth osztály távoli BLE-eszközzel való munkához iOS-ben
  • GATT hierarchia — Peripheral szolgáltatásokat (CBService), a szolgáltatások jellemzőket (CBCharacteristic), a jellemzők leírókat (CBDescriptor) tartalmaznak
  • Felderítés — discoverServices: és discoverCharacteristics:forService: az eszköz GATT-struktúrájának megszerzéséhez
  • Olvasás és írás — readValueForCharacteristic: és writeValue:forCharacteristic:type: megerősítéssel (withResponse) vagy anélkül (withoutResponse)
  • Értesítések — setNotifyValue:forCharacteristic: aktiválja a BLE-eszköz jellemzőinek változásaira való feliratkozást

Mi az a CBPeripheral: lényeg és cél

CBPeripheral — egy objektum, amely egy távoli BLE-eszközt képvisel egy iOS alkalmazásban. Ellentétben a CBCentralManager-rel, amely az iPhone helyi Bluetooth-adapterét kezeli, a CBPeripheral egy külső perifériás eszközt modellez: érzékelő, fitneszkövető, jeladó, orvosi eszköz. Minden CBPeripheral példány egy egyedi azonosítót (UUID) tartalmaz, amely a kapcsolódási munkamenetek között megmarad — az Apple az UUID-t egy adott eszközhöz köti a rendszer Bonding segítségével.

A CBPeripheral nem közvetlenül az init-en keresztül jön létre. A Core Bluetooth keretrendszer két forgatókönyvben ad vissza CBPeripheral objektumot: az eszköz észlelésekor a scanForPeripheralsWithServices: segítségével (delegate didDiscoverPeripheral) és egy korábban ismert eszközhöz való csatlakozáskor a retrievePeripheralsWithIdentifiers: segítségével. Az objektum átvétele után a fejlesztő meghívja a connectPeripheral: metódust a CBCentralManager-en, amely után a CBPeripheral elérhetővé válik GATT-műveletekhez.

A CBPeripheral életciklusa hat állapotot foglal magában: disconnected (kezdeti), connecting (a connect hívása után), connected (a didConnectPeripheral után), discovering (a discoverServices hívása közben), discovered (a szolgáltatások megérkezése után) és disconnecting (a cancelPeripheralConnection után). Minden állapot a CBPeripheralDelegate delegate-en keresztül követhető — kötelező protokoll minden BLE alkalmazáshoz iOS-ben.

CBPeripheral és GATT hierarchia: szolgáltatások, jellemzők, leírók

CBPeripheral egy hierarchikus GATT-struktúrát tárol, amely három szintből áll. A gyökérszint — CBService tömb (szolgáltatások), minden szolgáltatás CBCharacteristic tömböt (jellemzők), minden jellemző CBDescriptor tömböt (leírók) tartalmaz. Ez a modell teljes mértékben megfelel a Bluetooth GATT specifikációnak: szolgáltatás — az eszköz funkciója (például „Heart Rate Service“), jellemző — konkrét érték (pulzus 72 bpm), leíró — a jellemző metaadatai (mértékegységek, értesítések konfigurációja).

SzintCore Bluetooth osztályLeírás
SzolgáltatásCBServiceRokon jellemzők logikai csoportja, UUID (16-bit, 32-bit vagy 128-bit) által azonosítva
JellemzőCBCharacteristicKonkrét adatérték, támogatja az olvasást, írást, értesítést
LeíróCBDescriptorA jellemző metaadatai: CCCD kliens konfiguráció, User Description, Presentation Format

A szabványos BLE-szolgáltatások a Bluetooth SIG-nél vannak regisztrálva: Heart Rate Service (UUID 180D), Battery Service (180F), Device Information (180A), Blood Pressure (1810). Egyedi szolgáltatásokhoz 128 bites UUID-ket használnak (például E20A39F4-73F5-4BC4-A12F-17D1AD07A961). Az iOS automatikusan felismeri a szabványos UUID-ket és ember által olvasható neveket jelenít meg; az egyedi UUID-k hex formátumban jelennek meg.

Csatlakozás után a CBPeripheral hierarchiája üres — a szolgáltatások és jellemzők nincsenek betöltve. A fejlesztőnek meg kell hívnia a discoverServices: metódust a szolgáltatások megszerzéséhez, majd minden szolgáltatáshoz a discoverCharacteristics:forService: metódust. Ha a szolgáltatás tartalmazott szolgáltatásokat (includedServices) tartalmaz, akkor a discoverIncludedServices:forService: is meghívásra kerül. Csak a hierarchia felderítésének befejezése után töltődik fel a CBPeripheral és válik elérhetővé olvasásra és írásra.

Szolgáltatások és jellemzők felderítése: metódusok és delegate-ek

Felderítés (discovery) a CBPeripheral GATT-struktúrájának — kötelező lépés bármilyen olvasási vagy írási művelet előtt. A discoverServices: metódus elindítja az eszköz összes szolgáltatásának aszinkron keresését. Ha nil kerül átadásra, minden szolgáltatás felderítésre kerül; ha CBUUID tömb kerül átadásra — csak a megadott UUID-vel rendelkező szolgáltatások (időoptimalizálás). Az eredmény a peripheral:didDiscoverServices: delegate-be érkezik — a CBPeripheral objektum kitölti a services tulajdonságot egy CBService tömbbel.

A szolgáltatások megérkezése után minden CBService-hez meg kell hívni a discoverCharacteristics:forService: metódust. Hasonlóan, nil — minden jellemző, CBUUID tömb — csak a megadottak. Eredmény: peripheral:didDiscoverCharacteristicsForService:error:. Ebben a fázisban a CBCharacteristic tulajdonságokat kap (properties: .read, .write, .notify, .indicate), amelyek meghatározzák az engedélyezett műveleteket.

swift
import CoreBluetooth

extension BLEViewController: CBPeripheralDelegate {

    // 1. Szolgáltatás felderítése
    func peripheral(_ peripheral: CBPeripheral,
                     didDiscoverServices error: Error?) {
        guard let services = peripheral.services else { return }

        for service in services {
            // Jellemzők kérése minden szolgáltatáshoz
            peripheral.discoverCharacteristics(nil, for: service)
        }
    }

    // 2. Jellemző felderítése
    func peripheral(_ peripheral: CBPeripheral,
                     didDiscoverCharacteristicsFor service: CBService,
                     error: Error?) {
        guard let characteristics = service.characteristics else { return }

        for characteristic in characteristics {
            if characteristic.properties.contains(.read) {
                peripheral.readValue(for: characteristic)
            }
            if characteristic.properties.contains(.notify) {
                peripheral.setNotifyValue(true, for: characteristic)
            }
        }
    }

    // 3. Érték olvasása
    func peripheral(_ peripheral: CBPeripheral,
                     didUpdateValueFor characteristic: CBCharacteristic,
                     error: Error?) {
        guard let data = characteristic.value,
              let value = String(data: data, encoding: .utf8)
        else { return }
        print("Characteristic value: \(value)")
    }
}

A példában a CBPeripheralDelegate három kötelező felderítési metódusa van implementálva. A didDiscoverServices végigjárja az összes megtalált szolgáltatást és jellemzőket kér. A didDiscoverCharacteristicsForService ellenőrzi az egyes jellemzők tulajdonságait: .read esetén meghívja a readValue-t, .notify esetén a setNotifyValue(true)-t. A didUpdateValueForCharacteristic metódus megkapja az aktuális értéket Data formátumban.

Jellemzők olvasása és írása: withResponse és withoutResponse

Értékek olvasása CBCharacteristic esetén a readValueForCharacteristic: metódussal történik. Az eredmény aszinkron módon érkezik a peripheral:didUpdateValueForCharacteristic:error:-ban. Fontos: az eszköznek lehet gyorsítótárazott értéke (a characteristic.value közvetlenül a felderítés után elérhető), de az aktuális érték megszerzéséhez a readValue hívása kötelező. Az iOS gyorsítótárazhatja az értékeket az energiahatékonyság érdekében — a readValue frissíti a gyorsítótárat.

Értékek írása a writeValue:forCharacteristic:type: metódussal történik. A type paraméter határozza meg az írás típusát: .withResponse (CBCharacteristicWriteWithResponse) — az eszköz megerősíti az írást a didWriteValueForCharacteristic-en keresztül; .withoutResponse (CBCharacteristicWriteWithoutResponse) — írás megerősítés nélkül, maximális sebesség, de szállítási garancia nélkül. A BLE specifikáció korlátozza az MTU-t (Maximum Transmission Unit): 23 bájtig BLE 4.0 esetén, 251 bájtig BLE 5.0+ esetén. Az MTU-nál nagyobb adatokhoz alkalmazásszintű fragmentáció szükséges.

swift
// CBPeripheral jellemző olvasása és írása
class BLEService {

    private let peripheral: CBPeripheral
    private let serviceUUID = CBUUID(string: "180D")
    private let charUUID = CBUUID(string: "2A37")

    init(peripheral: CBPeripheral) {
        self.peripheral = peripheral
    }

    // Olvasás megerősítéssel
    func readHeartRate() {
        guard let service = peripheral.services?.first(where: { $0.uuid == serviceUUID }),
              let characteristic = service.characteristics?.first(where: { $0.uuid == charUUID })
        else { return }
        peripheral.readValue(for: characteristic)
    }

    // Írás megerősítéssel (withResponse)
    func writeWithResponse(data: Data) {
        guard let characteristic = findCharacteristic() else { return }
        peripheral.writeValue(data, for: characteristic,
                             type: .withResponse)
    }

    // Írás megerősítés nélkül (withoutResponse)
    // Maximális átvitel, szállítási garancia nélkül
    func writeWithoutResponse(data: Data) {
        guard let characteristic = findCharacteristic() else { return }
        peripheral.writeValue(data, for: characteristic,
                             type: .withoutResponse)
    }

    private func findCharacteristic() -> CBCharacteristic? {
        return peripheral.services?
            .flatMap { $0.characteristics ?? [] }
            .first(where: { $0.uuid == charUUID })
    }
}

Az írás típusának kiválasztása withResponse vagy withoutResponse a megbízhatósági követelményektől függ. Parancsokhoz (lámpa bekapcsolása, zár kinyitása) használja a withResponse-t — a szállítás garanciája kritikus. Folyamatos adatokhoz (pulzus, hőmérséklet) használja a withoutResponse-t — egy csomag elvesztése nem jelentős. A BLE-eszköz csak egy írási típust támogathat — ellenőrizze a characteristic.properties.contains(.write) és .writeWithoutResponse tulajdonságot.

Feliratkozás BLE-értesítésekre setNotifyValue segítségével

Értesítések (notifications) — BLE mechanizmus, amelyben a perifériás eszköz aszinkron módon küldi el a jellemző értékét a központi eszköznek, a központi részről történő állandó polling nélkül. A CBPeripheral a setNotifyValue:forCharacteristic: metódussal aktiválja a feliratkozást. A feliratkozás aktiválása után az iOS automatikusan kiírja a CCCD-t (Client Characteristic Configuration Descriptor) a perifériára, és az eszköz minden értékváltozáskor frissítéseket kezd küldeni.

Az indikációkkal (indicate) ellentétben az értesítések nem igényelnek megerősítést a központitól — a csomag elküldésre kerül és elfelejtődik. Ez maximális sávszélességet biztosít, de csomagvesztés lehetséges. Az indikációk protokoll szinten (L2CAP) igényelnek megerősítést — megbízhatóbbak, de lassabbak. A CBCharacteristic a properties tulajdonságon keresztül pontosan jelzi, melyik módot támogatja: .notify, .indicate vagy mindkettőt.

A CBPeripheral megszakításakor (disconnect, hatókörön kívülre kerülés) az összes aktív feliratkozás automatikusan visszaállításra kerül. Újracsatlakozáskor minden jellemzőhöz újra meg kell hívni a setNotifyValue:true metódust. Az iOS a feliratkozásokat is elveszíti, amikor az alkalmazás kilép az előtérből (ha a háttérmód nincs engedélyezve) — háttérmunkához engedélyezni kell a „Uses Bluetooth LE accessories“ képességet az Info.plist-ben.

swift
// CBPeripheral értesítési feliratkozás kezelése
class NotificationManager: NSObject {

    private var peripheral: CBPeripheral?
    private var subscribedCharacteristics: Set<CBUUID> = []

    // Feliratkozás értesítésekre az összes .notify jellemzőhöz
    func subscribeToAllNotifications(peripheral: CBPeripheral) {
        self.peripheral = peripheral

        guard let services = peripheral.services else { return }

        for service in services {
            guard let characteristics = service.characteristics else { continue }

            for characteristic in characteristics {
                if characteristic.properties.contains(.notify)
                    || characteristic.properties.contains(.indicate) {
                    peripheral.setNotifyValue(true, for: characteristic)
                    subscribedCharacteristics.insert(characteristic.uuid)
                }
            }
        }
    }

    // Leiratkozás az összes értesítésről
    func unsubscribeFromAll() {
        guard let peripheral = peripheral else { return }
        guard let services = peripheral.services else { return }

        for service in services {
            guard let characteristics = service.characteristics else { continue }

            for characteristic in characteristics {
                if subscribedCharacteristics.contains(characteristic.uuid) {
                    peripheral.setNotifyValue(false, for: characteristic)
                }
            }
        }
        subscribedCharacteristics.removeAll()
    }

    // Értesítéskezelő
    func peripheral(_ peripheral: CBPeripheral,
                     didUpdateNotificationStateFor characteristic: CBCharacteristic,
                     error: Error?) {
        if characteristic.isNotifying {
            print("Subscription active: \(characteristic.uuid)")
        } else {
            print("Subscription inactive: \(characteristic.uuid)")
        }
    }
}

A NotificationManager feliratkozás-kezelő bemutatja a CBPeripheral értesítésekkel való helyes munkát. A subscribeToAllNotifications végigjárja az összes szolgáltatást és jellemzőt, aktiválva a .notify és .indicate tulajdonságokat. A subscribedCharacteristics nyomon követi az aktív feliratkozásokat a helyes leiratkozáshoz. A didUpdateNotificationStateForCharacteristic megerősíti a feliratkozási állapot sikeres megváltoztatását a characteristic.isNotifying tulajdonságon keresztül.

Teljes példa a CBPeripheral használatára Swift-ben

Teljes munkaciklus a CBPeripheral-lel magában foglalja: az objektum fogadását a CBCentralManager-től, csatlakozást, felderítést, olvasást/írást, feliratkozást az értesítésekre és a kapcsolat bontását. Az alábbi példában a BLEConnection osztály van implementálva, amely a BLE-periféria teljes életciklusát kezeli Swift-ben a modern async/await API (iOS 15+) segítségével.

swift
import CoreBluetooth

// Teljes CBPeripheral kezelési példa async/await segítségével
class BLEConnection: NSObject {

    private let centralManager: CBCentralManager
    private var peripheral: CBPeripheral?
    private var continuation: CheckedContinuation<Void, Error>?

    override init() {
        centralManager = CBCentralManager(delegate: nil, queue: .main)
        super.init()
        centralManager.delegate = self
    }

    // 1. Csatlakozás a perifériához
    func connect(to peripheral: CBPeripheral) async throws {
        self.peripheral = peripheral
        peripheral.delegate = self
        centralManager.connect(peripheral, options: nil)

        try await withCheckedThrowingContinuation { continuation in
            self.continuation = continuation
        }
    }

    // 2. Felderítés  
    func discoverServices() async throws {
        guard let peripheral = peripheral else {
            throw BLEError.notConnected
        }
        peripheral.discoverServices(nil)
        try await withCheckedThrowingContinuation { continuation in
            self.continuation = continuation
        }
    }
}

// 3. CBCentralManager
extension BLEConnection: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        // Bluetooth-eszköz állapotának kezelése
    }

    func centralManager(_ central: CBCentralManager,
                        didConnect peripheral: CBPeripheral) {
        continuation?.resume()
        continuation = nil
    }

    func centralManager(_ central: CBCentralManager,
                        didFailToConnect peripheral: CBPeripheral,
                        error: Error?) {
        continuation?.resume(throwing: error ?? BLEError.connectionFailed)
        continuation = nil
    }
}

enum BLEError: Error {
    case notConnected
    case connectionFailed
    case serviceNotFound
    case characteristicNotFound
}

A BLEConnection osztály a Swift Concurrency (async/await) funkciót használja a CheckedContinuation segítségével — ez egy modern minta a Core Bluetooth delegate API-ival való munkához. A connect(to:) a csatlakozás megerősítésére vár a didConnectPeripheral-en keresztül, a discoverServices() — a didDiscoverServices-en keresztül. Ez a megközelítés kiküszöböli a beágyazott delegate-eket, és a BLE kódot lineárissá és olvashatóvá teszi. A BLEError-on keresztüli hibakezelés lefedi a BLE-kapcsolat összes tipikus meghibásodási forgatókönyvét.

Gyakran Ismételt Kérdések

Hogyan szerezhetek CBPeripheral-t szkennelés nélkül?

A CBPeripheral egy korábban csatlakoztatott eszközhöz a retrievePeripheralsWithIdentifiers: segítségével szerezhető meg a CBCentralManager-en. Adjon át egy UUID (NSUUID) tömböt a korábban mentett eszközökről — a keretrendszer visszaad egy CBPeripheral tömböt a rendszer BLE-bonding adatbázisában lévő eszközökhöz. Ez csak azokkal az eszközökkel működik, amelyekkel az iPhone korábban párosítva volt. Új eszközhöz a szkennelés kötelező.

Miért nem észleli a CBPeripheral a szolgáltatásokat?

Fő okok: az eszköz hatókörön kívül van (RSSI a küszöbérték alatt), a BLE rádió ki van kapcsolva (CBCentralManager.state != .poweredOn), a CBPeripheralDelegate delegát nincs beállítva (peripheral.delegate = self), vagy a discoverServices hívása a csatlakozás előtt történt. Ellenőrizze a centralManager.state állapotát, győződjön meg arról, hogy a delegát be van állítva a connect hívása előtt, és használja az újrapróbálkozást 5–10 másodperces időkorláttal.

Mit tegyek, ha a writeValue nem válaszol?

Ok — a .withResponse használata olyan jellemzőn, amely csak a .writeWithoutResponse-t támogatja, vagy fordítva. Ellenőrizze a characteristic.properties-t a hívás előtt. MTU probléma is lehet: ha az adat > 20 bájt (BLE 4.0 MTU), MTU-egyeztetés szükséges a negotiateMTU vagy fragmentáció segítségével. Használja a peripheral.maximumWriteValueLength(for: .withResponse) metódust a maximális csomagméret meghatározásához.

Hogyan különböztetem meg a hatókörön belüli CBPeripheral-t az elérhetetlentől?

A hatókörön kívüli CBPeripheral nem szakad meg azonnal — az iOS időtúllépésen keresztül (általában 20–30 másodperc) áthelyezi a .disconnected állapotba. Figyeléshez használja a readRSSI-t a CBPeripheral-en — elérhetetlenség esetén hibát ad vissza a CBError.connectionTimeout kóddal. Kövesse nyomon a centralManager:didDisconnectPeripheral:error: metódust is a kapcsolat megszakadásának időben történő észleléséhez.

Használható egy CBPeripheral több szálból?

A Core Bluetooth nem szálbiztos — az összes CBPeripheral hívást egyetlen sorból kell végrehajtani (általában main queue vagy a CBCentralManager inicializálásakor megadott soros serial queue). A különböző szálakból történő egyidejű hívások versenyhelyzethez és az alkalmazás összeomlásához vezetnek. Használja a DispatchQueue(label: „com.app.ble“) sorokat az összes BLE-művelethez és a DispatchQueue.main.async-et a UI frissítéséhez.

Összefoglaló

  • CBPeripheral — Core Bluetooth osztály távoli BLE-eszközzel való munkához iOS-ben, amelyet a CBCentralManager ad vissza
  • GATT hierarchia szolgáltatásokból (CBService), jellemzőkből (CBCharacteristic) és leírókból (CBDescriptor) áll, 16 bites vagy 128 bites UUID-vel
  • Felderítés szekvenciálisan történik: discoverServices: → discoverCharacteristics:forService: delegate-en keresztüli feldolgozással
  • Olvasás — readValueForCharacteristic:, írás — writeValue:forCharacteristic:type: (.withResponse vagy .withoutResponse)
  • Értesítések — setNotifyValue:forCharacteristic: aktiválja az aszinkron adatküldést a perifériáról a központira
  • MTU BLE 4.0 korlátozza a csomagot 23 bájtra, BLE 5.0+ — 251 bájtig, az MTU-nál nagyobb adatok fragmentációt igényelnek
  • Async/await Swift a CheckedContinuation segítségével leegyszerűsíti a BLE kódot, a beágyazott delegate-eket lineáris hívásokkal helyettesítve

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is