ウェブブラウザとハードウェアの関係

今回は、ウェブアプリからハードウェアを制御する話をちょっとしてみたいと思います。

今日のウェブブラウザの立ち位置

ウェブブラウザが世の中に登場してからすでに長い時間が経過しています。パソコンをお持ちの方々は、そのほとんどの時間をウェブブラウザの中で過ごしているはずです。もはやパソコンに直接インストールされているWindowsやmcOSといったOSが何であれ、ウェブブラウザさえ使えれば大半のことができるようになった、今はそんな時代です。ウェブブラウザがOSである、そんな言い方もあながち間違ってはいないかと思います。

ウェブブラウザには、数多くのAPIが提供されています。それらのAPIは、OSが提供するAPIに匹敵するほど強力な機能をウェブページにもたらしてくれます。2014年前後に盛り上がったHTML5付近でウェブブラウザをアプリケーションプラットフォームに仕立てる動きが加速しました。現在当たり前のように使われているAPI群は、その時期から次々と登場して安定化されていきました。

現在では、ウェブブラウザは大きく3つの陣営が存在します(と個人的に思ってます)。

  • Blink - Chromiumで使われているレンダリングエンジン
  • Gecko - Firefoxで使われているレンダリングエンジン
  • Webkit - Safariで使われているレンダリングエンジン

それぞれウェブに対する思想(こうあるべきだ!という考え)が異なっています。「あ、ウェブアプリとしていろんなことをできるようにしたいんだな」とか「できることを増やすよりもプライバシー重視なんだな」というような感じです。その違いが、使えるAPIと実装されていないAPIのバリエーションの違いとなって現れています。

Chromium、言い換えるとGoogle ChromeやMicrosoft EdgeがAPIの提供に積極的です。ちょっと前までは「ウェブブラウザなんだからできなくて仕方がない」と言われていたことが、どんどんできるようになってきています。

ウェブアプリからハードウェアを制御する

特に「ハードウェアの制御」に関しては、そりゃネイティブアプリじゃないとできないでしょ、と言われていた分野です。

今では、ウェブアプリからハードウェアをかなり制御することができるようになっています。

電子回路工作でよく使われるマイコンボードとして、以下をあげることができます。

  • Arduino UNO、Arduino Nano、Arduino Leonardo、Arduino Mega
  • Raspberry Pi、Raspberry Pi Zero、Raspberry Pi Pico
  • ESP8266、ESP32、ESP32-C3
  • micro:bit

これらは、パソコンとUSBでつないだり、シリアル通信でやり取りしたりしながら、ファームウェアをパソコンからマイコンに書き込んでハードウェアを制御します。また、BluetoothやWiFiに対応したマイコンボードであれば、パソコンから無線でハードウェアを制御することもできるでしょう。

そう、ChromeやEdgeであれば、ウェブアプリから上記のようなハードウェアの制御ができるのです。

ChromeやEdgeに搭載されているハードウェアの制御に使えるAPIを紹介してみましょう。掲載しているサンプルプログラムは「あ、こんな “感じ” になるのね」程度で眺めてください。

Web Serial API

ウェブアプリからシリアル通信を実現するためのAPIです。OSが提供するシリアルポートを選択して、ウェブアプリからシリアルポートに情報を送信したり、シリアルポートに流れてきた情報をウェブアプリで受け取ることができます。

シリアルポートを開いて情報を送受信するプログラムは、以下のようになります。

// ポートを開く
const port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 });
reader = port.readable.getReader();
writer = port.writable.getWriter();

// 送信する
const data = new TextEncoder().encode("Hello!\n");
await writer.write(data);

// 受信する
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  const data = new TextDecoder().decode(value);
  // 受け取ったdataに対して何か処理
}

上記は文字列をUTF-8で通信相手とやり取りするプログラムです。バイト列そのもので良ければ、TextEncoderやTextDecoderは使わずに、Uint8Arrayとして送受信すれば大丈夫です。もちろん、送受信されるバイト列は、お互いに仕様を合わせておく必要があります。

Web USB API

ウェブアプリからUSBデバイスに直接アクセスできるAPIです。これにより、特定のUSBデバイスと通信するウェブアプリを開発できます。通常、USBデバイスとの通信にはOSのドライバやネイティブアプリが必要ですが、Web USB APIを使うことで、ドライバ不要でウェブブラウザから直接USB機器を制御できます。

以下は、架空のUSBデバイスとの情報の送受信を行うサンプルプログラムです。USBシリアルデバイスという想定です。

// USBデバイスを開く
const device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x1234 }] });
await device.open();
await device.selectConfiguration(1);
await device.claimInterface(0);

// 送信する
await device.transferOut(1, new TextEncoder().encode("Hello!\n"));

