自作パーツの作り方

自分のパーツを作って公開する方法

自分で作りたい!

obnizは標準でサーボモーターやセンサーを扱うためのライブラリが用意されています。
しかし、ライブラリにない部品や自分で作った回路のためにオリジナルのパーツライブラリを作りたいことがあると思います。
今回はその方法を紹介します。

まずはやってみる。

仕組みを勉強する前にとりあえずやってみましょう。
標準ライブラリにある、LEDはオンオフや点滅しかないので、「1秒だけ点灯する」という機能をつけた新しい自分用LEDを用意してみます。

class MYLED {
  constructor() {
    this.keys = ['anode', 'cathode'];
    this.requiredKeys = ['anode', 'cathode'];
  }

  static info() {
    return {
      name: 'MYLED',
    };
  }

  wired(obniz) {
    this.obniz = obniz;
    this.io_anode = obniz.getIO(this.params.anode);
    this.io_anode.output(false);
    this.io_cathode = obniz.getIO(this.params.cathode);
    this.io_cathode.output(false);
  }

  onesec() {
    this.io_anode.output(true);
    obniz.wait(1000);
    this.io_anode.output(false);
  }
}

if (typeof module === 'object') {
  module.exports = MYLED;
}

これがその自分用LED。名付けて「MYLED」です。
onesec()関数に1秒だけアノードをONにしてLEDをつけるプログラムが書いてあります。
これを自分のHTMLプログラムに取り込む方法は2つあります。

  1. scriptタグを書いてその中に直接書いてしまう
  2. 別ファイルに書いて公開して、scriptタグで取り込む

1は単純に上記プログラムをプログラムの中にコピー&ペーストする方法です。
最も簡単にできます。
今回は少し手間ですが、より便利な2の方法にします。

このjavascriptを公開する必要がありますので、アカウントを作ってobnizクラウドのマイページから新しいjavascriptを作成します。

「新規作成」から Typeで 「Parts/Util js file」となっている方を選びます。
ファイル名は今回はmyledにします。何でも良いです。

そして作成を押して上記プログラムを書いて保存します。
保存は「保存&開く」を押してもいいですし、ツールから「保存」を押しても保存できます。
保存できたらマイページをもう一度開いてみましょう。
myledがあるはずです。更に、これを読み込むためにどういうscriptタグを書いたらよいかが表示されると思います。

これを自分のプログラムに取り込んで使えるようにします。やることは2つです。

  1. scriptタグで部品のjsを読み込む
  2. Obniz.PartsRegistrate 関数でobnizに部品を登録する。
<html>
<head>
  <script src="https://unpkg.com/obniz@1.14.1/obniz.js" crossorigin="anonymous"></script>
  <script src="https://obniz.io/users/あなたのid/repo/myled.js"></script>
</head>
<body>

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

<script>
var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {

  Obniz.PartsRegistrate(MYLED);
  var led = obniz.wired("MYLED", { anode:0, cathode:1 } );
  led.onesec();
}

</script>
</body>
</html>

LEDをio0,1につないでこれを実行すると、LEDが1秒だけ点灯して消えると思います。
無事に新しい部品を作って、それを自分のプログラムで使うことができましたね!
同じように新しいjsファイルを作れば好きなだけ部品を作れますし、好きなだけ自分の関数を用意できます。

自分ライブラリのクラスの作り方をとても簡単に説明すると

  1. 上にあるようなクラスを作る
  2. constructor()内のkeysにobniz.wiredで呼ばれる時のオブジェクトのキー名を入れて、reuiqredKeysに必須のキー名を入れる
  3. info()のnameにobniz.wiredで部品を使う時の名前を入れる。
  4. wired()内に部品の初期化処理を書く。obniz.wired()で渡されるオブジェクトはthis.paramsに入っている。
  5. 自分の使いたい関数などを用意する。
  6. そして、そのjavascriptクラスを公開してscriptタグで読み込んで使う

しくみはどうなっているのか

パーツライブラリがどうなっているのかを見てみましょう。例えばLEDを開くと使い方が出てきますが、プログラムを開くこともできます。
ドキュメント内に「Source」というボタンがあり、それを押すことでLEDがどういうプログラムでできているのかを確認できます。
またGithubへリンクがあり、それを押すことでGithubでソースを確認することもできます。どちらも同じプログラムです。

