お知らせ

(本サイトは、アフィリエイト広告を利用しています)

Fitbit Versa 4でSwitchBotを制御する Web APIでトラッカーによる充実スマートホーム体験!?

2024年7月2日IoT・スマートホーム

Fitbit Versa 4を購入しました。

もともとスマホはGoogle Pixel。この度、最新のPixel 8aをGoogle Storeで購入したのですが、その際に2万円のクーポン(ポイント)が付いてきました。

とはいえ、Google Storeのクーポンは正直、もらっても困る系のポイントです。他で使えないし、Google Storeで購入できる商品だと2万円というお値段も微妙に使いにくいのです。

そんな折、Google Storeで筆者がちょっと気になっていたスマートトラッカーのFitbitが割引になりました。いくつかモデルのある中で、高度もわかるセンサー付きということでVersa 4というモデルが7千円引き。27,800円の7千円引きなので800円出せば、そこそこ上位モデルのスマートトラッカーが購入できるというわけです。

それならと、早速購入したという流れです。

Google Storeの公式サイトより転載 (Fitbit Versa 4)

ところで、Fitbit Versa 4を購入した後に知ったのですが、実はFitbitってSDKが公開されています。

知りませんでした。早速プログラミングしてみようではありませんか。

Fitbitの開発環境

Fitbitの開発は、JavaScriptかTypeScriptで行ないます。

使うツールは、npm(Node package manager)。昨今のプログラマーが使うツールとしてはおなじみのコマンドです。

エミュレータを使っての開発も可能です。エミュレータはWindows向けとMacos向けの両方が用意されていて無料でダウンロード可能。これだけで、あの小さな腕時計にむけたアプリの開発ができるとは、なかなかの充実具合です。

アプリのスケルトンも、以下のコマンド一発でできます。my-first-clockというディレクトリを作成し、その中に必要なファイルを配置してくれるものです。

npx create-fitbit-app my-first-clock

ビルドは、npmによってインストールされたfitbitというコマンドを使います。

npx fitbit

npx fitbitコマンドを実行すると、コマンドラインプロンプトがfitbit$に変わり、ビルドやインストールのコマンドが利用できます。

エミュレータか、本物のFitbitで実行するのかの選択も、このコマンドラインのツールによって表示されるメニューにより切り替えることができます。

などなど、非常に親切にできたツール群を使って、あなたも今日から開発が始められますよ!

プログラミングに使用する開発言語は、JavaScriptです。ですので、基本的なJavaScriptの開発経験がある開発者であれば非常にとっつきやすい感じになっています。使用可能なAPIも標準的なものは、W3Cなどの標準に準拠しています。したがって、JavaScriptに詳しい方であれば学習コストがかなり低く済みます。

Fitbitアプリのアーキテクチャ

Fitbit OS上のアプリの実行環境はすこし特殊です。Fitbit本体のプログラムと、スマホで動作するプログラムをセットで開発しなければならないのです。

これはたぶん、Fitbitデバイスがネットに直接つながらないというところが理由でしょう。

単体でネットにつながりませんが、Bluetoothでスマホとはつながります。したがって、もしネットにつなげてデータを操作するようなアプリをつくるためには、デバイスで動作するプログラムと、スマホで動作するプログラムを通信させてスマホからネット上のサーバーを呼び出す必要があるわけです。

そのため、ソースコードのディレクトリ内部にはサブディレクトリとして、appとcompanionの2つがあります。appはデバイス上で動作するコードを格納するディレクトリ、companionはスマホ上で動作するコードを格納するディレクトリです。どちらのコードもJavaScriptで記述します。

ということは、推測するにJSのエンジンがデバイスとスマホの両方に存在するということです。

FitbitデバイスのJSエンジンはプラットフォームとして搭載されているのでしょう。一方、スマホのJSエンジンはGoogle Storeからインストールする「Fitbitアプリ」が担っているようです。

