読者です 読者をやめる 読者になる 読者になる

taiyoh's memorandum

@ttaiyoh が、技術ネタで気づいたことを書き溜めておきます。

lirc_webを使ってどこからでも赤外線リモコンの操作ができるようにする

 335先生から「早く書け」とプレッシャーが来てるのでメモっておく。

  • 用意するもの
    • こちらのブログに書いてある部品一式
      • ブレッドボードあると楽ですね
    • lirc (これはapt-getでインストールできる。上記ブログ参照)
    • lirc_web

 特に回路図の載っているこちらのブログは、やることの根幹部分を成しているので、まず書かれていることは全部実行して、動作確認をしておいてほしい。ただ、一つだけ変えたところがあって、この人とほぼ同じ抵抗で設定すると、出力が弱くて肝心のレシーバまで信号が届かなかったので、赤外線LEDの前に置く抵抗は、確か4.7Ωか10Ωくらいに下げている。こうすれば、LEDにより電圧がかかるので、出力は増す。赤外線LEDも、「高輝度」と謳ってるものにしておくとより確実。

 そうして組み上がった回路とRaspberry Piはこんな感じになる(一例です)

DSC02953

 ブレッドボード上の右側の素子が赤外線受光素子で、ここにリモコンの信号をガンガンぶつけて学習させる。

 回路が組めて、ターミナル上から実際にリモコン操作ができることが確認できれば、もう8割以上やることは終わっている。あとは、「lirc_web」というnode.js製のツールを使って、ブラウザから操作できるようにする。lirc_webは元々Raspberry Pi上で動かすことを想定していて、APIにリクエストを投げると、パスからコマンドを解釈して、lirc_webプロセスからlircコマンドを投げてくれる。ただ、それだと家のネットワーク内からしか使えないので、認証はかけつつどこからでも操作できるようにしたいなぁ、と思ったので、app.jsのパス指定を以下の様に変更した。

 /api/streamというパスを新たに用意し、ここにつなぎっぱにしたプロセスに対し、APIのリクエスト情報をごっそり送るという変更を加えた。これをVPSで立ち上げた上で、以下のスクリプトを用意する。

 今度はこれをRaspberry Pi上から実行し、予めVPSに立てておいたlirc_webのシステムに対してアクセスし、つなぎっぱなしにしておく。これができれば、NAT越えの問題は楽々突破できるし、lirc_webのシステムに認証さえつけておけば、便宜上ある程度のセキュリティは保たれる筈。VPSに立てたlirc_webのシステムにブラウザからアクセスすると、こんな感じになる。

f:id:sun-basix:20130524002717p:plain

 因みに、今のところ上記の通り、ダイニングの明かりしか操作できてません。。。!とはいえ、ちょっとbasic認証がうざいけど、この存在は相当ライフチェンジングになってて、今までは帰って扉開けた瞬間だと真っ暗で、手探りで部屋のスイッチを探さないといけなかったけど、今は先にスマホから上記のコントロールページを出しておいて、鍵開けて扉開けた瞬間にスイッチ操作して明かりを点けられるので、それだけでもストレスがだいぶ減ってる。なお、そのダイニングの明かりは、後付けでリモコンで操作できるようになる機器をつけてある。

天井照明器具専用 リモコンスイッチOCR-04 07-0154

天井照明器具専用 リモコンスイッチOCR-04 07-0154

 最近、ソフトウェアだけで完結できるものじゃなくて、こうやって現実世界に反映される何かを組むのがすごく楽しいと思えるようになってきた。と言っても、まだ実質これしかできてないけど。

MTでエントリ以外の要素を任意のタイミングで自動的に再構築する

 MT情弱なのでぐぐってもなかなか出て来なかったし、ましてやPluginやToolも書きたくなかったので、頑張って探したら、これが出てきた
 → alfasado/mt-tools-rebuild-archives · GitHub
 やや古いツールだけど、一応現時点のMT最新版(5.2)でも動く。
 どの形式のテンプレートで作成したかでコマンドラインに入れる引数atの値が変化する。今回は、登録したユーザのプロフィール情報を定期的に反映させたくて、その反映するテンプレートがインデックステンプレートにあったので、

cd /path/to/mt
perl tools/rebuild-archives --at Index --blog_id 1,2

 という感じで実行すればOK。warningがウザいけど。

hubotにもunazu_kun的な機能を追加する

 「unazu_kunって何?」って方は以下を参照。
 → 社内IRCがカビ臭くてピリピリしてたので癒し系botを投入した後、リマインダー機能を搭載した話 - kenjiskywalker no memo
 → 多分結構バージョンの古いコード

 hubotで提供してるものがどれもかわいくないので、unazu_kun的な機能を以下のコードで追加した。pugはちょっとアリだけど、pugって最初に入れないといけないあたりがカジュアルじゃない。なお、リマインダは現時点で未搭載。(11:37追記 シンプルなリマインダ機能入れました。日をまたぐとかはこの正規表現じゃまだできないけど)

