LaMetricTimeを使って朝会議があるときだけ開始前にアラームを鳴らす

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/9cac3dd0-b32e-7ab8-e85a-9ae09d1e436f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/a4876e66-df60-ec33-f69c-3e83534a9449.png)

LaMetric Time [https://LaMetric Time.com/ja-JP?market=]() というスマートクロック（クラウドやAPIを使って操作できる据え置き型時計）があることをご存じでしょうか。私は知りませんでした。もう何年も前から日本でも容易に入手できていたようですね。
事の発端はコロナ渦にまで遡ります。在宅勤務になって朝会議がZOOMで行われるようになり、寝坊して出られない悲劇に見舞われるサラリーマンが続出していると想像されます。そこで何かソリューションを考えなくてはという正義感にかられて今回のPoCに臨むことにしました。

# 1. 実現したいこと

1. Google Calendarから会議の開始時間を取得（OutlookからGoogle Calendarに連携すれば、Outlookのイベントをトリガーにすることも可能）
1. 平日の朝会議だった場合、会議開始前30分にアラームを鳴らす
1. 起きてもらわないと意味が無いので、この時のアラームは大音量で鳴らしたい

ポイントは、朝会議があるときだけ、その会議の直前にアラームを鳴らしたいということです。
言い換えれば、朝会議がなければアラームは鳴らさなくて良いし、朝会議が9時からなら8:30に、10時からなら9:30にといった具合に直前まで寝かせておいてあげる優しさも欲しいということです。

これを行うには以下のような技術要素が必要（あったら良い）ということになります。
1. IFTTTやAPIから自由にアラームを鳴らせること
1. IFTTTやAPIから自由にアラーム音を変えられること

# 2. LaMetric Timeで出来ること

結論から言うと、IFTTTやAPIで操作できる据え置き型時計はLaMetric Timeしか見あたりませんでした。お高い商品ですが、見た目も可愛く、カラー表示も可能なので目を瞑って購入ボタンを押しました。

### 2-1. IFTTTで出来ること（トリガー）

今回、IFTTT上のトリガー周りは直接使用しないのですが、IFTTTの他のサービスに繋ぎ込んだりも出来るので便利です。IFTTTはERST APIを発火することも出来るため、この後出てくるLaMetric TimeのAPIを使って、LaMetric Time自体の操作なども可能です。

1. **Action Button Pressed**：LaMetric Timeのアクションボタンを押すたびに発生するトリガーです。IFTTTのLaMetric Time用アプリは2種類公開されていて、その2種類それぞれにアクションボタンの動作を割り当てることが出来ます。LaMetric Time自体についているアクションボタンは1つなので、アプリを切り替えることで2種類の動作が可能といったイメージになります。
1. **Alarm Went Off**：LaMetric Time Clockアプリがアラームを発生させた時にイベントを発生させます。
1. **Timer Started**：タイマーアプリがLaMetric Timeデバイスのカウントダウンを開始した際に発生するトリガーです。
1. **Timer Finished**：カウントダウンが終了したときにイベントを発生させるトリガーです。

### 2-2. IFTTTで出来ること（アクション）

アクションは色々と用意されています。が、やはり限定的なところもあります。また、LaMetric TimeのAPIでも出来るしIFTTTでも出来ることと、LaMetric TimeのAPIでしか出来ない事が混在します。内容によってはIFTTTからしか出来ない内容もあります。

1. **Display Notification**：このアクションは、LaMetric Timeに通知を表示します。
1. **Display Sticky Notification**：LaMetric Timeデバイスに通知を表示します。通知は、解除されるまで画面に表示されます。
1. **Update Indicator App**：LaMetric TimeのIndicatorアプリを更新し（表示内容を指示）ます。
1. **Set Clock Face**：LaMetric Timeデバイスの時計の文字盤を設定または更新するアクションです。
1. **Activate App**：LaMetric Time端末で特定のアプリを起動するアクションです。以下のようにインストールされたアプリから選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/f9e352eb-4b0e-7baf-8778-5bba6dde4611.png)
1. **Start Radio**：LaMetric Timeのデバイスでラジオ再生を開始します。チャンネルの指定は出来ないようです。
1. **Stop Radio**：LaMetric Timeデバイスのラジオ再生を停止します。
1. **Start Timer**：LaMetric Timeデバイスのタイマーを開始します。タイマー時間は以下から選択出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/dd1aa9b2-76a5-4df8-9e0f-9d79d9f174c3.png)
1. **Pause Timer**：LaMetric Timeデバイスのタイマーを一時停止します。
1. **Reset Timer**：LaMetric Timeデバイスのタイマーをリセットします。
1. **Start Stopwatch**：LaMetric Timeデバイスでストップウォッチを開始します。
1. **Pause Stopwatch**：LaMetric Timeデバイスのストップウォッチを一時停止することができます。
1. **Reset Stopwatch**：LaMetric Timeデバイスのストップウォッチをリセットするアクションです。

