EnOcean STM 550B マルチセンサーモジュール(BLE) を obniz の BLE で取得するメモ

EnOcean STM 550B マルチセンサーモジュール(BLE) を obniz の BLE で取得するメモです。

経緯

中畑さんから

を試させていただいてます。そして obniz で BLE でつないでみます。

データを初めて取得する

image

ここは結構ハマったのですが、ポイントを書いておきます。

  • 開封したら太陽電池のところに光を当ててしばらく十分に充電する。
    • 充電が不十分で検証するとデータが来なくて検証しにくい。
  • 説明サイトではデータを見るために加速度を変化させて「振ってみる」と書いてあり確かにそれで動くけれど初見で分かりにくいので注意
    • 私は最初うまくいかなくてハマったので以下のやり方を推奨

そのやり方とは「LEARNボタンを2回素早く押して」データを強制的にデータを送ることで検証する方法です。

こちらでデータが送られると、

image

赤く丸で囲んだあたりにあるLEDが赤く一瞬光ります。

おかげさまで、無事取得できました。

注意

ただし、これ、疎通チェックのみで使いましょう。LEARNボタン使用時の中身のペイロードは、通常のセンサーデータが送られてくるものとは違うようです。

image

センサーデータをちゃんと解析する場合は、磁気センサー部分に磁石を押し当てる方法がやりやすいです。(はじめからそのやり方のほうが良かったかもしれない)

データ解析

データ解析で参考にした記事はこちらです。ありがとうございます!

obnizでのソースコード

image

実際に取得できたコードはこちらです。

<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
    <script src="https://unpkg.com/obniz@3.7.0/obniz.js" crossorigin="anonymous"></script>
  </head>
  <body>

    <!-- <div id="obniz-debug"></div> -->

    <div class="container">
      <div>
        <h2>EnOcean STM 550B マルチセンサーモジュール(BLE)</h2>
      </div>
      <div>
        <h3>[raw advertise data]</h3>
        <div id="valueSTM550B">--</div>
        <h3>[raw advertise data 16進数]</h3>
        <div id="valueSTM550B2">--</div>
        <h3>[Temperature]</h3>
        <div id="temperature">--</div>
        <h3>[Illumination_Sensor]</h3>
        <div id="illumination">--</div>
        <h3>[Humidity]</h3>
        <div id="humidity">--</div>
        <h3>[Magnet]</h3>
        <div id="magnet">--</div>
      </div>
    </div>

    <script>

let loopCount = 0;

const settings = {
  duration: null
}

const obniz = new Obniz("Obniz_ID");
obniz.onconnect = async function () {

  obniz.display.print("obniz BLE");
  obniz.display.print(" ↑ ↓");
  obniz.display.print("EnOcean");

  await obniz.ble.initWait();

  obniz.ble.scan.onfind = async function(peripheral){
    if( peripheral.address === "XXXXXXXXXXXX"){  // 取得したいEnOcean STM 550B マルチセンサーモジュールのアドレスを記述
      console.log("EnOcean STM 550B connect!" + new Date().getTime());

      // 通常のアドバタイズデータ
      const adv_data = peripheral.adv_data;
      
      // 読解用。アドバタイズデータを16進法で表記することで Manufacturer ID の 0x03DA といった値が分かりやすくなります。
      const adv_data16 = adv_data.map(
        function(value){
          return value.toString(16);
        }
      );

      $('#valueSTM550B').text(adv_data.toString());
      $('#valueSTM550B2').text(adv_data16.toString());

      // 温度センサー
      const temperature = ( adv_data[9] + adv_data[10] * 256 ) * 0.01;
      $('#temperature').text(temperature);
      // 湿度センサー
      const humidity = adv_data[12] * 0.5;
      $('#humidity').text(humidity);
      // 照度センサー
      const illumination = adv_data[14] + adv_data[15] * 256;
      $('#illumination').text(illumination);
      // 磁気センサー
      const magnet = adv_data[22];
      if( magnet === 1 ){
        $('#magnet').text("ON");
      } else if( magnet === 2 ){
        $('#magnet').text("OFF");
      } 
      // データを受信するたびに再スキャン
      // 再スキャンは endWait を走らせると onfinish が発動するのでそこで再開させる
      await obniz.ble.scan.clearAdvertisementFilter();
      await obniz.ble.scan.endWait();
    }
  };

  obniz.ble.scan.onfinish = async function(peripherals, error){
    loopCount++;
    console.log("scan timeout! [" + loopCount + "]");
    // 再スキャンは endWait を走らせると onfinish が発動するのでそこで再開させる
    await obniz.ble.scan.startWait(settings);
  };

  // 初回スタート
  await obniz.ble.scan.startWait(settings);
}
    </script>
  </body>
