お知らせ

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

SwitchBot BLE API で機器にBluetoothで直接コマンドを送る ESP32でスマートホームをもっと便利に

IoT・スマートホーム

以前、このブログ「テック大家さん」にて、公開されているBLE (Bluetooth Low Energy)のプロトコルでSwitchBot機器から直接データを取得する方法について解説しました。

以下の記事に詳しく書かれています。

本日の記事はその続編です。

以前書いた記事では、BLEのアドバタイズパケットに載っているSwtichBot製品のセンサーの値を読み取る方法について書いていました。続編としては、BLEのGATT通信についてより詳細に解説していきます。

SwitchBot製品群と公開APIについて「おさらい」

SwitchBotは、スマートホームを手軽に実現するためのIoT (Internet of Things)製品群のブランド名です。電球やスイッチ、温度計や人感センサーなどの製品があり、全てスマホで操作できる製品です。

こういったスマート家電商品はいくつものメーカーから販売されていますが、SwitchBotの良いところはプログラマーが独自の機能を実現できるよう、API(Application Programming Interface)が公開されている点です。

ソフト開発大好きな、テック大家さんとしてはSwitchBotのこの点が気に入っています。推しの理由に関しては以下の記事に詳しく書いておりますので、合わせてご覧いただけると幸いです。

公開されているAPI情報は2つ。Web APIと今回説明するBLE APIです。以前の記事でも説明しているのですが、この2つのAPIの関係は下図のようになっています。

SwitchBot Web APIとBLE APIの関係

つまり、SwitchBotクラウド経由で操作する、例えば、家の外からでも操作が必要な場合はWeb APIを使い、室内でレスポンスよく操作する場合はBLEを使う、というイメージです。

BLE GATT通信の仕組み

SwtichBotのおさらいができたところで、BLEに話を戻します。

SwitchBotのBLE APIを使うには、Bluetooth Low Energyの規格の一部である。GATT通信について基本的な理解が必要になります。

BLEで通信する場合、規格上は機器のどちらかがセントラル(クライアント)になり、どちらかがペリフェラル(サーバー)になる必要があります。

SwitchBot BLE API の前提としては、SwtichBot機器はペリフェラルになります。したがって、筆者が作るプログラムはセントラルの機器、ということになるわけです。言い方を変えると、SwitchBot が公開しているBLE APIはペリフェラル、つまりサーバー側のAPI仕様ということになります。

公開されている仕様はGithubにありまして、全て英語なのではありますが、以下のリンクから参照することが出来ます。

ただし、率直に言って、この資料はとにかくわかりにくいです。APIというよりはプロトコル仕様なのですが、被筆者は当初、この資料のByte 0 がどこのパケットの先頭の話をしているのか理解できませんでした。英語だからということではないと思います。筆者自身がBLEにそれほど精通していないせいもあるかも知れません。が、正直、不親切な説明に感じました。

ちなみに、上記の仕様では、ペリフェラルを「Device」、セントラルを「Terminal」と呼んでいます。資料(英語)を読むときは本記事の説明を読み替えて下さい。

さて、SwtichBot機器と通信をするには、BLEのGATT通信という仕組みを理解している必要があります。

BLEの規格では、GATTのサーバーは以下のような構造でコマンドを体系化することになっています。

つまり、ペリフェラルは「サービス」(Service)という概念で括られる機能を有しており、「サービス」というグループの中に個々の機能「キャラクタリスティック」(Characteristic)を搭載している、というモデルです。

実際にコマンドを送ったり、値を取得する際にはペリフェラルの「キャラクタリスティック」を指定してやり取りすることになります。

したがって実際の通信は、

  1. 機器を見つける
  2. 機器に「コネクト」(接続)する
  3. 機器の「サービス」を見つける
  4. 機器の「キャラクタリスティック」を見つける

という一連の操作を行った上で、キャラクタリスティックに対してコマンドのWrite(書き込み)を行うことで通信が成立します。以下で説明する、実際のプログラミングでもこのような手続きを踏むことになります。

サービスとキャラクタリスティックには、それぞれ固有のUUIDが付けるのがBLE GATTの規定です。これに従い、SwitchBotの API仕様書にはそれぞれの機器に応じてUUIDが書かれています。実際にSwitchBotの機器を呼び出す際は、これ使ってアクセスするというわけです。

ESP32 の Arduino BLEライブラリ

実際にBLEを通信を使ってSwtichBot製品を制御するセントラル(クライアント)を作ってみましょう。

使用するのはESP32系のチップが搭載されているM5 Atom S3U という機器です。

写真では大きく見えますが、親指ほどの小さな機器です。小さくてもESP32が搭載されており、これによりBLE通信が可能です。

小さな筐体にボタンもついているし、フルカラーのLEDもついているので、ユーザーインターフェースもバッチリです。Amazonには売っていないようですが、ディスプレイが付いた類似品などM5の機器で動作するはずです。

この機器にArduinoの BLEライブラリ (C++)を使ってコードを書くことにします。

BLEライブラリは、Platform IOでespressif32のプラットフォームをインストールするとBLEというライブラリが入るのですが、筆者が使った時点ではどうもうまく動作しませんでした。

そこで、nkolbanという方が作っているバージョンを試しました。以下に置き換えの方法が書かれています。

若干手間はかかります。

