Google Fit: フィットネスデータ, 歩数取得
Google Fit: フィットネスデータ, 歩数取得 (Google Fit: FitnessData, Get Steps)
Google Fit 内の歩数データを取得します。任意期間における歩数(集計値)を取得します。総移動距離を取得することも可能です。たとえば、介護職員や配達員の勤務時間歩数を自動的に取得します。
Configs
  • U: HTTP認証設定を選択してください *
  • A1: 抽出範囲の開始日時をセットしてください (例 “2021-12-31 09:00″) *#{EL}
  • A2: 抽出範囲の終了日時をセットしてください (例 “2021-12-31 17:00″) *#{EL}
  • B1: 歩数データが格納される数値型データを選択してください (更新) *
  • B2: 移動距離データが格納される数値型データを選択してください (更新)
Script (click to open)
// GraalJS Script (engine type: 2)

//////// START "main()" /////////////////////////////////////////////////////////////////

main();
function main(){ 

//// == Config Retrieving / 工程コンフィグの参照 ==
const strAuthzSetting     = configs.get      ( "AuthzConfU" );   /// REQUIRED
  engine.log( " AutomatedTask Config: Authz Setting: " + strAuthzSetting );
const strDurationStart    = configs.get      ( "StrConfA1" );    /// REQUIRED
  if( strDurationStart  === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A1: DurationStart} is empty \n" );
  }
const strDurationEnd      = configs.get      ( "StrConfA2" );    /// REQUIRED
  if( strDurationEnd    === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A2: DurationEnd} is empty \n" );
  }
const numPocketStep       = configs.getObject( "SelectConfB1" ); /// REQUIRED
const numPocketDistance   = configs.getObject( "SelectConfB2" ); // NotRequired


//// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)


//// == Calculating / 演算 ==
/// Times in milliseconds since epoch
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime
let dateDurationStart = toJsDate( strDurationStart );
let numDurationStart  = dateDurationStart.getTime();
let dateDurationEnd   = toJsDate( strDurationEnd );
let numDurationEnd    = dateDurationEnd.getTime();

/// Get StepCounts (and Distance)
/// Google Fit API
/// https://developers.google.com/fit/rest/v1/reference/users/dataset/aggregate
let request1Obj = {};
    request1Obj.aggregateBy = [];
    request1Obj.aggregateBy[0] = {};
    request1Obj.aggregateBy[0].dataTypeName = "com.google.step_count.delta";
    if( numPocketDistance !== null ){
      request1Obj.aggregateBy[1] = {};
      request1Obj.aggregateBy[1].dataTypeName = "com.google.distance.delta";
    }
    request1Obj.endTimeMillis   = numDurationEnd;
    request1Obj.startTimeMillis = numDurationStart;
    request1Obj.bucketByTime = {};
    request1Obj.bucketByTime.durationMillis = numDurationEnd - numDurationStart;
let request1Uri = "https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate";
let request1    = httpClient.begin(); // HttpRequestWrapper
    request1    = request1.authSetting( strAuthzSetting ); // with "Authorization: Bearer XX"
    // https://questetra.zendesk.com/hc/en-us/articles/360024574471-R2300#HttpRequestWrapper
    request1    = request1.body( JSON.stringify( request1Obj ), "application/json" );
// request1, try
const response1     = request1.post( request1Uri ); // HttpResponseWrapper
engine.log( " AutomatedTask ApiRequest1 Start: " + request1Uri );
const response1Code = response1.getStatusCode() + "";
const response1Body = response1.getResponseAsString() + "";
engine.log( " AutomatedTask ApiResponse Status: " + response1Code );
if( response1Code !== "200"){
  throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
                    response1Code + "\n" + response1Body + "\n" );
}
// response1, parse
/* 
engine.log( response1Body ); // debug
{
  "bucket": [
    {
      "startTimeMillis": "1621436400000",
      "endTimeMillis": "1621522800000",
      "dataset": [
        {
          "dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:aggregated",
          "point": [
            {
              "startTimeNanos": "1621456113977325463",
              "endTimeNanos": "1621488145246312108",
              "dataTypeName": "com.google.step_count.delta",
              "originDataSourceId": "raw:com.google.step_count.cumulative:Sony:SO-41A:cdfccXXXXX8b674Y:pedometer  Non-wakeup",
              "value": [
                {
                  "intVal": 9987,
                  "mapVal": []
                }
              ]
            }
          ]
        },
        {
          "dataSourceId": "derived:com.google.distance.delta:com.google.android.gms:aggregated",
          "point": [
            {
              "startTimeNanos": "1621456169872000000",
              "endTimeNanos": "1621488145246312108",
              "dataTypeName": "com.google.distance.delta",
              "originDataSourceId": "derived:com.google.distance.delta:com.google.android.gms:merge_distance_delta",
              "value": [
                {
                  "fpVal": 8987.1162967085838,
                  "mapVal": []
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

== if no record ==
{
  "bucket": [
    {
      "startTimeMillis": "1621782000000",
      "endTimeMillis": "1621782010000",
      "dataset": [
        {
          "dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:aggregated",
          "point": []
        },
        {
          "dataSourceId": "derived:com.google.distance.delta:com.google.android.gms:aggregated",
          "point": []
        }
      ]
    }
  ]
}
*/
const response1Obj = JSON.parse( response1Body );
let   numStep = 0;
if( response1Obj.bucket[0].dataset[0].point.length === 0 ){
  engine.log( " AutomatedTask RuntimeWarning:" +
              " No Record of StepCount (no point in dataset)" );
}else{
      numStep = response1Obj.bucket[0].dataset[0].point[0].value[0].intVal;
}
let   numDistance = 0;
if( numPocketDistance !== null ){
  if( response1Obj.bucket[0].dataset[1].point.length === 0 ){
    engine.log( " AutomatedTask RuntimeWarning:" +
                " No Record of Distance (no point in dataset)" );
  }else{
        numDistance = response1Obj.bucket[0].dataset[1].point[0].value[0].fpVal;
  }
}

//// == Data Updating / ワークフローデータへの代入 ==
engine.setData( numPocketStep,       new java.math.BigDecimal( numStep ) );
if( numPocketDistance !== null ){
  engine.setData( numPocketDistance, new java.math.BigDecimal( numDistance ) );
}

} //////// END "main()" /////////////////////////////////////////////////////////////////


function toJsDate( bpmsDateOrDatetimeStr ){
  // BPMS Date:     "2020-04-01"  (subtype "Y/M" "M/D" "Y", not supported)
  // BPMS Datetime: "2020-04-01 23:59"
  let year       = 0;
  let monthIndex = 0;
  let day        = 0;
  let hours      = 0;
  let minutes    = 0;

  //  The ECMA/JavaScript Date object has a large number of methods.
  // "Date.parse" is danger (strongly discouraged)
  // - new Date("2014-11-10") // Mon Nov 10 2014 09:00:00 GMT+0900 (JST)
  // - new Date(2014, 10, 10) // Mon Nov 10 2014 00:00:00 GMT+0900 (JST)
  let arrDatetime = bpmsDateOrDatetimeStr.split(" ");
  if( arrDatetime.length === 1 ){
    let arrDateParts = arrDatetime[0].split("-");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
  }
  if( arrDatetime.length === 2 ){
    let arrDateParts = arrDatetime[0].split("-");
    let arrTimeParts = arrDatetime[1].split(":");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
    hours      = parseInt(arrTimeParts[0], 10);
    minutes    = parseInt(arrTimeParts[1], 10);
  }
  return new Date( year, monthIndex, day, hours, minutes );
}


