Matter QR コード生成を Wasm にしてみた

Nature ソフトウェアエンジニアの桒山です。この記事は、第2回 Nature Engineering Blog 祭の13日目の記事になります!

Matter のコミッショニングで用いる QR コード1生成を Wasm で実装して、Web ブラウザから QR コードを生成できるようにした話です。実装は以下です。

私、個人的な目的としては

  • QR コードを颯爽と出力して、Commissionee 検証などの際に遊びたい
  • Matter Spec について復習したい
  • Rust を書きたい

です。Matter 開発を楽しんでいきましょう!

QR コードによる Matter のコミッショニング

Matter のコミッショニングについては、Nature Matter Kaigi の田井の発表資料が分かりやすいと思います。参照ください。

speakerdeck.com

Matter のコミッショニングでは、MPC(Manual Pairing Code) を使う方法と QR コードを使う方法があります。matter_qrcode_generator では、この QR コードを出力します。QR コードの仕様については Matter 1.0 Core Specification 5.1.3. QR Code 2 を参照してください。

Wasm 3 って?

WebAssembly は現代のウェブブラウザーで実行できる新しい種類のコードです。ネイティブに近いパフォーマンスで動作する、コンパクトなバイナリー形式の低レベルなアセンブリー風言語です。さらに、 C/C++C# や Rust などの言語のコンパイル先となり、それらの言語をウェブ上で実行することができます。 WebAssembly は JavaScript と並行して動作するように設計されているため、両方を連携させることができます。

Wasm を JavaScript から読めるように実装

レポジトリ構成は、おおよそ下記です。

├── matter_qrcode_generator
│   ├── Cargo.toml
│   └── src
│       ├── base38.rs
│       ├── cli.rs
│       ├── lib.rs
│       ├── main.rs
│       ├── onboarding_payload.rs
│       └── qr.rs
└── matter_qrcode_generator_wasm
    ├── Cargo.toml
    ├── src
    │   └── lib.rs
    └── www
        ├── css
        │   └── style.css
        ├── index.html
        └── js
            └── app.js

二つのディレクトリについて、それぞれ何をやっているか説明します。

  • matter_qrcode_generator/
    • Matter の仕様に沿って QR コードを生成する Rust 実装
      • main.rs から CLI として動くように
      • lib.rs としてモジュールを参照可能に
  • matter_qrcode_generator_wasm/
    • ../matter_qrcode_generator/ を用いて Wasm のコードを書き出すように実装
      • lib.rs にて wasm_bindgen クレートを利用
      • Wasm コードを JavaScript から参照して、フロントエンドにて QR コードを生成・表示

つまり、依存関係は下記の通りです。

matter_qrcode_generator_wasm/src/lib.rs で用いられるクレートを紹介しておきます。

  • wasm_bindgen
    • JavaScript から Rust の関数を呼び出したり、Rust から JavaScript の関数を呼び出し可能にするための Wasm を書き出すようにコンパイルするためのクレート
      • #[wasm_bindgen]
  • js_sys
    • JavaScript から呼び出せる Rust の関数を実装する際に、返り値を JavaScript の型として実装できるようにするクレート
      • JSValue
#[wasm_bindgen]
pub fn do_print_qr(
    vid: u16,
    pid: u16,
    passcode: u32,
    discriminator: u16,
    soft_ap: bool,
    ble: bool,
    on_ip_nw: bool,
    pixel: u32,
) -> Result<String, JsValue> {
    // QR コードを SVG として生成、HTML タグで書き出して文字列として返す

Github Actions にて .wasm と .js と index.html ファイルを公開用ブランチ上に配置

npm build <scripts> からコマンドを実行できるようにしました。matter_qrcode_generator/public/ 以下に .wasm と .js と index.html が書き出されます。内部で利用しているツールは下記です。

  • wasm-pack
    • Rust から出力された .wasm を npm パッケージとして構築するためのツール
  • webpack
    • 依存する .js や .css など複数のファイルをまとめて出力してくれるツール
      • www/ 以下に書いた css と .js をまとめ、index.html から参照してくれるようにするために利用
$ npm install   # 依存する .js 取得

$ npm run build # 以前のビルド結果掃除、wasm-pack、webpack 実行してビルド

$ npm run start # http-server を立てて localhost:8080 をオープン
// 省略
"scripts": {
        "lint": "eslint www/index.html www/js",
        "build:pre": "rm -rf public",
        "build:wasm": "wasm-pack build --target web --no-typescript --features wee_alloc",
        "build:webpack": "webpack",
        "build": "run-s build:pre build:wasm build:webpack",
        "start": "cd public && http-server -o"
    }
// 省略

Github Actions にて、main ブランチに push があれば自動デプロイされるようにしています。

  • github-pages-action
    • Github Pages するための Github Actions
      • ビルドした .wasm と .js と index.html だけを公開したい。その他の Rust のコードとかは公開する必要はない。matter_qrcode_generator/public/ 以下だけ公開するように設定するために利用
      • デフォルトで gh-pages を上書きする形でデプロイ
    • https://github.com/marketplace/actions/github-pages-action
    - run: npm install
      working-directory: ./matter_qrcode_generator_wasm
    - run: npm run build
      working-directory: ./matter_qrcode_generator_wasm
    - name: Deploy
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./matter_qrcode_generator_wasm/public

公開用ブランチを設定して Github Pages で公開

上記を用いて、Github Actions にて public に書き出された .wasm と .js と index.html を gh-pages ブランチのルートから上書きして配置します。

github.com

GitHubリポジトリから HTML、CSS、および JavaScript ファイル を直接取得し、任意でビルドプロセスを通じてファイルを実行し、ウェブサイトを公開できる静的なサイトホスティングサービスです。

実際にコミッショニングしてみる

Commissionee は matter-rs の onoff_light を用います。手元に Rust 環境のある PC をご用意ください。手元の PC にて

$ git clone git@github.com:project-chip/matter-rs.git

$ cd matter-rs

$ cargo run --example onoff_light

matter-rs を書き換えずにそのまま実行しますと

で起動されます。上記を web にて入力して、 print ボタンを押してください。QR コードが生成されます。

PC と同じ無線 LAN にて、Commissioner からコミッショニングしてみてください。コミッショニングが成功すると思います。下記は iPad から Home アプリを起動した場合のスクリーンショットです。

コミッショニング成功です。 🎉🎉

まとめ

Matter QR コード生成を実装し、そして Wasm にして Github Pages にて公開しました。もし Matter 開発において、QR コードが必要になった際に助けになれば幸いです。

Nature エンジニアコミュニティ

エンジニアコミュニティはじめました。Matter を使った Nature Remo nano の活用方法から Nature Remo could API の疑問など、Nature のエンジニアがお答えします! Discord への参加はこちらから。

discord.gg

Nature Remo nano 好評発売中!

Matter 対応の Nature Remo nano が定価3,980円で発売中!


  1. QRコードは(株)デンソーウェーブの登録商標です
  2. Matter Specification 1.0 5.1.3. QR Code pp.217-221
  3. https://webassembly.github.io/spec/core/intro/introduction.html#wasm