GATT (Generic Attribute Profile) — نمایه Bluetooth Low Energy (BLE) که ساختار داده و قوانین تبادل اطلاعات بین دستگاههای BLE را تعریف میکند. GATT بر روی Attribute Protocol (ATT) ساخته شده است و دادهها را در سلسلهمراتبی سازماندهی میکند: سرویسها (services)، ویژگیها (characteristics) و توصیفگرها (descriptors). بر اساس دادههای Bluetooth SIG (2025)، نمایه GATT در 98٪ از همه برنامههای BLE استفاده میشود — از ردیابهای تناسب اندام گرفته تا قفلهای هوشمند و حسگرهای پزشکی.
نکات اصلی
GATT (Generic Attribute Profile) — نمایه Bluetooth Low Energy (BLE) است که نحوه تبادل داده بین دو دستگاه BLE را از طریق Attribute Protocol (ATT) تعریف میکند. GATT ساختار داده را استاندارد میکند: همه دادهها در سلسلهمراتب «سرویس → ویژگی → توصیفگر» سازماندهی شدهاند. این نمایه در مشخصات Bluetooth 4.0 (2010) همراه با BLE معرفی شد و از آن زمان تاکنون مکانیسم اصلی انتقال داده برای دستگاههای Bluetooth کممصرف باقی مانده است. برخلاف Bluetooth کلاسیک، که در آن دادهها از طریق پورت سریال (SPP) منتقل میشوند، GATT دسترسی ساختاریافته به دادهها را از طریق عملیات خواندن، نوشتن و اعلان فراهم میکند.
پشته BLE از چندین لایه تشکیل شده است: Physical Layer (رادیو)، Link Layer (مدیریت اتصال)، L2CAP (انتقال کانال منطقی)، ATT (Attribute Protocol — دسترسی به ویژگیها) و GATT (نمایه مبتنی بر ATT). GATT بالاترین لایهای است که توسعهدهنده برنامه با آن کار میکند. ATT زیرین عملیات پایه را فراهم میکند: خواندن، نوشتن، اعلان و نشانهگذاری ویژگیها. GATT معناشناسی را اضافه میکند: تعریف میکند که سرویس چیست، ویژگی چیست، چگونه گروهبندی میشوند و چه قوانینی در هنگام خواندن و نوشتن آنها اعمال میشود. طبق Bluetooth Core Specification 5.4 (2023)، GATT تا 65,535 ویژگی (سرویسها + ویژگیها + توصیفگرها) را در یک دستگاه پشتیبانی میکند.
سلسلهمراتب GATT از سه سطح تشکیل شده است. سرویس (Service) — گروه منطقی از ویژگیها که یک وظیفه را حل میکند (مثلاً «سرویس باتری» یا «سرویس ضربان قلب»). ویژگی (Characteristic) — واحد داده با نوع مشخص: سطح شارژ فعلی، خوانش حسگر، وضعیت کلید. هر ویژگی دارای یک مقدار (value) و یک یا چند توصیفگر (Descriptors) است که فراداده را توصیف میکنند: واحدهای اندازهگیری، تنظیمات اعلان، محدوده مقادیر. UUID (Universally Unique Identifier) هر سرویس و هر ویژگی را به طور یکتا شناسایی میکند.
GATT چهار نوع عملیات برای تعامل با ویژگیها پشتیبانی میکند. Read — کلاینت مقدار فعلی ویژگی را از سرور درخواست میکند. Write — کلاینت مقدار جدیدی به سرور ارسال میکند. Notify — سرور مقدار را بدون تأیید به کلاینت ارسال میکند (روش سریعتر اما کمتر قابل اعتماد). Indicate — سرور مقدار را با تأیید دریافت ارسال میکند (قابل اعتمادتر اما کندتر). توسعهدهنده بسته به سناریو نوع را انتخاب میکند: برای خوانش حسگر ضربان قلب Notify کافی است، برای نوشتن تنظیمات قفل هوشمند — Write با تأیید.
// ساختار داده GATT در کد Android
data class BleService(
val uuid: UUID,
val characteristics: List<BleCharacteristic>
)
data class BleCharacteristic(
val uuid: UUID,
val properties: Int, // READ، WRITE، NOTIFY، INDICATE
val descriptors: List<BleDescriptor>,
var value: ByteArray?
)
در مشخصات BLE دو نمایه اصلی تعریف شده است: GAP (Generic Access Profile) و GATT (Generic Attribute Profile). GAP مسئول کشف دستگاهها، برقراری اتصال و مدیریت دیدپذیری است — این «لایه شبکه» BLE است. GATT — برای تبادل داده پس از برقراری اتصال، یعنی «لایه کاربردی». توسعهدهنده از GAP برای اسکن و اتصال به دستگاه استفاده میکند و از GATT — برای خواندن، نوشتن و دریافت اعلان از دستگاه متصل.
| ویژگی | GAP | GATT |
|---|---|---|
| هدف | کشف و اتصال | تبادل داده |
| نقشها | Central / Peripheral | Client / Server |
| پروتکل | HCI, Link Layer | ATT (Attribute Protocol) |
| مرحله | قبل از اتصال | پس از اتصال |
| کلاس اصلی | BluetoothAdapter | BluetoothGatt |
GATT دو نقش تعریف میکند: GATT Server و GATT Client. سرور — دستگاهی که داده ارائه میدهد (مثلاً ردیاب تناسب اندام که ضربان قلب را ارسال میکند). کلاینت — دستگاهی که داده درخواست میکند (مثلاً گوشی هوشمندی که خوانشها را میخواند). در بیشتر سناریوها، برنامه Android به عنوان GATT Client عمل میکند و تجهیزات جانبی BLE به عنوان GATT Server. با این حال، Android همچنین میتواند GATT Server باشد — مثلاً اگر برنامه یک دستگاه BLE را برای دستگاههای دیگر شبیهسازی کند. نقش در مرحله برقراری اتصال GATT تعیین میشود و در طول جلسه تغییر نمیکند.
فرآیند ارتباطات GATT پس از برقراری اتصال BLE بین دستگاهها آغاز میشود. ابتدا GATT Client سرویسها را در GATT Server از طریق عملیات Service Discovery کشف میکند — Android این کار را به طور خودکار هنگام اتصال از طریق BluetoothGatt.discoverServices() انجام میدهد. پس از کشف، کلاینت لیست سرویسها، ویژگیها و توصیفگرهای موجود را دریافت میکند. سپس کلاینت میتواند مقادیر ویژگیها را بخواند (Read)، مقادیر جدید بنویسد (Write) یا در اعلانها مشترک شود (Set Notify/Indicate). GATT Server میتواند در هر زمان پس از برقراری اتصال، Notify/Indicate را به کلاینت ارسال کند.
به طور پیشفرض، اندازه یک بسته GATT (MTU, Maximum Transmission Unit) در BLE 23 بایت است که 3 بایت آن هدر ATT و 20 بایت داده مفید است. اگر برنامه نیاز به انتقال داده بیشتری داشته باشد (مثلاً بهروزرسانی OTA سیستمعامل)، میتوان از طریق requestMtu() در Android درخواست افزایش MTU تا 517 بایت داد. MTU افزایشیافته تعداد بستههای لازم برای انتقال یک بلوک داده را کاهش میدهد — به جای 50 بسته کوچک میتوان 2 بسته بزرگ ارسال کرد که مصرف انرژی را کاهش داده و انتقال را سرعت میبخشد. حداکثر MTU به نسخه BLE و قابلیتهای تراشه بستگی دارد — Bluetooth 5.0 تا 517 بایت، نسخههای قدیمیتر تا 247 بایت را پشتیبانی میکنند.
// اشتراک در اعلانهای ویژگی
fun enableNotifications(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
gatt.setCharacteristicNotification(characteristic, true)
// فعالسازی CCCD (Client Characteristic Configuration Descriptor)
val cccdUuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
val descriptor = characteristic.getDescriptor(cccdUuid)
descriptor?.let {
it.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
gatt.writeDescriptor(it)
}
}
برای دریافت اعلان از GATT Server در Android باید callback BluetoothGattCallback.onCharacteristicChanged() را پیادهسازی کرد. در این متد، برنامه هر بار که سرور Notify یا Indicate ارسال میکند، مقدار بهروز شده ویژگی را دریافت میکند. برای پردازش داده در زمان واقعی از بافر و کوروتینهای Kotlin استفاده کنید — این کار باعث میشود نخ UI در هنگام اعلانهای فشرده (مثلاً 100+ خوانش ضربان قلب در ثانیه) مسدود نشود. در نشانهگذاریها (Indicate) حتماً gatt.sendResponse() را در سمت سرور فراخوانی کنید — در کلاینت Android این کار به طور خودکار انجام میشود.
در Android کار با GATT از طریق کلاسهای بسته android.bluetooth انجام میشود: BluetoothGatt (اتصال)، BluetoothGattService (سرویس)، BluetoothGattCharacteristic (ویژگی) و BluetoothGattDescriptor (توصیفگر). اتصال به دستگاه BLE با فراخوانی BluetoothDevice.connectGatt() آغاز میشود — این متد BluetoothGatt را برمیگرداند که از طریق آن تمام عملیات بعدی انجام میشود. همه callbackهای GATT در BluetoothGattCallback دریافت میشوند — این یک رابط ناهمزمان است که در همان نخی که BluetoothGatt در آن ایجاد شده فراخوانی میشود. مهم: همه عملیات GATT باید به صورت ترتیبی انجام شوند — فراخوانی همزمان چندین عملیات روی یک BluetoothGatt منجر به خطا میشود.
مدیریت صحیح چرخه حیات اتصال GATT برای پایداری برنامه BLE حیاتی است. پس از فراخوانی connectGatt()، برنامه منتظر callback onConnectionStateChange() با وضعیت STATE_CONNECTED میماند. سپس سیستم به طور خودکار Service Discovery را شروع میکند و پس از اتمام آن onServicesDiscovered() فراخوانی میشود. فقط پس از این میتوان خواندن، نوشتن و اشتراک را انجام داد. پس از اتمام کار حتماً gatt.close() را در onDestroy() یا onPause() فراخوانی کنید — اتصالات GATT بسته نشده باتری مصرف میکنند و ممکن است اتصال مجدد به همان دستگاه را در Android مسدود کنند.
// اتصال به دستگاه BLE از طریق GATT
private val gattCallback = object : BluetoothGattCallback() {
override fun onConnectionStateChange(
gatt: BluetoothGatt, status: Int, newState: Int
) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices()
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
val service = gatt.getService(UUID.fromString("180D"))
val characteristic = service?.getCharacteristic(
UUID.fromString("2A37")
)
characteristic?.let { enableNotifications(gatt, it) }
}
}
Bluetooth SIG (Special Interest Group) دهها نمایه و سرویس استاندارد GATT با UUIDهای 16 بیتی ثابت تعریف میکند. رایجترین آنها: سرویس Battery Service (UUID 180F، ویژگی Battery Level 2A19)، سرویس Heart Rate (UUID 180D، ویژگی Heart Rate Measurement 2A37)، سرویس Device Information (UUID 180A، ویژگیهای Manufacturer Name، Serial Number). استفاده از سرویسهای استاندارد سازگاری بین دستگاههای تولیدکنندگان مختلف را تضمین میکند — هر دستبند تناسب اندام با سرویس Heart Rate باید با هر برنامه Android که از آن پشتیبانی میکند کار کند.
اگر سرویسهای استاندارد وظیفه را پوشش نمیدهند، توسعهدهنده میتواند سرویسهای GATT خود را با UUIDهای 128 بیتی (UUID سفارشی) ایجاد کند. هنگام طراحی سرویس سفارشی باید: گروه منطقی ویژگیها را تعریف کنید (مثلاً «سرویس مدیریت قفل»)، به هر ویژگی ویژگیهای صحیح (Read, Write, Notify) بدهید، مقادیر مجاز و واحدهای اندازهگیری را از طریق توصیفگر Characteristic Presentation Format تعیین کنید. برای پروتکلهای پیچیده توصیه میشود یک ویژگی Command با ویژگی Write و یک ویژگی Status با Notify در سرویس گنجانده شود — این مطابق الگوی Command/Status است که در برنامههای صنعتی BLE پذیرفته شده است.
// ایجاد سرویس سفارشی GATT (Android به عنوان GATT Server)
private fun createCustomService(): BluetoothGattService {
val serviceUuid = UUID.fromString("12345678-1234-5678-1234-56789abcdef0")
val service = BluetoothGattService(
serviceUuid, BluetoothGattService.SERVICE_TYPE_PRIMARY
)
val charUuid = UUID.fromString("12345678-1234-5678-1234-56789abcdef1")
val characteristic = BluetoothGattCharacteristic(
charUuid,
BluetoothGattCharacteristic.PROPERTY_READ or
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ
)
service.addCharacteristic(characteristic)
return service
}
سوالات متداول
GATT (Generic Attribute Profile) — نمایه Bluetooth Low Energy است که ساختار تبادل داده بین دستگاهها را تعریف میکند. برای استانداردسازی دسترسی به اطلاعات لازم است: همه دستگاههای BLE دادهها را در سرویسها و ویژگیها سازماندهی میکنند که به هر کلاینتی اجازه میدهد خوانش حسگرها را بخواند، دستگاهها را کنترل کند و اعلان دریافت کند.
GAP مسئول کشف و اتصال دستگاههای BLE (اسکن، تبلیغات، برقراری اتصال) است. GATT — برای تبادل داده پس از اتصال (خواندن، نوشتن، اعلانها). GAP قبل از اتصال کار میکند، GATT — بعد از آن. هر دو نمایه برای BLE الزامی هستند اما وظایف متفاوتی دارند: GAP «لایه شبکه» است، GATT «لایه کاربردی».
سرویسهای استاندارد شامل Battery Service (180F، سطح شارژ)، Heart Rate (180D، ضربان قلب)، Device Information (180A، اطلاعات دستگاه) هستند. هر سرویس شامل چندین ویژگی با UUID 16 بیتی است. توسعهدهندگان میتوانند سرویسهای سفارشی با UUID 128 بیتی برای وظایف خاص ایجاد کنند — مثلاً کنترل قفل هوشمند یا انتقال دادههای ردیاب تناسب اندام.
در Android، GATT از طریق BluetoothGatt (اتصال)، BluetoothGattService (سرویس)، BluetoothGattCharacteristic (ویژگی) و BluetoothGattDescriptor (توصیفگر) پیادهسازی میشود. اتصال از طریق connectGatt() انجام میشود، پس از آن رویدادها در callback BluetoothGattCallback دریافت میشوند: onConnectionStateChange، onServicesDiscovered، onCharacteristicChanged (برای اعلانها). همه عملیات GATT باید به صورت ترتیبی انجام شوند.
UUID (Universally Unique Identifier) — شناسه 16 بیتی یا 128 بیتی که سرویس یا ویژگی را در GATT به طور یکتا مشخص میکند. سرویسهای استاندارد Bluetooth SIG از UUIDهای 16 بیتی استفاده میکنند (مثلاً 180D برای Heart Rate). سرویسهای سفارشی توسعهدهندگان — UUIDهای 128 بیتی (مثلاً 12345678-1234-5678-1234-56789abcdef0). UUID به کلاینت اجازه میدهد دادههای مورد نیاز را در GATT Server پیدا کند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید