CBPeripheral: bu nədir, metodları və iOS-da BLE-periferiyanın idarə edilməsi

Müəllif: IT Sectr Dərc olunub: 2026-07-16 Oxuma vaxtı: 10 dəq

CBPeripheral — iOS-da uzaq BLE cihazını təmsil edən Core Bluetooth framework sinfi. Hər CBPeripheral obyekti UUID, ad, RSSI və qoşulmuş BLE cihazının GATT servis iyerarxiyasını inkapsulyasiya edir. Developer periferiya ilə yalnız CBPeripheral vasitəsilə qarşılıqlı əlaqə qurur: servislərin discovery-si (discoverServices:), xarakteristikaların oxunması (readValueForCharacteristic:), məlumatların yazılması (writeValue:forCharacteristic:type:) və bildirişlərə abunə olma (setNotifyValue:forCharacteristic:). Apple Developer, 2026-ya görə, CBPeripheral — CBCentralManager tərəfindən cihaz aşkar edildikdə və ya qoşulduqda qaytarılan, BLE-periferiya ilə bütün əməliyyatlar üçün mərkəzi obyektdir.

Əsas məqamlar

  • CBPeripheral — iOS-da uzaq BLE cihazı ilə iş üçün Core Bluetooth sinfi
  • GATT iyerarxiyası — Peripheral servisləri (CBService), servislər xarakteristikaları (CBCharacteristic), xarakteristikalar deskriptorları (CBDescriptor) ehtiva edir
  • Discovery — cihazın GATT strukturunu əldə etmək üçün discoverServices: və discoverCharacteristics:forService:
  • Oxu və yazı — readValueForCharacteristic: və writeValue:forCharacteristic:type: təsdiqlə (withResponse) və ya təsdiqsiz (withoutResponse)
  • Bildirişlər — setNotifyValue:forCharacteristic: BLE cihazının xarakteristikalarında dəyişikliklərə abunəliyi aktivləşdirir

CBPeripheral nədir: mahiyyəti və təyinatı

CBPeripheral — iOS tətbiqində uzaq BLE cihazını təmsil edən obyektdir. iPhone-un lokal Bluetooth adapterini idarə edən CBCentralManager-dən fərqli olaraq, CBPeripheral xarici periferik cihazı modelləşdirir: sensor, fitnes treker, mayak, tibbi cihaz. Hər CBPeripheral nümunəsi unikal identifikator (UUID) ehtiva edir ki, bu da qoşulma seansları arasında saxlanılır — Apple UUID-ni sistem Bonding vasitəsilə konkret cihazla əlaqələndirir.

CBPeripheral birbaşa init vasitəsilə yaradılmır. Core Bluetooth framework-i CBPeripheral obyektini iki ssenaridə qaytarır: scanForPeripheralsWithServices: vasitəsilə cihaz aşkar edildikdə (delegat didDiscoverPeripheral) və retrievePeripheralsWithIdentifiers: vasitəsilə əvvəlcədən tanınan cihaza qoşulduqda. Obyekt alındıqdan sonra developer CBCentralManager-da connectPeripheral: çağırır, bundan sonra CBPeripheral GATT əməliyyatları üçün əlçatan olur.

CBPeripheral həyat dövrü altı vəziyyəti əhatə edir: disconnected (ilkin), connecting (connect çağırışından sonra), connected (didConnectPeripheral-dən sonra), discovering (discoverServices çağırışı zamanı), discovered (servislər alındıqdan sonra) və disconnecting (cancelPeripheralConnection-dan sonra). Hər vəziyyət CBPeripheralDelegate delegatı vasitəsilə izlənilir — iOS-da hər BLE tətbiqi üçün məcburi protokol.

CBPeripheral və GATT iyerarxiyası: servislər, xarakteristikalar, deskriptorlar

CBPeripheral üç səviyyədən ibarət iyerarxik GATT strukturu saxlayır. Kök səviyyə — CBService massivi (servislər), hər servis CBCharacteristic massivi (xarakteristikalar), hər xarakteristika CBDescriptor massivi (deskriptorlar) ehtiva edir. Bu model Bluetooth GATT spesifikasiyasına tam uyğundur: servis — cihazın funksiyası (məsələn, "Heart Rate Service"), xarakteristika — konkret dəyər (nəbz 72 bpm), deskriptor — xarakteristikanın metadatası (ölçü vahidləri, bildiriş konfiqurasiyası).

SəviyyəCore Bluetooth sinfiTəsvir
ServisCBServiceƏlaqəli xarakteristikaların məntiqi qrupu, UUID (16-bit, 32-bit və ya 128-bit) ilə identifikasiya olunur
XarakteristikaCBCharacteristicKonkret məlumat dəyəri, oxu, yazı, bildiriş dəstəkləyir
DeskriptorCBDescriptorXarakteristikanın metadatası: CCCD kliet konfiqurasiyası, User Description, Presentation Format

Standart BLE-servislər Bluetooth SIG-də qeydiyyatdan keçib: Heart Rate Service (UUID 180D), Battery Service (180F), Device Information (180A), Blood Pressure (1810). Xüsusi servislər üçün 128-bit UUID istifadə olunur (məsələn, E20A39F4-73F5-4BC4-A12F-17D1AD07A961). iOS standart UUID-ləri avtomatik tanıyır və insan tərəfindən oxuna bilən adlar göstərir; xüsusi UUID-lər hex formatında göstərilir.

CBPeripheral qoşulduqdan sonra onun iyerarxiyası boşdur — servislər və xarakteristikalar yüklənməyib. Developer servisləri əldə etmək üçün discoverServices: çağırmalı, sonra hər servis üçün discoverCharacteristics:forService: çağırmalıdır. Servis daxil edilmiş servislər (includedServices) ehtiva edirsə, əlavə olaraq discoverIncludedServices:forService: çağırılır. Yalnız discovery iyerarxiyası tamamlandıqdan sonra CBPeripheral doldurulur və oxu/yazı üçün əlçatan olur.

Servislərin və xarakteristikaların discovery-si: metodlar və delegatlar

Discovery (aşkaretmə) CBPeripheral GATT strukturunun — hər hansı oxu və ya yazı əməliyyatından əvvəl məcburi addımdır. discoverServices: metodu cihazın bütün servislərinin asinxron axtarışını başladır. Nil ötürülərsə, bütün servislər aşkar edilir; CBUUID massivi ötürülərsə — yalnız göstərilən UUID-li servislər (vaxt optimizasiyası). Nəticə peripheral:didDiscoverServices: delegatına gəlir — CBPeripheral obyekti services xassəsini CBService massivi ilə doldurur.

Servislər alındıqdan sonra hər CBService üçün discoverCharacteristics:forService: çağırılmalıdır. Eynilə, nil — bütün xarakteristikalar, CBUUID massivi — yalnız göstərilənlər. Nəticə: peripheral:didDiscoverCharacteristicsForService:error:. Bu mərhələdə CBCharacteristic icazə verilən əməliyyatları müəyyən edən xüsusiyyətlər (properties: .read, .write, .notify, .indicate) alır.

swift
import CoreBluetooth

extension BLEViewController: CBPeripheralDelegate {

    // 1. Servis discovery-si
    func peripheral(_ peripheral: CBPeripheral,
                     didDiscoverServices error: Error?) {
        guard let services = peripheral.services else { return }

        for service in services {
            // Hər servis üçün xarakteristikaların tələbi
            peripheral.discoverCharacteristics(nil, for: service)
        }
    }

    // 2. Xarakteristika discovery-si
    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. Dəyərin oxunması
    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)")
    }
}

Nümunədə CBPeripheralDelegate-in üç məcburi aşkaretmə metodu tətbiq edilib. didDiscoverServices bütün tapılan servisləri dövr edir və xarakteristikaları tələb edir. didDiscoverCharacteristicsForService hər xarakteristikanın xüsusiyyətlərini yoxlayır: .read üçün readValue çağırır, .notify üçün — setNotifyValue(true). didUpdateValueForCharacteristic metodu cari dəyəri Data formatında alır.

Xarakteristikaların oxunması və yazılması: withResponse və withoutResponse

Dəyərlərin oxunması CBCharacteristic readValueForCharacteristic: metodu ilə həyata keçirilir. Nəticə asinxron olaraq peripheral:didUpdateValueForCharacteristic:error:-da gəlir. Vacib: cihazda keşlənmiş dəyər ola bilər (characteristic.value discovery-dən dərhal sonra əlçatandır), lakin cari dəyəri əldə etmək üçün readValue çağırışı məcburidir. iOS enerji səmərəliliyi üçün dəyərləri keşləyə bilər — readValue keşi yeniləyir.

Dəyərlərin yazılması writeValue:forCharacteristic:type: metodu ilə həyata keçirilir. type parametri yazı tipini müəyyən edir: .withResponse (CBCharacteristicWriteWithResponse) — cihaz didWriteValueForCharacteristic vasitəsilə yazını təsdiqləyir; .withoutResponse (CBCharacteristicWriteWithoutResponse) — təsdiqsiz yazı, maksimal sürət, lakin çatdırılma zəmanətsiz. BLE spesifikasiyası MTU-nu (Maximum Transmission Unit) məhdudlaşdırır: BLE 4.0 üçün 23 baytadək, BLE 5.0+ üçün 251 baytadək. MTU-dan böyük məlumatlar üçün tətbiq səviyyəsində fraqmentasiya tələb olunur.

