ラベル Ruby の投稿を表示しています。 すべての投稿を表示
ラベル Ruby の投稿を表示しています。 すべての投稿を表示

2022-09-16

rubyで住所情報から都道府県を取り出す

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

 以下のような住所情報があったとします。

東京都府中市1-2-3 道路横ビル

これから都道府県と取り出し、それ以外と分離する場合は、以下のような感じで可能です。

org = "東京都府中市1-2-3 道路横ビル"

pref = org.match(/^.+?[都道府県]/).to_s

addr = org.sub(pref,"")

prefに都道府県、addrにそれ以外が入る感じなります。

都道府県取得の正規表現に?を忘れると

prefが「東京都府中市1-2-3 道」と最長一致なってしまうのでご注意です。


※やっぱりこれだと京都府がとれないです。

pref = org.match(/^.{2,3}[都道府県]/).to_s

の方がよさそうです。


※※上記では東京都府中市が東京都府になっちゃいます。最短一致させるための?を忘れてました。

pref = org.match(/^.{2,3}?[都道府県]/).to_s

の方がよさそうです。


2017-12-28

raspberry pi zero wとダイソーのリモートシャッターとrubyで遊ぶ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
raspberry pi zero wを買ったのは、bluetooth機器とつないで、ちょっと遊んでみたいなぁと思っていたことも一つの理由だったりします。

お手軽に遊ぶ材料として、ダイソーで売っているリモートシャッターがよさげかと思ってみました。以下と同じもののようです。



これを利用した例を以下のサイトを紹介していたので、参考にさせてもらいました。
https://qiita.com/vimyum/items/8b7548ca8cf45383c5b0

こちらでは、bluebuttonというツールを利用しているのですが、ソースは以下にあります。
https://github.com/kinnalru/bluebutton

こちらのソースを見て、ちょっと遊んでみました。
こちらでは、二つのボタンを特に区別してなくて、押したことと長押しを検出していたので、ボタンを識別できるよう改造してみました。

上のIOSボタンは、押すとVolumeUpが送られてきているようです。
下のandoridボタンは、押すとEnterが来て、さらにVolumeUpが送られてきてるようです。

これで識別できそうなので、改造したのは以下のものになります。
rootで実行する必要があります。
これは、二つのボタンとそれぞれの長押しを検出して、さらにLINEに特定のメッセージを送るようにしてみました。


とりあえずIoTな気分を感じてみました。


2017-11-03

Rubyで暗号化した文字列をJavaScriptで復号化してみた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Qiitaにある
JavaScriptで暗号化した文字列をRubyで復号化してみた
という記事の逆をやってみたいと思ってみました。

JavaScript側では、CryptJSを使ってRuby側で暗号されたものを
var text = CryptoJS.AES.decrypt(data, "pass").toString(CryptoJS.enc.Utf8);
で複合化をできるようにRuby側で暗号化したいと思います。
Ruby側で暗号化された値が上記のdataに入る感じです。

Ruby側は以下のような感じです。


これを使ってruby側で
enc_data = encrypt(”hogehoge”,"pass")
としてできた、enc_dataの内容をJavascript側のdataに入れてやれば、hogehogeと戻せる感じでした。

2017-08-31

sinatraでベーシック認証した時のユーザ名とパスワードを取得する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
apacheなどのwebサーバ側でベーシック認証させておいて、
sinatra側で、その時のユーザ名とパスワードを取得する方法です。


auth_info = Base64.decode64(request.env['HTTP_AUTHORIZATION'].split(' ')[1]).split(':')
username = auth_info[0]
password = auth_info[1]

2017-04-04

LINE BOT APIを使っていたものをLINE Messaging APIに書き直す

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
すごく今更ですが、以前LINE BOT APIを使ってみたものを、LINE Messaging APIに直したものを紹介します。

ちなみにLINE Messaging APIを始めるには、以下が参考になりました。
http://milk0824.hatenadiary.jp/entry/2016/10/01/211555

まずは、
LINE BOT APIのcallbackにAWS Lambdaを使ってみる
を直したのは、以下のような感じです。

お次は、rubyで書いたものです。
ruby2.0以上ならば、line-bot-apiというgemがあり、こっちを使うと、もうちょっと楽にかけそうなのですが、以下はruby1.9でも動くことを前提としているのでline-bot-apiは使っていません。