デバイス上のアプリが実行されると、companionのコードが自動でロードされるという仕組みになっているようです。起き上がった、companionのコードは、Fitbitで動作するappのコードと、Messaging APIという仕組みでやり取りできます。

Messaging APIは、WebSocketというスタンダードのインターフェースのサブセットとなっており、addEventListner()といったJavaScriptではお馴染みの形式で定義されています。

なんとわかりやすのでしょう!

ところで、Fitbitアプリには2つのタイプがあります。

  • Clockface
  • 通常のApp

Clockfaceはいわゆる、時計の文字盤表示するためのアプリです。Fitbitトラッカーを使っていて腕を顔の方に向けた時に表示される画面を構築するアプリです。

通常のAppはFitbitのアプリ一覧に表示されて、ユーザーが選択して実行するようなアプリです。

2つのタイプのアプリはどちらも同じ技術で開発します。ロジックはJavaScript(or TypeScript)で、画面の構成要素はSVGやCSSといったWebの標準的な技術を使っています。(ただし、SVGやCSSのパラメータなどは独自に定義されたものです)

Versa 4は新しすぎたのか 非公式な開発手法が必要

喜び勇んで開発環境を入手した筆者は、まずはエミュレータを使ってサンプルを動作させてみました。

しかしここで、行き詰まります。

肝心の実際のトラッカーVersa 4に転送できないのです。色々と調べてみたところ、Versa 4は新しすぎてSDKやエミュレータの準備が整っていないようです。

さらに調査を進めると、捨てる神あれば拾う神あり。Versa 4の非公式アプリ開発の情報を提供してくれている方がいるではありませんか。

以下のGithubリポジトリに、Versa 4向けのサンプルアプリが公開されています。

自分でアプリを構築した場合は、上記のリポジトリのpackage.jsonの"devDependencies"と"fitbit > buildTargets"を参考に書き換えれば良いようです。

が、残念ながらエミュレーターはVersa4対応がなされていないようでした。

したがって、筆者の場合は前述の「npx create-fitbit-app」ツールでプロジェクトを作り、エミュレータである程度のアプリコードを開発。最終的にVersa4の実機で動作させる場合は、package.jsonの該当箇所を書き換えて必要なモジュールをインストールしなおすという技(!?)を編み出しました。

「SwitchBotアプリ」開発のために

サンプルアプリを実行しているだけだと面白みにかけます。

筆者の推し活「SwitchBot Web API」を使ったアプリを作ってみたくなりました。

ほんとにそんなことができるのだろうか?とFitbit SDKのリファレンスマニュアルを見ます。JavaScriptなので当然JSONの扱いはできるものの、SwitchBotのWeb APIを呼び出す際の認証に関する機能があるかどうかがポイントでした。

で、見てみると、ありました。Crypto API。これに関しては後ほど詳しく述べます。

ちなみに、ネットワークへのアクセスはどうするのだろうと思って調べてみると、最近のブラウザのAPI に標準的に搭載されているFetch APIが用意されています。

Companion用のAPIなのでスマホからSwitchBot Web APIを呼び出すことになりそうです。

つくるものはこんなものです。

操作画面は以下のエミュレータのスクリーンショットを御覧ください。

Fitbitトラッカー上でSwitchBotの機器を制御する(エミュレータ画面)

筆者の自宅はSwtichBotでスマート化(!)していますので、SwitchBot ハブ2という機器があります。この機器は赤外線の発信器になっており、Web API経由で赤外線リモコンのコードを送信することができます。Amazonで売られている以下のような製品です。

SwitchBotハブ2に関しては、より詳細な記事を別に書いています。こちらも併せてご覧頂くと、より理解が深まります↓

一方、この暑い夏。リビングでは扇風機が大活躍。

幸い筆者の扇風機は赤外線リモコン制御が可能です。扇風機には以下の写真のような小さなリモコンが付属されており、離れたところからも扇風機の操作ができる便利なシロモノです。

