Web Serial API, web sitelerinin seri cihazlarla iletişim kurmasına olanak tanır.
Web Serial API nedir?
Seri bağlantı noktası, bir veri akışına izin veren iki yönlü aldığı anlamına gelir.
Web Serial API, web sitelerinin belirli bir sunucudan okuması ve bir sunucuya yazması için JavaScript yüklü seri cihazda. Seri cihazlar bir kullanıcının sistemindeki seri bağlantı noktası veya çıkarılabilir USB ve Bluetooth cihazlar üzerinden seri bağlantı noktası emüle eder.
Başka bir deyişle Web Serial API, web ile fiziksel dünya arasında Web sitelerinin mikrodenetleyiciler gibi seri cihazlarla iletişim kurmasına olanak tanır. 3D yazıcılardan oluşur.
İşletim sistemlerinin gerektirmesi nedeniyle bu API, WebUSB için de mükemmel bir tamamlayıcıdır. bazı seri bağlantı noktalarıyla iletişim kurmalarına olanak tanır. seri API'sını kullanabilirsiniz.
Önerilen kullanım alanları
Eğitim, hobi amaçlı ve endüstriyel sektörlerde kullanıcılar çevre birimlerini birbirine bağlar. kendi bilgisayarlarına aktarabilir. Bu cihazlar genellikle tarafından kullanılan seri bağlantıyla mikrodenetleyiciler üzerinde çalışır. Biraz özel web teknolojisiyle geliştirilmiştir:
Bazı durumlarda web siteleri bir aracı üzerinden cihazla iletişim kurar kullanıcıların manuel olarak yüklediği uygulamadır. Diğerlerinde ise uygulama Electron gibi bir çerçeve aracılığıyla paketlenmiş bir uygulamada teslim edilir. Bazı durumlarda ise kullanıcının derlenmiş bir uygulamayı, USB flash sürücü aracılığıyla cihaza kopyalama.
Tüm bu durumlarda, kullanıcı deneyimini iyileştirmek için doğrudan kontrol ettiği cihaz arasındaki iletişimi sağlar.
Mevcut durum
Step | Durum |
---|---|
1. Açıklayıcı oluşturun | Tamamlandı |
2. İlk spesifikasyon taslağını oluşturun | Tamamlandı |
3. Geri bildirim toplama tasarımı yineleyin | Tamamlandı |
4. Kaynak denemesi | Tamamlandı |
5. Başlat | Tamamlandı |
Web Serial API'yi kullanma
Özellik algılama
Web Serial API'nin desteklenip desteklenmediğini kontrol etmek için şunu kullanın:
if ("serial" in navigator) {
// The Web Serial API is supported.
}
Seri bağlantı noktasını açma
Web Serial API, tasarımı gereği eşzamansızdır. Bu işlem, web sitesinin kullanıcı arayüzünün Bu önemli bir noktadır, çünkü seri verileri çok sayıda dinlemenin bir yol olması gerekir.
Bir seri bağlantı noktasını açmak için önce bir SerialPort
nesnesine erişin. Bunun için
ya da telefon araması yaparak kullanıcıdan tek bir seri bağlantı noktası seçmesini
Dokunma gibi kullanıcı hareketlerine yanıt olarak navigator.serial.requestPort()
veya imleçle eşleşen navigator.serial.getPorts()
seçeneğinden birini seçin.
Web sitesinin erişmesine izin verilen seri bağlantı noktalarının listesi.
document.querySelector('button').addEventListener('click', async () => {
// Prompt user to select any serial port.
const port = await navigator.serial.requestPort();
});
// Get all serial ports the user has previously granted the website access to.
const ports = await navigator.serial.getPorts();
navigator.serial.requestPort()
işlevi, isteğe bağlı bir nesne değişmez değeri alır
bir filtre oluşturabilirsiniz. Bunlar, bağlı herhangi bir seri cihazı eşleştirmek için kullanılır
Zorunlu USB tedarikçisi (usbVendorId
) ve isteğe bağlı USB ürünü içeren USB
tanımlayıcılar (usbProductId
).
// Filter on devices with the Arduino Uno USB Vendor/Product IDs.
const filters = [
{ usbVendorId: 0x2341, usbProductId: 0x0043 },
{ usbVendorId: 0x2341, usbProductId: 0x0001 }
];
// Prompt user to select an Arduino Uno device.
const port = await navigator.serial.requestPort({ filters });
const { usbProductId, usbVendorId } = port.getInfo();
requestPort()
çağrısı yapıldığında kullanıcıdan cihaz seçmesi istenir ve
SerialPort
nesne algılandı. port.open()
çağrısı yapan bir SerialPort
nesneniz olduğunda
seri bağlantı noktası açılır. baudRate
sözlüğü
üye, verilerin bir seri hat üzerinden ne kadar hızlı gönderildiğini belirtir. Bu ifade
birimi (bit/sn) cinsinden girin. Cihazınızın dokümanlarında
doğru değere sahip. Bu durumda gönderdiğiniz ve aldığınız tüm veriler anlamsız olacaktır
yanlış belirtilmiş olabilir. Seri emülasyonu kullanan bazı USB ve Bluetooth cihazlarda
göz ardı edildiğinden, güvenli bir şekilde herhangi bir değere ayarlanabilir.
emülasyon.
// Prompt user to select any serial port.
const port = await navigator.serial.requestPort();
// Wait for the serial port to open.
await port.open({ baudRate: 9600 });
Ayrıca, bir seri bağlantı noktasını açarken aşağıdaki seçeneklerden herhangi birini de belirtebilirsiniz. Bu seçenekler isteğe bağlıdır ve uygun varsayılan değerlere sahiptir.
dataBits
: Kare başına veri biti sayısı (7 veya 8).stopBits
: Bir karenin sonundaki durak bitlerinin sayısı (1 ya da 2).parity
: Eşlik modu ("none"
,"even"
veya"odd"
).bufferSize
: Oluşturulması gereken okuma ve yazma arabelleklerinin boyutu (16 MB'tan küçük olmalıdır).flowControl
: Akış denetimi modu ("none"
veya"hardware"
).
Seri bağlantı noktasından okuma
Web Serial API'deki giriş ve çıkış akışları, Streams API tarafından işlenir.
Seri bağlantı noktası bağlantısı kurulduktan sonra readable
ve writable
SerialPort
nesnesindeki özellikler bir ReadableStream ve
WritableStream. Bunlar,
seri cihaz. Her ikisi de veri aktarımı için Uint8Array
örneklerini kullanır.
Seri cihazdan yeni veri geldiğinde, port.readable.getReader().read()
eşzamansız olarak iki özellik döndürür: value
ve done
boole. Eğer
done
doğru, seri bağlantı noktası kapatılmış veya gelen başka veri yok
inç port.readable.getReader()
çağrıldığında bir okuyucu oluşturulur ve readable
şuna kilitlenir:
somut olarak ortaya koyar. readable
kilitli durumdayken seri bağlantı noktası kapatılamaz.
const reader = port.readable.getReader();
// Listen to data coming from the serial device.
while (true) {
const { value, done } = await reader.read();
if (done) {
// Allow the serial port to be closed later.
reader.releaseLock();
break;
}
// value is a Uint8Array.
console.log(value);
}
Önemli olmayan bazı seri bağlantı noktası okuma hataları,
arabellek taşması, çerçeveleme hataları veya parite hataları. Bunlar
istisnalar vardır ve bir öncekinin üzerine başka bir döngü eklenerek yakalanabilir.
port.readable
olup olmadığını kontrol edin. Bu işe yarar çünkü hatalar
önemli olmayan bir değer varsa otomatik olarak yeni bir ReadableStream oluşturulur. Önemli bir hata
seri cihazın kaldırılması gibi bir gerçekleştiğinde port.readable
,
null.
while (port.readable) {
const reader = port.readable.getReader();
try {
while (true) {
const { value, done } = await reader.read();
if (done) {
// Allow the serial port to be closed later.
reader.releaseLock();
break;
}
if (value) {
console.log(value);
}
}
} catch (error) {
// TODO: Handle non-fatal read error.
}
}
Seri cihaz metni geri gönderirse port.readable
öğesini bir
TextDecoderStream
olarak gösterilir. TextDecoderStream
, bir dönüşüm akışıdır
tüm Uint8Array
parçaları yakalayıp dizelere dönüştüren bir komut dosyasıdır.
const textDecoder = new TextDecoderStream();
const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable.getReader();
// Listen to data coming from the serial device.
while (true) {
const { value, done } = await reader.read();
if (done) {
// Allow the serial port to be closed later.
reader.releaseLock();
break;
}
// value is a string.
console.log(value);
}
"Kendi Arabelleğinizi Getirin" işlevini kullanarak akıştan okuma yaptığınızda belleğin nasıl ayrılacağını kontrol edebilirsiniz. yardımcı olur. ReadableStreamBYOBReader arayüzünü almak için port.readable.getReader({ mode: "byob" })
yöntemini arayın ve read()
çağrısı yaparken kendi ArrayBuffer
öğenizi sağlayın. Chrome 106 veya sonraki sürümlerde Web Serial API'nin bu özelliği desteklediğini unutmayın.
try {
const reader = port.readable.getReader({ mode: "byob" });
// Call reader.read() to read data into a buffer...
} catch (error) {
if (error instanceof TypeError) {
// BYOB readers are not supported.
// Fallback to port.readable.getReader()...
}
}
Aşağıda, value.buffer
öğesinden arabelleğin nasıl yeniden kullanılacağına dair bir örnek verilmiştir:
const bufferSize = 1024; // 1kB
let buffer = new ArrayBuffer(bufferSize);
// Set `bufferSize` on open() to at least the size of the buffer.
await port.open({ baudRate: 9600, bufferSize });
const reader = port.readable.getReader({ mode: "byob" });
while (true) {
const { value, done } = await reader.read(new Uint8Array(buffer));
if (done) {
break;
}
buffer = value.buffer;
// Handle `value`.
}
Aşağıda, bir seri bağlantı noktasından belirli miktarda verinin nasıl okunacağına ilişkin başka bir örnek verilmiştir:
async function readInto(reader, buffer) {
let offset = 0;
while (offset < buffer.byteLength) {
const { value, done } = await reader.read(
new Uint8Array(buffer, offset)
);
if (done) {
break;
}
buffer = value.buffer;
offset += value.byteLength;
}
return buffer;
}
const reader = port.readable.getReader({ mode: "byob" });
let buffer = new ArrayBuffer(512);
// Read the first 512 bytes.
buffer = await readInto(reader, buffer);
// Then read the next 512 bytes.
buffer = await readInto(reader, buffer);
Seri bağlantı noktasına yazma
Bir seri cihaza veri göndermek için verileri şuraya aktarın:
port.writable.getWriter().write()
releaseLock()
aranıyor açık
Seri bağlantı noktasının daha sonra kapatılması için port.writable.getWriter()
gerekir.
const writer = port.writable.getWriter();
const data = new Uint8Array([104, 101, 108, 108, 111]); // hello
await writer.write(data);
// Allow the serial port to be closed later.
writer.releaseLock();
port.writable
hizmetine bağlı TextEncoderStream
üzerinden cihaza metin gönderin
aşağıda gösterildiği gibidir.
const textEncoder = new TextEncoderStream();
const writableStreamClosed = textEncoder.readable.pipeTo(port.writable);
const writer = textEncoder.writable.getWriter();
await writer.write("hello");
Seri bağlantı noktasını kapatma
port.close()
, readable
ve writable
üyeleri varsa seri bağlantı noktasını kapatır
kilidi açık. Yani releaseLock()
, ilgili
ve yazarsınız.
await port.close();
Ancak döngü kullanılarak bir seri cihazdan gelen veriler sürekli okunurken,
port.readable
, bir hatayla karşılaşana kadar her zaman kilitli kalır. Burada
destek kaydı, reader.cancel()
çağrıldığında reader.read()
zorla çözümlenir
{ value: undefined, done: true }
ile hemen yapıp
reader.releaseLock()
arama döngüsünü uygulayın.
// Without transform streams.
let keepReading = true;
let reader;
async function readUntilClosed() {
while (port.readable && keepReading) {
reader = port.readable.getReader();
try {
while (true) {
const { value, done } = await reader.read();
if (done) {
// reader.cancel() has been called.
break;
}
// value is a Uint8Array.
console.log(value);
}
} catch (error) {
// Handle error...
} finally {
// Allow the serial port to be closed later.
reader.releaseLock();
}
}
await port.close();
}
const closedPromise = readUntilClosed();
document.querySelector('button').addEventListener('click', async () => {
// User clicked a button to close the serial port.
keepReading = false;
// Force reader.read() to resolve immediately and subsequently
// call reader.releaseLock() in the loop example above.
reader.cancel();
await closedPromise;
});
Dönüşüm akışları kullanılırken seri bağlantı noktasının kapatılması daha karmaşık bir işlemdir. reader.cancel()
adlı kişiyi eskisi gibi arayın.
Ardından writer.close()
ve port.close()
numaralı telefonu arayın. Bu işlem, hataları yayarak
temel seri bağlantı noktasına aktarmanızı sağlar. Çünkü hata yayılımı
hemen gerçekleşmezse readableStreamClosed
ve kullanmanız gerekir.
port.readable
adlı zamanın algılanması için daha önce oluşturulmuş writableStreamClosed
taahhütleri
ve port.writable
cihazının kilidi açıldı. reader
iptal edildiğinde
akışın iptal edilmesi; Bu nedenle, ortaya çıkan hatayı bulup yoksaymanız gerekir.
// With transform streams.
const textDecoder = new TextDecoderStream();
const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable.getReader();
// Listen to data coming from the serial device.
while (true) {
const { value, done } = await reader.read();
if (done) {
reader.releaseLock();
break;
}
// value is a string.
console.log(value);
}
const textEncoder = new TextEncoderStream();
const writableStreamClosed = textEncoder.readable.pipeTo(port.writable);
reader.cancel();
await readableStreamClosed.catch(() => { /* Ignore the error */ });
writer.close();
await writableStreamClosed;
await port.close();
Bağlantıyı ve bağlantıyı kesmeyi dinleyin
Bir USB cihazı tarafından seri bağlantı noktası sağlanırsa o cihaz bağlı olabilir
veya sistemle bağlantısı kesilebilir. Web sitesine
seri bağlantı noktasına eriştiğinde connect
ve disconnect
etkinliklerini izlemesi gerekir.
navigator.serial.addEventListener("connect", (event) => {
// TODO: Automatically open event.target or warn user a port is available.
});
navigator.serial.addEventListener("disconnect", (event) => {
// TODO: Remove |event.target| from the UI.
// If the serial port was opened, a stream error would be observed as well.
});
Sinyalleri işleme
Seri bağlantı noktası bağlantısını kurduktan sonra, bu bağlantıyı doğrudan cihaz algılama ve akış kontrolü için seri bağlantı noktası tarafından açığa çıkarılan sinyaller. Bu sinyalleri boole değerleri olarak tanımlanır. Örneğin, Arduino gibi bazı cihazlar değeri, Veri Terminali Hazır (DTR) sinyali düğmesi açıldı.
Çıkış sinyallerini ayarlama ve giriş sinyallerini alma işlemleri sırasıyla
port.setSignals()
ve port.getSignals()
aranıyor. Aşağıdaki kullanım örneklerini inceleyin.
// Turn off Serial Break signal.
await port.setSignals({ break: false });
// Turn on Data Terminal Ready (DTR) signal.
await port.setSignals({ dataTerminalReady: true });
// Turn off Request To Send (RTS) signal.
await port.setSignals({ requestToSend: false });
const signals = await port.getSignals();
console.log(`Clear To Send: ${signals.clearToSend}`);
console.log(`Data Carrier Detect: ${signals.dataCarrierDetect}`);
console.log(`Data Set Ready: ${signals.dataSetReady}`);
console.log(`Ring Indicator: ${signals.ringIndicator}`);
Akışları dönüştürme
Seri cihazdan veri aldığınızda, tüm bildirimleri almayabilirsiniz. verileri tek seferde toplayabilirsiniz. Rastgele parçalanabilir. Daha fazla bilgi için bkz. Streams API kavramları.
Bununla başa çıkmak için
TextDecoderStream
veya kendi dönüşüm akışınızı oluşturun.
ayrıştırılır ve ayrıştırılan veriler döndürülür. Dönüşüm akışı
seri cihaz ile akışı tüketen okuma döngüsü arasında bağlantı kurar. O da
veriler tüketilmeden önce rastgele bir dönüşüm uygular. Bunu bir
montaj çizgisi: bir widget çizginin aşağısına doğru ilerledikçe satırdaki her adım
Bu şekilde, son hedefine vardığında widget'ın tam olarak
işleyen bir widget'a dokunun.
Örneğin, şu miktarda veri tüketen bir dönüşüm akışı sınıfının nasıl
akış şeklinde gösterir ve satır sonlarına göre parçalara ayırır. transform()
yöntemi
akış tarafından her yeni veri alındığında. Verileri sıraya alabilir ya da
daha sonra ilgilenmek üzere
saklayabilirsiniz. flush()
yöntemi, akış kapatıldığında çağrılır ve
henüz işlenmemiş tüm verileri işler.
Dönüştürme akışı sınıfını kullanmak için gelen akışı akış olarak eklemeniz gerekir:
somut olarak ortaya koyar. Seri bağlantı noktasından okuma altındaki üçüncü kod örneğinde,
orijinal giriş akışı yalnızca bir TextDecoderStream
üzerinden sağlanır. Bu nedenle,
yeni LineBreakTransformer
ile bağlantı kurmak için pipeThrough()
adlı kişiyi çağırmamız gerekiyor.
class LineBreakTransformer {
constructor() {
// A container for holding stream data until a new line.
this.chunks = "";
}
transform(chunk, controller) {
// Append new chunks to existing chunks.
this.chunks += chunk;
// For each line breaks in chunks, send the parsed lines out.
const lines = this.chunks.split("\r\n");
this.chunks = lines.pop();
lines.forEach((line) => controller.enqueue(line));
}
flush(controller) {
// When the stream is closed, flush any remaining chunks out.
controller.enqueue(this.chunks);
}
}
const textDecoder = new TextDecoderStream();
const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable
.pipeThrough(new TransformStream(new LineBreakTransformer()))
.getReader();
Seri cihaz iletişim sorunlarını ayıklamak için şunun tee()
yöntemini kullanın:
Seri cihaza giden veya seri cihazdan gelen akışları bölmek için port.readable
. İkisi
oluşturulan akışlar bağımsız olarak tüketilebilir ve bu, tek bir akış yazdırmanıza olanak tanır.
konsola gönderilir.
const [appReadable, devReadable] = port.readable.tee();
// You may want to update UI with incoming data from appReadable
// and log incoming data in JS console for inspection from devReadable.
Seri bağlantı noktasına erişimi iptal etme
Web sitesi, artık kullanılmayan bir seri bağlantı noktasına erişim izinlerini temizleyebilir
SerialPort
örneğinde forget()
çağırarak elde tutmayı düşünebilir. Örneğin,
Örneğin, birçok kullanıcıyla paylaşılan bir bilgisayarda kullanılan eğitsel bir web uygulaması
kullanıcı tarafından oluşturulmuş çok sayıda izin, kötü performansa neden olur.
en iyi uygulamaları paylaşacağız.
// Voluntarily revoke access to this serial port.
await port.forget();
forget()
, Chrome 103 veya sonraki sürümlerde kullanıma sunulduğundan bu özelliğin
şunlar tarafından desteklenir:
if ("serial" in navigator && "forget" in SerialPort.prototype) {
// forget() is supported.
}
Geliştiriciler İpuçları
Chrome'da Web Serial API'de hata ayıklamak dahili sayfa,
Seri cihazla ilgili tüm etkinlikleri tek bir yerde görebileceğiniz about://device-log
çok işe yarar.
Codelab
Google Developer codelab'de şu etkinliklerle ilgili olarak Web Serial API'yi kullanacaksınız: BBC micro:bit kartı ile bu verilerin 5x5 LED matrisinde gösteriliyor.
Tarayıcı desteği
Web Serial API tüm masaüstü platformlarında (ChromeOS, Linux, macOS, ve Windows) - Chrome 89'da kullanılabilir.
Çoklu Dolgu
Android'de WebUSB API kullanılarak USB tabanlı seri bağlantı noktaları desteklenebilir ve Serial API çoklu dolgusu. Bu çoklu dolgu, donanımla ve platforma erişim sağlanamadığından cihazın WebUSB API üzerinden erişilebilir olduğu yerleşik bir cihaz sürücüsü tarafından hak talebinde bulunulmuş olabilir.
Güvenlik ve gizlilik
Bu spesifikasyonların yazarları, çekirdek API'yi kullanarak Web Serial API'yi Güçlü Web Platformu Özelliklerine Erişimi Kontrol Etme'de açıklanan ilkeleri, dahil olmak üzere tüm bunları kapsar. Bunu kullanma imkanı API, esas olarak yalnızca tek bir kullanıcıya erişim veren bir izin modeliyle denetlenir. seri cihazdan sarkıtılabilir. Kullanıcı istemine yanıt olarak kullanıcının etkin olması gerekir adımları uygulayın.
Güvenlikle ilgili ayrıntıları anlamak için güvenlik ve gizlilik konularına göz atın. bölümlerine göz atın.
Geri bildirim
Chrome ekibi Web Serial API.
Bize API tasarımı hakkında bilgi verin
API'de beklendiği gibi çalışmayan bir şey mi var? Yoksa fikrinizi uygulamak için ihtiyacınız olan yöntem veya özelliklerden yoksun mu?
Web Serial API GitHub deposunda teknik özellik sorunu bildirin veya düşünmeye başlayabilirsiniz.
Uygulamayla ilgili bir sorunu bildirin
Chrome'un uygulanmasıyla ilgili bir hata buldunuz mu? Yoksa ve spesifikasyondan farklı mı?
https://new.crbug.com adresinden hata bildiriminde bulunun. Olabildiğince çok sayıda
mümkün olduğunca ayrıntı verin, hatayı yeniden oluşturmak için basit talimatlar sağlayın ve
Bileşenler Blink>Serial
olarak ayarlandı. Glitch mükemmel bir yöntemdir
hızlı ve kolay yenidenler
paylaşabilirsiniz.
Desteğinizi gösterin
Web Serial API'yi kullanmayı planlıyor musunuz? Herkese açık desteğiniz Chrome'un ekibinin öncelikle özelliklerin ne kadar önemli olduğunu gösterir ve diğer tarayıcı tedarikçilerine destek olmak.
Hashtag'i kullanarak @ChromiumDev hesabına tweet gönderin
#SerialAPI
ve nerede ve nasıl kullandığınızı bize bildirin.
Faydalı bağlantılar
- Spesifikasyon
- Hata izleme
- ChromeStatus.com girişi
- Blink Bileşeni:
Blink>Serial
Demolar
Teşekkür
Bu makaleyle ilgili yorumları için Reilly Grant ve Joe Medley'ye teşekkür ederiz. Birmingham Museums Trust tarafından Unsplash'teki uçak fabrikası fotoğrafı.