C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

RustのcdylibをバックエンドにElectronをフロントエンドにするcargo-generateプロジェクトテンプレートを公開したメモ

「RustのcdylibをバックエンドにElectronをフロントエンドにする」プロジェクトを3秒くらいでお手軽作れるcargo-generateできるプロジェクトテンプレートを公開しました。

f:id:USAGI-WRP:20200320172806p:plain

使い方:

cargo generate --git https://github.com/usagi/template-rust-backend-with-electron-frontend.git

使い方としての細かいことは README.md#Usage を読んでください。

このメモの主体は↑の使い方ではなく、作る最中に遭遇したトラブルシュートのメモです。

作るまでに遭遇したトラブルたち

  1. Rust の GUI Toolkit を採用したプロジェクトを作ろうと思ったけれど:
  2. Electron を GUI フロントエンド部に採用しようと思い:

こんな事がありました。ありましたが💪で解決できたのでとりあえずこの Rust をバックエンドに cdylib を書いて Electron をフロントエンドにイケイケできるプロジェクトのテンプレートを cargo-generate できるように公開しました。👍

ちなみに、この template-rust-backend-with-electron-frontend で GUI 部分をイケイケに作り込む場合はさらに TypeScript やクライアントサイド向けのフレームワークなどの要素技術スタックがアーキテクチャーに仲間入りしたり、 React を Angular / Vue へ変えたくなる事もあるかもしれません。🤔 バックエンド部の Rust も何をするアプリかにより crate を追加し、ビジネスロジックをにゃんにゃん書きます。もちろん、最小限の試作程度ならこの CSS なにそれ美味しいの的な HTML で GUI をごりっと書いて Rust でビジネスロジックの核心的な部分を書いて十分、それもアリです。

全ての技術要素を完全に理解して使う事は難しいと思いますが、このテンプレートを使えば Rust と Electron で可能性は無限大かつ現実的なやつがすぐに作れちゃうぞ的な美味しい感じでわくわくプロジェクトを始められると思います。たぶん。Rust 純度高めでも QML みたいなお手軽GUIホイホイできるようになるその日まで。(ΦωΦ)フフフ…

react-electron-ffi-(native dll/so/dylib) プロジェクトを作るメモ (2020-03-19版)

(1/2) react-electron

ここは今回のメモの本編ではないものの、"やり方"がころころ変わるようなので一応現時点での方法をついで程度に整理します。

(1) プロジェクトのディレクトリー(=リポジトリー)を create-react-app で生成:

npx create-react-app myapp
cd myapp

(2) electron 系のパッケージを追加:

yarn add electron electron-builder wait-on concurrently --dev
yarn add electron-is-dev

(3) public/electron.js を作る:

const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;

const path = require('path');
const isDev = require('electron-is-dev');

let mainWindow;

function createWindow() {
  app.allowRendererProcessReuse = true;
  mainWindow = new BrowserWindow({width: 1920/4, height: 1080/4, webPreferences:{ nodeIntegration: true } });
  mainWindow.loadURL(isDev ? 'http://localhost:3000' : `file://${path.join(__dirname, '../build/index.html')}`);
  mainWindow.on('closed', () => mainWindow = null);
}

app.on('ready', createWindow);

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow();
  }
});

(4) package.json に electron 用のお約束を追記:

(以下のコードはmergeする追記分のみ)

{ "main": "public/electron.js"
, "scripts":
  { "dev": "concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\""
  }
}

ここまでの時点で yarn dev で package.json に追記した scripts の dev を呼ぶと一応 react-scripts を介して react-electron が期待動作してくれるはず。しなかったらこのメモの作成時点とは何か変化が必要にどこかが変わっている可能性があります。 Node.js, electron, Chromium など要素技術の変化はかなり激しいので、そういう事があっても慌てず問題を探りましょう、未来のわたしへ。

(5) rescripts を導入し eject せず create-react-app を扱える様に調整:

(5-1) rescripts を install

yarn add @rescripts/cli @rescripts/rescript-env --dev

(5-2) package.json / scripts の start, build, testreact-scripts から resccripts へ変更:

(以下のコードは該当部分の変更後のみ)

{ "scripts":
  { "start": "rescripts start"
  , "build": "rescripts build"
  , "test": "rescripts test"
  }
}

(5-3) package.json / scripts に postinstall, preelectron-pack, electron-pack を追加:

(以下のコードはmergeする追記分のみ)

{ "scripts":
  { "postinstall": "electron-builder install-app-deps"
  , "preelectron-pack": "yarn build"
  , "electron-pack": "electron-builder build -w"
  }
}

ここで electron-packelectron-builder build -w-wWindows 向けのパッケージングを有効にする引数。OSX向けを有効にしたければ -mGNU/Linux 向けを有効にしたければ -lWindowsOSXGNU/Linux 向けを同時に有効にしたければ -wml のように定義でき、プロジェクトに応じて変更します。必要ならプラットフォームのアーキテクチャーも --ia32, --x64 で設定できます。

(5-4) package.json / scripts から eject を削除

rescripts を使う場合 eject を使う必要は無いし、残しておいても事故の元になるだけなので scripts から完全に消し去ります。

(5-5) package.json に rescripts を追記:

(以下のコードはmergeする追記分のみ)

{ "rescripts": [ "env" ]
}

これを書かないと electron のウィンドウ(=client-side)は動いても react な中身(=server-side)が期待動作しなくなります。

(5-6) .webpack.config.js を追加:

module.exports = config =>
{
  config.target = 'electron-renderer';
  return config;
}

(5-7) .rescripts.js を追加:

module.exports = [require.resolve('./.webpack.config.js')]

(6) package.json にパッケージング用のメタデータを追加:

