ארגון חילופי נתוני GATT עם התקני BLE היקפיים
דמיינו שאתם מפתחים אפליקציה לאינטראקציה עם חיישן דופק רפואי דרך BLE. לאחר החיבור, אתם מנסים להירשם להתראות דופק, אבל הנתונים לא מגיעים. באנדרואיד, אתם רואים שגיאה 133; ב-iOS, כתיבת המאפיין מחזירה שגיאה. נתקלנו בזה ביותר מ-20 פרויקטי אינטגרציית BLE: חיישנים רפואיים, שעוני כושר, בקרים תעשייתיים. משימה נפוצה אחת היא הרשמה להתראות דופק או העברת כמויות נתונים גדולות, כמו קובץ קושחה של 100 KB. עם MTU ברירת מחדל של 23 בתים, שליחת 100 KB דורשת כ-5000 חבילות, מה שלוקח דקות. בקשת MTU גדול יותר של 512 בתים מפחיתה את מספר החבילות לכ-200 ואת זמן ההעברה לשניות. פיתחנו גישה שיטתית לחילופי נתוני BLE אמינים: מהרשמה נכונה להתראות ועד לתורי פעולות ומשא ומתן על MTU.
סוגי פעולות מאפיין GATT
לכל מאפיין GATT יש קבוצת דגלי properties הקובעים פעולות אפשריות. הנה טבלת עזר מהירה:
| דגל | iOS (CBCharacteristicProperties) | אנדרואיד | פעולה |
|---|---|---|---|
| קריאה | .read |
PROPERTY_READ |
קריאה חד-פעמית |
| כתיבה | .write |
PROPERTY_WRITE |
כתיבה עם אישור קבלה |
| כתיבה ללא תגובה | .writeWithoutResponse |
PROPERTY_WRITE_NO_RESPONSE |
כתיבה מהירה |
| התראה | .notify |
PROPERTY_NOTIFY |
התראות ללא אישור קבלה |
| אינדיקציה | .indicate |
PROPERTY_INDICATE |
התראות עם אישור קבלה |
Write Without Response מהיר יותר — ללא ACK מהמכשיר. מתאים לסטרימינג (שמע, קריאות חיישנים). Write מיועד לפקודות שבהן חשובה אחריות למסירה.
MTU: כיצד להגדיל את תפוקת ערוץ BLE
כברירת מחדל, MTU של BLE (יחידת העברה מקסימלית) הוא 23 בתים, עם רק 20 בתים של מטען. כדי להעביר 10 KB של נתונים, זה אומר 500 חבילות. אם תבקשו MTU גדול יותר (לדוגמה, 512), מספר החבילות יורד לכ-20 — חיסכון של עד 90% בזמן. הנה איך לעשות זאת בכל פלטפורמה:
| פלטפורמה | MTU ברירת מחדל | משא ומתן אוטומטי | בקשה ידנית |
|---|---|---|---|
| iOS | 23 | כן (מאז iOS 9+) | בעקיפין דרך אורך כתיבה מקסימלי |
| אנדרואיד | 23 | לא | gatt.requestMtu(512) + קריאה חוזרת onMtuChanged |
בפועל, רוב שבבי BLE תומכים ב-MTU של 247–512 בתים. זה קריטי להעברות קושחה או תצורה גדולה.
כיצד להירשם להתראות BLE ולא לפספס נתונים?
הרשמה להתראות היא הדרך הסטנדרטית לקבל נתונים בזמן אמת ממכשיר BLE. ב-iOS, פשוט קוראים ל-setNotifyValue(true, for:). אבל באנדרואיד, התהליך מורכב יותר: צריך לא רק להפעיל התראות מקומית, אלא גם לכתוב במפורש את הערך ENABLE_NOTIFICATION_VALUE למתאר CCCD (Client Characteristic Configuration Descriptor). מפתחים רבים מדלגים על שלב זה — וההתראות לא מגיעות.
iOS: הרשמה להתראות וניתוח
// Включаем notify
peripheral.setNotifyValue(true, for: characteristic)
// Получаем данные
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
guard error == nil, let data = characteristic.value else { return }
// Пример: датчик отправляет 3 байта [flags, heartRate, energyExpended]
guard data.count >= 2 else { return }
let flags = data[0]
let heartRate: Int
if flags & 0x01 == 0 {
// heart rate в 1 байте
heartRate = Int(data[1])
} else {
// heart rate в 2 байтах (little-endian)
heartRate = Int(data[1]) | (Int(data[2]) << 8)
}
}עבודה עם נתונים בינאריים דרך // Включаем notify peripheral.setNotifyValue(true, for: characteristic) // Получаем данные func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { guard error == nil, let data = characteristic.value else { return } // Пример: датчик отправляет 3 байта [flags, heartRate, energyExpended] guard data.count >= 2 else { return } let flags = data[0] let heartRate: Int if flags & 0x01 == 0 { // heart rate в 1 байте heartRate = Int(data[1]) } else { // heart rate в 2 байтах (little-endian) heartRate = Int(data[1]) | (Int(data[2]) << 8) } } + היסטי בתים. אם המכשיר אינו סטנדרטי והתיעוד דל, Data + מצית BLE עוזרים לפענח את הפרוטוקול.
אנדרואיד: התראה + מתאר CCCD
התראה דורשת שני שלבים: הפעלת התראה מקומית וכתיבת CCCD במכשיר:
fun enableNotification(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { // Шаг 1: включаем locally
gatt.setCharacteristicNotification(characteristic, true)
// Шаг 2: пишем дескриптор на устройство
val cccd = characteristic.getDescriptor(
UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
) ?: return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
gatt.writeDescriptor(cccd, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
} else {
@Suppress("DEPRECATION")
cccd.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
@Suppress("DEPRECATION")
gatt.writeDescriptor(cccd)
}
}שלב 2 מוחמץ לעתים קרובות — וההתראות לא מגיעות. זו הטעות הנפוצה ביותר בעבודה עם התראות.
מדוע אנדרואיד מציג שגיאה 133 וכיצד להימנע ממנה?
פרט קריטי אחד של BLE באנדרואיד: לא ניתן לבצע מספר פעולות GATT בו-זמנית. רק פעולה אחת בטיסה. שלחו את הבאה רק לאחר קבלת הקריאה החוזרת עבור הקודמת. הפרת כלל זה מובילה לשגיאת Wireshark או לאובדן נתונים ברוב מכשירי האנדרואיד.
פתרון — תור:
class BleOperationQueue {
private val queue: LinkedList<BleOperation> = LinkedList()
private var operationInProgress = false
fun enqueue(operation: BleOperation) {
queue.add(operation)
if (!operationInProgress) {
executeNext()
}
}
fun onOperationCompleted() {
operationInProgress = false
executeNext()
}
private fun executeNext() {
val op = queue.poll() ?: return
operationInProgress = true
op.execute()
}
} תהליך יישום חילופי BLE
אנו מפרקים את יישום חילופי BLE אמינים לשלבים:
- ניתוח פרוטוקול המכשיר או מפרט שירות GATT.
- תכנון תור הפעולות ותוכנית ניתוח הנתונים.
- יישום בפלטפורמות היעד (iOS/אנדרואיד) עם טיפול ב-MTU, חיבור וחיבור מחדש.
- בדיקות על מכשירים אמיתיים עם גרסאות מערכת הפעלה שונות.
- אינטגרציה לאפליקציית הלקוח ומסירת תיעוד.
מה כלול בעבודה
במסגרת השירות, אנו מספקים:
- ניתוח ותיעוד של פרוטוקול מכשיר ה-BLE הנוכחי.
- קוד מקור למודול חילופי הנתונים ב-Swift/Kotlin עם תור פעולות ותמיכה ב-MTU.
- בדיקות אינטגרציה על 3+ מכשירים אמיתיים.
- תיעוד API תמציתי למודול.
- חודש ייעוץ לאחר המסירה.
אנו מבטיחים הרשמה יציבה להתראות, כתיבת פקודות נכונה וטיפול בשגיאות בשתי הפלטפורמות. צרו קשר להערכה ראשונית של הפרויקט שלכם. קבלו ייעוץ מהמהנדסים שלנו אם אתם מחפשים פתרון אינטגרציית BLE מוכן או נתקלים בשגיאות חילופי נתונים.
לוח זמנים ותמחור
לוח זמנים ליישום — מ-3 עד 10 ימים בהתאם למורכבות הפרוטוקול הבינארי ומספר הפלטפורמות. התמחור מחושב באופן אישי לאחר ניתוח הדרישות.







