LoginSignup
3
5

More than 3 years have passed since last update.

node.jsでswitchbotの温湿度計データ取得

Posted at

switchbotの温湿度計を購入したので、node.jsでデータを取得し、s3にアップロードしてみた。

データの取得

データの取得にはnobleを使用した。
nodeのv9以降では動かないようなので、v8系をインストールすること。
nobleの使い方は割愛。

microbotの開発元?のOpenWonderLabsがAPI仕様を公開しているので、それを参照しながらデータを読み取る。
https://github.com/OpenWonderLabs/python-host/wiki/Meter-BLE-open-API
ビットの操作はとっても苦手なので、苦労した。
例えば、4バイト目の後ろ7ビットには温度のデータが入っているようなので、このようにして取得。

const temperature = data.readUInt8(4) & 0x7f;

&(ビット演算子)で0x7f(1111111)をビットANDして、後ろ7桁を切り出すらしい。

前3桁が欲しかったら、こんな感じで0xE0(11100000)をビットANDして、
さらにシフト演算子 >>> (0埋めバージョン)で後ろ5桁を溢れさせる。

var a = data.readUInt8(4) & 0xE0 >>> 5

web開発ばっかりやってた人間としては、このあたりはとっても苦手な領域。

データが取れたら fs でファイルに書き出す。
後で扱いやすいように moment.js を使って日時分秒をファイル名にした。

↓ソース全体(scan.js)

'use strict';

const noble = require('noble');
const fs = require('fs');
const moment = require('moment');

// living swithbot
const MAC = "xxxxxxx"; // switchbotのmacアドレス

const tmpDir = "/var/tmp/envdata/"; // データを保存したいディレクトリ

noble.on('stateChange', (state) => {
    if (noble.state === 'poweredOn'){
        noble.startScanning();
    } else {
        noble.on('stateChange', scanStart);
    }
});

noble.on('scanStart', () => {
    console.log('start scanning');
});

noble.on('scanStop', () => {
    console.log('stop scanning');
    process.exit(0);
});

noble.on('discover', (peripheral) => {
    if (peripheral.uuid === MAC) {
        noble.stopScanning();

        const data = peripheral.advertisement.serviceData[0].data;
        const deviceType = data.slice(0, 1).toString('ascii');
        const battery = data.readUInt8(2) & 0x7f;
        const temperature = data.readUInt8(4) & 0x7f;
        const humidity = data.readUInt8(5) & 0x7f;
        const time = moment().format('YYYY-MM-DD_HH:mm:ss');

        const jsonData = {
            "datetime": time,
            "battery": battery,
            "temperature": temperature,
            "humidity": humidity
        };

        // write to file
        fs.writeFileSync(tmpDir + time + '.log', JSON.stringify(jsonData));

        noble.stopScanning();
    }
});

s3へのアップロード

s3へのアップロードはいたって簡単です。

下準備

aws-sdk のライブラリを npm install する。
AWSのIAMでアップロード用のユーザ作ってAmazonS3FullAccessのポリシー(uploadだけだったら権限絞ったポリシーで良い気もする)付けて、そのcredential情報をjsonファイルに書き出しておく。

{
  "accessKeyId": "xxxxxxxxxxxxx",
  "secretAccessKey": "xxxxxxxxxx"
}

こんな具合。

S3への接続

こんな感じでs3オブジェクトをセットアップ。

AWS.config.loadFromPath('/home/pi/.aws/credential.json'); // 保存したcredentialファイルのパスを指定
AWS.config.update({region: 'ap-northeast-1'});

const s3 = new AWS.S3();

あとはアップロードしたいファイルの情報を整えて s3.putObject() でアップロード。

↓ソース(upload.js)

const AWS = require('aws-sdk');
const fs = require('fs');

AWS.config.loadFromPath('/home/pi/.aws/credential.json');
AWS.config.update({region: 'ap-northeast-1'});

const s3 = new AWS.S3();
const tmpdir = '/var/tmp/envdata/';


fs.readdir(tmpdir, (err, files) => {
  if (err) throw err;

  files.forEach( (file) => {
    var params = {
      Bucket: 'switchbot-room',
      Key: file
    };

    params.Body = fs.readFileSync(tmpdir + file);
    s3.putObject(params, (err, data) => {
      if (err) throw err;
      fs.unlinkSync(tmpdir + file, (err) => {
        if (err) throw err;
      });
    });
  });
});

自動起動設定

cron設定するだけ。

 */5 * * * * /usr/local/bin/node /home/pi/swithbot/scan.js
 */5 * * * * /usr/local/bin/node /home/pi/swithbot/upload.js

5分間隔でデータを取得して、アップロード。

今のところ問題なくデータが上がってます。

NextAction

次は、上がったデータを可視化したい。
QuickSight, Mackerel, ES + Kibana どれでやろうか検討中。chart.js使って自分で作ってもいいけど、
一番費用が掛からない方法がいいな。

3
5
1

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