まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

2015年11月

Chrome 拡張アプリケーションとして MQTT パブリッシャー/サブスクライバーとして動作する MQTTLens なるものを使ってみました:
2015111201


これを Chrome ストアからダウンロード(インストール)して起動すると、MQTT のクライアントとして利用できます。パブリッシャーとしてもサブスクライバーとしても動作する、というものです。動作確認に便利そうです。


試しに IBM BluemixNode-RED + IoT Foundation QuickStart 環境で使ってみました。今回の例では MQTTLens を MQTT パブリッシャーとみなして IoT Foundation QuickStart にメッセージをパブリッシュし、Node-RED 側でそのメッセージを受け取って表示する、というシンプルな流れを試してみました。

まずは Node-RED 側を用意します。IBM Bluemix のボイラープレートを使って Node-RED 環境を構築し、Node-RED フローエディタを開き、IBMIOT (input)ノードと Debug (output)ノードを1つずつ配置して接続します:
2015111202


IBMIOT ノードの属性を以下のように指定します。今回は QuickStart 環境を使うので、"Authentication" には "QuickStart" を指定し、"Device Id" として、誰も思いつかないような適当な文字列(この例では "mydeviceid1234")を入力します:
2015111203


最後にこの状態で "Deploy" します。これで Node-RED 側の(つまり MQTT サブスクライバー側の=受け取り側の)準備は完了です。MQTT メッセージが送られてきさえすれば、そのメッセージ内容を表示できる準備が整いました。いつもながら Node-RED だと簡単です:
2015111204


次に MQTTLens 側を設定します。Chrome を起動して MQTTLens を開き(または上記のダウンロード URL からダウンロード後に「アプリを起動」ボタンをクリックし)ます:
2015111209


MQTTLens の初期画面が表示されたら、画面左上の "Connections" 横の+印をクリックします:
2015111205


"Connection Details" 画面が表示されたら、以下の赤枠の内容を指定します。"Connection name" は接続に付ける名称なので任意の文字列で構いません(図では "QuickStart")。"Hostname" には IBM IoT Foundation QuickStart サーバーを指定する必要があるので "quickstart.messaging.internetofthings.ibmcloud.com" を指定します。"Port" はデフォルト値の "1883" のままにします。"Client ID" には QuickStart 用のフォーマットである "d:quickstart:(任意の値):(Device Id)" を指定します。この中の (Device Id) の部分は、先程の Node-RED フローエディタの中で指定した Device Id の値(上記例では mydeviceid1234)と同じものを指定してください。最後に画面右下の "CREATE CONNECTION" ボタンをクリックして接続します:
2015111206


接続すると MQTTLens の画面が以下のように切り替わります(指定した "QuickStart" が "connected" な状態になっていることがわかります)。今回 MQTTLens は MQTT パブリッシャーとして使いたいので、"Publish" と書かれた下の部分を使います。まず "Topic" にはこれも QuickStart 用のフォーマットである "iot-2/evt/(任意の文字列)/fmt/json" と入力し、その下の "Message" に適当な文字列を入力します。最後に "Publish" ボタンをクリックして、このメッセージを QuickStart サーバーにパブリッシュします:
2015111207


正しくメッセージが送信されると、稼働中の Node-RED アプリケーションがこのメッセージを受け取り、Debug タブ内に Message で指定した内容が表示されるはずです:
2015111208


あっさり成功。MQTT パブリッシャー側のデバイスをブラックボックス化しての動作確認などには便利に使えそうで重宝しそうです。


Node.js サーバー上で簡単に CRUD API が作れてしまう StrongLoopローカル環境に導入した StrongLoop 上で作った API を、IBM Bluemix 環境にデプロイする場合の手順を紹介します。まあイメージとしてはローカル環境で開発・テストして、本番環境をスケールも簡単な Bluemix 上で運用する、といった場合の手順になります。

まずはローカル環境上に StrongLoop を導入して、CRUD API を作っておく必要があります。その API を Bluemix 上にデプロイする、という内容です。(CentOS を使った場合ですが)この辺りの手順は以前のエントリで紹介しているので、こちらを参照ください:
CentOS に StrongLoop をインストールする


上記手順で作成した環境に SSH 等のターミナルでログインし、作成した myapp プロジェクトのディレクトリに移動している状態まで準備できているものとします。この時点でカレントディレクトリの内容は以下のようになっているものとします:
2015111201


