ESP32 ile Bluetooth Mesh Ağı Kurulumu
Bluetooth Mesh Nedir ve Neden ESP32?
Bluetooth Mesh, Bluetooth Low Energy (BLE) teknolojisi üzerine inşa edilmiş, çoktan çoğa (many-to-many) iletişim sağlayan bir ağ topolojisidir. Geleneksel Bluetooth bağlantılarının aksine, mesh ağında her düğüm (node) hem veri gönderebilir hem de diğer düğümlerden gelen verileri iletebilir. Bu sayede geniş alanlarda, yüzlerce cihazın birbirleriyle iletişim kurması mümkün hale gelir.
ESP32, Espressif Systems tarafından üretilen, Wi-Fi ve Bluetooth 4.2/BLE desteği sunan güçlü bir mikrodenetleyicidir. Düşük maliyeti, geniş topluluk desteği ve ESP-IDF framework'ünün sunduğu kapsamlı Bluetooth Mesh API'leri sayesinde mesh ağı projeleri için ideal bir tercihtir.
Gerekli Donanım ve Yazılım
Donanım
- En az 3 adet ESP32 DevKit v1 veya benzeri geliştirme kartı (mesh ağının anlamlı çalışması için minimum 3 düğüm önerilir)
- Micro USB kabloları
- Provisioner olarak kullanılacak bir akıllı telefon (opsiyonel — nRF Mesh uygulaması ile)
Yazılım
- ESP-IDF v5.x (Espressif IoT Development Framework)
- Python 3.8+ (ESP-IDF araçları için)
- VS Code + ESP-IDF eklentisi (opsiyonel ama önerilir)
- nRF Mesh mobil uygulaması (Android/iOS — provisioning için)
ESP-IDF Ortamının Kurulumu
Öncelikle ESP-IDF'i sisteminize kurmanız gerekir. Linux veya macOS üzerinde terminal ile aşağıdaki adımları izleyin:
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git -b v5.2
cd esp-idf
./install.sh esp32
source export.sh
Kurulum tamamlandıktan sonra her yeni terminal oturumunda source ~/esp/esp-idf/export.sh komutunu çalıştırarak ortam değişkenlerini yüklemeniz gerekir. Bunu .bashrc veya .zshrc dosyanıza ekleyerek otomatikleştirebilirsiniz.
Bluetooth Mesh Temel Kavramları
Koda geçmeden önce mesh ağının temel kavramlarını anlamak önemlidir:
- Node (Düğüm): Mesh ağına dahil edilmiş (provision edilmiş) her bir cihaz.
- Provisioner: Yeni cihazları ağa ekleyen, güvenlik anahtarlarını dağıtan yetkili düğüm.
- Element: Bir düğüm içindeki adreslenebilir birim. Her düğümün en az bir elementi vardır.
- Model: Bir elementin desteklediği işlevselliği tanımlar. Örneğin Generic OnOff Server modeli, bir LED'i açıp kapatmayı temsil eder.
- Publish/Subscribe: Düğümler mesajlarını belirli adreslere yayınlar (publish) ve belirli adreslerden gelen mesajlara abone olur (subscribe).
- Relay: Mesajları diğer düğümlere ileten düğüm. Mesh ağının kapsama alanını genişletir.
Proje Yapısı ve Konfigürasyon
ESP-IDF'in örnek projelerinden yola çıkarak kendi mesh projemizi oluşturalım:
cp -r $IDF_PATH/examples/bluetooth/esp_ble_mesh/onoff_models/onoff_server ~/esp/mesh_node
cd ~/esp/mesh_node
Projenin sdkconfig dosyasında Bluetooth Mesh desteğinin aktif olduğundan emin olun. idf.py menuconfig komutuyla yapılandırmaya girin ve şu ayarları kontrol edin:
- Component config → Bluetooth → Bluedroid → BLE Mesh: Etkinleştirilmiş olmalı
- BLE Mesh Relay: Relay özelliğini kullanacak düğümler için etkinleştirin
- BLE Mesh Proxy: Telefon ile iletişim için gereklidir
- BLE Mesh Friend / Low Power: Düşük güçlü düğümler için opsiyonel
Generic OnOff Server Uygulaması
Aşağıdaki kod, bir ESP32'yi mesh ağında Generic OnOff Server olarak yapılandırır. Bu düğüm, uzaktan açılıp kapatılabilen bir LED'i kontrol eder:
#include "esp_ble_mesh_defs.h"
#include "esp_ble_mesh_common_api.h"
#include "esp_ble_mesh_networking_api.h"
#include "esp_ble_mesh_provisioning_api.h"
#include "esp_ble_mesh_config_model_api.h"
#include "esp_ble_mesh_generic_model_api.h"
#include "driver/gpio.h"
#define LED_PIN GPIO_NUM_2
#define CID_ESP 0x02E5
static uint8_t dev_uuid[16] = { 0x32, 0x10 };
// OnOff durumunu tutan değişken
static esp_ble_mesh_gen_onoff_srv_t onoff_server = {
.rsp_ctrl = {
.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP,
},
};
// Model tanımları
static esp_ble_mesh_model_t root_models[] = {
ESP_BLE_MESH_MODEL_CFG_SRV_DEFAULT(),
ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(
&publish_info, &onoff_server),
};
// Element tanımı
static esp_ble_mesh_elem_t elements[] = {
ESP_BLE_MESH_ELEMENT(0, root_models,
ESP_BLE_MESH_MODEL_NONE),
};
// Composition data
static esp_ble_mesh_comp_t composition = {
.cid = CID_ESP,
.elements = elements,
.element_count = ARRAY_SIZE(elements),
};
// Provisioning özellikleri
static esp_ble_mesh_prov_t provision = {
.uuid = dev_uuid,
};
// Provisioning callback
static void mesh_prov_cb(esp_ble_mesh_prov_cb_event_t event,
esp_ble_mesh_prov_cb_param_t *param)
{
switch (event) {
case ESP_BLE_MESH_PROV_REGISTER_COMP_EVT:
ESP_LOGI("MESH", "Provisioning kaydı tamamlandı");
break;
case ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT:
ESP_LOGI("MESH", "Düğüm ağa eklendi! "
"Adres: 0x%04x",
param->node_prov_complete.addr);
break;
default:
break;
}
}
// Generic Server model callback
static void mesh_model_cb(
esp_ble_mesh_generic_server_cb_event_t event,
esp_ble_mesh_generic_server_cb_param_t *param)
{
switch (event) {
case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT:
if (param->ctx.model->model_id ==
ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV) {
uint8_t onoff = param->value
.state_change.onoff_set.onoff;
gpio_set_level(LED_PIN, onoff);
ESP_LOGI("MESH", "LED durumu: %s",
onoff ? "AÇIK" : "KAPALI");
}
break;
default:
break;
}
}
void app_main(void)
{
// GPIO yapılandırması
gpio_reset_pin(LED_PIN);
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
// NVS ve BT başlatma
esp_err_t err = nvs_flash_init();
ESP_ERROR_CHECK(err);
ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg));
ESP_ERROR_CHECK(esp_bt_controller_enable(
ESP_BT_MODE_BLE));
ESP_ERROR_CHECK(esp_bluedroid_init());
ESP_ERROR_CHECK(esp_bluedroid_enable());
// Callback'leri kaydet
esp_ble_mesh_register_prov_callback(mesh_prov_cb);
esp_ble_mesh_register_generic_server_callback(
mesh_model_cb);
// Mesh başlat
err = esp_ble_mesh_init(&provision, &composition);
if (err != ESP_OK) {
ESP_LOGE("MESH", "Mesh başlatılamadı: %d", err);
return;
}
ESP_LOGI("MESH", "BLE Mesh OnOff Server başlatıldı");
esp_ble_mesh_node_prov_enable(
ESP_BLE_MESH_PROV_ADV |
ESP_BLE_MESH_PROV_GATT);
}
Derleme ve Yükleme
Projeyi derleyip ESP32'ye yüklemek için aşağıdaki komutları kullanın:
idf.py set-target esp32
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor
Not: Birden fazla ESP32 kartınız varsa her birini ayrı USB portlarına bağlayın ve /dev/ttyUSB0, /dev/ttyUSB1 gibi farklı port isimlerini kullanın. Windows'ta bu portlar COM3, COM4 şeklinde görünür.
Provisioning (Ağa Ekleme) İşlemi
ESP32 düğümlerini mesh ağına eklemek için nRF Mesh uygulamasını kullanabilirsiniz:
- Uygulamayı açın ve "Add Node" seçeneğine tıklayın.
- Uygulama, BLE üzerinden reklam (advertising) yapan provisionlanmamış düğümleri tarar.
- ESP32 düğümünüzü listeden seçin ve "Identify" butonuna basın.
- "Provision" butonuna basarak düğümü ağa ekleyin. Bu adımda güvenlik anahtarları değiş tokuş edilir.
- Provisioning tamamlandıktan sonra düğümün Generic OnOff Server modeline erişebilirsiniz.
- Aynı işlemi diğer ESP32 kartları için de tekrarlayın.
Mesaj Yayılımı ve Relay Yapılandırması
Bluetooth Mesh'in en güçlü yanlarından biri managed flooding mekanizmasıdır. Bir düğüm mesaj gönderdiğinde, relay özelliği aktif olan tüm düğümler bu mesajı tekrar yayınlar. Bu sayede mesaj, doğrudan menzil dışında olan düğümlere de ulaşabilir.
Relay özelliğini etkinleştirmek için menuconfig içinde BLE Mesh Relay seçeneğini aktif edin. Ayrıca provisioning sonrası nRF Mesh uygulamasından düğümün Configuration Server modeli üzerinden relay özelliğini açabilirsiniz.
Mesajların sonsuz döngüye girmesini önlemek için her mesajın bir TTL (Time To Live) değeri vardır. Her relay işleminde TTL bir azaltılır ve sıfıra ulaştığında mesaj artık iletilmez. Varsayılan TTL değeri genellikle 5'tir ve çoğu senaryo için yeterlidir.
Publish/Subscribe Yapılandırması
Düğümler arası iletişimi yönetmek için grup adresleri kullanılır. Örneğin, bir odadaki tüm lambaları tek bir komutla kontrol etmek için:
- Bir grup adresi oluşturun (ör.
0xC000— "Salon Lambaları") - Kontrol edilecek tüm düğümlerin OnOff Server modelini bu gruba subscribe ettirin
- Kontrol düğümünün (istemci) OnOff Client modelini aynı gruba publish edecek şekilde ayarlayın
Bu yapılandırma nRF Mesh uygulamasından veya programatik olarak Configuration Client modeli aracılığıyla yapılabilir.
Performans ve Güvenlik İpuçları
Performans
- Ağdaki düğüm sayısı arttıkça managed flooding trafiği de artar. 100'den fazla düğüm içeren ağlarda relay düğümlerini stratejik olarak konumlandırın.
- Mesaj gönderim sıklığını makul tutun — saniyede birden fazla mesaj göndermekten kaçının.
- Düşük güçlü cihazlar için Friend/Low Power Node özelliklerini kullanın. LPN'ler sürekli dinleme yapmak yerine periyodik olarak Friend düğümden mesajlarını alır.
Güvenlik
- Bluetooth Mesh, AES-CCM 128-bit şifreleme kullanır. Tüm mesajlar ağ katmanında şifrelenir.
- NetKey (ağ anahtarı) tüm ağ trafiğini şifreler, AppKey (uygulama anahtarı) ise uygulama verilerini şifreler. Bu iki katmanlı yapı sayesinde relay düğümleri mesajları iletirken içeriğini okuyamaz.
- Provisioning sırasında OOB (Out of Band) doğrulama kullanmak güvenliği artırır. Statik OOB değeri veya çıktı OOB (LED yanıp sönme sayısı gibi) yöntemlerini tercih edin.
- Düğüm çıkarma işleminde Key Refresh prosedürünü uygulayarak ağ anahtarlarını yenileyin. Aksi takdirde çıkarılan düğüm hâlâ ağ trafiğini dinleyebilir.
Hata Ayıklama
Mesh ağı geliştirirken karşılaşılan yaygın sorunlar ve çözümleri:
- Düğüm provisioning listesinde görünmüyor:
esp_ble_mesh_node_prov_enable()fonksiyonunun çağrıldığından ve hemADVhemGATTbearer'ların aktif olduğundan emin olun. - Mesajlar iletilmiyor: TTL değerini kontrol edin. Relay özelliğinin aktif olduğundan ve düğümlerin aynı NetKey'i paylaştığından emin olun.
- Yüksek gecikme: Ağdaki relay düğüm sayısını artırın veya düğümler arasındaki fiziksel mesafeyi azaltın.
- NVS hatası:
idf.py erase-flashkomutuyla flash belleği temizleyin ve yeniden yükleyin.
Sonuç
ESP32 ile Bluetooth Mesh ağı kurmak, akıllı ev otomasyonu, endüstriyel IoT, aydınlatma kontrolü ve sensör ağları gibi birçok alanda güçlü bir çözüm sunar. ESP-IDF'in kapsamlı BLE Mesh desteği sayesinde, düşük maliyetli donanımlarla profesyonel düzeyde mesh ağları oluşturmak mümkündür. Başlangıç olarak bu yazıdaki OnOff Server örneğini çalıştırın, ardından sensör modelleri, sahne (scene) yönetimi ve OTA güncelleme gibi ileri düzey özellikleri keşfedin.