プログラムを見てみましょう。

全部見てみると大変なので重要な部分だけ取り出します。
ledはon()関数でONにできるので、その周りだけ取り出します。

class LED {
  constructor() {
    this.keys = ['anode', 'cathode'];
    this.requiredKeys = ['anode'];
  }

  static info() {
    return {
      name: 'LED',
    };
  }

  wired(obniz) {
    function getIO(io) {
      if (io && typeof io === 'object') {
        if (typeof io['output'] === 'function') {
          return io;
        }
      }
      return obniz.getIO(io);
    }

    this.obniz = obniz;
    this.io_anode = getIO(this.params.anode);
    this.io_anode.output(false);
    if (this.params.cathode) {
      this.io_cathode = getIO(this.params.cathode);
      this.io_cathode.output(false);
    }
  }

  on() {
    this.endBlink();
    this.io_anode.output(true);
  }

  off() {
    this.endBlink();
    this.io_anode.output(false);
  }
}

if (typeof module === 'object') {
  module.exports = LED;
}

部品は1つ1つが1つのクラスになっています。
今回は"LED"というクラス名になっています。
このクラスをobniz.jsのobnizクラスに登録することでobniz.wired()を使って部品を使えるようになります。
実はobniz.jsの最初からあるパーツはプログラムが動き出した時にobniz.jsが自分ですべての部品を自分自身に登録しているのです。
これと同じことを自分もやってしまえば、自分の部品をobnizに登録できます。

パーツクラスの最小構成と登録の流れ

部品のためのクラスに最低でも必要なのは以下です。

class LED {
  constructor() {
    this.keys = ['anode', 'cathode'];
    this.requiredKeys = ['anode'];
  }

  static info() {
    return {
      name: 'LED',
    };
  }

  wired(obniz) {

  }
}

if (typeof module === 'object') {
  module.exports = LED;
}

constructor内にあるkeysはobniz.wiredで渡されるオブジェクトの中で必要なもののキー名です。

this.keys = ['anode', 'cathode'];

requiredKeysはobniz.wiredで渡されるオブジェクトの中で絶対に必要なもののキー名です。それがもしなければ自動的にエラーとなります。今回の場合はanodeは必須です。cathodeは受け取るものの、必須ではないということです。

this.requiredKeys = ['anode'];

info()関数内のnameで部品の名前を決められます。この名前で obniz.wired('LED')として部品を利用できます。クラスの名前はobniz.wiredのときには関係ありません。

static info() {
  return {
    name: 'LED',
  };
}

wired()関数はobniz.wiredが呼ばれた時に呼ばれる関数です。
obniz.wired()で渡されたオブジェクトはthis.paramsでアクセスできます。

また、最後にあるmodule.exportsはHTMLでは必須ではありませんが、
これを書いておくことでnodejsでも利用したくなった時にとても便利です。

if (typeof module === 'object') {
  module.exports = LED;
}

登録と利用

さて、登録と使えるまでの流れは以下になります

  1. Obniz.PartsRegistrate(); 関数で自分の作った部品のクラスを渡す

この時に名前が決まります。名前は部品の中にあるinfo()関数の中のjsonで定義されているものです

static info() {
  return {
    name: 'LED',
  };
}
  1. obniz.wired() 関数で自分の作った部品を使う。

この時にobnizが部品に対して行うのは以下です。

  1. まずインスタンス化する。 つまり、部品のconstructor()部分が実行される。
  2. obniz.wired()で渡されたオブジェクトのうち、keysにあるkeyのみを抽出し,requiredKeysで定義されるあるはずのkeyがなければエラーとする。
  3. 上記オブジェクトをparamsというキーでインスタンス化したオブジェクトにつける
  4. wired()関数を呼ぶ

となっています。

obnizに対して部品の登録を行うことでobniz.wiredで部品を使えたり渡されたオブジェクトのキーの検証などができるわけです。最初にやった例のように。

var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {

  Obniz.PartsRegistrate(MYLED);
  var led = obniz.wired("MYLED", { anode:0, cathode:1 } );
  led.onesec();
}

obnizに対して部品を登録しないで、部品を使うことももちろんできます。

その場合は以下のようになります。

var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {

  var led = new MYLED();
  led.params = { anode:0, cathode:1 };
  led.wired(obniz);
  led.onesec();
}