Angular で WebHID API を使ってみる

目的

WebHID APIをAngularで使用するために必要なことを備忘録としてメモします。

やる内容としては以下の通りです。

  • Angularプロジェクト作成
  • @types/w3c-web-hidをnpm install
  • 接続するHIDデバイスのVID(ベンダーID)、PID(プロダクトID)の確認
  • コーディング

WebHID APIとは

WebHID は、ブラウザからクライアントPCに接続されているHIDデバイスにアクセスすることができます。というかできちゃいます。

セキュリティ的に大丈夫なのかと思うのは当然で、WebHID APIをサポートしているのは2022/7/27現在 デスクトップ版のChrome、Edge、Operaブラウザのみです。[1]

ですが、個人で遊ぶ分には魅力的な機能になります。

Angularプロジェクト作成

以下のコマンドを入力してAngularプロジェクトを作成します。

ちなみにバージョンは、Angular14です。

ng new webhid-sample

Angularプロジェクトに@types/w3c-web-hidをinstall

プロジェクトが作成されたら、WebHID をtypescriptで定義したnpmパッケージをプロジェクトへインストールします。

以下のコマンドを入力します。

npm install @types/w3c-web-hid

インストールが完了したら以下のファイルを編集します。

tsconfig.app.json

“include”に”node_modules/@types/w3c-web-hid/index.d.ts”を追加

/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": []
  },
  "files": [
    "src/main.ts",
    "src/polyfills.ts"
  ],
  "include": [
    "src/**/*.d.ts",
    "node_modules/@types/w3c-web-hid/index.d.ts"
  ]
}

WebHID APIコーディング

Angularで WebHID APIを使用してHIDデバイスを検索、接続、データ送信・受信を行ってみたいと思います。まずは、HIDデバイスの検索から。

WebHIDを検索、接続

import { Injectable } from "@angular/core";

@Injectable({
    providedIn: 'root'
})
export class SampleHIDService{
    /** ベンダーID */
    private readonly VID: number = 0xXXXX; //接続したいHIDデバイスのVIDを設定
    /** プロダクトID */
    private readonly PID: number = 0xXXXX; //接続したいHIDデバイスのPIDを設定

    private hidDevices: HIDDevice[];
    private targetDevice: HIDDevice;

    constructor() {
        this.hidDevices = [];
    }

    async connect(): Promise<boolean> {
        //検索
        this.hidDevices = await navigator.hid.requestDevice({
            filters: [{
                vendorId: this.VID,
                productId: this.PID
            }]
        });

        this.targetDevice = this.hidDevices[0];
        if (!this.targetDevice) {
            return false;
        }

        //接続
        await this.targetDevice.open();
        return true;
    }
}

HIDにデータを送信

コマンドをUint8Arrayに格納して送信します。

this.targetDevice.sendReport(0, new Uint8Array([0,0,0,0,0,0,0,0]));

HIDからデータを受信

// 受信イベント作成
this.targetDevice.addEventListener("inputreport", event => {
    const eventInfo: HIDInputReportEvent = event as HIDInputReportEvent;
    console.log(eventInfo.data.getUint8(0));
});

WebHID を使う際の注意点

ユーザからの何かしらのイベント(ボタンのクリックなど)を行わずにHIDデバイスを操作するスクリプトを実行した場合、以下のようなエラーが出力され、処理が実行されません。

Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules

解決するには、ボタンクリック時などのイベントにHIDデバイス操作の処理を記載すればエラーは出力されなくなります。

HIDデバイスの接続を行おうとすると以下のようなプロンプトがブラウザに表示されるはずです。

WebHID デバイスアクセスプロンプト

参考サイト

  1. TypescriptでWebHIDを扱う
  2. WebHID API – Web APIs | MDN

この記事以外にも色々と公開していますので、見てみてください。

ゆるキャリエンジニア日誌

コメントする