WebBluetooth'a Giriş
Yayınlanan: 2022-03-10Aşamalı Web Uygulamaları ile web, yerel uygulamalara her zamankinden daha fazla yaklaşıyor. Ancak, gizlilik ve platformlar arası uyumluluk gibi web'e özgü ek avantajlarla.
Web, geleneksel olarak ağdaki sunucularla ve özellikle İnternet'teki sunucularla konuşmak konusunda harika olmuştur. Artık web uygulamalara doğru ilerlediğine göre, yerel uygulamaların sahip olduğu yeteneklere de ihtiyacımız var.
Tarayıcılarda son birkaç yılda uygulanan yeni özelliklerin ve özelliklerin miktarı şaşırtıcı. WebGL ve yakında çıkacak WebGPU gibi 3D ile başa çıkmak için spesifikasyonlarımız var. Ses akışı ve üretebilir, video izleyebilir ve web kamerasını bir giriş aygıtı olarak kullanabiliriz. Ayrıca WebAssembly kullanarak kodu neredeyse yerel hızlarda çalıştırabiliriz. Ayrıca, başlangıçta yalnızca ağ ortamı olmasına rağmen, web, hizmet çalışanları ile çevrimdışı desteğe doğru ilerledi.
Bu harika ve hepsi, ancak bir alan yerel uygulamalar için neredeyse özel alan olmuştur: cihazlarla iletişim. Bu bizim uzun zamandır çözmeye çalıştığımız bir problem ve muhtemelen herkesin bir noktada karşılaştığı bir problem. Web, sunucularla konuşmak için mükemmeldir, ancak cihazlarla konuşmak için değil . Örneğin, ağınızda bir yönlendirici kurmaya çalışmayı düşünün. Muhtemelen herhangi bir güvenlik olmaksızın bir IP adresi girmeniz ve düz bir HTTP bağlantısı üzerinden bir web arayüzü kullanmanız gerekebilir. Bu sadece kötü bir deneyim ve kötü güvenlik. Bunun da ötesinde, doğru IP adresinin ne olduğunu nereden biliyorsunuz?
HTTP, aynı zamanda, bir cihazla konuşmaya çalışan bir Aşamalı Web Uygulaması oluşturmaya çalıştığımızda karşılaştığımız ilk sorundur. PWA'lar yalnızca HTTPS'dir ve yerel cihazlar her zaman yalnızca HTTP'dir. HTTPS için bir sertifikaya ihtiyacınız var ve bir sertifika almak için, alan adına sahip herkese açık bir sunucuya ihtiyacınız var (yerel ağımızda erişilemeyen cihazlardan bahsediyorum).
Bu nedenle, birçok cihaz için, cihazları kurmak ve kullanmak için yerel uygulamalara ihtiyacınız vardır, çünkü yerel uygulamalar web platformunun sınırlamalarına bağlı değildir ve kullanıcıları için hoş bir deneyim sunabilir. Ancak, bunu yapmak için 500 MB'lık bir uygulama indirmek istemiyorum. Belki de sahip olduğunuz cihaz birkaç yaşındadır ve uygulama yeni telefonunuzda çalışacak şekilde hiçbir zaman güncellenmemiştir. Belki bir masaüstü veya dizüstü bilgisayar kullanmak istiyorsunuz ve üretici yalnızca bir mobil uygulama geliştirdi. Ayrıca ideal bir deneyim değil.
WebBluetooth, Chrome ve Samsung İnternet'te uygulanan ve tarayıcıdan Bluetooth Düşük Enerji cihazlarıyla doğrudan iletişim kurmamızı sağlayan yeni bir özelliktir. WebBluetooth ile birlikte Progresif Web Uygulamaları, cihazlarla doğrudan konuşma gücüne sahip bir web uygulamasının güvenliğini ve rahatlığını sunar.
Bluetooth, sınırlı menzil, kötü ses kalitesi ve eşleştirme sorunları nedeniyle oldukça kötü bir isme sahip. Ancak, hemen hemen tüm bu sorunlar geçmişte kaldı. Bluetooth Low Energy, aynı frekans spektrumunu kullanmak dışında, eski Bluetooth spesifikasyonlarıyla pek ilgisi olmayan modern bir spesifikasyondur . Her gün 10 milyondan fazla cihaz Bluetooth desteğiyle gönderilir. Buna bilgisayarlar ve telefonların yanı sıra kalp atış hızı ve glikoz monitörleri gibi çeşitli cihazlar, ampuller gibi IoT cihazları ve uzaktan kumandalı arabalar ve dronlar gibi oyuncaklar dahildir.
Önerilen okuma : API Tabanlı Platformları Anlama: Ürün Yöneticileri İçin Bir Kılavuz
Sıkıcı Teorik Kısım
Bluetooth'un kendisi bir web teknolojisi olmadığı için bize yabancı gelebilecek bazı kelimeler kullanır. Şimdi Bluetooth'un nasıl çalıştığını ve bazı terminolojiyi gözden geçirelim.
Her Bluetooth cihazı ya bir 'Merkezi cihaz' veya bir 'Çevre Birimi'dir. Yalnızca merkezi cihazlar iletişimi başlatabilir ve yalnızca çevre birimleriyle konuşabilir. Merkezi bir cihaza örnek olarak bir bilgisayar veya cep telefonu verilebilir.
Bir çevre birimi iletişimi başlatamaz ve yalnızca merkezi bir cihazla konuşabilir. Ayrıca, bir çevre birimi aynı anda yalnızca bir merkezi cihazla konuşabilir. Bir çevre birimi başka bir çevre birimiyle konuşamaz.
Merkezi bir cihaz aynı anda birden fazla çevre birimiyle konuşabilir ve isterse mesajları iletebilir. Yani bir kalp atış hızı monitörü ampullerinizle konuşamaz, ancak kalp atış hızınızı alan ve kalp atış hızı belirli bir eşiğin üzerine çıkarsa ışıkları kırmızıya çeviren merkezi bir cihazda çalışan bir program yazabilirsiniz.
WebBluetooth hakkında konuştuğumuzda, GATT kısaltmasına sahip olan Genel Nitelik Profili adlı Bluetooth spesifikasyonunun belirli bir bölümünden bahsediyoruz. (GAP zaten alınmış.)
GATT bağlamında artık merkezi cihazlar ve çevre birimlerinden değil, istemcilerden ve sunuculardan bahsediyoruz. Ampulleriniz sunucudur. Bu sezgisel görünebilir, ancak düşünürseniz aslında mantıklı geliyor. Ampul bir hizmet, yani ışık sunar. Tıpkı tarayıcının İnternet'teki bir sunucuya bağlanması gibi, telefonunuz veya bilgisayarınız da ampuldeki GATT sunucusuna bağlanan bir istemcidir.
Her sunucu bir veya daha fazla hizmet sunar. Bu hizmetlerden bazıları resmi olarak standardın bir parçasıdır, ancak kendinizinkini de tanımlayabilirsiniz. Kalp atış hızı monitörü söz konusu olduğunda, teknik özelliklerde tanımlanan resmi bir hizmet vardır. Ampul söz konusu olduğunda, yoktur ve hemen hemen her üretici tekerleği yeniden icat etmeye çalışır. Her hizmetin bir veya daha fazla özelliği vardır. Her özelliğin okunabilen veya yazılabilen bir değeri vardır. Şimdilik bunu, her bir nesnenin değerleri olan özelliklere sahip olduğu bir nesneler dizisi olarak düşünmek en iyisi olacaktır.
Nesnelerin özelliklerinden farklı olarak, hizmetler ve özellikler bir dize ile tanımlanmaz. Her hizmet ve özellik, 16 veya 128 bit uzunluğunda olabilen benzersiz bir UUID'ye sahiptir. Resmi olarak, 16 bit UUID resmi standartlar için ayrılmıştır, ancak hemen hemen hiç kimse bu kurala uymaz. Son olarak, her değer bir bayt dizisidir. Bluetooth'ta süslü veri türleri yoktur.
Bluetooth Ampulüne Yakından Bakış
Şimdi gerçek bir Bluetooth cihazına bakalım: bir Mipow Playbulb Sphere. Cihaza bağlanmak ve tüm hizmetleri ve özellikleri görmek için BLE Scanner veya nRF Connect gibi bir uygulama kullanabilirsiniz. Bu durumda, iOS için BLE Tarayıcı uygulamasını kullanıyorum.
Ampule bağlandığınızda ilk gördüğünüz şey bir servis listesidir. Cihaz bilgi servisi ve pil servisi gibi bazı standartlaştırılmış olanlar var. Ancak bazı özel hizmetler de var. 0xff0f
16 bit UUID'sine sahip hizmetle özellikle ilgileniyorum. Bu hizmeti açarsanız, uzun bir özellik listesi görebilirsiniz. Yalnızca bir UUID tarafından tanımlandıkları ve ne yazık ki özel bir hizmetin parçası oldukları için bu özelliklerin çoğunun ne yaptığı hakkında hiçbir fikrim yok; standart değildirler ve üretici herhangi bir belge sağlamamıştır.
0xfffc
UUID'sine sahip ilk özellik özellikle ilginç görünüyor. Dört baytlık bir değere sahiptir. Bu baytların değerini 0x00000000
0x00ff0000
değiştirirsek, ampul kırmızıya döner. 0x0000ff00
olarak değiştirmek, ampulü yeşile ve 0x000000ff
maviye dönüştürür. Bunlar RGB renkleridir ve HTML ve CSS'de kullandığımız altıgen renklere tam olarak karşılık gelir.
Bu ilk bayt ne yapar? Değeri 0xff000000
olarak değiştirirsek, ampul beyaza döner. Ampul dört farklı LED içerir ve dört baytın her birinin değerini değiştirerek istediğimiz her rengi oluşturabiliriz.
WebBluetooth API'sı
Bir ampulün rengini değiştirmek için yerel bir uygulama kullanabilmemiz harika, ancak bunu tarayıcıdan nasıl yaparız? Bluetooth ve GATT hakkında yeni öğrendiğimiz bilgilerle, WebBluetooth API sayesinde bunun nispeten basit olduğu ortaya çıktı. Bir ampulün rengini değiştirmek için sadece birkaç satır JavaScript yeterlidir.
WebBluetooth API'sini gözden geçirelim.
Bir Cihaza Bağlanma
Yapmamız gereken ilk şey tarayıcıdan cihaza bağlanmak. navigator.bluetooth.requestDevice()
fonksiyonunu çağırırız ve fonksiyona bir konfigürasyon nesnesi sağlarız. Bu nesne, hangi cihazı kullanmak istediğimiz ve API'mizde hangi hizmetlerin mevcut olması gerektiği hakkında bilgiler içerir.
Aşağıdaki örnekte, sadece PLAYBULB
önekini içeren cihazları görmek istediğimiz için cihazın adına göre filtreleme yapıyoruz. Ayrıca kullanmak istediğimiz bir hizmet olarak 0xff0f
. requestDevice()
işlevi bir söz verdiği için sonucu bekleyebiliriz.
let device = await navigator.bluetooth.requestDevice({ filters: [ { namePrefix: 'PLAYBULB' } ], optionalServices: [ 0xff0f ] });
Bu fonksiyonu çağırdığımızda belirlemiş olduğumuz filtrelere uyan cihazların listesinin bulunduğu bir pencere açılır. Şimdi bağlanmak istediğimiz cihazı manuel olarak seçmeliyiz. Bu, güvenlik ve gizlilik için önemli bir adımdır ve kontrolü kullanıcıya verir. Web uygulamasının bağlanmasına ve tabii ki hangi cihaza bağlanmasına izin verilip verilmeyeceğine kullanıcı karar verir. Web uygulaması, kullanıcı manuel olarak bir cihaz seçmeden cihazların listesini alamaz veya bağlanamaz.
Cihaza erişim sağladıktan sonra cihazın gatt
özelliği üzerinde bulunan connect()
fonksiyonunu çağırarak GATT sunucusuna bağlanabilir ve sonucu bekleyebiliriz.
let server = await device.gatt.connect();
Sunucumuza sahip olduğumuzda, parametre olarak kullanmak istediğimiz hizmetin UUID'si ile sunucu üzerinde getPrimaryService()
'i çağırabilir ve sonucu bekleyebiliriz.
let service = await server.getPrimaryService(0xff0f);
Ardından, parametre olarak özelliğin UUID'si ile hizmette getCharacteristic()
çağırın ve sonucu tekrar bekleyin.
Artık veri yazmak ve okumak için kullanabileceğimiz özelliklerimiz var:
let characteristic = await service.getCharacteristic(0xfffc);
Veri Yazma
Veri yazmak için, ikili veriler için bir depolama yöntemi olan ArrayBuffer olarak yazmak istediğimiz değere sahip karakteristiğe writeValue()
işlevini çağırabiliriz. Düzenli bir dizi kullanamamamızın nedeni, düzenli dizilerin çeşitli türlerde veri içerebilmesi ve hatta boş deliklere sahip olabilmesidir.
Doğrudan bir ArrayBuffer oluşturamayacağımız veya değiştiremeyeceğimiz için bunun yerine 'yazılan dizi' kullanıyoruz. Yazılan bir dizinin her elemanı her zaman aynı tiptedir ve herhangi bir deliği yoktur. Bizim durumumuzda, herhangi bir negatif sayı içeremeyeceği için işaretsiz olan bir Uint8Array
kullanacağız; bir tamsayı, bu nedenle kesirler içeremez; ve 8 bittir ve yalnızca 0 ile 255 arasındaki değerleri içerebilir. Başka bir deyişle: bir bayt dizisi.
characteristic.writeValue( new Uint8Array([ 0, r, g, b ]) );
Bu özel ampulün nasıl çalıştığını zaten biliyoruz. Her LED için bir tane olmak üzere dört bayt sağlamamız gerekiyor. Her bayt 0 ile 255 arasında bir değere sahiptir ve bu durumda sadece kırmızı, yeşil ve mavi LED'leri kullanmak istiyoruz, bu yüzden 0 değerini kullanarak beyaz LED'i kapalı bırakıyoruz.
Veri Okuma
Ampulün mevcut rengini okumak için readValue()
fonksiyonunu kullanabilir ve sonucu bekleyebiliriz.
let value = await characteristic.readValue(); let r = value.getUint8(1); let g = value.getUint8(2); let b = value.getUint8(3);
Geri aldığımız değer, bir ArrayBuffer'ın DataView'idir ve verileri ArrayBuffer'dan çıkarmanın bir yolunu sunar. Bizim durumumuzda, diziden bireysel baytları çıkarmak için bir indeksli getUint8()
işlevini parametre olarak kullanabiliriz.
Değişikliklerden Haberdar Olmak
Son olarak, bir cihazın değeri değiştiğinde bildirim almanın da bir yolu var. Bu bir ampul için pek kullanışlı değil, ancak kalp atış hızı monitörümüz için sürekli değişen değerlere sahibiz ve mevcut değeri her saniye manuel olarak sorgulamak istemiyoruz.
characteristic.addEventListener( 'characteristicvaluechanged', e => { let r = e.target.value.getUint8(1); let g = e.target.value.getUint8(2); let b = e.target.value.getUint8(3); } ); characteristic.startNotifications();
Bir değer değiştiğinde bir geri arama almak için, characteristicvaluechanged
üzerinde addEventListener()
fonksiyonunu, featurevaluechanged parametresi ve bir geri çağırma fonksiyonu ile çağırmamız gerekir. Değer değiştiğinde, geri çağırma işlevi parametre olarak bir olay nesnesi ile çağrılacak ve olayın hedefinin değer özelliğinden verileri alabiliriz. Ve son olarak, bireysel baytları ArrayBuffer'ın DataView'ından tekrar çıkarın.
Bluetooth ağındaki bant genişliği sınırlı olduğu için, özellik üzerinde startNotifications()
çağırarak bu bildirim mekanizmasını manuel olarak başlatmamız gerekiyor. Aksi takdirde, ağ gereksiz verilerle dolup taşacaktır. Ayrıca, bu cihazlar tipik olarak bir pil kullandığından, göndermemiz gerekmeyen her bir bayt, dahili radyonun sık sık açılması gerekmediğinden, cihazın pil ömrünü kesin olarak artıracaktır.
Çözüm
Artık WebBluetooth API'sinin %90'ını aştık. Sadece birkaç işlev çağrısı ve 4 bayt göndererek, ampullerinizin renklerini kontrol eden bir web uygulaması oluşturabilirsiniz. Birkaç satır daha eklerseniz, bir oyuncak arabayı kontrol edebilir veya drone uçurabilirsiniz. Gittikçe daha fazla Bluetooth cihazının piyasaya çıkmasıyla, olasılıklar sonsuzdur.
Diğer Kaynaklar
- Bluetooth.rocks! Demolar | (GitHub'daki kaynak kodu)
- “Web Bluetooth Spesifikasyonu”, Web Bluetooth Topluluk Grubu
- GATT Kayıt Defterini Açın Bluetooth Düşük Enerji cihazları için Genel Öznitelik hizmetleri için resmi olmayan bir belge koleksiyonu.