手順としては、https://github.com/nkolban/esp32-snippets.gitをcloneしてきて、ビルドしてできるESP32_BLE.zipというライブラリを使います。Platform IOがインストールするBLEライブラリをまるっと入れ替えるという作業です。

このライブラリは、上述のBLE GATT通信の論理的な構造をうまく抽象化したクラス構成になっています。以下にライブラリの構造の一部をクラス図にしてみました。かなり端折って単純化しています。

Arudino ESP32 BLE ライブラリのクラス図(一部)

クラス名は、プレフィックスの"BLE"を除いた名前を書いているので本物とちょっと異なりますのでご注意を。

これを見てわかるように、BLEDeviceクラスからcreateClient()によりクライアント(つまり、セントラル)用のBLEClientクラスのインスタンスを生成します。ここで、BLEClientに対してconnect()を呼ぶと相手のデバイス(=SwitchBot機器)と通信を開始します。

BLEClientには、getService()という関数があり、サービスのUUIDを指定して呼び出すことによりBLEServiceインスタンスを取得。BLEServiceにはgetCharacteristic()という関数があるので、これも同様にキャラクタリスティックのUUID指定で、BLECharacteristicのインスタンスを取り出します。

BLECharacteristicクラスにはメンバーとしてwirte()、read()の関数があります。このwrite()関数を使うと該当キャラクタリスティックを持つSwitchBot機器の操作ができるというわけです。

SwitchBot機器へBLEコマンドを送る(例: スマート電球)

では具体的に、BLECharacteristic::write()に送るコマンド(データ)はどのような形式になるのでしょうか。

それが、SwitchBot BLE APIとして公開されているサイトに書かれている仕様を参考にする部分です。

ここでは実例として、スマート電球のオフ・オンをするケースを考えます。スマート電球は、仕様書では”ColorBubble”と呼んでいます。

この仕様には、以下のようにあります。

SwitchBot BLE APIのColorBubbleのページから転載

BLECharacteristicクラスのwrite関数の形式は具体的には以下のようになっています。

bool writeValue(uint8_t* data, size_t length, bool response = false);

引数にはデータの配列の先頭アドレス(data)と長さ(length)を指定します。

この関数に送るべきデータは、SwitchBotの仕様の上の表にあるREQ Packet NO encriptionのByte 0からのデータです。(この表の読み方も結構ややこしい…)

以下は電源オンとオフを行うコード(抜粋)です。(最終行にあるsendValue()関数に渡しているパラメータがBLECharacteristic::writeValue()に渡る値です)

オンするときは、writeValueに書き込むデータは、0x57を先頭に、上記表の"Turn On Bulb"の列に書かれたコードを書きます(Byte:2まで)。

同様に、オフにするときは、0x57を先頭に、上記表の"Turn Off Bulb"の列に書かれたコードを書きます(Byte:2まで)。

(上の表とコードをジッと見比べてみると意味がわかるのではないでしょうか)

  bool setEnabled(boolean onOrOff)
  {
    uint8_t writeDataOn[] = {0x57, 0x0f, 0x47, 0x01, 0x01};
    uint8_t writeDataOff[] = {0x57, 0x0f, 0x47, 0x01, 0x02};

    uint8_t *pWriteData = onOrOff ? writeDataOn : writeDataOff;
    size_t writeLen = onOrOff ? (sizeof(writeDataOn) / sizeof(writeDataOn[0])) : (sizeof(writeDataOff) / sizeof(writeDataOff[0]));
    return sendValue(pWriteData, writeLen);
  }

SwitchBot BLEを呼び出すサンプルコード

執筆時点では、全体のコードはちょっとまだ完全に整理できておらず、残念ながらそのまま公開状態ではありません。別途公開したい考えていますので、お楽しみに!

ですが、それだとちょっと物足りないので、BLEライブラリでSwitchBotを操作する部分のコード(クラス)のみを公開します。ご興味があれば参考にしてみて下さい。

どのSwitchBot機器にも共通に使える基底クラスを作りました。

ヘッダ(SwitchBotBaseDevice.h)です(ファイル全体を表示するには、ファイル名のリンクをクリックして下さい)

その実装(SwitchBotBaseDevice.cpp)です。(ファイル全体を表示するには、ファイル名のリンクをクリックして下さい)

個々のSwitchBot機器に対する実装は来てクラスから派生して実装します。例えば、ColorBubble用のクラスなら以下のようなコードです。(ファイル全体を表示するには、ファイル名のリンクをクリックして下さい)

というわけで、最後は少し駆け足になりましたが、ESP32でSwitchBotをBLEで制御する方法論について解説しました。今日はここまで〜。

created by Rinker
Generic
¥3,800(2024/10/14 17:32:14時点 Amazon調べ-詳細)
SwitchBot スマートプラグ プラグミニ スマートコンセント スイッチボット 消費電力モニター タイマー コンセント 節電·省エネ 直差し 遠隔操作 音声コントロール Bluetooth&Wi-Fi両方対応 スマートホーム Alexa, Google Home, Siri, IFTTT, SmartThings対応
スイッチボット(SwitchBot)
メールマガジンにて本サイト(Tech Landlordテック大家さん)の更新情報をご連絡します。
本サイトのプライバシーポリシーをご確認の上、是非メールアドレスをご登録下さい!


プロフィール

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