2021年8月31日火曜日

卒論に向けて

学会の詳細抄録が完成し、一息つきました。実証実験も順調に進み、あとは定量評価に向けてデータを蓄積し、実証実験で出てきた課題を解決してシステムの改善をしていくばかりとなりました。

それと並行して卒業論文の準備を進めていきたいと思います。まずは先行研究の調査です。システム開発を開始する前に先行研究の論文は読みましたが、読みっぱなしでまとめてきませんでした。しかし、卒論では先行研究について関連する研究の要約と今回の研究との違いについて触れなくてはなりません。

そこで、次回から先行研究の論文を読んでスライド5枚程度にまとめ(緒論、方法、結果、考察、結論)10分ほどの発表をしてはどうでしょうか。

今回の研究のコンセプトに「家族健康記録(FHR)」があります。そこで、家族で高齢者を見守るというコンセプトの研究について調べてはどうでしょうか。例えば、「第四次産業革命時代におけるヘルスケアサービス分野のデジタルトランスフォーメーション等に関する調査研究」なんかどうでしょうか。

また、スマートデバイスで高齢者のバイタルをモニタリングする試みとしてスマートウォッチによる心電図の計測が最近話題を集めています。先進的な取り組みとして調べておくとよいかもしれません。例えば「腕時計型脈波モニタリングデバイスによる心房細動の検出の妥当性に関する研究」というのがあります。

これは、研究ではありませんがタカラトミーという玩具メーカーから「あみちゃん」という高齢者をターゲットとしたAI人形が出ています。モニタリングではありませんが、スマートスピーカーのチャットボットと通じるところがあり、将来的にはこうしたAI人形が高齢者の健康管理のユーザーインターフェースになるのではないかと思います。そこで、このAI人形について調べてみるのも面白いかもしれません。

2021年8月28日土曜日

血圧の記録にトラブルが発生!

8/24のGoogle Home班の報告にある血圧記録のトラブルについて原因を究明して解決したので報告します。

【現象】

8/24以降に入力した血圧データが壊れている。最初は収縮期血圧のみが壊れていたが、その後確認すると拡張期血圧も壊れている。

薬シェア健康記録のスプレッドシート「血圧」に記録されたデータが下記のようになっている(血圧の数値が入るべきところが Ljava.lang.Object になっている)。

