Back to tech

obnizをBLEにてperipheralとして動かす

3 min read
Table of Contents

2019/05/18現在、obnizの仕様が変わったため本記事は動作しない可能性があります

以前の記事にてobniz買ってなんか作ってみたという記事をあげました

しかし、このマイコンを買った理由はBLEが簡単にできるという点です

さっそくobnizをBLEのperipheral(接続される側)として、データを一定間隔(継続的に)で送信するプログラムを作ってみたので記載しておきます

はじめに

obnizは、obniz独自のエディタで作れる他にもNode.jsでも作ることが可能です

作りやすさから本プログラムではNode上でつくりました

公式に従って初期化をします

obniz.io
obniz.io

どうやら変更されたようです(2019/05/18)

obniz.io
obniz.io
$npm init
$npm install obniz

動作

twitter.com
twitter.com

プログラム

今日時点(2018/08/30)にて動作を確認したプログラムを記載しておきます

プログラムの簡単な流れは

  1. obnizライブラリを読み込み
  2. advertiseの設定
  3. characteristicの設定(ここでnotifyを設定している)
  4. Serviceの設定
  5. BLEスタート
  6. 1秒毎ごとに値を更新

です

var Obniz = require("obniz");
var obniz = new Obniz("your obniz id");

obniz.onconnect = async function(){
    var value = 0;
    var State = "DisConnected";

    //Set advertise
    obniz.ble.advertisement.setScanRespData({
        localName : "obniz BLE",
    });

    //Set characteristic
    var Characteristic = new obniz.ble.characteristic({
        uuid: 'FFF1',
        data: [0x00, 0x00], // Same descriptors data array
        properties : ["notify"],
        descriptors: [{
            uuid:'2902',
            data: [0x00, 0x00], //notify array
            }]
    });

    //Set Service
    var Service = new obniz.ble.service({
        uuid: 'FFF0',
        characteristics: [Characteristic]
    });


    obniz.ble.peripheral.addService(Service);
    obniz.ble.advertisement.setAdvData(Service.advData);

    //advertise start
    obniz.ble.advertisement.start();

    //Connect and DisConnect Event
    obniz.ble.peripheral.onconnectionupdates = function(data){
        console.log("remote device:", data.address, data.status);

        if(data.status === "connected"){
            State = "Connected";
        }else if(data.status === "disconnected"){
            State = "DisConnected";
        }
    };

    //Notify 1Hz
    setInterval(function() {
        if(value >= 255){ //0xff
            value = 0;
        }else{
            value += 1;
        }

        //WriteValue
        Characteristic.writeWait([value, value]); //write value
        Characteristic.notify(); // notify change value

        obniz.display.clear();
        obniz.display.print("State:" + State + '\n');
        obniz.display.print("Send:" + "[" + "0x" + value.toString(16) + "," + "0x" + value.toString(16) +"]" + '\n');



        console.log("value:", value);
        console.log("value(hex):", "0x" + value.toString(16));
        console.log("-----");
    }, 1000);
};

プログラムの補足説明

  • “your obniz id”のところに各自のobniz IDを入れてください

    var obniz = new Obniz("your obniz id");
    
  • obniz.ble.advertisement.setScanRespDataにてアドバタイズでだす名称を設定しています

    例では名称を”obniz BLE”としています

    obniz.ble.advertisement.setScanRespData({
            localName : "obniz BLE",
        });
  • var Characteristicにてデータの送受信の定義をしています

    とりあえず2byteのデータ列を出力しています

    注意として、descriptorsのdataにも2byteを定義していますが、これと一致させなければなりません

    今回は一定間隔でデータを送信し、セントラル側に値を変わってことを教えたいためproperitesはnotifyにしています

    var Characteristic = new obniz.ble.characteristic({
            uuid: 'FFF1',
            data: [0x00, 0x00], // Same descriptors data array
            properties : ["notify"],
            descriptors: [{
                uuid:'2902',
                data: [0x00, 0x00], //notify array
                }]
        });
  • var Serviceにてcharacteristicの箱のようなものを作っています

    Serviceを作り、この中にはこんなcharacteristicが入っているよーとしてあげています

    characteristicsにて先程作ったCharacteristicをいれます

    またServiceには複数のCharacteristicを入れることができます (ex: characteristics: [Characteristic1, Characteristic2])

    var Service = new obniz.ble.service({
            uuid: 'FFF0',
            characteristics: [Characteristic]
        });
  • addServiceとsetAdvDataにてServiceを追加してあげます

    obniz.ble.peripheral.addService(Service);
    obniz.ble.advertisement.setAdvData(Service.advData);
  • obniz.ble.advertisement.start()にてBLEの電波を発します

    obniz.ble.advertisement.start()
  • obnizの接続状態も知りたいためにonconnectionupdatesを入れています

    obniz.ble.peripheral.onconnectionupdates = function(data){
            console.log("remote device:", data.address, data.status);
    
            if(data.status === "connected"){
                State = "Connected";
            }else if(data.status === "disconnected"){
                State = "DisConnected";
            }
        };
  • 一定間隔で通知をしたいためsetIntervalをつけています 通知間隔は1秒毎としています

    writeWait()のなかに値を書き込み、notify()にて値が変わったことを接続している側へ通知をしています

    重要なこととして、必ずwriteWait()したあとにnotify()をしないと値が変わったこと通知していくれません

    setInterval(function() {
            if(value >= 255){ //0xff
                value = 0;
            }else{
                value += 1;
            }
    
            //WriteValue
            Characteristic.writeWait([value, value]); //write value
            Characteristic.notify(); // notify change value
    
            obniz.display.clear();
            obniz.display.print("State:" + State + '\n');
            obniz.display.print("Send:" + "[" + "0x" + value.toString(16) + "," + "0x" + value.toString(16) +"]" + '\n');
    
    
    
            console.log("value:", value);
            console.log("value(hex):", "0x" + value.toString(16));
            console.log("-----");
        }, 1000);

余談

obnizでBLEをするときに「Notifyなくね?」となり、フォーラムに質問したところ1~2週間で実装してくれました

すばらしい

Does Obniz support Notify on the periferal side of BLE?
forum.obniz.com
image

実際にobnizでBLEをやってみてJavaScirptでBLEができていいじゃんと思いましたが、obniz自体がwifiを繋がなければ動かないため、「wifi環境あるんだったらBLEじゃなくてもよくない?」感があります

BLEにしか対応していないマイコン(BLEnano2とか)に繋げてなにかするしか利用する価値がないような・・・

あとBLEの接続プロセスしってないと難しい感じします obnizドキュメントにてBLEのやり方をみると(記事)、初心者にはとっつきにくい感じになってます

次はBLEのCentral(接続する側)をやってみたいと思います