かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

IoT初心者がobnizと戯れてみて、"簡単に"とは何かについて考えてみたメモ。

これはobniz Advent Calendar 201812日目の記事です。

はじめまして。
IoTデバイスを触ったり、回路作ったり自体が初めてのド素人です。
obnizのハンズオンに参加してJavaScriptSDKを使って"簡単に"LEDを光らせたりモーターを動かしたりができたので、調子に乗って自分で考えた機能を作ろうと思い立ったものの、いざやり始めてみたら壁に激突してしまいました。
その経験からobnizに限らず様々なIoTデバイスでよく謳われている"簡単に"とは何かを考えてみることにしました。
Advent Calendarでは比較的作ってみた系が多い中、チョット毛色の違う読み物的な記事かもしれません。

IoTド素人なので、認識などに間違いがあるかと思います。
認識違いなどがあれ是非教えてください。 ヨロシクオネガイシマス!

obniz, Arduino, RaspberryPiの違いについて考える

Rasbperry PI / Arduino / obniz

バイス 特徴
Raspberry Pi
Linuxコンピューター (small single-board computers)
Raspberry Pi上のOSからプログラムを実行する
  • PCでできることはだいたいできる。
  • Linuxライブラリの恩恵を受けることができる
  • 処理をマルチタスクで実行できる
  • OSのインストールとかセットアップが大変 (な印象
  • PCなので雑に扱うと壊れやすい
Arduino
マイコン (Single-board microcontroller)
Arduino上のメモリ領域にプログラムを書き込んで実行する
  • リアルタイム性のある処理が得意
  • 比較的 安価 (OSSなので超安価な互換機も多い)
  • 機能を追加する拡張パーツが多い
  • 1つのタスクしか動かせない
  • プログラムを書き込める容量に制限がある
obniz
マイコン (API maneged IO)
クラウド/ネット上にあるプログラムをAPI経由でobnizで実行する
  • WEB開発の資産が利用できる
  • プログラムのサイズを心配する必要はない
  • 日本発なので日本語のドキュメントが豊富
  • インターネット環境必須
  • ネット回線に動作が左右される

Raspberry Piはもともと学生のための安価なコンピューターとして考案され、Arduinoは学生のためのハードウェアの試作の為のシンプルなツールとして考案されたそうです。

obnizはどちらかといえばArduinoに近い印象です。
そしてインターネットが必要という特徴から、IoTに特化したAPISDKを含めたツール群と言った感じでしょうか。

簡単とはなにか

Raspberry PiArduino、obnizに限らず、多くの開発ボードが「簡単に」できるを謳っているように思います。
似ていると感じた、obniz / Arduino のそれぞれのWEBサイトに掲載されているコンセプトを見てみましょう。

obniz

obnizには、難しくてあきらめることも、 できないストレスも、細かく膨大な準備もありません。 スマートフォンでプログラムページを開けば、 センサーやモーターの遠隔操作も思いのまま。 あなたが作ってみたいと思っていたものも、作れないと思っていたものも、 obnizならずっと簡単に
obnizには、難しくてあきらめることも、 できないストレスも、細かく膨大な準備もありません。 スマートフォンでプログラムページを開けば、 センサーやモーターの遠隔操作も思いのまま。 あなたが作ってみたいと思っていたものも、作れないと思っていたものも、 obnizならずっと簡単に

Arduino

Arduino is an open-source electronics platform based on easy-to-use hardware and software. It's intended for anyone making interactive projects.
Arduino is an open-source electronics platform based on easy-to-use hardware and software. It's intended for anyone making interactive projects.

どちらも簡単に使えるよ的な事が書かれています。

コードで見る"簡単に"とはなにか

よくあるLEDを光らせるサンプルコードを比べてみます。 ※ obnizはJavaScriptSDKを使った場合で

obniz

f:id:kikiki-kiki:20181212073844j:plain

const obniz = new Obniz("<OBNIZ_ID>");
obniz.onconnect = async function() {
  // LEDのアノードを0、カソードを1に接続
  const led = obniz.wired("LED", {anode:0, cathode:1});
  // LEDを点灯
  led.on();
  // LEDを消灯
  led.off();
};

cf. obniz: Make everything online

Arduino

f:id:kikiki-kiki:20181212073903j:plain

// LEDのアノードをデジタルピン13に接続
const int LED = 13;
void setup() {
  // デジタルピンを出力に設定
  pinMode(LED, OUTPUT);
}
void loop {
  // HIGHを出力してLEDを点ける
  digitalWrite(LED, HIGH);
  // LOWを出力してLEDを消す
  digitalWrite(LED, LOW);
}

定番とも言えるLEDを点けるような処理でも、ArduinoではHIGH/LOWといった回路的な用語が使用されます。
対してobniz(JavaScriptSDK)はLEDキーワードでオブジェクトを作り、ON/OFFにするという直感的な感じです。 (GitHubで公開されているobnizのコードを追って見た感じだと、 obnizeの処理の裏側ではanodeに割り当てられたピンに対しwebsocketからIOをONにするiox.output(true)相当の命令が送られているようでした。)

ここからも Arduinoはハードウェアの学習に主眼が置かれており、ハードウェアの試作が"簡単に"であり、 obnizはIoTの製作に主眼が置かれており、ハードウェアを意識することなくIoTの製作が"簡単に"である。という思想が見てとれるのではないでしょうか。

"簡単に"が内包する問題

このようにobnizでは用意されたSDKを利用することでハードウェアを意識することなく、様々な機器をドキュメントにあるコードを参考に動作させることが出来ます。

例えばDCMotorであれば
cf. obniz: Make everything online

const obniz = new Obniz("<OBNIZ_ID>");
obniz.onconnect = async function() {
  const motor = obniz.wired("DCMotor", {forward:0, back:1});
  motor.forward();
};

のように、たったこれだけの記述でDCMotorを動作させることが可能です。
forwardbackで指定されたピンはioで5v push-pullに設定していることなどを知る必要もありません。
cf. obniz/parts/Moving/DCMotor at master · obniz/obniz · GitHub

距離センサ(HC-SR04)なら
cf. obniz: Make everything online

const obniz = new Obniz("<OBNIZ_ID>");
obniz.onconnect = async function() {
  const hcsr04 = obniz.wired("HC-SR04", {gnd:0, echo:1, trigger:2, vcc:3});
  hcsr04.measure(function( distance ){
    console.log("distance " + distance + " mm");
  });
};

単にセンサーを動作させ値を取得することを目的とするなら、
割り当てているピンのgnd, echo, trigger, vccが何なのかも、センサーからどのように値を取っているのかも知る必要もありません。
cf. obniz/parts/DistanceSensor/HC-SR04 at master · obniz/obniz · GitHub

更に用意されているブロックプログラミングを利用すればJavaScriptのコードすら知る必要もありません。 obnizのブロックプログラミング

簡単に実際のパーツを動かして試せる = IoTの実験に注力できる反面、ややこしい部分をSDKが良い感じにラップしているので回路的な事を学ぶ機会は少なくなるように感じます。
故に私のようなIoTド素人の場合、リファレンスに載っていないパーツを使って自分で考えたモノを作ろうとした時に、vccって何?gndって何?どのピンにどれを繋いでどう設定すればいいの?という壁に当たる事になるでしょう。(Pin Peripheralsのようなリファレンスもありますが、ド素人的には用語の意味を知っている事が前提のように感じました。)

Team obniz に期待したいこと

obnizならずっと"簡単に"。 とは現状、

  • JavaScriptを知っていれば "簡単に" をIoTできる但し、リファレンスにあるパーツを使えば
  • ブロックプログラミングを使えばJavaScriptを知らなくても "簡単に" に作ることができる。但し、登録されているパーツを使えば
  • "簡単に" JavaScript SDKを使ってIoTなモノを作ることができる。但し、ある程度回路的な知識があれば

のような省略された但し書きの条件の上での"簡単に"ではないかと思います。

obnizはブロックプログラミングも用意されており、実際に動くモノを(リファレンスにあるパーツを使えば)"簡単に"作れ、成功体験を得られ、モチベーションを維持しやすい、という仕組みができていると思います。
なのでIoT初学者やプロトタイプ作り、教育の現場ではとても向いているのではないかと強く感じました。
一方、そこからリファレンスにないパーツを使ったりした独自の仕組みを作れるようになるステップアップの方法が"簡単"さを実現するために難しいくなっている気がします。回路的な知識を得ることができるようなコンテンツが用意されれば、よりobnizを選択する動機づけになるのではないかと感じました。

おまけ

ワタシハIoTチョットデキル
作ってみたが力不足で出来なかったので、イラストを描いてみました!


[参考]

JavaScript 該当する文字を全部変換したいメモ

例えば次のようなテキストを

"藤堂ユリカ\n一ノ瀬かえで\n神崎美月"

👇

"藤堂ユリカ 一ノ瀬かえで 神崎美月"

のように置き換えたい時

JavaScriptにはreplaceAllのようなメソッドがないので、

const str = "藤堂ユリカ\n一ノ瀬かえで\n神崎美月";
str.replace("\n", " ");
// => "藤堂ユリカ 一ノ瀬かえで\n神崎美月"

単純にstr.replace()を使っても最初にマッチした文字しか置き換えられません。

str.replace() で正規表現を使って置き換える

正攻法。
str.replace() の検索文字を正規表現( RegExp )にする方法。
g(グローバルサーチ)オプションを使うことで全てのマッチを置き換えることができます。

const str = "藤堂ユリカ\n一ノ瀬かえで\n神崎美月";
str.replace(/\n/g, ' ');
// => "藤堂ユリカ 一ノ瀬かえで 神崎美月"

str.split().join() で置き換える

split()メソッドが指定した区切り文字全てで分割して配列をかえすことを利用して、str.split('検索文字').join('変換文字')としてしまえば一括変換に利用できます。

const str = "藤堂ユリカ\n一ノ瀬かえで\n神崎美月";
str.split("\n").join(' ');
// => "藤堂ユリカ 一ノ瀬かえで 神崎美月"

splitで配列になっているので、reduce()で値を弄ったりして合算することも出来ます。

const str = "藤堂ユリカ\n一ノ瀬かえで\n神崎美月";
str.split("\n").reduce((sum, val)=> {
  if( /^神崎美月$/.test(val) ) {
    val = 'レジェンド美月';
  }
  return `${val}🌟${sum}`;
});
// => "レジェンド美月🌟一ノ瀬かえで🌟藤堂ユリカ"

 

単一な文字を一括して変換したい時、str.split('検索文字').join('変換文字')はハック的だけど簡潔で良いなと思いました。
処理的には正攻法な正規表現の方が関数呼び出しも1つだし高速な気もしますが…

おまけ str.replace() の第二引数(置換える文字)は関数にできる

str.replace()のドキュメントを見ていて、第二引数に関数が取れる事を知ったので試してみました。

str.replace(regexp|substr, newSubstr|function)
function (replacement)
新しい部分文字列を生成するために実行される関数で、regexpsubstr でマッチしたものを置き換えるのに使われます。この関数に渡される引数は下記の "Specifying a function as a parameter" で述べられています。

const str = "藤堂ユリカ\n一ノ瀬かえで\n神崎美月";
str.replace(/(.+)\n/g, (...val)=> {
    console.log(val);
    return 'ジョニー別府 ';
});
// => [ '藤堂ユリカ\n', '藤堂ユリカ', 0, '藤堂ユリカ\n一ノ瀬かえで\n神崎美月' ]
// => [ '一ノ瀬かえで\n', '一ノ瀬かえで', 6, '藤堂ユリカ\n一ノ瀬かえで\n神崎美月' ]
// res => "ジョニー別府 ジョニー別府 神崎美月"

第二引数を関数にした場合の引数は、

  • match: マッチした文字列
  • p1, p2, ...: 正規表現の場合、キャプチャされたサブマッチ文字列
  • offset: マッチした箇所のオフセット
  • strings: 元の文字列

として渡され、return した値に第一引数のマッチした部分が置き換えられるようです。

cf. 引数としての関数の指定セクション
正規表現で一括変換マッチさせて、サブマッチ文字列をjoinさせるサンプルが書かれてて興味深かったです。


[参考]

スラスラ読める JavaScript ふりがなプログラミング (ふりがなプログラミングシリーズ)

スラスラ読める JavaScript ふりがなプログラミング (ふりがなプログラミングシリーズ)

Sublime Text 3 プロジェクトの切替で表示されるプロジェクトをクリーンアップしたい

未だにSublime Textを使っています。

Sublime Textはプロジェクトごとにフォルダや設定を保存でき、⌘ + Ctr + P でプロジェクトごとに環境を簡単に切り替えることが出来ます。
このプロジェクトの設定は{project name}.sublime-project{project name}.sublime-workspaceいうフォルダで保存されています。(メニュー Project > Save Project AS...で、プロジェクトを保存する時に保存場所を選べる)

今回、終わったりしたプロジェクトを整理したのですが、⌘ + Ctr + Pでプロジェクト切替のモーダルを表示させると削除したプロジェクトも表示されてしまっていました。Sublime Textを再起動しても存在しないプロジェクトが選択肢から消えずに表示され続けてちょっと困りました。

f:id:kikiki-kiki:20181206214821p:plain

Session.sublime_session ファイルの "recent_workspaces"から不要なパスを削除する

どうやらSession.sublime_sessionというファイルがあり、その中でプロジェクト情報などを保持しているようです。

Macでは下記にファイルがありました。

/Users/<user name>/Library/Application Support/Sublime Text 3/Local/
  1. セッションファイルっぽいのでSublime Textを終了し、 Session.sublime_sessionテキストエディタで開きます。
  2. ファイルはjson形式になっているので、"recent_workspaces"というキーを検索。
  3. 値の[]内に〜/{project name}.sublime-workspaceといったファイルが羅列されているので、不要なプロジェクトに関連するものを削除
  4. Session.sublime_sessionを保存して、Sublime Textを起動

これでプロジェクトの切替で不要なプロジェクトが表示されなくなりました!

セッションっぽいので時間が経過すれば自動的に存在しないパスのものは消えたのかもしれませんが、試せてないので謎です。クリーンアップみたいなコマンドがあるか、起動時にパス/ファイルが存在してるかチェックしてくれれば便利かなーって少し思いました。
 
できるエンジニアになるには、そろそろエディタも見直すべきか...
(慣れてしまっているから少し億劫...


[参考]