0

RICOH THETAのシャッター音を消す

http://npmjs.org/package/ricoh-theta

音量設定オプションをthetaコマンドに付けた。
THETAにWiFiで接続してから

% npm install ricoh-theta -g
% theta --volume 0

0x502C AudioVolume | RICOH THETA Developersを使って設定している。


初期型の2013年モデルはシャッター音が消せないという公式見解だけど、消せた。去年ファームウェア入れた気がするのでそのせいかもしれないけど。


0

Node.jsでRICOH THETAを操作する

node.jsでRICOH THETAを操作できるnpmを作った。nodeが入ってるMacやLinuxをWiFiでTHETAに接続して使う。

https://github.com/shokai/node-ricoh-theta
https://www.npmjs.com/package/ricoh-theta

不具合・質問などはtwittergithubのissueにお願いします。


ネットを探した感じだと、thetaのシャッターを切るコード片は色々な言語で実装されてた。
でもそれらはちゃんとPTP-IPのコネクションやセッションを管理せず撮影命令のパケットを送るだけなので、撮影した写真を吸い出したり、リスト取得、削除はできない。
そこでptp.jsにそれらの機能を追加して、それをさらにラップしてricoh-theta npmを作った。


インストール

グローバルにインストールするとthetaというコマンドが使える。
% npm install ricoh-theta -g
% theta --help


crontabに
* * * * * theta --capture tmp.jpg && open tmp.jpg
とか書いて大きいモニタに表示しておくだけで結構おもしろい。


ライブラリとして使う


もちろんライブラリとしてもこんな感じで使える。
var Theta = require('ricoh-theta');

var theta = new Theta();
theta.connect('192.168.1.1');

// capture
theta.on('connect', function(){
theta.capture(function(err){
if(err) return console.error(err);
console.log('capture success');
});
});

// get picture
theta.on('objectAdded', function(object_id){
theta.getPicture(object_id, function(err, picture){
fs.writeFile('tmp.jpg', picture, function(err){
console.log('picture saved => tmp.jpg');
theta.disconnect();
});
});
});
取得した写真はbufferなので、ファイルに書き出さずにそのままhttpで配信するとかも容易。

captureからのコールバックで撮影したオブジェクトのIDを受け取るのではなく、objectAddedという別イベントにしてある。PTP-IPがそれらを別に扱っているのでそうした(今後のTHETAでどっちが先に発火するか、逆になる可能性あるし)
この書き方だと、APIに接続していればリモートシャッターではなく本体の撮影ボタンを自分で押して撮って、オブジェクト追加通知をnodeで受けて写真を吸い取るという事もできる。

そんなわけで、最初は接続→撮影→取得っていう手続きすればいいんだからPromiseでやろうと思ったけど、socket.io風のインタフェースに落ち着いた。

PTPではオブジェクトIDのほかにストレージIDというのもあって、これは例えばデジカメで内蔵メモリとSDカードとを切り替えて使う時に指定するためのIDなんだけど、thetaは内蔵メモリしかないから常にID:1が使われている。
もし今後マイクロSDを追加できるTHETAがでてきたら、APIを変えると思う。




ptp.jsへの追加分はプルリクしておいたんだけど、今のところricoh-theta npmがインストールするptp.jsは俺のgithubのread_dataブランチからインストールするようになっている。
(2015年1月31日:mergeされたのでnpmjs.orgから普通にインストールするようにした)

nodeって、マイナーなプロトコルの基本実装がnpmになっている事が多かったり、変更が本家にmergeされていなくても言語のパッケージマネージャがgithubから依存解決できたりというのがすごい良いと思う。

0

debug npmが有効じゃない時、他のロガーに切り替える

debug npm とは


debug npmはexpressやsocket.ioにも使われているログ出力用のライブラリで、ログがカラフルに表示できるし環境変数DEBUGによって出力をフィルタできる。

debug = require('debug')('myapp:main')
debug 'hello'

debug2 = require('debug')('hoge')
debug2 'hi'

% DEBUG=myapp* node app.js
ワイルドカードでも指定できる。この例だとmyapp:mainは表示されるけどhogeは表示されない。
ライブラリの中の細かいログを種類分けれるので便利。


debug使えなかったらconsole.logする

基本的にdebugのカラフルな表示で全部出力したいんだけど、どうしても見てほしい情報とかはdebug有効じゃなくても出力したい。

(if debug.enabled then debug else console.log) 'hello'
debugはfunctionだけどenabledというプロパティがあるので、それを見てdebug出力できない時はconsole.logするとかできる。


debug使えなかったら標準ロガーに渡す

hubot等ではrobot.logger.infoとかrobot.logger.errorがある。
でも色んなhubot scriptがログ出してて、どれが何の出力なのかわからなくなるので自分のscriptではなるべくdebug使うようにしてた。

hubotで、なるべくdebugに出したい、無理ならrobot.loggerを使う、という場合こうしてる

debug = require('debug')('hubot-rss-reader:rss-checker')
module.exports = (robot) ->

logger =
info: (msg) ->
return debug msg if debug.enabled
msg = JSON.stringify msg if typeof msg isnt 'string'
robot.logger.info "#{debug.namespace}: #{msg}"
error: (msg) ->
return debug msg if debug.enabled
msg = JSON.stringify msg if typeof msg isnt 'string'
robot.logger.error "#{debug.namespace}: #{msg}"

logger.info "start!!"
logger.error "やばい"

0