rubyで書いたものの最初の、
LINE BOT APIを利用して電車遅延情報の送信を改良した
を直したのは、以下のような感じです。

そして、
LINE BOT APIを利用してGoogle Calendarの情報を通知する
を直したのは、以下のような感じです。
ちなみにキャンセルされた予定の処理を追加しています。

最後に、
LINE BOT APIを利用して雨が降りそうな時は通知するようにしてみる
を直したのは、以下のような感じです。

2016-08-05

capybaraとseleniumを使ってrubyでできてないwebサイトのテストをする

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
普段はrailsを使っているのでrspecを使ったテストを書いているのですが、このテストを既存のrubyを使ってないwebサイトの試験に使ってみることを試してみました。

前提は以下のような感じです。
・テストはWindows上でInternetExplorerを利用して行う
・データベースはMS SQL server
・webサイトはASP.Netで書かれている(htmlを出力しているなら言語は問わないはずです)
・テスト用のデータベース、webサイトを専用に用意する
 ※今回database_cleanerを利用しているので既存データがあったらごっそり消えます。

windows環境でrubyが使えるようにする手順は省略します。
bundlerとrspecをgem installして利用できるところまでは準備してください。


まずInternetExplorerをseleniumで利用できるように準備します。
IE用のドライバを以下から取得します。
http://docs.seleniumhq.org/download/
ダウンロードしたzipファイル内の
IEDriverServer.exe

c:\ruby\bin
などのパスが通っているフォルダに配置してください。
そしてIEの設定を確認します。
インターネットオプション
セキュリティで
各ゾーンの
保護モードを有効にする
のチェック状態をすべてのゾーンで同じにするように設定しておく必要があります。


ここからテストプログラム用の環境を作っていきます。
ちなみに、ここから作成するファイルの文字コードはすべてUTF-8です。

まず適当なフォルダを作成して、その作成したフォルダ内で以下を実行します。
rspec --init

フォルダ内にGemfileを準備します。
Gemfile

必要なgemをインストールするためフォルダ内で以下を実行します。
bundle install


rspec設定ファイル(.rspec)を作成します。
.rspec

フォルダ内にconfigフォルダを作成して、その中にデータベース接続設定ファイルを作成します。
config/database.yml

フォルダ内にspecフォルダを作成して、その中にspec_helperを作成します。
spec/spec_helper.rb

データベースのデータにアクセスするためのActiveRecordモデルを作成します。
specフォルダ内にmodelsフォルダを作成して、ここにrailsと同じようにモデルを作成します。
ここではItemクラスを例として作成しています。
spec/models/items.rb

データベースにテストデータを登録するためのFactoryGirlの設定を作成します。
specフォルダ内にfactoriesフォルダを作成して、この中に作成します。
上記のItemクラスに設定する値を例として作成しています。
spec/factories/items.rb

これらの準備ができたらspecフォルダ内にspecファイルを作成します。
spec/sample_spec.rb

テストの実行は作成したフォルダの一番上(Gemfileがあるところ)で以下を実行します。
rspec


こんな感じでとりあえず、データベースにテスト用データを突っ込んで、毎回データベースを初期化するための環境ができあがります。


今回のフォルダ構成をまとめると以下のような感じなります。
+-config
| +-database.yml
+-spec
| +-factories
| | +-items.rb
| +-models
| | +-items.rb
| +-spec_helper.rb
| +-sample_spec.rb
+-.rspec
+-Gemfile
+-Gemfile.lock


以下のサイトが参考になりました。
http://kakakakakku.hatenablog.com/entry/2016/01/09/142221


2016-05-09

LINE BOT APIを利用して雨が降りそうな時は通知するようにしてみる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
※サンプルをLINE BOT APIからLINE Messaging APIに書き換えたものを以下で公開しました。
https://kingyo-bachi.blogspot.jp/2017/04/line-bot-apiline-messaging-api.html

LINEで電車遅延情報を送ってみる

LINEでGoogle Calendarの情報を送ってみる
に続きLINEで雨が降りそうな時に通知してみることにしてみます。

天気に関する情報を取得する手段はいろいろあるのですが、降水確率を取得する手段はあまりなく、以下ぐらいしか見つけられませんでした。
http://www.drk7.jp/weather/
こちらを活用させていただきます。

家を出る直前ぐらいにLINEで通知する感じにして祝日は通知しないようにしたいと思います。

以下のような感じになります。



