2021年8月14日土曜日

8月10日から実証実験始めました

 2021年8月10日より、コントローラを我が家に設置し、実証実験を始めました。実証実験の記録はGoogleドライブ内に作った専用フォルダ内にあるExcelファイル「実証実験.xlsx」に記録していってます。

また、このフォルダには次のフォルダを作成し、様々な記録を保存しています。

Debug

これは、GASが出力したログのバックアップです。ログはGoogleドキュメントDebugに出力していますが、定期的にバックアップを取って切り詰めないと(ログを削除しないと)膨れ上がって遅くなります。バックアップを取った日付をファイル名としてこのフォルダにバックアップファイルを溜めています。

YakuShare

これは、コントローラ側で動くNodejsのサーバプロセス YakuShare.js のログや、障害記録を保存しているフォルダです。現在はログは手作業で保存しています。これも日付をファイル名にしています。


障害事例

ここで、今日(2021/8/14)発生した障害とその対応を書き記しておきます。

8/14に発生した障害とその対応

6:30にスピーカが朝食後の薬の服用を促したが、他の部屋にいて気付かず、6:45の4回目の督促後の6:46に「OKグーグル、お薬あとで」と話しかけた。この段階で、服薬イベントの開始時刻が6:30から6:40に書き換わったが、何事もなかったかのように約5分後の6:50に5回目の督促が発話された。その後、カレンダーの予定は赤色(未)から黄色(応答無)に変わった。

この不可解な動きの原因は、最初にスピーカが服用を促してから10分を経過したあとに「あとで」を指示したときのプログラムの挙動にある。常識的にはその時刻から10分後に開始時刻を延期するだろうと考えるが、なぜかプログラムは、開始時刻(つまり6:30)を10分延期してしまった(その結果、開始時刻が6:40と過去の時刻になった)。

そこで、開始時刻を現在時刻から10分後にするために、プログラムを修正した。修正対象のプログラムは「服薬管理システムA2」の関数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();
  for(const event of events){
    //遅らせる時
    if(delay > 0){
      var start_time = event.getStartTime();
      var end_time = event.getEndTime();
      if (start_time <= current_time && current_time <= end_time) {
        // 2021.8.14 by M.Tanaka
        delay += getDiffSec(start_time, current_time) / 60;
        event.setTime(delayTime(start_time, delay), 
          delayTime(end_time, delay));
        break;
      }
    //早める時
    }else if(delay < 0){
      var start_time = event.getStartTime();
      var end_time = event.getEndTime();
      if (start_time >= current_time) {
        event.setTime(delayTime(start_time, delay), 
          delayTime(end_time, delay));
        break;
      }
    }
  }
}

/**
 * 2つの時間の差を取得する(秒単位)
 * 2021.8.14 by M.Tanaka
 */
function getDiffSec(date1, date2) {
  const diff = date2.getTime() - date1.getTime();
  return diff / 1000;
}

リスト1 修正した服薬管理システムA2

修正内容は関数delayStartTimeの「遅らせる時」の処理で、遅延時間deleyに開始時刻から現在時刻の時間差を足している箇所である。

delay += getDiffSec(start_time, current_time) / 60;

これによって、現在時刻の10分後に開始時刻が設定される。

プログラムを修正して新規デプロイして、新しいWebURLをIFTTTの「お薬待って」のWebhook URLに上書きした。

【補足】2021.8.15追記

翌日(8/15)、テストがてらに同じことをやってみた(4回目の督促後に「あとで」と話しかけた)。その結果、カレンダーの服薬予定は現在時刻の10分後に無事変更されたが、5回目の督促後に予定が赤色(未)から黄色(応答無)になった。

プログラムを確認すると、コントローラ側のプログラムYakuShare.jsでは予定延期時にカウンタをリセットしておらず、そのため、督促が5回目に達すると(未)から(応答無)に変更されていた。