f:id:sun-basix:20130519105534p:plain

 もっと違う返答パターンもお待ちしております。

nagiosで通知先を追加する、もしくはnagiosのalertをhubot or ikachanに渡してIRCに通知させる

 hubotをIRC連携するのは「Ukigumo + hubot-ircでビルド結果を通知 - taiyoh's memorandum」を参照。ikachanなら元からインターフェイスがあるので省略。
 これを承前として、/etc/nagios/objects/commands.cfgに以下を追加。

define command{
        command_name    notify-service-by-hubot
        command_line    /usr/bin/curl -s 'http://localhost:5000/hubot/say' -d 'channel=#hoge' -d "message=** $NOTIFICATIONTYPE$ Service Alert: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$ **"
        }

 別にhubotじゃなくてもいいんだけど。。。そこは環境に合わせて。
 次に/etc/nagios/objects/contacts.cfgを編集して、IRC通知用のcontactを作成する。

define contact{
        contact_name                    hogefugahubot
        use                             generic-contact
        alias                           MyHubot
        service_notification_commands   notify-service-by-hubot
        }

 あとはcontacts.cfgのcontactgroupに、作ったcontact(ここだとhogefugahubot)を追加すれば、IRCにも通知されるようになる。使ってるメッセージはメール送信時のsubjectをそのまま使ってるけど、よしなに変えればいいと思う。

nagiosでsocket.ioのレスポンスを監視する

 nagiosのcheck_httpだとhttp通信の監視しかできないので、websocketというか、socket.ioの通信を監視するのはだいぶ厳しいなー、と思ったので、以下のようなスクリプトを作った(当然部分的にボカしてる)。socket.io-clientとoptimistを予めnpm installしておく必要がある。

 んで、/etc/nagios/objects/commands.cfgに以下の記述を加えてコマンドを登録する。

define command{
        command_name    check_node
        command_line    /path/to/socketio_watch.js -h $HOSTADDRESS$ -w $ARG1$ -c $ARG2$ -u $ARG3$
        }

 最後に、/etc/nagios/objects/localhost.cfgに記述を加えて監視サービスを追加する。

define service{
        use                             local-service
        host_name                       localhost
        service_description             NODE
        check_command                   check_node!80!500!/
        notifications_enabled           1
        }

 あとはnagiosを再起動すれば、監視対象に加わる。
 予期しないデータ構造が返ってきたり、レスポンス時間が長くなってくると警告出るようにしてるので、だいぶ捗るのではないかと思います。socket.ioのresourceとか、レスポンス時間の調整はサービス登録するところで変更すればいいようにしているので、多少汎用性はあるはず。

Ukigumo + hubot-ircでビルド結果を通知

 hubotをIRC通知するやり方はあちこちで書かれてるが、僕としてはhubot-irc-runnableを使った方がカジュアルなのでオススメ。
 →jgable/hubot-irc-runnable · GitHub
 その上で、scripts/httpd.coffeeに以下のコードを追加する

  #http://chobie.hatenablog.com/entry/2012/02/26/125532
  robot.router.post "/hubot/say", (req, res) ->
    room = req.body.channel
    message = req.body.message
    #user = robot.userForId room # これだと動かない
    user = robot.adapter.userForId room
    user.room = room
    user.type = 'groupchat'
    robot.send user, "#{message}"
    res.writeHead 200, {'Content-Type': 'text/plain'}
    res.end 'OK'

こうすると、POST /hubot/sayにリクエストを送ればmessageパラメータの内容をchannelパラメータで指定したチャンネルに対して投稿してくれる。これでhubotにもikachanの機能が追加される。
なので、

$app->push_notifier(
    Ukigumo::Client::Notify::Ikachan->new(
        url     => 'http://example.com/hubot',
        channel => '#your-channel',
        method  => 'say'
    )
);

 Ukigumo::Clientのpush_notifierでNotify::Ikachanがそのまま使えるようになる。methodの指定が必要だから、同梱されてるukigumo-client.plとは別でスクリプトを用意しないといけないけど、/hubot/noticeのパスで受け取れるようにしておけばそのまま使える。

socket.ioで下層パスで通信する

 メモ書き。例えば/path/toなんてパスの下でコンテンツの表示もsocket.ioの通信もしたい時。

// in node
var app_path = "/path/to/app";
io.set('resource', app_path);
io.of(app_path).on('connect', function() {
  // do something
});

 とやって、表示するHTMLでsocket.io.jsを取得する際に

<script src="/path/to/app/socket.io/socket.io.js"></script>
<script type="javascript">
var socket = io.connect('http://' + location.hostname, {
  'resource': 'path/to/app'
});
</script>

 という感じで指定する。
 キモはnode側でresourceとofメソッドの引数に同じものを入れることと、クライアント側でio.connectのオプションにnode側と同じ(でも頭の/はない)resourceを入れておくことか。
 別のパスで別のsocket.ioのアプリを立てたい時なんかに使える。