Sunday, August 31, 2014

jQuery Memo

jQUeryについてのメモ。正直、まともに勉強したことないからググる率高いのん…(;ω;

selector - scriptタグ

セレクタの使い方。<script id="vs" type="x-shader/x-vertex">...</script>…こういうタグを取得した場合こうなる。続いてtype属性の値を取得したい場合はattr(name)を使う。

var el = $('script#vs');
el.attr('type');

Written with StackEdit.

Friday, August 22, 2014

NodeBB on Windows8

公式のインストールガイドでまさかのOSXがない…!ので、やむをえずWindows8(on Surface 3 Pro)にインストールする。

事前インストール

インストール

redisサーバーを起動させておく。

アプリにまんまStart Redis Serverってあるから、それを実行したけど激しくかっこ悪いorz

ターミナル(ckw x Nyaos)開いて、粛々とコマンドを打つ。

$ git clone https://github.com/NodeBB/NodeBB.git
$ cd NodeBB
$ npm install

最初の起動では初期セットアップを行う。

$ node app.js

全部デフォルトのままでいいよって書いてあったが流石に管理者アカウントくらいは設定。インストール時に幾つかwarn レベルの警告が出たけど、中でもこれ大丈夫か?ってのが1つ。

arn: No administrators have been detected, running initial user setup
(node) warning: possible EventEmitter memory leak detected. 11 listeners added.
Use emitter.setMaxListeners() to increase limit.
Trace
    at ReadStream.EventEmitter.addListener (events.js:179:15)
    at ReadStream.Readable.on (_stream_readable.js:667:33)
    at new Interface (readline.js:124:11)
    at Object.exports.createInterface (readline.js:38:10)
    at read (c:\Users\Yukaary\home\project\nodebb\NodeBB\node_modules\prompt\node_modules\read\lib\read.js:45:23)
    at EventEmitter.prompt.getInput (c:\Users\Yukaary\home\project\nodebb\NodeBB\node_modules\prompt\lib\prompt.js:502:3)
    at get (c:\Users\Yukaary\home\project\nodebb\NodeBB\node_modules\prompt\lib\prompt.js:321:12)
    at c:\Users\Yukaary\home\project\nodebb\NodeBB\node_modules\prompt\lib\prompt.js:280:7
    at iterate (c:\Users\Yukaary\home\project\nodebb\NodeBB\node_modules\prompt\node_modules\utile\node_modules\async\lib\async.js:134:13)
    at Object.async.eachSeries (c:\Users\Yukaary\home\project\nodebb\NodeBB\node_modules\prompt\node_modules\utile\node_modules\async\lib\async.js:150:9)

イベントエミッタ―のリスナー制限数が10になってる?警告が言う通り、最大リスナ数を上げればいいのかな。試用してて動きが怪しかったらやり直してみよう。githubのmasterブランチってそもそも安定してるか疑わしいのがちょっとね…。

初期セットアップが終わったら、もう一度

$ node app.js
info: NodeBB v0.5.0-2 Copyright (C) 2013-2014 NodeBB Inc.
info: This program comes with ABSOLUTELY NO WARRANTY.
info: This is free software, and you are welcome to redistribute it under certain conditions.
info:
info: Time: Fri Aug 22 2014 23:12:05 GMT+0900 (東京 (標準時))
info: Initializing NodeBB v0.5.0-2
info: * using configuration stored in: c:\Users\Yukaary\home\project\nodebb\NodeBB\config.json
info: * using redis store at 127.0.0.1:6379
info: * using themes stored in: c:\Users\Yukaary\home\project\nodebb\NodeBB\node_modules
warn: You have no redis password setup!
morgan deprecated morgan(options): use morgan("default", options) instead src\logger.js:128:22
morgan deprecated default format: use combined format src\logger.js:128:22
info: [user.startJobs] Registering User Jobs
info: [meta/css] Minifying LESS/CSS
info: [themes] Compiling templates
info: [themes] Successfully compiled templates.
info: NodeBB attempting to listen on: 0.0.0.0:4567
info: NodeBB is now listening on: 0.0.0.0:4567
info: [meta/css] Done.
info: [meta/js] Successfully minified.
info: [meta/js] Retrieved Mapping.
info: [meta/js] Compilation complete
info: NodeBB Ready

なんやかんや出てきたけど、見た感じ動いてそう。nodeは今のところ手順通りやったけど動かない!のが少ないからいいな。削除も楽だしね。

試用

http://127.0.0.1:4567/ にアクセス。表示された!

以下、使ってみた時のメモ.


profile画像をアップロードできない。デフォルト画像を保存して再アップロードしても無理だからバグかな?
これっていわゆる掲示板ツールみたいだな。トピックという単位で話題を管理でき、それぞれのトピックにスレッドを立ててやり取りするスタイル。デフォルトでは12のトピックが定義されている。

ログインしている他のユーザに対して1:1のチャットを始めることができる。チャット開始時にリアルタイムで通知が来ている(小さいびっくりマークだけども)

尚、投稿の際の記法はMD形式っぽい。これは地味にありがたい。


手軽にコミュニケーションサイトを立ち上げたいときには、結構いい選択肢かもしれない。

Written with StackEdit.

Webアプリ開発者向けの基本Javascriptツール

InfoWorldのSlideshow で紹介されていたのでなんとなく。

自分が知らないツールがたくさんある現実。

Meteor

Javascriptで書かれた多Web Application Frameworkか。Backbone.jsやAngular.jsのお仲間なのかな。

気になった特徴が幾つか。

2.Live page updates.

templateさえ書いてしまえば、データベースで変更があったときに自動更新。なんてこった。push型通信がデフォルトで実装されてるのかな。

3.Clean, powerful data synchronization.

RESTのendpointからデータをロードする必要がなくなっている。サーバー側のコードのようにデータベースへのアクセスを実現できる。

7.Fully self-contained application bundles.

1コマンドでアプリケーションをtarball形式にコンパイルできる。これをnode.jsが動いているサーバー上で解凍すれば、1コマンドで実行できる。こにより特定のホスティングプロバイダによる制約を受けずに済む。

8.Interoperability.

単純なDDPプロトコルを実装するだけで何でも(ネイティブなモバイルアプリから従来データベースまで?)Meteorに接続できる。

文字通り受け取ればRaspbery Pi使ってセンサ情報を取得、node経由でサーバーに送ろうとしている自分には朗報なのですが。

Epoch

d3.js をベースにしたチャート描画モジュールなのかな。d3.jsを直で触るのは色々つらいので最近この手のやつが幾つかある印象。

Raspberry Piで収集したセンサ情報を可視化するときに使ってみようかな。そのためにはnode.js > wiringPi でセンサ情報を継続的に取れないとな。後でwiringPi直で使った場合のSPI経由データ取得方法を調べよう…。

Web Starter Kit

google様謹製のWebApi開発ツールキット?。 開発するWebアプリがマルチデバイス(古いタイプのiPadとかAndoroid端末とか…)に対応するよう色々と便宜を図ってくるらしい。なんか面白そう。

reveal.js

htmlベースのパワポだっ。かっこいいなこれ。

RxJs

複数のデータストリーム(マウス操作、キーボード操作、tweet、etc…)を同時に監視して、ユーザの直接的な操作とは無関係にイベントを発生させる用のライブラリなのかな?

簡単に概要読んだくらいじゃ全容が分からないorz。後でもう少し詳しく読む…後で。

NodeBB

github

nodeで書かれたコミュニケ―ションWebアプリ。機能がとても豊富そう。何より、Chatがっあるぞっ Chartだーーーッ!

★簡単そうだったら自宅のOSXにインストールしてみようかな。

Odyssey.js

github

ブラウザ上で地図(map)を表示、簡単なコーディングでインタラクティブな操作を可能にするライブラリってことでいいのかな。旅行記なんかを作るときに使えるぜって書いてある気がする。既存のWebアプリにインタラクティブなMapを簡単に追加したりできるなら歓喜する人たちがいそうだ…。

PlayCanvas

WebGL Game Engineを使ったゲーム開発環境?
サイト見てきたけど、なんか凄い。ここまでやるか&できるのな…。

Deb.js

javascriptで書いたアプリのデバッグヘルパー。

SPIについてお勉強

Raspberry PI SPIによるアナログ―デジタル変換について

SPI

そもそもSPIって何ぞ? wiringPiを作った人のサイトで解説されてた。助かる(;ω;

SPI Serial Peripheral Interface

モトローラによって開発された同期型のシリアルクロック、双方向バス(マスター/スレーブ)のインターフェース。

データはクロック信号(Wire1)に同期して送信(Wire2)される。また、データを受信するワイヤ(Wire3)があり、最後にチップセレクトとして動作する4本目のワイヤ(Wire4)がある。送信/受信それぞれにワイヤとピンが用意されるからfull-duplexである。4本のワイヤを使うので4-wireバスとも言われる。

master/slave方式により、バス上に存在するデバイスではどれでも他のデバイスにデータ転送を行うことができる。チップセレクトワイヤは複数存在することができ、同じSPIバス上で複数のデバイスと接続できる。

Raspberry PIはマスターモードのみ実装されており、2つのチップセレクトピンを持っているため、2のSPIデバイスを同時に制御できる。(ただ、いくつかのデバイスは独自のサブアドレススキームを持っていることがあり、この場合はもっと多くのデバイスを設置できる。)

SPIについて覚えておかなければならないのは、バイトデータを受信するために、バイトデータを送信しなければならない点にある。

MCP3002 2channel, 10-bit analog to digital converterの例。

このチップはSPIクロックを内部ロジックを動かすために利用している。MCP3002には4bit長のコマンドのみで十分だが、帰ってくるデータ長は最後のコマンドビットの後ろから数え始めて10bitだ。従って実際に通信するときは2byteのデータを送り、2byteの結果を得ることになる。データは5bit目から始まって10bit後ろまで続いている。従ってクロックが動作している間、MCP3002との間では2byteを送り、2byteの結果を取得、この結果から10bitぶんのデータビットを取得する必要がある。


ここまで読んでrubyのpi_piperで書かれたサンプルコードの意味が分かった。

PiPiper::Spi.begin do |spi|
    raw = spi.write [0b01101000,0]
    value = ((raw[0]<<8) + raw[1]) & 0x03FF
end

spi経由でMCP3002に送っているのはコマンドビットである4bitのみ。上の例だと1001(先頭ビットは0固定)。6bit目からは返信されてくるデータビットのためにダミーバイトを11bit送っている。

データの送受信が同時に実行されているから、結果はrawに入ってくる。最初のバイトの先頭4byteは意味がないので8bit左シフトした上で不要な部分を論理積(0x3FF)で排除し。raw[0]ってやると16bit長のデータが得られるっぽいな。ruby内部でint型は16bitだからってことか。

Thursday, August 21, 2014

raspberry pi スイッチでLED点灯

練習がてらブレッドボード上で回路を組んで、前回同様にrubynodeで実装してみた。

ruby

require "open3"

def readswitch
    out, err, status = Open3.capture3("gpio read 6")
    return out
end

def blink(value)
    puts "LED would be set on " + value
    Open3.capture3("gpio write 1 " + value)
end

Open3.capture3("gpio mode 1 OUT")
Open3.capture3("gpio mode 6 IN")

loop {
    led = readswitch()
    blink(led)
    sleep 0.1
}

node

var Q    = require('q');
var exec = require('child_process').exec;

exec('gpio mode 1 OUT');
exec('gpio mode 6 IN');

function blink(value) {
    console.log('LED would be set on ' + value);
    exec('gpio write 1 ' + value);
}

function readswitch() {
    var deffered = Q.defer();
    exec('gpio read 6',
        function(error, stdout, stderr) {
            deffered.resolve(stdout);
        });
    return deffered.promise;
}

setInterval(function() {
    readswitch().then(blink);
}, 100);

nodeでは相変わらずQ(deffered)を使いループに代わりにsetIntervalを使っている。慣れるとこちらのほうが違和感が無くなってくる不思議。

回路図あげたいなどうしようかな…。

Written with StackEdit.

raspberry pi B+ LED x PWM

raspberry pi B+ でPWMを使って明るさの制御をやったときのメモ.

rubyとnodeでそれぞれサンプルコードを記述。配線はごく単純にLED, 抵抗, ケーブル2本。

ruby

require "open3"

out, err, status = Open3.capture3("gpio mode 1 pwm")
out, err, status = Open3.capture3("gpio pwm-bal")
out, err, status = Open3.capture3("gpio pwmr 1024")

0.step(1023, 8) do |x|
    Open3.capture3("gpio pwm 1 " + x.to_s)
    sleep 0.1
end

0.step(1023, 8) do |x|
    Open3.capture3("gpio pwm 1 " + (1023-x).to_s)
    sleep 0.1
end

rubyにはwiringpiのモジュールがあってgemでインストールできるのだけど(参考)、まだModel B+に対応していないぽい。仕方がないので直接外部コマンドを叩くことにした。

  • gpio mode 1 pwm …GPIOピン1をpwmモードに変更
  • gpio pwm-bal …pwmの制御モードを「バランス」に設定
  • gpio pwmr 1024 …pwmの制御幅を「1023」に設定
  • gpio pwm 1 x …pwmによる電圧調整(厳密には電圧一定でパルス調整なんだろうけど)

node

var Q = require('q');
var exec = require('child_process').exec;

// この3コマンドもdefferedで実行制御したほうがいいかも.
exec('gpio -g mode 18 pwm');
exec('gpio pwm-bal');
exec('gpio pwmr 1024');

var step = 8;

function inc_intensity() {
    var deffered = Q.defer();
    var intensity = 0;
    var id = setInterval(function() {
        intensity += step;
        if(intensity > 1023) {
            clearInterval(id);
            deffered.resolve();
            return;
        }
        exec('gpio pwm 1 ' + intensity);
    }, 100);
    return deffered.promise;
}

function dec_intensity() {
    var deffered = Q.defer();
    var intensity = 1023;
    var id = setInterval(function() {
        intensity -= step;
        if(intensity < 0) {
            clearInterval(id);
            deffered.resolve();
            return;
        }
        exec('gpio pwm 1 ' + intensity);
    }, 100);
    return deffered.promise;
}

inc_intensity().then(dec_intensity);

やってることはrubyのコードで一緒。ただし、nodeは非同期で動いちゃうので、Q(deffered)を使って明るさの制御順を指定している。最初はだんだん明るくして…次にだんだん暗くする。

まとめ

単純なプログラムだけどruby, nodeそれぞれで特色が出るなぁ。rubystepを使いつつnodedeffered使えたら最高なんだけど…coffee script、type script使えって話ですかね。

Written with StackEdit.

Sunday, August 17, 2014

node.js q promise

node.jsでpromise(deffered)を使いたかったので現状どうなってるのか簡単に調べた。
まず、本家のPromiseだけど安定板のv0.10.30ではまだサポートされていない。仕方ないのでlatestv0.11.13を使って試してみる。

node.js Promise

サンプルコード。
function promiseA() {
    return new Promise(function(onFulfilled, onRejected) {
        setTimeout(function() {
            console.log('I execute first.');
            onFulfilled();
        }, 1000);
    });
}

function promiseB() {
    return new Promise(function(onFulfilled, onRejected) {
        setTimeout(function() {
            console.log('I execute second.');
            onFulfilled();
        }, 5000);
    });
}

function promiseC() {
    return new Promise(function(onFulfilled, onRejected) {
        setTimeout(function() {
            console.log('I execute third.');
            onFulfilled();
        }, 5000);
    });
}


promiseA().then(promiseB).then(promiseC);
// ダメ. 関数を実行してしまい、promiseBとpromiseCが同時に動く.
//promiseA().then(promiseB()).then(promiseC());
こんな感じか。
最初はnew Promise(..)で取得したオブジェクトを直接thenに指定してしまい、promiseB, promiseCが同時に実行されてはまる。
お馬鹿な例。
var promiseA = new Promise(function(fulfill, reject) {
    setTimeout(function(){ console.log('first.') },1000);
});
var promiseB = new Promise(function(fulfill, reject) {
    setTimeout(function(){ console.log('second.') },1000);
});
var promiseC = new Promise(function(fulfill, reject) {
    setTimeout(function(){ console.log('third.') },1000);
});

promiseA.then(promiseB).then(promiseC);
newした瞬間に処理実行されちゃってるからな。このnew、地味にこういう誤解を招くと思うんだけど…。

Q

node.jsの現バージョンであるv0.10.30はPromiseをまだ実装していない。ぐぐったらQがデファクトっぽい扱いだったのでこちらで同様の事を試みる。

サンプルコード
var Q = require('q');

function one() {
    var deffered = Q.defer();

    setTimeout(function() {
        console.log('execute one.');
        deffered.resolve();
    }, 1000);

    return deffered.promise;
}

function two() {
    var deffered = Q.defer();

    setTimeout(function() {
        console.log('execute two.');
        deffered.resolve();
    }, 1000);

    return deffered.promise;
}

function three() {
    var deffered = Q.defer();

    setTimeout(function() {
        console.log('execute three.');
        deffered.resolve();
    }, 1000);

    return deffered.promise;
}

one().then(two).then(three).done();
関数内でdefferedを作り、返り値をdeffered.promise、処理完了をdeffered.resolve()で伝えてあげればいいみたい。こっちのほうが凄いしっくりくる。node.js/Promisethenable使えば似たような感じになりそうだけど、いちいち自前でnewを書くのがちょっと面倒に感じた。

Saturday, August 16, 2014

node.js fs.watch

node.jsのメモ.

fs.watch(filename, [options], [listener])

ファイルまたはディレクトリ名をfilenameに指定すると、変化があった時にコールバックlistnerを実行する。listner関数は2つの引数を取る。

  • eventchange, renameのどちらか。
  • filename … ファイルパス。提供されない場合もある。

optionのデフォルトは{persistent: true}で恒久的に監視を続けるとかなんとか。

この関数は完全に動作を保証するものではなく、動作するOSによって動きが異なるかもしれない。

OS ネイティブコール
Linux inotify
Windows ReadDirectoryChangesW

サンプルコード

Watcher.prototype.start = function() {
    var watcher = this;
    fs.watch(watchDir, function(event, filename) {
        console.log('event is: ' + event);
        if(filename) {
            console.log('filename provided: ' + filename);
        }
        watcher.watch();
    });
}

watcher.watch()は監視しているディレクトリに対して、実際に何らかの処理を行う。


これでVoiceconsoroid.wavがwavファイルを作成し終えた事を感知して転送などの処理をトリガーできる。

Written with StackEdit.

Friday, August 15, 2014

やっぱりあった

リモートで電源のON/OFFをしてくれる賢い奴。

Belinが販売しているWeMo。

http://www.belkin.com/us/Products/home-automation/c/wemo-home-automation/

コンセントと家電の間に差し込む形で設置。これとは別にモーションセンサを電源管理したい家電に取り付けることで、何かあったら自動的に電源OFFにできるらしい。不在の時に犬が悪戯したら勝手に電源落とすとかなんとか。「そっちかよっ」って思った。


個人的には家に設置したサーバーを必要なときのみ電源ONして起動、必要なくなったらOFFするって使い道を考えてたんだけど…。


こういうの、PLCと組み合わせたら面白いことができそうだけどな。ついでに家電に電源リモートスイッチ経由で色々コマンド送ったりモニタリングできるようにして欲しい。それで誰が嬉しいのか分からんけど私は欲しい(キリッ


Written with StackEdit.

raspberry PIでLED光らせてキャッキャウフフ

久しぶりなせいか妙に楽しいwww
GPIOポートにアクセスする方法は何種類かある。手元で確認したのは
  1. sys/class/gpio/exportを使う方法
  2. wiringPiを使う方法
  3. RPi.GPIO(raspberry gpio python)を使う方法
1.の方法はrootじゃないと使えない & 使用するポートを毎回エクスポートして、向き(direction)を設定しなければならないなど実用には向いていないので現状だとwiringPIがよい感触。公式はRPi.GPIO(PythonのGPIO入出力モジュール)押しっぽい。Raspbianにプレインストールされてるし。
とりあえずLED光らせてみたのと、ボタンのON/OFFを読み取れる(デフォルトON, デフォルトOFFの両方試した)事を確認。どちらもブレッドボード上で単純な回路を作った。
回路触るの久々だったから妙に楽しかったでござる。読み取り簡単だし、これはセンサとか付けたくなるなっ。
Written with StackEdit.

Thursday, August 14, 2014

fig and docker on OSX

Docker絡みの話.
figというdocker用のオーケストレーション?ツールがDocker社に買収されて公式ツールになるらしいので触ってみた。
Dockerの軽量さを活かして個人のPCでそこそこのシステムを動かせるならとても嬉しいのだけど。
bash-3.2$ fig run web rails new . --force --database=postgresql --skip-bundle
結構時間がかかる。サイトの説明を見てみると…
Fig will build the image for the web service using the Dockerfile. Then it’ll run rails new inside a new container, using that image.
上のコマンドを実行すると、figはまずDockerfileをベースにイメージを作成、このイメージを使ったコンテナ内でrails newを実行する…らしい。
なるほど重い訳だ。
Dockerfileの中身.
FROM ruby
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
RUN bundle install
ADD . /myapp
  • FROM ruby … rubyという名前の基本イメージをベースにする。
    • 名前の通りrubyに特化したlinuxイメージなんだろな
  • RUN apt-get … postgresql用のバイナリをインストール?
  • 以降… /myappディレクトリを作ってアプリの雛形をbundleでインストール
fig run実行時のログ。
bash-3.2$ fig run web rails new . --force --database=postgresql --skip-bundle
Creating fig_db_1...
Pulling image postgres...
4ee79ff38eba: Pulling dependent layers
...
c84d12730ef9: Download complete
Building web...
Pulling repository ruby
011aa33ba92b: Download complete
...
6bdb3289ca8b: Download complete
# Executing 3 build triggers
Step onbuild-0 : ADD . /usr/src/app
 ---> d0cee0e603a2
Step onbuild-1 : WORKDIR /usr/src/app
 ---> Running in 1ec73019cb0d
 ---> a094423d3c26
Step onbuild-2 : RUN [ ! -e Gemfile ] || bundle install --system
 ---> Running in a95fb45a003f
Don't run Bundler as root. Bundler can ask for sudo if it is needed, and
installing your bundle as root will break this application for all non-root
users on this machine.
Fetching gem metadata from http://rubygems.org/...........
Resolving dependencies...
Installing rake 10.3.2
Installing i18n 0.6.11
Using minitest 4.7.5
Installing multi_json 1.10.1
Installing thread_safe 0.3.4
Installing tzinfo 0.3.41
Installing activesupport 4.0.2
Installing builder 3.1.4
Installing erubis 2.7.0
Installing rack 1.5.2
Installing rack-test 0.6.2
Installing actionpack 4.0.2
Installing mime-types 1.25.1
Installing polyglot 0.3.5
Installing treetop 1.4.15
Installing mail 2.5.4
Installing actionmailer 4.0.2
Installing activemodel 4.0.2
Installing activerecord-deprecated_finders 1.0.3
Installing arel 4.0.2
Installing activerecord 4.0.2
Using bundler 1.6.2
Installing hike 1.2.3
Installing thor 0.19.1
Installing railties 4.0.2
Installing tilt 1.4.1
Installing sprockets 2.12.1
Installing sprockets-rails 2.0.1
Installing rails 4.0.2
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
 ---> 0a6f7eda2733
 ---> 0a6f7eda2733
Removing intermediate container db6342aaa98c
Removing intermediate container 1ec73019cb0d
Removing intermediate container a95fb45a003f
Step 1 : RUN apt-get update -qq && apt-get install -y build-essential libpq-dev
 ---> Running in b676849b1b1e
Reading package lists...
Building dependency tree...
Reading state information...
build-essential is already the newest version.
The following packages were automatically installed and are no longer required:
  libyaml-0-2 rubygems-integration
Use 'apt-get autoremove' to remove them.
Suggested packages:
  postgresql-doc-9.4
The following packages will be upgraded:
  libpq-dev libpq5
2 upgraded, 0 newly installed, 0 to remove and 260 not upgraded.
Need to get 277 kB of archives.
After this operation, 345 kB of additional disk space will be used.
Get:1 http://http.debian.net/debian/ jessie/main libpq-dev amd64 9.4~beta2-1 [159 kB]
Get:2 http://http.debian.net/debian/ jessie/main libpq5 amd64 9.4~beta2-1 [119 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 277 kB in 2s (134 kB/s)
(Reading database ... 30861 files and directories currently installed.)
Preparing to unpack .../libpq-dev_9.4~beta2-1_amd64.deb ...
Unpacking libpq-dev (9.4~beta2-1) over (9.3.4-1+b1) ...
Preparing to unpack .../libpq5_9.4~beta2-1_amd64.deb ...
Unpacking libpq5:amd64 (9.4~beta2-1) over (9.3.4-1+b1) ...
Setting up libpq5:amd64 (9.4~beta2-1) ...
Setting up libpq-dev (9.4~beta2-1) ...
Processing triggers for libc-bin (2.18-7) ...
 ---> 2f06bd40a808
Removing intermediate container b676849b1b1e
Step 2 : RUN mkdir /myapp
 ---> Running in 1348b1fc6e2e
 ---> f3caa2b67285
Removing intermediate container 1348b1fc6e2e
Step 3 : WORKDIR /myapp
 ---> Running in 3889c5376814
 ---> e8976281600f
Removing intermediate container 3889c5376814
Step 4 : ADD Gemfile /myapp/Gemfile
 ---> 1ebecb73d3d2
Removing intermediate container 6def9af6926a
Step 5 : RUN bundle install
 ---> Running in e642bd491e17
Don't run Bundler as root. Bundler can ask for sudo if it is needed, and
installing your bundle as root will break this application for all non-root
users on this machine.
Fetching gem metadata from http://rubygems.org/...........
Resolving dependencies...
Using rake 10.3.2
Using i18n 0.6.11
Using minitest 4.7.5
Using multi_json 1.10.1
Using thread_safe 0.3.4
Using tzinfo 0.3.41
Using activesupport 4.0.2
Using builder 3.1.4
Using erubis 2.7.0
Using rack 1.5.2
Using rack-test 0.6.2
Using actionpack 4.0.2
Using mime-types 1.25.1
Using polyglot 0.3.5
Using treetop 1.4.15
Using mail 2.5.4
Using actionmailer 4.0.2
Using activemodel 4.0.2
Using activerecord-deprecated_finders 1.0.3
Using arel 4.0.2
Using activerecord 4.0.2
Using bundler 1.6.2
Using hike 1.2.3
Using thor 0.19.1
Using railties 4.0.2
Using tilt 1.4.1
Using sprockets 2.12.1
Using sprockets-rails 2.0.1
Using rails 4.0.2
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
 ---> c1f3d4fff3fe
Removing intermediate container e642bd491e17
Step 6 : ADD . /myapp
 ---> eda8814fd49e
Removing intermediate container 520b22eccc25
Successfully built eda8814fd49e
       exist  
      create  README.rdoc
      create  Rakefile
      create  config.ru
      create  .gitignore
       force  Gemfile
      create  app
      create  app/assets/javascripts/application.js
      create  app/assets/stylesheets/application.css
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/views/layouts/application.html.erb
      create  app/assets/images/.keep
      create  app/mailers/.keep
      create  app/models/.keep
      create  app/controllers/concerns/.keep
      create  app/models/concerns/.keep
      create  bin
      create  bin/bundle
      create  bin/rails
      create  bin/rake
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/filter_parameter_logging.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/secret_token.rb
      create  config/initializers/session_store.rb
      create  config/initializers/wrap_parameters.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  lib
      create  lib/tasks
      create  lib/tasks/.keep
      create  lib/assets
      create  lib/assets/.keep
      create  log
      create  log/.keep
      create  public
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/favicon.ico
      create  public/robots.txt
      create  test/fixtures
      create  test/fixtures/.keep
      create  test/controllers
      create  test/controllers/.keep
      create  test/mailers
      create  test/mailers/.keep
      create  test/models
      create  test/models/.keep
      create  test/helpers
      create  test/helpers/.keep
      create  test/integration
      create  test/integration/.keep
      create  test/test_helper.rb
      create  tmp/cache
      create  tmp/cache/assets
      create  vendor/assets/javascripts
      create  vendor/assets/javascripts/.keep
      create  vendor/assets/stylesheets
      create  vendor/assets/stylesheets/.keep
最初はDocker用の基本イメージを作っている(dbとweb、2つ作ってる?)。
ハッシュ値で表されているのはfs layerと呼ばれるもの(多分)。LXCの「元のイメージを壊さずに順番に重ねていく」ということかな。
基本イメージの立ち上げ後、Dockerファイルの2行目以降に書いた命令が順番に実行されていく。
コマンド実行後、Gemfileが上書きされている。Gemfileを開いてtherubyracerを有効にして再ビルドしろと書いてあるのでやってみる。
bash-3.2$ fig build
db uses an image, skipping
Building web...
# Executing 3 build triggers
Step onbuild-0 : ADD . /usr/src/app
 ---> 11334d9d17c3
...
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
 ---> 94c537526f32
Removing intermediate container 3d782eb9c15f
Step 6 : ADD . /myapp
 ---> 280d26cf922d
Removing intermediate container 0265b7152c45
Successfully built 280d26cf922d
流石にfs layerの再ダウンロードからはやり直していない。よかったっ。
続いてデータベースの接続先を書き換える。config/database.ymlを開いて接続先をデフォルトのlocalhostからコンテナdb_1に変更。
development: &default
  adapter: postgresql
  template: template0
  encoding: unicode
  database: postgres
  pool: 5
  username: postgres
  password:
  host: db_1

test:
  <<: *default
  database: myapp_test
そんでもってfig up
bash-3.2$ fig up
Recreating fig_db_1...
Recreating fig_web_1...
Attaching to fig_db_1, fig_web_1
db_1  | LOG:  database system was shut down at 2014-08-15 05:24:52 UTC
db_1  | LOG:  database system is ready to accept connections
db_1  | LOG:  autovacuum launcher started
web_1 | [2014-08-15 05:24:56] INFO  WEBrick 1.3.1
web_1 | [2014-08-15 05:24:56] INFO  ruby 2.1.2 (2014-05-08) [x86_64-linux]
web_1 | [2014-08-15 05:24:56] INFO  WEBrick::HTTPServer#start: pid=1 port=3000
おおお、動き出したぞ。
最後に別のターミナルを開いてデータベースを作成する。ここで、環境変数DOCKER_HOSTが指定されていないと怒られるので注意(エラートレースが長くて最初分からなかった)。
yukaarynote:fig yukaary$ export DOCKER_HOST=tcp://172.16.42.43:4243
yukaarynote:fig yukaary$ fig run web rake db:create
DOCKER_HOSTってどこなのん?って思ったら,docker-osx sshしてifconfigすれば分かる。
ただ、上のdbの作成コマンド発行してもエラーなんだよね…
db_1  | ERROR:  database "postgres" already exists
db_1  | STATEMENT:  CREATE DATABASE "postgres" ENCODING = 'unicode' TEMPLATE = "template0"
db_1  | ERROR:  database "myapp_test" already exists
何度かTry & Error繰り返している内に作っちゃったのか?そもそもドロップしないのん?
yukaarynote:fig yukaary$ fig run web rake db:drop
Starting fig_db_1...
PG::ObjectInUse: ERROR:  cannot drop the currently open database
: DROP DATABASE IF EXISTS "postgres"
/usr/local/lib/ruby/gems/2.1.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:128:in `async_exec'
dropしようとすると怒られる。でもコンテナを立ち上げないとdropできないでござるの巻。しょぼん。
ともあれhttp://localdocker:3000/にアクセスしたら繋がったっ。figコマンドを見てみるとスケールアウトができるみたいだし暇があったら試してみようかな。
おまけ。
yukaarynote:fig yukaary$ fig ps
  Name               Command             State        Ports      
----------------------------------------------------------------
fig_db_1    postgres                     Up      49157->5432/tcp 
fig_web_1   bundle exec rackup -p 3000   Up      3000->3000/tcp
アプリとサービスで区別しないところに好感。別件でCloud Foundryを使っているけど、あれよく分からないorz
Written with StackEdit.

Monday, August 11, 2014

ゆかりさんとRaspberry # 1

走り書き。

Raspberry PIからのリクエストに応じてVoiceroid3人娘をしゃべらせたい、という謎のモチベーションで、がそごさしていていたのが少しだけ形になった。

上のお話は開発モチーフで、本音はsocket.ioでどんな事が出来るか試したかったというのもある。

今回の作ったシステムの構成

  • サーバー(windows)
    • node.js, javascript
    • VoiceConsoroid, C#
  • クライアント(Raspbianの予定)
    • node.js, javascript

サーバーとクライアントはsocket.ioでリアルタイムに通信、クライアントからサーバーに喋ってほしいメッセージを送ると、サーバーはVoiceConsoroid経由でVoiceroid+にwav作成を依頼、wavができるとそれをクライアントに送信する。

ここまで動作確認。

後はクライアントをRaspberry上で動かして、wavを取得後にaplayで喋ってもらえれば完成…!という構図。

Raspberry側にセンサーを取り付けてセンサー経由のイベントに応じて喋ってもらったり、一度喋った内容をキャッシュサーバーに記憶させて応答を早くしたり構想だけは色々あったりなかったり。

これをgithubに上げるかどうかは微妙なところだよなあ…
publicなWebサーバーとして公開されちゃうと、商用ツールを部分的にでも、誰でも使えてしまう。

Reference

Saturday, August 9, 2014

socket.io with both client and server on nodejs

今更なのん!?なネタを一つメモ書き。今後半自動でバイナリデータの受信を実現する上で大事なのです。

socket.io

socket.io、Websocketを初めとしたhttpを用いたリアルタイム通信を実現するとても高機能なモジュール。

こいつは通常server(nodejs)側にrequire(socketio)を使い、client側(ブラウザ)にrequire(socket.io-client)を使ってアプリケーションを実装することが多いと思う。

ただしクライアントが常にWebブラウザを実装しているとは限らない…というかRaspberryをコンソールで使っている状況では難しそう。ヘッドレスブラウザ使ったり、組み込まれてるブラウザ(Midori?)を頑張って解析すればもしかしたら?かもだけど、目的を逸脱した感じが半端無い…。

解決策は簡単でRaspberry側がnodejs上でrequire('socket.io-client')すればブラウザ無しにserverと通信できる(参考)。流石ですnodejsさん!(とnpmとsocket.io兄貴)。

サンプルコード

手元で動作確認した時のサンプルコードを掲載.

server.js

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(3000);
console.log('Server running at http://127.0.0.1:3000/');

app.get('/', function(req, res){
    res.sendfile(__dirname + '/index.html');
});

io.on('connection', function(client) {
    console.log('some client has been connected.');
    client.on('message', function(msg) {
        console.log('receive message.');
        client.emit('voice', 'You say ' + msg);
    });
});

client.js

var client = require('socket.io-client');
var socket = client.connect('http://localhost:3000');
socket.on('connect', function() {
    console.log('connection has been established.');

    socket.emit('message', 'まきまき、応答してください。');

    socket.on('voice', function(msg) {
        console.log('Received:' + msg);
        socket.disconnect();
        process.exit(0);
    });
});

index.html(今回htmlはオマケ.)

<html>
    <head>
        <title>socket.io sample.</title>
    </head>
    <body>
        <p>Both server and client will be running on nodejs.</p>
    </body>
</html>

server. clientそれぞれをnodeで起動すると次のような結果が得られる。

$ node server.js
Server running at http://127.0.0.1:3000/
some client has been connected.
receive message.
$ node client.js
connection has been established.
Received:You say まきまき、応答してください。

nodejs楽しいな。いいなこれ。

Written with StackEdit.