FlashAir(W-04)の画像をGoogle Photos(Picasa Web)のアルバムにアップロードする

カメラをEOS7D Mark IIに新しくしたら、SDカードがUHS-I対応と言うことで、Wi-Fi SDカードもUHS-I対応のFlashAir W-04に変更しました。

f:id:naoyukinagano:20180102102210j:plain

そこで、luaスクリプトを使ってFlashAirから直接Google Photosにアップロードを試みたのですが、何度やってもエラー。どうやらPicasaweb APISSL証明書のサイズが大きいらしく、ネゴシエーションエラーを起こすようです。

 

seesaawiki.jp

そこで、方向を変え、PQI Airと同様、IPアドレスを固定とし、サーバーからFlashAirに対して写真をダウンロードしに行き、サーバーからGoogle Photosにアップロードすることにしました。

 

まずはIPアドレスを固定します。

FlashAirのCONFIGで設定します。

/SD_WLAN/CONFIGに[Vender]とは別に新たに[WLANSD]というセクションを設けて、IPアドレス等を指定します。

私の場合は192.168.x.161としました。(xは皆さんの環境に合わせてください。)

ルーターは192.168.x.1です。

IDは適当な名称をつけてください。

 [WLANSD]

ID=Flashair_999
DHCP_Enabled=NO
IP_Address=192.168.x.161
Subnet_Mask=255.255.255.0
Default_Gateway=192.168.x.1
Preferred_DNS_Server=192.168.x.1
Alternate_DNS_Server=8.8.8.8

 

で、STAモード(インフラストラクチャモード、つまり子機となってWi-Fiアクセスポイントに接続しにいくモード)で接続します。

私は次のサイトを参考にさせてもらいました。

database-tearoom.seesaa.net

そして、サーバー側のスクリプトを書きます。

手順としては、192.168.x.161を死活監視します。

もしhttpの応答があったら、/DCIM直下にあるindex.htmlの中から指定した名称が入ったフォルダのリストを抽出して配列に格納します。

通常、カメラは/DCIMの配下にカメラの機種名かメーカー名が入ったフォルダを作成し、その配下に9999枚までのファイルを保存していきます。たとえば私の場合はxxxEOS7Dという感じ。xxxは数字3桁ですね。

これをキーとして抽出することで、FlashAirの制御用画像を対象外にすることが出来ますし、どれだけフォルダが出来ても全てスキャン出来ます。

それぞれの配下のindex.htmlからファイルリストを取得します。

ファイルを一つづつflashair_done.txtの中にあるかないかをgrepで検証し、あれば処理を無視、なければwgetでFlashAirからダウンロード。

そして2048pxに縮小、Google Photosにアップロード、flashair_done.txtに書き出し、exiftoolで日付ディレクトリに移動させて、次のファイルの処理を行います。

 

アップロードの処理については前回PQI Airの際に作成した"upload_images_in_dir.sh"に任せます。

gentoolinux.hatenablog.com

 

必要なアプリケーションとしてはsedwgetImagemagick、exiftoolです。

 

スクリプトはこうなりました。

FLASHAIR_IP=にはFlashAirのIPアドレスを、

DCIM_FOLDER=にはカメラがDCIMの配下に作成するファイル名の3桁の数字を除いた文字列を入れてください。

 

#!/bin/bash

#初期変数一覧

#Flashairのアドレス
FLASHAIR_IP="http://192.168.x.161"

#DCIMフォルダの名称
DCIM_FOLDER="CANON"


#現在のディレクトリに移動
cd `dirname $0`

#プロセスIDを保存
echo $$ > pid.txt

#DCIMフォルダのURLを生成
WGET_PRE_URL=${FLASHAIR_IP}"/DCIM/"

 

while :
do

#Flashairを死活監視
ALIVE=$(/usr/bin/wget -nv --spider --timeout 60 -t 1 ${FLASHAIR_IP} 2>&1 | grep -c '200 OK')

#もし死活監視で生きていたら
if [ $ALIVE -eq 1 ]; then

#配列を初期化
echo "Flashair - Format Arrys."
DCIM_LIST=()
JPG_LIST=()

#DCIM配下のディレクトリを配列に代入
echo "Flashair - Get under DCIM directory list."
DCIM_LIST=(`/usr/bin/wget ${WGET_PRE_URL} -q -O - | grep 'wlansd.push({"r_uri"' | sed -e 's/wlansd.push({"r_uri":"//' -e 's/", "fname":"/\//' -e 's/", "fsize".*//' | grep ${DCIM_FOLDER}`)