</html>

取得したいEnOcean STM 550B マルチセンサーモジュールのアドレス

 if( peripheral.address === "XXXXXXXXXXXX"){  // 取得したいEnOcean STM 550B マルチセンサーモジュールのアドレスを記述

こちらは、ifで絞り込む前に、何度かLEARNボタンをおして peripheral.addressconsole.log で確かめてキャッチできるようにしましょう。

センサー取得

こちらは EnOceanのBLE環境センサー「STM550B」をNode-REDで受信して解析した話 を参考にしましたが、Node-REDで取得するアドバタイズデータの配列と、今回の obniz で取得できる adv_data では、完全に位置が一致するわけではなく、ちょっとズレるのでそこは読み替えています。

計算式も、試行錯誤の末、こちらの記事と同じアプローチになっていたので大丈夫だと思います。検証でくる対象があるのはとってもありがたいです。

      // 温度センサー
      const temperature = ( adv_data[9] + adv_data[10] * 256 ) * 0.01;
      $('#temperature').text(temperature);
      // 湿度センサー
      const humidity = adv_data[12] * 0.5;
      $('#humidity').text(humidity);
      // 照度センサー
      const illumination = adv_data[14] + adv_data[15] * 256;
      $('#illumination').text(illumination);
      // 磁気センサー
      const magnet = adv_data[22];
      if( magnet === 1 ){
        $('#magnet').text("ON");
      } else if( magnet === 2 ){
        $('#magnet').text("OFF");
      } 

スキャンし続ける流れ

  obniz.ble.scan.onfind = async function(peripheral){
    if( peripheral.address === "XXXXXXXXXXXX"){  // 取得したいEnOcean STM 550B マルチセンサーモジュールのアドレスを記述
      console.log("EnOcean STM 550B connect!" + new Date().getTime());

      // ~~~~~~~~~~~ 略 ~~~~~~~~~~~
      
      // データを受信するたびに再スキャン
      // 再スキャンは endWait を走らせると onfinish が発動するのでそこで再開させる
      await obniz.ble.scan.clearAdvertisementFilter();
      await obniz.ble.scan.endWait();
    }
  };

  obniz.ble.scan.onfinish = async function(peripherals, error){
    loopCount++;
    console.log("scan timeout! [" + loopCount + "]");
    // 再スキャンは endWait を走らせると onfinish が発動するのでそこで再開させる
    await obniz.ble.scan.startWait(settings);
  };

途中省略していますが、データを受信するたびに再スキャンしています。

この理由は、同じスキャン中だと同じアドレスが下りてこないケースがあり、それを愚直に回避するためです。読むたびに endWait で終了させています。そして、onfinish が発動するのでstartWaitで再開させています。

どうも settings の設定値 BleScanSetting | obniz をうまく使えば解決しそうですが、今回は動かせなかったので上記のようなアプローチをしています。

設定値でうまくいかないときも、処理で同じように作れることを知っておくことは大事。

動かしてみる

実際に動かしてみます。

image

obnizクラウドで実行してみます。

image

磁気センサーに磁石を押し当てて強制的にセンサーを反応させます。

image

実際に受け取ることができました!