半分近くはタイマーとストップウォッチに関するものですね。そして、所謂アラームそのもののセットという機能がないので、今回はタイマーを上手く使って実現をしていきたいと思います。もう一つ気付くのは、音量の指定が出来ないということです。普段は音量を下げて使いたいですが、タイマーのアラームを鳴らすときには音を大きくしたいので、IFTTTだけでは役者不足ということになります。

:::note warn
IFTTTからは音量調節が出来ない
:::

### 2-3. APIで出来ること

[https://LaMetric Time-documentation.readthedocs.io/en/latest/reference-docs/LaMetric Time-time-reference.html]()
こちらに、APIのドキュメントがあります。

APIは**ローカルネットワークから**REST APIで行う事が出来、以下のような書式で行います。


```text:エンドポイント
https://local-ip-address:4343/api/v2/device/apps/com.LaMetric Time.clock/widgets/1_com.LaMetric Time.clock/activate
└─ LaMetric Timeに直接リーチ出来るネットワークでないといけない。
└─ ポート4343にて暗号化通信に対応しているのはありがたい。
```

:::note warn
（無手の状態では）ローカルネットワークからのアクセスが前提
:::

```text:ヘッダー
Content-Type: application/json
Authorization: Basic base64-data
└─ base64-dataは dev:api-key をBASE64エンコードしたテキスト値
```
ボディーはPOSTなどで必要であればJSON形式で指定をするといった感じです。
api-keyは、スマホアプリやWEBからLaMetric Timeにログインすると、紐付けられたデバイスの情報として参照が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/6565f7ff-735c-06a3-202a-2e191e807d33.png)

APIで出来ることは主に以下の通りです。

1. **Device**：デバイスに関する確認や指定
1. **Apps**：アプリに関する確認や指定
1. **Notifications**：ノティフィケーション関連
1. **Display**：ディスプレイに関する確認や指定
1. **Audio**：オーディオに関する確認や指定（音量指定もココで可能）
1. **Bluetooth**：ブルートゥースに関する確認や指定
1. **Wi-Fi**：Wi-Fiに関する確認や指定

エンドポイント一覧はこちら
[https://LaMetric Time-documentation.readthedocs.io/en/latest/reference-docs/device-endpoints.html]()

# 3. IFTTT（インターネット）からLaMetric TimeのAPIをコール出来るようにする

LAN上でCurlでAPIをコール出来てもあまり嬉しくはありません。WAN側からキック出来ないとIFTTTから色々と操作出来ないためです。
そこで、ルーターのポートフォワード機能を使って特定のポートへのアクセスがLaMetric Timeに向くように設定します。
グローバルIPを取得していない場合は、ngrokやその他のDDNSサービスを使ってインターネットから自宅環境に到達出来るようにしておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/61dc1c84-640b-d308-4acc-0dcbb5216ad5.png)
適当な外部ポートをLaMetric Timeに割り当てられたローカルIPの4343に割り当てます。4343はLaMetric Timeの固定ポートです。インターネットを経由することになるので、必ずこの4343暗号化通信を使います。
LaMetric TimeのローカルIPはDHCPなどで振っていると変わってしまう可能性があるので、常に同じIPが割り振られるようにDHCPで設定するか、固定IPを割り振るようにしておきます。

:::note alert
ポート4343のSSL暗号化通信を使う
:::

# 4. IFTTTを起点にフローを書いていく

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/0b11d93a-712a-9a67-4f6f-93e361a8d5ef.png)

1. カレンダーのイベントを起点にイベント開始30分前に動作開始
1. フィルターコードで、平日、朝会議といった条件を検査
1. 5分後にアラームをセット
1. 5分後に音量を大きくするAPIをキック（する別のIFTTT WebHookをキックしておく）
1. 5分45秒後に音量を元に戻すAPIをキック（する別のIFTTT WebHookをキックしておく）
1. イベント名を表示
1. 10分後に時計表示に戻す

といった動作をするようにしてあります。それぞれのWidgetの内容を見ていきます。

### 4-1. カレンダーのイベントを起点にイベント開始30分前に動作開始

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/4a8af9dc-557a-5456-4e31-91e695135dc6.png)
Googleアカウントを指定して、どのカレンダーからイベントを取得するか指定します。
動作タイミングとしては30分を指定します。もっと前にアラームを鳴らしたいのであれば、ここを調節すればOKです。

### 4-2. フィルターコードで、平日、朝会議といった条件を検査

