プログラミング

SwitchBotの温湿度計、防水かどうかでBluetoothのデータの取り方違うぞ

投稿日:

SwitchBotは機器のAPIを公開していて、ユーザーの自作プログラムからBluetooth(BLE)越しにデータが取れたりします。
特に温湿度計のデータを取りたいというニーズは強くて、安価で安定していてバッテリーの持ちが良いということで重宝されてます。

さて、通常の温湿度計については、以下のようなコード(M5 Stack想定)でデータが取れるんですが。かなり省略したので詳しくは先人の知恵を参照ください。
batteryとtemperatureとhumidityに値が入ります。

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

/* グローバル変数宣言 */
BLEScan *pBLEScan;
static const String TargetMacAddr = "ab:cd:ef:01:23:45";

/* 初期化処理内 */
pBLEScan = BLEDevice::getScan();
pBLEScan->setInterval(1000);
pBLEScan->setWindow(1000);
pBLEScan->setActiveScan(true);

/* ループ内 */
BLEScanResults foundDevices = pBLEScan->start(1, false);
uint32_t dev_count = foundDevices.getCount();
for (uint32_t iDevNo = 0; iDevNo < dev_count; iDevNo++)
{
  BLEAdvertisedDevice device = foundDevices.getDevice(iDevNo);
  BLEAddress address = device.getAddress();
  if (TargetMacAddr.compareTo(address.toString().c_str()) == 0)
  {
    std::string s = device.getServiceData();
    const char* data = s.c_str();
    int8_t battery = data[2] & 0b01111111;
    bool tempSign = data[4] & 0b10000000;
    float temperature = ( data[3] & 0b00001111 ) / 10.0 + ( data[4] & 0b01111111 );
    if (!tempSign)
    {
      temperature *= -1;
    }
    float humidity = (float)((int8_t)(data[5] & 0b01111111) * 1.0);
  }
}

防水温湿度計はデータの配置が変わってまして、元々はService Dataだけで全部取れていたものが、Manufacturer Specific Dataも取らないといけなくなってます。
詳しくはAPIの公式ドキュメントにありますが、
Manufacturer Specific Dataの10,11,12バイト目にデータが動いています。
上記のコードでいうとif文内を以下のように書き換える必要があります。

  if (TargetMacAddr.compareTo(address.toString().c_str()) == 0)
  {
    std::string s = device.getServiceData();
    const char* data = s.c_str();
    int8_t battery = data[5] & 0b01111111;
    s = device.getManufacturerData();
    data = s.c_str();
    bool tempSign = data[11] & 0b10000000;
    float temperature = ( data[10] & 0b00001111 ) / 10.0 + ( data[11] & 0b01111111 );
    if (!tempSign)
    {
      temperature *= -1;
    }
    float humidity = (float)((int8_t)(data[12] & 0b01111111) * 1.0);
  }

こういうの地味にハマるんだよなぁ、という感じで終わりです。

-プログラミング

執筆者:

関連記事

SHOWROOMのガチイベをGoogleスプレッドシートでグラフにしよう

もくじ1 まえがき2 みほん3 だいじな注意事項3.1 Google Apps Scriptの制限3.2 SHOWROOMの仕様4 てじゅん4.0.1 1.4.0.2 2.4.0.3 3.4.0.4 …

no image

[C言語]スペースを大量に入れるとバグが直るコードを書いてみた

↓こういうツイートがバズっていたので、実際に組んでみた。 修士の頃、授業の課題でC言語書いてる時にどうしても謎のエラーが出て困っていた。それを見たSE経験(金融系)がある社会人大学院生の同期の女性が「 …

no image

“API”をなるべく分かりやすく説明してみる

“API”という言葉が一般にもよく使われ始めています。 しかし、非エンジニアにとっては馴染みのない言葉で、しかも謎の英略語なので、一部の人々からは「APIがなくなった」(=AP …

no image

Google Apps Script (GAS)でBlueskyのbotを作る

Blueskyで何かやりたくなったので、PRTimesのプレスリリースを自動投稿するbotを作ってみました。 Google Apps Scriptを使うと、無料でbotが作れるので便利です。 せっかく …

no image

例え話をしないC言語のポインタの説明

もくじ1 まえおき2 Hello, Worldより簡単に2.1 サンプルコード2.2 変数の置き場所2.3 変数が入っているところを見てみる3 C言語とメモリ3.1 変数cの「まわり」を見てみる3.2 …