Androidスマホで自動写真撮影 + 写真をSlackに投稿 (Tasker使用)

Androidの自動化アプリ「Tasker」を使って自動的に写真撮影、Slackに画像を投稿するルーチンを繰り返すマクロを組んでみました。古いスマホを簡易監視カメラ、子供やペットの見守りカメラ、定点観測カメラとして活用するのに使えそうです。

#Taskerとは
時刻やセンサーの反応をトリガーとしてあらかじめ組んだマクロを実行するアプリです。マップを起動したときにGPSを起動する、夜になったら画面を暗くする、通知をOFFにする、自宅に着いたらWifiをONにする等様々な作業を自動化できます。

Google Play上のTaskerのページはこちら
https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm

Taskerのユーザーガイド(日本語)はこちら
http://tasker-userguide.pralin.info

#何をさせるのか

1. タイマー等をトリガーにして起動
2. カメラで写真を撮影して画像ファイルを保存
3. 画像ファイルを読み込み
4. HTTP通信でSlack上の任意のチャネルに画像を投稿

この流れで写真をSlackに流せるようにしていきます。

#事前準備
Taskerのタスク(マクロ)を作成する前に、以下のものを用意しておいてください。
1.SlackのAPI Token
**files.upload** を利用できる権限のTokenが必要になります(詳細は[こちら](https://api.slack.com/methods/files.upload))。私はbot用のトークンでやってみました。Tokenの取得方法については以下の記事が参考になります。
[Slack API 推奨Tokenについて](https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21)

2.画像を投稿したいチャネルのID
チャネルのIDの取得方法については以下の記事が参考になります。
[Slack | APIに使う「チャンネルID」を取得する方法]
(https://qiita.com/Yinaura/items/bd28c7b9ef614696fb7e)

#タスクの作成
Taskerを起動して適当な名前をつけた新しいタスクを作成し、アクションを

1. Take Photo
2. Read Binary
3. JavaScriptlet

の順に追加します。
それぞれ 

1. 写真撮影
2. 写真のファイルを読み込んでBase64エンコード
3. Base64エンコードされた画像データをデコードしてSlackのfiles.uploadに対してHTTP POST

を行っています。

<img src= "https://qiita-image-store.s3.amazonaws.com/0/228798/eeb148eb-4403-d5d7-92a1-ef4225908d07.png" width=50%/>


次に各アクションの詳細を設定していきます。

1. Take Photo
以下の項目についてそれぞれ設定してください。

- Filename: slack (拡張子 .jpg を除いたファイル名です。)
- Naming Sequence: None (名前に連番をつけないようにします。)

<img src= "https://qiita-image-store.s3.amazonaws.com/0/228798/735b67cf-88af-e86d-d0f6-f7f16bfaa7d4.png" width=50%/>

写真はDCIMの直下に作られたTaskerディレクトリに保存されます。

2. Read Binary
以下の項目についてそれぞれ設定してください。

- File: DCIM/Tasker/slack.jpg (読み込むファイルのパスです。)
- To Var: %image (読み込んだファイルの内容を保持する変数です。) 

<img src= "https://qiita-image-store.s3.amazonaws.com/0/228798/929e2b1b-4ef1-63c7-7de8-ae42a2dd428e.png" width=50%/>

Read Binary はバイナリファイルをBase64エンコードして文字列を変数に入れています。

3.JavaScriptlet
以下の項目についてそれぞれ設定してください。

- Code: (下のスクリプトをコピー&ペーストしてください。)
- Auto Exit: (チェックを入れておきます。)

[API Token]、[Channel ID] はそれぞれ用意しておいたAPI Token、Channel ID に入れ替えてください。

```javascript
var xhr = new XMLHttpRequest();
xhr.open("post", "https://slack.com/api/files.upload", false);
var form = new FormData();
form.append('token', '[API Token]');
form.append('channels', '[Channel ID]');
form.append('filename', 'slack.jpg');

form.append('file', toBlob(image) );
xhr.send(form);
flash(xhr.responseText);

function toBlob(base64) {
 var bin = atob(base64.replace(/^.*,/, ''));
 var buffer = new Uint8Array(bin.length);
 for (var i = 0; i < bin.length; i++) { 
  buffer[i] = bin.charCodeAt(i); 
 }
 try {
  var blob = new Blob([buffer.buffer], { type: 'image/jpg' }); 
 } catch(e) {
  flash(e);
  return false;
 }
 return blob; 
}
```

このスクリプトはBase64エンコードされた文字列となった画像をtoBlob関数でデコードしてBlobオブジェクトに変換し、FormDataオブジェクトに格納して https://slack.com/api/files.upload にPOSTしています。

<img src= "https://qiita-image-store.s3.amazonaws.com/0/228798/cc0bffb5-1040-4865-219a-8f3913529c55.png" width=50%/>

toBlob関数は以下のリンク先の記事を参考にさせていただいております。
[JS: base64文字列をBlob形式のFileに変換する](https://qiita.com/uin010bm/items/150003f016287750cf34)

タスクが出来上がったらそのまま実行して動作確認をしてみてください。うまく動作することが確認出来たら適当なプロファイル(トリガー)と結び付けて自動的に撮影・投稿するように設定します。Timeをトリガーとした定刻・定期での撮影、Event>Sensor>Shakeをトリガーとした振動に応じた撮影等をさせることができます。