在宅勤務中のランチタイムを IoT でアピールしてみた

# 作った動機

COVID-19 の影響で在宅勤務になった方、多いかと思います。社員間のコミュニケーションのほとんどが Slack になったという方も多いのではないでしょうか。私の場合はかねてより Slack 中心の生活を送っていましたが、最近 Slack 上にオフィスがあるような気持ちが強まりました。

Slack ではできるだけ即レスしたいな、と思う気持ちはある一方で、この情勢ではきちんと休憩をとることも大事だと思い昼休みの時間などは意図的に Slack デトックスをするようにしています。
そんなわけで昼休み中はできるだけ Slack 上のステータスを "lunch" にして「今はちょっとすぐには返せないよ」という意思表示をしていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/aa5a3818-2b49-003d-b3c5-c2966539480d.png)

ただ毎回 Slack の"Set a status" を開くのは少し億劫だったので、何か簡略化する方法はないかと思ったのがきっかけです。

# 作ったもの

加速度センサー付きの [GPS マルチユニット SORACOM Edition](https://soracom.jp/products/kit/gps_multiunit/) なるものを購入したのでこちらを使ってみることにしました。

こちらのデバイスの青い面を上にすると、重力加速度で z ≒ -1G となり、下にすると z ≒ 1G になっていました。以下は SORACOM Harvest Data で確認してみた結果です。何度かひっくり返して、1000 か -1000 になっているのがわかります (単位は mG)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/34a0504b-985f-798e-af0b-3d395d2108b8.png)

(こんな感じで青い面が上だと、約 -1000 になる)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/94baf02f-1366-c44e-b75e-3a113b2e1266.png)

[SORACOM Funk](https://soracom.jp/services/funk/) というサービスを利用すると AWS Lambda などの FaaS を手軽に呼べるので、デバイスの上向き下向きで status を変更する Slack API を呼んでみることにしました。以下がシステムの構成図です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/4615adf9-9884-e393-af5e-920e16cc3ec3.png)

これによって、デバイスをひっくり返すだけで自分がランチ中かを Slack に反映できるようになりました。

# 具体的な設定・コード

GPS マルチユニット SORACOM Edition は SORACOM ユーザーコンソール上でポチポチと送信する情報や頻度、時間帯を指定できます。今回の目的はランチタイムのアピールなので平日の 10:00-15:00 の間に 5 分間隔で送信する設定にしてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/0cfb10e9-fb01-e90e-639a-2b2b5954d5ff.png)

SORACOM Funk から AWS Lambda を呼んで Slack API を叩く方法は[公式ドキュメント](https://dev.soracom.io/jp/start/funk_aws_lambda/)を参考にしました。

Slack API で Status を変更する方法は [Slack の API ドキュメント](https://api.slack.com/docs/presence-and-status)を参考にしました。なお今回の実装には`users.profile:write` 権限を持ったトークンを発行する必要があるのですが、この権限だと[自身の氏名や電話番号といった情報も変更できてしまう](https://api.slack.com/methods/users.profile.set)ので、トークンの取り扱いには注意してください。

参考ドキュメントを踏まえて、以下のようなコードにしました。SLACK_TOKEN を Lambda の環境変数に入れます。

```javascript
const https = require('https');
const url = require('url');
const slackToken = process.env.SLACK_TOKEN;
const slackUrl = "https://slack.com/api/users.profile.set";

exports.handler = function(e, ctx, cb) {
    console.log('event: %j', e)
    console.log('context: %j', ctx)

    var slackReqOptions = url.parse(slackUrl);
    slackReqOptions.method = 'POST';
    
    var payload = 
      e.z < -900 ? { "profile":{"status_text": "lunch", "status_emoji": ":rice:"}}
    : e.z > 900 ? { "profile":{"status_text": "", "status_emoji": ""}}
    : { "profile":""}
    ;
    
    var body = JSON.stringify(payload);
    console.log("body: %j", body);
    var auth = "Bearer " + slackToken; 
    slackReqOptions.headers = { 
        "Authorization": auth,
        'Content-Type': 'application/json; charset=utf-8',
        'Content-Length': Buffer.byteLength(body),
        };
    var req = https.request(slackReqOptions, function(res) {
        if (res.statusCode === 200) {
            console.log('Posted to slack');
            console.log('res: %s',res)
            cb(null, {"result":"ok"});
        } else {
            cb(false, {"result":"ng", "reason":'Failed to post slack ' + res.statusCode})
        }
        return res;
    });
    req.write(body);
    req.end();
};
```

# 応用

上記もシンプルで良いのですが、`e.z > 900` (デバイスが下向き) の時に毎回 status がリセットされてしまい、何かしらの理由で手動で status をセットしたい場合などに不便でした。

GPS マルチユニット SORACOM Edition にはファンクションボタンというのがついており、こちらを押下することでもデータが送信されます。これを利用し、さらにせっかくなので側面も利用して以下のようなルールにしてみました。

- ファンクションボタンを押す : status をリセット
- デバイスが上向き : 何もしない
- デバイスが下向き : ランチタイム
- デバイスが横向き① : コーヒータイム
- デバイスが横向き② : 集中タイム

なおこのデバイスの側面はあと 2 つあるのですが、ちょっと自立しなかったので今回は利用を見送りました。しかしこれらの側面もうまく使えれば合計で 5 つのイベントを手軽に送れるデバイスになるので、さらなる応用の可能性を感じました。

上記のルールを踏まえで、上記のコードの `payload` 部分を以下のように変えました。ファンクションボタンを押下すると `{"type": 1}` でデータが送信されます。

```javascript
    var payload = 
      e.type == 1 ? { "profile":{"status_text": "", "status_emoji": ""}}
    : e.z > 900 ? { "profile":{"status_text": "lunch break", "status_emoji": ":rice:"}}
    : e.x > 900 ? { "profile":{"status_text": "coffee break", "status_emoji": ":coffee:"}}
    : e.x < -900 ? { "profile":{"status_text": "concentrating", "status_emoji": ":male-technologist:"}}
    : { "profile":""}
    ;
```

# (補足) GPS マルチユニットを使った理由

SORACOM や AWS の費用を考えると [LTE-M Button](https://soracom.jp/products/gadgets/) の方がボタンを押したときだけイベントを送信するので安いという風にも考えたのですが、以下にメリットを感じて GPS マルチユニットを使うことにしました。

- LTE-Button だと「ランチモードにしたっけ？」みたいなのが自信なくなるが、GPS マルチユニットだと実物の向きで状態がわかる
- LTE-M Button は送信完了までに時間がかかって「ちゃんと送れるかな...？」みたいなドキドキがあるが、GPS マルチユニットは 5 分に 1 回勝手に送ってくれるので向きを変えた瞬間に意識しなくてよくなる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/6d8951b8-cd2a-2d00-5755-f60bd7f66a91.png)

# まとめ

GPS マルチユニット SORACOM Edition と AWS Lambda を組み合わせることで手軽に Slack の Status を変更できました。側面も駆使して 3 パターンの状態を送信でき、ケースなどがあれば 5 パターンの状態も送れる可能性があります。