#フォルダの数だけループ処理を実施
echo "Flashair - Starting loop under DCIM directory."
DCIM_LOOP=${#DCIM_LIST[@]}
DCIM_LOOP=$*1
while [ $DCIM_LOOP -ge 0 ];
do

#フォルダの中のファイルを配列に代入
echo "Flashair - Get file list under "${DCIM_LIST[DCIM_LOOP]}
JPG_LIST=(`/usr/bin/wget ${FLASHAIR_IP}${DCIM_LIST[${DCIM_LOOP}]} -q -O - | grep 'wlansd.push({"r_uri"' | sed -e 's/wlansd.push({"r_uri":"//' -e 's/", "fname":"/\//' -e 's/", "fsize".*//'`)

#ファイルの数だけループ
echo "Flashair - Starting loop under "${DCIM_LIST[DCIM_LOOP]}
JPG_LOOP=${#JPG_LIST[@]}
JPG_LOOP=$*2
while [ $JPG_LOOP -ge 0 ];
do

#アップ済みのファイルかどうかをチェック
echo "Flashair - Check FLASHAIR_DONE "${JPG_LIST[JPG_LOOP]}
if ! `cat flashair_done.txt | grep -q "${JPG_LIST[JPG_LOOP]}"` ; then

#アップ済みになかった場合の処理
#wgetによるファイルの取得
echo "Flashair - Get file "${JPG_LIST[JPG_LOOP]}
/usr/bin/wget -q -N --no-host-directories --no-directories ${FLASHAIR_IP}${JPG_LIST[JPG_LOOP]}

#ダウンロードした全てのJPGを2048pxにリサイズ
echo "Flashair - Resize "${JPG_LIST[JPG_LOOP]}
/usr/bin/mogrify -resize 2048x2048 -quality 100 *.JPG

#ディレクトリ上にあるJPGファイルをpicasaweb APIでアップロード
echo "Flashair - Uploading "${JPG_LIST[JPG_LOOP]}
./upload_images_in_dir.sh

#ディレクトリ上にあるJPGファイルを日付ディレクトリで整理
echo "Flashair - Move YMD directory "${JPG_LIST[JPG_LOOP]}
/usr/bin/exiftool -q '-Directory < CreateDate' -d %Y%m%d *.JPG

#flashair_done.txtにファイル名を追加
echo "Flashair - Output to flashair_done.txt "${JPG_LIST[JPG_LOOP]}
echo ${JPG_LIST[JPG_LOOP]} >> flashair_done.txt

fi

JPG_LOOP=$*3
done


DCIM_LOOP=$*4
done

fi

sleep 10
done

 

 

ちなみに、upload_images_in_dir.shの中身はこんな感じです。

#/bin/bash

CLIENT_ID="xxxxxx.apps.googleusercontent.com"
CLIENT_SECRET="yyyyyy"
REFRESH_TOKEN="zzzzzz"
USER_ID="" #googleアカウントのユーザー名
ALBUM_ID="aaaaaaaaa(全て数字)"

#アクセストークン取得
curl -s --data "refresh_token=${REFRESH_TOKEN}" --data "client_id=${CLIENT_ID}" --data "client_secret=${CLIENT_SECRET}" --data "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token > token.JSON
ACCESS_TOKEN=`cat token.JSON | jq -r '.access_token'`


ENDPOINT="https://picasaweb.google.com/data/feed/api/user/${USER_ID}/albumid/${ALBUM_ID}?access_token=${ACCESS_TOKEN}"

DIR="./" # 任意のディレクトリを指定

IFS_BAK=${IFS}
IFS="
"
FILES=`ls -1 ${DIR}`
for FILE in ${FILES}
do
if [ "${FILE}" != "" ]; then
TYPE="UNKNOWN"
case "${FILE}" in
*\.bmp) TYPE="image/bmp";;
*\.JPG | *\.jpg) TYPE="image/jpeg";;
*\.png) TYPE="image/png";;
*) TYPE="UNKNOWN";;
esac
# echo "$TYPE $FILE $LENGTH"
if [ "${TYPE}" = "UNKNOWN" ]; then
continue;
fi
LENGTH=`ls -l "${DIR}/${FILE}" | tail -n1 | sed -E 's/ +/ /g' | cut -d' ' -f5`
curl -s -XPOST "${ENDPOINT}" \
-H "Content-Type:${TYPE}" \
-H "Content-Length:${LENGTH}" \
-H "Slug:${FILE}" \
--data-binary "@${DIR}/${FILE}" > /dev/null
sleep 1
fi
done
IFS=$IFS_BAK

 

うーん。このインデントがなくなるの、なんとかならないかなぁ。

*1:DCIM_LOOP - 1

*2:JPG_LOOP - 1

*3:JPG_LOOP - 1

*4:DCIM_LOOP - 1