Son Güncelleme: 08.11.2019
Geliştireceğiniz uygulama
Bu codelab'de, resimleri 5x5 LED matrisi üzerinde göstermek için BBC micro:bit panosuyla etkileşimde bulunmak üzere Web Serial API'yi kullanan bir web sayfası oluşturacaksınız. Web Serial API hakkında bilgi edinecek ve tarayıcı aracılığıyla seri cihazlarla iletişim kurmak için okunabilir, yazılabilir ve dönüştürme akışlarını nasıl kullanacağınızı öğreneceksiniz.
Neler öğreneceksiniz?
- Web Seri Bağlantı Noktası'nı açma ve kapatma
- Giriş akışındaki verileri işlemek için okuma döngüsünü kullanma
- Veri akışı yazma yoluyla nasıl gönderilir?
Gerekenler
- En son Espruino donanım yazılımına sahip bir BBC micro:bit panosu
- Chrome'un yeni bir sürümü (78 veya sonraki sürümler)
- HTML, CSS, JavaScript ve Chrome Geliştirici Araçları hakkında bilgi
Bu codelab'de uygun fiyatlı olduğu için micro:bit kullanmayı tercih ettik. Bunun için birkaç giriş (düğme) ve çıkış (5x5 LED ekran) sunmalı ve ek giriş ve çıkış sağlamanız gerekiyor. Mikro:bit'in yapabilecekleriyle ilgili ayrıntılar için Espruino sitesindeki BBC micro:bit sayfasına bakın.
Web Serial API, web sitelerinin komut dosyaları içeren seri bir cihazdan okuması ve yazması için bir yol sağlar. API, web sitelerinin mikrodenetleyiciler ve 3D yazıcılar gibi seri cihazlarla iletişim kurmasına olanak tanıyarak web'i ve fiziksel dünyayı birbirine bağlar.
Web teknolojisi kullanılarak oluşturulan kontrol yazılımlarına birçok örnek verilebilir. Örneğin:
Bazı durumlarda bu web siteleri, kullanıcı tarafından manuel olarak yüklenmiş bir yerel aracı uygulaması üzerinden cihazla iletişim kurar. Diğer durumlarda uygulama, Electron gibi bir çerçeveyle paketlenmiş bir yerel uygulamada yayınlanır. Diğer durumlarda, kullanıcının derlenmiş bir uygulamayı USB flash sürücüyle cihaza kopyalama gibi ek bir adım gerçekleştirmesi gerekir.
Site ve kontrol ettiği cihaz arasında doğrudan iletişim sağlanarak kullanıcı deneyimi iyileştirilebilir.
Web Serial API'yi etkinleştir
Web Serial API şu anda geliştirme aşamasındadır ve yalnızca bayrakla kullanılabilir. chrome://flags
içinde #enable-experimental-web-platform-features
flag'ini etkinleştirmeniz gerekir.
Kodu alın
Bu codelab için ihtiyacınız olan her şeyi bir Glitch projesine yerleştirdik.
- Yeni bir tarayıcı sekmesi açın ve https://web-serial-codelab-start.glitch.me/ adresine gidin.
- Başlangıç projesinin kendi sürümünü oluşturmak için Remix Glitch bağlantısını tıklayın.
- Kodunuzu göstermek için Göster düğmesini tıklayın ve ardından Yeni Pencerede'yi seçin.
Web Serial API'nin desteklenip desteklenmediğini kontrol etme
Yapmanız gereken ilk şey Web Serial API'nin mevcut tarayıcıda desteklenip desteklenmediğini kontrol etmektir. Bunu yapmak için serial
uygulamasının navigator
bölgesinde olup olmadığını kontrol edin.
DOMContentLoaded
etkinliğinde, projenize aşağıdaki kodu ekleyin:
script.js - DOMContentLoaded
// CODELAB: Add feature detection here.
if ('serial' in navigator) {
const notSupported = document.getElementById('notSupported');
notSupported.classList.add('hidden');
}
Bu işlem, Web Serisi'nin desteklenip desteklenmediğini kontrol eder. Öyleyse bu kod, Web Seri Numarası'nın desteklenmediğini belirten banner'ı gizler.
Deneyin
- Sayfayı yükleyin.
- Sayfada, Web Seri Numarası'nın desteklenmediğini belirten kırmızı bir banner göstermediğini doğrulayın.
Seri bağlantı noktasını açın
Ardından, seri bağlantı noktasını açmamız gerekiyor. Diğer çoğu modern API'de olduğu gibi Web Serial API de eşzamansızdır. Bu, giriş beklenirken kullanıcı arayüzünün engellenmesini engeller ancak web sayfaları da seri verileri herhangi bir zamanda alabileceğinden bu verileri dinlemek için bir yönteme ihtiyaç duymamız önem taşır.
Bir bilgisayarda birden fazla seri cihazı olabileceğinden, tarayıcı bağlantı noktası istemeye çalıştığında kullanıcıdan hangi cihaza bağlanacağını seçmesini ister.
Projenize aşağıdaki kodu ekleyin:
script.js - connect()
// CODELAB: Add code to request & open port here.
// - Request a port and open a connection.
port = await navigator.serial.requestPort();
// - Wait for the port to open.
await port.open({ baudrate: 9600 });
requestPort
araması, kullanıcıya hangi cihaza bağlanmak istediğini sorar. port.open
araması, bağlantı noktasını açar. Ayrıca, seri cihazla iletişim kurmak için ihtiyaç duyduğumuz hızı da sağlamamız gerekmektedir. BBC micro:bit, USB-seri-çip ile ana işlemci arasında 9.600 baud bağlantısı kullanır.
Ayrıca, bağlan düğmesini bağlayalım ve kullanıcı tıkladığında düğmeyi connect()
çağırsın.
Projenize aşağıdaki kodu ekleyin:
script.js - clickConnect()
// CODELAB: Add connect code here.
await connect();
Deneyin
Projemizde artık başlangıç için gereken minimum veri yok. Bağlan düğmesini tıklamak, kullanıcıdan bağlanacağı seri cihazı seçmesini ve ardından micro:bit'e bağlanmasını ister.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
- Sekmede bir seri cihaza bağlandığınızı belirten bir simge görürsünüz:
Seri bağlantı noktasından gelen verileri dinlemek için giriş akışı ayarlayın
Bağlantı kurulduktan sonra cihazdaki verileri okumak için bir giriş akışı ve okuyucu ayarlamamız gerekir. Öncelikle port.readable
numaralı telefonu arayarak bağlantı noktasındaki okunabilir akışa ulaşacağız. Cihazdan metin alacağımızı bildiğimiz için bu özelliği bir metin kod çözücüden izleyeceğiz. Şimdi, bir okuyucu bulup okuma döngüsünü başlatacağız.
Projenize aşağıdaki kodu ekleyin:
script.js - connect()
// CODELAB: Add code to read the stream here.
let decoder = new TextDecoderStream();
inputDone = port.readable.pipeTo(decoder.writable);
inputStream = decoder.readable;
reader = inputStream.getReader();
readLoop();
Okuma döngüsü, bir döngüde çalıştırılan ve ana iş parçacığını engellemeden içerik bekleyen eşzamansız bir işlevdir. Yeni veriler geldiğinde okuyucu iki özellik döndürür: value
ve done
boole değeri. done
doğruysa bağlantı noktası kapalıdır veya gelen başka veri yoktur.
Projenize aşağıdaki kodu ekleyin:
script.js - readLoop()
// CODELAB: Add read loop here.
while (true) {
const { value, done } = await reader.read();
if (value) {
log.textContent += value + '\n';
}
if (done) {
console.log('[readLoop] DONE', done);
reader.releaseLock();
break;
}
}
Deneyin
Projemiz artık cihaza bağlanabilir ve cihazdan alınan tüm verileri günlük öğesine ekler.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
- Espruino logosunu görmeniz gerekir:
Seri bağlantı noktasına veri göndermek için çıkış akışı oluşturma
Seri iletişim genellikle çift yönlüdür. Seri bağlantı noktasından veri almaya ek olarak, bağlantı noktasına da veri göndermek istiyoruz. Giriş akışında olduğu gibi, çıkış akışı üzerinden yalnızca micro:bit üzerinden metin göndereceğiz.
Önce, bir metin kodlayıcı akışı oluşturun ve akışı port.writeable
kanalına aktarın.
script.js - connect()
// CODELAB: Add code setup the output stream here.
const encoder = new TextEncoderStream();
outputDone = encoder.readable.pipeTo(port.writable);
outputStream = encoder.writable;
BBC micro:bit tahtası, seri üzerinden Espruino donanım yazılımına bağlandığında Node.js kabuğunda aldığınıza benzer JavaScript eval-printcycle (REPL) işlevi görür. Ardından, akışa veri göndermek için bir yöntem sunmamız gerekir. Aşağıdaki kod, çıkış akışında bir yazar alır ve her satırı göndermek için write
kodunu kullanır. Gönderilen her satır, micro:bit'e gönderilen komutu değerlendirmek için yeni bir satır karakteri (\n
) içerir.
script.js - writeToStream()
// CODELAB: Write to output stream
const writer = outputStream.getWriter();
lines.forEach((line) => {
console.log('[SEND]', line);
writer.write(line + '\n');
});
writer.releaseLock();
Sistemi bilinen bir duruma getirmek ve gönderdiğimiz karakterleri tekrar çalmasını önlemek için CTRL-C tuşlarına basıp yankıyı kapatmamız gerekir.
script.js - connect()
// CODELAB: Send CTRL-C and turn off echo on REPL
writeToStream('\x03', 'echo(false);');
Deneyin
Projemiz artık micro:bit üzerinden veri gönderip alabilir. Komutları düzgün bir şekilde gönderebildiğimizi doğrulayın:
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
- Chrome Geliştirici Araçları'ndaki Konsol sekmesini açın ve
writeToStream('console.log("yes")');
yazın.
Sayfada basılı olarak aşağıdakine benzer bilgiler görmeniz gerekir:
matris ızgara dizesini oluşturma
Mikro:bit'teki LED matrisini kontrol etmek için show()
işlevini çağırmamız gerekir. Bu yöntem, yerleşik 5x5 LED ekranda grafikler gösterir. Bu, ikili sayı veya bir dize alır.
Onay kutularını tekrarlayıp hangisinin tıklanıp hangilerinin işaretlenmediğini belirten 1 ve 0'lık diziler oluşturuyoruz. Daha sonra diziyi tersine çevirmemiz gerekir. Çünkü onay kutularımızın sıralaması, matristeki LED'lerin sırasının tam tersidir. Ardından, diziyi dizeye dönüştürür ve micro:bit'e göndermek için komutu oluştururuz.
script.js - sendGrid()
// CODELAB: Generate the grid
const arr = [];
ledCBs.forEach((cb) => {
arr.push(cb.checked === true ? 1 : 0);
});
writeToStream(`show(0b${arr.reverse().join('')})`);
matrisi güncellemek için onay kutularını işaretleme
Ardından, onay kutularındaki değişiklikleri dinlememiz ve değişiklik olması halinde bu bilgileri micro:bit adresine göndermemiz gerekiyor. Özellik algılama kodunda (// CODELAB: Add feature detection here.
) aşağıdaki satırı ekleyin:
script.js - DOMContentLoaded
initCheckboxes();
Mikro:bit ilk kez bağlandığında ızgarayı sıfırlayalım, böylece mutlu bir yüz gösterin. drawGrid()
işlevi zaten sağlanmış. Bu işlev sendGrid()
işlevine benzer bir şekilde çalışır; 1 ve 0'lardan oluşan bir dizi alır ve onay kutularını gerektiği şekilde kontrol eder.
script.js - clickConnect()
// CODELAB: Reset the grid on connect here.
drawGrid(GRID_HAPPY);
sendGrid();
Deneyin
Artık sayfa micro:bit bağlantısını açtığında mutlu bir yüz gönderecektir. Onay kutuları tıklandığında, LED matristeki ekran güncellenir.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
- Mikro:bit LED matrisi gösteren bir gülümseme göreceksiniz.
- Onay kutularını değiştirerek LED matrisine farklı bir desen çizin.
Mikro veri bit düğmelerine izleme etkinliği ekleme
Mikro:bit üzerinde, biri matrisin iki tarafında olan iki düğme vardır. Espruino, düğmeye basıldığında etkinlik/geri arama gönderen bir setWatch
işlevi sağlar. Her iki düğmeyi de dinlemek istediğimiz için işlevimizi genel yapıp etkinlik ayrıntılarını yazdırmasını sağlayacağız.
script.js - watchButton()
// CODELAB: Hook up the micro:bit buttons to print a string.
const cmd = `
setWatch(function(e) {
print('{"button": "${btnId}", "pressed": ' + e.state + '}');
}, ${btnId}, {repeat:true, debounce:20, edge:"both"});
`;
writeToStream(cmd);
Şimdi, seri bağlantı noktası cihaza her bağlandığında iki düğmeyi de (micro:bit tahtada BTN1 ve BTN2 adı) bağlamamız gerekiyor.
script.js - clickConnect()
// CODELAB: Initialize micro:bit buttons.
watchButton('BTN1');
watchButton('BTN2');
Deneyin
Bağlanıldığında mutlu bir yüz göstermenin yanı sıra micro:bit üzerindeki düğmelerden birine bastığınızda sayfaya hangi düğmenin basıldığına dair bir metin eklenir. Büyük olasılıkla her karakter kendi satırında olacaktır.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
- Mikro:bit bit matriste bir gülümseme gösteriliyor.
- Mikro:bit'teki düğmelere basın ve sayfaya, düğme ayrıntılarına basılarak yeni metin eklendiğini doğrulayın.
Temel akış işleme
Mikro:bit düğmelerinden biri aktarıldığında mikro:bit, verileri akış yoluyla seri bağlantı noktasına gönderir. Akışlar çok kullanışlı olsa da tüm verileri aynı anda almanız gerekmediği için rastgele bir zorluk da oluşabilir.
Uygulama, şu anda gelen akışı readLoop
içinde yazdırıyor. Çoğu durumda, her karakter kendi satırındadır, ancak bu çok kullanışlı değildir. İdeal olarak akış, ayrı satırlar halinde ayrıştırılmalıdır ve her mesaj kendi satırı olarak gösterilmelidir.
TransformStream
ile akışları dönüştürme
Bunun için, gelen akışı ayrıştırmanızı ve ayrıştırılan verileri döndürmenizi sağlayan bir dönüştürme akışı (TransformStream
) kullanabiliriz. Dönüşüm akışı, akış kaynağı (bu örnekte micro:bit) ile akışı tüketen şey (bu örnekte readLoop
) arasında yer alabilir ve nihai olarak tüketilmeden önce rastgele bir dönüşüm uygulayabilir. Bunu bir montaj hattı gibi düşünün: Widget'ın çizgiden aşağı inmesi durumunda, çizgideki her adım widget'ı değiştirir. Böylece, son hedefine ulaştığında widget tam olarak çalışır durumda bir widget olur.
Daha fazla bilgi için MDN's Streams API kavramları başlıklı makaleyi inceleyin.
Akışı LineBreakTransformer
ile dönüştürme
LineBreakTransformer
adlı bir sınıf oluşturalım. Bu ders, akışı alıp satır sonlarına (\r\n
) göre parçalara ayırır. Sınıfın iki yönteme ihtiyacı vardır: transform
ve flush
. Akış tarafından her yeni veri alındığında transform
yöntemi çağrılır. Verileri sıraya alabilir veya daha sonra kullanmak üzere kaydedebilir. Akış kapatıldığında flush
yöntemi çağrılır ve henüz işlenmemiş verileri işler.
transform
yöntemimizde, container
için yeni veriler ekler ve ardından container
içinde hiç satır sonu olup olmadığını kontrol ederiz. Varsa bir diziye bölün ve daha sonra, satırları ayrıştırarak ayrıştırılan satırları göndermek için controller.enqueue()
değerini çağırın.
script.js - LineBreakTransformer.transform()
// CODELAB: Handle incoming chunk
this.container += chunk;
const lines = this.container.split('\r\n');
this.container = lines.pop();
lines.forEach(line => controller.enqueue(line));
Akış kapatıldığında kalan tüm verileri enqueue
kullanarak tamamen temizleriz.
script.js - LineBreakTransformer.flush()
// CODELAB: Flush the stream.
controller.enqueue(this.container);
Son olarak, gelen akışı yeni LineBreakTransformer
aracılığıyla yönlendirmemiz gerekir. Orijinal giriş akışımız yalnızca TextDecoderStream
üzerinden aktarıldığından, yeni akışı LineBreakTransformer
eklemek için fazladan bir pipeThrough
eklememiz gerekiyor.
script.js - connect()
// CODELAB: Add code to read the stream here.
let decoder = new TextDecoderStream();
inputDone = port.readable.pipeTo(decoder.writable);
inputStream = decoder.readable
.pipeThrough(new TransformStream(new LineBreakTransformer()));
Deneyin
Mikro:bit düğmelerinden birine bastığınızda, yazdırılan verilerin tek bir satıra döndürülmesi gerekir.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
- Mikro:bit LED matrisi gösteren bir gülümseme göreceksiniz.
- Mikro:bit üzerindeki düğmelere basın ve aşağıdakine benzer bir şey gördüğünüzü doğrulayın:
Akışı JSONTransformer
ile dönüştürme
Dizeyi readLoop
içindeki JSON'da ayrıştırmayı deneyebiliriz. Ancak bunun yerine, verileri bir JSON nesnesine dönüştürecek çok basit bir JSON dönüştürücü oluştururuz. Veriler geçerli JSON biçiminde değilse gelen verileri döndürün.
script.js - JSONTransformer.transform
// CODELAB: Attempt to parse JSON content
try {
controller.enqueue(JSON.parse(chunk));
} catch (e) {
controller.enqueue(chunk);
}
Ardından, LineBreakTransformer
akışından geçtikten sonra akışı JSONTransformer
üzerinden geçirin. Bu, JSON'un yalnızca tek bir satırda gönderileceğini bildiğimiz için JSONTransformer
özelliğimizi basit tutmamıza olanak tanır.
script.js - connect
// CODELAB: Add code to read the stream here.
let decoder = new TextDecoderStream();
inputDone = port.readable.pipeTo(decoder.writable);
inputStream = decoder.readable
.pipeThrough(new TransformStream(new LineBreakTransformer()))
.pipeThrough(new TransformStream(new JSONTransformer()));
Deneyin
Artık micro:bit düğmelerinden birine bastığınızda sayfada [object Object]
olduğunu göreceksiniz.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
- Mikro:bit LED matrisi gösteren bir gülümseme göreceksiniz.
- Mikro:bit üzerindeki düğmelere basın ve aşağıdakine benzer bir şey gördüğünüzü doğrulayın:
Düğmeye basıldığında yanıt verme
Mikro:bit düğme basışlarına yanıt vermek için readLoop
sütununu, aldığı verilerin button
özelliğine sahip bir object
olup olmadığını kontrol edin. Ardından, düğme aktarımı için buttonPushed
numaralı telefonu arayın.
script.js - readLoop()
const { value, done } = await reader.read();
if (value && value.button) {
buttonPushed(value);
} else {
log.textContent += value + '\n';
}
Bir mikro mikrobit düğmesi aktarıldığında LED matrisindeki ekran değişmelidir. Matrisi ayarlamak için aşağıdaki kodu kullanın:
script.js - buttonPushed()
// CODELAB: micro:bit button press handler
if (butEvt.button === 'BTN1') {
divLeftBut.classList.toggle('pressed', butEvt.pressed);
if (butEvt.pressed) {
drawGrid(GRID_HAPPY);
sendGrid();
}
return;
}
if (butEvt.button === 'BTN2') {
divRightBut.classList.toggle('pressed', butEvt.pressed);
if (butEvt.pressed) {
drawGrid(GRID_SAD);
sendGrid();
}
}
Deneyin
Mikro:bit düğmelerinden birine bastığınızda LED matrisi, mutlu bir yüz veya üzgün bir yüz olarak değiştirilmelidir.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
- Mikro:bit bit matriste bir gülümseme gösteriliyor.
- Mikro:bit üzerindeki düğmelere basın ve LED matrisinin değiştiğini doğrulayın.
Son adım, kullanıcı bittiğinde bağlantı noktasını kapatmak için bağlantı kesme işlevini bağlamaktır.
Kullanıcı Bağlan/Bağlantıyı Kes düğmesini tıkladığında bağlantı noktasını kapatın
Kullanıcı Bağlan/Bağlantıyı kes düğmesini tıkladığında bağlantıyı kapatmamız gerekir. Bağlantı noktası zaten açıksa disconnect()
numaralı telefonu arayıp sayfanın artık seri cihaza bağlı olmadığını belirtecek şekilde kullanıcı arayüzünü güncelleyin.
script.js - clickConnect()
// CODELAB: Add disconnect code here.
if (port) {
await disconnect();
toggleUIConnected(false);
return;
}
Akışları ve bağlantı noktasını kapatma
disconnect
işlevinde giriş akışını, çıkış akışını ve bağlantı noktasını kapatmamız gerekir. Giriş akışını kapatmak için reader.cancel()
numaralı telefonu arayın. cancel
çağrısı eşzamansız olarak olduğundan, tamamlanmasını beklemek için await
kullanmamız gerekiyor:
script.js - disconnect()
// CODELAB: Close the input stream (reader).
if (reader) {
await reader.cancel();
await inputDone;
reader = null;
inputDone = null;
}
Çıkış akışını kapatmak için bir writer
alın, close()
çağrısı yapın ve outputDone
nesnesinin kapanmasını bekleyin:
script.js - disconnect()
// CODELAB: Close the output stream.
if (outputStream) {
await outputStream.getWriter().close();
await outputDone;
outputStream = null;
outputDone = null;
}
Son olarak, seri bağlantı noktasını kapatın ve kapanmasını bekleyin:
script.js - disconnect()
// CODELAB: Close the port.
await port.close();
port = null;
Deneyin
Artık seri bağlantı noktasını istediğiniz zaman açıp kapatabilirsiniz.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
- Mikro:bit LED matriste bir gülümseme göreceksiniz
- Bağlantıyı kes düğmesine basın ve LED matrisinin kapandığını ve konsolda herhangi bir hata olmadığını doğrulayın.
Tebrikler! Web Serial API kullanan ilk web uygulamanızı başarıyla oluşturdunuz.
Web Serial API'yle ilgili en son gelişmeleri ve Chrome ekibinin üzerinde çalıştığı diğer tüm yeni web özelliklerini öğrenmek için https://goo.gle/fugu-api-tracker web sitesine göz atın.