これを以下のような感じでcron設定して月曜から金曜までの出勤前の6:50に動作するようにしました。
50 6 * * 1,2,3,4,5 /usr/bin/ruby /home/hogehoge/ruby/line_bot/rain_chk.rb >> /home/hogehoge/ruby/line_bot/rain_chk.log

毎日、朝お天気アプリを見て天気を見ているのに、出る直前には傘を持つことを忘れてしまうので何かの形でわかるようにしたいと思ったわけです。

一番よいのは傘が置いてあるところでわかりやすく気付ける形になれればよいのですけどね。


2016-05-07

LINE BOT APIを利用してGoogle Calendarの情報を通知する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
※サンプルをLINE BOT APIからLINE Messaging APIに書き換えたものを以下で公開しました。
https://kingyo-bachi.blogspot.jp/2017/04/line-bot-apiline-messaging-api.html

LINEに電車遅延情報を送ってみるに続き、Google Calendarの情報を送ってみます。

Google Calendarの情報を取得するには、
rubyでGoogle Calendarをいじる
を参考にしていただけたらと思います。
google-api-clientを利用するのですが、今回は古いバージョンの0.6.4を利用します。
最新バージョンでは結構使い方が変わっているようです。

そして情報を取得したいユーザのoauth情報を取得した「.google-api.yaml」を作成しておいて以下のプログラムと同じ場所に置いておきます。
以下は明日の予定をチェックして予定があればLINEに通知するものになります。



ローカル環境で利用することを前提にしています。 送信先IDはcallbackを設定してなんとか事前に取得しておく必要があります。

これを以下のような感じでcron設定して毎日23:10に動作するようにしました。
10 23 * * * /usr/bin/ruby /home/hogehoge/ruby/line_bot/gcal_chk.rb >> /home/hogehoge/ruby/line_bot/gcal_chk.log


Google Nowを使っていれば不要な気がするけれど、いずれLINE BOT APIでグループチャットにもメッセージが送れるようになると信じて、その時はグループチャットにグループの予定を送るものとして使いたいなぁと思ってみたりしています。

2016-04-30

LINE BOT APIを利用して電車遅延情報の送信を改良した

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
※サンプルをLINE BOT APIからLINE Messaging APIに書き換えたものを以下で公開しました。
https://kingyo-bachi.blogspot.jp/2017/04/line-bot-apiline-messaging-api.html

以前
LINE BOT APIを利用して電車遅延情報を送信する
というのを書いたのですが、ちょっと改造しました。

以下をできるようにしようと思います。
・祝日は通知しなくてよくしたい
・localで実行しているがIPアドレスが変わる可能性があるので送信できなかったときはメール通知をしたい

祝日に関してはholiday_jpというgemを使って判別することにしました。
https://github.com/komagata/holiday_jp

メール送信はGmailを利用しようと思います。以下が参考になりました。
http://qiita.com/nownabe/items/3a348c86b3c0a2c87ab0
http://grottad.com/blog/228


で、改良版の電車遅延情報を送信するものは以下のとおりです。



これを以下のような感じでcron設定して月曜から金曜までの出勤前の6:50に動作するようにしました。
50 6 * * 1,2,3,4,5 /usr/bin/ruby /home/hogehoge/ruby/line_bot/train_chk2.rb >> /home/hogehoge/ruby/line_bot/train_chk.log

2016-04-27

LINE BOT APIを利用して電車遅延情報を送信する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
LINE BOT APIを利用してメッセージを送信するには、以下のような感じでできます。



ローカル環境で利用することを前提にしています。
送信先IDはcallbackを設定してなんとか事前に取得しておく必要があります。

これでメッセージは送信できたのですが、せっかくなので役に立つ機能を作りたいものです。
なので電車が遅延していたら通知するbotを作ってみます。
適当な時間に自動実行できるようにさせたら便利な気がします。