// 受信する
while (true) {
  const result = await device.transferIn(1, 64);
  const data = new TextDecoder().decode(result.data);
  // 受け取ったdataに対して何か処理
}

USBで規定されたプロトコルをそのまま扱うことになるので、通信対象のUSBの使用にある程度詳しくなる必要があります。

Web HID API

ウェブアプリから HID(Human Interface Device) に直接アクセスできるAPIです。HIDデバイスには キーボード、マウス、ゲームパッド、カスタムコントローラー などが含まれます。通常、HIDデバイスはOSの標準ドライバで動作しますが、Web HID APIを使うことで、カスタムデバイスや特殊なHIDデバイスをウェブアプリから制御 できます。

以下は、架空のHIDデバイスとの情報の送受信を行うサンプルプログラムです。

// HIDデバイスを開く
const device = await navigator.hid.requestDevice({ filters: [{ vendorId: 0x1234 }] });
await device.open();

// 送信する
await device.sendReport(0, new TextEncoder().encode("Hello!\n");

// 受信する
device.addEventListener("inputreport", event => {
  const data = new Uint8Array(event.data.buffer);
  const text = new TextDecoder().decode(data);
  // 受け取ったtextに対して何か処理
});

HIDデバイスからの受信がイベントハンドラ登録なのが特徴的ですね。

Web Bluetooth API

ウェブアプリから Bluetooth Low Energy(BLE)デバイスと通信 できるAPIです。これにより、ウェブアプリからワイヤレスでセンサーやIoTデバイスを制御 できます。

以下は、架空のBluetoothデバイスとの情報の送受信を行うサンプルプログラムです。

実際の利用シーン

ここまで紹介してきたAPIを実際に僕がどう使っているのかを紹介したいと思います。

Remap

自作キーボードキットの多くが、キーマップやLEDの点灯パターンのカスタマイズのために、Remapに対応しています。Remapは、ウェブブラウザからマイコンと通信をして、各種カスタマイズを行うことができる便利なウェブアプリです。

Remap

キーボードに搭載されたマイコンに対して、Remapでは以下のようなことを行っています。

  • マイコンにファームウェアを書き込むために、RemapではWeb USB APIやWeb Serial APIを使っています。具体的には、ブートローダーにLeonardoが使われているときはWeb Serial APIを、DFUが使われているときはWeb USB APIを使っています。
  • キーマップやLEDの点灯パターンのカスタマイズのために、RemapではWeb HID APIを使っています。

Web USB APIやWeb Serial API、Web HID APIにより、自作キーボードキットを組み立てた後、その人は何か特別なアプリをOSにインストールすることなく、ウェブブラウザでRemapを開いてすぐにカスタマイズを始めることができます。今では、キーボードのカスタマイズアプリのいくつかが、Remapに追随してウェブアプリ化を遂げています。

Sketch Bridge

最近作り始めたウェブアプリです。Sketch Bridgeは、Arduinoボード向けの開発環境です。現在は、Arduino UNO R3と、Arduino UNO R4 Minimaに対応しています。

Sketch Bridge

Sketch Bridgeでは、以下のようなことを行っています。

  • Arduino UNO R3が採用しているOptibootブートローダーとWeb Serial APIで通信を行い、ファームウェアの書き込みを行っています。
  • Arduino UNO R4 Minimaが採用しているDFUブートローダーとWeb USB APIで通信を行い、ファームウェアの書き込みを行っています。

ウェブアプリから直接マイコンにファームウェアを書き込むことができるようになったため、Arduino IDEをインストールすることなく、ウェブブラウザのみでArduino向けのプログラミングができるようになります。これは、Arduino IDEをインストールすることが比較的大変なChromebookでも、Arduino向けの開発が可能になることを意味しています。

まとめ

ChromeやEdgeでは、ハードウェアをウェブアプリから直接制御することを可能にするいくつかのAPIが提供されています。それらによって、ハードウェアを直接扱うウェブアプリの開発ができるようになり、ユーザーは手軽にハードウェアをウェブブラウザのみで制御することができるようになります。これは素晴らしいことだと思っています。

マイコンボードを使ってハードウェアを開発している方々、電子工作に興味はあるけどなんか難しそうだなと思ってるソフトウェア開発者の方々には、特に知っておいて欲しいなと思い、この記事をまとめてみました。手元に何らかマイコンボードがある方は、ぜひウェブブラウザからの制御にチャレンジしてみてください。

このエントリーをはてなブックマークに追加

関連記事

Firebase FunctionsデプロイでArtifact Registryのクリーンアップポリシー設定エラーに遭遇した話

Web Serial APIでブラウザからシリアルデバイスを操作する

macOSやLinuxからWindowsに移行したら快適になった話

「エンジニアチームの生産性の高め方」という書籍が出版されました

2023年のRemap