11.4. Reklam yapma ve tarama¶
Daha önce hiç karşılaşmamış iki BLE cihazının önce birbirini bulması gerekir. Ağ kullanımı bunu, her cihaza paylaşılan bir havuzdan bir adres vererek ve her iki tarafın da yönlendiriciler aracılığıyla diğerine ulaşmasına izin vererek çözer. BLE’de yönlendirici yoktur, paylaşılan havuz yoktur ve çoğu cihaz çifti arasında önceden hiçbir ilişki yoktur. Generic Access Profile (GAP) bunun yerine keşfi bir yayınla-ve-dinle deseniyle çözer. Bir taraf reklam yapar: kim olduğunu açıklayan kısa bir paketi düzenli aralıklarla üç reklam kanalında iletir. Diğer taraf tarama yapar: aynı üç kanalı bu paketleri dinleyerek tarar.
GAP, bu desen etrafında her biri reklam yapma ve dinlemenin belirli bir kombinasyonu olan dört rol tanımlar.
11.4.1. Dört GAP rolü¶
Dört GAP rolü. Dikey eksen cihazın reklam yapıp yapmadığı; yatay eksen ise bağlantıları kabul edip etmediği (veya başlatıp başlatmadığı).¶
Bir peripheral (çevre birim), “buradayım ve bana bağlanabilirsin” diyen paketlerin reklamını yapar. Başka bir cihaz bir bağlantı açtığında, peripheral reklam yapmayı durdurur ve GATT isteklerine hizmet vermeye başlar. Nabız bantları, termometreler ve sensör olarak çoğu kamera peripheral olarak davranır.
Bir central (merkezi), peripheral’lar için tarama yapar, birini seçer ve bir bağlantı başlatır. Bağlandıktan sonra bir istemci olarak GATT konuşur. Telefonlar, dizüstü bilgisayarlar ve veri toplayıcı olarak davranan kameralar central’dır.
Bir broadcaster (yayıncı) reklam yapar ancak hiçbir zaman bağlantı kabul etmez. Reklam yükü veri olur: bağlanılacak bir şey yoktur. iBeacon’lar ve mağaza varlık işaret vericilerinin çoğu broadcaster’dır.
Bir observer (gözlemci) bu reklamlar için tarama yapar ve yükü okur, yine hiçbir zaman bağlanmadan. Yakındaki işaret vericileri dinleyen ve duyduğuna göre hareket eden bir kamera observer’dır.
Tek bir cihaz aynı anda birden fazla rol oynayabilir: bir kamera, kendi durumunu yayınlayan bir peripheral ve yakındaki bir sensöre bağlanan bir central olabilir. Telsiz işi çoğullar.
11.4.2. Bir reklam paketinin içeriği¶
Bir reklam paketi küçüktür: 31 bayt yük, veya reklam veren ayrıca tarayıcıların anlık olarak isteyebileceği bir tarama yanıtı (scan response) yayınlıyorsa 62 bayt. Yük, kısa türlü alanlardan oluşan bir listedir:
Flags (bayraklar). Bağlanılabilir olup olmadığı, genel/sınırlı keşfedilebilir.
Yerel ad. Kısa, insan dostu bir dize: bir telefon veya dizüstü bilgisayardaki işletim sisteminin Bluetooth menüsünde gösterdiği ad.
Servis UUID’leri. Cihazın barındırdığı GATT servis tanımlayıcılarının bir listesi; böylece bir tarayıcı önce bağlanmadan yetenekli peripheral’ları tanıyabilir. Bir nabız bandı
0x180Dreklamını yapar (standart Heart-Rate servis UUID’si) ve telefondaki bir nabız uygulaması yalnızca bundan, cihazın bağlanmaya değer olduğunu bilir.Appearance (görünüm). Bluetooth atanmış-numaralar listesinden 16 bitlik bir değer (sensör, genel ortam, genel saat, …): central’a neyi göstereceği konusunda bir ipucu.
Üreticiye özel veri. Bir şirket kimliğiyle ön eklenmiş serbest biçimli baytlar. iBeacon’lar bu alanı UUID, major ve minor değerlerini taşımak için kullanır; özel uygulamalar buraya istedikleri her şeyi koyabilir.
Reklam yükleri sıkıdır. 31 baytlık sınır, neyin dahil edileceğini seçmeyi gerçek bir tasarım kararı haline getirir; uzun, insan tarafından okunabilir bir ad servis UUID’lerine yer bırakmayabilir. aioble.advertise() API’si bunların her birini bir anahtar sözcük argümanı olarak alır ve baytları sizin için birleştirir; ana paket dolarsa otomatik olarak tarama yanıtına taşar.
11.4.3. Aktif ve pasif tarama¶
Bir tarayıcı pasif çalışabilir; bu durumda reklam paketlerini dinler ve gelenleri ayrıştırır, veya aktif çalışabilir; bu durumda ayrıca her reklam verene bir tarama isteği (scan request) gönderir ve geri gelen tarama yanıtını ayrıştırır.
Pasif tarama yalnızca ilk reklam paketini görür (en fazla 31 bayt). Aktif tarama bunu ikiye katlar: tarama yanıtı, peripheral’ın sığmayan alanlar için kullanabileceği başka bir 31 bayttır. Aktif tarama ayrıca her iki tarafta da güce mal olur, çünkü tarayıcı iletir ve reklam veren fazladan bir paket iletir; dolayısıyla bu varsayılan değil, bir seçimdir.
aioble API’sinde, aioble.scan() üzerindeki active=True modu değiştirir ve her ScanResult, bayt seviyesindeki ayrıştırmayı gizleyen result.name() ve result.services() gibi yardımcıların yanı sıra birleştirilmiş adv_data artı resp_data değerlerini açığa çıkarır.
Not
adv_data ve resp_data öznitelikleri ham reklam ve tarama-yanıtı yükleridir (bytes). Yardımcılar (name(), services(), manufacturer()) yaygın standart alanları kapsar ve %99 oranında doğru seçimdir. Ham baytlara yalnızca yardımcıların ayrıştırmadığı bir satıcı alanına ihtiyaç duyduğunuzda başvurun (Eddystone URL’leri, iBeacon UUID/major/minor, özel reklam türleri). Bayt düzeni standart TLV düzenidir: her alan length, type, value... şeklindedir.
11.4.4. Reklam aralığı¶
Peripheral’ın ne sıklıkla yayın yaptığı bir güç/keşif-gecikmesi ödünleşmesidir. Her 20 ms’de bir çıkan reklamlar bir tarayıcı tarafından neredeyse anında alınır ancak telsizi meşgul tutar ve pili tüketir; her saniyede bir çıkan reklamlar neredeyse hiç güç kullanmaz ancak bir tarayıcının cihazı fark etmesini için yaptığı taramayı yavaşlatır.
aioble.advertise() üzerindeki interval_us aralığı mikrosaniye cinsinden ayarlar:
20.000 ila 100.000 us (20 ms - 100 ms): hızlı eşleşme, uygulamanın hızlı yanıt beklediği, prize takılı cihaz.
250.000 ila 1.000.000 us (250 ms - 1 s): şarjı tüketmeden keşfedilebilir olmak isteyen pille çalışan bir peripheral için makul bir varsayılan.
1.000.000 us’nin üzerinde: yavaş arka plan yayını, birkaç saniyede bir konum güncellemesi gönderen işaret vericileri.
Tarayıcı tarafının kendi ayarları vardır: aioble.scan(), interval_us ve window_us değerlerini alır (tarayıcının telsizini ne sıklıkla uyandırdığı ve her seferinde ne kadar süre dinlediği). Varsayılanlar uygundur; tek yaygın değişiklik, pil bir endişe olmadığında sürekli bir tarama için her ikisini de eşit ayarlamaktır.
11.4.5. Bağlantısız desenler: broadcaster ve observer¶
Çevre birimi olarak davranma ve Merkez olarak davranmak sayfaları API’nin bağlanılabilir biçimini işler; bir peripheral’ın bir bağlantıyı kabul ettiği ve iki tarafın GATT aracılığıyla veri alışverişi yaptığı yer. Diğer biçim bağlantısızdır: bir broadcaster yükü-reklam-olarak iletir ve menzildeki herhangi bir observer bunu hiçbir zaman bağlanmadan okuyabilir. İşaret vericileri, varlık sensörleri ve tek yönlü telemetri burada yaşar.
Bir broadcaster, connectable=False ile aioble.advertise()‘dır. Yükü üreticiye özel veri taşır:
import aioble
import asyncio
import struct
_COMPANY_ID = const(0xFFFF) # 0xFFFF is "no specific vendor"
async def beacon():
seq = 0
while True:
seq = (seq + 1) & 0xFFFF
payload = struct.pack("<H", seq)
await aioble.advertise(
interval_us=500000,
connectable=False,
name="openmv-beacon",
manufacturer=(_COMPANY_ID, payload),
timeout_ms=1000, # one cycle, then loop
)
asyncio.run(beacon())
timeout_ms anahtar sözcüğü advertise çağrısını bir saniye sonra sonlandırır; dış döngü onu bir sonraki sıra numarasıyla yeniden yayınlar, böylece dinleyiciler taze veri görür. connectable=False bayrağı reklamı broadcaster tarzı yapan şeydir: bir bağlanma isteği gelse bile kamera buna yanıt vermez.
Bir observer, eşleşen salt okunur tarayıcıdır. aioble.scan()‘i sonsuza kadar çalıştırır, gelen reklamları ayrıştırır ve hiçbir zaman connect()‘i çağırmaz:
import aioble
import asyncio
_COMPANY_ID = const(0xFFFF)
async def watch():
async with aioble.scan(duration_ms=0, active=False) as scanner:
async for result in scanner:
for company, data in result.manufacturer(filter=_COMPANY_ID):
print(result.device.addr_hex(),
"rssi", result.rssi, "data", data)
asyncio.run(watch())
duration_ms=0, bağlam yöneticisi çıkana kadar tarar; active=False, en düşük güç tüketimi için observer’ın kendi telsizini sessiz tutar (tarama-yanıtı istekleri yok). manufacturer() üzerindeki filter= argümanı, şirket kimliğiyle eşleşmeyen her reklamı atar, böylece döngü yalnızca broadcaster’ın trafiği için tetiklenir.
11.4.6. Keşiften bir bağlantıya¶
Bir central konuşacağı bir peripheral seçtiğinde, dinlemeyi durdurur, peripheral’ın en son kullandığı reklam kanalında bir bağlanma isteği (connect request) gönderir ve her iki taraf da bağlantı katmanının atlamalı veri kanallarına geçer. Peripheral bu noktada genellikle reklam yapmayı durdurur. Bundan sonra ne olduğu (bağlantı parametreleri, GATT keşfi, bağlantının ömrü) Bağlantılar sayfasındadır.