shokai今スイスにいる。middlewareの作り方を学んだ。APIがよくわからない。(hijackについてはそのうち書く)ソースコードはgithubに全部置いてある。github.com/shokai/rack-plugin-studyRackSinatra/Rails/Padrino等のRuby製webアプリケーションフレームワークと、webrick/thin/mongrel/unicorn等などのRuby製webサーバーを接続するしくみがRackです。Webアプリフレームワークが、どのwebサーバーででも動くように接続部分を抽象化してくれている。以前rackの上にsinatra風のフレームワークを実装してみた時に、くわしく解説した。middlewareを作ると、WebサーバーがWebアプリケーションフレームワーク(WAF)とやりとりするデータを書き換えたりできる。rack::auth系の認証プラグインとか、rack::cache系のキャッシュ系が有名。どちらもリクエストとレスポンスの間をいじる処理で、プラグインをsinatraやrailsで実装するよりもrackでやったほうが楽だと思った。middlewareとして実装しておけばrailsでもsinatraでもpadrinoでも使える。middlewareを作って、sinatraアプリから使えるかどうか試した。Sinatraアプリを準備するまず、単なるHTMLを返すSinatraアプリを作る。文章は感嘆符や句読点が色々欲しかったので、艦これwikiからお借りしました。敵地偵察作戦の場合、軽巡洋艦を1隻含む6隻構成、旗艦Lv20以上、編成合計Lvは駆逐艦のみで構成した場合に100Lv以上。</p><p>旗艦に軽巡を据える必要性は無く、旗艦:駆逐改でも成功することが確認されている。</p><p>また、編成艦船の最低Lvは関係無いことも判明している。</p>'endこのmain.rbをconfig.ruからrequireして、rackupすればsinatraアプリが起動する。middlewareを作った。https://github.com/shokai/rack-plugin-study/tree/master/kumaこうなるkuma_response_filter.rbクラスを作って、initializeとcallだけメソッドを宣言する。body_part.gsub(/([。endendsinatraに処理させてから、そのレスポンスがtextの時のみ中身をいじってから返している。感嘆符や句読点の前にクマを挿入するだけ。Content-Lengthが変わるので最後に計算し直す。bodyが書き換えられる。middlewarehttps://github.com/shokai/rack-plugin-study/tree/master/image_glitchJPEG画像がこうなる。glitchはmakimotoさんのスライドを参考にしたimage_glitch.rbSinatraのレスポンスをみて、image/jpegだったらa/b置換glitchする。Rack::ImageGlitchするだけで有効になる。打ち間違えてもレスポンスが返ってくるプラグインを作った。.JpEGとかでリクエストされても、Sinatraのlogには.jpgとしてリクエストされた、と表示される。REQUEST_URI全部書き換える。endendまとめリクエスト・レスポンスを加工するならrackでやったほうが楽な場合もある。gemにした————-帰宅前にスマホからクーラーをつけれるようにした。ソフトウェア部分はまだアップデートされるだろうけど、(rubygemにするとか)ハードウェアはもうこれ以上変更しないので是非自作してお試しください。動かなかったり欠陥があったら、githubのissueかtwitterで@shokaiにどうぞ。実際に使いたいのはエアコンだけど、エアコンは地味なのでテレビでやってみた。研究室にあるパナソニックとシャープのテレビで試したら両方とも動いた。パナソニックのテレビから学習した赤外線データはgistに貼った。データフォーマットについてもこの記事の下の方で解説してます。経緯などLindaで家の温度を見れるようにしたら、だれもいない部屋の温度が高すぎるのが見えてしまい、帰るのが嫌になったので作った。以前KURO-RSという赤外線学習リモコンをRubyから使えるようにしたのだが、うちの日立のエアコンの信号が特殊らしく操作できなかったので、赤外線学習リモコンも自作した。日立エアコンだけでなく、富士通のエアコンでも動いたし、パナソニックやシャープのテレビも大丈夫だったから、たぶんどのメーカーの製品でも動くと思う。赤外線学習リモコンが動かない理由は2つ考えられる。2.信号をちゃんと解析しているタイプの学習リモコンの場合は解析に失敗している、のどちらか。うちの日立のエアコンは富士通のに比べて3倍ぐらいデータが長かったので、たぶん電源on/offだけでなく温度風向き風量など現在の状態も全て送信している。2.信号を解析せずに保存し再現出力するだけ、という仕様にした。RocketIOでWebアプリも作った。動かすソースコードはgithubに全部あり、回路も簡単なのでまず動かし方・設置方法を説明する。1個(100〜150円ぐらい)以上。ArduinoはLeonardoとMicroで動作確認した。v2(duemillanove互換)では動かなかった。下のほうに書いた赤外線LEDを38kHzで点滅させる処理が面倒くさい問題のせいだと思う。Arduinoコードのdelay時間をちょっといじればなんとかなると思うのでそのうちやるRubyが動くマシンやArduinoはそのへんに落ちているだろうし、150円ぐらいの追加で作れるのでやってみるといいのでは。回路は大変簡単だった。12番ピンに赤外線LEDを付けた。赤外線リモコン受光器はいろいろあるけど、どれも5V/GND/DATAの3ピンで動く。これをエアコンの方に向ければいい。離れていても届くけど、市販の赤外線LEDは指向性が強いので光が当たらない事がある。狙うか、LEDの頭を切断して拡散させるかするといい。別の赤外線受光器も試してみたけど、ちゃんと動いた。installすればok赤外線を読むbinディレクトリ内にCUIで赤外線読み書きできるツールが入っている。/dev/tty.usb-devicenamereadして2.5秒以内に赤外線リモコンを照射したら、ターミナルに読み取ったデータがprintされる。writeすると、1回前に読み取ったデータを発射する。保存しておくと名前を指定して発射できる。sample.data.ymlみたいにすればいい。上の数字列は34,15,5,11の場合、3400マイクロ秒間38kHzの赤外線を発射、1500マイクロ秒間停止、500マイクロ秒間38Khzの赤外線を発射、11マイクロ秒停止という意味。赤外線リモコンは自然光と区別するために38kHzの赤外線が300〜600マイクロ秒続く状態をon、何もなし状態が300〜600マイクロ秒続く状態をoffとして送信する。メーカーによって時間が違う。elm-chan.orgの解説がわかりやすい。赤外線リモコンの通信フォーマットこれを赤外線リモコン受光器に入力すると、38kHzの赤外線が入っている時にLOW、何もなし状態の時にHIGHが出力される。信号データの内容を解析するのは面倒だったので、リモコンから来たのと同じ赤外線を再現するようにした。赤外線リモコン受光器を監視して、出力がHIGH/LOWで変化した時間をmicros()で保存した。データが1byteに収まるように、100マイクロ秒を1単位とした。installしてrackupすれば起動する。上のディレクトリのdata.ymlを読む。環境変数ARDUINOにArduinoのデバイス名を渡しておく必要がある。アプリは外から勝手に操作できないようにbasic認証を付けられる。環境変数BASIC_AUTH_USERNAMEとBASIC_AUTH_PASSWORDで設定する。サービスとしてインストールWebUIのREADMEに書いてあるとおりforemanで家のMacのlaunchdにインストールした。hostでremote.shookai.orgに置いてる。苦労したことなどそもそもちゃんと赤外線が読めているのか、ちゃんと38khzで発射できているのかがよくわからず苦労した。試作これを作る前に、2種類の方式で赤外線学習リモコンを試作した。200マイクロ秒ごとに38kHz赤外線のon/offをbool配列で記録するbinary方式と、on/offが切り替わるまでの時間を記録するinterval方式を作った。これはbinary方式。デジタルピン2番にスイッチを接続して、pushしたら2.5秒以内に赤外線リモコンを読ませる。シリアル通信で赤外線データを出力してくる。38kHzを作るのが難しいbinary方式とinterval方式でdelayMicrosecondsの時間が違う。ループや条件式の計算の処理時間があるので、それぞれの方式で別のdelay時間になってしまった。そもそもPWMを使って38kHzを作ればいいんだけど、最初はStandardFirmataに赤外線学習リモコン機能を付けた物を作りたくてdelayとIO操作のみという縛りでやっていて、信号は読み書きできるんだけどRAM容量が足りなくて動かなかったからこうなった。FirmataじゃないのになんでPWM使わない縛りやってるんだろうって気分に今なってる。shokaiGitHubのissue機能が好きすぎてヤバイので、最近90日以内に更新した全リポジトリのopenなissueを表示するサービスを作った。何か思いつく毎にissueに書いて開発してて、手詰まりになったり精神が調子悪くなったら一旦手を止めて別のプロジェクトのissueを潰すようにしてると永遠にプログラマーズハイ状態を維持できるんだけど、自分の持っているissueを一覧できるページがGitHubにない。GitHubには通知機能があるけど参加したりアサインされたissueしか通知されないので、全く手付かずのissueはだんだん下の方に下がっていって見つからなくなってしまう。自分の持っているリポジトリ全体のissueを一覧したかった。最近は21個のリポジトリをいじってて、73個もissue溜まってるんだなという事がわかる。GitHub経緯もともとこれgithubの自分のリポジトリのissue一覧を使っていたんだけど動かなくなったのでカッとなって作った。さっきgithubのパスワードリセットしたら動くようになった。(2)にissue表示する機能を足しただけなので、だいたい2時間ぐらいでできた。issueの取得には時間がかかるから、1つリポジトリ取得する毎にsinatra-rocketioでブラウザに送っている。取得したissueはmemcachedに3日間とっておいてる。shokaitwiticonはこのblogの右上にも出しているtwitterアイコンのサービス。SinatraとHerokuで実装している。src="http://twiticon.herokuapp.com/shokai/mini">などで埋め込めるようになる。gyazzなどで使っている。v1.0が終了したのだが、1.1ではprofile_image_urlのAPIが無くなった。代わりにusers/showでprofile_image_urlが取得できるが、各種サイズのURLは無くnormalサイズだけ。biggerやminiなどのサイズはprofile_image_urlの末尾を_normal.pngから_bigger.pngなどに置換すると得られる。users/showは認証しないと読めなくなったので@shokai_twiticonというアカウントを作ってその権限でOAuthしている。GitHubtwitterなどの設定は全て環境変数で入れる。