ということは、なんと、SwitchBotハブ2とリモコン対応扇風機の2つを組み合わせると、SwitchBot Web APIを使って、リモコン以外の機器から扇風機の遠隔操作ができるのです。

筆者所有の扇風機は赤外線リモコンで操作が可能

SwitchBot ハブ2とWeb APIを使って赤外線リモコンの制御をする記事は別に書いています。こちらの記事↓では、Web APIで赤外線リモコン機器を制御する方法を少し詳しく説明しています。合わせて御覧ください。

今回作るFitbitアプリは、画面に3つボタンが表示されるシンプルなものです。電源ボタン、ファンのスピード切り替え、および、首振りの切り替えの3つです。

それらを押すと、扇風機が反応する、というわかりやすいアプリです。

Fitbitアプリのボタン(SwitchBotから操作する扇風機に対応)

ちなみに、このアプリ。後述のようにソースコードをGithubにて公開しています。

ただし、操作する機器も固定ですし、SwitchBotアカウントの筆者のものを固定的に使っています。汎用的にSwitchBot機器の全てに対応しているようなアプリではないので、ご注意下さい。

Fitbit用「SwitchBotアプリ」の仕組み

せっかくここは筆者テック大家さんのブログです。技術背景を深堀りしないとテックブログになりませんね。

というわけで、少し上記のFitbit SDKのアーキテクチャの状況も踏まえて、筆者のFitbitアプリが動作するための仕組み、全体像をここで説明しましょう。

Fitbit トラカー上のアプリで電源ボタンを押すと…

上の絵を見て下さい。

腕にFitbitトラッカーを着けた筆者が、眼の前にある扇風機の電源を入れるために必要となる登場人物たちです。

ぱっとみ、複雑ですね(笑)。

番号順に説明しましょう。

1で筆者が作ったFitbit上のアプリを操作します。この場合は電源アイコンを押します。

すると筆者のアプリ([app]ディレクトリに入れたJavaScriptコード)は、スマホ上のコード([companion]ディレクトリに入れたJavaScriptコード)にMessage API経由でメッセージを送ります。それが2番です。

3番目では、SwitchBotのWeb APIを呼び出します。このコードは、[companion]ディレクトリのコードになります。なぜなら、Fitbit本体ではネットワーク通信ができないからです。

4番目は、SwitchBotクラウドと筆者の家の室内にあるSwitchBotハブ2との通信になります。ここは公開された通信規格ではなく、SwitchBotが勝手にやってくれる部分です。

Web APIを呼び出した結果として、5番目の動作が発生します。それは、SwtichBotハブ2が赤外線の信号を発することです。この赤外線コードは、あらかじめSwitchBotアプリで設定しておくものです。

赤外線信号に応答する形で、扇風機の電源が入ります。

SwitchBot Web API に必須 Crypto API

さて、今回のアプリを実装するうえでキモとなったのは、SwitchBotのWeb APIを呼び出す際の認証(Authentication)です。

簡単にSwitchBot Web APIの認証の仕組みを説明しておきます。APIの仕様書に説明があるように、Web API経由でSwitchBot機器を操作するためには、どのユーザの機器を制御するのかを指定するために「認証」が必要になります。認証に必要な情報としては、SwitchBotアプリで開発者用メニューを表示させて、token とsecretという情報の「組」をあらかじめ入手しておく必要があります。

そして、token とsecretから暗号化されたsignを生成して、なにかサーバーと通信が必要な場合には、毎回HTTPSプロトコルのヘッダにsign付けてAPIをコールするという仕組みになっています。

signをつくるコードは、上記のAPI仕様書のAuthenticationの章にポピュラーな言語ごとに用意されています。

Fitbitが使うJavaScriptの場合、同ページに親切にコードが用意されているのですが、問題はそれがサーバーサイド用JavaScriptつまりNodejsのCrypto APIを使っているところです。NodejsのCrypto APIはFitbitのCrypto APIとは異なる形式です。

