Web Serial API'yi kullanmaya başlama

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

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.

  1. Yeni bir tarayıcı sekmesi açın ve https://web-serial-codelab-start.glitch.me/ adresine gidin.
  2. Başlangıç projesinin kendi sürümünü oluşturmak için Remix Glitch bağlantısını tıklayın.
  3. 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

  1. Sayfayı yükleyin.
  2. 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.

  1. Sayfayı tekrar yükleyin.
  2. Bağlan düğmesini tıklayın.
  3. Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
  4. 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.

  1. Sayfayı tekrar yükleyin.
  2. Bağlan düğmesini tıklayın.
  3. Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
  4. 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:

  1. Sayfayı tekrar yükleyin.
  2. Bağlan düğmesini tıklayın.
  3. Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
  4. 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.

  1. Sayfayı tekrar yükleyin.
  2. Bağlan düğmesini tıklayın.
  3. Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
  4. Mikro:bit LED matrisi gösteren bir gülümseme göreceksiniz.
  5. 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.

  1. Sayfayı tekrar yükleyin.
  2. Bağlan düğmesini tıklayın.
  3. Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
  4. Mikro:bit bit matriste bir gülümseme gösteriliyor.
  5. 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.

  1. Sayfayı tekrar yükleyin.
  2. Bağlan düğmesini tıklayın.
  3. Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
  4. Mikro:bit LED matrisi gösteren bir gülümseme göreceksiniz.
  5. 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.

  1. Sayfayı tekrar yükleyin.
  2. Bağlan düğmesini tıklayın.
  3. Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
  4. Mikro:bit LED matrisi gösteren bir gülümseme göreceksiniz.
  5. 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.

  1. Sayfayı tekrar yükleyin.
  2. Bağlan düğmesini tıklayın.
  3. Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
  4. Mikro:bit bit matriste bir gülümseme gösteriliyor.
  5. 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.

  1. Sayfayı tekrar yükleyin.
  2. Bağlan düğmesini tıklayın.
  3. Seri Bağlantı Noktası seçici iletişim kutusunda BBC micro:bit cihazı seçip Bağlan'ı tıklayın.
  4. Mikro:bit LED matriste bir gülümseme göreceksiniz
  5. 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.