00 BlueZ mimarisi — D-Bus, HCI, kernel yığını
BlueZ, Linux'un resmi Bluetooth protokol yığınıdır. Kernel'dan uygulama katmanına kadar tüm Bluetooth işlevlerini kapsar.
Uygulama (Python, C, bluetoothctl)
↓ D-Bus API
bluetoothd → BlueZ daemon (userspace)
↓ HCI socket (BTPROTO_HCI)
Kernel Bluetooth subsystem
├── L2CAP (Logical Link Control)
├── RFCOMM (Serial Port Emulation)
├── BNEP (Bluetooth Network Encapsulation)
├── HID (Human Interface Device)
└── ATT/GATT (BLE)
↓
HCI driver → hci_uart (UART), hci_usb (USB), hci_vhci
↓
Bluetooth donanımı (BCM43xx, CSR8510, nRF52, CC2642)
BlueZ, uygulamalarla D-Bus üzerinden iletişim kurar. bluetoothd daemon'ı, sistem D-Bus üzerinde org.bluez servisini sunar. Tüm Bluetooth nesneleri (adapter, device, GATT service) D-Bus object path'leri ile temsil edilir.
Kurulum
# Debian / Ubuntu / Raspberry Pi OS
apt-get install bluez bluetooth
# Python D-Bus kütüphanesi
pip3 install pydbus PyGObject
# BlueZ versiyon kontrol
bluetoothd --version
# 5.66
# Servis başlat
systemctl start bluetooth
# HCI cihazlarını listele
hciconfig
# hci0: Type: Primary Bus: UART
# BD Address: DC:A6:32:XX:XX:XX ACL MTU: 1021:8 SCO MTU: 64:1
# UP RUNNING
01 bluetoothctl — cihaz tarama, eşleştirme, bağlama
bluetoothctl, BlueZ'in interaktif komut satırı aracıdır. D-Bus API'sinin tüm işlevlerine erişim sağlar.
bluetoothctl
# Agent registered
# [bluetooth]#
Temel işlemler
# Adapter bilgisi
[bluetooth]# show
Controller DC:A6:32:XX:XX:XX (public)
Name: raspberrypi
Alias: raspberrypi
Class: 0x00200000
Powered: yes
Discoverable: no
DiscoverableTimeout: 0x000000b4
Pairable: yes
UUID: Generic Attribute Profile (00001801-...)
UUID: Generic Access Profile (00001800-...)
Modalias: usb:v1D6Bp0246d0537
Discovering: no
# Adaptörü aç/kapat
[bluetooth]# power on
[bluetooth]# power off
# Taramayı başlat
[bluetooth]# scan on
# Discovery started
# [NEW] Device AA:BB:CC:DD:EE:01 Sıcaklık_Sensörü
# [NEW] Device AA:BB:CC:DD:EE:02 Telefon
# Bulunan cihazları listele
[bluetooth]# devices
# Device AA:BB:CC:DD:EE:01 Sıcaklık_Sensörü
# Device AA:BB:CC:DD:EE:02 Telefon
# Taramayı durdur
[bluetooth]# scan off
# Cihaza bağlan (eşleştirmeden)
[bluetooth]# connect AA:BB:CC:DD:EE:01
# Eşleştir (pair)
[bluetooth]# pair AA:BB:CC:DD:EE:01
# Güvenilir yap (otomatik bağlantı)
[bluetooth]# trust AA:BB:CC:DD:EE:01
# Cihaz bilgisi
[bluetooth]# info AA:BB:CC:DD:EE:01
# Device AA:BB:CC:DD:EE:01 (public)
# Name: Sıcaklık_Sensörü
# Alias: Sıcaklık_Sensörü
# Paired: yes
# Trusted: yes
# Connected: yes
# RSSI: -52
# Bağlantıyı kes
[bluetooth]# disconnect AA:BB:CC:DD:EE:01
# Eşleştirmeyi kaldır
[bluetooth]# remove AA:BB:CC:DD:EE:01
Non-interaktif bluetoothctl
# Tek komut çalıştır
bluetoothctl power on
bluetoothctl show
# Pipe ile komut dizisi
echo -e "power on\nscan on" | bluetoothctl
# Expect benzeri yaklaşım (script)
bluetoothctl -- connect AA:BB:CC:DD:EE:01
02 hciconfig ve hcitool (legacy araçlar)
Eski araçlar hâlâ çalışır, ancak BlueZ 5.x'ten itibaren deprecated sayılır. Düşük seviye HCI debug için yararlıdır.
hciconfig, hcitool ve hcidump, BlueZ 5.40+ ile deprecated oldu. Yeni kodda bluetoothctl veya D-Bus API kullan. Mevcut sistemlerde debug amaçlı hâlâ işe yarar.
hciconfig — adapter yönetimi
# Tüm HCI cihazlarını listele
hciconfig
# hci0: Type: Primary Bus: UART
# BD Address: DC:A6:32:XX:XX:XX
# UP RUNNING PSCAN
# hci0'ı aç
hciconfig hci0 up
# Kamuya açık hale getir (discoverable)
hciconfig hci0 piscan
# Cihaz adını değiştir
hciconfig hci0 name "IoT_Sensor"
# Detaylı bilgi
hciconfig hci0 info
# HCI reset
hciconfig hci0 reset
hcitool — cihaz tarama ve bağlantı
# BR/EDR cihaz tara
hcitool scan
# Scanning ...
# AA:BB:CC:DD:EE:01 Kulaklık
# AA:BB:CC:DD:EE:02 Klavye
# BLE cihaz tara (LE Scan)
hcitool lescan
# LE Scan ...
# AA:BB:CC:DD:EE:03 BLE_Sensor
# AA:BB:CC:DD:EE:04 (unknown)
# Sinyal gücü (RSSI)
hcitool rssi AA:BB:CC:DD:EE:01
# RSSI return value: -52
# Bağlı cihazları listele
hcitool con
# hcidump — HCI paketlerini izle
hcidump -i hci0 -X
03 D-Bus Python API — pydbus
pydbus kütüphanesi ile Python'dan BlueZ D-Bus API'sine erişim — tarama, bağlanma ve cihaz yönetimi.
from pydbus import SystemBus
from gi.repository import GLib
bus = SystemBus()
# BlueZ adapter'ı al
adapter = bus.get('org.bluez', '/org/bluez/hci0')
# Adapter özellikleri
print("Adres:", adapter.Address)
print("İsim:", adapter.Name)
print("Güç:", adapter.Powered)
# Adaptörü aç
adapter.Powered = True
BLE Tarama (Python)
from pydbus import SystemBus
from gi.repository import GLib
import threading
bus = SystemBus()
mainloop = GLib.MainLoop()
adapter = bus.get('org.bluez', '/org/bluez/hci0')
bulunan_cihazlar = {}
def cihaz_eklendi(path, interfaces):
"""Yeni BLE cihazı bulunduğunda çağrılır."""
if 'org.bluez.Device1' not in interfaces:
return
props = interfaces['org.bluez.Device1']
addr = props.get('Address', 'bilinmiyor')
name = props.get('Name', 'isimsiz')
rssi = props.get('RSSI', 0)
print(f" Bulundu: {addr} | {name} | RSSI: {rssi} dBm")
bulunan_cihazlar[addr] = name
# InterfacesAdded sinyaline bağlan
objmanager = bus.get('org.bluez', '/')
objmanager.InterfacesAdded.connect(cihaz_eklendi)
# Taramayı başlat
adapter.StartDiscovery()
print("Tarama başladı — 10 saniye...")
# 10 saniye tarama
def dur():
adapter.StopDiscovery()
mainloop.quit()
GLib.timeout_add_seconds(10, dur)
mainloop.run()
print(f"\nToplam {len(bulunan_cihazlar)} cihaz bulundu.")
Cihaza bağlanma (Python)
from pydbus import SystemBus
import time
bus = SystemBus()
# Cihaz path'i: MAC adresindeki ':' yerine '_'
device_path = '/org/bluez/hci0/dev_AA_BB_CC_DD_EE_01'
device = bus.get('org.bluez', device_path)
# Bağlan
print("Bağlanılıyor...")
device.Connect()
time.sleep(2)
# Durum kontrol
print("Bağlı:", device.Connected)
print("Eşleşmiş:", device.Paired)
print("RSSI:", device.RSSI)
# GATT servislerini listele
print("UUID'ler:", device.UUIDs)
# Bağlantıyı kes
device.Disconnect()
04 BlueZ D-Bus API: Adapter1, Device1, GATT
BlueZ, Bluetooth nesnelerini D-Bus object hiyerarşisi olarak sunar. Bu hiyerarşiyi anlamak GATT programlama için zorunludur.
D-Bus nesne hiyerarşisi
/org/bluez
├── /org/bluez/hci0 (Adapter1)
│ └── /org/bluez/hci0/dev_AA_BB_CC_DD_EE_01 (Device1)
│ ├── /org/bluez/hci0/dev_AA_.../service0001 (GattService1)
│ │ ├── /...service0001/char0002 (GattCharacteristic1)
│ │ │ └── /...char0002/desc0003 (GattDescriptor1)
│ │ └── /...service0001/char0004
│ └── /org/bluez/hci0/dev_AA_.../service0005
Adapter1 arayüzü
Device1 arayüzü
GATT nesneleri (Python ile okuma)
from pydbus import SystemBus
bus = SystemBus()
# Cihaza bağlı olmalı
device_path = '/org/bluez/hci0/dev_AA_BB_CC_DD_EE_01'
# Tüm nesneleri listele (servisler, karakteristikler)
objmanager = bus.get('org.bluez', '/')
objs = objmanager.GetManagedObjects()
for path, ifaces in objs.items():
if 'org.bluez.GattCharacteristic1' in ifaces and device_path in path:
char = ifaces['org.bluez.GattCharacteristic1']
print(f" Char: {path}")
print(f" UUID: {char.get('UUID')}")
print(f" Flags: {char.get('Flags')}")
# Belirli karakteristiği oku
char_path = device_path + '/service0001/char0002'
char = bus.get('org.bluez', char_path)
# Read (READ flag gerekir)
deger = char.ReadValue({})
print("Değer:", bytes(deger))
# Write
char.WriteValue([0x01, 0x02, 0x03], {})
05 BR/EDR vs BLE farkları
Klasik Bluetooth (BR/EDR) ve Bluetooth Low Energy (BLE/LE) farklı protokol yığınlarıdır. Aynı donanımda birlikte çalışabilirler (Bluetooth 4.0+).
Transport seçimi (bluetoothctl)
[bluetooth]# scan on
# Her iki modu da tarar
# Sadece BLE cihazları tara
[bluetooth]# menu scan
[bluetooth]# transport le
[bluetooth]# back
[bluetooth]# scan on
# Sadece klasik Bluetooth
[bluetooth]# transport bredr
# Python'da transport filtresi
from pydbus import SystemBus
bus = SystemBus()
adapter = bus.get('org.bluez', '/org/bluez/hci0')
# Sadece BLE (LE) cihazları tara
adapter.SetDiscoveryFilter({
'Transport': 'le',
'RSSI': -80, # Minimum sinyal eşiği
'DuplicateData': False
})
adapter.StartDiscovery()
06 rfkill ve BlueZ
rfkill, Bluetooth donanımını yazılımsal olarak açıp kapatmak için kullanılır.
# Bluetooth durumunu listele
rfkill list bluetooth
# 1: hci0: Bluetooth
# Soft blocked: no
# Hard blocked: no
# Bluetooth'u blokla (kapat)
rfkill block bluetooth
# Bluetooth'u aç
rfkill unblock bluetooth
# BlueZ bu değişikliği otomatik algılar
bluetoothctl show | grep Powered
# Güç tasarrufu: Bluetooth kullanılmadığında kapat
#!/bin/sh
bluetooth_kullan() {
rfkill unblock bluetooth
bluetoothctl power on
# ... bluetooth işlemleri ...
bluetoothctl power off
rfkill block bluetooth
}
# Kernel rfkill event'lerini izle
cat /dev/rfkill | hexdump -C
07 systemd bluetooth.service
bluetoothd daemon'ı systemd ile yönet, önyüklemede otomatik başlat.
# Servis durumu
systemctl status bluetooth
# Başlat / durdur
systemctl start bluetooth
systemctl stop bluetooth
# Önyüklemede başlasın
systemctl enable bluetooth
# Log izle
journalctl -u bluetooth -f
# bluetoothd'yi debug modda yeniden başlat
systemctl stop bluetooth
bluetoothd -d -n # -n: daemon olmadan, -d: debug
systemd servis dosyası
[Unit]
Description=Bluetooth service
Documentation=man:bluetoothd(8)
ConditionPathIsDirectory=/sys/class/bluetooth
[Service]
Type=dbus
BusName=org.bluez
ExecStart=/usr/lib/bluetooth/bluetoothd
NotifyAccess=main
#WatchdogSec=10
#Restart=on-failure
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
LimitNOFILE=65536
ProtectHome=true
ProtectSystem=full
[Install]
WantedBy=bluetooth.target
Alias=dbus-org.bluez.service
bluetoothd parametreleri
[Policy]
# Otomatik eşleştirme zaman aşımı (saniye)
AutoEnable=true
[General]
# Cihaz adı
Name = EmbeddedDevice
# ClassicBondedOnly: sadece eşleşmiş cihazlardan gelen bağlantı
ClassicBondedOnly = false
# Privacy: BLE random address kullan
Privacy = device
08 Embedded — bluetoothd minimal ve obexd
Gömülü sistemlerde BlueZ'i hafifletmek için gereksiz plugin'leri devre dışı bırak. obexd ile dosya transferi.
bluetoothd --noplugin ile minimal başlatma
# Tüm plugin'leri devre dışı bırak
bluetoothd --noplugin=*
# Belirli plugin'leri hariç tut
bluetoothd --noplugin=sap,a2dp,avrcp,hfp,hsp,hid,gap
# Sadece belirli plugin'leri yükle
bluetoothd --plugin=gatt
# Tüm plugin listesi
bluetoothd --list-plugins
systemd override ile minimal config
[Service]
ExecStart=
ExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=sap,a2dp,avrcp,hfp
obexd — Bluetooth Dosya Transferi
# obexd kurulum
apt-get install obexd
# obexd başlat (OPP: Object Push Profile)
obexd --root=/tmp/bluetooth --opp
# Python ile obex dosya transferi
from pydbus import SessionBus
import time
bus = SessionBus()
# obexd session bus üzerinde çalışır
client = bus.get('org.bluez.obex', '/org/bluez/obex')
# Oturum oluştur
session_path, props = client.CreateSession(
'AA:BB:CC:DD:EE:01',
{'Target': 'opp'}
)
session = bus.get('org.bluez.obex', session_path)
opp = bus.get('org.bluez.obex', session_path + '/opp')
# Dosya gönder
transfer_path, props = opp.SendFile('/tmp/sensor_data.csv')
# Transfer tamamlanmasını bekle
transfer = bus.get('org.bluez.obex', transfer_path)
while transfer.Status != 'complete':
time.sleep(0.5)
print("Transfer tamamlandı:", transfer.Transferred, "bayt")
# Oturumu kapat
client.RemoveSession(session_path)
IoT sensör düğümlerinde BlueZ sadece GATT server/client ihtiyacı için kullanılıyorsa --noplugin=* ile başlat. Bu, RAM kullanımını önemli ölçüde azaltır. Buildroot'ta BR2_PACKAGE_BLUEZ5_UTILS=y ve yalnızca gerekli plugin'leri seç.