Wi-Fi ağı bulunmayan ortamlarda veya cihazın ilk kurulumunda (Provisioning – telefondan cihaza Wi-Fi şifresi tanımlama) en az güç tüketen ve akıllı telefonlarla doğrudan haberleşen teknoloji BLE (Bluetooth Low Energy / Bluetooth 4.2 & 5.0) standardıdır. ESP-IDF üzerinde ESP-IDF BLE GATT sunucusu (Generic Attribute Profile) kurmak; sensör verilerini bildirim (Notification) olarak akıllı telefonlara göndermeyi ve telefondan gelen ayar komutlarını kablosuz olarak almayı sağlar.
Bu rehberde; BLE profil mimarisini (Services, Characteristics, Descriptors), hafif ve az bellek tüketen NimBLE protokol yığınını, reklam paketleri (Advertising) yayınlamayı ve telefon uygulamasıyla (nRF Connect) iki yönlü veri transferini öğreneceğiz.
BLE Mimarisi: GAP ve GATT Temelleri
BLE dünyası iki ana protokole dayanır:
- GAP (Generic Access Profile): Cihazın görünürlüğünü kontrol eder. Cihaz yayın yapar (Advertising: “Benim adım ESP32-Device”) ve telefonun bağlanmasını sağlar.
- GATT (Generic Attribute Profile): Bağlantı kurulduktan sonra verilerin nasıl yapılandırılacağını belirler:
– Service (Servis): Mantıksal bir veri grubu (örn: Çevre Algılama Servisi, UUID: 0x181A). – Characteristic (Karakteristik): Gerçek veriyi tutan değişken (örn: Sıcaklık, UUID: 0x2A6E). Özellikleri: Read, Write, Notify. – Descriptor (Tanımlayıcı): Karakteristiğin ek ayarı (örn: Bildirimleri açıp kapatma izni – CCCD).
Neden NimBLE Yığını? (Bluedroid Alternatifi)
ESP-IDF’te iki Bluetooth yığını bulunur:
- Bluedroid: Klasik Bluetooth (BT Classic) ve BLE destekler; ancak ~120 KB RAM tüketir.
- NimBLE (Apache NimBLE): Sadece BLE odaklıdır; son derece hafiftir, yalnızca ~30 KB RAM tüketir ve çok daha hızlı bağlanır. Modern IoT projelerinde standart tercihtir (
menuconfigüzerinden seçilebilir).
Adım Adım NimBLE GATT Sunucusu Kodu
Aşağıdaki örnekte bir özel servis (0x180F – Batarya Servisi) ve okunabilir/yazılabilir bir karakteristik tanımlıyoruz:
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
static const char *TAG = "BLE_SERVER";
static uint8_t battery_level = 85; // %85 pil seviyesi
// 1. Karakteristik Okuma / Yazma Geri Çağırım Fonksiyonu
static int gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg) {
if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
ESP_LOGI(TAG, "Telefondan Pil Seviyesi Okundu: %d%%", battery_level);
os_mbuf_append(ctxt->om, &battery_level, sizeof(battery_level));
return 0;
} else if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
uint8_t new_val;
uint16_t len = OS_MBUF_PKTLEN(ctxt->om);
ble_hs_mbuf_to_flat(ctxt->om, &new_val, sizeof(new_val), NULL);
ESP_LOGI(TAG, "Telefondan Yeni Değer Yazıldı: %d", new_val);
battery_level = new_val;
return 0;
}
return BLE_ATT_ERR_UNLIKELY;
}
// 2. GATT Servis ve Karakteristik Tablosu
static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
{
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(0x180F), // Battery Service UUID
.characteristics = (struct ble_gatt_chr_def[]) {
{
.uuid = BLE_UUID16_DECLARE(0x2A19), // Battery Level UUID
.access_flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY,
.access_cb = gatt_svr_chr_access,
},
{ 0 } // Sonlandırıcı
},
},
{ 0 } // Servis Tablosu Sonu
};
Adım 3: Reklam (Advertising) Başlatmak
Cihazın etraftaki telefonlar tarafından “ESP32-Sensor” adıyla bulunabilmesi için yayın başlatılır:
static void ble_app_advertise(void) {
struct ble_gap_adv_params adv_params;
struct ble_hs_adv_fields fields;
memset(&fields, 0, sizeof(fields));
fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
fields.name = (uint8_t *)"ESP32-Sensor";
fields.name_len = strlen("ESP32-Sensor");
fields.name_is_complete = 1;
ble_gap_adv_set_fields(&fields);
memset(&adv_params, 0, sizeof(adv_params));
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; // Herkese bağlanabilir mod
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; // Genel keşfedilebilir mod
ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, NULL, NULL);
ESP_LOGI(TAG, "BLE Yayını Başladı! nRF Connect ile taranabilir.");
}
Test Etme: nRF Connect Mobil Uygulaması
Telefonunuza ücretsiz nRF Connect for Mobile uygulamasını indirip “Scan” butonuna bastığınızda:
ESP32-Sensoraygıtını göreceksiniz.- “Connect” dediğinizde
Battery Service (0x180F)listelenecektir. - Karakteristiğin yanındaki ok işaretine bastığınızda cihazdaki
85değerini telefon ekranında anında okuyabilirsiniz!
Özet
NimBLE yığını ile ESP32 üzerinde yüksek performanslı ve ultra düşük bellekli BLE sunucuları kurabilirsiniz. Wi-Fi şifresi gerektirmeyen doğrudan telefon haberleşmesi sayesinde akıllı ev ve medikal projelerinizde kusursuz bir kullanıcı deneyimi sunabilirsiniz.