swift
// CBPeripheral xarakteristika oxu və yazısı
class BLEService {

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

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

    // Təsdiqlə oxu
    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)
    }

    // Təsdiqlə yazı (withResponse)
    func writeWithResponse(data: Data) {
        guard let characteristic = findCharacteristic() else { return }
        peripheral.writeValue(data, for: characteristic,
                             type: .withResponse)
    }

    // Təsdiqsiz yazı (withoutResponse)
    // Maksimal ötürmə, çatdırılma zəmanətsiz
    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 })
    }
}

withResponse və ya withoutResponse yazı tipinin seçimi etibarlılıq tələblərindən asılıdır. Komandalar üçün (işığı yandır, qıfılı aç) withResponse istifadə edin — çatdırılma zəmanəti kritikdir. Axın məlumatları üçün (nəbz, temperatur) withoutResponse istifadə edin — bir paketin itirilməsi əhəmiyyətsizdir. BLE cihazı yalnız bir yazı tipini dəstəkləyə bilər — characteristic.properties.contains(.write) və .writeWithoutResponse xassəsini yoxlayın.

setNotifyValue vasitəsilə BLE bildirişlərinə abunə olma

Bildirişlər (notifications) — periferik cihazın xarakteristika dəyərini mərkəzi cihaza asinxron göndərdiyi BLE mexanizmidir, mərkəzi tərəfdən daimi polling tələb olunmur. CBPeripheral setNotifyValue:forCharacteristic: metodu vasitəsilə abunəliyi aktivləşdirir. Abunəlik aktivləşdirildikdən sonra iOS avtomatik olaraq periferiyada CCCD (Client Characteristic Configuration Descriptor) yazır və cihaz hər dəyər dəyişikliyində yeniləmələr göndərməyə başlayır.

İndikasiyalardan (indicate) fərqli olaraq, bildirişlər mərkəzi tərəfdən təsdiq tələb etmir — paket göndərilir və unudulur. Bu maksimal ötürmə qabiliyyəti verir, lakin paket itkisi mümkündür. İndikasiyalar protokol səviyyəsində (L2CAP) təsdiq tələb edir — daha etibarlı, lakin yavaşdır. CBCharacteristic properties xassəsi vasitəsilə hansı rejimi dəstəklədiyini dəqiq göstərir: .notify, .indicate və ya hər ikisi.

CBPeripheral söndürüldükdə (disconnect, zonalı tərk etdikdə) bütün aktiv abunəliklər avtomatik sıfırlanır. Təkrar qoşulduqda hər xarakteristika üçün yenidən setNotifyValue:true çağırılmalıdır. iOS tətbiq foreground-dan çıxdıqda da abunəlikləri itirir (background mode aktiv deyilsə) — fon işi üçün Info.plist-də "Uses Bluetooth LE accessories" capability-i aktivləşdirilməlidir.

swift
// CBPeripheral bildiriş abunəliyinin idarə edilməsi
class NotificationManager: NSObject {

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

    // Bütün .notify xarakteristikaları üçün bildirişlərə abunə ol
    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)
                }
            }
        }
    }

    // Bütün bildirişlərdən abunəliyi ləğv et
    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()
    }

    // Bildiriş handleri
    func peripheral(_ peripheral: CBPeripheral,
                     didUpdateNotificationStateFor characteristic: CBCharacteristic,
                     error: Error?) {
        if characteristic.isNotifying {
            print("Subscription active: \(characteristic.uuid)")
        } else {
            print("Subscription inactive: \(characteristic.uuid)")
        }
    }
}

NotificationManager abunəlik meneceri CBPeripheral bildirişləri ilə düzgün işi nümayiş etdirir. subscribeToAllNotifications bütün servisləri və xarakteristikaları dövr edir, .notify və .indicate aktivləşdirir. subscribedCharacteristics düzgün abunəlikdən çıxma üçün aktiv abunəlikləri izləyir. didUpdateNotificationStateForCharacteristic characteristic.isNotifying xassəsi vasitəsilə abunəlik vəziyyətinin uğurlu dəyişməsini təsdiqləyir.

Swift-də CBPeripheral ilə işin tam nümunəsi

CBPeripheral ilə tam iş dövrü daxildir: CBCentralManager-dən obyektin alınması, qoşulma, discovery, oxu/yazı, bildirişlərə abunəlik və söndürmə. Aşağıdakı nümunədə Swift-də müasir async/await API (iOS 15+) istifadə edərək BLE-periferiyanın tam həyat dövrünü idarə edən BLEConnection sinfi tətbiq edilmişdir.

swift
import CoreBluetooth

// async/await ilə tam CBPeripheral idarəetmə nümunəsi
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. Periferik cihaza qoşul
    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. Discovery  
    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 cihaz vəziyyətini idarə et
    }

    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
}

