プログラミング

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);
  }

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

-プログラミング

執筆者:

関連記事

【Unity】GPUを使ってパンツを隠すスクリプトができた

かわいいスカートを履きたい!でもパンチラしたくない! それは誰もが抱く夢です。もちろん、3Dモデルだってパンチラしたくないと思っているハズです。 というわけで偉大なる先人がいます。 Unityでパンツ …

GeoJSONで市町村境界をマージして都道府県境界にしたい(実践編)

前々回と前回で問題を整理して、ようやく実践編です。 まず実物のリンク貼りましょう。GitHubに上げました。 今回はGo言語で書いてますが、ポイントがいくつかあります。 ちなみに言語としてGoを選択し …

no image

M5StickC Plusの明るさ(M5.Axp.ScreenBreath)、0~100かもしれない

M5StickC Plusで画面の明るさを調整するM5.Axp.ScreenBreath()という関数があります。 日本語リファレンスでは指定値7~12ということになっています。 また、公式ドキュメン …

no image

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

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

no image

プログラミングとアルゴリズムのはなし

みんなー!小学校でプログラミングの授業がはじまるよー!! プログラミングってなんだろう? プログラミングって、コンピューターに「○○をしなさい」って命令して、なにかの問題を解いたり、ゲームをつくったり …