2021/08/27 20:04:14,[Ljava.lang.Object;@2570d431,[Ljava.lang.Object;@3e48722a

【原因調査】

Action consoleでテストしてREQUESTデータを入手した(下記)。

{
  "responseId": "17678248-26ed-4c5c-a581-65b716413a8f-b9889856",
  "queryResult": {
    "queryText": "上が129で、下が70です",
    "parameters": {
      "systole": [
        129
      ],
      "diastolic": [
        70
      ],
      "ketsuatsu": [
        "最高血圧",
        "最低血圧"
      ]
    },
    "allRequiredParamsPresent": true,
    "fulfillmentMessages": [
      {
        "text": {
          "text": [
            ""
          ]
        }
      }
    ],
    "outputContexts": [
      {
        "name": "projects/kusuri-141ad/agent/sessions/ABwppHGn1M9qnMcRD7Nut4wAt7mBfE0xTyUfQAHnGuhxNzWnq5nemI-Hb1w8H9PwoR0SK9SvaUIc5fFP/contexts/actions_capability_media_response_audio",
        "parameters": {
          "systole": [
            129
          ],
          "systole.original": [
            "129"
          ],
          "diastolic": [
            70
          ],
          "diastolic.original": [
            "70"
          ],
          "ketsuatsu": [
            "最高血圧",
            "最低血圧"
          ],
          "ketsuatsu.original": [
            "上",
            "下"
          ]
        }
      },
      {
        "name": "projects/kusuri-141ad/agent/sessions/ABwppHGn1M9qnMcRD7Nut4wAt7mBfE0xTyUfQAHnGuhxNzWnq5nemI-Hb1w8H9PwoR0SK9SvaUIc5fFP/contexts/actions_capability_screen_output",
        "parameters": {
          "systole": [
            129
          ],
          "systole.original": [
            "129"
          ],
          "diastolic": [
            70
          ],
          "diastolic.original": [
            "70"
          ],
          "ketsuatsu": [
            "最高血圧",
            "最低血圧"
          ],
          "ketsuatsu.original": [
            "上",
            "下"
          ]
        }
      },
      {
        "name": "projects/kusuri-141ad/agent/sessions/ABwppHGn1M9qnMcRD7Nut4wAt7mBfE0xTyUfQAHnGuhxNzWnq5nemI-Hb1w8H9PwoR0SK9SvaUIc5fFP/contexts/actions_capability_account_linking",
        "parameters": {
          "systole": [
            129
          ],
          "systole.original": [
            "129"
          ],
          "diastolic": [
            70
          ],
          "diastolic.original": [
            "70"
          ],
          "ketsuatsu": [
            "最高血圧",
            "最低血圧"
          ],
          "ketsuatsu.original": [
            "上",
            "下"
          ]
        }
      },
      {
        "name": "projects/kusuri-141ad/agent/sessions/ABwppHGn1M9qnMcRD7Nut4wAt7mBfE0xTyUfQAHnGuhxNzWnq5nemI-Hb1w8H9PwoR0SK9SvaUIc5fFP/contexts/actions_capability_audio_output",
        "parameters": {
          "systole": [
            129
          ],
          "systole.original": [
            "129"
          ],
          "diastolic": [
            70
          ],
          "diastolic.original": [
            "70"
          ],
          "ketsuatsu": [
            "最高血圧",
            "最低血圧"
          ],
          "ketsuatsu.original": [
            "上",
            "下"
          ]
        }
      },
      {
        "name": "projects/kusuri-141ad/agent/sessions/ABwppHGn1M9qnMcRD7Nut4wAt7mBfE0xTyUfQAHnGuhxNzWnq5nemI-Hb1w8H9PwoR0SK9SvaUIc5fFP/contexts/google_assistant_input_type_voice",
        "parameters": {
          "systole": [
            129
          ],
          "systole.original": [
            "129"
          ],
          "diastolic": [
            70
          ],
          "diastolic.original": [
            "70"
          ],
          "ketsuatsu": [
            "最高血圧",
            "最低血圧"
          ],
          "ketsuatsu.original": [
            "上",
            "下"
          ]
        }
      },
      {
        "name": "projects/kusuri-141ad/agent/sessions/ABwppHGn1M9qnMcRD7Nut4wAt7mBfE0xTyUfQAHnGuhxNzWnq5nemI-Hb1w8H9PwoR0SK9SvaUIc5fFP/contexts/__system_counters__",
        "parameters": {
          "no-input": 0,
          "no-match": 0,
          "systole": [
            129
          ],
          "systole.original": [
            "129"
          ],
          "diastolic": [
            70
          ],
          "diastolic.original": [
            "70"
          ],
          "ketsuatsu": [
            "最高血圧",
            "最低血圧"
          ],
          "ketsuatsu.original": [
            "上",
            "下"
          ]
        }
      }
    ],
    "intent": {
      "name": "projects/kusuri-141ad/agent/intents/a27fc1b7-5ddc-40c7-8c38-cbe1c79bafe4",
      "displayName": "ketsuatsu"
    },
    "intentDetectionConfidence": 1,
    "languageCode": "ja"
  },
  "originalDetectIntentRequest": {
    "source": "google",
    "version": "2",
    "payload": {
      "user": {
        "locale": "ja-JP",
        "lastSeen": "2021-08-27T23:23:51Z",
        "userVerificationStatus": "VERIFIED"
      },
      "conversation": {
        "conversationId": "ABwppHGn1M9qnMcRD7Nut4wAt7mBfE0xTyUfQAHnGuhxNzWnq5nemI-Hb1w8H9PwoR0SK9SvaUIc5fFP",
        "type": "ACTIVE",
        "conversationToken": "[]"
      },
      "inputs": [
        {
          "intent": "actions.intent.TEXT",
          "rawInputs": [
            {
              "inputType": "VOICE",
              "query": "上が129で、下が70です"
            }
          ],
          "arguments": [
            {
              "name": "text",
              "rawText": "上が129で、下が70です",
              "textValue": "上が129で、下が70です"
            }
          ]
        }
      ],
      "surface": {
        "capabilities": [
          {
            "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
          },
          {
            "name": "actions.capability.SCREEN_OUTPUT"
          },
          {
            "name": "actions.capability.ACCOUNT_LINKING"
          },
          {
            "name": "actions.capability.AUDIO_OUTPUT"
          }
        ]
      },
      "isInSandbox": true,
      "availableSurfaces": [
        {
          "capabilities": [
            {
              "name": "actions.capability.AUDIO_OUTPUT"
            },
            {
              "name": "actions.capability.SCREEN_OUTPUT"
            },
            {
              "name": "actions.capability.WEB_BROWSER"
            }
          ]
        }
      ],
      "requestType": "SIMULATOR"
    }
  },
  "session": "projects/kusuri-141ad/agent/sessions/ABwppHGn1M9qnMcRD7Nut4wAt7mBfE0xTyUfQAHnGuhxNzWnq5nemI-Hb1w8H9PwoR0SK9SvaUIc5fFP"
}

リスト1.Action consoleで取得したリクエストデータ

これをDialogflowとGoogle Assistantの統合のリスト2と比較すると、outputTexts[0].parameters内のパラメタが、以前はスカラーだったのに対して今はベクトル(配列)になっている(下記へ抜粋)。

"parameters": {
  "systole": [
    129
  ],
  "systole.original": [
    "129"
  ],
  "diastolic": [
    70
  ],
  "diastolic.original": [
    "70"
  ],
  "ketsuatsu": [
    "最高血圧",
    "最低血圧"
  ],
  "ketsuatsu.original": [
    "上",
    "下"
  ]
}

そのため、下記プログラムでスプレッドシートに血圧を書き込むとLjava.lang.Objectとなるようだ。

function handleWebhook(req) {
  const parameters = req.queryResult.outputContexts[0].parameters;
  const intent = req.queryResult.intent;
  var text = '';
  if (req.queryResult.intent.displayName == 'ketsuatsu'){
      text =  '今日の最高血圧' + parameters['systole.original'] + '、最低血圧' + parameters['diastolic.original'] + 'を記録しました。';
      recordBloodPressure(parameters['systole.original'], parameters['diastolic.original']);
  }
  ...(中略)...
  return res;
}

リスト2.関数handleWebhookの抜粋(血圧処理部分)

この中でparameters['systole.original']などが配列になっているために起きるトラブルである。

この問題を解決するために、以下のように、パラメタの配列要素のうち先頭要素のみを取り出すように修正した。

function handleWebhook(req) {
  debug('handleWebhook:req=\n' + JSON.stringify(req, null, ' '));
  const parameters = req.queryResult.outputContexts[0].parameters;
  const intent = req.queryResult.intent;
  var text = '';
  if (req.queryResult.intent.displayName == 'ketsuatsu'){
    const systole = parameters['systole.original'][0]; // ←修正!
    const diastolic = parameters['diastolic.original'][0]; //  ←修正!
    text =  '今日の最高血圧' + systole + '、最低血圧' + diastolic + 'を記録しました。';
    recordBloodPressure(systole, diastolic);
  }
  ...(中略)...
  return res;
}

リスト3.修正したプログラム

すなわち、最高血圧は parameters['systole.original'] を取り出してスプレッドシートへ書き込んでいたが、parameters['systole.original'] は配列になっていたので parameters['systole.original'][0] のように[0]を付けて先頭要素を取り出した。この修正で血圧データが記録されないという問題は解消した。

2021年8月25日水曜日

2021/08/24

【全体】

本日は作成途中の詳細抄録に関するお話をしました。

未完成の部分をゼミメンバーで分担し、作業を行います。

次回のゼミは 27日(金)です。それまでに抄録の8割方完成を目指します。

 

【Google Home班】

今日は、まず#2 脈拍の記録機能 を追加しようとしました。

スピーカーに記録する際は、最高血圧、最低血圧の後に続けて伝えます。

ですが、色々しているうちに最高血圧がスプレッドシートに記録されずLjava.lang.Object;

が表示されます。調べてみてもどこを改善すればいいのか分かりません。

次回はここから進めたいと思います。

2021年8月18日水曜日

2021/08/17

 【Google Home班】

お盆が明けて、久しぶりの活動でした。

今日は、To Doリストの把握をしました。”#4 血圧のグラフを折れ線グラフに”を来週進めていくことにしました。また、140と90に赤い線を引くことも同時に進めていきたいと思います。

また、”#7 血圧の削除時の確認”で削除対象記録の日時・最高血圧・最低血圧を読み上げるようにすることに取り組む予定です。

 

【LINE班】

現在、学会用の詳細抄録を作成中です。

先生によるシステムの検証により、様々な課題も見つかりました。優先順位を決め、1つずつ課題をこなしていきたいです。

2021年8月14日土曜日

TODOリスト(Vol.2)

 TODOリストの第2弾です。今回は、実証実験も始まって具体的な課題が見えてきたました。

#1 音声ヘルプ機能

スピーカに向かって何を言えばよいか戸惑うことがある。そこで、音声ヘルプ機能を作成したらどうか。

#2 脈拍の記録機能

今使っている血圧計は脈拍も測定できる。日々記録する情報は身長よりも脈拍の方が重要度が高いと思われるので、脈拍を記録できる機能を付けたらどうか。

#3 音声入力に要する時間を計測

「OKグーグル、あゆみにつないで」と話しかけてすべての記録が完了するまでの過程をログ(Debug)に書いて、音声入力に要する時間を自動で計測できるようにしたらどうか。

#4 血圧のグラフを折れ線グラフに

現在、血圧のグラフは曲線で補正したグラフになっているが、データ密集点では返って不自然で見にくいグラフになっている。曲線補正はやめて直線で結んではどうか。

図 血圧のグラフ

また、縦軸の目盛りが小さくて見えないので、140と90に赤い線を引いてはどうか?

#5 手入力で薬剤を追加したい

現在、処方情報はQRコードで入力しているが、それに対して薬剤を手入力で追加・修正する手段があるといい。

#6 スマートスピーカ同士の音声通話

Google Duoを使ってスマートスピーカ同士で会話ができないだろうか?

#7 血圧削除時の確認

血圧削除時に削除データを読み上げたらどうか(何も言わずに「削除」となると、何が消されたのか不安になる)。読み上げる項目は入力日時と上下の血圧。

#8 薬の情報

LINEの「薬の情報」で表示されるカルーセルの「バイアスピリン」が川崎病になっている。これは「くすりのしおり」の検索結果の先頭がこれになっているためだと思われる。正しい薬剤情報を出すにはどうすればよいか(何が必要か)を検討してはどうか。

#9 YakuShareクライアント

コントローラ上で稼働しているYakuShareサーバへ各種Webリクエスト(config, reload, help, google-home-notifier)を送るクライアントを作ってはどうか。

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のやり方を真似て作ればよいでしょう。

2021年8月4日水曜日

2021/08/03

  【Google Home班】

前回の問題点を解決しようと試みましたが、原因がわからず、解決できませんでした。

見たいグラフを変更するとき、3回目以降(例:血圧→身長→血圧)から表示が古いものになってしまいます。

利用者は身長・体重はあまり見ないだろうということで、このままでいくことに...。

そろそろ実際にスピーカーで記録していかねば。

 

【LINE班】

作成していた「使い方ガイド」ページの作成を進め、実際に公開してみました。また、LINEのリッチメニューにリンクを張り付けて、スマートフォンでの表示も確認しました。未完成のページも随時更新していきたいです。

来週からは、詳細抄録を中心に進めていきます。

2021年7月30日金曜日

2021/07/27

 【Google Home班】

今日は前回の課題であったグラフ表示画面で、他のデータを見れるようにしました。

血圧から身長・体重のデータは見れるようにできたのですが、身長から血圧・体重、体重から血圧・身長が表示できない状態です。

来週はそこから取り組みたいと思います。

 

【LINE班・IFTTT班】

 ①お薬の時間を早める機能を、一部変更しました。

・服薬イベントが時間外の時に早めることが可能になりました。

・「お薬〇分早めて」 の話し方に変更しました。

今までは、服薬イベントの時間を変える際(遅くする場合も含む)は「イベントの時間内」でしか変更することが出来ませんでした。ですが「服薬時間を早めたい」ときは、イベントが現在時刻よりも後の方にあるパターンの方が多いと考えました。そこでプログラムを変更し、現在時刻よりも遅いイベントを取得して時間を変更することが出来るようにしました。

②「使い方ガイド」の作成

「Googleサイト」を用いて使い方を閲覧できるWebサイトを作成中です。まだまだ完成には程遠いので、引き続き頑張っていきたいと思います。

2021年7月24日土曜日

2021/07/20

 【Google Home班】

今日は、ToDoリスト#4.グラフのボタン作成に取り掛かりました。

1週間、1か月、半年の記録の表示ボタンに加えて血圧、身長、体重の記録の表示をグラフ表示画面で切り替えるようにします。

 

【LINE班・IFTTT班】

 ①薬の時間を遅くする時の、スピーカーへのしゃべり方を変更しました。

 以前は「待って、ちょっと待って、後で」と言うと時間が10分延期されるという仕組みでしたが、何回か実践を重ねてみて、少々言いにくい印象を受けました。そのため、「『お薬』待って、『お薬』ちょっと待って、『お薬』あとで」の言葉に変更することに。この方法で、また何回か検証をしてみたいと思います。

 また、各機能を用いるためにはどうしゃべれば良いのか、全てを覚えるのは難しいという観点から、スピーカーに使い方を聞くことが出来る機能を作ればどうか、という案が出ました。こちらも頭にいれつつ、可能であれば実現したいと思います。

②プログラムの一部編集

 お薬を飲んでスピーカーに報告した際のプログラムを、一部変更しました。時間外にお薬服用の報告をした際にLINEメッセージが来ない点を改善し、正常に機能が動くようにしました。


2021年7月19日月曜日

ToDoリスト(Vol.1)

 春学期もそろそろ終わりを迎え,システム開発も峠を越しました。そこで,やるべきリスト(ToDoリスト)を作ってみました。今まで分かっている問題点,中間報告で指摘されたこと,あったらいいなという機能,論文作成に向けての文献調査,思いつくままですがリストを作成してみました。

#1.服薬督促に応答がない場合の対応

中間報告会で指摘された件です。スピーカーが服薬を督促しても高齢者から応答がなかった場合どうするのか?・・・現実的には電話をかけるだろうと思われます。そこで,緊急連絡先をシステムに登録しておいて,LINE公式アカウントから「お薬を飲むように5回催促しましたが応答がありません。」というメッセージを出力する際,単なるテキストメッセージではなく,ボタンにして,事前に登録した緊急連絡先を表示し,タップするとそこに電話がかかる仕組みを作ってはどうだろうか?

#2.ユースケース図(第2版)

システム開発に先立って,4月頃,必要な機能を洗い出してユースケース図を作成した。しかし,こうしてシステムがほぼ完成した段階であのユースケース図を振り返ってどうだろうか?おそらく,実際に作ると当初のユースケースとはかなり違ってきているのではないだろうか?そこで,ユースケース図を改訂して,現実に即したものを作成し,第2版として残してはどうか。この作業を通じて,実現している機能の整理をしておきたい。きっとマニュアル作成にも役立つだろう。もちろん論文作成にも。[Googleドライブ > ゼミ2020 > 4限輪読 > 11 システム設計 > ユースケース分析 > 作成したユースケース図 > 第2版]

#3.新機能のアイデア集

今後の検証活動を通じて「こんな機能があったらいいな」と思えるような機能があれば,それをユースケース図にして,論文の「今後の課題」のネタや後輩たちに引き継ぐテーマとしてアイデアの蓄積をしてはどうだろう?

#4.グラフのボタン作成

今,グラフの時間軸のスケール(1週間,1か月,半年)の切り替えをボタンでやっているが,それに加えて「血圧」「身長」「体重」のグラフ表示もボタンでやれば便利じゃないか?いちいちLINE公式アカウントに戻ってリッチメニューをタップというのはどうもかったるい・・・。

#5.文献調査

今回開発したシステムのコンセプトは「ファミリー健康記録」(FHR)である。つまり,独居高齢者見守りシステムと個人健康記録(PHR)の融合を図ったシステムである。これは今までにない概念で,その新規性を論文で主張するためには先行研究から高齢者見守りシステムや高齢者を対象とする服薬管理システムを調べ,それらとの違いを明確に論じなければならない。そこで,該当する論文を収集して少しずつ読み進め,読後サマリーをブログに掲載してはどうか?

これまで収集した文献は以下のフォルダにある。

#6.検証作業

前回のブログに書いた検証作業を実践する。Amazonで購入した血圧手帳に日々の検証活動を記録する。正常に入力できたとか,上の血圧が240と誤認識されたとか,「OKグーグル・・・につないで」と声掛けしたら「わかりません」と返されたとか,そんな記録を手帳に付けて,あとで集計して誤認識率など定量的なデータを取得する。入力に要した時間や誤認識した場合の訂正して正しい入力を終えるまでの時間なども計測できればなお良い。

#7.セキュリティ

公式LINEアカウントはQRコードを読み込めば誰でも友達追加できる。ということは,このシステムは個人情報漏えいに対して全くの無防備である。そこで,スプレッドシートに利用が許可されたUIDリストを登録し,そこに無いUIDのユーザがアクセスしてきたら,拒絶できるようにUIDフィルタリング機能を実装してはどうか?

#8.ログ

作成したWebAPIにログを出力する機能を実装し,利用状況のログを書き込み,入力時間や誤認識データの検知など,計測を自動化してはどうか。また,定期的にログを切り替えて,ログのバックアップを取るためのスケジュール機能をGASで実装する。そうすると,使っているうちに知らぬ間に実験データが蓄積されることになる。

#9.受診予定アラート

日々薬を服用していけば,やがて薬はなくなり,次の受診を考えなければいけない。システムは薬の残量を把握できるはずだから,「あと一週間で薬はなくなります。受診を考えてはどうでしょうか」といったアラートをスピーカーが喋るとありがたくないか?

2021年7月17日土曜日

検証の重要性

 主要なシステム開発はだいたい終わり,あとはデザインの修正や優先度の低い機能の実装,そしてヘルプ機能の実現などを残すだけとなりました。

そこで,これから力を入れて行かないといけないのは検証です。機能は作ったけれど,動かない,あるいは動いても使い勝手が悪くてはそのうち利用されなくなるのは明らかです。今回の目玉はスマートスピーカーを利用した音声入力です。これは複雑極まりない多機能スマホアプリに比べたら,お年寄りでも簡単に操作できると考えたから導入したものです。でも,本当にそうでしょうか?

音声の方が操作しやすいというのは我々の思い込みかもしれません。思い込みかそうではないかは実際にテストをしてみなければわかりません。いきなりお年寄りにスマートスピーカーの相手を頼むのは無謀です。まずは,開発した我々がテストすべきです。毎日,血圧を測定して「OKグーグル,***につないで」と呼びかけます。どのくらいの割合で応答するでしょうか?

応答したら「血圧」を記録することを告げ,上下の血圧を伝えます。「OKグーグル」と話しかけて,血圧の入力を終えるまでに何秒くらいかかるかを計測します。スマートスピーカーが音声認識に失敗したら,たった今入力した記録を取り消して,もう一度入力しなければいけません。これにはどのくらいの時間がかかるでしょうか。もしかしたら「かったるくてやってられない」と思うかもしれませんね。そうした場合は,どうやったらもっと簡単に入力できるようになるか工夫が必要かもしれません。

このようにやるべきことはいくらでもあります。特に高齢者が操作する部分は入念に検証する必要があります。学会で報告する際もそれがメインになるでしょう。どのくらいの精度で認識するのか,どのくらいの時間をかけて入力するのか,もし,認識間違いをしたらどのくらいの時間で修正できるのか,具体的な数値を示して報告しなければなりません。

これをやる上でチェックシートを作りましょう(Amazonに血圧手帳が出品されていたので4冊購入しました!)。毎日,スマートスピーカーに向かってテストし,その結果を記録するチェックシートです。認識の成否だけでなく入力に要した時間,認識に失敗した場合,修正に要した時間,そういったものを記録するためのシートです。

2021年7月13日火曜日

2021/07/13

 【Google Home班】

引き続きデザイン・レイアウトに取り組みました。

スマートフォンの画面なサイズに合わせてボタンを表示させるところで苦戦中です。

調べて頑張りたいと思います。

 

【LINE班・IFTTT班】

 ①LINE公式アカウントのリッチメニュー「お薬飲んだよ」が完成

 メニューをタップするだけで、現在時刻のイベントを取得し、お薬を飲んだことが登録できるようになりました。

②スピーカーでの服薬登録を「お薬飲んだよ」だけで可能に

 以前は服薬のタイミング(朝、昼、夜、就寝前)もスピーカーへ伝えていたが、それをなくし、「お薬飲んだよ」だけで読み取れるようにしました。非常にしゃべりやすくなったと思います。

次回は、リッチメニュー「使い方ガイド」の作成を進めていきたいです。


2021年7月9日金曜日

中間報告会

家族健康記録「薬シェア」の開発と評価

中間報告会が開催され,現時点までに開発されたシステムと今後の課題を報告しました。ここをクリックすると発表内容と質疑の動画を視聴できます(ただし,認証が必要)。

指摘事項は次の通りです。

  1. 速すぎて分からなかった
  2. システム全体の構成図を示してほしい

いずれも研究内容自体ではなく発表の仕方の指摘でした。この指摘を受けて「ああ,なるほどな」と思うと同時に,わかりやすい説明をすることはとても難しいことなんだなと改めて実感しました。

今回の発表は「木を見て森を見ず」的な側面があったのかもしれません。学会や本番では,まず,システムの全体像を示して,それを踏まえたうえで各サブシステムや機能の説明をすることを心掛けたいものです。