CBPeripheral — iOS-da uzoqdagi BLE qurilmasini ifodalovchi Core Bluetooth framework sinfi. Har bir CBPeripheral obyekti UUID, nom, RSSI va ulangan BLE qurilmasining GATT servislar iyerarxiyasini inkapsulatsiya qiladi. Dasturchi periferiya bilan faqat CBPeripheral orqali o'zaro aloqa qiladi: servislarni discovery qilish (discoverServices:), xarakteristikalarni o'qish (readValueForCharacteristic:), ma'lumotlarni yozish (writeValue:forCharacteristic:type:) va bildirishnomalarga obuna bo'lish (setNotifyValue:forCharacteristic:). Apple Developer, 2026 ma'lumotlariga ko'ra, CBPeripheral — CBCentralManager tomonidan qurilma topilganda yoki ulanganda qaytariladigan, BLE-periferiya bilan barcha operatsiyalar uchun markaziy obyektdir.
Asosiy ma'lumotlar
CBPeripheral — iOS ilovasida uzoqdagi BLE qurilmasini ifodalovchi obyektdir. iPhone-ning mahalliy Bluetooth adapterini boshqaradigan CBCentralManager-dan farqli o'laroq, CBPeripheral tashqi periferik qurilmani modellashtiradi: sensor, fitness treker, mayoq, tibbiy asbob. Har bir CBPeripheral nusxasi noyob identifikator (UUID) o'z ichiga oladi, u ulanish seanslari orasida saqlanadi — Apple UUID-ni tizim Bonding orqali ma'lum bir qurilma bilan bog'laydi.
CBPeripheral to'g'ridan-to'g'ri init orqali yaratilmaydi. Core Bluetooth framework-i CBPeripheral obyektini ikkita ssenariyda qaytaradi: scanForPeripheralsWithServices: orqali qurilma topilganda (delegat didDiscoverPeripheral) va retrievePeripheralsWithIdentifiers: orqali oldindan ma'lum qurilmaga ulanganda. Obyekt olingandan so'ng, dasturchi CBCentralManager-da connectPeripheral: chaqiradi, shundan so'ng CBPeripheral GATT operatsiyalari uchun mavjud bo'ladi.
CBPeripheral hayot aylanishi oltita holatni o'z ichiga oladi: disconnected (boshlang'ich), connecting (connect chaqiruvidan so'ng), connected (didConnectPeripheral-dan so'ng), discovering (discoverServices chaqiruvi vaqtida), discovered (servislar olingandan so'ng) va disconnecting (cancelPeripheralConnection-dan so'ng). Har bir holat CBPeripheralDelegate delegati orqali kuzatiladi — iOS-dagi har bir BLE ilovasi uchun majburiy protokol.
CBPeripheral uch darajadan iborat iyerarxik GATT strukturasini saqlaydi. Ildiz darajasi — CBService massivi (servislar), har bir servis CBCharacteristic massivi (xarakteristikalar), har bir xarakteristika CBDescriptor massivi (deskriptorlar) o'z ichiga oladi. Bu model Bluetooth GATT spetsifikatsiyasiga to'liq mos keladi: servis — qurilmaning funktsiyasi (masalan, „Heart Rate Service“), xarakteristika — aniq qiymat (yurak urishi 72 bpm), deskriptor — xarakteristikaning metama'lumotlari (o'lchov birliklari, bildirishnomalar konfiguratsiyasi).
| Daraja | Core Bluetooth sinfi | Tavsif |
|---|---|---|
| Servis | CBService | O'zaro bog'liq xarakteristikalar mantiqiy guruhi, UUID (16-bit, 32-bit yoki 128-bit) bilan identifikatsiya qilinadi |
| Xarakteristika | CBCharacteristic | Aniq ma'lumot qiymati, o'qish, yozish, bildirishnomani qo'llab-quvvatlaydi |
| Deskriptor | CBDescriptor | Xarakteristikaning metama'lumotlari: CCCD mijoz konfiguratsiyasi, User Description, Presentation Format |
Standart BLE-servislar Bluetooth SIG da ro'yxatdan o'tgan: Heart Rate Service (UUID 180D), Battery Service (180F), Device Information (180A), Blood Pressure (1810). Maxsus servislar uchun 128-bit UUID ishlatiladi (masalan, E20A39F4-73F5-4BC4-A12F-17D1AD07A961). iOS standart UUID-larni avtomatik taniydi va odam o'qiy oladigan nomlarni ko'rsatadi; maxsus UUID-lar hex formatida ko'rsatiladi.
CBPeripheral ulangandan so'ng, uning iyerarxiyasi bo'sh — servislar va xarakteristikalar yuklanmagan. Dasturchi servislarni olish uchun discoverServices: chaqirishi kerak, so'ngra har bir servis uchun discoverCharacteristics:forService: chaqirishi kerak. Agar servis qo'shilgan servislarni (includedServices) o'z ichiga olsa, qo'shimcha ravishda discoverIncludedServices:forService: chaqiriladi. Faqat discovery iyerarxiyasi tugallangandan so'ng, CBPeripheral to'ldiriladi va o'qish/yozish uchun mavjud bo'ladi.
Discovery (topish) CBPeripheral GATT strukturasining — har qanday o'qish yoki yozish operatsiyalaridan oldin majburiy qadamdir. discoverServices: metodi qurilmaning barcha servislarining asinxron qidiruvini boshlaydi. Agar nil uzatilsa, barcha servislar topiladi; agar CBUUID massivi uzatilsa — faqat ko'rsatilgan UUID-li servislar (vaqt optimizatsiyasi). Natija peripheral:didDiscoverServices: delegatiga keladi — CBPeripheral obyekti services xususiyatini CBService massivi bilan to'ldiradi.
Servislar olingandan so'ng, har bir CBService uchun discoverCharacteristics:forService: chaqirilishi kerak. Xuddi shunday, nil — barcha xarakteristikalar, CBUUID massivi — faqat ko'rsatilganlar. Natija: peripheral:didDiscoverCharacteristicsForService:error:. Bu bosqichda CBCharacteristic ruxsat etilgan operatsiyalarni aniqlaydigan xususiyatlarni (properties: .read, .write, .notify, .indicate) oladi.
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 {
// Har bir servis uchun xarakteristikalarni so'rash
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. Qiymatni o'qish
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)")
}
}
Misolda CBPeripheralDelegate-ning uchta majburiy topish metodi amalga oshirilgan. didDiscoverServices barcha topilgan servislarni aylanib chiqadi va xarakteristikalarni so'raydi. didDiscoverCharacteristicsForService har bir xarakteristikaning xususiyatlarini tekshiradi: .read uchun readValue chaqiradi, .notify uchun — setNotifyValue(true). didUpdateValueForCharacteristic metodi joriy qiymatni Data formatida oladi.
Qiymatlarni o'qish CBCharacteristic readValueForCharacteristic: metodi bilan amalga oshiriladi. Natija asinxron ravishda peripheral:didUpdateValueForCharacteristic:error: da keladi. Muhim: qurilmada keshlangan qiymat bo'lishi mumkin (characteristic.value discovery-dan so'ng darhol mavjud), ammo joriy qiymatni olish uchun readValue chaqiruvi majburiydir. iOS energiya samaradorligi uchun qiymatlarni keshlashi mumkin — readValue keshlarni yangilaydi.
Qiymatlarni yozish writeValue:forCharacteristic:type: metodi bilan amalga oshiriladi. type parametri yozish turini aniqlaydi: .withResponse (CBCharacteristicWriteWithResponse) — qurilma didWriteValueForCharacteristic orqali yozishni tasdiqlaydi; .withoutResponse (CBCharacteristicWriteWithoutResponse) — tasdiqlashsiz yozish, maksimal tezlik, lekin yetkazib berish kafolatisiz. BLE spetsifikatsiyasi MTU (Maximum Transmission Unit) ni cheklaydi: BLE 4.0 uchun 23 baytgacha, BLE 5.0+ uchun 251 baytgacha. MTU dan katta ma'lumotlar uchun dastur darajasida fragmentatsiya talab qilinadi.
// CBPeripheral xarakteristika o'qish va yozish
class BLEService {
private let peripheral: CBPeripheral
private let serviceUUID = CBUUID(string: "180D")
private let charUUID = CBUUID(string: "2A37")
init(peripheral: CBPeripheral) {
self.peripheral = peripheral
}
// Tasdiqlash bilan o'qish
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)
}
// Tasdiqlash bilan yozish (withResponse)
func writeWithResponse(data: Data) {
guard let characteristic = findCharacteristic() else { return }
peripheral.writeValue(data, for: characteristic,
type: .withResponse)
}
// Tasdiqlashsiz yozish (withoutResponse)
// Maksimal o'tkazish, yetkazib berish kafolatisiz
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 yoki withoutResponse yozish turini tanlash ishonchlilik talablariga bog'liq. Buyruqlar uchun (chiroqni yoqish, qulfni ochish) withResponse dan foydalaning — yetkazib berish kafolati muhim. Oqimli ma'lumotlar uchun (yurak urishi, harorat) withoutResponse dan foydalaning — bitta paketning yo'qolishi ahamiyatsiz. BLE qurilmasi faqat bitta yozish turini qo'llab-quvvatlashi mumkin — characteristic.properties.contains(.write) va .writeWithoutResponse xususiyatini tekshiring.
Bildirishnomalar (notifications) — periferik qurilma xarakteristika qiymatini markaziy qurilmaga asinxron yuboradigan BLE mexanizmi, markaziy tomondan doimiy polling talab qilinmaydi. CBPeripheral setNotifyValue:forCharacteristic: metodi orqali obunani faollashtiradi. Obuna faollashtirilgandan so'ng, iOS avtomatik ravishda periferiyada CCCD (Client Characteristic Configuration Descriptor) ni yozadi va qurilma har bir qiymat o'zgarishida yangilanishlarni yuborishni boshlaydi.
Indikatsiyalardan (indicate) farqli o'laroq, bildirishnomalar markaziy tomondan tasdiqlashni talab qilmaydi — paket yuboriladi va unutiladi. Bu maksimal o'tkazish qobiliyatini beradi, ammo paket yo'qotilishi mumkin. Indikatsiyalar protokol darajasida (L2CAP) tasdiqlashni talab qiladi — ishonchliroq, lekin sekinroq. CBCharacteristic properties xususiyati orqali qaysi rejimni qo'llab-quvvatlashini aniq ko'rsatadi: .notify, .indicate yoki ikkalasi.
CBPeripheral uzilganda (disconnect, zonadan chiqishda) barcha faol obunalar avtomatik ravishda tiklanadi. Qayta ulanganda har bir xarakteristika uchun yana setNotifyValue:true chaqirilishi kerak. iOS ilova foreground-dan chiqqanda ham obunalarni yo'qotadi (background mode yoqilmagan bo'lsa) — fon ishi uchun Info.plist da „Uses Bluetooth LE accessories“ capability si yoqilgan bo'lishi kerak.
// CBPeripheral bildirishnoma obunasini boshqarish
class NotificationManager: NSObject {
private var peripheral: CBPeripheral?
private var subscribedCharacteristics: Set<CBUUID> = []
// Barcha .notify xarakteristikalar uchun bildirishnomalarga obuna bo'lish
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)
}
}
}
}
// Barcha bildirishnomalardan obunani bekor qilish
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()
}
// Bildirishnoma 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 obuna menejeri CBPeripheral bildirishnomalari bilan to'g'ri ishlashni namoyish etadi. subscribeToAllNotifications barcha servislar va xarakteristikalarni aylanib chiqadi, .notify va .indicate ni faollashtiradi. subscribedCharacteristics to'g'ri obunani bekor qilish uchun faol obunalarni kuzatadi. didUpdateNotificationStateForCharacteristic characteristic.isNotifying xususiyati orqali obuna holatining muvaffaqiyatli o'zgarishini tasdiqlaydi.
CBPeripheral bilan to'liq ish sikli o'z ichiga oladi: CBCentralManager dan obyektni olish, ulanish, discovery, o'qish/yozish, bildirishnomalarga obuna bo'lish va uzish. Quyidagi misolda Swift-da zamonaviy async/await API (iOS 15+) yordamida BLE-periferiyaning to'liq hayot aylanishini boshqaradigan BLEConnection sinfi amalga oshirilgan.
import CoreBluetooth
// async/await bilan to'liq CBPeripheral boshqarish namunasi
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 qurilmaga ulanish
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 qurilma holatini boshqarish
}
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 orqali Swift Concurrency (async/await) dan foydalanadi — Core Bluetooth delegat API-lari bilan ishlash uchun zamonaviy namuna. connect(to:) didConnectPeripheral orqali ulanish tasdig'ini kutadi, discoverServices() — didDiscoverServices orqali. Bu yondashuv ichma-ich delegatlardan xalos qiladi va BLE kodini chiziqli va o'qiladigan qiladi. BLEError orqali xato boshqaruvi BLE ulanishining barcha tipik muvaffaqiyatsizlik stsenariylarini qamrab oladi.
Tez-tez beriladigan savollar
CBPeripheral avval ulangan qurilma uchun CBCentralManager da retrievePeripheralsWithIdentifiers: orqali olinishi mumkin. Oldin saqlangan qurilmalarning UUID (NSUUID) massivini uzating — framework tizim BLE-bonding bazasidagi qurilmalar uchun CBPeripheral massivini qaytaradi. Bu faqat iPhone avval bog'langan qurilmalar uchun ishlaydi. Yangi qurilma uchun skan qilish majburiydir.
Asosiy sabablar: qurilma zonadan tashqarida (RSSI chegaradan past), BLE radiosi o'chirilgan (CBCentralManager.state != .poweredOn), CBPeripheralDelegate delegati o'rnatilmagan (peripheral.delegate = self) yoki discoverServices ulanishdan oldin chaqirilgan. centralManager.state holatini tekshiring, delegat connect chaqiruvidan oldin o'rnatilganligiga ishonch hosil qiling va 5–10 soniya taym-aut bilan retry dan foydalaning.
Sabab — faqat .writeWithoutResponse ni qo'llab-quvvatlovchi xarakteristikada .withResponse dan foydalanish yoki aksincha. characteristic.properties ni chaqiruvdan oldin tekshiring. MTU muammosi ham bo'lishi mumkin: agar ma'lumot > 20 bayt (BLE 4.0 MTU) bo'lsa, negotiateMTU yoki fragmentatsiya orqali MTU kelishuvi talab qilinadi. Maksimal paket hajmini aniqlash uchun peripheral.maximumWriteValueLength(for: .withResponse) dan foydalaning.
Zonadan tashqaridagi CBPeripheral darhol uzilmaydi — iOS uni taym-aut orqali (odatda 20–30 soniya) .disconnected holatiga o'tkazadi. Kuzatish uchun CBPeripheral da readRSSI dan foydalaning — mavjud bo'lmaganda CBError.connectionTimeout kodi bilan xato qaytaradi. Shuningdek, ulanish uzilishini o'z vaqtida aniqlash uchun centralManager:didDisconnectPeripheral:error: ni kuzating.
Core Bluetooth thread-xavfsiz emas — barcha CBPeripheral chaqiruvlari bitta navbatdan bajarilishi kerak (odatda main queue yoki CBCentralManager ishga tushirilganda ko'rsatilgan ketma-ket serial queue). Turli threadlardan bir vaqtning o'zida chaqiruvlar race condition va ilovaning ishdan chiqishiga olib keladi. Barcha BLE operatsiyalari uchun DispatchQueue(label: „com.app.ble“) va UI yangilash uchun DispatchQueue.main.async dan foydalaning.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.