問題とその解決策
予定を変更する
WebAPI (A2) の修正
実験2日目のブログで「予定を変更する」機能があるといいのにと書いたが、それを実装した。その方法はGoogle Homeから服用のお知らせがあったのち「後でお薬飲む」と伝えると、Googleカレンダーの開始日・終了日を指定した時間(今回は10分間)だけ遅らせるというものである。
修正対象のプログラムは、WebAPI (A2) である。まず、HTTPリクエストのエンドポイントとなる関数 doPost は以下のように修正する。
/** * IFTTTからのリクエストに応じてGoogleカレンダーを服用済みに更新する * @param {Object} e POSTメソッドで送られてくるデータ * delay: 10 (開始を10分間遅らせる) * timing: [朝|昼|夜|就寝前] * */ function doPost(e) { var params = JSON.parse(e.postData.getDataAsString()); // ※ if (params.timing) { //カレンダーのタイトルと色を変える var timing = params.timing; // => [朝|昼|夜|就寝前]が取れる NotifyNotTaking(timing); } else if (params.delay) { //開始時刻を遅らせる var delay = parseInt(params.delay); // => 遅らせる時間[分] delayStartTime(delay); } var out = ContentService.createTextOutput(); //Mime TypeをJSONに設定 out.setMimeType(ContentService.MimeType.JSON); //JSONテキストをセットする result = { status: 'OK' }; out.setContent(JSON.stringify(result)); return out; }
リスト1.WebAPI (A2) のエントリポイント
パラメータにtimingがなくdelayがある場合、リスト2に示す関数delayStartTimeを呼び出す。
/** * 現在時刻の予定を指定した時間だけ遅らせる * @param {Integer} delay 遅らせる時間(分) */ function delayStartTime(delay) { debug('delayStartTime:delay=' + delay); // 当日の服薬予定(未)をすべて取得する var events = CalendarApp.getDefaultCalendar().getEventsForDay( new Date(), {search: '(未)'} ); // 取得した予定から現在時刻が開始~終了時刻に含まれる予定を探してdelay(分)だけ遅らせる var current_time = new Date(); events.forEach(function(event,i,array){ var start_time = event.getStartTime(); var end_time = event.getEndTime(); if (start_time <= current_time && current_time <= end_time) { event.setTime(delayTime(start_time, delay), delayTime(end_time, delay)); } }); } // 引数に指定した日時target_timeをdelay[分]だけ遅らせる function delayTime(target_time, delay){ var delay_time = new Date(target_time.getYear(), target_time.getMonth(), target_time.getDate(), target_time.getHours(), target_time.getMinutes() + delay, target_time.getSeconds() ); return delay_time; }
リスト2.予定時刻を遅らせる関数delayStartTime
当日の予定から'(未)'を含む予定を探し、delayだけ開始・終了時刻を遅らせる。
IFTTTの登録
次に、「後でお薬飲む」とスピーカーに向かって話すと「分かりました。予定を10分遅らせます。」と返答して、Webhooks機能を用いて WebAPI (A3) を呼び出すIFTTTのアクティビティを登録する。
トリガーはGoogle Assistantで、下記のような設定にする。
What do you want to say? -> 後でお薬飲む What's another way to say it? (optional) -> 後で飲む And another way? (optional) -> 少し待って What do you want the Assistant to say in response? -> 分かりました。予定を10分遅らせます。 Language -> Japanese
リスト3.Trigger
続いて、下記はWeb requestの設定である。
URL -> https://script.google.com/macros/s/AKfy..............................nIbMw/exec Method -> POST Content Type (optional) -> application/json Body (optional) -> {"delay": 10}
リスト4.Web request
ここで、URLは WebAPI (A3) のURLである。
ベアボーンサーバ(発話依頼プログラム pill-reminder.js)
ベアボーンサーバ上で稼働する発話依頼プログラム pill-reminder.js は、起動時に読み込んだGoogleカレンダーの予定通りに服薬通知を発話するようプログラムされている。
しかし、服用開始時刻を変更できるようにしたため、それに同期して発話の時刻を変更しなければならない。そこで、予定の開始時間になったら呼び出される関数dosing_remindを以下のように修正した。
function dosing_remind(speech, counter, id) { counter++; putLog('"' + speech + '"の発話時刻になりました(' + counter + '回目), id=' + id); if (counter > 10) { putLog('催促回数が上限を超えました'); return; } // WebAPI A3 をid指定で叩いて服用済みかどうかを確認する webclient.get( { url: data + "?id=" + id + "&num_reminder=" + counter }, function (error, response, body) { if(!error) { var json = JSON.parse(body); putLog('当該服薬スケジュール(id=' + id + '):\n' + JSON.stringify(json, null, " ")); if(json.taiking_status == "0" && !isOver(json)){ message = speech + 'を飲んでください'; putLog(message + '(' + counter + '回目)'); // まだ開始時刻(json.drug_notifies[0].startTime)になっていなければ、開始時刻にタイマーを設定する var startTime = new Date(json.drug_notifies[0].startTime); var now = new Date(); var df = startTime - now; if (df > 0) { putLog('予定が変更されています。この予定は' + parseInt(df / 60000) + '分後に発話されます。'); setTimeout(dosing_remind, df, speech, 0, id);//繰り返し } else { // Google homeへ発話依頼(開始時刻を過ぎている場合) setTimeout(dosing_remind, C_INTERVAL, speech, counter, id);//繰り返し webclient.get({ url: url, qs: { text: message, } }, function (error, response, body) { if(!error) { putLog('発話依頼成功:' + body); } else { putLog('発話依頼失敗:' + error); } }); } } else { putLog('済になったか催促上限オーバーになったので催促を終了します。'); } } else { putLog('WebAPI A3 呼び出しに失敗しました:' + error + '(id=' + id + ')'); } } ); }
リスト5.予定の開始時間になったら呼び出される関数dosing_remind
0 件のコメント:
コメントを投稿