BLEConnection sinfi CheckedContinuation vasitəsilə Swift Concurrency (async/await) istifadə edir — Core Bluetooth delegat API-ləri ilə iş üçün müasir nümunədir. connect(to:) didConnectPeripheral vasitəsilə qoşulma təsdiqini gözləyir, discoverServices() — didDiscoverServices vasitəsilə. Bu yanaşma iç-içə delegatlardan xilas edir və BLE kodunu xətti və oxunaqlı edir. BLEError vasitəsilə xəta idarəetməsi BLE bağlantısının bütün tipik uğursuzluq ssenarilərini əhatə edir.

Tez-tez verilən suallar

Skan etmədən CBPeripheral necə əldə etmək olar?

CBPeripheral əvvəllər qoşulmuş cihaz üçün CBCentralManager-da retrievePeripheralsWithIdentifiers: vasitəsilə əldə edilə bilər. Əvvəlcədən saxlanmış cihazların UUID (NSUUID) massivini ötürün — framework sistem BLE-bondinq bazasında olan cihazlar üçün CBPeripheral massivi qaytaracaq. Bu yalnız iPhone-un əvvəllər qoşulduğu cihazlar üçün işləyir. Yeni cihaz üçün skan etmə məcburendir.

Niyə CBPeripheral servisləri aşkar etmir?

Əsas səbəblər: cihaz zonaladan kənardadır (RSSI həddən aşağı), BLE radiosu söndürülmüşdür (CBCentralManager.state != .poweredOn), CBPeripheralDelegate təyin edilməmişdir (peripheral.delegate = self) və ya discoverServices qoşulmadan əvvəl çağırılmışdır. centralManager.state statusunu yoxlayın, delegatın connect çağırışından əvvəl təyin edildiyinə əmin olun və 5–10 saniyə timeout ilə retry istifadə edin.

writeValue cavab vermirsə nə etməli?

Səbəb — yalnız .writeWithoutResponse dəstəkləyən xarakteristikada .withResponse istifadəsi və ya əksi. characteristic.properties-i çağırışdan əvvəl yoxlayın. MTU problemi də ola bilər: məlumat > 20 bayt (BLE 4.0 MTU) olduqda negotiateMTU və ya fraqmentasiya vasitəsilə MTU uzlaşması tələb olunur. Maksimal paket ölçüsünü təyin etmək üçün peripheral.maximumWriteValueLength(for: .withResponse) istifadə edin.

CBPeripheral-i zonalada olanı əlçatmazdan necə fərqləndirmək olar?

Zonaladan kənar CBPeripheral dərhal sönmür — iOS onu timeout vasitəsilə (adətən 20–30 saniyə) .disconnected vəziyyətinə keçirir. İzləmə üçün CBPeripheral-da readRSSI istifadə edin — əlçatmaz olduqda CBError.connectionTimeout kodu ilə xəta qaytaracaq. Həmçinin bağlantı qırılmasının vaxtında aşkarlanması üçün centralManager:didDisconnectPeripheral:error:-i izləyin.

Bir CBPeripheral-i çox sayda thread-dən istifadə etmək olar?

Core Bluetooth thread-təhlükəsiz deyil — bütün CBPeripheral çağırışları bir növbədən icra edilməlidir (adətən main queue və ya CBCentralManager-in inisializasiyasında göstərilən ardıcıl serial queue). Müxtəlif thread-lərdən eyni vaxtda çağırışlar race condition və tətbiqin çökməsinə səbəb olur. Bütün BLE əməliyyatları üçün DispatchQueue(label: "com.app.ble") və UI yeniləməsi üçün DispatchQueue.main.async istifadə edin.

Nəticə

  • CBPeripheral — CBCentralManager tərəfindən qaytarılan, iOS-da uzaq BLE cihazı ilə iş üçün Core Bluetooth sinfi
  • GATT iyerarxiyası servislərdən (CBService), xarakteristikalardan (CBCharacteristic) və deskriptorlardan (CBDescriptor) 16-bit və ya 128-bit UUID ilə ibarətdir
  • Discovery ardıcıl icra edilir: discoverServices: → discoverCharacteristics:forService: delegat vasitəsilə işlənir
  • Oxu — readValueForCharacteristic:, yazı — writeValue:forCharacteristic:type: (.withResponse və ya .withoutResponse)
  • Bildirişlər — setNotifyValue:forCharacteristic: periferiyadan mərkəzə asinxron məlumat göndərilməsini aktivləşdirir
  • MTU BLE 4.0 paketi 23 baytla məhdudlaşdırır, BLE 5.0+ — 251 baytadək, MTU-dan böyük məlumatlar fraqmentasiya tələb edir
  • Async/await Swift CheckedContinuation vasitəsilə iç-içə delegatları xətti çağırışlarla əvəz edərək BLE kodunu sadələşdirir

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun