1. Giriş
Son Güncelleme Tarihi: 21.07.2020
Oluşturacaklarınız
Bu codelab'de, BBC micro:bit panosuyla etkileşimde bulunmak için Web Serial API'yi kullanan bir web sayfası oluşturacaksınız. Bu kart, görüntüleri 5x5 LED matrisinde gösterir. Web Serial API hakkında bilgi edinecek ve seri cihazlarla tarayıcı üzerinden iletişim kurmak için okunabilir, yazılabilir ve dönüştürme akışlarının nasıl kullanılacağını öğreneceksiniz.
Neler öğreneceksiniz?
- Web Seri bağlantı noktası nasıl açılır ve kapatılır?
- Giriş akışındaki verileri işlemek için okuma döngüsü kullanma
- Yazma akışı üzerinden veri gönderme
Gerekenler
- En son Espruino donanım yazılımına sahip bir BBC micro:bit kartı
- Chrome'un yeni bir sürümü (80 veya sonraki sürüm)
- HTML, CSS, JavaScript ve Chrome Geliştirici Araçları hakkında bilgi
Bu codelab'in uygun maliyetli olması, birkaç giriş (düğme) ve çıkışı (5x5 LED ekran) sunması, ek giriş ve çıkışlara imkan vermesi nedeniyle bu codelab için micro:bit kullanmayı tercih ettik. micro:bit'in yapabildiği şeylerle ilgili ayrıntılar için Espruino sitesindeki BBC micro:bit sayfasına bakın.
2. Web Serial API hakkında
Web Serial API, web sitelerinin komut dosyalarıyla bir seri cihazda okuma ve yazma işlemleri yapması 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 ile fiziksel dünya arasında köprü kurar.
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üklenen bir yerel aracı uygulaması aracılığıyla cihazla iletişim kurar. Bazı durumlarda ise uygulama, Electron gibi bir çerçeve üzerinden paketlenmiş yerel bir uygulamada teslim edilir. Diğer durumlarda, kullanıcının derlenmiş bir uygulamayı bir USB flash sürücüyle cihaza kopyalamak gibi ek bir işlem yapması gerekir.
Site ile kontrol ettiği cihaz arasında doğrudan iletişim sağlanarak kullanıcı deneyimi iyileştirilebilir.
3. Kurulum
Kodu alma
Bu codelab'de 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üzü oluşturmak için Remiks Glitch bağlantısını tıklayın.
- Göster düğmesini tıklayın ve ardından kodunuzu çalışırken görmek için Yeni Pencerede'yi seçin.
4. Seri bağlantıyı açma
Web Serial API'nin desteklenip desteklenmediğini kontrol etme
İlk olarak, Web Serial API'nin mevcut tarayıcıda desteklenip desteklenmediğini kontrol edin. Bunun için serial
adlı kullanıcının navigator
grubunda olup olmadığını kontrol edin.
DOMContentLoaded
etkinliğinde projenize aşağıdaki kodu ekleyin:
script.js - DOMContentLoaded
// CODELAB: Add feature detection here.
const notSupported = document.getElementById('notSupported');
notSupported.classList.toggle('hidden', 'serial' in navigator);
Bu işlem, Web Serisinin desteklenip desteklenmediğini kontrol eder. Reklam gösteriliyorsa bu kod, Web Serial'ın desteklenmediğini belirten banner'ı gizler.
Deneyin
- Sayfayı yükleyin.
- Sayfada, Web Serisinin desteklenmediğini belirten kırmızı bir banner görüntülenmediğinden emin olun.
Seri bağlantı noktasını açma
Ardından, seri bağlantı noktasını açmamız gerekir. Diğer modern API'lerin çoğu gibi Web Serial API de eşzamansızdır. Bu, giriş beklerken kullanıcı arayüzünün engelleme yapmasını önler, ancak seri verileri web sayfası tarafından herhangi bir zamanda alınabileceğinden ve bu verileri dinlemek için bir yönteme ihtiyacımız olduğundan bu önemli bir noktadır.
Bir bilgisayarda birden fazla seri cihaz olabileceğinden, tarayıcı bir bağlantı noktası isteğinde bulunmaya çalıştığında kullanıcıdan hangi cihaza bağlanacağını seçmesini ister.
Projenize şu 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ıdan hangi cihaza bağlanmak istediğini ister. port.open
arandığında bağlantı noktası açılır. Ayrıca, seri cihazla iletişim kurmak istediğimiz hızı da sağlamamız gerekir. BBC micro:bit, USB-seri çipi ile ana işlemci arasında 9600 baud bağlantısı kullanır.
Ayrıca, Bağlan düğmesini de bağlayıp kullanıcı tıkladığında connect()
komutunu çağıralım.
Projenize şu kodu ekleyin:
script.js - clickConnect()
// CODELAB: Add connect code here.
await connect();
Deneyin
Projemiz, başlangıç yapmak için artık minimum düzeyde. Bağlan düğmesi tıklandığında kullanıcıdan bağlanacağı seri cihazı seçmesi istenir, ardından micro:bit'e bağlanı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ını seçin ve Bağlan'ı tıklayın.
- Sekmede, bir seri cihaza bağlı olduğunuzu belirten bir simge görürsünüz:
Seri bağlantı noktasından veri dinlemek için giriş akışı ayarlama
Bağlantı kurulduktan sonra, cihazdaki verileri okuyacak bir giriş akışı ve okuyucu ayarlamamız gerekir. Öncelikle port.readable
işlevini çağırarak bağlantı noktasından okunabilir akışı alacağız. Cihazdaki metni geri alacağımızı bildiğimizden, bunu bir metin kod çözücüden faydalanacağız. Sonra, bir okuyucu alıp okuma döngüsünü başlatacağız.
Projenize şu 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ü, döngü içinde çalışan ve ana iş parçacığını engellemeden içeriği bekleyen eşzamansız bir işlevdir. Yeni veri geldiğinde okuyucu iki özellik döndürür: value
ve done
boole. done
true ise, bağlantı noktası kapatılmıştır veya başka veri gelmemektedir.
Projenize şu 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 veriler günlük öğesine eklenir.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda, BBC micro:bit cihazını seçin ve Bağlan'ı tıklayın.
- Espruino logosunu görürsünüz:
Seri bağlantı noktasına veri göndermek için çıkış akışı oluşturma
Seri iletişim genellikle iki yönlüdür. Seri bağlantı noktasından veri almaya ek olarak, bağlantı noktasına veri göndermek de istiyoruz. Giriş akışında olduğu gibi yalnızca çıkış akışı üzerinden micro:bit'e metin göndereceğiz.
Önce metin kodlayıcı akışı oluşturun ve akışı port.writeable
öğesine bağlayı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;
Espruino donanım yazılımıyla seri bağlantıyla BBC micro:bit kartı, Node.js kabuğunda bulunana benzer şekilde JavaScript okuma-eval-yazdırma döngüsü (REPL) görevi görür. Ardından, akışa veri göndermek için bir yöntem sağlamamız gerekir. Aşağıdaki kod, çıkış akışından bir yazar alır ve ardından her satırı göndermek için write
öğesini kullanır. Gönderilen her satır, micro:bit'e gönderilen komutu değerlendirmesini bildirmek için bir yeni 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 karakterlerin tekrarlanmasını durdurmak için CTRL-C tuşlarına basarak 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'ten veri gönderip alabilir. Düzgün bir şekilde komut gönderebildiğimizi doğrulayalım:
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda, BBC micro:bit cihazını seçin ve Bağlan'ı tıklayın.
- Chrome Geliştirici Araçları'nda Konsol sekmesini açıp
writeToStream('console.log("yes")');
yazın
Sayfada şuna benzer bir şey görürsünüz:
5. LED matrisini kontrol etme
Matris ızgara dizesini oluşturma
micro:bit üzerindeki LED matrisini kontrol etmek için show()
çağrısını yapmamız gerekir. Bu yöntem, yerleşik 5x5 LED ekranda grafikler gösterir. Bu, ikilik sayı veya bir dize alır.
Onay kutularını tekrar tekrar kullanarak, hangisinin işaretli olduğunu, hangilerinin işaretlenmediğini gösteren bir 1 ve 0 dizisi oluşturacağız. Onay kutularının sırası matristeki LED'lerin sırasının tersi olduğundan diziyi tersine çevirmemiz gerekir. Ardından, diziyi bir dizeye dönüştürüp micro:bit'e gönderilecek 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şaretleyin
Ardından, onay kutularındaki değişiklikleri dinlememiz ve bu değişikliklerin olması durumunda bu bilgiyi micro:bit'e göndermemiz gerekir. Özellik algılama koduna (// CODELAB: Add feature detection here.
) aşağıdaki satırı ekleyin:
script.js - DOMContentLoaded
initCheckboxes();
Ayrıca, micro:bit ilk bağlandığında ızgarayı sıfırlayalım, böylece mutlu bir yüz gösterebiliriz. drawGrid()
işlevi zaten sağlanmış. Bu işlev, sendGrid()
işlevine benzer şekilde çalışır; 1'ler ve 0'lardan oluşan bir dizi alır ve onay kutularını uygun şekilde işaretler.
script.js - clickConnect()
// CODELAB: Reset the grid on connect here.
drawGrid(GRID_HAPPY);
sendGrid();
Deneyin
Sayfa artık micro:bit ile bir bağlantı açtığında mutlu bir yüz gönderir. Onay kutuları tıklandığında, LED matrisindeki 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ını seçin ve Bağlan'ı tıklayın.
- micro:bit LED matrisinde bir gülümseme göreceksiniz.
- Onay kutularını değiştirerek LED matrisinde farklı bir desen çizin.
6. micro:bit düğmelerini kullanmaya başlayın
micro:bit düğmelerine izleme etkinliği ekleme
micro:bit üzerinde, LED matrisinin her iki tarafında bir düğme olmak üzere iki düğme bulunur. Espruino, düğmeye basıldığında etkinlik/geri çağırma gönderen bir setWatch
işlevi sağlar. Her iki düğmeyi de dinlemek istediğimiz için işlevimizi genel hale getirecek ve etkinliğin 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);
Ardından, seri bağlantı noktası cihaza her bağlandığında iki düğmeyi de (mikro:bit kartında BTN1 ve BTN2 olarak adlandırılır) bağlamamız gerekir.
script.js - clickConnect()
// CODELAB: Initialize micro:bit buttons.
watchButton('BTN1');
watchButton('BTN2');
Deneyin
Bağlantı kurulduğunda mutlu bir yüz göstermenin yanı sıra, micro:bit üzerindeki düğmelerden birine bastığınızda sayfaya hangi düğmeye basıldığını belirten bir metin eklenir. Büyük olasılıkla, her karakter kendi satırında yer alı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ını seçin ve Bağlan'ı tıklayın.
- micro:bits LED matrisinde bir gülümseme göreceksiniz.
- micro:bit'teki düğmelere basın ve düğmenin ayrıntıları basılarak sayfaya yeni metin eklendiğini doğrulayın.
7. Gelen verileri ayrıştırmak için dönüşüm akışı kullanma
Temel akış işleme
micro:bit düğmelerinden birine basıldığında, micro:bit, verileri seri bağlantı noktasına bir akış üzerinden gönderir. Akışlar çok faydalıdır ancak aynı zamanda tüm verilere aynı anda erişemeyeceğiniz ve rastgele parçalanabilir. Bu nedenle, akışlar çok faydalı olabilir.
Uygulama şu anda gelen akışı geldiğinde (readLoop
) yazdırıyor. Çoğu durumda, her karakter kendi satırındadır, ancak bu pek faydalı değildir. İdeal olarak, akışın ayrı satırlara ayrıştırılması ve her mesaj kendi satırı olarak gösterilmesi gerekir.
TransformStream
ile akışları dönüştürme
Bunu yapmak için gelen akışın ayrıştırılmasını ve ayrıştırılmış verilerin döndürülmesini sağlayan bir dönüştürme akışı ( TransformStream
) kullanabiliriz. Dönüşüm akışı, akış kaynağı (bu örnekte micro:bit) ile akışı tüketen her şey (bu örnekte readLoop
) arasında yer alabilir ve son olarak tüketilmeden önce rastgele bir dönüşüm uygulayabilir. Bunu bir montaj hattı gibi düşünebilirsiniz: Bir widget'ın ilerisinde olduğunda, satırdaki her adım widget'ı değiştirir. Böylece, son hedefine vardığında widget tam olarak çalışır hale gelir.
Daha fazla bilgi için MDN's Streams API kavramları bölümüne bakın.
LineBreakTransformer
ile akışı dönüştürün
Akışı alıp satır sonlarına (\r\n
) göre parçalayacak bir LineBreakTransformer
sınıfı oluşturalım. Sınıf için transform
ve flush
olmak üzere iki yöntem gerekli. transform
yöntemi, akış tarafından her yeni veri alındığında çağrılır. Verileri sıraya alabilir veya daha sonra kullanmak üzere kaydedebilir. flush
yöntemi, akış kapatıldığında çağrılır ve henüz işlenmemiş tüm verileri işler.
transform
yöntemimizde, container
öğesine yeni veriler ekleyeceğiz ve ardından container
içinde satır sonu olup olmadığını kontrol edeceğiz. Varsa diziye bölün ve satırlar boyunca yinelenir. Ayrıştırılmış satırları göndermek için controller.enqueue()
çağrısı yapı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, kapsayıcıda kalan tüm verileri enqueue
kullanarak temizleyeceğiz.
script.js - LineBreakTransformer.flush()
// CODELAB: Flush the stream.
controller.enqueue(this.container);
Son olarak, gelen akışı yeni LineBreakTransformer
üzerinden yönlendirmemiz gerekir. Orijinal giriş akışımız yalnızca bir TextDecoderStream
aracılığıyla sağlanır. Bu nedenle, yeni LineBreakTransformer
ile aktarması için ek 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
Artık micro:bit düğmelerinden birine bastığınızda, yazdırılan veriler tek bir satırda döndürülecektir.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda, BBC micro:bit cihazını seçin ve Bağlan'ı tıklayın.
- micro:bit LED matrisinde bir gülümseme göreceksiniz.
- micro:bit'teki düğmelere basın ve aşağıdakine benzer bir sonuç aldığınızı doğrulayın:
JSONTransformer
ile akışı dönüştürün
Dizeyi readLoop
içinde JSON biçimine 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şturalım. Veriler geçerli JSON değilse yalnızca 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
üzerinden geçtikten sonra JSONTransformer
üzerinden akışı yönlendirin. JSON dosyasının her zaman yalnızca tek bir satırda gönderileceğini bildiğimizden bu yöntem, JSONTransformer
dosyamızı basit tutmamızı sağlar.
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]
basılı olduğunu görürsünüz.
- Sayfayı tekrar yükleyin.
- Bağlan düğmesini tıklayın.
- Seri Bağlantı Noktası seçici iletişim kutusunda, BBC micro:bit cihazını seçin ve Bağlan'ı tıklayın.
- micro:bit LED matrisinde bir gülümseme göreceksiniz.
- micro:bit'teki düğmelere basın ve aşağıdakine benzer bir sonuç aldığınızı doğrulayın:
Düğmelere basıldığında yanıt verme
micro:bit düğmesi basmalarına yanıt vermek için readLoop
uygulamasını, aldığı verilerin button
özelliğine sahip bir object
olup olmadığını kontrol edecek şekilde güncelleyin. Ardından, düğmeye basma işlemini gerçekleştirmek için buttonPushed
öğesini çağırın.
script.js - readLoop()
const { value, done } = await reader.read();
if (value && value.button) {
buttonPushed(value);
} else {
log.textContent += value + '\n';
}
Bir micro:bit düğmesine basıldığında, LED matristeki 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
Şimdi, micro:bit düğmelerinden birine bastığınızda LED matrisiniz mutlu veya üzgün bir yüze dönüşü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ını seçin ve Bağlan'ı tıklayın.
- micro:bits LED matrisinde bir gülümseme göreceksiniz.
- Mikro:bit üzerindeki düğmelere basın ve LED matrisinin değiştiğini doğrulayın.
8. Seri bağlantı noktasını kapatma
Son adım, kullanıcı işi bittiğinde bağlantı noktasını kapatmak için bağlantı kaldırma işlevini bağlamaktır.
Kullanıcı Bağlan/Bağlantıyı Kes düğmesini tıkladığında bağlantı noktasını kapat
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()
yöntemini çağırın ve sayfanın artık seri cihaza bağlı olmadığını belirtmek için 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()
komutunu çağırın. cancel
çağrısı eşzamansız olduğundan, bu çağrının tamamlanmasını beklemek için await
çağrısını kullanmamız gerekir:
script.js - disconnect()
// CODELAB: Close the input stream (reader).
if (reader) {
await reader.cancel();
await inputDone.catch(() => {});
reader = null;
inputDone = null;
}
Çıkış akışını kapatmak için bir writer
alın, close()
yöntemini çağırın ve outputDone
nesnesinin kapatılması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ı dilediğ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ını seçin ve Bağlan'ı tıklayın.
- micro:bit LED matrisinde bir gülümseme göreceksiniz
- Bağlantıyı kes düğmesine basıp LED matrisinin kapandığını ve konsolda herhangi bir hata olmadığını doğrulayın.
9. Tebrikler
Tebrikler! Web Serial API'yi kullanan ilk web uygulamanızı başarıyla derlediniz.
Web Serial API ile ilgili son gelişmeler ve Chrome ekibinin üzerinde çalıştığı diğer heyecan verici yeni web özellikleri için https://goo.gle/fugu-api-tracker adresine göz atın.