Google Fit: FitnessData, Get Steps
Google Fit: FitnessData, Get Steps
Gets the step count data in Google Fit. Gets the aggregated value for any period. It is also possible to acquire travel distance data (meters). For example, the number of steps taken during working hours for care workers and delivery staff is acquired.
Configs
  • U: Select HTTP_Authz Setting *
  • A1: Set Start Datetime of Duration (eg “2021-12-31 09:00”) *#{EL}
  • A2: Set End Datetime of Duration (eg “2021-12-31 17:00”) *#{EL}
  • B1: Select NUMERIC DATA for Step Count (update) *
  • B2: Select NUMERIC DATA for Distance (update)
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/addons/google-fit-fitnessdata-get-steps-2021/
The Addon-import feature is available with Professional edition.

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”

Capture

Gets the step count data in Google Fit. Gets the aggregated value for any period. It is also possible to acquire travel distance data (meters). For example, the number of steps taken during working hours for care workers and delivery staff is acquired.
google-fit-rest-api
Gets the step count data in Google Fit. Gets the aggregated value for any period. It is also possible to acquire travel distance data (meters). For example, the number of steps taken during working hours for care workers and delivery staff is acquired.

Appendix

See also

1 thought on “Google Fit #FitnessData: Get Steps”

  1. Pingback: Google Fit: Dataset; Aggregate Step Count – Questetra Support

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: