「寝てたら起こして」の仕組みを作る

公開:2021/02/03
更新:2021/02/04
4 min読了の目安(約3600字TECH技術記事

アラームは設定したくない。
とはいえ寝坊もしたくない。
だから「寝てたら」起こして欲しい。

仕組み

仕組みの図

IFTTTGoogle Apps Scriptでやってることをまとめるとこんな感じ。コード量は少なめで、わりとシンプル。始業が11時なので、10:50まで寝てたら起こしてもらいます。

IFTTTに馴染みがない方に補足しておくと、If This, Then That の略で"イフト"と読みます。名前のとおり「もし ◯◯◯ をしたら XXX をする」という組み合わせを設定できるサービスです。この組み合わせをアプレットと呼びます。今回はIFTTTを使って「ベッドから出たらスプレッドシートの値を更新する」みたいなアプレットを作っていきます。

以降、長々と書いてますが、まとめると「Withings Sleepはいいぞ」です。

「寝てる」のセンサー

Withings Sleep

Withings Sleepというセンサー。Amazonで13,000円ぐらいで購入。睡眠のトラッキングだけでなく、就寝/起床のタイミングでIFTTTと連携できる優れもの。睡眠をスコアにしてくれるだけでも嬉しいけれど、外部連携ができると夢が広がる。

https://www.withings.com/jp/ja/sleep

「寝てる」の状態管理

スプレッドシートのスクリーンショット

「寝てる」の状態はスプレッドシートで設定。ついでに、有休や外泊時にスクリプトを無効にするためのフラグも設定しておく。

IFTTTでWithings Sleepを連携

あとはIFTTTとWithings Sleepを連携して、就寝したら1、起床したら0に設定するアプレットを作って状態管理は完了。

IFTTTでWebhooksを設定

あとでIFTTTのWebhooksをトリガーにしてVoIP Callsを実行するので、事前にアプレットを作成しておく。Webhookのイベントを作成すると、こんな感じのURLが発行されます。

https://maker.ifttt.com/trigger/event-name/with/key/xxxxxxxxxx

「起こす」のスクリプト

Google Apps Script(GAS)で、始業直前に寝てたら起こしてもらうスクリプトを書く。祝日は、CalendarApp日本の祝日を取得して判定。ここらへんをサクッとできるのがGASのいいところ。あと、いつのまにかV8 runtimeで動くようになってた。

const SPREADSHEET_ID = 'xxxxxxxxxx'
const SHEET_NAME = 'State'
const ACTIVE_CELL = 'B1'
const SLEEPING_CELL = 'B2'

const HOLIDAY_CALENDAR_ID = 'ja.japanese#holiday@group.v.calendar.google.com'
const IFTTT_WEBHOOK_URL = 'xxxxxxxxxx'

function wakeUp() {
  const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME)
  const isActive = sheet.getRange(ACTIVE_CELL).getValue() === '1'
  const isSleeping = sheet.getRange(SLEEPING_CELL).getValue() === '1'

  if (isActive && isSleeping && isWeekday()) {
    UrlFetchApp.fetch(IFTTT_WEBHOOK_URL, { method: 'post' })
  }
}

function isWeekday() {
  const today = new Date()
  const dayOfWeek = today.getDay()

  if (dayOfWeek === 0 || dayOfWeek === 6) {
    return false
  }

  const calendar = CalendarApp.getCalendarById(HOLIDAY_CALENDAR_ID)
  const events = calendar.getEventsForDay(today)

  if (events.length) {
    return false
  }

  return true
}

カレンダーと同期して、長期休暇・有休・外泊あたりも考慮できたら理想なのだけど、そこまでやる気は起きなかったので運用でカバーする。自分用の休日カレンダーを作成しても、そのカレンダーの運用が発生するので、どっちみち面倒くさい。

GASでは、毎日10:50という細かい単位でトリガーを設定できないので、下記の記事を参考に力技で乗り切った。ざっくりいうと、10:50にトリガーを設定する関数を作って、それを毎日「9:00〜10:00」のどこかで実行する形。トリガーを作成するトリガーを設定するあたり、ハック感が強い。日時の処理をする際は、appsscript.jsonでタイムゾーンの設定を忘れずに。

https://qiita.com/sumi-engraphia/items/465dd027e17f44da4d6a

動作確認

朝、ベッドで待っていると、無事にIFTTTから着信。応答すると「逃げて...逃げて...逃げてえええええ」と自動音声で喋ってもらう設定にしたので、狂気じみた恐ろしさとともに、途方もない虚しさに襲われた。1分のズレは愛嬌。

IFTTTから電話
寝坊したらIFTTTから着信がある世界

ソース

https://github.com/nishinoshake/wake-me-up