平日朝の会議だけが気になる分けなので、それ以外のイベントについては無視するようにフィルターコードを書きます。
IFTTTで取得出来る時間情報をそのままキャスとしようとすると、なんだか失敗することがある（あった気がする）ので作ったのが冗長ではありますが「確かに日付型にキャストする手順JS」です。これを利用して曜日と時間帯の判定を行っていきます。

```Filter code.js
let eventTime = GoogleCalendar.anyEventStarts.Starts;

// Year
let regex = new RegExp('[0-9]{4}');
let yyyy = eventTime.match(regex)[0];

// Month
regex = new RegExp('^[a-zA-Z]*');
let moOrg = eventTime.match(regex)[0].trim();
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
let mo = (months.indexOf(moOrg) + 1).toString();

// Day
regex = new RegExp('(?<= )[0-9]{1,2}(?=,)');
let dd = eventTime.match(regex)[0];

// Hour
regex = new RegExp('[0-9]{2}(?=:)');
let hh = eventTime.match(regex)[0];

// Minutes
regex = new RegExp('(?<=:)[0-9]{2}');
let mi = eventTime.match(regex)[0];

if (eventTime.indexOf('PM') > -1) hh = (parseInt(hh) + 12).toString();

// Reformatting
let myDateFormat = `${yyyy}/${mo}/${dd} ${hh}:${mi}:00`;
let myDate = new Date(myDateFormat);

// 0:sun~6:
let weekDate = myDate.getDay();

if (
  (weekDate == 0 || weekDate == 6) ||
  (Number(hh) < 9 || 11 < Number(hh))
) {
  LaMetric Time.startTimer.skip();
  LaMetric Time.notification.skip();
  MakerWebhooks.makeWebRequest1.skip();
  MakerWebhooks.makeWebRequest2.skip();
}
```

:::note warn
イベント開始時刻文字列をそのまま日時型にキャストしても上手く行かないことがある
:::


### 4-3. 5分後にアラームをセット

メインイベントとなるアラームの部分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/64568358-78b1-a791-4e25-831c5077f632.png)
5分後にタイマーを仕掛けます。ピピッピピッという無機質な音しか選択出来ませんが、まずはこれで我慢ということにします。イベント30分前に5分後のタイマーを仕掛けるので、起床はイベントの25分前となります。

### 4-4. 5分後に音量を大きくするAPIをキック（する別のIFTTT WebHookをキックしておく）5分45秒後に音量を元に戻すAPIをキック（する別のIFTTT WebHookをキックしておく）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/b855c4b4-2224-cc0a-3db2-27e08f423524.png)

別のWebHookを作っておいて、5分後に音量を上げて、5分45秒後に音量を下げるように**予約**します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/64c78690-11ed-8213-d394-7555c009bb0a.png)
呼び出されるWebHookはシンプルで、Delayを使って5分待機してからLaMetric TimeのAPIをコールするようになっています。
このDelayが曲者で自由に時間を指定出来ず、分は5単位、秒は15秒単位でしか指定出来ないため、今回も5分とか5分45秒といった間隔になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/ab339879-8096-e442-d469-03cdeae902fb.png)
LaMetric TimeのAPIコール部分はこんな感じです。自宅のアドレス、ドメインなどに適当につけたポートを指定してアクセスさせます。ポートフォワードが出来ていれば、これでローカルネットワーク上のLaMetric Timeに到達出来ます。繰り返しになりますが、httpsを指定して暗号化通信をするように指定する事も忘れないようにします。

:::note alert
httpsスキーマを指定しSSL暗号化通信を行う
:::

IFTTTのDelayには引数を指定出来ないため、5分待機とか、5分45秒待機といった指定は固定になるものの、音量の指定部分はWebHookの引数を利用出来ます。

### 4-6. イベント名を表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206965/a86b156b-d305-af02-8cfd-17784060d261.png)
見るか分かりませんが、イベント名も一定期間表示しておきます。音は鳴らしても良いかもしれません。実行はイベント開始30分前に行われるので、5分後のアラームを待たずにもしかしたらスッキリ起きてくれるかもしれないからです。但し、今回この時点では音量を上げていないので、気付かれることは無いかもしれません。

PriorityはImportantにしておきます。こうすることでスクリーンセーバーが掛かっていても実行がされます。スクリーンセーバーは設定にも寄りますが、暗くなったら実行するようにしている場合など、カーテンを閉めきった朝の暗い部屋では実行されている可能性も高いと思われます。

### 4-7. 10分後に時計表示に戻す

いちいち手動で時計表示に戻すのが面倒なので、10分後に時計表示に戻すWebHookも実行しておきます。

# 5. まとめ

いかがでしたでしょうか。これで寝ている間に朝会議を設定されたとしても、ちゃんと会議前に起きられる環境が出来上がりました。
更に、IFTTTからLaMetric TimeのAPIも叩ける環境が整ったので、色々と試すと面白いのではないでしょうか。

以上