なので別のAPIで同等のsignを生成するコードを作らねばなりませんでした。以下に実装コードの抜粋(関数)を掲載します。

// 非同期でbase64形式のsignatureを生成する
async function generateSignature(token, secret, t, nonce) {
  const data = token + t + nonce;

  // シークレットからキーを生成
  const keyMaterial = await Crypto.subtle.importKey(
    "raw",
    str2arrayBuffer(secret),
    { name: "HMAC", hash: "SHA-256" },
    false,
    ["sign"]
  );

  // HMACを計算
  const signature = await Crypto.subtle.sign(
    "HMAC",
    keyMaterial,
    str2arrayBuffer(data)
  );

  // Base64エンコーディング
  return arrayBufferToBase64(signature);
}

ちなみに、FitbitのCrypto APIはW3Cで定義されてCryptography APIと互換性があるようです。

ここで筆者がハマったポイントを一つご紹介します。

筆者のアプリ開発時点では、Fitbit公式のReference manualによると、Crypto APIはCompanion APIとして記載されていました。Companion APIはスマホ側で動作するコード([companion]ディレクトリのコード)から使うものです。

しかし、実際には、CompanionではこのAPIの呼び出しはできませんでした。なぜ呼び出せないのか原因究明に時間を有しました。

そこで、ネットを調べてみたところ、FitbitのCrypto APIリリース時のリリースノートにDevice APIとして紹介されてることに気づきます。そうなのです、このAPIはDevice 側([app]ディレクトリのコード)からしかアクセスできないようなのです。誤植(?)により無駄な時間を費やしてしまいました。

全ソースコード

ということで作ったアプリの全ソースコードをGithubで公開します。

前述のように、機器は固定ですし、token, secretは固定的に埋め込む必要があります。ですので、ソースコードは「こうやればSwitchBot機器を操作するアプリが作れる、というサンプル」としてご覧いただけると幸いです。はい。

さらに、免責事項というか…

ちなみに、このアプリ。Unofficial なSDKや仕組みを使ってはいますが、一応動作はします。

ただし、Androidスマホの仕組みの問題なのでしょう。スマホをロックしてしばらく放置しておくとFitbitアプリからボタンをおしても扇風機が反応しなくなります。

どうも、Fitbitアプリの動作がAndroid OSにより制限されているようです。スマホロックを解除すると、動作します。一旦解除すると、ロックしてもしばらくは動作します。

たぶん、電池セーブのためでしょう。Fitbitアプリのバックグラウンドの処理が制限され遅れて実行されているように見えます。なぜなら、ロックした状態でFitbitアプリのボタンを数回押すと、ロック解除のタイミングで複数回赤外線コマンドが送られて、扇風機がピーピー・ピーピーと複数鳴るからです。

こればかりはどうしようもないのか?

それとも、なにかAndroid設定でなにか対策できるのか…

今のところ、残念ながら思っていたような使用感でFitbit アプリは動いてくれませんね。

メールマガジンにて本サイト(Tech Landlordテック大家さん)の更新情報をご連絡します。
本サイトのプライバシーポリシーをご確認の上、是非メールアドレスをご登録下さい!


プロフィール

テック大家さん
ソフトエンジニア兼不動産オーナー。
某超有名日本メーカーにおいてソフトウエア開発畑を30年近く勤務。
かつてはWindowsのアプリ開発や、組み込み機器のソフト開発を行う。プロジェクトマネジメント・オフショア開発・要件管理などの経験あり。現在は、個人開発で、JavaScript/TypeScript/React/Express、PHP/Laravel、Firebase、Google cloud、Arduino(C++)などでプログラミングを楽しむ。
サラリーマンの傍ら不動産経営を始め、現在、1棟モノの賃貸4物件を東京・神奈川に所有。夫婦でおよそ20年の賃貸経営の実績。
最近の物件では、入居者向けフリーWiFiなど、テック系の設備はDIYで自ら構築。
海外MBA取得。