/*
Notes:
- Used in the daily reporting process of caregiver, deliveryman, etc. GoogleFitSteps
    - It is possible to count periods that exceed 24 hours.
    - Long-term like over 2 months will result in an "aggregate duration too large" error.
- Only the data of the person who permitted API communication (OAuth Authz) can be acquired.
    - That is, only one person's data can be acquired for each automated task.
    - As of 2021-05, data cannot be acquired with any user ID (userId). 
- The unit of travel distance data is meters.
    - Variable decimal numbers follow the numeric data definition of the workflow app.
- If the datetime (DurationStart and DurationEnd) are set in date format, considered as "00:00".
    - eg: "2021-12-31" to "2021-12-31 00:00"

Notes-ja:
- 介護職員や配達員などが勤務時間内の歩数や距離を報告する業務プロセス等で利用します。 GoogleFitSteps
    - 24時間を超えるような時間範囲での集計も可能です。
    - ただし、2カ月を超えるような長期間の集計は "aggregate duration too large" エラーとなります。
- API通信を許可(OAuth認可)した本人のデータしか取得できません。 "HTTP認証設定"
    - すなわち、自動処理工程1つにつき、1人のデータしか取得できません。
    - 2021-05現在、任意のユーザID(userId)でのデータ取得はできません。
- 移動距離データの単位はメートルです。
    - 小数点以下有効数字(切り捨て位置)は、ワークフローアプリの数値型データ定義に従います。
- 日時(範囲開始と範囲終了)が日付フォーマットで設定された場合、"00:00" とみなされます。
    - 例: "2021-12-31" → "2021-12-31 00:00"

APPENDIX-en
- For usage of Google Fit itself, refer to the Google Fit documents.
    - Track your fitness activity
        - https://support.google.com/fit/answer/6075066?hl=en
    - Find your activity
        - https://support.google.com/fit/answer/6090183?hl=en
    - Fit isn't tracking activities correctly
        - https://support.google.com/fit/answer/6075068?hl=en
    - Connect other apps with Google Fit
        - https://support.google.com/accounts/answer/6098255?hl=en
- Setting example of "HTTP Authentication" (OAuth2)
    - Authorization Endpoint URL:
        - https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force
    - Token Endpoint URL:
        - https://accounts.google.com/o/oauth2/token
    - Scope:
        - https://www.googleapis.com/auth/fitness.activity.read https://www.googleapis.com/auth/fitness.location.read
    - Client ID, Consumer Secret:
        - ( from https://console.developers.google.com/ )
        - Redirect URLs: https://s.questetra.net/oauth2callback
APPENDIX-ja
- Google Fit 自体の基本的な利用方法は、Google Fit のドキュメントを参照してください。
    - フィットネス アクティビティを記録する
        - https://support.google.com/fit/answer/6075066?hl=ja
    - アクティビティを確認する
        - https://support.google.com/fit/answer/6090183?hl=ja
    - Fit がアクティビティを正しくトラッキングしていない
        - https://support.google.com/fit/answer/6075068?hl=ja
    - 他のアプリと Google Fit を接続する
        - https://support.google.com/accounts/answer/6098255?hl=ja
- "HTTP認証"(OAuth2)の設定例
    - Authorization Endpoint URL:
        - https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force
    - Token Endpoint URL:
        - https://accounts.google.com/o/oauth2/token
    - Scope:
        - https://www.googleapis.com/auth/fitness.activity.read https://www.googleapis.com/auth/fitness.location.read
    - Client ID, Consumer Secret:
        - ( from https://console.developers.google.com/ )
        - Redirect URLs: https://s.questetra.net/oauth2callback
*/

Download

2021-05-24 (C) Questetra, Inc. (MIT License)
https://support.questetra.com/ja/addons/google-fit-fitnessdata-get-steps-2021/
Addonファイルのインポートは Professional でのみご利用いただけます

Notes

  • 介護職員や配達員などが勤務時間内の歩数や距離を報告する業務プロセス等で利用します。 GoogleFitSteps
    • 24時間を超えるような時間範囲での集計も可能です。
    • ただし、2カ月を超えるような長期間の集計は “aggregate duration too large” エラーとなります。
  • API通信を許可(OAuth認可)した本人のデータしか取得できません。 “HTTP認証設定”
    • すなわち、自動処理工程1つにつき、1人のデータしか取得できません。
    • 2021-05現在、任意のユーザID(userId)でのデータ取得はできません。
  • 移動距離データの単位はメートルです。
    • 小数点以下有効数字(切り捨て位置)は、ワークフローアプリの数値型データ定義に従います。
  • 日時(範囲開始と範囲終了)が日付フォーマットで設定された場合、”00:00″ とみなされます。
    • 例: “2021-12-31” → “2021-12-31 00:00”

Capture

Google Fit 内の歩数データを取得します。任意期間における歩数(集計値)を取得します。総移動距離を取得することも可能です。たとえば、介護職員や配達員の勤務時間歩数を自動的に取得します。
google-fit-rest-api
Google Fit 内の歩数データを取得します。任意期間における歩数(集計値)を取得します。総移動距離を取得することも可能です。たとえば、介護職員や配達員の勤務時間歩数を自動的に取得します。

Appendix

See also

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

%d