遅くまで会社にいたら自動で「帰り遅くなる」とメールする

#やりたいこと
残業で帰りが遅くなりそうなときは，「今日は帰りが遅くなる」と家族にメールをしているのですが，
~~面倒なので~~ メールし忘れることがあるので，これを自動化したい．

我が家には小さい子供がいるのですが，遅くとも20時半までに子供をお風呂に入れることにしています．
私の帰宅が20時半より遅いときは妻が子供をお風呂に入れることになるので，妻にとっては私の帰りが20時半を過ぎるかどうかを知りたいということになります．
私の場合，「帰りが20時半を過ぎるかどうか」は「19時半前に会社を出られるかどうか」に対応します．
そのため，19時半の時点で会社にいるかどうかを検出して，自動でメールしてくれるシステムがあればよいと考えました．


##IFTTTだけだと出来ない
IFTTTとは，IF This Then Thatの略で，
トリガーの条件（This）とアクション（That）を予め設定しておくと，トリガー条件が満たされたときに自動でアクションを実行してくれるというサービスです．

IFTTTのよくある使い方として，
「会社から帰るときに、自動で「今から帰る」とメールを送る」というのがあります．
（例えばこちらで紹介されています：　[位置情報をつかったIFTTTの自動化レシピ](https://lifehacking.jp/2014/01/ifttt-location-based/)）
会社から離れたことをスマホのGPSで検知し，これをトリガーとして，メールを送信するというものです．
これは今回やりたいことに近いのですが，トリガーに時刻という要素がありません．
そのため，次の点で困ります．

- 会社を出るときまでメールが送信されない
- 関係ない時間に会社から離れたときでも，メールが送信されてしまう（ランチタイムに会社から離れるときや，別のオフィスに移動するときなど）

以上のように，IFTTTだけでは出来ません．
が，スマホの位置情報を手軽に使うにはIFTTTが便利そうです．


#処理の流れ
下図のように，IFTTTとGoogle Apps Scriptを組み合わせたシステムをつくりました．

![図1.png](https://qiita-image-store.s3.amazonaws.com/0/239549/52da6720-a459-c093-3f26-e186791329ce.png)

1. 会社周辺エリアに入ったときと出たときの時刻のログをGoogleスプレッドシートに残す．
2. 19時半になると，最後のログをみて会社にいるかどうかをチェックし，会社にいるときはweb requestを送る．
3. web requestをIFTTTで受けると，「今日帰り遅くなる」とメールを送る．

IFTTTだけだとトリガーは「場所だけ」または「時間だけ」しか設定できないので，Google Apps Scriptと組み合わせることで「場所と時間を組み合わせた」トリガーをつくったという形になります．


なお，わざわざ3のIFTTTを用意しなくても，2のGoogle Apps Scriptの中から直接メール送信もできそうですが，
IFTTTを使えばスマホアプリから簡単にメール文章を書き換えられるので，あえてIFTTTを使ってみました．
また，IFTTTならメールの代わりにLINEでメッセージを送ることも出来ます．

以下，詳細です．

#1. IFTTTで出社・退社ログ
IFTTTでトリガー・アクションの組合せ（Applet）を設定します．
ここでは出社用と退社用の2つを作ります．
この２つはほぼ同じで，enterと入力するかexitかの違いくらいです．

[IFTTT](https://ifttt.com/my_applets)のページで「New Applet」をクリックして，This（トリガー）とThat（アクション）を設定します．
事前にIFTTTのアカウントの作成，Google Spreadsheetなどの連携登録や，スマホGPSを使うためのスマホアプリのインストールが必要です．（ここでは説明省略）

###1-1. This (Location)の設定
Choose a serviceの画面でLocationを選び，
<img width="686" alt="スクリーンショット 2018-02-22 23.34.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/340e14ac-e42f-6365-a762-dbab05a22032.png">

Choose triggerは，
出社用では"You enter an area"を，
退社用では"You exit an area"を選択します．
<img width="729" alt="スクリーンショット 2018-02-22 23.52.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/11d2fd8b-adf6-03b9-a7fa-d258173170f0.png">


あとはエリアを設定するだけです．
<img width="505" alt="スクリーンショット 2018-02-22 23.42.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/4454b723-1f22-0ed8-ac4a-92b723f032ab.png">

地図画面のドラッグで中心位置を自由に決められると思いきや，住所で指定しないとダメかもしれません．
また，エリアが狭いと設定できないので，センター位置をあえて会社から少しずらすなど，微調整が必要です．
最終的には，このあとのThatを入力したあとの画面で確認して，修正するのがよいです．

###1-2. That (Google Sheets)の設定
上のThis (Location)と同じ要領で，
Choose a serviceではGoogle Sheetsを選択し，
Choose actionではAdd row to Spreadsheetを選択します．

actionの詳細はこちら．
<img width="389" alt="スクリーンショット 2018-02-22 23.54.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/8e78fd32-f9f9-785d-7e03-7c7fe5229e4f.png">

このうち，真ん中のFormatted rowは，
出社用では"enter"（上図のとおり），
退社用では"exit"
とします．

上のSpreadsheet nameは，出社用と退社用で同じものにします．
（同じシートに出社時刻と退社時刻のログを記載していくので．）

そうやってできたスプレッドシートがこちら．
<img width="378" alt="スクリーンショット 2018-02-22 23.59.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/dc7401bf-abb6-7411-96cd-83163233690b.png">
何時に会社に行って，何時に帰ったのかのログとなっています．
これを見ているだけでも意外と面白いかも．

#2. Google Apps Scriptで会社にいるかのチェック
Google Apps Scriptは，ExcelでいうところのVBAのようなものです．
つまり，セルの値を読み取ったり，書き込んだりなどの操作をプログラムで出来ます．
（他にももっと色々な機能があるようですが）

Google Apps Scriptでプログラムを書き，時刻をトリガーにしてそれが実行されるように設定します．

##2-1. プログラムを書く
まず，上で作ったスプレッドシートの画面から，ツール＞スクリプトエディタをクリックします．
そして，次の通り，プログラムを書きます．

```javascript

var sheet = SpreadsheetApp.getActiveSheet();

//一日の通知スケジュール
function setSchedules() {
  setTrigger("checkEnterOrExit", 19, 30);
}

//その日の指定時刻にトリガーを設定
function setTrigger(funcName, h, m) {
  var triggerDay = new Date();
  triggerDay.setHours(h);
  triggerDay.setMinutes(m);
  ScriptApp.newTrigger(funcName).timeBased().at(triggerDay).create();
}

//その日のトリガーを削除する関数(消さないと残る)
function deleteTrigger(funcName) {
  var triggers = ScriptApp.getProjectTriggers();
  for(var i=0; i < triggers.length; i++) {
    if (triggers[i].getHandlerFunction() == funcName) {
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }
}

//いるかどうかをチェック（最後のログがenterかexitのどちらかをチェック）
function checkEnterOrExit() {
  //一時トリガーを消す
  deleteTrigger("checkEnterOrExit");
  
  var lastrow = sheet.getLastRow();
  var col = 1;　//1列目（A列）にenter or exitが入力されている
  var range = sheet.getRange(lastrow, col);
  var value = range.getValue();
  Logger.log("getvalue: " + range.getValue());
  
  if (value == "exit") {
    Logger.log("そのエリアにいない");
    return;

    //そのエリアにいる場合には，IFTTTのwebhookをかける
  } else if (value == "enter"){
    Logger.log("そのエリアにいる");
 
    var url = "https://maker.ifttt.com/trigger/he_is_there/with/key/xxxxxxxx...";
    UrlFetchApp.fetch(url);
    
    return;
  }
  
}
```
[Google Home、IFTTT、Googleスプレッドシートを使って独自音声コマンドでログをとる](https://qiita.com/miso_develop/items/be562d8a823ad2639d94)　のコードを参考にさせて頂きました．

会社にいるときには，プログラム中で指定したURLにアクセスします．
これにより，下の3で設定するIFTTTのトリガー（Webhooks）がかかります．

##2-2. Webhooksのkeyを調べる
最後のURLのxxxx...の部分については，自分のkeyを入力する必要があります．
keyを調べる方法は，まず下のようにwebhooksのserviceのページに行き，

<img width="799" alt="スクリーンショット 2018-02-23 23.00.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/0f622235-6057-6432-70e2-b4c842b344e9.png">

（↓Webhookアイコンをクリックして，下の画面に移動）

<img width="787" alt="スクリーンショット 2018-02-23 22.57.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/53870e6a-caf7-24fe-3cad-9ae6e193845c.png">

右上の"Documentation"をクリックすると，keyが表示されます．
<img width="910" alt="スクリーンショット 2018-02-23 23.04.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/0cd91989-f315-97fc-969d-c2de27ee1fff.png">

これをコピーして，Google Apps ScriptのプログラムのURL部分に貼り付けます．

##2-3. トリガーを設定する
次に，プログラム中の関数を実行するトリガーを設定します．
上のプログラムを書いたスクリプトエディタの画面から，編集＞現在のプロジェクトのトリガーをクリックして画面を開き，次のように設定します．

<img width="829" alt="スクリーンショット 2018-02-23 22.42.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/fb32f72a-1cec-2091-707a-fd187bb316d6.png">
「午前9時〜10時」というのは適当に決めました．
この時刻になると自動で19:30というトリガーが設定されます．


#3. IFTTTでメール送信
上の「1. IFTTTで出社・退社ログ」と同じように，IFTTTを使います．
1と同じ要領なので，解説は省略．
<img width="575" alt="スクリーンショット 2018-02-23 23.06.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/113d2c3f-45b6-833b-dd15-875b44e2a51d.png">
↓
<img width="506" alt="スクリーンショット 2018-02-23 23.07.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/4a485783-d7d7-f7fb-5428-2890623aac0d.png">
↓
<img width="572" alt="スクリーンショット 2018-02-23 23.07.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/803be1fb-705c-1c57-bf1d-ccc165198bc5.png">
↓
<img width="497" alt="スクリーンショット 2018-02-23 23.07.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/239549/e5e1dd97-5b77-a097-9523-61d8cd274c8e.png">

以上で完成です．

#おわりに
遅くまで会社にいたら自動で「帰り遅くなる」とメールするシステムをつくりました．
IFTTTだけだと単純なトリガーしか使えなくてイマイチ自分に合ったものがつくれないなーと思っていたのですが，
Google Apps Scriptを組み合わせることで解決できました．
他の用途にも色々使えそうです．

なお，Google Apps Scriptでなく，MESHと組み合わせることでIFTTTのトリガーに発動時間を指定する方法がこちらで紹介されていました．なるほどです．
[IFTTTアクションの発動時間を制御する方法を発見！](https://y-harada.net/wordpress/?p=4676)