📖

OMRON 環境センサUSB型 形2JCIE-BU01 のアドバタイジングパケットをnode.jsでパースする

2024/03/23に公開

はじめに

超久しぶりにオムロン環境センサを使う必要ができたので改めてアドバタイジングパケットのパーサーを書きました。環境センサバック型(2JCIE-BL01)のパーサーは以前記事を書いたんだけどUSB型のほうは書いてなかったので記事化しておこうと思います。

ちなみにバック型は生産終了したので上記の記事は間もなく使えなくなるでしょう。書いたのはもう5年も前になるのか。。

これを書くにあたってついでに@abandonware/nobleの存在を知ったので付記しておこうと思います。以前nobleがdisconn状態なのでnode.jsでのBLEモジュールの代替方法について書きましたが、こういう孤児になったプロジェクトを保守するAbandonWareコミュニティによってnobleが保守されていました。現時点でnode v20.11.0で動作を確認しています。非常にありがたい。

パーサー

ユーザーマニュアルによると2JCIE-BU01のアドバタイジングパケットには5種類のフォーマットがあってdata typeを切り替えるて利用できます。とりあえずは直近必要なデフォルトのdata type 1 (sensor data)をパースするようにしました。

declare interface Omron2JCIEBU01_TYPE1 {
    dataType: number;
    temperature: number;
    relativeHumidity: number;
    ambientLight: number;
    barometicPressure: number;
    soundNoise: number;
    eTvoc: number;
    eCo2: number;
}

class Omron2JCIEBU01 {
    data: Buffer;
    constructor(data: Buffer) {
        this.data = data;
    }
    get dataType(): number {
        return this.data.readUInt8(2);
    }
    get temperature(): number {
        return this.data.readInt16LE(4) / 100;
    }
    get relativeHumidity(): number {
        return this.data.readInt16LE(6) / 100;
    }
    get ambientLight(): number {
        return this.data.readInt16LE(8);
    }
    get barometicPressure(): number {
        return this.data.readInt32LE(10) / 1000;
    }
    get soundNoise(): number {
        return this.data.readInt16LE(14) / 100;
    }
    get eTvoc(): number {
        return this.data.readInt16LE(16);
    }
    get eCo2(): number {
        return this.data.readInt16LE(18);
    }
    hasValidCompanyId(): boolean {
        return this.data.readUInt16BE(0) === 0xd502;
    }
    parse(): Omron2JCIEBU01_TYPE1|undefined {
        let result: Omron2JCIEBU01_TYPE1|undefined = undefined;
        switch (this.dataType) {
        case 0x01:
            result = {
                dataType: this.dataType,
                temperature: this.temperature,
                relativeHumidity: this.relativeHumidity,
                ambientLight: this.ambientLight,
                barometicPressure: this.barometicPressure,
                soundNoise: this.soundNoise,
                eTvoc: this.eTvoc,
                eCo2: this.eCo2
            };
            break;
        default:
            break
        }
        return result;
    }
}

export default Omron2JCIEBU01;

実行してみる

npm i -S @abandonware/noble
npm i -D typescript ts-node
npx tsc --init
import noble from '@abandonware/noble';
import Omron2JCIEBU01 from './2jcie-bu01';

noble.on('stateChange', async(state: string) => {
  if (state === 'poweredOn') {
    try {
        await noble.startScanningAsync();
    } catch (error: unknown) {
        throw new Error(String(error));
    }
  } 
});

noble.on('discover', async (peripheral: noble.Peripheral) => {
  const sensor = new Omron2JCIEBU01(peripheral.advertisement.manufacturerData);
  if (peripheral.advertisement.localName === 'Rbt' && sensor.hasValidCompanyId()) {
    console.info(sensor.parse());
    await noble.stopScanningAsync();
    process.exit(0);
  }
});

実行します

npx ts-node index.ts

{
  dataType: 1,
  temperature: 25.3,
  relativeHumidity: 53.13,
  ambientLight: 214,
  barometicPressure: 1016.243,
  soundNoise: 79.97,
  eTvoc: 25,
  eCo2: 570
}

できてるっぽいです。

おわりに

2JCIE-BU01はUSB電源さえあればBLEで環境データを送り続けてくれるので様々な環境で簡易に環境データを取る時に重宝します。今回はRaspberry Piで温度や湿度を受信しようと思って書いてみました。長年使い慣れているnobleもちゃんと動いてくれているので開発が捗りそうです。

Discussion