3
5

More than 1 year has passed since last update.

SwitchBot温湿度計からBluetoothで気温と湿度を取得する

Posted at

SwitchBot温湿度計 から Bluetooth 通信で現在値を取得するメモ。

動作確認環境

  • macOS 12.1
  • node v17.3.0
  • npm v8.3.0
  • SwitchBot温湿度計

node-switchbot で値を取る

OpenWonderLabsが公開しているnode-switchbotを使うと、非常に楽。

必要なモジュールをインストールして、

npm install @abandonware/noble
npm install node-switchbot

Quick Start のコードをapp.js等に保存して実行するだけで、値が取得できる。

// Load the node-switchbot and get a `Switchbot` constructor object
const Switchbot = require('node-switchbot');
// Create an `Switchbot` object
const switchbot = new Switchbot();

(async () => {
  // Start to monitor advertisement packets
  await switchbot.startScan();
  // Set an event hander
  switchbot.onadvertisement = (ad) => {
    console.log(JSON.stringify(ad, null, '  '));
  };
  // Wait 10 seconds
  await switchbot.wait(10000); // 10秒だと受信しないことがあるので、受信確認用に60秒くらいにしておくと良い
  // Stop to monitor
  switchbot.stopScan();
  process.exit();
})();

こんな感じのデータが受信できる。

{
  "id": "11d6e84dd3e18b4e3aab47da4aecb60a",
  "address": "XX:XX:XX:XX:XX:XX",
  "rssi": -54,
  "serviceData": {
    "model": "T",
    "modelName": "WoSensorTH",
    "temperature": {
      "c": 21.7,
      "f": 71.1
    },
    "fahrenheit": false,
    "humidity": 53,
    "battery": 100
  }
}

serviceData.temperature.c が気温(℃)
serviceData.humidity が湿度(%)
serviceData.address が対象端末のMACアドレスなので、これで個体を識別する

・データタイプ(modelName)には、
 Bot, Meter, Curtain があるようで、
 温湿度計はMeterに属する。
 https://github.com/OpenWonderLabs/node-switchbot#advertisement-data

・データの受信はプログラム実行直後にくるとは限らず、
 実行から30秒くらいかかることもある。

・アパートの一部屋で実行すると、ご近所さんのSwitchBotからも ガンガン データを受信する

Bluetooth API で値を取る

SwitchBot温湿度計は、Bluetooth通信規格に BLE(Bluetooth Low Energy)を採用しているので、とってもエコ。

通信データの内容が公開されているので、任意のBLE通信APIからアクセスしてデータを活用できる。

手元では、abandonware/nobleを使ってデータを取得することもできた。

abandonware/noble

nodeのBLE通信モジュールとしてnobleが有名みたいだが、本家は更新が止まっているので、
abandonwareさん?がそういった有益なOSSを引き継いで開発保守をしてくれているらしい。

BLEでは、[親機(central module)] 1 対 [子機(peripheral)] で通信が行われ、
nobleは親機の実装用モジュールとなる。

雑にデータを取りに行くだけならこんな感じ。

const UUIDs = ['cba20d00224d11e69fb80002a5d5c51b'];
const noble = require('@abandonware/noble');
noble.on('stateChange', state => {
  // nobleの初期stateはUnknown. poweredOn になってからスキャンを開始しなければいけない
  if (state == 'poweredOn'){
    // UUIDsで指定された対象だけが、スキャンの対象となる。
    // ここで設定している値は、SwitchBot機器用に公開されているUUID
    // 第2引数は duplicate. 同端末からは1回のみデータを受け取るならば false にする
    noble.startScanning(UUIDs, true);
  }
});
noble.on('discover', peripheral => {
  console.log('' + peripheral);
});

こんな感じにデータが取れる

{
  "id": "11d6e84dd3e18b4e3aab47da4aecb60a",
  "address": "",
  "addressType": "unknown",
  "connectable": true,
  "advertisement": {
    "manufacturerData": {
      "type": "Buffer",
      "data": [ 89, 0, 220, 48, 188, 73, 157, 176 ]
    },
    "serviceData": [
      {
        "uuid": "0d00",
        "data": {
          "type": "Buffer",
          "data": [ 84, 16, 100, 8, 148, 54 ]
        }
      }
    ],
    "serviceUuids": [
      "cba20d00224d11e69fb80002a5d5c51b"
    ]
  },
  "rssi": -55,
  "mtu": null,
  "state": "disconnected"
}

Meter BLE open API

abandonware/nobleでデータ取得ができるようになったら、
Meter BLE open APIで公開されているデータ仕様を参考にして必要な値を取得する。

※ここにUUIDについての記載もある
UUID: cba20d00-224d-11e6-9fb8-0002a5d5c51b and fee7

温湿度計用には(New) Broadcast Messageのあたりが直接参考になるので、コードにおこすとこんな感じになる。

noble.on('discover', peripheral => {
    const sd = peripheral.advertisement.serviceData[0].data;
    const md = peripheral.advertisement.manufacturerData;

    const temperatureAboveZero = (sd[4] & 0b10000000) != 0;
    const data = {
        'type': sd[0] & 0b01111111,
        'battery': sd[2] & 0b01111111,
        'temperature': ((sd[3] & 0b00001111) / 10 + (sd[4] & 0b01111111)) * (temperatureAboveZero?1:-1),
        'humidity': sd[5] & 0b01111111,
        'rssi': peripheral.rssi,
        'address': `${md[2].toString(16)}:${md[3].toString(16)}:${md[4].toString(16)}:${md[5].toString(16)}:${md[6].toString(16)}:${md[7].toString(16)}`
    };
    console.log(JSON.stringify(data));
});
3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5