{ "author":
  { "name": "Author Name"
  , "email": "aurhot.email@example.com"
  , "url": "https://author-website.example.com"
  }
, "build":
  { "appId": "com.my-website.my-app"
  , "productName": "MyApp"
  , "copyright": "Copyright © 2020 ${author}",
  , "mac":
    { "category": "public.app-category.utilities"
    }
  , "files":
    [ "build/**/*"
    , "node_modules/**/*"
  ]
, "directories":
  { "buildResources": "assets"
  }
}

(7) assets / icon.png を作成

  1. assets ディレクトリーを作成
  2. 256x256 の icon.png を放り込む(アプリのアイコンになります)

以上で react-electron の 2020-03-19 頃の準備手順は完了です。 yarn dev で開発版を実行、 yarn electron-pack でリリース版パッケージを dist ディレクトリーへ生成できるようになっています。なっていなければ、このメモの作成時点とは何か変化が必要にどこかが変わっている可能性があります。 Node.js, electron, Chromium など要素技術の変化はかなり激しいので、そういう事があっても慌てず問題を探りましょう、未来のわたしへ。

動作を確認したら次の react-electron を react-electron-ffi-(native dll/so/dylib) へ進みましょう。

(2/2) react-electron から react-electron-ffi-(native dll/so/dylib) へ

react-electron を使わない Node.js で FFI して native dll/so/dylib を呼ぶ方法は1つ前回書いた Node.js と FFI の 2020-03-18 時点でのメモ; node-ffi 系 → node-ffi-napi 系 - C++ ときどき ごはん、わりとてぃーぶれいく☆ のように node-ffi 系ではなく node-ffi-napi 系を使う事だけ知っていればわりと簡単に yarn add ffi-napi ref-napi して、

var ffi = require('ffi-napi')
var ref = require('ref-napi')
var s = ref.types.CString
var nyanko = ffi.Library( 'nyanko.dll',{ 'f': [ s, [] ] } )
console.log( nyanko.f() )

のように使えばよいだけです。これを踏まえて、 (1/2) で作成した react-electron のプロジェクトで、

  1. yarn add ffi-napi ref-napi して
  2. src/App.js で前述のような FFI コードを記述して実行

すると:

f:id:USAGI-WRP:20200318225023p:plain

こんな具合で死にます。☠ Node.js, react, electron に慣れていない初心者にはわけがわからない上にググらビリティーに問題を抱えたエラーの様に感じられますが、わかってしまえばどうという事はなくなります:

(1) public/electron.js の new BrowserWindowwebPreferences.nodeIntegration を明示的に true に変更する:

  mainWindow = new BrowserWindow({width: 1920/4, height: 1080/4, webPreferences:{ nodeIntegration: false } });

これをやらないと次の(2)だけやっても "window.require is not a function" とか electron のウィンドウにエラーが表示される事になります。nodeIntegrationtrue にしないと Node.js 部分の機能が有効にならないため、 fs も使えないとかそういう事が起こります。そうなると ffi も使えません。(2/2) の最初の死亡状態で無いと言われていた exists はたぶん fsexists でしょう。そこに気がつければこの問題と原因と解決方法へ繋がります。

(2) src/App.js では window.require('electron').remoterequire して FFI する

const remote = window.require('electron').remote;
const ffi = remote.require( 'ffi-napi' );
const ref = remote.require( 'ref-napi' );

こんな具合で期待動作します。これで例えば:

let s = ref.types.CString;
let nyanko = ffi.Library( '../fuga/nyanko.dll',{ 'f': [ s, [] ] } ); // 例として前回適当に作った文字列値を返すだけのライブラリーを束縛
let mewing = nyanko.f();

としておいて、 function App()return{mewing} を:

          Learn React {mewing} !

など仕込んで実行すると:

f:id:USAGI-WRP:20200319013223p:plain

こうなります。成功👍

もし、 yarn dev する場合とパッケージングして実行する場合では native dll/so/dylib のパスが変わる場合は:

const is_dev = remote.require( 'electron-is-dev' );
const nyanko_path = is_dev ? '../fuga/nyanko.dll' : 'nyanko.dll';
let nyanko = ffi.Library( nyanko_path,{ 'f': [ s, [] ] } )

と electron-is-dev を使うと簡単です。呼び出す native dll/so/dylib もオリジナルに作ったものを使用したいプロジェクトではこのように対応します。あるいは、たぶん実行時の引数かシェル変数で渡す事にしておいて dev では package.json の scripts/start で特殊化しても対応できそうですが、私は今回 electron-is-dev で満足したのでその方法については思いついただけに留まります。

ついで、蛇足となりますが自分用メモとして、 electron-is-dev の値は Boolean なので、これを文字列で表示したい場合は {is_dev} ではなく {is_dev.toString()} しないと文字列では見れません。このメモを書いた時に一度「あれ、文字列には…」と期待動作しない状態を見てしまったので自分用備忘録。

参考

Node.js と FFI の 2020-03-18 時点でのメモ; node-ffi 系 → node-ffi-napi 系

今回のメモの Node.js は:

node -v
v13.5.0

です。先ずは Node.js 初心者らしく npm i ffi して死にました:

npm i ffi

f:id:USAGI-WRP:20200318171359p:plain

ほか多数のエラーを観測し、死んでしまいました。☠

f:id:USAGI-WRP:20200318170856p:plain

どんどん使われなくなっているので何か代替に置き換わったのだろうと思い調べてみると、 ffi は Node.js < 11 の時代で死んでしまったらしい事、 Node >= 11 用には fork した @saleae/ffi が対応しているらしい事がわかりました。

既にこちらも Weekly download が怪しいですが、とりあえず npm i @saleae/ffi してみました:

npm i @saleae/ffi

f:id:USAGI-WRP:20200318171506p:plain

死亡。☠

ここで元々の ffi の Issues を眺めてみると、

が見つかり、

  1. ffi-napi が Node >= 12 用に使えるらしい
  2. ffi-napi はコールバックの実装にまだ問題があるかもしれないらしい(このメモより14日前の情報)

事がわかりました。コールバックの問題点は、

  1. Fix crasher in callback calls by atishay · Pull Request #56 · node-ffi-napi/node-ffi-napi · GitHub (このメモより6日前に merged )
  2. Port fix for Multithreaded callback crash by atishay · Pull Request #50 · node-ffi-napi/node-ffi-napi · GitHub (このメモより2ヶ月くらい前に merged )

あたりについて、特に日付的に #56 の方の注意だと思います。現在は解決しているようです。とりあえず ffi-napi もインストールチャレンジしてみました:

npm i ffi-napi

しばらくのち:

+ ffi-napi@2.4.7
added 10 packages from 57 contributors, removed 4 packages and audited 17 packages in 18.686s
found 0 vulnerabilities

エラーなく導入できました。👍

実際に使う場合は型のバインディングref も欲しいのですが、こちらも node-ffi-napi シリーズの repos が一通りあるので:

npm i ref-napi します:

npm i ffi-napi

しばらくのち:

+ ref-napi@1.4.3
updated 1 package, moved 1 package and audited 23 packages in 5.993s
found 0 vulnerabilities

ref-napi も導入できました。👍

これでFFIの最低限の準備が整いました。適当に動作テストしてみます。

(1) テスト用に FFI で呼ばれる native な .dll (.so, .dylib) を作ります:

今回はなんとなく Rust で呼ぶと "にゃおーん" 文字列を返してくれる nyanko.dll を作ります。

# Windows でやっている場合は PowerShell で echo すると utf16 になるので 
echo '#[no_mangle] pub extern fn f() -> * const u8 { "にゃおーん".as_ptr() }' > nyanko.utf16.rs

# UTF8 に一手間増えます(Windowsの謎仕様でBOMが付きますが rustc はスルーしてくれます)
Get-Content nyanko.utf16.rs | Out-File -Encoding utf8 nyanko.rs

# このくらいなら Cargo さんに頑張ってもらわなくても rustc 直呼びで手早く済ませられます
rustc --crate-type cdylib nyanko.rs

これで Node.js から ffi-napi により FFI で呼ばれる側の nyanko.dll ができました。一応 nyanko.rs のソースだけ書き残しておくと

#[no_mangle] pub extern fn f() -> * const u8
{
  "にゃおーん".as_ptr()
}

(2) テスト用に FFI で呼ぶ側の Node.js な tester.js を作ります:

echo "console.log( require('ffi-napi').Library( 'nyanko.dll',{ 'f': [ require('ref-napi').types.CString, [] ] } ).f() )" > tester.utf16.js
Get-Content tester.utf16.js | Out-File -Encoding utf8 tester.js

ワンライナーにしちゃうとこちらはしんどいですね…。素直に書いたソースは:

var ffi = require('ffi-napi')
var ref = require('ref-napi')
var s = ref.types.CString
var nyanko = ffi.Library( 'nyanko.dll',{ 'f': [ s, [] ] } )
console.log( nyanko.f() )

です😏

Node.js で tester.js を実行して node-ffi-napi / node-ref-napi が期待動作しネイティブライブラリーの nyanko.dll から "にゃおーん" が無事に返り表示されるはずです:

node tester.js
にゃおーん

成功しました👍

コンパクト化したコマンドライン

ついでに npm -> yarn 化。

# テスト用のディレクトリーと npm init していない場合はここから
mkdir myapp
cd myapp
yarn init -y
# ffi-napi, ref-napi を追加
yarn add ffi-napi ref-napi
# テスト用の native dll を作成
echo '#[no_mangle] pub extern fn f() -> * const u8 { "にゃおーん".as_ptr() }' > nyanko.utf16.rs
Get-Content nyanko.utf16.rs | Out-File -Encoding utf8 nyanko.rs
rustc --crate-type cdylib nyanko.rs
# テスト用の .js を作成
echo "console.log( require('ffi-napi').Library( 'nyanko.dll',{ 'f': [ require('ref-napi').types.CString, [] ] } ).f() )" > tester.utf16.js
Get-Content tester.utf16.js | Out-File -Encoding utf8 tester.js
# 動作確認
node tester.js
にゃおーん

参考

さいきん試した Rust の GUI Toolkit 的な crate たちと日本語アプリでの実用性のメモ

現時点ではほぼダメです。試した中では唯一 conrod だけ日本語アプリを作る実用に耐えられそうです。

crate 日本語表示 日本語入力 コピペ UI部品の見栄え その他
conrod ○TTF可 ◎自然にできる ◎自然にできる ∞ 作り込み次第 vulkan対応で軽快, GL版だともっさり気味
druid ◎システム可、TTF可 ✘無理 △事実上無理 △ぼちぼち フォント回りや2Dドロー回りはたぶん界隈では最強
OrbTk ○TTF可 ✘無理 ✘無理 ○まあまあ 開発は活発なので続けばよくなるかも
azul ○システム可 ✘無理 ✘無理 △ぼちぼち exampleにも動作しない機能、壊れた機能が多い。開発が不活性化していて事実上終了かも

日本語表示の(システム可)はシステムフォントを名前で指定すれば使えるものです。使えないものはフォントファイルをバイナリーで直接ロードする仕組みになっています。

conrod はもともとゲーム開発向けなせいかデフォルトの UI 部品の見栄え的にはとてもしょぼいです。一般的にゲームではUI部品の絵から作り込むため、デフォルトでリッチな見栄えのUI部品を実装するモチベーションは低いのだろうと思います。また、使う場合は vulkan 版が前提になると思います。 GL 版はハイエンド環境でも動作がもっそりめで体感で30FPSでてるか怪しい状態でした。 vulkan 版はとても軽快に動作し、60FPS基準のゲームでも作り込めそうです。

druid は開発のなかのひとがフォント系に強く、 GUI Toolkit として完成度の高いフォント回りの実装を依存 crate 群と併せて実現できています。特別にフォントを設定しなくてもOSのフォントからフォールバックも含め使用できるため、他のライブラリーと違い何もしなくても日本語環境で実行すれば日本語も表示できます。ただし、キーコードで直接打てる以外のテキスト処理の実装状況はまだまだで、日本語入力する手段がコピペを含めてありません。コピペの実装もいまのところ独特な仕様で example の多くのライブラリー内蔵の AppLauncher を介した実行形態ではアプリの内部構造の内側でのみコピー&ペーストできる状態です。アプリの外とクリップボードを介してコピペ…できそうなPRはmergeされていましたが、 example の多くの AppLauncher を介した実行形態で使用できる状態になるのはまだ先の様子です。他の実行形態として druid-shell と呼ばれている実行形態と少量の example もありますが、このモードでは druid のほとんどの GUI 部品を使用できません。 開発はアクティブで、PRの対応もフレンドリー、ソースコードも綺麗で読みやすい方と思いましたので、 Authors のモチベーションが半年か1年か続けば化ける気はします。

OrbTk も開発のアクティビティーは良好で、ロゴデザインや UI 部品の意匠など良質な GUI Toolkit に育つかも…という期待はありますが、日本語入力やコピペはまだできず、こちらもあと1年くらい Authors のモチベーションが続けば…という気配です。

azul は今回検討対象を列挙した段階ではアーキテクチャーなど含め最良の選択肢の可能性を感じたものの…実際に試してみると未成熟というか…壊れてるというか…。 Authors のモチベーションまたは作業時間が既にほぼ無くなってしまっている気配が感じられるので、 fork が発展または Authors がヤルキを漲らせる様子が観測されなければこのまま錆びてしまうかも知れません。

ほか

今回の調査では非OSSなお仕事アプリでも使いやすい MIT, BSD系のライセンスに限り、Gtk, Qt のバインディングは除外しました。ライセンスに問題が無ければ、特にOSSでは素直に Gtk, Qt のバインディングを試すのが現状の開発途上な他のライブラリーに比べると圧倒的に苦労が少ないような気はします。

また、 Android 向けを主軸に iOSWindows, OSX などのクロスプラットフォームに対応した flutter のバインディング flutter-rs も試そうとしましたが、日常的に Android, flutter での開発に触れ Dart もそこそこ現役で使えるマンじゃないと使用は難しそうです。少なくとも私は少々遊んだ程度では flutter のエコシステムをゼロから理解して最初のビルドが完了できるまでには至りませんでした。

ちなみに

アプリの生産性と実用性(ユーザー視点でのUIへのとっつきやすさ、ユーザーがUIへ要望する事の実現のし安さなど)という点では、 バックエンドに Rust を採用するにしても、一般的なアプリケーションを非OSSで開発する場合にエンドユーザーが触る部分の GUI としてのフロントエンド部分は Rust ではないなにかで開発し、バックエンド部分の Rust とはマーシャリングする構成がよいのではないかと思います。少なくとも現状で半年や1年以内にリリースするアプリを作りたいのなら。

GUIフロントエンド部分にボタンやテーブルやメニューのような一般的なビジネスアプリ的なUI部品が不要な場合は conrod でもいいでしょうし、 UE4 や Unity でも、あるいは C++ で Siv3D とかも良いかもしれません。

一般的なビジネスアプリ的なUI部品でまとめれば良い場合は、 electron 系と組み合わせてもいいでしょうし、JVM 系のテクノロジーと組み合わせ、あるいはプラットフォーム次第では .net core WPF 系も良い事もあるかもしれません。

一般的なビジネスアプリ的なUI部品も欲しいし、GPUレンダリングも欲しい場合は…どうしましょうね。 electron 系と組み合わせると GPU レンダー部分を WebGL2 や Three.js で制限されたり、描画コンテキストとUI配置の仕組みで苦労するかもしれません。WebGL制約を受けたくなければバックエンド側でオフラインレンダリングしてフロントエンド側へテクスチャーとして渡すようなトリッキーでオーバーヘッドの心配な方法が必要になるかもしれません。GPUレンダリングパワーの需要が大きい場合はフロントエンド部分をUE4やUnityと組み合わせ、3Dコンテキスト系のUI部品でも顧客が本当にほしかったアプリのUIを実現するのが現実的かもしれません。その場合はウィンドウの上の方のメニューと下の方のステータスバーのようなUIもUE4やUnityで作れないわけではありませんから…。Excelっぽいやつ出してとかは…もうそうなったら素直に別プロセスでQtで作ってIPCとかで…いいんじゃないですかね…😭

ある日とつぜんWSL2が起動しなくなったメモ

きょうもいちにち。Windows Terminalを起動…しない。正確にはメインウィンドウを出そうとする辺りまでは起動はしているようだけど、一瞬で消えてしまうので実質起動しない。

とりあえず cmdwsl る:

f:id:USAGI-WRP:20200317074659p:plain

WSL 2 requires an update to its kernel component. For information please visit https://aka.ms/wsl2kernel

f:id:USAGI-WRP:20200317075210p:plain

と、いうわけで「このリンク」とやらを踏み、

f:id:USAGI-WRP:20200317075250p:plain

"Windows Subsystem for Linux Update Setup" を install する。よくわからないが一瞬で終わる。

f:id:USAGI-WRP:20200317075431p:plain

なんか知らんけど(†1) wsl が動くようになり、

f:id:USAGI-WRP:20200317075911p:plain

Windows Terminal も起動するようになりました。

Microsoftのエラー時に示されるリンクが有用だっただけでも感動できる素晴らしいUX体験ですね。もちろん嫌味です。

参考

VSCode の extension にコマンドを追加する時に使わない方がよい文字のメモ

"category"_ (アンダースコア文字) を入れてしまうと、実際に使う時にコマンドの絞り込みが期待動作しなくなって悲しい。

例: category を hoge_fuga として description を puyopuyo にすると…:

  • CTRL+SHIFT+P して >hgp とか >gapu とか入れてもコマンドが見つからなくなる
  • hoge_fuga を最初から入れれば出てくるけれど、完全に入力したり、そもそもコマンドで _ を省略せずに打鍵するのは高コストなので不便になる

という知見を得たのでメモを残しました。

category = hoge-fuga だと >hf のように - を省略してもコマンドの絞り込みから外れないので便利を維持できる。

  • - のほか、 . / # は同様に省略しても絞り込みで外れない区切り記号として使用できる

屋内撮影の照明のON/OFFに手スイッチ操作するよりOK,Googleできたら便利かなーって、スマート電球…ではなくてスマートプラグのやすいの買ってみたのです。のメモ

音声を出すのエネルギー使うにめんどくさいって思っていたのですが、すんごい便利でした…。

もの

買ってみたもの → VStarcam WIFIスマートプラグ スマートコンセント

お値段 = 1,499 円 (執筆時点; keepa価格推移↓)

f:id:USAGI-WRP:20200311204245p:plain

届いたもの↓

f:id:USAGI-WRP:20200311200739j:plainf:id:USAGI-WRP:20200311200556j:plainf:id:USAGI-WRP:20200311200546j:plain

専用アプリ tuya smart life と Google Home

箱や取扱説明書は紙質もよく日本語で表示されていますが、メーカー不明、その他いろいろ不明状態。取扱説明書もけっこーゆるふわ。たぶん技師属性持ちじゃないと扱えないかも。技師属性もちの人はたぶん簡単に扱えます。

懸念点として、専用アプリが .apk ぽん置きページへの誘導になっている事。箱や取扱説明書の QR を読むと Google Play とか Apple のそれじゃない謎のメーカーかどこか(ユーザーには箱や取扱説明書からはわからない…)の .apk ぽん置きウェブサイトへ飛びます。

飛びますのですが、ここでメーカーらしきところが "tuya" っぽい事がわかるので、野良 .apk はいやだーという事で Google Play で検索したらありました🙆‍♀️

と、いうわけで、

  1. tuya の smart life アプリを Google Play からインストールし、
  2. 取扱説明書に従ってスマートプラグの電源ボタンを5秒押し、
  3. アプリ右上のデバイスを追加するっぽいボタン → Auto Scan
  4. 設置場所の WiFi ネットワークの AP の接続情報を設定 (こわい<便利)
  5. スマートプラグに名前を付けて保存

するとアプリで on/off できるようになります。すごいべんり。応答もはやい。(LED電球とか繋ぐ照明も応答がはやい場合)

さらに、 Google の Home アプリをこの状態で起動すると自動的にデバイスを発見して画面の上の方に表示してくれています。表示をぽちって登録すると、

  • "OK,Google. (付けた名前) on"
  • "OK,Google. (付けた名前) off"

とかで音声操作できるようになります。べんり。 Google Home 経由だと応答はちょっともさる。音声認識からの応答としてはすごいはやいけどね。

ちなみに、スマートプラグに付ける名前を "light" とかにしておくと、 Google Home が照明らしい事を勝手に忖度してくれるようになり、

  • 「おーけーぐっぐぅ、あかりつけて」
  • 「おーけーぐっぐぅ、でんきつけて」

みたいな呼びかけにも期待動作してくれるようになります。

…すごい便利…。