hubot-slackアダプタv3にアップデートしたら色々辛かった

hubot-slackアダプタを今までv2.x系を使っていたんだけど、先月ぐらいに出てたv3系にアップデートした。
hubot-slack アダプタ v2 から v3 へ | 半月記が参考になった。

hubot-rss-readerがv3で動かない機能があったりしたのも直した。


結論

v3系は色々おかしい気がするのでまだv3にアップデートしないほうがいいと思う。
とにかく今v2のhubot integrationをslackで使ってるなら、設定画面から削除はしないほうがいい。消したらv3しか使えなくなる。

slackの設定

slackに新規にhubot integrationを追加するとv3じゃないと使えないようになっている。
今まで使っていたintegration消して、新しいintegration作ってつなげた。
新規作成時に、hubotにアカウントを設定されるようになった。

/invite @hubotとかして予めチャットメンバーに追加しておかなければならないが、そのかわりprivate roomに参加させられる。


アダプタv2とv3の違い

通信がHTTPからwebsocketになった。
hubot側がclientなので、外に丸見えのサーバーじゃなくてもbotが動かせるのは良いと思う。


エラーの内容が読めない

なんかエラー出力がtoString使ってるので[object Object]とか言われて何だかわからない。
[Sun Jan 11 2015 16:51:34 GMT+0900 (JST)] ERROR Received error [object Object]
これはプルリク送っておいた

mergeしてもらえればこういうエラーになるはず
[Sun Jan 11 2015 16:59:42 GMT+0900 (JST)] ERROR Received error {"code":-1,"msg":"slow down, too many messages..."}

マジで辛かったのは、これとbrainの爆発が同時に起こってて本当に何がなんだかわからなかった。

いきなりexitする

websocketが切断されたり、単にエラーが起こるだけでprocess.exitが呼ばれるのは豪快すぎる。

存在しないroomに送信しようとするとエラー起こってprocess.exitする。

そうじゃなくても連続でsendしたらclientが落ちてプロセスも落ちる。hubot-rss-readerはqueueを作って500msecごとにsendするようにした。

いきなりexitする件は#127で議論されていて、slackのサーバー側が返すエラーコードに応じて自動再接続するか処理を分岐したいらしい。


room名の頭に#が付けられない

robot.send {room: "#hoge"}, "こんにちは"
じゃだめで
robot.send {room: "news"}, "こんにちは"
とする必要がある。
自分が使ってたスクリプトも#つけてるのが結構あったので、ここでエラーになってた。#つけても大丈夫にするプルリク送っておいた


websocket接続するまでrobot.sendが無い


起動した時に通知を送るようにしている。
v2まではHTTPだったから、これでよかったけど
module.exports = (robot) ->

robot.send {room: "news"}, "Hubot、起動しました"

v3ではwebsocketが接続するまでrobot.send関数が存在しないので、sendが生えてくるまで待つようにした。
module.exports = (robot) ->

cid = setInterval ->
return if typeof robot?.send isnt 'function'
robot.send {room: "news"}, "Hubot、起動しました"
clearInterval cid
, 1000

hubotって、まずrobot.adapterがチャットサービスに接続してconnectedイベントをemitして、それを受けてからscripts以下のcoffeeやjsが読み込まれるはずなんだけど、slackアダプタはなぜかscripts読み込まれた後でもまだadapterが接続されてない。connectedとは一体何なのか。

これはhubot-slackの下で使われてるnode-slack-clientの問題だったので、プルリクしておいた

0

tesselに日本語を喋らせるnpmライブラリ作った

そういえばtesselに日本語を喋らせるをnpmにしたのだった
書くの忘れてた

https://www.npmjs.org/package/audio-vs1053b-textspeech


インストール

% npm install audio-vs1053b-textspeech


使う

まずaudioモジュールにスピーカーを接続しておく。

こんな感じでaudioモジュールをtextspeechモジュールに食わせてセットアップし、
var audio = require('audio-vs1053b').use(tessel.port['A']);
var textspeech = require('audio-vs1053b-textspeech').use(audio);

audio.on('ready', function(){
audio.setVolume(20, function(err){ // 音量調整
console.log('audio setup');
// この後に喋ったりさせる
});
});


簡単に喋らせれる。日本語でおk
textspeech.speech('こんにちは'); // japanese
textspeech.speech('hello world', {tl: 'en'}); // english

なお初めてしゃべる言葉はgoogle翻訳にmp3を取りに行くので10秒ぐらいかかる。
2回目以降はオンメモリのキャッシュに入っているので、すぐ発声できる。
でもaudioモジュールの通信がUARTなので、同時に他のセンサ系モジュール使ったりしてるとそっちのUARTもバリバリ通信おこなわれて、途切れ途切れになってちゃんと喋れなくなる。

tesselはaudioとかカメラとか大きなマルチメディアデータやりとりする系のモジュールがウリっぽい所あるのに、それ使ってると他のモジュールが動かなくなるのはなんかつらい。そもそもtesselのCPUであるARMから拡張ボード用に4つUART出してるけど、たぶん全部ソフトウェアUARTだから、ファームウェアの実装を効率化してもどうにかなる気がしない。どうするんだろ。


あとキャッシュのサイズも指定できる
textspeech.setCacheSize(5); // default is 3


前に書いたとおり(おそらく)streamのバグがある状態の上で妥協する感じで実装しているので、そのうち仕様変わるかもしれないので最新情報はnpmjs.orgのほうのドキュメント見てください