PQI Air Card+Ruby1.9.3+FlickrawでFlickrにポストする
公開日:
:
最終更新日:2012/12/19
Appleいろいろ
PQI Air Cardにインストールした自力ビルドのRubyを使ってFlickrにポストできたという記録ですが、なにぶんソースからビルドなんて256倍とかRun Run Linuxを読んでた頃(=前世紀)の経験しかないブログ主の記録なので、それはないわ、とかあれば是非ともご指摘下さい。
なお、Flickrへのアップはけっこう時間がかかり、現実的なのか?!とか、iPhoneでアクセスしてiPhoneからFlickrに投げたらいいのでは?という問題は今回はおいときます。
目次
全体の流れ
さて、Air Cardからftpするのはmyashiさんの「ひとりぶろぐ » デジカメ内部でRubyを動かす狂気!無線LAN内蔵SDカードアダプタPQI Air Cardの間違った使い方」を参考にさせていただいて実現できていましたが、Flicrに投げるにはとんすけさんの「FlucardでプログラムとかCGIとか|とんすけぶろぐ」で戴いたRubyではFlickrawをインストールできずに前に進みませんでした。
そんなわけで、Rubyを自力ビルドすることになりました。が、次から次へと依存関係といいましょうか、必須なものをビルドするはめになり2週間もかかってしまいました。
結果的には全体の流れとして、
- クロスコンパイル用に仮想環境をつくる
- Ubuntuのインストール
- CodeBenchのインストール
- zlibをビルド&インストール
- OpenSSLをビルド&インストール
- yamlをビルド&インストール
- rubyをビルド&インストール
- ntpをビルド&インストール
- できたものをAir Cardにもっていき、動作するようAir Card側の環境を整える
- Flickrawをインストール
- アップロード用のスクリプトを修正
となりました。
クロスコンパイル用に仮想環境をつくる
MacBook Air(mid 2012)上のVMwareFusion5.0.2にUbuntuをインストールしたのですが、この辺りは詳細記録がないです。
選択したのはubuntu-12.04.1-server-i386です。当初は64bit版でミニマルに構成しようとしていたのですが、どうもうまくいかず、こんなところで時間を食ってるわけにはいかない、と32bitサーバー版でてんこ盛り環境を作成。
OSX側と仮想側とファイル共有するためにVMware Toolsもインストールしています。また、当初はUbuntu出来合いのクロスコンパイル環境で取り組んでいました(後にCodeBenchに変更)
aptのログをみてみると、
- Commandline: apt-get install emacs
- Commandline: apt-get install gcc
- Commandline: apt-get install build-essential linux-headers-3.2.0-29-generic-pae
- Commandline: apt-get install g++-4.6-multilib-arm-linux-gnueabihf
- Commandline: apt-get install qemu-user-static
- Commandline: apt-get install wget libssl-dev zlib1g-dev libreadline-dev libxslt-dev libxml2-dev
- Commandline: apt-get install gawk
と記録があります。2番目、3番目はVMware Toolsのインストールに必要でした。4番目、5番目は最初に試みたクロスコンパイル用パッケージ。6番目の前あたりに、前述のCodeBenchを入れています。実際にクロスコンパイルでRubyをビルドするためにRubyが必要だったので、Rubyもソースからビルドして入れてあります(これは簡単なので省略)。
Sourcery CodeBenchのインストール
どうにもうまくいかず、クロスコンパイル環境をCodeBenchに変更。この時点で不慣れなUbuntuに来た意味がなくなってしまってるのですが、もう戻れない。とんすけさんの「FlucardでプログラムとかCGIとか|とんすけぶろぐ」の真ん中あたりを参考にCodeBenchを入手してインストール。
今後間違いなくわけがわからなくなりそうなので、インストールはホームディレクトリにしました。パスは通ってないのですが、デフォルトでパスを通すのもどうかと思ったので、毎回ログイン後 export PATH=/home/hoge/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/bin:$PATH としてます。
ぐぐってみたら、解凍ソースディレクトリでConfigureしないほうがいい、とあったので素直に従い、objディレクトリを作成し、ここで作業することにします。環境変数は export ARCH=arm も設定しました。
それからいまいちわかってないのですが、必要ファイルをAir Card側にも入れておかないとダメっぽいので、
~/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/arm-none-linux-gnueabi/libc/を丸ごと、Ubuntu上の/mnt/sd/libcとしてコピーしました(Air Card内と同じ位置関係を意識)。これらはmicroSD内に置くことになるのですが、microSDはFATのためシンボリックリンクなどが使えないのでcp -LRしました。ドキュメントではlibcディレクトリ以下全部は必要ないとあったのですが、まずは動作最優先で全部入りです。以下、目標物は/usr/arm-linux/以下にインストールすることにします。
zlibをビルド
1 2 |
CFLAGS=-O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -Wl,\ -rpath=/mnt/sd/libc/lib:/mnt/sd/libc/usr/lib -Wl,--dynamic-linker |
objディレクトリではなく、ソース解凍ディレクトリで
CC=arm-none-linux-gnueabi-gcc \
LDSHARED=”arm-none-linux-gnueabi-gcc -shared -Wl,-soname,libz.so.1″ \
./configure –prefix=/usr/arm-linux –shared
としてMakefileを作ってから、Makefileを編集。以下、変更部分だけ。
1 2 3 4 5 6 7 |
CC=arm-none-linux-gnueabi-gcc CFLAGS=-O3 -D_LARGEFILE64_SOURCE=1 -DHAVE_HIDDEN -Wl,\ -rpath=/mnt/sd/libc/lib:/mnt/sd/libc/usr/lib -Wl,--dynamic-linker LDSHARED=arm-none-linux-gnueabi-gcc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map AR=arm-none-linux-gnueabi-ar RANLIB=arm-none-linux-gnueabi-ranlib prefix =/usr/arm-linux |
make
make test
sudo make install
OpenSSLのインストール
かなりハマッてしまった。最新のソースでのビルドを断念して一つ前の(openssl-1.0.1c)でなんとかOK。
perlに文句言われるので、
1 2 |
export LANGUAGE=ja_JP.UTF-8 export LC_ALL=ja_JP.UTF-8 |
ソースを解凍したディレクトリで
1 2 3 4 5 |
CROSS_COMPILE= /home/hoge/CodeSourcery/\ Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/bin/arm-none-linux-gnueabi- \ ./Configure --prefix=/usr/arm-linux --openssldir=/usr/arm-linux/etc/ssl \ --with-zlib-lib=/usr/arm-linux/lib --with-zlib-include=/usr/arm-linux/include \ threads zlib shared no-asm linux-armv4 |
としてMakefile生成後、Makefileを手修正。
CFLAGに-Wl,-rpath=/mnt/sd/libc/lib:/mnt/sd/libc/usr/lib -Wl,–dynamic-linker=/mnt/sd/libc/lib/ld-linux.so.3を追記。
1 2 |
LD_LIBRARY_PATH=/home/hoge/CodeSourcery/\ Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/arm-none-linux-gnueabi/bin |
としたが、何がよくて何がダメだったのかわからないけど、とりあえず、
make
make test
sudo make install
と無事に完了。
yamlのビルド
改めてCCをexportする
1 2 3 4 |
export CC=/home/hoge/CodeSourcery/\ Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/bin/arm-none-linux-gnueabi-gcc-4.7.2 ../yaml-0.1.4/configure --prefix=/usr/arm-linux --target=arm-linux --host=arm-linux |
configure後、MakefileのCFLAGに-Wl,-rpath=/mnt/sd/libc/lib:/mnt/sd/libc/usr/lib -Wl,–dynamic-linker=/mnt/sd/libc/lib/ld-linux.so.3を足した。
make
sudo make install
Rubyのビルド
1 2 3 4 5 6 7 8 9 |
export CC="/home/hoge/CodeSourcery/\ Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/bin/\ arm-none-linux-gnueabi-gcc-4.7.2 \ -Wl,-rpath=/mnt/sd/libc/lib:/mnt/sd/libc/usr/lib \ -Wl,--dynamic-linker=/mnt/sd/libc/lib/ld-linux.so.3" ../ruby-1.9.3-p327/configure --prefix=/usr/arm-linux \ --with-opt-dir=/usr/arm-linux --target=arm-linux \ --host=arm-linux --disable-install-doc --disable-ipv6 |
make
make test
sudo make install
ntpのビルド
Flickrawで認証エラーが出るのがなぜだかわからなかったのですが、Air Cardは時計が設定されていないので、起動毎に1月1日になってしまうため、ntpdateで時刻を取得することにしました。ビルドは適当にやって通りました。
各生成物をmicroSDに移動
/usr/arm-linux以下をvmの共有にcp -LRしてから、OSXでmicroSDをマウントして丸ごと/mnt/sd/usr/arm-linuxにコピー。/mnt/sd/libcもコピー。ntpdateをコピー。しかし/mnt/sdにたくさんあるとAir CardにiPhoneから直接アクセスするときに重くなりますね。
PQI Air Card側の環境設定
autorun.shでのシンボリックリンクの張り替え。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
ln -s /mnt/sd/usr/arm-linux /usr/arm-linux ln -s /mnt/sd/usr/arm-linux/bin/* /usr/arm-linux/bin/ ln -s /mnt/sd/usr/arm-linux/include /usr/arm-linux/include ln -s /mnt/sd/usr/arm-linux/share /usr/arm-linux/share ln -s /mnt/sd/usr/arm-linux/lib/libruby-static.a /usr/arm-linux/libruby-static.a ln -s /mnt/sd/usr/arm-linux/lib/libyaml-0.so.2.0.2 /usr/arm-linux/libyaml-0.so.2.0.2 ln -s /mnt/sd/usr/arm-linux/lib/libyaml.a /usr/arm-linux/libyaml.a ln -s /mnt/sd/usr/arm-linux/lib/libyaml.la /usr/arm-linux/libyaml.la ln -s /mnt/sd/usr/arm-linux/lib/libyaml-0.so.2.0.2 /usr/arm-linux/lib/libyaml-0.so.2 ln -s /mnt/sd/usr/arm-linux/lib/libyaml-0.so.2.0.2 /usr/arm-linux/lib/libyaml.so ln -s /mnt/sd/usr/arm-linux/lib/pkgconfig /usr/arm-linux/pkgconfig ln -s /mnt/sd/usr/arm-linux/lib/ruby /usr/arm-linux/ruby |
ntpdateを動作させるために/mnt/sd/DCIM/122_TREK/etc/servicesを作成。内容は以下のとおり。
1 2 |
ntp 123/tcp ntp 123/udp |
/mnt/sd/DCIM/122_TREK/etc/profileでパスを通す
1 |
export PATH=/usr/arm-linux/bin:$PATH |
ntpdateはアップロードスクリプトの実行直前にw2にて
1 2 |
# ntp /usr/arm-linux/bin/ntpdate ntp1.jst.mfeed.ad.jp |
Air CardからRubyでFlickrにポスト
Flickraw用にFlickr APIキー等の取得が必要です。最初に書いてますが、アップロードするのに結構時間がかかるため、実際には自前の快速ftpサーバを設けて、アップロード後、サーバー側でのんびりとFlickrにポストさせたほうがよいのかなぁ。
Flick用のトークン等の取得方法はFlickawのREADMEにあるように
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
require 'flickraw' FlickRaw.api_key="your_api_key" #http://www.flickr.com/services/apps/create/ にて取得 FlickRaw.shared_secret="your_secret" #同上 token = flickr.get_request_token auth_url = flickr.get_authorize_url(token['oauth_token'], :perms => 'delete') puts "Open this url in your process to complete the authication process : #{auth_url}" puts "Copy here the number given when you complete the process." #ここで認証用URLが表示されるのでアクセスして、返される文字列をコピーして、ターミナルで入力するとOK verify = gets.strip begin flickr.get_access_token(token['oauth_token'], token['oauth_token_secret'], verify) login = flickr.test.login puts "You are now authenticated as #{login.username} with token #{flickr.access_token} and secret #{flickr.access_secret}" rescue FlickRaw::FailedResponse => e puts "Authentication failed : #{e.msg}" end |
Rubyの勉強がてらひとりぶろぐさんのスクリプトを改変させていただきました。
autprint.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
#!/usr/arm-linux/bin/ruby # -*- coding: utf-8 -*- require 'net/http' require 'uri' require 'flickraw' #load('/mnt/sd/config.rb') # ------------------------------ # user configuration # ------------------------------ #AUTPRINT_MRK = "/mnt/sd/MISC/AUTPRINT.MRK" #FTP_SERVER = "your_ftp_server" #FTP_USER = "your_ftp_login" #FTP_PASSWORD = "your_ftp_password" #FTP_PATH = "your_ftp_dir" # http://stewgate.appspot.com/sg1/ #STEW_GATE_TOKEN = "your_stew_gate_token" #MENTION_TO = "@your_twitter_id" # flickr for flickraw #FlickRaw.api_key="your_api_key" #FlickRaw.shared_secret="your_secret" #flickr.access_token = "your_token" #flickr.access_secret = "your_access_secret" # ------------------------------ # constants # ------------------------------ STEW_GATE_API = "http://stewgate.appspot.com/sg1/post/" LINE_BREAK = "\r\n" DELIMITER = "#{LINE_BREAK}#{LINE_BREAK}" # ------------------------------ # methods # ------------------------------ def generate_signature() a = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a return " " + ( Array.new(4) do a[rand(a.size)] end ).join end def post_escape( string ) string.gsub(/([^ a-zA-Z0-9_.-]+)/) do '%' + $1.unpack('H2' * $1.bytesize).join('%').upcase end.tr(' ', '+') end def post(msg) params = { "_t" => STEW_GATE_TOKEN, "msg" => "#{MENTION_TO} " + msg + generate_signature, } begin uri = URI::parse( STEW_GATE_API ) http = Net::HTTP.new( uri.host, uri.port ) request = Net::HTTP::Post.new( uri.request_uri ) request.content_type = "application/x-www-form-urlencoded" query = params.map do |key, val| "#{key}=#{post_escape(val.to_s)}" end res = http.request( request, query.join( '&' ) ) puts "Response: #{res.code}" rescue post("Error while Stewing: #{$!}") end end def post_flickr(file) login = flickr.test.login res = flickr.upload_photo file, :title => File.basename(file), :description => "via PQI Air Card", :is_public => "0", :is_friend => "0", :is_family => "0" info = flickr.photos.getInfo(:photo_id => res) url = FlickRaw.url_short(info) #短縮URLを返す。他にも画像サイズ指定など可能。 end # ------------------------------ # main # ------------------------------ # AUTPRINT.MRKは存在するか? if !File.exists?(AUTPRINT_MRK) # 無ければ終了 exit else begin # MRKファイルの読み込み MRK_FILE = File.read(AUTPRINT_MRK) # RICOH用にCRLFを追加 if MRK_FILE.match("RICOH") MRK_FILE.gsub!("\[JOB\]", "#{LINE_BREAK}\[JOB\]") end # あれば読み込みして改行二つでセクションごとにsplit sections = MRK_FILE.split(DELIMITER) sections_shadow = sections.dup # セクションを走査 sections.each do |section| # セクションの中身を改行でsplit lines = section.split("{LINE_BREAK}") # 最初の行が[JOB]だったら if lines[0].match(/\[JOB\]/) # 1行ごとに走査 lines.each do |l| # 画像パスの行だったら if md = l.match(/^<img src="(.+)" />/) # ファイルパスをSDのマウントポイントからのフルパスにして取り出す fname = md[1].sub("..", "/mnt/sd") # フルパスの場所に画像が存在したら if File.exists?(fname) # Flickrに画像をアップロード begin flickr_res = post_flickr(fname) post("#{File.basename(fname)} uploaded to #{flickr_res} .") rescue post("Error while flickr put: #{$!}") end end # 正常に終了したらこのJOBを削除 sections_shadow.delete(section) # 終了したJOBを削除した状態でまだJOBが残っていたら # JOBを一つ削除した形でAUTPRINT.MRKを書き込み if (sections_shadow.length > 1) File.write(AUTPRINT_MRK, sections_shadow.join(DELIMITER)) else # 削除してJOBが残っていなかったらAUTPRINT.MRKを削除 File.unlink(AUTPRINT_MRK) post("All uploads done.") exit end end end end end rescue post("Error while processing: #{$!}") end end |
Comment
ありがたいですが、とてもできそうにありません!スマホンを持ちたくない妻の写真が自動でFlickrにアップされる方法を探していましたが、年間50ドルのEye-FiクラウドとIFFT以外はまだ見つかっていません。Samsung WB350Fはできるそうですが、5万円も安くありません。
武本さんのコメントを拝見いたしまして、よい物がないか探しましたが、古いEye-Fiくらいしかございませんね。
実際のところ、Flickrはアップロード速度が遅く、SDカードからのアップロードは現実的でありません。
そのため、Eye-Fi社も自社のクラウドに変えていったのかもしれません。
PQI AirCardなどでDIY的に対応してく場合、いったん、軽快な別サーバにFTPでアップロード、そこから
自動的にFlickrにアップロードさせるのが現実的かなぁと思います。
3年近く前のエントリへのコメント&お尋ね、失礼いたします。
rubyもflickrも使わないのですが…
カーナビに音楽ファイルを送る方法として、pqui air card2を購入しました。
お書きの通り、起動の度に時刻が初期値に戻ってしまうので、ntpdateを導入したいのですが、
「ntpのビルド」と「各生成物をmicroSDに移動」の具体的方法が判らずこまっております。
お教えいただけたら幸いです。
自己レスですいません。
別の方法で解決しました!
ntpdが効くようにして、
ntpd -p ipaddress
でいけました。
お騒がせしましたm..m