メール便忘れ防止ボタンをAWS IoT ボタンで作ってみた

#若手ならではのメール便担当
僕の会社では若手の仕事として「メール便」というものがあります。
会社からの送付・受取を毎週9時・11時・15時に行うというもので、これがまた結構責任重大。
__ﾔｯﾍﾞｪｪｪ忘れてた郵送物を送り損ねた！__なんてことがあったら普通に先輩に迷惑が掛かります。

僕自身も数回メール便を忘れた実績があり、リマインダーをつけてもアラームを消してそのまま忘れることも（ひどい）。
どうにかメール便忘れを防ぐ仕組みを作りたいと思い、AWS IoTボタンを使って実装してみました。

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666990/9db75bd0-eaa1-961d-efd7-f4c9bfa1eedc.jpeg">
こいつです

#完成デモ
##メール便処理したらボタンを押す
送付したい郵便物をためておくメール便ボックスみたいなものがあり、そこに設置します。
メール便担当はちゃんとメール便を処理したよ！というときにボタンをﾎﾟﾁーと押す、という運用にします。
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666990/deba8ee3-35df-6c61-a295-3214bfde55f9.jpeg">
なんかｶｯｺｲｲ

##ボタンを押さないとアラートが上がる
メール便担当だけが参加しているTeamsがあり、メール便を忘れると所定の時間でアラート通知が上がります。
これを見て「__ﾔｯﾍﾞｪあいつメール便忘れてんじゃん行かねえと__」みたいに他の人が気づいてやってくれることも。

メール便処理をしてもボタンを押し忘れるとアラート通知が上がるので、ボタンの押し忘れだけ要注意です。
__僕はこれで何回か同期にしばかれました。__

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666990/ce717d75-7018-6ccb-c8f4-b6c4d2e0cbda.png">

##ダブルクリックで「処理したよ」
メール便未処理のアラートをみて、誰かがちゃんと処理してくれたかが分かりませんよね。
そこでボタンをタブルクリックしたら「処理したよ」通知が行くようにしています。

「いやああいつもドジだなあ」といってボタンをダブルクリックしないでメール便代打をすると、他の人が「__え・・・これ誰かちゃんと処理した・・・？誰もやってない・・・？__」みたいな不穏な空気になります。
__僕はこれで何回か同期にしばかれました。__

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666990/b14f811c-ec1a-bb87-157c-0952a8f60e2a.png">

#実装こまごま
##ボタンを押したらフラグを立てる
AWS IoTボタンを押すと、AWS Lambda経由でGoogleAppsScriptで実装した処理が実行されます。
スプレッドシートに「処理したよフラグ」が立ちます。
Lambdaの実装はこちら。

```py
import json
import boto3
from logging import getLogger, INFO, DEBUG
import urllib.request


logger = getLogger(__name__)
logger.setLevel(DEBUG)


def lambda_handler(event, context):
    
    #ダブルクリックした場合
    click_type = event['deviceEvent']['buttonClicked']['clickType']
    if click_type == "DOUBLE":
        url = 'Power AutomateのURL'
        data = {
            'message': "【自動連絡】誰かがメール便を確認しました。"
        }
        headers = {
            'Content-Type': 'application/json',
        }
        #PowerAutomateへ送信
        req = urllib.request.Request(url, json.dumps(data).encode(), headers)
        with urllib.request.urlopen(req) as res:
            body = res.read()

    #フラグを立てる
    url = 'GoogleAppsScriptのURL'
    data = {
            'message': "doPost"
        }
    headers = {
            'Content-Type': 'application/json',
        }

    req = urllib.request.Request(url, json.dumps(data).encode(), headers)
    with urllib.request.urlopen(req) as res:
        body = res.read()    
    return

```
GoogleAppsScript側はこちら。

```js
//ボタンが押されたら値をchecked!に変える
function doPost(e) {
  var spreadsheet = SpreadsheetApp.openById('スプレッドシートのID');
  var sheet = spreadsheet.getSheetByName('mailcheck');
  sheet.getRange("B2").setValue("checked!");
}
```
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666990/cd5cdcf5-d849-25fc-4797-539999c2d3a8.png">


##時間が来たらフラグの確認
メール便の時間になったときにフラグの確認をします。
時刻単位で実行するのをGoogleAppsScriptで出来るのかよくわからず、cloud schedulerを使いました。
cloud schedulerでcloud functionとPub/Sub連携をし、GAS経由でスプレッドシート内のフラグを確認します。
cloud function内でフラグを確認して、通知の必要があればPower AutomateへPostされるという仕組みになっています。

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666990/fa52b44d-e5a9-15d4-8ebe-84588c648739.png">


```py

import urllib.request, json

def doPost(self,request):
    url = "GoogleAppsScriptのURL"
    
    #スプレッドシートのメールフラグチェック
    request = urllib.request.Request(url)
    with urllib.request.urlopen(request) as response:
        response_binary = response.read().decode("utf-8")
        response_dict = json.loads(response_binary)
    
    #メール未処理の場合
    if response_dict["mailcheck"] == "none": 
        url = "Power Automate側のURL"
        obj = {"message":"【自動連絡】メール便が未処理です！"}
        method = "POST"
        headers = {"Content-Type" : "application/json"}
        json_data = json.dumps(obj).encode("utf-8")
    
        #TeamsにPOST
        request = urllib.request.Request(url, data=json_data, method=method, headers=headers)
        with urllib.request.urlopen(request) as response:
            response_body = response.read().decode("utf-8")
    
    #メール処理済の場合
    elif response_dict["mailcheck"] == "checked!":
        print("mailcheck completed")
    
    #不具合
    else:
        print("something is wrong")
        
    return "処理完了"

```

##フラグクリーニング
このままだとフラグがたったままもとに戻らなくなってしまうので、フラグクリーニングを行います。
同様にcloud schedulerを使ってgasを実行する仕様です。

```js
//時間が来たら値をnoneにcleaningする
function doGet(e){
  var spreadsheet = SpreadsheetApp.openById('スプレッドシートのID');
  var sheet = spreadsheet.getSheetByName('mailcheck');
  sheet.getRange("B2").setValue("none");
}
```

#さいごに
こういうの作ってみるとIoTボタンって結構無限な可能性あるなあという感覚。
特に__ダブルクリックで処理が変わるのは面白い__ですよね。
もっと何か作ってみてみたいところです。

最後までご覧いただきありがとうございました！
LGTMいただけるとむちゃくちゃ励みになります！何卒宜しくお願い致します！！