ローカル環境上に作成した StrongLoop プロジェクトを Bluemix の Node.js ランタイムで運用する場合、プロジェクトで生成されたファイルのうち、1つだけ手動で変更する必要があります。Bluemix のランタイムとして、起動時にこのディレクトリで Node.js を起動させる必要があるため、プロジェクト直下に作成されている package.json ファイルをテキストファイルで開き、以下の青字の1行を書き加えて保存します:
{
  "name": "myapp",
  "version": "1.0.0",
  "main": "server/server.js",
  "scripts": {
    "start": "node .",
    "pretest": "jshint ."
  },
  "dependencies": {
    "compression": "^1.0.3",
      :
      :

これでこのプロジェクトを Bluemix 上の Node.js ランタイムにプッシュできるようになりました。早速 Node.js ランタイムを Bluemix 上に1つ作成します。この図の例では "dotnsf-strongloop" という名称で、米国南部データセンター上に作成しています:
2015111301


cf コマンドを使ってこのランタイム上にローカル環境の strongloop プロジェクトをプッシュします。cf コマンドラインツールをまだ導入していない場合は、こちらから環境にあった cf ツールを選択してインストールしておいてください:
https://github.com/cloudfoundry/cli/releases


改めてローカル環境上から以下のコマンドでカレントディレクトリ(myapp の中)のファイルを、上記で作成したランタイム(上記例であれば dotnsf-strongloop)にプッシュします:
# cf login -a https://api.ng.bluemix.net/  (米国データセンターの場合)
(ユーザー名を指定)
(パスワードを指定)

# cf push dotnsf-strongloop (上記作業で作成したBluemix上のアプリケーション名を指定)

プッシュが成功したら、http://(ランタイムサーバー名)/explorer にブラウザでアクセスしてみましょう:
2015111302


ローカル環境で動いていた StrongLoop の API Explorer が Bluemix 上でも動きました。もちろんローカル環境で動いていたとおりに動くし、作っていた API は Explorer 以外の環境でも(普通に)使えるので、これで作成した API が一般に公開できたことになります。

前回も記述しましたが、StrongLoop を使うとデータベースのモデル(テーブル)定義をするだけで、そのモデルの CRUD(作成/読み/更新/削除) の API を自動的に作成してくれ、加えて確認かつリファレンスとなる Explorer 機能が自動付与されます。肝となる API が簡単に作れるので、この API を API Management で管理監視できるようにすれば、業務向けの API 群の統合なども可能になる、ということになりますね。


IBM が9月に買収した StrongLoop は、Node.jsExpress フレームワークへのコントリビューションの多く、IBM の Node.js による API 開発の中核的な役割になっていくものと思われます。例えば、以下の Watson API リファレンスのサイトは StrongLoop を使って提供されています:
http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/

この StrongLoop (と、前提としての Node.js)そのものは無料で提供されているので、誰でも自分の環境にインストールして使うことができます。 というわけで、CentOS に(Node.js と)StrongLoop をインストールして使ってみました。


StrongLoop は npm で提供されています。なので、まずは Node.js と npm を yum でインストールします:
# yum install epel-release
# yum install nodejs npm --enablerepo=epel

Node.js と npm がインストールできたら、npm を使って LoopBack と StrongLoop をインストールします:
# npm install -g loopback
# npm install -g strongloop

このインストールにはそれなりに時間がかかりますが、作業としてはこれだけで StrongLoop がインストールできます!


では実際に StrongLoop を使ってデータベースのモデルを作り、その CRUD の REST API を公開してみましょう。 まずは空のディレクトリ(下の例では ~/tmp)を作ってそこに移動します:
# cd
# mkdir tmp
# cd tmp

このディレクトリに loopback 環境を作成します:
# slc loopback
2015111001


アプリケーションの名前と、そのアプリケーションの作成ディレクトリを聞かれます。ここでは両方とも myapp と指定しました:
2015111002


すると必要なモジュールのインストールを含めた作業が始まり、完了すると myapp というディレクトリが作られます:
2015111003


出来上がった myapp ディレクトリに移動して、モデルの定義を行います。以下のコマンドを入力します:
# cd myapp
# slc loopback:model

ここからは API で CRUD を行うモデルとして、以下の様な item モデルを定義することにしましょう:
列名列型必須条件
namestringYES
codestringYES
pricenumber 


実際にはこの定義に加え、自動的に id という列が定義されます。では最初に myapp アプリ内に item モデルを作成し、これらの3つの列を順に定義していきます。まず model name は "item" を入力します。次に data-source は、今回はデフォルトのメモリ DB を使うので "db (memory)" を選びます。またこのモデルは永続性(persistant)を有効にしたいので、その Base class には "PersistedModel" を指定してします。またこの item は REST API で公開したいので Expose するかどうかの質問には Yes を選択。この item モデルの複数形名にカスタムな名称を使うわけではない(普通に items とする)ので、Custom plural form の質問は空のままで Enter を押します。そしてこのモデルは common モデルにするので "common" を選択します:
2015111004


次に各列を順に定義します。最初は name 列を定義します。名前には "name" を指定し、その type には "string" を、そして必須かどうかの属性は必須なので "Y" を入力します:
2015111005


続けて "code" 列を定義します。同様にして名前には "code"、type には "string"、そして必須属性を "Y" で指定します:
2015111006


最後に "price" 列を定義します。名前には "price"、type には "number" 、必須属性を "N" で指定します:
2015111007


これで全ての列を指定し終わったので、最後に名前欄を空欄にして Enter を押します。これでモデルの定義が完了です:
2015111008


ここまでの作業ができたら、カレントディレクトリで node.js を起動します:
# node .

すると、デフォルトでは 3000 番ポートで node.js が待受る形で起動します:
2015111001


この状態で表示されているアドレス(http://(strongloopをインストールしたホスト名):3000/explorer)にブラウザでアクセスしてみると、作成した myapp アプリケーション内に定義されている API の一覧が表示され、その中には item モデルについても含まれているはずです:
2015111002


item と書かれた箇所をクリックすると展開され、この item モデル向けに用意されている API の一覧が表示されます。特に何もしなくても item モデルの定義をしただけで一通りの CRUD 操作ができるような API が準備されていることがわかります:
2015111003


用意された API はこの画面から実際に動かして試してみることもできます。例えば一番上にある /items への GET を実行してみましょう。このエントリの /items を書かれた箇所をクリックして開くと、この GET リクエスト API に関する情報が表示されます:
2015111101


この画面内の "Try it out" と書かれたボタンをクリックすると実際に API を発行することができます。実際にクリックすると curl で実行されたコマンドや実際にリクエストされた API の URL などが確認できます。また Response Body には実行結果が表示されます。この例では実行結果は [] と、空の配列になっているので、実行しても何も得られなかった、ということになります(今はまだ中身がないのでこれで正しい実行結果です):
2015111102


では実際に item レコードを作ってみましょう。レコードを作成するには POST リクエストを実行することになるので、/items への POST エントリを開き、Parameters 欄の data の部分に以下のようなフォーマットの JSON データを入力して "Try it out!" ボタンをクリックします( "id" は自動割り振りされるので、指定してあってもいなくても構いません。また実際に指定するデータは適当で構いません):
{
  "name": "アディゼロ匠 B22875",
  "code": "4055339759613",
  "price": 12050,
  "id": 0
}

2015111103


問題なく処理が成功すると、以下の様な結果が得られます。Response Code が 200 になっていれば成功を意味しており、Response Body には以下の様な JSON が返されます("id" の値として 0 を指定していましたが、自動割り振りされた結果の 1 が付与されています)。このデータが正しく追加された、ということになります:
{
  "name": "アディゼロ匠 B22875",
  "code": "4055339759613",
  "price": 12050,
  "id": 1
}

2015111104


データが正しく追加されたので、改めて再度 /items の GET を実行すると、今度は Response Body の結果は [] ではなく、先程入力したデータが含まれた配列になっているはずです。モデルを定義しただけで自動生成された CRUD の API が( /items の GET と POST だけですが)正しく動いていることが確認できました:
2015111105


RDB のテーブルに相当するレコードを定義すれば、(コードを書くこともなく)即 CRUD API が用意される、という意味では便利です。


いずれはモニタリングやトレーシングなどもできる StrongLoop Arc についても勉強して、ここで紹介するつもりです。



久しぶりに Twitter API キーやアクセストークンを新規に取得しようとしたら、それまで知っていた手順と違っていたので、改めて書き残しておきます。

まず以下のサイトへ行きます。ログインしていない場合は右上に "Sign in" というリンクが表示されるので、そこからログインします:
Twitter Application Management


Twitter Application Management サイトにログインすると、自分が過去に作った Twitter アプリの一覧が表示されます(まだ作ったことがない場合は何も表示されないはずです)。新たに API キーを取得するには新しいアプリを1つ定義します。画面右上の "Create New App" と書かれたボタンをクリックします:
2015111101


新規に作成するアプリケーションの概要を入力します。このうち "Name" はアプリケーションの名称ですが、全半角スペースを含むことができません。また、既に誰かが使っている名称を使うこともできません。1語の単語の形でユニークな名称を指定してください。"Description" はアプリケーションの説明文ですが、空にはできません。"WebSite" はアプリケーションのウェブサイト URL でこれも必須ですが、Streaming API などウェブサイトの存在しないアプリを作る場合もあると思います。ここは http://127.0.0.1 で始まるような名前を指定しても動作には支障なさそうでした。Callback URL は OAuth のコールバック先ですが、必須ではありません:
2015111102


全て入力したら下にスクロールして、Developer Agreement を確認し、内容に同意できる場合は "Yes, I agree" にチェックを入れて、最後に "Create you Twitter application" ボタンをクリックします:
2015111103


指定したアプリケーションの API キーが作成されます。API キーを確認するには、"Keys and Access Tokens" タブを開くと、その中に API Key や API Secret などが表示されているはずです:
2015111104


一方、アクセストークンはこの段階ではまだ作成されていないはずです。アクセストークンが必要な場合はこのページを下にスクロールして、まだ作成されていないことを確認した上で "Create my access token" ボタンをクリックします:
2015111101


処理が成功すると同ページの内容が書き換わり、アクセストークンとアクセストークンシークレットが確認できるようになります:
2015111102



以前の方法だと、最初は https://dev.twitter.com/ からスタートしたような記憶があるんだけど、今はそこからだと API Key 取得ページへのリンクが見当たらないんだよな、、変わったのかな?


話題の分散演算環境である Apache Spark を1台の CentOS 6 に導入する手順を紹介します。今回紹介する内容はプレビルド版を使った方法なので、おそらく CentOS の他バージョンや、RHEL, Ubuntu といった他の Linux ディストリビューションでもほぼ同様の方法で導入できると思います。また分散環境で Spark をインストールするのが本来の使い方だと理解した上で、ここではシェルなどを自由に気軽に試せる環境を作りたいので、1台の CentOS を使う、という方法を紹介します。


Apache Spark は Java VM 上で動きます。なので前提として、Java のランタイム環境が必要です。 まだ導入されていない場合はあらかじめ Java を導入しておいてください。CentOS で OpenJDK 1.7.0 を使う場合であれば、このコマンドで導入できます:
# yum install java-1.7.0-openjdk

Java の導入までできてしまえば後はどの Linux ディストリビューションでも動くと思います。次に Apache Spark 本体をダウンロードします。このブログエントリを書いている時点での最新版は 1.5.2 なので、このバージョンのビルド済みバイナリを入手して、/opt/spark 以下に展開します:
# cd /tmp
# wget https://archive.apache.org/dist/spark/spark-1.5.2/spark-1.5.2-bin-cdh4.tgz
# cd /opt
# tar xzvf /tmp/spark-1.5.2-bin-cdh4.tgz
# mv spark-1.5.2-bin-cdh4 spark

これでインストール完了です。動作確認の意味で Spark-Shell と呼ばれるシェルインターフェースを起動してみましょう:
# cd /opt/spark/bin
# ./spark-shell
2015111001


"Spark" と書かれたそれっぽい画面がバージョン名とともに表示され、各種ライブラリのロードが行われます(Spark context が sc という変数で使える、というメッセージも表示されています)。Spark-Shell のロードが完了すると、 "scala>" というプロンプトが表示されます:

2015111002


では Spark の機能を使って Spark の README.md ファイルの文字数を カウントしてみます。README.md ファイルは Spark ディレクトリ(今回の例では /opt/spark/)の直下にあるので、sc 変数を使って以下のようにプロンプトに入力します。
scala> sc.textFile( "/opt/spark/README.md" ).count()

すると Spark の機能で指定したファイルが読み込まれ、その文字数(以下の例では 98)がカウントされて表示されます:

2015111003


正しく動作していることが確認できました。exit と入力すると、Spark-Shell を終了します。

IBM Bluemix でも Apache Spark を使う機会があると思うのですが、自分の手元に1個インスタンスがあると色々試せて便利ですよね。この後もちょっとした応用的なブログを書くつもりなので、それらはこのインスタンスを使って書いていこうと思ってます。


このページのトップヘ