そこで、YakuShare.jsの456行目あたりにカウンタをリセットするコードを追加した。

counter = 1;

リスト2 カウンタのリセット(YakuShare.js)

この修正を反映させるためにYakuShare.jsを再起動した。なお、YakuShare.jsはNodejsのforeverというツールで常駐化させているので、foreverコマンドを使って一旦停止し、再度、開始する必要がある。

また、YakuShare.jsはngrokを使って公開URLを作成しているので、起動時に配慮すべき事項がある。そのあたりに関しては別途マニュアルを作成したので注意されたい。


その他の問題点

8/10から実証実験を始めていろいろな問題に遭遇しました。ここでは、その主だったものを書き記しておきます。

①「あゆみ」に繋がらない!(8/10)

血圧を記録しようと「OKグーグル、あゆみにつないで」と話しかけると「わかりません」とスピーカーが応答しました。これはこれまでも何度も経験していることです。しょっちゅうというわけではありませんが、数週間に一度くらい遭遇します。原因はわかっていないのですが、ネットで検索すると同じような現象に出くわした人がいて、Action on googleでDisplay nameをリセット(削除してからまた設定)すると復旧することがわかりました。

Display nameというのはAction Consoleの [Develop] -> [Invocation] -> [Japanese] で設定する項目で、「OKグーグル〇〇につないで」というときの「〇〇」に該当する呼び出し名のことです。数週間に一度、これが認識されなくなるのです。

②最低血圧を誤認識!(8/11)

最低血圧を尋ねられて「59」と言ったつもりが「19」と誤認識されました。データの削除のやり方がわからず、スプレッドシートを手修正しました。あとで、DialogflowのIntentsを確認すると、「血圧を削除」と言えばよいことがわかったのですが、後の祭りです。利用者にはDialogflowを見ることはできないので、ヘルプが欲しいところです。

例えば「助けて」と言えば、音声ガイドで操作方法(話しかけ方)を教えてもらうと嬉しいです。IntentsにHelpを追加し、user expressionに「助けて」「ヘルプ」「教えて」などを追加しておくのはどうだろうか。そして、このIntentsが呼び出されたらText Responseに操作方法を設定しておけばよい。

③「血圧」と言ったのに!(8/12, 8/13)

あゆみにつないで「血圧」と言ったのに、聞き取ってもらえず言い直すことがありました。8/11は1回言い直しただけですが、8/12は2回も言い直しました。8/13はこれだけでなく最低血圧77を「7」と誤認識されたり、「血圧を消して」と言うと「応答がありません」と強制終了されたり、最終的に入力を終えるまでに数分間を要しました。こうなるともううんざりです。

④「お薬10分早く」と言ったのに!(8/13)

食事が早く終わったので、予定の時刻(6:30)になる前に「お薬10分早く」と言うと、「かしこまりました。10分早くします」と応答して、カレンダーも6:20開始に変更されたのに、6:20になっても「お薬飲んで」の督促がありません。

それもそのはず、コントローラ側のプログラムは毎朝午前1時にその日の予定を読み込んでタイマをセットします。したがって、それ以降に変更された予定には対応していません。これに対応するにはもう一度強制的にその日の予定を読み込ませる必要があります。それを行うのがreloadです。reloadを行うにはYakuShareサーバにGETメソッドで次のようなWebリクエストを行う必要があります。

https://XXXXXXXX.ngrok.io/reload

リスト3 reloadリクエスト

ここで、「XXXXXXXX.ngrok.io」はngrokが払い出したURLで、スプレッドシートpill-reminderに書き込まれています。あるいは、ngrokのEndpointsのStatusでも確認できます。

いずれにしても、予定を変更したら必ずこのWebリクエストをしなければなりません。今回は、リスト1の「早める時」の処理にこれを加える必要があります。

Webリクエストは関数GOOGLE_HOME_notifyのやり方を真似て作ればよいでしょう。

0 件のコメント:

コメントを投稿