電車遅延情報の取得は
鉄道遅延情報のjson(https://rti-giken.jp/fhc/api/train_tetsudo/)
を使わせていただきます。

以下のような感じです。



遅延を確認したい電車情報の部分は、
鉄道遅延情報のjson(https://rti-giken.jp/fhc/api/train_tetsudo/)
を見ながら適当に変更します。

なんとなく便利そうな気がします。


LINE BOT APIを使ってみた感想としては、まだトライアルで機能が少ないので機能追加を期待したいところです。
個人的には以下のような改善されるとうれしいなぁと思うしだいです。
・グループチャットにbotから送信ができるようになってほしい
・callbackがなくてもフレンドリストなどを取得できるようになってほしい
・IPのホワイトリストは、めんどくさいのでなくしてもらいたいなぁ

2016-04-26

LINE BOT APIをまずはできるところまで試す

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
LINE BOT APIが利用できるようになり、いろんな方が試しているようなので試してみることにしました。

利用を開始する手順は以下が参考になりました。
https://www.panzee.biz/archives/9115
(今は上限に達して登録はできないようです)

APIを利用するためにはメッセージを受け取るcallbackの設定が必要なのですが、インターネットで受け取れるようなサーバを持っていないので、callbackの設定なしで自分のローカル環境だけでできるところまでやってみることにします。

私がやりたいなぁと思っていることは、なんらかの情報をグループチャットに通知するだけで、BOTでよくある対話的なことは、まぁ後でもよいかなぁと思っているのでcallbackなしでいろいろできると便利です。

ただ結論から言うとcallbackを用意しないと自分のプロファイルを取得することしかできなかったです。なのでとりあえず利用できるということが確認できることぐらいしか今はできないようです。

以下のような感じで試せます。

まずはAPIをたたくもとのIPアドレスをホワイトリストに登録が必要なので以下などでIPアドレスを調べてホワイトリストに登録します。
https://www.cman.jp/network/support/go_access.cgi

ここまで準備できて、linuxを利用できるならばcurlで以下のようにすれば、とりあえず確認ができます。

curl -H "X-Line-ChannelID: 自分のChannel_ID" -H "X-Line-ChannelSecret: 自分のChannel _Secret" -H "X-Line-Trusted-User-With-ACL: 自分のMID" -XGET https://trialbot-api.line.me/v1/profiles?mids=自分のMID

rubyでたたくならば以下のような感じです。


以下が参考になりました。
http://ola.kironono.com/entry/2016/04/09/205251

できるのがこれだけだと寂しいのでcallbackできるものを準備できるようにしようと思います。


2016-02-04

2015-08-09

rubyでモジュラス10ウェイト3

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
rubyでモジュラス10ウェイト3を利用してチェックデジットを計算する方法です。
モジュラス10ウェイト3の計算方法に関しては、以下をご確認ください。

http://www.barcode-net.com/chisiki/modulus10_3.html

2015-07-15

subversionの変更記録とredmineのチケット情報を連携させてレポートしてみる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
以下のサイトでsubversionのリポジトリのコード変更量を集計する方法を紹介しています。
http://iyukki.blog56.fc2.com/blog-entry-179.html

これを見てこの情報とredmineのチケット情報を組み合わせることができないかなぁと思ってみたので作ってみました。
以下に置いておきました。
https://github.com/vivahiraj/svn_rm_rep

subversionのコミットログに関連するredmineのチケット番号を
#1111
のように記録していることを前提とはしています。

まずは、リポジトリの変更量を
http://iyukki.blog56.fc2.com/blog-entry-179.html
と同じような仕組みで取得します。

そしてコミットログからredmineのチケット番号を取得して、集計をしておいて
最後にredmineのapiを利用してそのチケット情報を取得します。

使い方としては、以下のような感じになります。
ruby svn_rm_rep.rb -r "{2015-06-01}:{2015-08-01}" -c config.yaml

config.yamlには
subversionリポジトリのURL
redmineのURL
redmineのAPIキー
を記載する必要があります。

ちなみにredmineのAPIキーの取得方法は以下が参考になります。
http://www.r-labs.org/projects/r-labs/wiki/Redmine_REST_API

ツールを実行した結果は以下のようになります。
-----------------------------------------------------------------------------------
 rev| author   | date     | add| del| ticket 
 ---+----------+----------+----+----+-----------
 872|  jagajaga|2015-05-28|   7|   3|1826
 873|  jagajaga|2015-06-11| 124|  54|1922
 874|    imoimo|2015-06-15|   1|   4|
 875|  jagajaga|2015-06-24|  63|   0|1949
 876|  jagajaga|2015-06-24|   7|   7|1950
 877|    imoimo|2015-06-24|   1|   1|1958
 878|  jagajaga|2015-06-24|  19|   7|1949
 879|    imoimo|2015-06-24|   4|   4|
 880|  jagajaga|2015-07-03|  54| 124|1976
 881|    imoimo|2015-07-07|  30|  30|
 882|    imoimo|2015-07-07|   1|   0|
 883|    imoimo|2015-07-08|   2|   1|
 884|    imoimo|2015-07-09|   1|   1|
 885|  jagajaga|2015-07-09|  53|  28|1986
 886|  jagajaga|2015-07-09|  23|   0|1986


 month      | commits | add    | del    | delta  
 -----------+---------+--------+--------+--------
 2015-07    |       7 |   +164 |   -184 |    -20
 2015-06    |       7 |   +219 |    -77 |   +142
 2015-05    |       1 |     +7 |     -3 |     +4


 author     | commits | add    | del    | delta  
 -----------+---------+--------+--------+--------
 imoimo     |       7 |    +40 |    -41 |     -1
 jagajaga   |       8 |   +350 |   -223 |   +127


 ticket | commits | add    | del    | delta  | start      | end        | diff   
 -------+---------+--------+--------+--------+------------+------------+--------
 1986   |       2 |    +76 |    -28 |    +48 | 2015-07-09 | 2015-07-15 |     +5 
 1976   |       1 |    +54 |   -124 |    -70 | 2015-07-03 | 2015-07-03 |     +0 
 1958   |       1 |     +1 |     -1 |     +0 | 2015-06-24 | 2015-06-24 |     +0 
 1950   |       1 |     +7 |     -7 |     +0 | 2015-06-22 | 2015-06-24 |     +1 
 1949   |       2 |    +82 |     -7 |    +75 | 2015-06-22 | 2015-06-24 |     +2 
 1922   |       1 |   +124 |    -54 |    +70 | 2015-06-09 | 2015-06-11 |     +2 
 1826   |       1 |     +7 |     -3 |     +4 | 2015-05-28 | 2015-05-28 |     +0 

-----------------------------------------------------------------------------------

上3つのレポートは
http://iyukki.blog56.fc2.com/blog-entry-179.html
で紹介されたのと同じです。

最後の一つがredmineの情報を組み合わせています。
ticket欄がredmineのチケット番号になっており、startがチケットを起票した日(created_on)でendがチケットをクローズした日(closed_on)になっており、diffがstartからendまでの経過日数になっています。

2014-11-24

railsのログに情報を追加する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
railsのログに情報を簡単に追加する方法として
config.log_tags
を利用する方法があります。

config/environment/develpment.rb

config/environment/production.rb
に以下のように書くとセッションIDとリモートIPをログに追加できます。
config.log_tags = [ :uuid, :remote_ip ]

ここでふと、このlog_tagsにはどんなものが記載できるのだろう?と思ってみたわけです。

調べてみたところ、log_tagsで記載した内容が、実際にログにタグとして追加する処理は以下のcompute_tagsの部分で行っているようです。
https://github.com/rails/rails/blob/21a71cd5d8f266252278a63316a99cc403a32cad/railties/lib/rails/rack/logger.rb#L57

Sybolとして指定したものは、requestオブジェクトのメソッドとして呼ばれるようです。なのでrequestオブジェクトのメソッドがここで指定できる候補になります。

実際に、以下のようにuser_agentを追加してみたら
config.log_tags = [ :uuid, :remote_ip, :user_agent ]

以下のようなログが出力されました。
[a0b386ac-c108-4820-be22-4fbf8d14a1e8] [10.10.10.10] [Mozilla/5.0(Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36] Processing by WelcomeController#index as HTML

log_tagsで指定できるのは、Symbol以外にProcも指定できて、この場合はProcオブジェクトにrequestオブジェクトを引数として渡されて処理されるようです。
またそれ以外に、文字列を指定した場合は、その文字列が単純にセットされるようです。

ただrequestのメソッドならば、なんでもSymbolで指定したり、Proc内で処理できるわけではなさそうです。sessionなどは処理できませんでした。
どうも、通常は、ログの処理よりもセッションの処理の方が後に行われるようで、sessionを指定してもログの処理の段階ではセッションの処理がまだ行われていないことが原因のようです。

なので、以下のサイトで紹介されているように、処理の順番を入れ替えることでsessionも扱えるようになるようです。
http://threetreeslight.com/post/51883603368/rails-id-ip

2014-11-06

rubyで一時的にワーニングなしで定数を変更する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
rubyで定義済みの定数の値を変更するとワーニングが出力されます。

これは本来ありがたい仕様だと思うのですが、
今回、どーしても一時的に定数を書き換えたいケースがでました。

ワーニングが出るだけで動きに支障はないので、そのままでもよかったのですが
なんとなくワーニングが消せないかなぁと調べてみました。

以下のような感じでできました。
一時的な変更と言うより、一回削除して再作成です。

class A
  MOGE="momomo"
end

p A::MOGE
-> "momomo"

muga = A::MOGE

A.send :remove_const, :MOGE

A::MOGE = "mimimi"

p A::MOGE
-> "mimimi"

A.send :remove_const, :MOGE

A::MOGE = muga

p A::MOGE
-> "momomo"


これでクラスやモジュールに定義されている定数をワーニングなしで一時的に置き換えることができました。

ちなみにグローバルに定義している定数の場合は、以下のような感じです。

HOGE = "hohoho"

p HOGE
-> hohoho"

fuga = HOGE

Object.send :remove_const, :HOGE

HOGE="hihihi"

p HOGE
-> "hihihi"

Object.send :remove_const, :HOGE

HOGE = fuga

p HOGE
-> "hohoho"

2014-06-05

Raspberry Piにつないだカメラの画像をfluentdに送ってみる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Raspberry Piにつないだカメラで撮影した静止画のデータを別のマシンのfluentdに送って、保存してもらうことを試して見ました。


Raspberry Piでカメラ画像を処理するのにはOpenCVを使ってみます。

Raspberry PiでOpenCVを使えるようにする方法は、以下を参照してください。
Raspberry PiでOpenCVをrubyで使ってみた

そして、画像でデータを受け取るfluentdの方の設定については以下を参照してください。
fluentdに画像データを送ってみる


ここでは、Raspberry Piでカメラデータを取得して、fluentdにデータを送る部分を紹介します。

Raspberry Piでfluentdにデータを送れるようにするためにfluent-loggerをインストールします。
sudo gem install fluent-logger

カメラ画像をfluentdに送るプログラムは以下のような感じです。

vi send_image.rb
require 'opencv'
require 'fluent-logger'
require 'base64'

log = Fluent::Logger::FluentLogger.new(nil, :host=>'fluentdが起動しているホスト', :port=>24224)
cap = OpenCV::CvCapture.open

loop do
  #撮影間隔を以下のsleepで調整
  sleep 1

  img = cap.query
  #おくる画像のサイズを指定する場合は、以下のコメントをとる
  #img = img.resize OpenCV::CvSize.new 640, 360
  mat = img.to_CvMat
  data = Base64.encode64(mat.encode('.jpg').pack('C*'))

  unless log.post("exec_test.image", {"sender"=>"raspberry pi","image_data"=>data})
    p log.last_error # You can get last error object via last_error method
  end
end


これで
ruby send_image.rb
とすれば画像データをfluentdに送って、fluentd側では指定したディレクトリに画像を溜め込んでいきます。


そして、ため込んだ静止画データを利用して動画を作ってみたいと思ったわけです。
タイムラプスとかいうやつです。

ここからはRaspberry Pi側ではなく、fluentdが動いている側での作業になります。

静止画を動画に変換するためにffmpegを利用してみます。

なので、まずはインストールです。
yum --enablerepo=rpmforge install ffmpeg

ffmpegで静止画を動画に変換するには、ファイルに連番がついていないといけない模様です。
今回は、データを受け取った時間でファイル名が決まるようにしていたので、そのままでは使えません。

なので以下でファイル名を連番に変換します。
c=1 ; for i in *.jpg ; do ln $i img`printf %06d $c`.JPG ; c=$((c+1)) ; done

ファイル名を連番にできたら、以下を実行して動画に変換します。
ffmpeg -r 15 -i img%06d.JPG  out.avi


ネットワークさえつながればRaspberry Piのディスク容量を気にすることなく、いっぱい撮影をすることができるようになります。

データの送る方法としてfluentdを利用するのが最適なのか?という疑問はありますけどね。


2014-06-04

fluentdに画像データを送ってみる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
fluentdの使い方として適切でないような気がするのですが、画像データをfluentdに送って処理してもらうことを試しました。

ちなみにfluentdのインストール方法は、以下を参照してください。
centosにfluentdをインストールしてrubyでデータを投げてみた


imageデータを受け取って、指定したフォルダに保存してくれるpluginもある気配です。
https://github.com/bash0C7/fluent-plugin-imagefile

でも今回はデータを受け取ったら、プログラムを起動させて、そのプログラムに処理させる設定をしてみようと思います。


まずは試しに簡単なプログラムを起動させてみます。

起動させるプログラムやデータを保存する場所を準備します。
mkdir -p /var/td-agent/bin
mkdir -p /var/td-agent/tmp
mkdir -p /var/td-agent/data/test

fluentdから起動されるプログラムを作ります。
fluentdはプログラムを呼び出す際に、受け取ったデータをファイルにしてプログラムに渡すようです。

vi /var/td-agent/bin/out_test.rb
open("/var/td-agent/data/test/hoge.txt", "w") {|f|
  f.write ARGV
  f.write File.new(ARGV[0]).read
}

所有者情報を変更しておきます。
chown -R td-agent:td-agent /var/td-agent

fluetndには、以下のような設定を追加します。
vi /etc/td-agent/td-agent.conf
---------------------------
<match exec_test.**>
  type exec
  command /usr/local/bin/ruby /var/td-agent/bin/out_test.rb
  time_key got_at
  format json
  flush_interval 5s
  buffer_path /var/td-agent/tmp/buf
</match>
---------------------------

プログラムを実行させるにはtypeをexecにします。
実行させるプログラムはcommandで指定して、データを受け渡す際に受け取った時間をtime_kleyで指定したkeyに設定することができるようです。
そして、受け渡すファイルの形式をformatで選択します。jsonを選択した場合は、1行が一つのjsonデータになるようで、一つのファイルが一つのjsonになるわけではないようです。
flush_intervalで実行するプログラムの間隔を指定することになり、buffer_pathにプログラムに受け渡すファイルが一時的に格納されるようです。

設定後に設定を反映させます。
/etc/init.d/td-agent reload

テストで以下を実行してみます。
curl -X POST -d 'json={"json":"message"}' http://localhost:8888/exec_test.test

するとjsonデータが
/var/td-agent/data/test/hoge.txt
に保存されていることを確認できます。


ここで画像を受け取って保存できるようにプログラムを修正してみます。
vi /var/td-agent/bin/out_test.rb
require 'json'
require 'base64'

inf = open(ARGV[0])
inf.each do |l|
  data = JSON.parse l

  file_name=data['got_at'] + ".jpg"
  File.open("/var/td-agent/data/test/#{file_name}", 'wb') {|f|
    f.write Base64.decode64(data["image_data"])
  }
end


画像データを投げるプログラムは以下のような感じです。
vi image_send.rb
require 'fluent-logger'
require 'base64'

filename='aaa.jpg'
image=File.new(filename).read
image_data=Base64.encode64(image)
log = Fluent::Logger::FluentLogger.new(nil, :host=>'localhost', :port=>24224)
unless log.post("exec_test.image", {"file_name"=>filename,"image_data"=>image_data})
  p log.last_error # You can get last error object via last_error method
end

aaa.jpgを用意してimage_send.rbを実行すると
/var/td-agent/data/test/xxxxxxx.jp
としてaaa.jpgと同じものが保存されます。

2014-06-03

centosにfluentdをインストールしてrubyでデータを投げてみた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ログをいい感じにいろいろ何かをしてくれる
fluentd
の話題をよく聞くような気がしたのでcentosにインストールしてみました。


まずは準備です。

vi /etc/security/limits.conf
に以下を追加します。
---------------
root soft nofile 65536
root hard nofile 65536
* soft nofile 65536
* hard nofile 65536
---------------

追加したら
reboot

再起動後
ulimit -n
として
65535
となることを確認します。

そして
vi /etc/sysctl.conf
以下を追加します。
---------------
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 10240    65535
---------------

そして設定を反映させます。
sysctl -w


fluentdをインストールします。
インストールの仕方にはいくつかあるのですが、以下の手段でインストールします。

curl -L http://toolbelt.treasuredata.com/sh/install-redhat.sh | sh

これでfluentdがtd-agentという名前でインストールされます。

fluentdの起動は以下のとおりです。
/etc/init.d/td-agent start


設定ファイルは以下になります。
/etc/td-agent/td-agent.conf

インストールされて正しく動くことを確認です。
curl -X POST -d 'json={"json":"message"}' http://localhost:8888/debug.test

以下を実行して上記のjsonの内容が出力されていることを確認します。
cat /var/log/td-agent/td-agent.log


fluentdがインストールできたので、rubyからデータを投げて見ます。

rubyからデータを投げるためにfluent-loggerを利用してみます。
他にもいくつかgemがありそうな気配ではあります。

まずはインストール
gem install fluent-logger

データを投げるプログラムを作ります。
vi test.rb
require 'fluent-logger'

log = Fluent::Logger::FluentLogger.new(nil, :host=>'localhost', :port=>24224)
unless log.post("debug.aaaa", {"agent"=>"foo","bbbb"=>"cccc"})
  p log.last_error # You can get last error object via last_error method
end

ruby test.rb
を実行して、以下に投げたjsonデータが出てきていることを確認します。
cat /var/log/td-agent/td-agent.log

2014-05-04

Raspberry PiでOpenCVをrubyで使ってみた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Rapberry PiでUSBカメラを使う際にmotionを使うのを試してみたのですが、さらに画像からいろいろ認識するとかも試してみたいと思ってみました。

ちなみにmotionを利用する方法に関しては、以下をご覧ください。
Raspberry Piに大人の科学マガジンUSB特撮カメラをつないでみた
Raspberry PiにつないだUSBカメラの画像をブラウザから確認するものをrubyで作ってみた

画像から顔やらなんやらを認識するにはOpenCVを利用するわけです。
OpenCVは
sudo apt-get install libopencv-dev
でもインストールできるのですが、インストールされるバージョンは2.3系のものが入るようです。

OpenCVをrubyから使おうと思ったりする場合は、ruby-opencvというものを利用するのですが、こちらは2.4系を必要とします。

今回はrubyで利用するので、apt-getを利用せずにインストールします。

OpenCVは、以下のようにインストールします。

コンパイルに必要になるものを準備します。以下がすべて本当に必要なのかはよくわかりません。
sudo apt-get install build-essential libboost1.46-all-dev libqt4-dev libgtk2.0-dev pkg-config opencl-headers libjpeg-dev libopenjpeg-dev  libjasper-dev libjasper-runtime libpng12-dev libpng++-dev libpng3 libpnglite-dev libtiff-dev libtiff-tools pngtools zlib1g-dev zlib1g-dbg v4l2ucp python autoconf libeigen2-dev cmake openexr gstreamer-plugins-* freeglut3-dev libglui-dev libavc1394-dev libdc1394-22-dev libdc1394-utils libxine-dev libxvidcore-dev libva-dev libssl-dev libv4l-dev libvo-aacenc-dev libvo-amrwbenc-dev libvorbis-dev libvpx-dev

ソースを取得して展開します。今回は2.4.9を持ってきました。
wget http://downloads.sourceforge.net/project/opencvlibrary/opencv-unix/2.4.9/opencv-2.4.9.zip
unzip opencv-2.4.9.zip
cd opencv-2.4.9

コンパイルします。cmakeで指定したパラメータの意味は正直よく分かりません。そしてmakeはすごく時間がかかります。
mkdir build
cd build
cmake -DBUILD_DOCS=ON -DBUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=RELEASE -DWITH_TBB=OFF -DWITH_GTK=ON -DWITH_OPENGL=ON -DWITH_QT=OFF -DINSTALL_C_EXAMPLES=ON -DWITH_OPENCL=OFF -DWITH_CUDA=OFF -DWITH_OPENNI=OFF -DWITH_UNICAP=ON -DWITH_V4L=ON -DWITH_XINE=ON  ..
make

インストールします。
sudo make install


そして、ruby-opencvをインストールします。
sudo gem install ruby-opencv


ここまでのものが正しくインストールされたことを確認します。
以下のソースを実行してoutput.jpgにカメラ画像が保存されていればOKです。


カメラ画像から顔認識して顔の部分を四角で囲ってみます。カメラ画像はwebsocketを利用してブラウザで確認できるようにします。

rubyでwebsocketを利用するためem-websocketをインストールします。
sudo gem install em-websocket

で以下のソースを実行します。

実行したらwebsocketで画像を受け取るクライアントを用意します。とりあえず以下のhtmlを用意してブラウザで見れるようにします。
サーバ側においてもいいし、手元のPCにファイルとして用意してもよいのでブラウザから開くと顔認識した画像が見れるはずです。
ブラウザはchromeでしか試していないです。


ちなみに処理はすごく遅いです。体感的には2秒ぐらいで1回画面が切り替わる感じです。


以下がすごく参考になりました。
http://naohiro7.hatenablog.com/entry/2013/04/22/142243
http://shokai.org/blog/archives/8627