From afd9093b25891ac1f78ca6c0db7bd758b0162e0c Mon Sep 17 00:00:00 2001 From: Pauline Conde Date: Thu, 17 Sep 2020 12:45:11 +0100 Subject: [PATCH 01/12] Update version --- java-sdk/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-sdk/build.gradle b/java-sdk/build.gradle index 5f0de0c3..c3f9e16a 100644 --- a/java-sdk/build.gradle +++ b/java-sdk/build.gradle @@ -17,7 +17,7 @@ subprojects { apply plugin: 'idea' // Configuration - version = '0.5.14' + version = '0.5.15-SNAPSHOT' group = 'org.radarcns' ext.githubRepoName = 'RADAR-base/RADAR-Schemas' From 0b7be08464d9b84a3062ed338dbcba24540f1765 Mon Sep 17 00:00:00 2001 From: yatharthranjan Date: Fri, 30 Oct 2020 17:21:10 +0000 Subject: [PATCH 02/12] Add schemas for Garmin Health API. --- .../garmin/garmin_push_activity_details.avsc | 46 +++++++++++++++++++ .../garmin_push_activity_details_sample.avsc | 23 ++++++++++ .../garmin/garmin_push_activity_summary.avsc | 37 +++++++++++++++ .../garmin/garmin_push_body_composition.avsc | 18 ++++++++ .../garmin/garmin_push_daily_summary.avsc | 43 +++++++++++++++++ .../garmin/garmin_push_epoch_summary.avsc | 22 +++++++++ .../garmin/garmin_push_move_iq_summary.avsc | 16 +++++++ .../garmin/garmin_push_pulse_ox.avsc | 16 +++++++ .../garmin/garmin_push_respiration.avsc | 14 ++++++ .../garmin/garmin_push_sleep_levels_map.avsc | 21 +++++++++ .../garmin/garmin_push_sleep_summary.avsc | 23 ++++++++++ .../garmin_push_stress_detail_summary.avsc | 16 +++++++ .../garmin/garmin_push_user_metrics.avsc | 14 ++++++ 13 files changed, 309 insertions(+) create mode 100644 commons/push/integration/garmin/garmin_push_activity_details.avsc create mode 100644 commons/push/integration/garmin/garmin_push_activity_details_sample.avsc create mode 100644 commons/push/integration/garmin/garmin_push_activity_summary.avsc create mode 100644 commons/push/integration/garmin/garmin_push_body_composition.avsc create mode 100644 commons/push/integration/garmin/garmin_push_daily_summary.avsc create mode 100644 commons/push/integration/garmin/garmin_push_epoch_summary.avsc create mode 100644 commons/push/integration/garmin/garmin_push_move_iq_summary.avsc create mode 100644 commons/push/integration/garmin/garmin_push_pulse_ox.avsc create mode 100644 commons/push/integration/garmin/garmin_push_respiration.avsc create mode 100644 commons/push/integration/garmin/garmin_push_sleep_levels_map.avsc create mode 100644 commons/push/integration/garmin/garmin_push_sleep_summary.avsc create mode 100644 commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc create mode 100644 commons/push/integration/garmin/garmin_push_user_metrics.avsc diff --git a/commons/push/integration/garmin/garmin_push_activity_details.avsc b/commons/push/integration/garmin/garmin_push_activity_details.avsc new file mode 100644 index 00000000..7f65409c --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_activity_details.avsc @@ -0,0 +1,46 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminActivityDetails", + "type": "record", + "doc": "Fitness activity details summaries represent detailed information about discrete fitness activities, such as running or swimming, that are specifically and intentionally started by the user on their device. All wellness data, like steps and distance, contained in the activity are already represented in the Daily summary and in the corresponding Epoch summaries, so Activity Detail summaries should only be used for programs that wish to treat specific activity types in different ways, such as giving the user extra credit for going swimming three times in the same week. Activity details summaries include all data recorded by the device as part of the Fitness Activity, including GPS coordinates and all recorded sensor data. ", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "summary", "type": { + "name": "GarminActivityDetailsSummary", + "type": "record", + "doc": "Each activity detail contains an activity summary.", + "fields": [ + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type. See Appendix A for a complete list.", "default": null}, + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds.", "default": null}, + {"name": "averageBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Average Bike Cadence in rounds per minute.", "default": null}, + {"name": "maxBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Maximum Bike Cadence in rounds per minute.", "default": null}, + {"name": "distanceInMeters", "type": ["null", "double"], "doc": "Distance traveled in meters.", "default": null}, + {"name": "averageRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Average Run Cadence in Steps per minute.", "default": null}, + {"name": "maxRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Maximum Run Cadence in Steps per minute.", "default": null}, + {"name": "activeKilocalories", "type": ["null", "int"], "doc": "Active kilocalories (dietary calories) burned through actual movement and activity during the monitoring period.", "default": null}, + {"name": "averageSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Average Speed in meters per second.", "default": null}, + {"name": "maxSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Maximum Speed in meters per second.", "default": null}, + {"name": "averageSwimCadenceInStrokesPerMinute", "type": ["null", "double"], "doc": "Average Swim Cadence in strokes per minute.", "default": null}, + {"name": "averagePaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Average Pace in minutes per kilometer.", "default": null}, + {"name": "maxPaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Maximum Pace in minutes per kilometer.", "default": null}, + {"name": "numberOfActiveLengths", "type": ["null", "int"], "doc": "Number of Active Lengths.", "default": null}, + {"name": "averageHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, + {"name": "maxHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, + {"name": "startingLatitudeInDegree", "type": ["null", "double"], "doc": "Starting Latitude in Degree", "default": null}, + {"name": "startingLongitudeInDegree", "type": ["null", "double"], "doc": "Starting Longitude in Degree", "default": null}, + {"name": "steps", "type": ["null", "int"], "doc": "Count of steps recorded during the monitoring period.", "default": null}, + {"name": "totalElevationGainInMeters", "type": ["null", "double"], "doc": "Total Elevation Gain in meters", "default": null}, + {"name": "totalElevationLossInMeters", "type": ["null", "double"], "doc": "Total Elevation Loss in meters", "default": null}, + {"name": "isParent", "type": ["null", "boolean"], "doc": "If present and set to true, this activity is the parent activity of one or more child activities that should also be made available in the data feed to the partner. An activity of type MULTI_SPORT is an example of a parent activity.", "default": null}, + {"name": "parentSummaryId", "type": ["null", "string"], "doc": "If present, this is the summaryId of the related parent activity. An activity of type CYCLING with a parent activity of type MULTI_SPORT is an example of this type of relationship.", "default": null}, + {"name": "manual", "type": ["null", "boolean"], "doc": "Indicates that the activity was manually entered directly on the Connect site. This property will only exist for manual activities.", "default": null}, + {"name": "deviceName", "type": ["null", "string"], "doc": "Only Fitness Activities are associated with a specific Garmin device rather than the user’s overall account. If a user wears two devices at once during the same time and starts a Fitness Activity on each then both will generate separate Activity summaries with two different deviceNames. Always ‘unknown’ for manually created activities.", "default": null} + ] + } + }, + {"name": "samples", "type": { "type": "array", "items" : "GarminActivityDetailsSample", "default": [] }, "doc": "Each activity detail contains an optional list of samples. The samples list will be empty if the activity is manual or details are not supported by the device. Samples may be as frequent as once per second, and values should be considered valid until the next sample."} + ] +} diff --git a/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc b/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc new file mode 100644 index 00000000..f313abbd --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc @@ -0,0 +1,23 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminActivityDetailsSample", + "type": "record", + "doc": "Each activity detail contains an activity summary and an optional list of samples. The samples list will be empty if the activity is manual or details are not supported by the device. Samples may be as frequent as once per second, and values should be considered valid until the next sample. In all cases, movingDurationInSeconds is less than or equal to timerDurationInSeconds is less than or equal to clockDurationInSeconds.", + "fields": [ + {"name": "startTimeInSeconds", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "airTemperatureCelcius", "type": ["null", "double"], "doc": "Air Temperature in Celcius.", "default": null}, + {"name": "heartrate", "type": ["null", "int"], "doc": "Heart rate in beats per minute.", "default": null}, + {"name": "speedMetersPerSecond", "type": ["null", "double"], "doc": "Speed in Meters Per Second.", "default": null}, + {"name": "stepsPerMinute", "type": ["null", "double"], "doc": "Number of steps per minute.", "default": null}, + {"name": "totalDistanceInMeters", "type": ["null", "double"], "doc": "Total Distance in Meters.", "default": null}, + {"name": "timerDurationInSeconds", "type": ["null", "int"], "doc": "The amount of 'timer time' in an activity.", "default": null}, + {"name": "clockDurationInSeconds", "type": ["null", "int"], "doc": "The amount of real-world 'clock time' from the start of an activity to the end.", "default": null}, + {"name": "movingDurationInSeconds", "type": ["null", "int"], "doc": "The amount of 'timer time' during which the athlete was moving (above a threshold speed).", "default": null}, + {"name": "powerInWatts", "type": ["null", "double"], "doc": "The amount of power expended in watts.", "default": null}, + {"name": "bikeCadenceInRPM", "type": ["null", "int"], "doc": "Cycling cadence in revolutions per minute.", "default": null}, + {"name": "swimCadenceInStrokesPerMinute", "type": ["null", "int"], "doc": "Swim cadence in strokes per minute.", "default": null}, + {"name": "latitudeInDegree", "type": ["null", "double"], "doc": "Latitude in decimal degrees (DD)", "default": null}, + {"name": "longitudeInDegree", "type": ["null", "double"], "doc": "Longitude in decimal degrees (DD)", "default": null}, + {"name": "elevationInMeters", "type": ["null", "double"], "doc": "Elevation in meters", "default": null} + ] +} diff --git a/commons/push/integration/garmin/garmin_push_activity_summary.avsc b/commons/push/integration/garmin/garmin_push_activity_summary.avsc new file mode 100644 index 00000000..a8d21787 --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_activity_summary.avsc @@ -0,0 +1,37 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminActivitySummary", + "type": "record", + "doc": "Fitness activity summaries represent high-level information from discrete fitness activities, such as running or swimming, that are specifically and intentionally started by the user on their device. All wellness data, like steps and distance, contained in the Activity are already represented in the Daily summary and in the corresponding Epoch summaries, so Activity summaries should only be used for programs that wish to treat specific activity types in different ways, such as giving the user extra credit for going swimming three times in the same week.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type. See Appendix A for a complete list.", "default": null}, + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "averageBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Average Bike Cadence in rounds per minute.", "default": null}, + {"name": "maxBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Maximum Bike Cadence in rounds per minute.", "default": null}, + {"name": "distanceInMeters", "type": ["null", "double"], "doc": "Distance traveled in meters.", "default": null}, + {"name": "averageRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Average Run Cadence in Steps per minute.", "default": null}, + {"name": "maxRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Maximum Run Cadence in Steps per minute.", "default": null}, + {"name": "activeKilocalories", "type": ["null", "int"], "doc": "Active kilocalories (dietary calories) burned through actual movement and activity during the monitoring period.", "default": null}, + {"name": "averageSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Average Speed in meters per second.", "default": null}, + {"name": "maxSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Maximum Speed in meters per second.", "default": null}, + {"name": "averageSwimCadenceInStrokesPerMinute", "type": ["null", "double"], "doc": "Average Swim Cadence in strokes per minute.", "default": null}, + {"name": "averagePaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Average Pace in minutes per kilometer.", "default": null}, + {"name": "maxPaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Maximum Pace in minutes per kilometer.", "default": null}, + {"name": "numberOfActiveLengths", "type": ["null", "int"], "doc": "Number of Active Lengths.", "default": null}, + {"name": "averageHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, + {"name": "maxHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, + {"name": "startingLatitudeInDegree", "type": ["null", "double"], "doc": "Starting Latitude in Degree", "default": null}, + {"name": "startingLongitudeInDegree", "type": ["null", "double"], "doc": "Starting Longitude in Degree", "default": null}, + {"name": "steps", "type": ["null", "int"], "doc": "Count of steps recorded during the monitoring period.", "default": null}, + {"name": "totalElevationGainInMeters", "type": ["null", "double"], "doc": "Total Elevation Gain in meters", "default": null}, + {"name": "totalElevationLossInMeters", "type": ["null", "double"], "doc": "Total Elevation Loss in meters", "default": null}, + {"name": "isParent", "type": ["null", "boolean"], "doc": "If present and set to true, this activity is the parent activity of one or more child activities that should also be made available in the data feed to the partner. An activity of type MULTI_SPORT is an example of a parent activity.", "default": null}, + {"name": "parentSummaryId", "type": ["null", "string"], "doc": "If present, this is the summaryId of the related parent activity. An activity of type CYCLING with a parent activity of type MULTI_SPORT is an example of this type of relationship.", "default": null}, + {"name": "manual", "type": ["null", "boolean"], "doc": "Indicates that the activity was manually entered directly on the Connect site. This property will only exist for manual activities.", "default": null}, + {"name": "deviceName", "type": ["null", "string"], "doc": "Only Fitness Activities are associated with a specific Garmin device rather than the user’s overall account. If a user wears two devices at once during the same time and starts a Fitness Activity on each then both will generate separate Activity summaries with two different deviceNames. Always ‘unknown’ for manually created activities.", "default": null} + ] +} diff --git a/commons/push/integration/garmin/garmin_push_body_composition.avsc b/commons/push/integration/garmin/garmin_push_body_composition.avsc new file mode 100644 index 00000000..857bb8ad --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_body_composition.avsc @@ -0,0 +1,18 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminBodyComposition", + "type": "record", + "doc": "Body Composition summaries contain information about the user’s biometric data, like weight or body mass index. This data can be generated three ways. Users can manually enter their weight on Garmin Connect. This results in a summary with only time and weight. Users may also connect their MyFitnessPal account to their Garmin Connect account and update their weight on MyFitnessPal. This results in a summary that also just has a time and weight. Finally, a user might have a Garmin Index body composition scale and sync data from this device. This will generate a summary with all possible biometric fields.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "muscleMassInGrams", "type": ["null", "int"], "doc": "Muscle mass in grams.", "default": null}, + {"name": "boneMassInGrams", "type": ["null", "int"], "doc": "Bone mass in grams.", "default": null}, + {"name": "measurementTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "bodyWaterInPercent", "type": ["null", "double"], "doc": "Percentage of body water (range 0.0 - 100.0).", "default": null}, + {"name": "bodyFatInPercent", "type": ["null", "double"], "doc": "Percentage of body fat. (range 0.0 - 100.0).", "default": null}, + {"name": "bodyMassIndex", "type": ["null", "double"], "doc": "Body mass index, or BMI.", "default": null}, + {"name": "weightInGrams", "type": ["null", "int"], "doc": "Weight in grams.", "default": null} + ] +} \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_daily_summary.avsc b/commons/push/integration/garmin/garmin_push_daily_summary.avsc new file mode 100644 index 00000000..506f8b96 --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_daily_summary.avsc @@ -0,0 +1,43 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminDailySummary", + "type": "record", + "doc": "Daily summaries offer a high-level view of the user’s entire day. They generally correspond to the data found on the “My Day” section of Garmin Connect. Daily summaries are the most commonly used and are often the foundation of a Health API integration.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "activityType", "type": ["null", "string"], "doc": "This field is included in daily summaries for backwards compatibility purposes. It can be ignored and will always default to WALKING.", "default": null}, + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "steps", "type": ["null", "int"], "doc": "Count of steps recorded during the monitoring period.", "default": null}, + {"name": "distanceInMeters", "type": ["null", "double"], "doc": "Distance traveled in meters.", "default": null}, + {"name": "activeTimeInSeconds", "type": ["null", "int"], "doc": "Portion of the monitoring period (in seconds) in which the device wearer was considered Active. This relies on heuristics internal to each device.", "default": null}, + {"name": "activeKilocalories", "type": ["null", "int"], "doc": "Active kilocalories (dietary calories) burned through actual movement and activity during the monitoring period.", "default": null}, + {"name": "bmrKilocalories", "type": ["null", "int"], "doc": "BMR Kilocalories burned by existing Basal Metabolic Rate (calculated based on user height/weight/age/other demographic data).", "default": null}, + {"name": "consumedCalories", "type": ["null", "int"], "doc": "The number of calories that have been consumed by the user through food for that day (value subtracted from calorie goal). This value is received from MyFitnessPal and is not entered within Connect.", "default": null}, + {"name": "moderateIntensityDurationInSeconds", "type": ["null", "int"], "doc": "Cumulative duration of activities of moderate intensity, lasting at least 600 seconds at a time. Moderate intensity is defined as activity with MET value range 3-6.", "default": null}, + {"name": "vigorousIntensityDurationInSeconds", "type": ["null", "int"], "doc": "Cumulative duration of activities of vigorous intensity, lasting at least 600 seconds at a time. Vigorous intensity is defined as activity with MET value greater than 6.", "default": null}, + {"name": "floorsClimbed", "type": ["null", "int"], "doc": "Number of floors climbed during the monitoring period.", "default": null}, + {"name": "minHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Minimum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, + {"name": "averageHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, + {"name": "maxHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, + {"name": "restingHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average heart rate at rest during the monitoring period, in beats per minute.", "default": null}, + {"name": "timeOffsetHeartRateSamples", "type": {"type": "map","values" : "double", "default": {}}, "doc": "Collection of mappings between offset from start time (in seconds) to a heart rate value recorded for that time, in beats per minute. Each entry is a representative sample of the previous 15 seconds from the given offset. Lack of entry for a given offset should be interpreted as no data available."}, + {"name": "averageStressLevel", "type": ["null", "int"], "doc": "An abstraction of the user’s average stress level in this monitoring period, measured from 1 to 100, or -1 if there is not enough data to calculate average stress. Scores between 1 and 25 are considered “rest” (i.e not stressful), 26-50 as “low” stress, 51-75 “medium” stress, and 76-100 as “high” stress.", "default": null}, + {"name": "maxStressLevel", "type": ["null", "int"], "doc": "The highest stress level measurement taken during this monitoring period.", "default": null}, + {"name": "stressDurationInSeconds", "type": ["null", "int"], "doc": "The number of seconds in this monitoring period where stress level measurements were in the stressful range (26-100).", "default": null}, + {"name": "restStressDurationInSeconds", "type": ["null", "int"], "doc": "The number of seconds in this monitoring period where stress level measurements were in the restful range (1 to 25).", "default": null}, + {"name": "activityStressDurationInSeconds", "type": ["null", "int"], "doc": "The number of seconds in this monitoring period where the user was engaging in physical activity and so stress measurement was unreliable. All duration in this monitoring period not covered by stress, rest, and activity stress should be considered Uncategorized, either because the device was not worn or because not enough data could be taken to generate a stress score.", "default": null}, + {"name": "lowStressDurationInSeconds", "type": ["null", "int"], "doc": "The portion of the user’s stress duration where the measured stress score was in the low range (26-50).", "default": null}, + {"name": "mediumStressDurationInSeconds", "type": ["null", "int"], "doc": "The portion of the user’s stress duration where the measured stress score was in the medium range (51-75).", "default": null}, + {"name": "highStressDurationInSeconds", "type": ["null", "int"], "doc": "The portion of the user’s stress duration where the measured stress score was in the high range (76-100).", "default": null}, + {"name": "stressQualifier", "type": ["null", "string"], "doc": "A qualitative label applied based on all stress measurements in this monitoring period. Possible values: unknown, calm, balanced, stressful, very_stressful, calm_awake, balanced_awake, stressful_awake, very_stressful_awake. This matches what the user will see in Garmin Connect. It is recommended that implementations that use the stressQualifier be tolerant of unknown values in case more granular values are added.", "default": null}, + {"name": "stepsGoal", "type": ["null", "int"], "doc": "The user’s steps goal for this monitoring period.", "default": null}, + {"name": "netKilocaloriesGoal", "type": ["null", "int"], "doc": "The user’s goal for net caloric intake (consumed calories minus active calories) for this monitoring period. This field is related to integration with MyFitnessPal and may not be present for many users.", "default": null}, + {"name": "intensityDurationGoalInSeconds", "type": ["null", "int"], "doc": "The user’s goal for consecutive seconds of moderate to vigorous intensity activity for this monitoring period.", "default": null}, + {"name": "floorsClimbedGoal", "type": ["null", "int"], "doc": "The user’s goal for floors climbed in this monitoring period.", "default": null}, + {"name": "source", "type": ["null", "string"], "doc": "The name of the source of the third party data. For example FITBIT. Only present in Third Party summaries.", "default": null} + ] +} diff --git a/commons/push/integration/garmin/garmin_push_epoch_summary.avsc b/commons/push/integration/garmin/garmin_push_epoch_summary.avsc new file mode 100644 index 00000000..21a03361 --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_epoch_summary.avsc @@ -0,0 +1,22 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminEpochSummary", + "type": "record", + "doc": "The Epoch Summary contains wellness data for a specific time range. Epoch summary records contain much of the same data available in Daily summaries, but with 15-minute time-slice granularity. There is one record for each activity type monitored within an individual epoch. For example, if the user was sedentary for five minutes, walked for five minutes, and then ran for five minutes over the course of 15 minutes, three activity records would be generated for that single 15-minute epoch. The duration value would be 900 seconds for all three records, but the active time for each would be 300 seconds. A duration of less than 900 seconds indicates that the user synced data during the middle of an epoch. On the user’s next sync, that epoch record will be replaced with a 900-second-duration epoch covering the entire span. As such and to accommodate users with multiple devices, it is important that new epochs always replace existing epochs that have the same startTimeInSeconds. The most recent update from the Health API will always reflect the most recent data in Garmin Connect. Epoch data is useful when attempting to construct charts showing intraday wellness data. An example of this in Garmin Connect is the Steps Details chart that graphs step count changes throughout the user’s day.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type.", "default": null}, + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "steps", "type": ["null", "int"], "doc": "Count of steps recorded during the monitoring period.", "default": null}, + {"name": "distanceInMeters", "type": ["null", "double"], "doc": "Distance traveled in meters.", "default": null}, + {"name": "activeTimeInSeconds", "type": ["null", "int"], "doc": "Portion of the monitoring period (in seconds) in which the device wearer was active for this activity type. The sum of active times of all epochs of the same start time (and different activity types) should be equal to the duration.", "default": null}, + {"name": "activeKilocalories", "type": ["null", "int"], "doc": "Active kilocalories (dietary calories) burned during the monitoring period. This includes only the calories burned by the activity and not calories burned as part of the basal metabolic rate (BMR).", "default": null}, + {"name": "met", "type": ["null", "double"], "doc": "MET (Metabolic Equivalent of Task) value for the active time for this activity type. Metabolic Equivalent of Task (MET) is an official measure of activity intensity. Garmin’s calculation of MET is an estimation based on the biometric data provided (height, weight, date of birth, gender) and improves in accuracy if heart rate data is also captured. The following linked document hosted by the US Centers for Disease Control and Prevention provides detailed information on MET and physical activity intensity: http://www.cdc.gov/nccdphp/dnpa/physical/pdf/PA_Intensity_table_2_1.pdf", "default": null}, + {"name": "intensity", "type": ["null", "string"], "doc": "Qualitative measure of intensity. Possible values: SEDENTARY(Little to no activity monitored. This could be due to minimal movement, sitting, resting, or sleeping.), ACTIVE(Some activity monitored. A brisk walk could achieve this intensity.), HIGHLY_ACTIVE(High activity monitored. Running or speed walking could achieve this intensity.)", "default": null}, + {"name": "meanMotionIntensity", "type": ["null", "double"], "doc": "The average of motion intensity scores for all minutes in this monitoring period. Motion Intensity is a numerical abstraction of low-level accelerometer data, provided for use in further analysis. This data is not exposed directly to the consumer by Garmin but is used in in the creation of other metrics. Motion Intensity is calculated at minute-level granularity as a number between 0 and 7, with 0 being absolutely still and 7 being constant, sharp motion. Unlike steps, distance, or activity type, which take net movement in to account, motion intensity will increase even if the user does not move in space. For instance, if a user were to jump up and down or fidget with a pencil they would not get credit for any distance, but their motion intensity scores for that monitoring period would increase. It is very common to see mid-range max motion intensities even for sedentary epochs as most people do not sit absolutely still.", "default": null}, + {"name": "maxMotionIntensity", "type": ["null", "double"], "doc": "The largest motion intensity score of any minute in this monitoring period. Motion Intensity is a numerical abstraction of low-level accelerometer data, provided for use in further analysis. This data is not exposed directly to the consumer by Garmin but is used in in the creation of other metrics. Motion Intensity is calculated at minute-level granularity as a number between 0 and 7, with 0 being absolutely still and 7 being constant, sharp motion. Unlike steps, distance, or activity type, which take net movement in to account, motion intensity will increase even if the user does not move in space. For instance, if a user were to jump up and down or fidget with a pencil they would not get credit for any distance, but their motion intensity scores for that monitoring period would increase. It is very common to see mid-range max motion intensities even for sedentary epochs as most people do not sit absolutely still.", "default": null} + ] +} \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_move_iq_summary.avsc b/commons/push/integration/garmin/garmin_push_move_iq_summary.avsc new file mode 100644 index 00000000..523064a9 --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_move_iq_summary.avsc @@ -0,0 +1,16 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminMoveIQSummary", + "type": "record", + "doc": "Move IQ Event summaries are a feed of activities which have been automatically detected by the device based on movement patterns, like running or biking. These are not activities initiated by the user. Please note that wellness data, like steps and distance, from Move IQ events are already included in the Daily and Epoch summaries. Due to their automatically-detected nature, Move IQ events are not considered a fitness activity, do not contain the same details as activities, and cannot be edited by the user with Garmin Connect. These events should be considered a labeled-timespan on top of normal Daily or Epoch summary details, matching their representation within Garmin Connect. For more feature-level information on Move IQ events, please see: https://support.garmin.com/faqSearch/en- US/faq/content/zgFpy8MShkArqAxCug5wC6 . Move IQ activities are also known as Automatic Activity Detection in older devices or documentation.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "offsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "activityType", "type": ["null", "string"], "doc": "The activity type that has been identified for this timespan.", "default": null}, + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "The duration of the measurement period in seconds.", "default": null}, + {"name": "activitySubType", "type": ["null", "string"], "doc": "The activity subtype that has been identified for this timespan.", "default": null} + ] +} \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_pulse_ox.avsc b/commons/push/integration/garmin/garmin_push_pulse_ox.avsc new file mode 100644 index 00000000..2b8581da --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_pulse_ox.avsc @@ -0,0 +1,16 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminPulseOx", + "type": "record", + "doc": "Pulse Ox summaries contain blood oxygen saturation data. Two types of data are represented in Pulse Ox summaries based on the capabilities of the user’s device. If the onDemand field is not present or set to false, the timeOffsetSpo2Values map contains an SpO2 measurement that is an average of all measurements taken as part of the Acclimation feature (https://www8.garmin.com/manuals/webhelp/fenix5plus/EN-US/GUID-4D425925-D4EE-4C26-B974- 5375D0670860.html). If the onDemand field is true the timeOffsetSpo2Values map instead contains one or more exact measurements taken by a device that is capable of on-demand measurements but not the Acclimation feature, such as the Vivosmart 4. Backfill is supported for Pulse Ox summaries, but only for Acclimation data.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "timeOffsetSpo2Values", "type": { "type": "map", "values": "double", "default": {}}, "doc": "Collection of key-value pairs where the key is offset in seconds from the startTimeInSeconds and the value is the SpO2 measurement taken at that time (1 sample/minute)"}, + {"name": "onDemand", "type": ["null", "boolean"], "doc": "A Boolean to show whether this pulse ox summary represents an on- demand reading or an averaged acclimation reading.", "default": null} + ] +} \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_respiration.avsc b/commons/push/integration/garmin/garmin_push_respiration.avsc new file mode 100644 index 00000000..e0958dde --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_respiration.avsc @@ -0,0 +1,14 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminRespiration", + "type": "record", + "doc": "Respiration is a feature (https://www8.garmin.com/manuals/webhelp/vivoactive4_4S/EN-US/GUID-252F74B6-C24B-495B-8E73-4BD595CA7FE3.html) available on some Garmin devices that tracks breathing rate throughout the day, during sleep, and during activities such as breathwork and yoga.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "timeOffsetEpochToBreaths", "type": { "type": "map", "values": "double", "default": {}}, "doc": "Collection of key-value pairs where the key is offset in seconds from the startTimeInSeconds and respiration measurement taken at that time. Respiration measurement is in breaths per minute."} + ] +} \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_sleep_levels_map.avsc b/commons/push/integration/garmin/garmin_push_sleep_levels_map.avsc new file mode 100644 index 00000000..9477a5f7 --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_sleep_levels_map.avsc @@ -0,0 +1,21 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminSleepLevelsMap", + "type": "record", + "doc": "A map of sleep level time ranges, currently deep, light, rem and awake. Time ranges are represented as unix timestamps in seconds.", + "fields": [ + {"name": "deep", "type": { "type": "array", "items": { + "name": "GarminSleepLevelsMapValue", + "type": "record", + "doc": "The list of time periods for this sleep type.", + "fields": [ + {"name": "startTimeInSeconds", "type": "double", "doc": "Start time of this sleep period in seconds."}, + {"name": "endTimeInSeconds", "type": "double", "doc": "End time of this sleep period in seconds."} + ] + }, "default": [] }, + "doc": "Time ranges for the deep sleep periods."}, + {"name": "light", "type": { "type": "array", "items": "GarminSleepLevelsMapValue", "default": [] }, "doc": "Time ranges for the light sleep periods."}, + {"name": "awake", "type": { "type": "array", "items": "GarminSleepLevelsMapValue", "default": [] }, "doc": "Time ranges for the awake sleep periods."}, + {"name": "rem", "type": { "type": "array", "items": "GarminSleepLevelsMapValue", "default": [] }, "doc": "Time ranges for the rem sleep periods."} + ] +} diff --git a/commons/push/integration/garmin/garmin_push_sleep_summary.avsc b/commons/push/integration/garmin/garmin_push_sleep_summary.avsc new file mode 100644 index 00000000..4214628f --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_sleep_summary.avsc @@ -0,0 +1,23 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminSleepSummary", + "type": "record", + "doc": "Sleep summaries are data records representing how long the user slept and the automatically classified sleep levels during that sleep event (e.g. light, deep periods) based on data generated by the user’s device. Users may generate sleep data three different ways. Some older Garmin devices (e.g. first generation vívofit) allow users to manually place the device in sleep mode. Newer devices do not have this option and instead auto-detect sleep if it occurs between the user’s Bed/Wake time range configured in Garmin Connect. Users may also self-report sleep information using Garmin Connect. Sleep records from the Health API are labelled to identify how the sleep data was generated (see below). This allows partners to accept/reject various methods of collecting Sleep data. Recommended usage for this field is to filter out validation types that are not desired rather than accept only certain validation types in order to prevent lost data in the future if new validation types are added, as by default Garmin Connect displays records of all possible types. Unlike Daily summaries which are associated with a given day on a midnight-to-midnight basis, Sleep summaries are associated with a user’s overnight sleep range. Most will start on one calendar day and end on the next calendar day, but it is possible for two different Sleep summaries to begin on the same day if, for example, the user goes to bed after midnight, wakes up, and then goes to bed prior to midnight the next evening. The sleep summary will include REM sleep if the user’s device is capable of REM sleep analysis. Users without REM-capable devices, or with REM-capable devices that have not been updated to REM-capable firmware, are limited to only deep, light, and awake sleep levels. Additionally, REM sleep will only be generated if the REM-capable devices is set as the preferred activity tracker and is actually worn during sleep. Some pulse-oximetry-enabled devices will generate SpO2 values during sleep for use in sleep analysis. If such values are generated, they are included in the sleep summary for reference.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "unmeasurableSleepInSeconds", "type": ["null", "int"], "doc": "Time in seconds that the sleep level of the user could not be measured. This may or may not correspond to off-wrist time.", "default": null}, + {"name": "deepSleepDurationInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent in deep sleep during the sleep period.", "default": null}, + {"name": "lightSleepDurationInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent in light sleep during the sleep period.", "default": null}, + {"name": "remSleepInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent in REM sleep during the sleep period.", "default": null}, + {"name": "awakeDurationInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent awake during the sleep period.", "default": null}, + {"name": "sleepLevelsMap", "type": ["null", "GarminSleepLevelsMap"], "doc": "A map of sleep level time ranges, currently deep, light, rem and awake. Time ranges are represented as unix timestamps in seconds.", "default": null}, + {"name": "validation", "type": ["null", "string"], "doc": "String that relays the validation state of the sleep data and its date range. The data could be auto-confirmed, but the sleep window could have been manually adjusted, or the sleep data itself is entirely manually entered. Possible values: MANUAL: The user entered sleep start and stop times manually through a web form. There is no device data backing up the sleep assessment. DEVICE: The user used a device with the sleep feature to manually start and stop sleep. This type still requires manual user intervention to judge sleep start and stop. AUTO_TENTATIVE: The sleep start and stop times were auto-detected by Garmin Connect using accelerometer data. However, it is possible that further refinements to this sleep record will come later. This could be because the user is still asleep or could be because the user owns multiple devices and might sync another device later for this same time period. AUTO_FINAL: The sleep start and stop times were auto-detected by Garmin Connect, and enough data has been gathered to finalize the window. This status also indicates that the user only has one device so this record can never be updated again – users that own multiple devices will never get an AUTO_FINAL. AUTO_MANUAL: Sleep data was auto-detected by Garmin Connect, but the user is overriding the start and stop times or the user started with a manual entry and the sleep was auto-detected later. Garmin Connect stores both but will display the manual start and stop times in favor of the auto-detected times. ENHANCED_TENTATIVE: Sleep data was collected from a device capable of running an enhanced sleep analysis to detect REM sleep, but an updated sleep summary record may come later with further refinements or a greater sleep period. ENHANCED_FINAL: Sleep data was collected from a device capable of running an enhanced sleep analysis to detect REM sleep, and no further updates or refinements to this sleep analysis are expected.", "default": null}, + {"name": "timeOffsetSleepRespiration", "type": { "type": "map", "values": "double", "default": {}}, "doc": "Collection of key-value pairs where the key is offset in seconds from the startTimeInSeconds and respiration measurement taken at that time. Respiration measurement is in breaths per minute."}, + {"name": "timeOffsetSleepSpo2", "type": { "type": "map", "values": "double", "default": {}}, "doc": "A map of SpO2 readings, where the keys are the offsets in seconds from the startTimeInSeconds and the values are the SpO2 measurements at that time. Only present if the user’s device is SpO2-enabled."} + ] +} \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc b/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc new file mode 100644 index 00000000..b15e3654 --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc @@ -0,0 +1,16 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminStressDetailSummary", + "type": "record", + "doc": "Stress Details summaries contain the user’s stress level values for a given day. Stress levels are provided as 3-minute averages of the real-time stress scores generated on the device with values ranging from 1 to 100. A value of -1 means there was not enough data to detect stress, and -2 means there was too much motion (e.g. the user was walking or running). Scores between 1 and 25 are considered “rest” (i.e. not stressful), 26-50 as “low” stress, 51-75 “medium” stress, and 76- 100 as “high” stress. These numbers are derived based on a combination of many device sensors and will automatically adjust to the wearer of the device and gain accuracy over time as the stress algorithms learn the user’s natural biometric norms. Stress values from the Health API are exactly the stress values shown on Garmin Connect.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "timeOffsetStressLevelValues", "type": { "type": "map", "values": "double", "default": {}}, "doc": "Collection of mappings between offset from start time (in seconds) to a stress level value recorded for that time."}, + {"name": "timeOffsetBodyBatteryValues", "type": { "type": "map", "values": "double", "default": {}}, "doc": "Collection of mappings between offset from start time (in seconds) to a body battery value recorded for that time. Information on and a list of devices that support Body Battery are available here: https://support.garmin.com/ms-MY/?faq=2qczgfbN00AIMJbX33dRq9."} + ] +} \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_user_metrics.avsc b/commons/push/integration/garmin/garmin_push_user_metrics.avsc new file mode 100644 index 00000000..2c96c0bc --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_user_metrics.avsc @@ -0,0 +1,14 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminUserMetrics", + "type": "record", + "doc": "User Metrics are per-user calculations performed by Garmin based on the underlying data uploaded from the user’s device. This data can be specific to a single device and field availability is dependent on device model support. Unlike other summaries, User Metrics are associated only with a calendar date, not a specific time frame, and only the most recent value for any fields is presented to the user. Each metric directly corresponds to the similarly named field found in Garmin Connect.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "vo2Max", "type": ["null", "double"], "doc": "An estimate of the maximum volume of oxygen (in milliliters) the user can consume per minute per kilogram of body weight at maximum performance.", "default": null}, + {"name": "fitnessAge", "type": ["null", "int"], "doc": "An estimation of the ‘age’ of the user’s fitness level, calculated by comparing internal fitness metrics with the average readings of biometrically similar users by age. For instance, a fitness age of 48 indicates that the user’s physical fitness is similar to that of an average 48- year-old person of the same gender.", "default": null} + ] +} \ No newline at end of file From e5108a63bc82210aef7b35186f40915f884d86da Mon Sep 17 00:00:00 2001 From: yatharthranjan Date: Sat, 31 Oct 2020 15:07:02 +0000 Subject: [PATCH 03/12] Avoid nesting by moving maps and arrays to individual records. --- .../garmin/garmin_push_activity_details.avsc | 67 ++++++++----------- .../garmin_push_activity_details_sample.avsc | 4 +- .../garmin_push_body_battery_sample.avsc | 12 ++++ .../garmin/garmin_push_daily_summary.avsc | 1 - .../garmin/garmin_push_heart_rate_sample.avsc | 12 ++++ .../garmin/garmin_push_pulse_ox.avsc | 4 +- .../garmin/garmin_push_respiration.avsc | 4 +- .../garmin/garmin_push_sleep_level.avsc | 12 ++++ .../garmin/garmin_push_sleep_levels_map.avsc | 21 ------ .../garmin/garmin_push_sleep_summary.avsc | 5 +- .../garmin_push_stress_detail_summary.avsc | 4 +- .../garmin_push_stress_level_sample.avsc | 12 ++++ 12 files changed, 86 insertions(+), 72 deletions(-) create mode 100644 commons/push/integration/garmin/garmin_push_body_battery_sample.avsc create mode 100644 commons/push/integration/garmin/garmin_push_heart_rate_sample.avsc create mode 100644 commons/push/integration/garmin/garmin_push_sleep_level.avsc delete mode 100644 commons/push/integration/garmin/garmin_push_sleep_levels_map.avsc create mode 100644 commons/push/integration/garmin/garmin_push_stress_level_sample.avsc diff --git a/commons/push/integration/garmin/garmin_push_activity_details.avsc b/commons/push/integration/garmin/garmin_push_activity_details.avsc index 7f65409c..fbf21cfc 100644 --- a/commons/push/integration/garmin/garmin_push_activity_details.avsc +++ b/commons/push/integration/garmin/garmin_push_activity_details.avsc @@ -5,42 +5,33 @@ "doc": "Fitness activity details summaries represent detailed information about discrete fitness activities, such as running or swimming, that are specifically and intentionally started by the user on their device. All wellness data, like steps and distance, contained in the activity are already represented in the Daily summary and in the corresponding Epoch summaries, so Activity Detail summaries should only be used for programs that wish to treat specific activity types in different ways, such as giving the user extra credit for going swimming three times in the same week. Activity details summaries include all data recorded by the device as part of the Fitness Activity, including GPS coordinates and all recorded sensor data. ", "fields": [ {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, - {"name": "summary", "type": { - "name": "GarminActivityDetailsSummary", - "type": "record", - "doc": "Each activity detail contains an activity summary.", - "fields": [ - {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, - {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, - {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type. See Appendix A for a complete list.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds.", "default": null}, - {"name": "averageBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Average Bike Cadence in rounds per minute.", "default": null}, - {"name": "maxBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Maximum Bike Cadence in rounds per minute.", "default": null}, - {"name": "distanceInMeters", "type": ["null", "double"], "doc": "Distance traveled in meters.", "default": null}, - {"name": "averageRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Average Run Cadence in Steps per minute.", "default": null}, - {"name": "maxRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Maximum Run Cadence in Steps per minute.", "default": null}, - {"name": "activeKilocalories", "type": ["null", "int"], "doc": "Active kilocalories (dietary calories) burned through actual movement and activity during the monitoring period.", "default": null}, - {"name": "averageSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Average Speed in meters per second.", "default": null}, - {"name": "maxSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Maximum Speed in meters per second.", "default": null}, - {"name": "averageSwimCadenceInStrokesPerMinute", "type": ["null", "double"], "doc": "Average Swim Cadence in strokes per minute.", "default": null}, - {"name": "averagePaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Average Pace in minutes per kilometer.", "default": null}, - {"name": "maxPaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Maximum Pace in minutes per kilometer.", "default": null}, - {"name": "numberOfActiveLengths", "type": ["null", "int"], "doc": "Number of Active Lengths.", "default": null}, - {"name": "averageHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, - {"name": "maxHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, - {"name": "startingLatitudeInDegree", "type": ["null", "double"], "doc": "Starting Latitude in Degree", "default": null}, - {"name": "startingLongitudeInDegree", "type": ["null", "double"], "doc": "Starting Longitude in Degree", "default": null}, - {"name": "steps", "type": ["null", "int"], "doc": "Count of steps recorded during the monitoring period.", "default": null}, - {"name": "totalElevationGainInMeters", "type": ["null", "double"], "doc": "Total Elevation Gain in meters", "default": null}, - {"name": "totalElevationLossInMeters", "type": ["null", "double"], "doc": "Total Elevation Loss in meters", "default": null}, - {"name": "isParent", "type": ["null", "boolean"], "doc": "If present and set to true, this activity is the parent activity of one or more child activities that should also be made available in the data feed to the partner. An activity of type MULTI_SPORT is an example of a parent activity.", "default": null}, - {"name": "parentSummaryId", "type": ["null", "string"], "doc": "If present, this is the summaryId of the related parent activity. An activity of type CYCLING with a parent activity of type MULTI_SPORT is an example of this type of relationship.", "default": null}, - {"name": "manual", "type": ["null", "boolean"], "doc": "Indicates that the activity was manually entered directly on the Connect site. This property will only exist for manual activities.", "default": null}, - {"name": "deviceName", "type": ["null", "string"], "doc": "Only Fitness Activities are associated with a specific Garmin device rather than the user’s overall account. If a user wears two devices at once during the same time and starts a Fitness Activity on each then both will generate separate Activity summaries with two different deviceNames. Always ‘unknown’ for manually created activities.", "default": null} - ] - } - }, - {"name": "samples", "type": { "type": "array", "items" : "GarminActivityDetailsSample", "default": [] }, "doc": "Each activity detail contains an optional list of samples. The samples list will be empty if the activity is manual or details are not supported by the device. Samples may be as frequent as once per second, and values should be considered valid until the next sample."} - ] + {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, + {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type. See Appendix A for a complete list.", "default": null}, + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds.", "default": null}, + {"name": "averageBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Average Bike Cadence in rounds per minute.", "default": null}, + {"name": "maxBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Maximum Bike Cadence in rounds per minute.", "default": null}, + {"name": "distanceInMeters", "type": ["null", "double"], "doc": "Distance traveled in meters.", "default": null}, + {"name": "averageRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Average Run Cadence in Steps per minute.", "default": null}, + {"name": "maxRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Maximum Run Cadence in Steps per minute.", "default": null}, + {"name": "activeKilocalories", "type": ["null", "int"], "doc": "Active kilocalories (dietary calories) burned through actual movement and activity during the monitoring period.", "default": null}, + {"name": "averageSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Average Speed in meters per second.", "default": null}, + {"name": "maxSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Maximum Speed in meters per second.", "default": null}, + {"name": "averageSwimCadenceInStrokesPerMinute", "type": ["null", "double"], "doc": "Average Swim Cadence in strokes per minute.", "default": null}, + {"name": "averagePaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Average Pace in minutes per kilometer.", "default": null}, + {"name": "maxPaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Maximum Pace in minutes per kilometer.", "default": null}, + {"name": "numberOfActiveLengths", "type": ["null", "int"], "doc": "Number of Active Lengths.", "default": null}, + {"name": "averageHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, + {"name": "maxHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, + {"name": "startingLatitudeInDegree", "type": ["null", "double"], "doc": "Starting Latitude in Degree", "default": null}, + {"name": "startingLongitudeInDegree", "type": ["null", "double"], "doc": "Starting Longitude in Degree", "default": null}, + {"name": "steps", "type": ["null", "int"], "doc": "Count of steps recorded during the monitoring period.", "default": null}, + {"name": "totalElevationGainInMeters", "type": ["null", "double"], "doc": "Total Elevation Gain in meters", "default": null}, + {"name": "totalElevationLossInMeters", "type": ["null", "double"], "doc": "Total Elevation Loss in meters", "default": null}, + {"name": "isParent", "type": ["null", "boolean"], "doc": "If present and set to true, this activity is the parent activity of one or more child activities that should also be made available in the data feed to the partner. An activity of type MULTI_SPORT is an example of a parent activity.", "default": null}, + {"name": "parentSummaryId", "type": ["null", "string"], "doc": "If present, this is the summaryId of the related parent activity. An activity of type CYCLING with a parent activity of type MULTI_SPORT is an example of this type of relationship.", "default": null}, + {"name": "manual", "type": ["null", "boolean"], "doc": "Indicates that the activity was manually entered directly on the Connect site. This property will only exist for manual activities.", "default": null}, + {"name": "deviceName", "type": ["null", "string"], "doc": "Only Fitness Activities are associated with a specific Garmin device rather than the user’s overall account. If a user wears two devices at once during the same time and starts a Fitness Activity on each then both will generate separate Activity summaries with two different deviceNames. Always ‘unknown’ for manually created activities.", "default": null} + ] } diff --git a/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc b/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc index f313abbd..9a66720f 100644 --- a/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc +++ b/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc @@ -4,7 +4,9 @@ "type": "record", "doc": "Each activity detail contains an activity summary and an optional list of samples. The samples list will be empty if the activity is manual or details are not supported by the device. Samples may be as frequent as once per second, and values should be considered valid until the next sample. In all cases, movingDurationInSeconds is less than or equal to timerDurationInSeconds is less than or equal to clockDurationInSeconds.", "fields": [ - {"name": "startTimeInSeconds", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, + {"name": "time", "type": "double", "doc": "Start time of the sample in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time this sample was recieved by the push service in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "airTemperatureCelcius", "type": ["null", "double"], "doc": "Air Temperature in Celcius.", "default": null}, {"name": "heartrate", "type": ["null", "int"], "doc": "Heart rate in beats per minute.", "default": null}, {"name": "speedMetersPerSecond", "type": ["null", "double"], "doc": "Speed in Meters Per Second.", "default": null}, diff --git a/commons/push/integration/garmin/garmin_push_body_battery_sample.avsc b/commons/push/integration/garmin/garmin_push_body_battery_sample.avsc new file mode 100644 index 00000000..193be9ab --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_body_battery_sample.avsc @@ -0,0 +1,12 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminBodyBatterySample", + "type": "record", + "doc": "Body battery value recorded for the time. Usually assocaited with Stress Details Summary using summaryId. Information on and a list of devices that support Body Battery are available here: https://support.garmin.com/ms-MY/?faq=2qczgfbN00AIMJbX33dRq9.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, + {"name": "time", "type": "double", "doc": "Start time of the sample in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time this sample was recieved by the push service in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "bodyBattery", "type": ["null", "double"], "doc": "Body battery value recorded for the time", "default": null} + ] +} diff --git a/commons/push/integration/garmin/garmin_push_daily_summary.avsc b/commons/push/integration/garmin/garmin_push_daily_summary.avsc index 506f8b96..0285185f 100644 --- a/commons/push/integration/garmin/garmin_push_daily_summary.avsc +++ b/commons/push/integration/garmin/garmin_push_daily_summary.avsc @@ -24,7 +24,6 @@ {"name": "averageHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, {"name": "maxHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, {"name": "restingHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average heart rate at rest during the monitoring period, in beats per minute.", "default": null}, - {"name": "timeOffsetHeartRateSamples", "type": {"type": "map","values" : "double", "default": {}}, "doc": "Collection of mappings between offset from start time (in seconds) to a heart rate value recorded for that time, in beats per minute. Each entry is a representative sample of the previous 15 seconds from the given offset. Lack of entry for a given offset should be interpreted as no data available."}, {"name": "averageStressLevel", "type": ["null", "int"], "doc": "An abstraction of the user’s average stress level in this monitoring period, measured from 1 to 100, or -1 if there is not enough data to calculate average stress. Scores between 1 and 25 are considered “rest” (i.e not stressful), 26-50 as “low” stress, 51-75 “medium” stress, and 76-100 as “high” stress.", "default": null}, {"name": "maxStressLevel", "type": ["null", "int"], "doc": "The highest stress level measurement taken during this monitoring period.", "default": null}, {"name": "stressDurationInSeconds", "type": ["null", "int"], "doc": "The number of seconds in this monitoring period where stress level measurements were in the stressful range (26-100).", "default": null}, diff --git a/commons/push/integration/garmin/garmin_push_heart_rate_sample.avsc b/commons/push/integration/garmin/garmin_push_heart_rate_sample.avsc new file mode 100644 index 00000000..b6a095ce --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_heart_rate_sample.avsc @@ -0,0 +1,12 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminHeartRateSample", + "type": "record", + "doc": "Mapping between time (in seconds) to a heart rate value recorded for the time, in beats per minute. Each entry is a representative sample of the previous 15 seconds from the given time. Lack of entry for a given time should be interpreted as no data available. These are accompanied with the Dailies data and can be associated using the summaryId.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, + {"name": "time", "type": "double", "doc": "Start time of the sample in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time this sample was recieved by the push service in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "heartrate", "type": ["null", "double"], "doc": "Heart rate in beats per minute.", "default": null} + ] +} diff --git a/commons/push/integration/garmin/garmin_push_pulse_ox.avsc b/commons/push/integration/garmin/garmin_push_pulse_ox.avsc index 2b8581da..2727a465 100644 --- a/commons/push/integration/garmin/garmin_push_pulse_ox.avsc +++ b/commons/push/integration/garmin/garmin_push_pulse_ox.avsc @@ -2,7 +2,7 @@ "namespace": "org.radarcns.push.integration.garmin", "name": "GarminPulseOx", "type": "record", - "doc": "Pulse Ox summaries contain blood oxygen saturation data. Two types of data are represented in Pulse Ox summaries based on the capabilities of the user’s device. If the onDemand field is not present or set to false, the timeOffsetSpo2Values map contains an SpO2 measurement that is an average of all measurements taken as part of the Acclimation feature (https://www8.garmin.com/manuals/webhelp/fenix5plus/EN-US/GUID-4D425925-D4EE-4C26-B974- 5375D0670860.html). If the onDemand field is true the timeOffsetSpo2Values map instead contains one or more exact measurements taken by a device that is capable of on-demand measurements but not the Acclimation feature, such as the Vivosmart 4. Backfill is supported for Pulse Ox summaries, but only for Acclimation data.", + "doc": "Pulse Ox summaries contain blood oxygen saturation data. Two types of data are represented in Pulse Ox summaries based on the capabilities of the user’s device. If the onDemand field is not present or set to false, the spo2Values contains an SpO2 measurement that is an average of all measurements taken as part of the Acclimation feature (https://www8.garmin.com/manuals/webhelp/fenix5plus/EN-US/GUID-4D425925-D4EE-4C26-B974- 5375D0670860.html). If the onDemand field is true the spo2Values instead contains one or more exact measurements taken by a device that is capable of on-demand measurements but not the Acclimation feature, such as the Vivosmart 4. There maybe multiple records of spo2Value for the same summaryId. These may also be associated with Sleep summaries using summaryId. Backfill is supported for Pulse Ox summaries, but only for Acclimation data.", "fields": [ {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, @@ -10,7 +10,7 @@ {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, - {"name": "timeOffsetSpo2Values", "type": { "type": "map", "values": "double", "default": {}}, "doc": "Collection of key-value pairs where the key is offset in seconds from the startTimeInSeconds and the value is the SpO2 measurement taken at that time (1 sample/minute)"}, + {"name": "spo2Value", "type": ["null", "double"], "doc": "The SpO2 measurement taken at the time (1 sample/minute)", "default": null}, {"name": "onDemand", "type": ["null", "boolean"], "doc": "A Boolean to show whether this pulse ox summary represents an on- demand reading or an averaged acclimation reading.", "default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_respiration.avsc b/commons/push/integration/garmin/garmin_push_respiration.avsc index e0958dde..6f7c143f 100644 --- a/commons/push/integration/garmin/garmin_push_respiration.avsc +++ b/commons/push/integration/garmin/garmin_push_respiration.avsc @@ -2,13 +2,13 @@ "namespace": "org.radarcns.push.integration.garmin", "name": "GarminRespiration", "type": "record", - "doc": "Respiration is a feature (https://www8.garmin.com/manuals/webhelp/vivoactive4_4S/EN-US/GUID-252F74B6-C24B-495B-8E73-4BD595CA7FE3.html) available on some Garmin devices that tracks breathing rate throughout the day, during sleep, and during activities such as breathwork and yoga.", + "doc": "Respiration is a feature (https://www8.garmin.com/manuals/webhelp/vivoactive4_4S/EN-US/GUID-252F74B6-C24B-495B-8E73-4BD595CA7FE3.html) available on some Garmin devices that tracks breathing rate throughout the day, during sleep, and during activities such as breathwork and yoga. There maybe multiple records of respiration values for the same summaryId. These may also be associated with Sleep summaries using summaryId.", "fields": [ {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, - {"name": "timeOffsetEpochToBreaths", "type": { "type": "map", "values": "double", "default": {}}, "doc": "Collection of key-value pairs where the key is offset in seconds from the startTimeInSeconds and respiration measurement taken at that time. Respiration measurement is in breaths per minute."} + {"name": "respirationInBreathsPerMinute", "type": ["null", "double"], "doc": "Respiration measurement in breaths per minute.","default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_sleep_level.avsc b/commons/push/integration/garmin/garmin_push_sleep_level.avsc new file mode 100644 index 00000000..c368de00 --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_sleep_level.avsc @@ -0,0 +1,12 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminSleepLevel", + "type": "record", + "doc": "Sleep level time ranges, currently deep, light, rem and awake. Time ranges are represented as unix timestamps in seconds. Usually associated with Sleep Summary data using the summaryId field.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this record is associated with."}, + {"name": "sleepLevel", "type": "string", "doc":"Sleep levels, currently deep, light, rem and awake."}, + {"name": "startTimeInSeconds", "type": "double", "doc": "Start time of this sleep period in seconds."}, + {"name": "endTimeInSeconds", "type": "double", "doc": "End time of this sleep period in seconds."} + ] +} diff --git a/commons/push/integration/garmin/garmin_push_sleep_levels_map.avsc b/commons/push/integration/garmin/garmin_push_sleep_levels_map.avsc deleted file mode 100644 index 9477a5f7..00000000 --- a/commons/push/integration/garmin/garmin_push_sleep_levels_map.avsc +++ /dev/null @@ -1,21 +0,0 @@ -{ - "namespace": "org.radarcns.push.integration.garmin", - "name": "GarminSleepLevelsMap", - "type": "record", - "doc": "A map of sleep level time ranges, currently deep, light, rem and awake. Time ranges are represented as unix timestamps in seconds.", - "fields": [ - {"name": "deep", "type": { "type": "array", "items": { - "name": "GarminSleepLevelsMapValue", - "type": "record", - "doc": "The list of time periods for this sleep type.", - "fields": [ - {"name": "startTimeInSeconds", "type": "double", "doc": "Start time of this sleep period in seconds."}, - {"name": "endTimeInSeconds", "type": "double", "doc": "End time of this sleep period in seconds."} - ] - }, "default": [] }, - "doc": "Time ranges for the deep sleep periods."}, - {"name": "light", "type": { "type": "array", "items": "GarminSleepLevelsMapValue", "default": [] }, "doc": "Time ranges for the light sleep periods."}, - {"name": "awake", "type": { "type": "array", "items": "GarminSleepLevelsMapValue", "default": [] }, "doc": "Time ranges for the awake sleep periods."}, - {"name": "rem", "type": { "type": "array", "items": "GarminSleepLevelsMapValue", "default": [] }, "doc": "Time ranges for the rem sleep periods."} - ] -} diff --git a/commons/push/integration/garmin/garmin_push_sleep_summary.avsc b/commons/push/integration/garmin/garmin_push_sleep_summary.avsc index 4214628f..769ebef9 100644 --- a/commons/push/integration/garmin/garmin_push_sleep_summary.avsc +++ b/commons/push/integration/garmin/garmin_push_sleep_summary.avsc @@ -15,9 +15,6 @@ {"name": "lightSleepDurationInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent in light sleep during the sleep period.", "default": null}, {"name": "remSleepInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent in REM sleep during the sleep period.", "default": null}, {"name": "awakeDurationInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent awake during the sleep period.", "default": null}, - {"name": "sleepLevelsMap", "type": ["null", "GarminSleepLevelsMap"], "doc": "A map of sleep level time ranges, currently deep, light, rem and awake. Time ranges are represented as unix timestamps in seconds.", "default": null}, - {"name": "validation", "type": ["null", "string"], "doc": "String that relays the validation state of the sleep data and its date range. The data could be auto-confirmed, but the sleep window could have been manually adjusted, or the sleep data itself is entirely manually entered. Possible values: MANUAL: The user entered sleep start and stop times manually through a web form. There is no device data backing up the sleep assessment. DEVICE: The user used a device with the sleep feature to manually start and stop sleep. This type still requires manual user intervention to judge sleep start and stop. AUTO_TENTATIVE: The sleep start and stop times were auto-detected by Garmin Connect using accelerometer data. However, it is possible that further refinements to this sleep record will come later. This could be because the user is still asleep or could be because the user owns multiple devices and might sync another device later for this same time period. AUTO_FINAL: The sleep start and stop times were auto-detected by Garmin Connect, and enough data has been gathered to finalize the window. This status also indicates that the user only has one device so this record can never be updated again – users that own multiple devices will never get an AUTO_FINAL. AUTO_MANUAL: Sleep data was auto-detected by Garmin Connect, but the user is overriding the start and stop times or the user started with a manual entry and the sleep was auto-detected later. Garmin Connect stores both but will display the manual start and stop times in favor of the auto-detected times. ENHANCED_TENTATIVE: Sleep data was collected from a device capable of running an enhanced sleep analysis to detect REM sleep, but an updated sleep summary record may come later with further refinements or a greater sleep period. ENHANCED_FINAL: Sleep data was collected from a device capable of running an enhanced sleep analysis to detect REM sleep, and no further updates or refinements to this sleep analysis are expected.", "default": null}, - {"name": "timeOffsetSleepRespiration", "type": { "type": "map", "values": "double", "default": {}}, "doc": "Collection of key-value pairs where the key is offset in seconds from the startTimeInSeconds and respiration measurement taken at that time. Respiration measurement is in breaths per minute."}, - {"name": "timeOffsetSleepSpo2", "type": { "type": "map", "values": "double", "default": {}}, "doc": "A map of SpO2 readings, where the keys are the offsets in seconds from the startTimeInSeconds and the values are the SpO2 measurements at that time. Only present if the user’s device is SpO2-enabled."} + {"name": "validation", "type": ["null", "string"], "doc": "String that relays the validation state of the sleep data and its date range. The data could be auto-confirmed, but the sleep window could have been manually adjusted, or the sleep data itself is entirely manually entered. Possible values: MANUAL: The user entered sleep start and stop times manually through a web form. There is no device data backing up the sleep assessment. DEVICE: The user used a device with the sleep feature to manually start and stop sleep. This type still requires manual user intervention to judge sleep start and stop. AUTO_TENTATIVE: The sleep start and stop times were auto-detected by Garmin Connect using accelerometer data. However, it is possible that further refinements to this sleep record will come later. This could be because the user is still asleep or could be because the user owns multiple devices and might sync another device later for this same time period. AUTO_FINAL: The sleep start and stop times were auto-detected by Garmin Connect, and enough data has been gathered to finalize the window. This status also indicates that the user only has one device so this record can never be updated again – users that own multiple devices will never get an AUTO_FINAL. AUTO_MANUAL: Sleep data was auto-detected by Garmin Connect, but the user is overriding the start and stop times or the user started with a manual entry and the sleep was auto-detected later. Garmin Connect stores both but will display the manual start and stop times in favor of the auto-detected times. ENHANCED_TENTATIVE: Sleep data was collected from a device capable of running an enhanced sleep analysis to detect REM sleep, but an updated sleep summary record may come later with further refinements or a greater sleep period. ENHANCED_FINAL: Sleep data was collected from a device capable of running an enhanced sleep analysis to detect REM sleep, and no further updates or refinements to this sleep analysis are expected.", "default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc b/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc index b15e3654..5f2e68cd 100644 --- a/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc +++ b/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc @@ -9,8 +9,6 @@ {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, - {"name": "timeOffsetStressLevelValues", "type": { "type": "map", "values": "double", "default": {}}, "doc": "Collection of mappings between offset from start time (in seconds) to a stress level value recorded for that time."}, - {"name": "timeOffsetBodyBatteryValues", "type": { "type": "map", "values": "double", "default": {}}, "doc": "Collection of mappings between offset from start time (in seconds) to a body battery value recorded for that time. Information on and a list of devices that support Body Battery are available here: https://support.garmin.com/ms-MY/?faq=2qczgfbN00AIMJbX33dRq9."} + {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_stress_level_sample.avsc b/commons/push/integration/garmin/garmin_push_stress_level_sample.avsc new file mode 100644 index 00000000..543288eb --- /dev/null +++ b/commons/push/integration/garmin/garmin_push_stress_level_sample.avsc @@ -0,0 +1,12 @@ +{ + "namespace": "org.radarcns.push.integration.garmin", + "name": "GarminStressLevelSample", + "type": "record", + "doc": "Stress levels are provided as 3-minute averages of the real-time stress scores generated on the device with values ranging from 1 to 100. A value of -1 means there was not enough data to detect stress, and -2 means there was too much motion (e.g. the user was walking or running). Scores between 1 and 25 are considered “rest” (i.e. not stressful), 26-50 as “low” stress, 51-75 “medium” stress, and 76- 100 as “high” stress. These numbers are derived based on a combination of many device sensors and will automatically adjust to the wearer of the device and gain accuracy over time as the stress algorithms learn the user’s natural biometric norms. Usually assocaited with Stress Details Summary using the summaryId. Stress values from the Health API are exactly the stress values shown on Garmin Connect.", + "fields": [ + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, + {"name": "time", "type": "double", "doc": "Start time of the sample in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time this sample was recieved by the push service in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "stressLevel", "type": ["null", "double"], "doc": "Stress level value recorded for the time..", "default": null} + ] +} \ No newline at end of file From 31dd9690dda7ca006d3b072445a0ab4ba4182b1f Mon Sep 17 00:00:00 2001 From: yatharthranjan Date: Mon, 2 Nov 2020 12:13:44 +0000 Subject: [PATCH 04/12] Changes to schemas based on PR comments. --- .../garmin/garmin_push_activity_details.avsc | 40 +++++++++---------- .../garmin_push_activity_details_sample.avsc | 30 +++++++------- .../garmin/garmin_push_activity_summary.avsc | 40 +++++++++---------- .../garmin_push_body_battery_sample.avsc | 4 +- .../garmin/garmin_push_body_composition.avsc | 16 ++++---- .../garmin/garmin_push_daily_summary.avsc | 38 +++++++++--------- .../garmin/garmin_push_epoch_summary.avsc | 18 ++++----- .../garmin/garmin_push_heart_rate_sample.avsc | 4 +- .../garmin/garmin_push_move_iq_summary.avsc | 10 ++--- .../garmin/garmin_push_pulse_ox.avsc | 10 ++--- .../garmin/garmin_push_respiration.avsc | 8 ++-- .../garmin/garmin_push_sleep_level.avsc | 6 ++- .../garmin/garmin_push_sleep_summary.avsc | 20 +++++----- .../garmin_push_stress_detail_summary.avsc | 8 ++-- .../garmin_push_stress_level_sample.avsc | 4 +- .../garmin/garmin_push_user_metrics.avsc | 8 ++-- 16 files changed, 133 insertions(+), 131 deletions(-) diff --git a/commons/push/integration/garmin/garmin_push_activity_details.avsc b/commons/push/integration/garmin/garmin_push_activity_details.avsc index fbf21cfc..63a3ade4 100644 --- a/commons/push/integration/garmin/garmin_push_activity_details.avsc +++ b/commons/push/integration/garmin/garmin_push_activity_details.avsc @@ -4,31 +4,31 @@ "type": "record", "doc": "Fitness activity details summaries represent detailed information about discrete fitness activities, such as running or swimming, that are specifically and intentionally started by the user on their device. All wellness data, like steps and distance, contained in the activity are already represented in the Daily summary and in the corresponding Epoch summaries, so Activity Detail summaries should only be used for programs that wish to treat specific activity types in different ways, such as giving the user extra credit for going swimming three times in the same week. Activity details summaries include all data recorded by the device as part of the Fitness Activity, including GPS coordinates and all recorded sensor data. ", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, - {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type. See Appendix A for a complete list.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds.", "default": null}, - {"name": "averageBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Average Bike Cadence in rounds per minute.", "default": null}, - {"name": "maxBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Maximum Bike Cadence in rounds per minute.", "default": null}, - {"name": "distanceInMeters", "type": ["null", "double"], "doc": "Distance traveled in meters.", "default": null}, - {"name": "averageRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Average Run Cadence in Steps per minute.", "default": null}, - {"name": "maxRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Maximum Run Cadence in Steps per minute.", "default": null}, + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "startTimeOffset", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type. See Appendix A for a complete list. e.g - SEDENTARY, SLEEP, RUNNING, CYCLING, WALKING, etc.", "default": null}, + {"name": "duration", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds.", "default": null}, + {"name": "averageBikeCadence", "type": ["null", "float"], "doc": "Average Bike Cadence in rounds per minute.", "default": null}, + {"name": "maxBikeCadence", "type": ["null", "float"], "doc": "Maximum Bike Cadence in rounds per minute.", "default": null}, + {"name": "distance", "type": ["null", "float"], "doc": "Distance traveled in meters.", "default": null}, + {"name": "averageRunCadence", "type": ["null", "float"], "doc": "Average Run Cadence in Steps per minute.", "default": null}, + {"name": "maxRunCadence", "type": ["null", "float"], "doc": "Maximum Run Cadence in Steps per minute.", "default": null}, {"name": "activeKilocalories", "type": ["null", "int"], "doc": "Active kilocalories (dietary calories) burned through actual movement and activity during the monitoring period.", "default": null}, - {"name": "averageSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Average Speed in meters per second.", "default": null}, - {"name": "maxSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Maximum Speed in meters per second.", "default": null}, - {"name": "averageSwimCadenceInStrokesPerMinute", "type": ["null", "double"], "doc": "Average Swim Cadence in strokes per minute.", "default": null}, - {"name": "averagePaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Average Pace in minutes per kilometer.", "default": null}, - {"name": "maxPaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Maximum Pace in minutes per kilometer.", "default": null}, + {"name": "averageSpeed", "type": ["null", "float"], "doc": "Average Speed in meters per second.", "default": null}, + {"name": "maxSpeed", "type": ["null", "float"], "doc": "Maximum Speed in meters per second.", "default": null}, + {"name": "averageSwimCadence", "type": ["null", "float"], "doc": "Average Swim Cadence in strokes per minute.", "default": null}, + {"name": "averagePace", "type": ["null", "float"], "doc": "Average Pace in minutes per kilometer.", "default": null}, + {"name": "maxPace", "type": ["null", "float"], "doc": "Maximum Pace in minutes per kilometer.", "default": null}, {"name": "numberOfActiveLengths", "type": ["null", "int"], "doc": "Number of Active Lengths.", "default": null}, - {"name": "averageHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, - {"name": "maxHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, - {"name": "startingLatitudeInDegree", "type": ["null", "double"], "doc": "Starting Latitude in Degree", "default": null}, - {"name": "startingLongitudeInDegree", "type": ["null", "double"], "doc": "Starting Longitude in Degree", "default": null}, + {"name": "averageHeartRate", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, + {"name": "maxHeartRate", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, + {"name": "startingLatitude", "type": ["null", "float"], "doc": "Starting Latitude in Degree", "default": null}, + {"name": "startingLongitude", "type": ["null", "float"], "doc": "Starting Longitude in Degree", "default": null}, {"name": "steps", "type": ["null", "int"], "doc": "Count of steps recorded during the monitoring period.", "default": null}, - {"name": "totalElevationGainInMeters", "type": ["null", "double"], "doc": "Total Elevation Gain in meters", "default": null}, - {"name": "totalElevationLossInMeters", "type": ["null", "double"], "doc": "Total Elevation Loss in meters", "default": null}, + {"name": "totalElevationGain", "type": ["null", "float"], "doc": "Total Elevation Gain in meters", "default": null}, + {"name": "totalElevationLoss", "type": ["null", "float"], "doc": "Total Elevation Loss in meters", "default": null}, {"name": "isParent", "type": ["null", "boolean"], "doc": "If present and set to true, this activity is the parent activity of one or more child activities that should also be made available in the data feed to the partner. An activity of type MULTI_SPORT is an example of a parent activity.", "default": null}, {"name": "parentSummaryId", "type": ["null", "string"], "doc": "If present, this is the summaryId of the related parent activity. An activity of type CYCLING with a parent activity of type MULTI_SPORT is an example of this type of relationship.", "default": null}, {"name": "manual", "type": ["null", "boolean"], "doc": "Indicates that the activity was manually entered directly on the Connect site. This property will only exist for manual activities.", "default": null}, diff --git a/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc b/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc index 9a66720f..97d479de 100644 --- a/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc +++ b/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc @@ -4,22 +4,22 @@ "type": "record", "doc": "Each activity detail contains an activity summary and an optional list of samples. The samples list will be empty if the activity is manual or details are not supported by the device. Samples may be as frequent as once per second, and values should be considered valid until the next sample. In all cases, movingDurationInSeconds is less than or equal to timerDurationInSeconds is less than or equal to clockDurationInSeconds.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, {"name": "time", "type": "double", "doc": "Start time of the sample in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time this sample was recieved by the push service in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, - {"name": "airTemperatureCelcius", "type": ["null", "double"], "doc": "Air Temperature in Celcius.", "default": null}, - {"name": "heartrate", "type": ["null", "int"], "doc": "Heart rate in beats per minute.", "default": null}, - {"name": "speedMetersPerSecond", "type": ["null", "double"], "doc": "Speed in Meters Per Second.", "default": null}, - {"name": "stepsPerMinute", "type": ["null", "double"], "doc": "Number of steps per minute.", "default": null}, - {"name": "totalDistanceInMeters", "type": ["null", "double"], "doc": "Total Distance in Meters.", "default": null}, - {"name": "timerDurationInSeconds", "type": ["null", "int"], "doc": "The amount of 'timer time' in an activity.", "default": null}, - {"name": "clockDurationInSeconds", "type": ["null", "int"], "doc": "The amount of real-world 'clock time' from the start of an activity to the end.", "default": null}, - {"name": "movingDurationInSeconds", "type": ["null", "int"], "doc": "The amount of 'timer time' during which the athlete was moving (above a threshold speed).", "default": null}, - {"name": "powerInWatts", "type": ["null", "double"], "doc": "The amount of power expended in watts.", "default": null}, - {"name": "bikeCadenceInRPM", "type": ["null", "int"], "doc": "Cycling cadence in revolutions per minute.", "default": null}, - {"name": "swimCadenceInStrokesPerMinute", "type": ["null", "int"], "doc": "Swim cadence in strokes per minute.", "default": null}, - {"name": "latitudeInDegree", "type": ["null", "double"], "doc": "Latitude in decimal degrees (DD)", "default": null}, - {"name": "longitudeInDegree", "type": ["null", "double"], "doc": "Longitude in decimal degrees (DD)", "default": null}, - {"name": "elevationInMeters", "type": ["null", "double"], "doc": "Elevation in meters", "default": null} + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, + {"name": "airTemperature", "type": ["null", "float"], "doc": "Air Temperature in Celcius.", "default": null}, + {"name": "heartRate", "type": ["null", "int"], "doc": "Heart rate in beats per minute.", "default": null}, + {"name": "speed", "type": ["null", "double"], "doc": "Speed in Meters Per Second.", "default": null}, + {"name": "stepsPerMinute", "type": ["null", "float"], "doc": "Number of steps per minute.", "default": null}, + {"name": "totalDistance", "type": ["null", "float"], "doc": "Total Distance in Meters.", "default": null}, + {"name": "timerDuration", "type": ["null", "int"], "doc": "The amount of 'timer time' in an activity.", "default": null}, + {"name": "clockDuration", "type": ["null", "int"], "doc": "The amount of real-world 'clock time' from the start of an activity to the end.", "default": null}, + {"name": "movingDuration", "type": ["null", "int"], "doc": "The amount of 'timer time' during which the athlete was moving (above a threshold speed).", "default": null}, + {"name": "power", "type": ["null", "float"], "doc": "The amount of power expended in watts.", "default": null}, + {"name": "bikeCadence", "type": ["null", "int"], "doc": "Cycling cadence in revolutions per minute.", "default": null}, + {"name": "swimCadence", "type": ["null", "int"], "doc": "Swim cadence in strokes per minute.", "default": null}, + {"name": "latitude", "type": ["null", "float"], "doc": "Latitude in decimal degrees (DD)", "default": null}, + {"name": "longitude", "type": ["null", "float"], "doc": "Longitude in decimal degrees (DD)", "default": null}, + {"name": "elevation", "type": ["null", "float"], "doc": "Elevation in meters", "default": null} ] } diff --git a/commons/push/integration/garmin/garmin_push_activity_summary.avsc b/commons/push/integration/garmin/garmin_push_activity_summary.avsc index a8d21787..5fec7d2f 100644 --- a/commons/push/integration/garmin/garmin_push_activity_summary.avsc +++ b/commons/push/integration/garmin/garmin_push_activity_summary.avsc @@ -4,31 +4,31 @@ "type": "record", "doc": "Fitness activity summaries represent high-level information from discrete fitness activities, such as running or swimming, that are specifically and intentionally started by the user on their device. All wellness data, like steps and distance, contained in the Activity are already represented in the Daily summary and in the corresponding Epoch summaries, so Activity summaries should only be used for programs that wish to treat specific activity types in different ways, such as giving the user extra credit for going swimming three times in the same week.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, - {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type. See Appendix A for a complete list.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, - {"name": "averageBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Average Bike Cadence in rounds per minute.", "default": null}, - {"name": "maxBikeCadenceInRoundsPerMinute", "type": ["null", "double"], "doc": "Maximum Bike Cadence in rounds per minute.", "default": null}, - {"name": "distanceInMeters", "type": ["null", "double"], "doc": "Distance traveled in meters.", "default": null}, - {"name": "averageRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Average Run Cadence in Steps per minute.", "default": null}, - {"name": "maxRunCadenceInStepsPerMinute", "type": ["null", "double"], "doc": "Maximum Run Cadence in Steps per minute.", "default": null}, + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "startTimeOffset", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type. e.g - SEDENTARY, SLEEP, RUNNING, CYCLING, WALKING, etc.", "default": null}, + {"name": "duration", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "averageBikeCadence", "type": ["null", "float"], "doc": "Average Bike Cadence in rounds per minute.", "default": null}, + {"name": "maxBikeCadenceInRounds", "type": ["null", "float"], "doc": "Maximum Bike Cadence in rounds per minute.", "default": null}, + {"name": "distance", "type": ["null", "float"], "doc": "Distance traveled in meters.", "default": null}, + {"name": "averageRunCadence", "type": ["null", "float"], "doc": "Average Run Cadence in Steps per minute.", "default": null}, + {"name": "maxRunCadence", "type": ["null", "float"], "doc": "Maximum Run Cadence in Steps per minute.", "default": null}, {"name": "activeKilocalories", "type": ["null", "int"], "doc": "Active kilocalories (dietary calories) burned through actual movement and activity during the monitoring period.", "default": null}, - {"name": "averageSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Average Speed in meters per second.", "default": null}, - {"name": "maxSpeedInMetersPerSecond", "type": ["null", "double"], "doc": "Maximum Speed in meters per second.", "default": null}, - {"name": "averageSwimCadenceInStrokesPerMinute", "type": ["null", "double"], "doc": "Average Swim Cadence in strokes per minute.", "default": null}, - {"name": "averagePaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Average Pace in minutes per kilometer.", "default": null}, - {"name": "maxPaceInMinutesPerKilometer", "type": ["null", "double"], "doc": "Maximum Pace in minutes per kilometer.", "default": null}, + {"name": "averageSpeed", "type": ["null", "float"], "doc": "Average Speed in meters per second.", "default": null}, + {"name": "maxSpeed", "type": ["null", "float"], "doc": "Maximum Speed in meters per second.", "default": null}, + {"name": "averageSwimCadence", "type": ["null", "float"], "doc": "Average Swim Cadence in strokes per minute.", "default": null}, + {"name": "averagePace", "type": ["null", "float"], "doc": "Average Pace in minutes per kilometer.", "default": null}, + {"name": "maxPace", "type": ["null", "float"], "doc": "Maximum Pace in minutes per kilometer.", "default": null}, {"name": "numberOfActiveLengths", "type": ["null", "int"], "doc": "Number of Active Lengths.", "default": null}, - {"name": "averageHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, - {"name": "maxHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, - {"name": "startingLatitudeInDegree", "type": ["null", "double"], "doc": "Starting Latitude in Degree", "default": null}, - {"name": "startingLongitudeInDegree", "type": ["null", "double"], "doc": "Starting Longitude in Degree", "default": null}, + {"name": "averageHeartRate", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, + {"name": "maxHeartRate", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, + {"name": "startingLatitude", "type": ["null", "float"], "doc": "Starting Latitude in Degree", "default": null}, + {"name": "startingLongitude", "type": ["null", "float"], "doc": "Starting Longitude in Degree", "default": null}, {"name": "steps", "type": ["null", "int"], "doc": "Count of steps recorded during the monitoring period.", "default": null}, - {"name": "totalElevationGainInMeters", "type": ["null", "double"], "doc": "Total Elevation Gain in meters", "default": null}, - {"name": "totalElevationLossInMeters", "type": ["null", "double"], "doc": "Total Elevation Loss in meters", "default": null}, + {"name": "totalElevationGain", "type": ["null", "float"], "doc": "Total Elevation Gain in meters", "default": null}, + {"name": "totalElevationLoss", "type": ["null", "float"], "doc": "Total Elevation Loss in meters", "default": null}, {"name": "isParent", "type": ["null", "boolean"], "doc": "If present and set to true, this activity is the parent activity of one or more child activities that should also be made available in the data feed to the partner. An activity of type MULTI_SPORT is an example of a parent activity.", "default": null}, {"name": "parentSummaryId", "type": ["null", "string"], "doc": "If present, this is the summaryId of the related parent activity. An activity of type CYCLING with a parent activity of type MULTI_SPORT is an example of this type of relationship.", "default": null}, {"name": "manual", "type": ["null", "boolean"], "doc": "Indicates that the activity was manually entered directly on the Connect site. This property will only exist for manual activities.", "default": null}, diff --git a/commons/push/integration/garmin/garmin_push_body_battery_sample.avsc b/commons/push/integration/garmin/garmin_push_body_battery_sample.avsc index 193be9ab..0cb5287c 100644 --- a/commons/push/integration/garmin/garmin_push_body_battery_sample.avsc +++ b/commons/push/integration/garmin/garmin_push_body_battery_sample.avsc @@ -4,9 +4,9 @@ "type": "record", "doc": "Body battery value recorded for the time. Usually assocaited with Stress Details Summary using summaryId. Information on and a list of devices that support Body Battery are available here: https://support.garmin.com/ms-MY/?faq=2qczgfbN00AIMJbX33dRq9.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, {"name": "time", "type": "double", "doc": "Start time of the sample in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time this sample was recieved by the push service in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, - {"name": "bodyBattery", "type": ["null", "double"], "doc": "Body battery value recorded for the time", "default": null} + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, + {"name": "bodyBattery", "type": ["null", "float"], "doc": "Body battery value recorded for the time", "default": null} ] } diff --git a/commons/push/integration/garmin/garmin_push_body_composition.avsc b/commons/push/integration/garmin/garmin_push_body_composition.avsc index 857bb8ad..e1840fd2 100644 --- a/commons/push/integration/garmin/garmin_push_body_composition.avsc +++ b/commons/push/integration/garmin/garmin_push_body_composition.avsc @@ -4,15 +4,15 @@ "type": "record", "doc": "Body Composition summaries contain information about the user’s biometric data, like weight or body mass index. This data can be generated three ways. Users can manually enter their weight on Garmin Connect. This results in a summary with only time and weight. Users may also connect their MyFitnessPal account to their Garmin Connect account and update their weight on MyFitnessPal. This results in a summary that also just has a time and weight. Finally, a user might have a Garmin Index body composition scale and sync data from this device. This will generate a summary with all possible biometric fields.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "muscleMassInGrams", "type": ["null", "int"], "doc": "Muscle mass in grams.", "default": null}, - {"name": "boneMassInGrams", "type": ["null", "int"], "doc": "Bone mass in grams.", "default": null}, - {"name": "measurementTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, - {"name": "bodyWaterInPercent", "type": ["null", "double"], "doc": "Percentage of body water (range 0.0 - 100.0).", "default": null}, - {"name": "bodyFatInPercent", "type": ["null", "double"], "doc": "Percentage of body fat. (range 0.0 - 100.0).", "default": null}, - {"name": "bodyMassIndex", "type": ["null", "double"], "doc": "Body mass index, or BMI.", "default": null}, - {"name": "weightInGrams", "type": ["null", "int"], "doc": "Weight in grams.", "default": null} + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "muscleMass", "type": ["null", "int"], "doc": "Muscle mass in grams.", "default": null}, + {"name": "boneMass", "type": ["null", "int"], "doc": "Bone mass in grams.", "default": null}, + {"name": "measurementTimeOffset", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "bodyWater", "type": ["null", "float"], "doc": "Percentage of body water (range 0.0 - 100.0).", "default": null}, + {"name": "bodyFat", "type": ["null", "float"], "doc": "Percentage of body fat. (range 0.0 - 100.0).", "default": null}, + {"name": "bodyMassIndex", "type": ["null", "float"], "doc": "Body mass index, or BMI.", "default": null}, + {"name": "weight", "type": ["null", "int"], "doc": "Weight in grams.", "default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_daily_summary.avsc b/commons/push/integration/garmin/garmin_push_daily_summary.avsc index 0285185f..70f98d3c 100644 --- a/commons/push/integration/garmin/garmin_push_daily_summary.avsc +++ b/commons/push/integration/garmin/garmin_push_daily_summary.avsc @@ -4,38 +4,38 @@ "type": "record", "doc": "Daily summaries offer a high-level view of the user’s entire day. They generally correspond to the data found on the “My Day” section of Garmin Connect. Daily summaries are the most commonly used and are often the foundation of a Health API integration.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, - {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "date", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect in the local time zone of the device. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "startTimeOffset", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, {"name": "activityType", "type": ["null", "string"], "doc": "This field is included in daily summaries for backwards compatibility purposes. It can be ignored and will always default to WALKING.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "duration", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, {"name": "steps", "type": ["null", "int"], "doc": "Count of steps recorded during the monitoring period.", "default": null}, - {"name": "distanceInMeters", "type": ["null", "double"], "doc": "Distance traveled in meters.", "default": null}, - {"name": "activeTimeInSeconds", "type": ["null", "int"], "doc": "Portion of the monitoring period (in seconds) in which the device wearer was considered Active. This relies on heuristics internal to each device.", "default": null}, + {"name": "distance", "type": ["null", "float"], "doc": "Distance traveled in meters.", "default": null}, + {"name": "activeTime", "type": ["null", "int"], "doc": "Portion of the monitoring period (in seconds) in which the device wearer was considered Active. This relies on heuristics internal to each device.", "default": null}, {"name": "activeKilocalories", "type": ["null", "int"], "doc": "Active kilocalories (dietary calories) burned through actual movement and activity during the monitoring period.", "default": null}, {"name": "bmrKilocalories", "type": ["null", "int"], "doc": "BMR Kilocalories burned by existing Basal Metabolic Rate (calculated based on user height/weight/age/other demographic data).", "default": null}, {"name": "consumedCalories", "type": ["null", "int"], "doc": "The number of calories that have been consumed by the user through food for that day (value subtracted from calorie goal). This value is received from MyFitnessPal and is not entered within Connect.", "default": null}, - {"name": "moderateIntensityDurationInSeconds", "type": ["null", "int"], "doc": "Cumulative duration of activities of moderate intensity, lasting at least 600 seconds at a time. Moderate intensity is defined as activity with MET value range 3-6.", "default": null}, - {"name": "vigorousIntensityDurationInSeconds", "type": ["null", "int"], "doc": "Cumulative duration of activities of vigorous intensity, lasting at least 600 seconds at a time. Vigorous intensity is defined as activity with MET value greater than 6.", "default": null}, + {"name": "moderateIntensityDuration", "type": ["null", "int"], "doc": "Cumulative duration of activities of moderate intensity, lasting at least 600 seconds at a time. Moderate intensity is defined as activity with MET value range 3-6.", "default": null}, + {"name": "vigorousIntensityDuration", "type": ["null", "int"], "doc": "Cumulative duration of activities of vigorous intensity, lasting at least 600 seconds at a time. Vigorous intensity is defined as activity with MET value greater than 6.", "default": null}, {"name": "floorsClimbed", "type": ["null", "int"], "doc": "Number of floors climbed during the monitoring period.", "default": null}, - {"name": "minHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Minimum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, - {"name": "averageHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, - {"name": "maxHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, - {"name": "restingHeartRateInBeatsPerMinute", "type": ["null", "int"], "doc": "Average heart rate at rest during the monitoring period, in beats per minute.", "default": null}, + {"name": "minHeartRate", "type": ["null", "int"], "doc": "Minimum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, + {"name": "averageHeartRate", "type": ["null", "int"], "doc": "Average of heart rate values captured during the last 7 days, in beats per minute. The average heart rate value for the monitoring period can be calculated based on the data from timeOffsetHeartRateSamples.", "default": null}, + {"name": "maxHeartRate", "type": ["null", "int"], "doc": "Maximum of heart rate values captured during the monitoring period, in beats per minute.", "default": null}, + {"name": "restingHeartRate", "type": ["null", "int"], "doc": "Average heart rate at rest during the monitoring period, in beats per minute.", "default": null}, {"name": "averageStressLevel", "type": ["null", "int"], "doc": "An abstraction of the user’s average stress level in this monitoring period, measured from 1 to 100, or -1 if there is not enough data to calculate average stress. Scores between 1 and 25 are considered “rest” (i.e not stressful), 26-50 as “low” stress, 51-75 “medium” stress, and 76-100 as “high” stress.", "default": null}, {"name": "maxStressLevel", "type": ["null", "int"], "doc": "The highest stress level measurement taken during this monitoring period.", "default": null}, - {"name": "stressDurationInSeconds", "type": ["null", "int"], "doc": "The number of seconds in this monitoring period where stress level measurements were in the stressful range (26-100).", "default": null}, - {"name": "restStressDurationInSeconds", "type": ["null", "int"], "doc": "The number of seconds in this monitoring period where stress level measurements were in the restful range (1 to 25).", "default": null}, - {"name": "activityStressDurationInSeconds", "type": ["null", "int"], "doc": "The number of seconds in this monitoring period where the user was engaging in physical activity and so stress measurement was unreliable. All duration in this monitoring period not covered by stress, rest, and activity stress should be considered Uncategorized, either because the device was not worn or because not enough data could be taken to generate a stress score.", "default": null}, - {"name": "lowStressDurationInSeconds", "type": ["null", "int"], "doc": "The portion of the user’s stress duration where the measured stress score was in the low range (26-50).", "default": null}, - {"name": "mediumStressDurationInSeconds", "type": ["null", "int"], "doc": "The portion of the user’s stress duration where the measured stress score was in the medium range (51-75).", "default": null}, - {"name": "highStressDurationInSeconds", "type": ["null", "int"], "doc": "The portion of the user’s stress duration where the measured stress score was in the high range (76-100).", "default": null}, + {"name": "stressDuration", "type": ["null", "int"], "doc": "The number of seconds in this monitoring period where stress level measurements were in the stressful range (26-100).", "default": null}, + {"name": "restStressDuration", "type": ["null", "int"], "doc": "The number of seconds in this monitoring period where stress level measurements were in the restful range (1 to 25).", "default": null}, + {"name": "activityStressDuration", "type": ["null", "int"], "doc": "The number of seconds in this monitoring period where the user was engaging in physical activity and so stress measurement was unreliable. All duration in this monitoring period not covered by stress, rest, and activity stress should be considered Uncategorized, either because the device was not worn or because not enough data could be taken to generate a stress score.", "default": null}, + {"name": "lowStressDuration", "type": ["null", "int"], "doc": "The portion of the user’s stress duration where the measured stress score was in the low range (26-50).", "default": null}, + {"name": "mediumStressDuration", "type": ["null", "int"], "doc": "The portion of the user’s stress duration where the measured stress score was in the medium range (51-75).", "default": null}, + {"name": "highStressDuration", "type": ["null", "int"], "doc": "The portion of the user’s stress duration where the measured stress score was in the high range (76-100).", "default": null}, {"name": "stressQualifier", "type": ["null", "string"], "doc": "A qualitative label applied based on all stress measurements in this monitoring period. Possible values: unknown, calm, balanced, stressful, very_stressful, calm_awake, balanced_awake, stressful_awake, very_stressful_awake. This matches what the user will see in Garmin Connect. It is recommended that implementations that use the stressQualifier be tolerant of unknown values in case more granular values are added.", "default": null}, {"name": "stepsGoal", "type": ["null", "int"], "doc": "The user’s steps goal for this monitoring period.", "default": null}, {"name": "netKilocaloriesGoal", "type": ["null", "int"], "doc": "The user’s goal for net caloric intake (consumed calories minus active calories) for this monitoring period. This field is related to integration with MyFitnessPal and may not be present for many users.", "default": null}, - {"name": "intensityDurationGoalInSeconds", "type": ["null", "int"], "doc": "The user’s goal for consecutive seconds of moderate to vigorous intensity activity for this monitoring period.", "default": null}, + {"name": "intensityDurationGoal", "type": ["null", "int"], "doc": "The user’s goal for consecutive seconds of moderate to vigorous intensity activity for this monitoring period.", "default": null}, {"name": "floorsClimbedGoal", "type": ["null", "int"], "doc": "The user’s goal for floors climbed in this monitoring period.", "default": null}, {"name": "source", "type": ["null", "string"], "doc": "The name of the source of the third party data. For example FITBIT. Only present in Third Party summaries.", "default": null} ] diff --git a/commons/push/integration/garmin/garmin_push_epoch_summary.avsc b/commons/push/integration/garmin/garmin_push_epoch_summary.avsc index 21a03361..3d5e8c6e 100644 --- a/commons/push/integration/garmin/garmin_push_epoch_summary.avsc +++ b/commons/push/integration/garmin/garmin_push_epoch_summary.avsc @@ -4,19 +4,19 @@ "type": "record", "doc": "The Epoch Summary contains wellness data for a specific time range. Epoch summary records contain much of the same data available in Daily summaries, but with 15-minute time-slice granularity. There is one record for each activity type monitored within an individual epoch. For example, if the user was sedentary for five minutes, walked for five minutes, and then ran for five minutes over the course of 15 minutes, three activity records would be generated for that single 15-minute epoch. The duration value would be 900 seconds for all three records, but the active time for each would be 300 seconds. A duration of less than 900 seconds indicates that the user synced data during the middle of an epoch. On the user’s next sync, that epoch record will be replaced with a 900-second-duration epoch covering the entire span. As such and to accommodate users with multiple devices, it is important that new epochs always replace existing epochs that have the same startTimeInSeconds. The most recent update from the Health API will always reflect the most recent data in Garmin Connect. Epoch data is useful when attempting to construct charts showing intraday wellness data. An example of this in Garmin Connect is the Steps Details chart that graphs step count changes throughout the user’s day.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, - {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "startTimeOffset", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type. e.g - SEDENTARY, SLEEP, RUNNING, CYCLING, WALKING, etc.", "default": null}, + {"name": "duration", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, {"name": "steps", "type": ["null", "int"], "doc": "Count of steps recorded during the monitoring period.", "default": null}, - {"name": "distanceInMeters", "type": ["null", "double"], "doc": "Distance traveled in meters.", "default": null}, - {"name": "activeTimeInSeconds", "type": ["null", "int"], "doc": "Portion of the monitoring period (in seconds) in which the device wearer was active for this activity type. The sum of active times of all epochs of the same start time (and different activity types) should be equal to the duration.", "default": null}, + {"name": "distance", "type": ["null", "float"], "doc": "Distance traveled in meters.", "default": null}, + {"name": "activeTime", "type": ["null", "int"], "doc": "Portion of the monitoring period (in seconds) in which the device wearer was active for this activity type. The sum of active times of all epochs of the same start time (and different activity types) should be equal to the duration.", "default": null}, {"name": "activeKilocalories", "type": ["null", "int"], "doc": "Active kilocalories (dietary calories) burned during the monitoring period. This includes only the calories burned by the activity and not calories burned as part of the basal metabolic rate (BMR).", "default": null}, - {"name": "met", "type": ["null", "double"], "doc": "MET (Metabolic Equivalent of Task) value for the active time for this activity type. Metabolic Equivalent of Task (MET) is an official measure of activity intensity. Garmin’s calculation of MET is an estimation based on the biometric data provided (height, weight, date of birth, gender) and improves in accuracy if heart rate data is also captured. The following linked document hosted by the US Centers for Disease Control and Prevention provides detailed information on MET and physical activity intensity: http://www.cdc.gov/nccdphp/dnpa/physical/pdf/PA_Intensity_table_2_1.pdf", "default": null}, + {"name": "metabolicEquivalentOfTask", "type": ["null", "float"], "doc": "MET (Metabolic Equivalent of Task) value for the active time for this activity type. Metabolic Equivalent of Task (MET) is an official measure of activity intensity. Garmin’s calculation of MET is an estimation based on the biometric data provided (height, weight, date of birth, gender) and improves in accuracy if heart rate data is also captured. The following linked document hosted by the US Centers for Disease Control and Prevention provides detailed information on MET and physical activity intensity: http://www.cdc.gov/nccdphp/dnpa/physical/pdf/PA_Intensity_table_2_1.pdf", "default": null}, {"name": "intensity", "type": ["null", "string"], "doc": "Qualitative measure of intensity. Possible values: SEDENTARY(Little to no activity monitored. This could be due to minimal movement, sitting, resting, or sleeping.), ACTIVE(Some activity monitored. A brisk walk could achieve this intensity.), HIGHLY_ACTIVE(High activity monitored. Running or speed walking could achieve this intensity.)", "default": null}, - {"name": "meanMotionIntensity", "type": ["null", "double"], "doc": "The average of motion intensity scores for all minutes in this monitoring period. Motion Intensity is a numerical abstraction of low-level accelerometer data, provided for use in further analysis. This data is not exposed directly to the consumer by Garmin but is used in in the creation of other metrics. Motion Intensity is calculated at minute-level granularity as a number between 0 and 7, with 0 being absolutely still and 7 being constant, sharp motion. Unlike steps, distance, or activity type, which take net movement in to account, motion intensity will increase even if the user does not move in space. For instance, if a user were to jump up and down or fidget with a pencil they would not get credit for any distance, but their motion intensity scores for that monitoring period would increase. It is very common to see mid-range max motion intensities even for sedentary epochs as most people do not sit absolutely still.", "default": null}, - {"name": "maxMotionIntensity", "type": ["null", "double"], "doc": "The largest motion intensity score of any minute in this monitoring period. Motion Intensity is a numerical abstraction of low-level accelerometer data, provided for use in further analysis. This data is not exposed directly to the consumer by Garmin but is used in in the creation of other metrics. Motion Intensity is calculated at minute-level granularity as a number between 0 and 7, with 0 being absolutely still and 7 being constant, sharp motion. Unlike steps, distance, or activity type, which take net movement in to account, motion intensity will increase even if the user does not move in space. For instance, if a user were to jump up and down or fidget with a pencil they would not get credit for any distance, but their motion intensity scores for that monitoring period would increase. It is very common to see mid-range max motion intensities even for sedentary epochs as most people do not sit absolutely still.", "default": null} + {"name": "meanMotionIntensity", "type": ["null", "float"], "doc": "The average of motion intensity scores for all minutes in this monitoring period. Motion Intensity is a numerical abstraction of low-level accelerometer data, provided for use in further analysis. This data is not exposed directly to the consumer by Garmin but is used in in the creation of other metrics. Motion Intensity is calculated at minute-level granularity as a number between 0 and 7, with 0 being absolutely still and 7 being constant, sharp motion. Unlike steps, distance, or activity type, which take net movement in to account, motion intensity will increase even if the user does not move in space. For instance, if a user were to jump up and down or fidget with a pencil they would not get credit for any distance, but their motion intensity scores for that monitoring period would increase. It is very common to see mid-range max motion intensities even for sedentary epochs as most people do not sit absolutely still.", "default": null}, + {"name": "maxMotionIntensity", "type": ["null", "float"], "doc": "The largest motion intensity score of any minute in this monitoring period. Motion Intensity is a numerical abstraction of low-level accelerometer data, provided for use in further analysis. This data is not exposed directly to the consumer by Garmin but is used in in the creation of other metrics. Motion Intensity is calculated at minute-level granularity as a number between 0 and 7, with 0 being absolutely still and 7 being constant, sharp motion. Unlike steps, distance, or activity type, which take net movement in to account, motion intensity will increase even if the user does not move in space. For instance, if a user were to jump up and down or fidget with a pencil they would not get credit for any distance, but their motion intensity scores for that monitoring period would increase. It is very common to see mid-range max motion intensities even for sedentary epochs as most people do not sit absolutely still.", "default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_heart_rate_sample.avsc b/commons/push/integration/garmin/garmin_push_heart_rate_sample.avsc index b6a095ce..717ea3bd 100644 --- a/commons/push/integration/garmin/garmin_push_heart_rate_sample.avsc +++ b/commons/push/integration/garmin/garmin_push_heart_rate_sample.avsc @@ -4,9 +4,9 @@ "type": "record", "doc": "Mapping between time (in seconds) to a heart rate value recorded for the time, in beats per minute. Each entry is a representative sample of the previous 15 seconds from the given time. Lack of entry for a given time should be interpreted as no data available. These are accompanied with the Dailies data and can be associated using the summaryId.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, {"name": "time", "type": "double", "doc": "Start time of the sample in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time this sample was recieved by the push service in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, - {"name": "heartrate", "type": ["null", "double"], "doc": "Heart rate in beats per minute.", "default": null} + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, + {"name": "heartRate", "type": ["null", "float"], "doc": "Heart rate in beats per minute.", "default": null} ] } diff --git a/commons/push/integration/garmin/garmin_push_move_iq_summary.avsc b/commons/push/integration/garmin/garmin_push_move_iq_summary.avsc index 523064a9..4a3648fa 100644 --- a/commons/push/integration/garmin/garmin_push_move_iq_summary.avsc +++ b/commons/push/integration/garmin/garmin_push_move_iq_summary.avsc @@ -4,13 +4,13 @@ "type": "record", "doc": "Move IQ Event summaries are a feed of activities which have been automatically detected by the device based on movement patterns, like running or biking. These are not activities initiated by the user. Please note that wellness data, like steps and distance, from Move IQ events are already included in the Daily and Epoch summaries. Due to their automatically-detected nature, Move IQ events are not considered a fitness activity, do not contain the same details as activities, and cannot be edited by the user with Garmin Connect. These events should be considered a labeled-timespan on top of normal Daily or Epoch summary details, matching their representation within Garmin Connect. For more feature-level information on Move IQ events, please see: https://support.garmin.com/faqSearch/en- US/faq/content/zgFpy8MShkArqAxCug5wC6 . Move IQ activities are also known as Automatic Activity Detection in older devices or documentation.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, - {"name": "offsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, - {"name": "activityType", "type": ["null", "string"], "doc": "The activity type that has been identified for this timespan.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "The duration of the measurement period in seconds.", "default": null}, + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "date", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect in the local time zone of the device. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "offset", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "activityType", "type": ["null", "string"], "doc": "The activity type that has been identified for this timespan. e.g - SEDENTARY, SLEEP, RUNNING, CYCLING, WALKING, etc.", "default": null}, + {"name": "duration", "type": ["null", "int"], "doc": "The duration of the measurement period in seconds.", "default": null}, {"name": "activitySubType", "type": ["null", "string"], "doc": "The activity subtype that has been identified for this timespan.", "default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_pulse_ox.avsc b/commons/push/integration/garmin/garmin_push_pulse_ox.avsc index 2727a465..4ae3a1cf 100644 --- a/commons/push/integration/garmin/garmin_push_pulse_ox.avsc +++ b/commons/push/integration/garmin/garmin_push_pulse_ox.avsc @@ -4,13 +4,13 @@ "type": "record", "doc": "Pulse Ox summaries contain blood oxygen saturation data. Two types of data are represented in Pulse Ox summaries based on the capabilities of the user’s device. If the onDemand field is not present or set to false, the spo2Values contains an SpO2 measurement that is an average of all measurements taken as part of the Acclimation feature (https://www8.garmin.com/manuals/webhelp/fenix5plus/EN-US/GUID-4D425925-D4EE-4C26-B974- 5375D0670860.html). If the onDemand field is true the spo2Values instead contains one or more exact measurements taken by a device that is capable of on-demand measurements but not the Acclimation feature, such as the Vivosmart 4. There maybe multiple records of spo2Value for the same summaryId. These may also be associated with Sleep summaries using summaryId. Backfill is supported for Pulse Ox summaries, but only for Acclimation data.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, - {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, - {"name": "spo2Value", "type": ["null", "double"], "doc": "The SpO2 measurement taken at the time (1 sample/minute)", "default": null}, + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "startTimeOffset", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "date", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect in the local time zone of the device. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "duration", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "spo2Value", "type": ["null", "float"], "doc": "The SpO2 measurement taken at the time (1 sample/minute)", "default": null}, {"name": "onDemand", "type": ["null", "boolean"], "doc": "A Boolean to show whether this pulse ox summary represents an on- demand reading or an averaged acclimation reading.", "default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_respiration.avsc b/commons/push/integration/garmin/garmin_push_respiration.avsc index 6f7c143f..ce5ed153 100644 --- a/commons/push/integration/garmin/garmin_push_respiration.avsc +++ b/commons/push/integration/garmin/garmin_push_respiration.avsc @@ -4,11 +4,11 @@ "type": "record", "doc": "Respiration is a feature (https://www8.garmin.com/manuals/webhelp/vivoactive4_4S/EN-US/GUID-252F74B6-C24B-495B-8E73-4BD595CA7FE3.html) available on some Garmin devices that tracks breathing rate throughout the day, during sleep, and during activities such as breathwork and yoga. There maybe multiple records of respiration values for the same summaryId. These may also be associated with Sleep summaries using summaryId.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, - {"name": "respirationInBreathsPerMinute", "type": ["null", "double"], "doc": "Respiration measurement in breaths per minute.","default": null} + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "startTimeOffset", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "duration", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "respiration", "type": ["null", "float"], "doc": "Respiration measurement in breaths per minute.","default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_sleep_level.avsc b/commons/push/integration/garmin/garmin_push_sleep_level.avsc index c368de00..8a8f5b27 100644 --- a/commons/push/integration/garmin/garmin_push_sleep_level.avsc +++ b/commons/push/integration/garmin/garmin_push_sleep_level.avsc @@ -4,9 +4,11 @@ "type": "record", "doc": "Sleep level time ranges, currently deep, light, rem and awake. Time ranges are represented as unix timestamps in seconds. Usually associated with Sleep Summary data using the summaryId field.", "fields": [ + {"name": "time", "type": "double", "doc": "Start time of this sleep level in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this record is associated with."}, {"name": "sleepLevel", "type": "string", "doc":"Sleep levels, currently deep, light, rem and awake."}, - {"name": "startTimeInSeconds", "type": "double", "doc": "Start time of this sleep period in seconds."}, - {"name": "endTimeInSeconds", "type": "double", "doc": "End time of this sleep period in seconds."} + {"name": "startTime", "type": "double", "doc": "Start time of this sleep period in seconds."}, + {"name": "endTime", "type": "double", "doc": "End time of this sleep period in seconds."} ] } diff --git a/commons/push/integration/garmin/garmin_push_sleep_summary.avsc b/commons/push/integration/garmin/garmin_push_sleep_summary.avsc index 769ebef9..b1391ab2 100644 --- a/commons/push/integration/garmin/garmin_push_sleep_summary.avsc +++ b/commons/push/integration/garmin/garmin_push_sleep_summary.avsc @@ -4,17 +4,17 @@ "type": "record", "doc": "Sleep summaries are data records representing how long the user slept and the automatically classified sleep levels during that sleep event (e.g. light, deep periods) based on data generated by the user’s device. Users may generate sleep data three different ways. Some older Garmin devices (e.g. first generation vívofit) allow users to manually place the device in sleep mode. Newer devices do not have this option and instead auto-detect sleep if it occurs between the user’s Bed/Wake time range configured in Garmin Connect. Users may also self-report sleep information using Garmin Connect. Sleep records from the Health API are labelled to identify how the sleep data was generated (see below). This allows partners to accept/reject various methods of collecting Sleep data. Recommended usage for this field is to filter out validation types that are not desired rather than accept only certain validation types in order to prevent lost data in the future if new validation types are added, as by default Garmin Connect displays records of all possible types. Unlike Daily summaries which are associated with a given day on a midnight-to-midnight basis, Sleep summaries are associated with a user’s overnight sleep range. Most will start on one calendar day and end on the next calendar day, but it is possible for two different Sleep summaries to begin on the same day if, for example, the user goes to bed after midnight, wakes up, and then goes to bed prior to midnight the next evening. The sleep summary will include REM sleep if the user’s device is capable of REM sleep analysis. Users without REM-capable devices, or with REM-capable devices that have not been updated to REM-capable firmware, are limited to only deep, light, and awake sleep levels. Additionally, REM sleep will only be generated if the REM-capable devices is set as the preferred activity tracker and is actually worn during sleep. Some pulse-oximetry-enabled devices will generate SpO2 values during sleep for use in sleep analysis. If such values are generated, they are included in the sleep summary for reference.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, - {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "time", "type": "double", "doc": "Start time of the sleep in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, - {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, - {"name": "unmeasurableSleepInSeconds", "type": ["null", "int"], "doc": "Time in seconds that the sleep level of the user could not be measured. This may or may not correspond to off-wrist time.", "default": null}, - {"name": "deepSleepDurationInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent in deep sleep during the sleep period.", "default": null}, - {"name": "lightSleepDurationInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent in light sleep during the sleep period.", "default": null}, - {"name": "remSleepInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent in REM sleep during the sleep period.", "default": null}, - {"name": "awakeDurationInSeconds", "type": ["null", "int"], "doc": "Time in seconds the user spent awake during the sleep period.", "default": null}, + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "date", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect in the local time zone of the device. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "startTimeOffset", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "duration", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, + {"name": "unmeasurableSleepDuration", "type": ["null", "int"], "doc": "Time in seconds that the sleep level of the user could not be measured. This may or may not correspond to off-wrist time.", "default": null}, + {"name": "deepSleepDuration", "type": ["null", "int"], "doc": "Time in seconds the user spent in deep sleep during the sleep period.", "default": null}, + {"name": "lightSleepDuration", "type": ["null", "int"], "doc": "Time in seconds the user spent in light sleep during the sleep period.", "default": null}, + {"name": "remSleep", "type": ["null", "int"], "doc": "Time in seconds the user spent in REM sleep during the sleep period.", "default": null}, + {"name": "awakeDuration", "type": ["null", "int"], "doc": "Time in seconds the user spent awake during the sleep period.", "default": null}, {"name": "validation", "type": ["null", "string"], "doc": "String that relays the validation state of the sleep data and its date range. The data could be auto-confirmed, but the sleep window could have been manually adjusted, or the sleep data itself is entirely manually entered. Possible values: MANUAL: The user entered sleep start and stop times manually through a web form. There is no device data backing up the sleep assessment. DEVICE: The user used a device with the sleep feature to manually start and stop sleep. This type still requires manual user intervention to judge sleep start and stop. AUTO_TENTATIVE: The sleep start and stop times were auto-detected by Garmin Connect using accelerometer data. However, it is possible that further refinements to this sleep record will come later. This could be because the user is still asleep or could be because the user owns multiple devices and might sync another device later for this same time period. AUTO_FINAL: The sleep start and stop times were auto-detected by Garmin Connect, and enough data has been gathered to finalize the window. This status also indicates that the user only has one device so this record can never be updated again – users that own multiple devices will never get an AUTO_FINAL. AUTO_MANUAL: Sleep data was auto-detected by Garmin Connect, but the user is overriding the start and stop times or the user started with a manual entry and the sleep was auto-detected later. Garmin Connect stores both but will display the manual start and stop times in favor of the auto-detected times. ENHANCED_TENTATIVE: Sleep data was collected from a device capable of running an enhanced sleep analysis to detect REM sleep, but an updated sleep summary record may come later with further refinements or a greater sleep period. ENHANCED_FINAL: Sleep data was collected from a device capable of running an enhanced sleep analysis to detect REM sleep, and no further updates or refinements to this sleep analysis are expected.", "default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc b/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc index 5f2e68cd..1b6236ac 100644 --- a/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc +++ b/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc @@ -4,11 +4,11 @@ "type": "record", "doc": "Stress Details summaries contain the user’s stress level values for a given day. Stress levels are provided as 3-minute averages of the real-time stress scores generated on the device with values ranging from 1 to 100. A value of -1 means there was not enough data to detect stress, and -2 means there was too much motion (e.g. the user was walking or running). Scores between 1 and 25 are considered “rest” (i.e. not stressful), 26-50 as “low” stress, 51-75 “medium” stress, and 76- 100 as “high” stress. These numbers are derived based on a combination of many device sensors and will automatically adjust to the wearer of the device and gain accuracy over time as the stress algorithms learn the user’s natural biometric norms. Stress values from the Health API are exactly the stress values shown on Garmin Connect.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "startTimeOffsetInSeconds", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, - {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, - {"name": "durationInSeconds", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null} + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "startTimeOffset", "type": ["null", "int"], "doc": "Offset in seconds to add to time to derive the 'local' time of the device that captured the data.", "default": null}, + {"name": "date", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect in the local time zone of the device. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "duration", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_stress_level_sample.avsc b/commons/push/integration/garmin/garmin_push_stress_level_sample.avsc index 543288eb..70d0b4cc 100644 --- a/commons/push/integration/garmin/garmin_push_stress_level_sample.avsc +++ b/commons/push/integration/garmin/garmin_push_stress_level_sample.avsc @@ -4,9 +4,9 @@ "type": "record", "doc": "Stress levels are provided as 3-minute averages of the real-time stress scores generated on the device with values ranging from 1 to 100. A value of -1 means there was not enough data to detect stress, and -2 means there was too much motion (e.g. the user was walking or running). Scores between 1 and 25 are considered “rest” (i.e. not stressful), 26-50 as “low” stress, 51-75 “medium” stress, and 76- 100 as “high” stress. These numbers are derived based on a combination of many device sensors and will automatically adjust to the wearer of the device and gain accuracy over time as the stress algorithms learn the user’s natural biometric norms. Usually assocaited with Stress Details Summary using the summaryId. Stress values from the Health API are exactly the stress values shown on Garmin Connect.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, {"name": "time", "type": "double", "doc": "Start time of the sample in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, {"name": "timeReceived", "type": "double", "doc": "Time this sample was recieved by the push service in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, - {"name": "stressLevel", "type": ["null", "double"], "doc": "Stress level value recorded for the time..", "default": null} + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, + {"name": "stressLevel", "type": ["null", "float"], "doc": "Stress level value recorded for the time..", "default": null} ] } \ No newline at end of file diff --git a/commons/push/integration/garmin/garmin_push_user_metrics.avsc b/commons/push/integration/garmin/garmin_push_user_metrics.avsc index 2c96c0bc..1ba0026d 100644 --- a/commons/push/integration/garmin/garmin_push_user_metrics.avsc +++ b/commons/push/integration/garmin/garmin_push_user_metrics.avsc @@ -4,11 +4,11 @@ "type": "record", "doc": "User Metrics are per-user calculations performed by Garmin based on the underlying data uploaded from the user’s device. This data can be specific to a single device and field availability is dependent on device model support. Unlike other summaries, User Metrics are associated only with a calendar date, not a specific time frame, and only the most recent value for any fields is presented to the user. Each metric directly corresponds to the similarly named field found in Garmin Connect.", "fields": [ - {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, - {"name": "time", "type": "double", "doc": "Start time of the activity in seconds since January 1, 1970, 00:00:00 UTC (Unix timestamp)."}, + {"name": "time", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, {"name": "timeReceived", "type": "double", "doc": "Time that this record was collected by a service in seconds since the Unix Epoch (s)."}, - {"name": "calendarDate", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect. The date format is ‘yyyy-mm-dd’.", "default": null}, - {"name": "vo2Max", "type": ["null", "double"], "doc": "An estimate of the maximum volume of oxygen (in milliliters) the user can consume per minute per kilogram of body weight at maximum performance.", "default": null}, + {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary."}, + {"name": "date", "type": ["null", "string"], "doc": "The calendar date this summary would be displayed on in Garmin Connect in the local time zone of the device. The date format is ‘yyyy-mm-dd’.", "default": null}, + {"name": "vo2Max", "type": ["null", "float"], "doc": "An estimate of the maximum volume of oxygen (in milliliters) the user can consume per minute per kilogram of body weight at maximum performance.", "default": null}, {"name": "fitnessAge", "type": ["null", "int"], "doc": "An estimation of the ‘age’ of the user’s fitness level, calculated by comparing internal fitness metrics with the average readings of biometrically similar users by age. For instance, a fitness age of 48 indicates that the user’s physical fitness is similar to that of an average 48- year-old person of the same gender.", "default": null} ] } \ No newline at end of file From 23ee754c3c011d75b863bd12dc97a421e46a93da Mon Sep 17 00:00:00 2001 From: yatharthranjan Date: Mon, 2 Nov 2020 12:26:36 +0000 Subject: [PATCH 05/12] rename `org.radarcns.push.integration.garmin` -> `org.radarcns.push.garmin` --- .../{integration => }/garmin/garmin_push_activity_details.avsc | 0 .../garmin/garmin_push_activity_details_sample.avsc | 0 .../{integration => }/garmin/garmin_push_activity_summary.avsc | 0 .../{integration => }/garmin/garmin_push_body_battery_sample.avsc | 0 .../{integration => }/garmin/garmin_push_body_composition.avsc | 0 .../push/{integration => }/garmin/garmin_push_daily_summary.avsc | 0 .../push/{integration => }/garmin/garmin_push_epoch_summary.avsc | 0 .../{integration => }/garmin/garmin_push_heart_rate_sample.avsc | 0 .../{integration => }/garmin/garmin_push_move_iq_summary.avsc | 0 commons/push/{integration => }/garmin/garmin_push_pulse_ox.avsc | 0 .../push/{integration => }/garmin/garmin_push_respiration.avsc | 0 .../push/{integration => }/garmin/garmin_push_sleep_level.avsc | 0 .../push/{integration => }/garmin/garmin_push_sleep_summary.avsc | 0 .../garmin/garmin_push_stress_detail_summary.avsc | 0 .../{integration => }/garmin/garmin_push_stress_level_sample.avsc | 0 .../push/{integration => }/garmin/garmin_push_user_metrics.avsc | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename commons/push/{integration => }/garmin/garmin_push_activity_details.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_activity_details_sample.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_activity_summary.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_body_battery_sample.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_body_composition.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_daily_summary.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_epoch_summary.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_heart_rate_sample.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_move_iq_summary.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_pulse_ox.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_respiration.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_sleep_level.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_sleep_summary.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_stress_detail_summary.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_stress_level_sample.avsc (100%) rename commons/push/{integration => }/garmin/garmin_push_user_metrics.avsc (100%) diff --git a/commons/push/integration/garmin/garmin_push_activity_details.avsc b/commons/push/garmin/garmin_push_activity_details.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_activity_details.avsc rename to commons/push/garmin/garmin_push_activity_details.avsc diff --git a/commons/push/integration/garmin/garmin_push_activity_details_sample.avsc b/commons/push/garmin/garmin_push_activity_details_sample.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_activity_details_sample.avsc rename to commons/push/garmin/garmin_push_activity_details_sample.avsc diff --git a/commons/push/integration/garmin/garmin_push_activity_summary.avsc b/commons/push/garmin/garmin_push_activity_summary.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_activity_summary.avsc rename to commons/push/garmin/garmin_push_activity_summary.avsc diff --git a/commons/push/integration/garmin/garmin_push_body_battery_sample.avsc b/commons/push/garmin/garmin_push_body_battery_sample.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_body_battery_sample.avsc rename to commons/push/garmin/garmin_push_body_battery_sample.avsc diff --git a/commons/push/integration/garmin/garmin_push_body_composition.avsc b/commons/push/garmin/garmin_push_body_composition.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_body_composition.avsc rename to commons/push/garmin/garmin_push_body_composition.avsc diff --git a/commons/push/integration/garmin/garmin_push_daily_summary.avsc b/commons/push/garmin/garmin_push_daily_summary.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_daily_summary.avsc rename to commons/push/garmin/garmin_push_daily_summary.avsc diff --git a/commons/push/integration/garmin/garmin_push_epoch_summary.avsc b/commons/push/garmin/garmin_push_epoch_summary.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_epoch_summary.avsc rename to commons/push/garmin/garmin_push_epoch_summary.avsc diff --git a/commons/push/integration/garmin/garmin_push_heart_rate_sample.avsc b/commons/push/garmin/garmin_push_heart_rate_sample.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_heart_rate_sample.avsc rename to commons/push/garmin/garmin_push_heart_rate_sample.avsc diff --git a/commons/push/integration/garmin/garmin_push_move_iq_summary.avsc b/commons/push/garmin/garmin_push_move_iq_summary.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_move_iq_summary.avsc rename to commons/push/garmin/garmin_push_move_iq_summary.avsc diff --git a/commons/push/integration/garmin/garmin_push_pulse_ox.avsc b/commons/push/garmin/garmin_push_pulse_ox.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_pulse_ox.avsc rename to commons/push/garmin/garmin_push_pulse_ox.avsc diff --git a/commons/push/integration/garmin/garmin_push_respiration.avsc b/commons/push/garmin/garmin_push_respiration.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_respiration.avsc rename to commons/push/garmin/garmin_push_respiration.avsc diff --git a/commons/push/integration/garmin/garmin_push_sleep_level.avsc b/commons/push/garmin/garmin_push_sleep_level.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_sleep_level.avsc rename to commons/push/garmin/garmin_push_sleep_level.avsc diff --git a/commons/push/integration/garmin/garmin_push_sleep_summary.avsc b/commons/push/garmin/garmin_push_sleep_summary.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_sleep_summary.avsc rename to commons/push/garmin/garmin_push_sleep_summary.avsc diff --git a/commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc b/commons/push/garmin/garmin_push_stress_detail_summary.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_stress_detail_summary.avsc rename to commons/push/garmin/garmin_push_stress_detail_summary.avsc diff --git a/commons/push/integration/garmin/garmin_push_stress_level_sample.avsc b/commons/push/garmin/garmin_push_stress_level_sample.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_stress_level_sample.avsc rename to commons/push/garmin/garmin_push_stress_level_sample.avsc diff --git a/commons/push/integration/garmin/garmin_push_user_metrics.avsc b/commons/push/garmin/garmin_push_user_metrics.avsc similarity index 100% rename from commons/push/integration/garmin/garmin_push_user_metrics.avsc rename to commons/push/garmin/garmin_push_user_metrics.avsc From c67409a2aa23f78dd2970cc5f8d7dfae40c56c6d Mon Sep 17 00:00:00 2001 From: yatharthranjan Date: Mon, 2 Nov 2020 12:43:14 +0000 Subject: [PATCH 06/12] update namespace --- commons/push/garmin/garmin_push_activity_details.avsc | 2 +- commons/push/garmin/garmin_push_activity_details_sample.avsc | 2 +- commons/push/garmin/garmin_push_activity_summary.avsc | 2 +- commons/push/garmin/garmin_push_body_battery_sample.avsc | 2 +- commons/push/garmin/garmin_push_body_composition.avsc | 2 +- commons/push/garmin/garmin_push_daily_summary.avsc | 2 +- commons/push/garmin/garmin_push_epoch_summary.avsc | 2 +- commons/push/garmin/garmin_push_heart_rate_sample.avsc | 2 +- commons/push/garmin/garmin_push_move_iq_summary.avsc | 2 +- commons/push/garmin/garmin_push_pulse_ox.avsc | 2 +- commons/push/garmin/garmin_push_respiration.avsc | 2 +- commons/push/garmin/garmin_push_sleep_level.avsc | 2 +- commons/push/garmin/garmin_push_sleep_summary.avsc | 2 +- commons/push/garmin/garmin_push_stress_detail_summary.avsc | 2 +- commons/push/garmin/garmin_push_stress_level_sample.avsc | 2 +- commons/push/garmin/garmin_push_user_metrics.avsc | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/commons/push/garmin/garmin_push_activity_details.avsc b/commons/push/garmin/garmin_push_activity_details.avsc index 63a3ade4..c7c2c1ec 100644 --- a/commons/push/garmin/garmin_push_activity_details.avsc +++ b/commons/push/garmin/garmin_push_activity_details.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminActivityDetails", "type": "record", "doc": "Fitness activity details summaries represent detailed information about discrete fitness activities, such as running or swimming, that are specifically and intentionally started by the user on their device. All wellness data, like steps and distance, contained in the activity are already represented in the Daily summary and in the corresponding Epoch summaries, so Activity Detail summaries should only be used for programs that wish to treat specific activity types in different ways, such as giving the user extra credit for going swimming three times in the same week. Activity details summaries include all data recorded by the device as part of the Fitness Activity, including GPS coordinates and all recorded sensor data. ", diff --git a/commons/push/garmin/garmin_push_activity_details_sample.avsc b/commons/push/garmin/garmin_push_activity_details_sample.avsc index 97d479de..93cb357d 100644 --- a/commons/push/garmin/garmin_push_activity_details_sample.avsc +++ b/commons/push/garmin/garmin_push_activity_details_sample.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminActivityDetailsSample", "type": "record", "doc": "Each activity detail contains an activity summary and an optional list of samples. The samples list will be empty if the activity is manual or details are not supported by the device. Samples may be as frequent as once per second, and values should be considered valid until the next sample. In all cases, movingDurationInSeconds is less than or equal to timerDurationInSeconds is less than or equal to clockDurationInSeconds.", diff --git a/commons/push/garmin/garmin_push_activity_summary.avsc b/commons/push/garmin/garmin_push_activity_summary.avsc index 5fec7d2f..b058fa5d 100644 --- a/commons/push/garmin/garmin_push_activity_summary.avsc +++ b/commons/push/garmin/garmin_push_activity_summary.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminActivitySummary", "type": "record", "doc": "Fitness activity summaries represent high-level information from discrete fitness activities, such as running or swimming, that are specifically and intentionally started by the user on their device. All wellness data, like steps and distance, contained in the Activity are already represented in the Daily summary and in the corresponding Epoch summaries, so Activity summaries should only be used for programs that wish to treat specific activity types in different ways, such as giving the user extra credit for going swimming three times in the same week.", diff --git a/commons/push/garmin/garmin_push_body_battery_sample.avsc b/commons/push/garmin/garmin_push_body_battery_sample.avsc index 0cb5287c..a86eaee8 100644 --- a/commons/push/garmin/garmin_push_body_battery_sample.avsc +++ b/commons/push/garmin/garmin_push_body_battery_sample.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminBodyBatterySample", "type": "record", "doc": "Body battery value recorded for the time. Usually assocaited with Stress Details Summary using summaryId. Information on and a list of devices that support Body Battery are available here: https://support.garmin.com/ms-MY/?faq=2qczgfbN00AIMJbX33dRq9.", diff --git a/commons/push/garmin/garmin_push_body_composition.avsc b/commons/push/garmin/garmin_push_body_composition.avsc index e1840fd2..20d6845b 100644 --- a/commons/push/garmin/garmin_push_body_composition.avsc +++ b/commons/push/garmin/garmin_push_body_composition.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminBodyComposition", "type": "record", "doc": "Body Composition summaries contain information about the user’s biometric data, like weight or body mass index. This data can be generated three ways. Users can manually enter their weight on Garmin Connect. This results in a summary with only time and weight. Users may also connect their MyFitnessPal account to their Garmin Connect account and update their weight on MyFitnessPal. This results in a summary that also just has a time and weight. Finally, a user might have a Garmin Index body composition scale and sync data from this device. This will generate a summary with all possible biometric fields.", diff --git a/commons/push/garmin/garmin_push_daily_summary.avsc b/commons/push/garmin/garmin_push_daily_summary.avsc index 70f98d3c..0d16e5b7 100644 --- a/commons/push/garmin/garmin_push_daily_summary.avsc +++ b/commons/push/garmin/garmin_push_daily_summary.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminDailySummary", "type": "record", "doc": "Daily summaries offer a high-level view of the user’s entire day. They generally correspond to the data found on the “My Day” section of Garmin Connect. Daily summaries are the most commonly used and are often the foundation of a Health API integration.", diff --git a/commons/push/garmin/garmin_push_epoch_summary.avsc b/commons/push/garmin/garmin_push_epoch_summary.avsc index 3d5e8c6e..d5bf0371 100644 --- a/commons/push/garmin/garmin_push_epoch_summary.avsc +++ b/commons/push/garmin/garmin_push_epoch_summary.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminEpochSummary", "type": "record", "doc": "The Epoch Summary contains wellness data for a specific time range. Epoch summary records contain much of the same data available in Daily summaries, but with 15-minute time-slice granularity. There is one record for each activity type monitored within an individual epoch. For example, if the user was sedentary for five minutes, walked for five minutes, and then ran for five minutes over the course of 15 minutes, three activity records would be generated for that single 15-minute epoch. The duration value would be 900 seconds for all three records, but the active time for each would be 300 seconds. A duration of less than 900 seconds indicates that the user synced data during the middle of an epoch. On the user’s next sync, that epoch record will be replaced with a 900-second-duration epoch covering the entire span. As such and to accommodate users with multiple devices, it is important that new epochs always replace existing epochs that have the same startTimeInSeconds. The most recent update from the Health API will always reflect the most recent data in Garmin Connect. Epoch data is useful when attempting to construct charts showing intraday wellness data. An example of this in Garmin Connect is the Steps Details chart that graphs step count changes throughout the user’s day.", diff --git a/commons/push/garmin/garmin_push_heart_rate_sample.avsc b/commons/push/garmin/garmin_push_heart_rate_sample.avsc index 717ea3bd..c6965e71 100644 --- a/commons/push/garmin/garmin_push_heart_rate_sample.avsc +++ b/commons/push/garmin/garmin_push_heart_rate_sample.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminHeartRateSample", "type": "record", "doc": "Mapping between time (in seconds) to a heart rate value recorded for the time, in beats per minute. Each entry is a representative sample of the previous 15 seconds from the given time. Lack of entry for a given time should be interpreted as no data available. These are accompanied with the Dailies data and can be associated using the summaryId.", diff --git a/commons/push/garmin/garmin_push_move_iq_summary.avsc b/commons/push/garmin/garmin_push_move_iq_summary.avsc index 4a3648fa..c5a0571f 100644 --- a/commons/push/garmin/garmin_push_move_iq_summary.avsc +++ b/commons/push/garmin/garmin_push_move_iq_summary.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminMoveIQSummary", "type": "record", "doc": "Move IQ Event summaries are a feed of activities which have been automatically detected by the device based on movement patterns, like running or biking. These are not activities initiated by the user. Please note that wellness data, like steps and distance, from Move IQ events are already included in the Daily and Epoch summaries. Due to their automatically-detected nature, Move IQ events are not considered a fitness activity, do not contain the same details as activities, and cannot be edited by the user with Garmin Connect. These events should be considered a labeled-timespan on top of normal Daily or Epoch summary details, matching their representation within Garmin Connect. For more feature-level information on Move IQ events, please see: https://support.garmin.com/faqSearch/en- US/faq/content/zgFpy8MShkArqAxCug5wC6 . Move IQ activities are also known as Automatic Activity Detection in older devices or documentation.", diff --git a/commons/push/garmin/garmin_push_pulse_ox.avsc b/commons/push/garmin/garmin_push_pulse_ox.avsc index 4ae3a1cf..19ffdaff 100644 --- a/commons/push/garmin/garmin_push_pulse_ox.avsc +++ b/commons/push/garmin/garmin_push_pulse_ox.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminPulseOx", "type": "record", "doc": "Pulse Ox summaries contain blood oxygen saturation data. Two types of data are represented in Pulse Ox summaries based on the capabilities of the user’s device. If the onDemand field is not present or set to false, the spo2Values contains an SpO2 measurement that is an average of all measurements taken as part of the Acclimation feature (https://www8.garmin.com/manuals/webhelp/fenix5plus/EN-US/GUID-4D425925-D4EE-4C26-B974- 5375D0670860.html). If the onDemand field is true the spo2Values instead contains one or more exact measurements taken by a device that is capable of on-demand measurements but not the Acclimation feature, such as the Vivosmart 4. There maybe multiple records of spo2Value for the same summaryId. These may also be associated with Sleep summaries using summaryId. Backfill is supported for Pulse Ox summaries, but only for Acclimation data.", diff --git a/commons/push/garmin/garmin_push_respiration.avsc b/commons/push/garmin/garmin_push_respiration.avsc index ce5ed153..43b0842e 100644 --- a/commons/push/garmin/garmin_push_respiration.avsc +++ b/commons/push/garmin/garmin_push_respiration.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminRespiration", "type": "record", "doc": "Respiration is a feature (https://www8.garmin.com/manuals/webhelp/vivoactive4_4S/EN-US/GUID-252F74B6-C24B-495B-8E73-4BD595CA7FE3.html) available on some Garmin devices that tracks breathing rate throughout the day, during sleep, and during activities such as breathwork and yoga. There maybe multiple records of respiration values for the same summaryId. These may also be associated with Sleep summaries using summaryId.", diff --git a/commons/push/garmin/garmin_push_sleep_level.avsc b/commons/push/garmin/garmin_push_sleep_level.avsc index 8a8f5b27..90b2f129 100644 --- a/commons/push/garmin/garmin_push_sleep_level.avsc +++ b/commons/push/garmin/garmin_push_sleep_level.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminSleepLevel", "type": "record", "doc": "Sleep level time ranges, currently deep, light, rem and awake. Time ranges are represented as unix timestamps in seconds. Usually associated with Sleep Summary data using the summaryId field.", diff --git a/commons/push/garmin/garmin_push_sleep_summary.avsc b/commons/push/garmin/garmin_push_sleep_summary.avsc index b1391ab2..e6bf4d8a 100644 --- a/commons/push/garmin/garmin_push_sleep_summary.avsc +++ b/commons/push/garmin/garmin_push_sleep_summary.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminSleepSummary", "type": "record", "doc": "Sleep summaries are data records representing how long the user slept and the automatically classified sleep levels during that sleep event (e.g. light, deep periods) based on data generated by the user’s device. Users may generate sleep data three different ways. Some older Garmin devices (e.g. first generation vívofit) allow users to manually place the device in sleep mode. Newer devices do not have this option and instead auto-detect sleep if it occurs between the user’s Bed/Wake time range configured in Garmin Connect. Users may also self-report sleep information using Garmin Connect. Sleep records from the Health API are labelled to identify how the sleep data was generated (see below). This allows partners to accept/reject various methods of collecting Sleep data. Recommended usage for this field is to filter out validation types that are not desired rather than accept only certain validation types in order to prevent lost data in the future if new validation types are added, as by default Garmin Connect displays records of all possible types. Unlike Daily summaries which are associated with a given day on a midnight-to-midnight basis, Sleep summaries are associated with a user’s overnight sleep range. Most will start on one calendar day and end on the next calendar day, but it is possible for two different Sleep summaries to begin on the same day if, for example, the user goes to bed after midnight, wakes up, and then goes to bed prior to midnight the next evening. The sleep summary will include REM sleep if the user’s device is capable of REM sleep analysis. Users without REM-capable devices, or with REM-capable devices that have not been updated to REM-capable firmware, are limited to only deep, light, and awake sleep levels. Additionally, REM sleep will only be generated if the REM-capable devices is set as the preferred activity tracker and is actually worn during sleep. Some pulse-oximetry-enabled devices will generate SpO2 values during sleep for use in sleep analysis. If such values are generated, they are included in the sleep summary for reference.", diff --git a/commons/push/garmin/garmin_push_stress_detail_summary.avsc b/commons/push/garmin/garmin_push_stress_detail_summary.avsc index 1b6236ac..a3f44a85 100644 --- a/commons/push/garmin/garmin_push_stress_detail_summary.avsc +++ b/commons/push/garmin/garmin_push_stress_detail_summary.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminStressDetailSummary", "type": "record", "doc": "Stress Details summaries contain the user’s stress level values for a given day. Stress levels are provided as 3-minute averages of the real-time stress scores generated on the device with values ranging from 1 to 100. A value of -1 means there was not enough data to detect stress, and -2 means there was too much motion (e.g. the user was walking or running). Scores between 1 and 25 are considered “rest” (i.e. not stressful), 26-50 as “low” stress, 51-75 “medium” stress, and 76- 100 as “high” stress. These numbers are derived based on a combination of many device sensors and will automatically adjust to the wearer of the device and gain accuracy over time as the stress algorithms learn the user’s natural biometric norms. Stress values from the Health API are exactly the stress values shown on Garmin Connect.", diff --git a/commons/push/garmin/garmin_push_stress_level_sample.avsc b/commons/push/garmin/garmin_push_stress_level_sample.avsc index 70d0b4cc..34331437 100644 --- a/commons/push/garmin/garmin_push_stress_level_sample.avsc +++ b/commons/push/garmin/garmin_push_stress_level_sample.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminStressLevelSample", "type": "record", "doc": "Stress levels are provided as 3-minute averages of the real-time stress scores generated on the device with values ranging from 1 to 100. A value of -1 means there was not enough data to detect stress, and -2 means there was too much motion (e.g. the user was walking or running). Scores between 1 and 25 are considered “rest” (i.e. not stressful), 26-50 as “low” stress, 51-75 “medium” stress, and 76- 100 as “high” stress. These numbers are derived based on a combination of many device sensors and will automatically adjust to the wearer of the device and gain accuracy over time as the stress algorithms learn the user’s natural biometric norms. Usually assocaited with Stress Details Summary using the summaryId. Stress values from the Health API are exactly the stress values shown on Garmin Connect.", diff --git a/commons/push/garmin/garmin_push_user_metrics.avsc b/commons/push/garmin/garmin_push_user_metrics.avsc index 1ba0026d..516c9566 100644 --- a/commons/push/garmin/garmin_push_user_metrics.avsc +++ b/commons/push/garmin/garmin_push_user_metrics.avsc @@ -1,5 +1,5 @@ { - "namespace": "org.radarcns.push.integration.garmin", + "namespace": "org.radarcns.push.garmin", "name": "GarminUserMetrics", "type": "record", "doc": "User Metrics are per-user calculations performed by Garmin based on the underlying data uploaded from the user’s device. This data can be specific to a single device and field availability is dependent on device model support. Unlike other summaries, User Metrics are associated only with a calendar date, not a specific time frame, and only the most recent value for any fields is presented to the user. Each metric directly corresponds to the similarly named field found in Garmin Connect.", From 1c6dea818a465444a7b577ed61c2f60b289f361e Mon Sep 17 00:00:00 2001 From: yatharthranjan Date: Mon, 2 Nov 2020 13:16:10 +0000 Subject: [PATCH 07/12] Minor updates --- commons/push/garmin/garmin_push_activity_details_sample.avsc | 2 +- commons/push/garmin/garmin_push_activity_summary.avsc | 2 +- commons/push/garmin/garmin_push_sleep_summary.avsc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/commons/push/garmin/garmin_push_activity_details_sample.avsc b/commons/push/garmin/garmin_push_activity_details_sample.avsc index 93cb357d..ca04cf8d 100644 --- a/commons/push/garmin/garmin_push_activity_details_sample.avsc +++ b/commons/push/garmin/garmin_push_activity_details_sample.avsc @@ -9,7 +9,7 @@ {"name": "summaryId", "type": "string", "doc": "Unique identifier for the summary that this sample is associated with."}, {"name": "airTemperature", "type": ["null", "float"], "doc": "Air Temperature in Celcius.", "default": null}, {"name": "heartRate", "type": ["null", "int"], "doc": "Heart rate in beats per minute.", "default": null}, - {"name": "speed", "type": ["null", "double"], "doc": "Speed in Meters Per Second.", "default": null}, + {"name": "speed", "type": ["null", "float"], "doc": "Speed in Meters Per Second.", "default": null}, {"name": "stepsPerMinute", "type": ["null", "float"], "doc": "Number of steps per minute.", "default": null}, {"name": "totalDistance", "type": ["null", "float"], "doc": "Total Distance in Meters.", "default": null}, {"name": "timerDuration", "type": ["null", "int"], "doc": "The amount of 'timer time' in an activity.", "default": null}, diff --git a/commons/push/garmin/garmin_push_activity_summary.avsc b/commons/push/garmin/garmin_push_activity_summary.avsc index b058fa5d..3c9b781b 100644 --- a/commons/push/garmin/garmin_push_activity_summary.avsc +++ b/commons/push/garmin/garmin_push_activity_summary.avsc @@ -11,7 +11,7 @@ {"name": "activityType", "type": ["null", "string"], "doc": "Text description of the activity type. e.g - SEDENTARY, SLEEP, RUNNING, CYCLING, WALKING, etc.", "default": null}, {"name": "duration", "type": ["null", "int"], "doc": "Length of the monitoring period in seconds. 86400 once a full day is complete, but less if a user syncs mid-day.", "default": null}, {"name": "averageBikeCadence", "type": ["null", "float"], "doc": "Average Bike Cadence in rounds per minute.", "default": null}, - {"name": "maxBikeCadenceInRounds", "type": ["null", "float"], "doc": "Maximum Bike Cadence in rounds per minute.", "default": null}, + {"name": "maxBikeCadence", "type": ["null", "float"], "doc": "Maximum Bike Cadence in rounds per minute.", "default": null}, {"name": "distance", "type": ["null", "float"], "doc": "Distance traveled in meters.", "default": null}, {"name": "averageRunCadence", "type": ["null", "float"], "doc": "Average Run Cadence in Steps per minute.", "default": null}, {"name": "maxRunCadence", "type": ["null", "float"], "doc": "Maximum Run Cadence in Steps per minute.", "default": null}, diff --git a/commons/push/garmin/garmin_push_sleep_summary.avsc b/commons/push/garmin/garmin_push_sleep_summary.avsc index e6bf4d8a..2bd79279 100644 --- a/commons/push/garmin/garmin_push_sleep_summary.avsc +++ b/commons/push/garmin/garmin_push_sleep_summary.avsc @@ -13,7 +13,7 @@ {"name": "unmeasurableSleepDuration", "type": ["null", "int"], "doc": "Time in seconds that the sleep level of the user could not be measured. This may or may not correspond to off-wrist time.", "default": null}, {"name": "deepSleepDuration", "type": ["null", "int"], "doc": "Time in seconds the user spent in deep sleep during the sleep period.", "default": null}, {"name": "lightSleepDuration", "type": ["null", "int"], "doc": "Time in seconds the user spent in light sleep during the sleep period.", "default": null}, - {"name": "remSleep", "type": ["null", "int"], "doc": "Time in seconds the user spent in REM sleep during the sleep period.", "default": null}, + {"name": "remSleepDuration", "type": ["null", "int"], "doc": "Time in seconds the user spent in REM sleep during the sleep period.", "default": null}, {"name": "awakeDuration", "type": ["null", "int"], "doc": "Time in seconds the user spent awake during the sleep period.", "default": null}, {"name": "validation", "type": ["null", "string"], "doc": "String that relays the validation state of the sleep data and its date range. The data could be auto-confirmed, but the sleep window could have been manually adjusted, or the sleep data itself is entirely manually entered. Possible values: MANUAL: The user entered sleep start and stop times manually through a web form. There is no device data backing up the sleep assessment. DEVICE: The user used a device with the sleep feature to manually start and stop sleep. This type still requires manual user intervention to judge sleep start and stop. AUTO_TENTATIVE: The sleep start and stop times were auto-detected by Garmin Connect using accelerometer data. However, it is possible that further refinements to this sleep record will come later. This could be because the user is still asleep or could be because the user owns multiple devices and might sync another device later for this same time period. AUTO_FINAL: The sleep start and stop times were auto-detected by Garmin Connect, and enough data has been gathered to finalize the window. This status also indicates that the user only has one device so this record can never be updated again – users that own multiple devices will never get an AUTO_FINAL. AUTO_MANUAL: Sleep data was auto-detected by Garmin Connect, but the user is overriding the start and stop times or the user started with a manual entry and the sleep was auto-detected later. Garmin Connect stores both but will display the manual start and stop times in favor of the auto-detected times. ENHANCED_TENTATIVE: Sleep data was collected from a device capable of running an enhanced sleep analysis to detect REM sleep, but an updated sleep summary record may come later with further refinements or a greater sleep period. ENHANCED_FINAL: Sleep data was collected from a device capable of running an enhanced sleep analysis to detect REM sleep, and no further updates or refinements to this sleep analysis are expected.", "default": null} ] From 11208b74d292087d7f7f8326f6ba30c530907240 Mon Sep 17 00:00:00 2001 From: mpgxvii Date: Fri, 6 Nov 2020 14:43:39 +0000 Subject: [PATCH 08/12] Update Altoida summary metrics schema --- commons/connector/upload/altoida/altoida_summary_metrics.avsc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commons/connector/upload/altoida/altoida_summary_metrics.avsc b/commons/connector/upload/altoida/altoida_summary_metrics.avsc index 3ac41c1b..59a2d24f 100644 --- a/commons/connector/upload/altoida/altoida_summary_metrics.avsc +++ b/commons/connector/upload/altoida/altoida_summary_metrics.avsc @@ -8,7 +8,7 @@ {"name": "timeReceived", "type": "double", "doc": "Timestamp in unix time received from Altoida API."}, {"name": "audioHighReactionTimes", "type": "float", "doc": "Distribution of reaction times to high tone(s)."}, {"name": "audioHighAccuracy", "type": "float", "doc": "Distribution of deviation from speaker button center (cm)."}, - {"name": "audioLowReactions", "type": "int", "doc": "Distributions of number of reactions to low tones."}, + {"name": "audioLowReactions", "type": ["null","int"], "doc": "Distributions of number of reactions to low tones."}, {"name": "audioIgnoredHighTonePercentage", "type": "float", "doc": "Distribution of ratio of high tones ignored."}, {"name": "audioPrematureToneButtonPresses", "type": "int", "doc": "Distribution of number of premature tone button presses."}, {"name": "randomScreenPressesDuringPlacement", "type": "int", "doc": "Distribution of number of random screen presses during the placement phase."}, From 0cb1215d5092feb57d690135e5f5fff53c2b7e0a Mon Sep 17 00:00:00 2001 From: mpgxvii Date: Fri, 6 Nov 2020 14:45:17 +0000 Subject: [PATCH 09/12] Update Altoida summary metrics schema --- commons/connector/upload/altoida/altoida_summary_metrics.avsc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commons/connector/upload/altoida/altoida_summary_metrics.avsc b/commons/connector/upload/altoida/altoida_summary_metrics.avsc index 59a2d24f..aff1fa82 100644 --- a/commons/connector/upload/altoida/altoida_summary_metrics.avsc +++ b/commons/connector/upload/altoida/altoida_summary_metrics.avsc @@ -8,7 +8,7 @@ {"name": "timeReceived", "type": "double", "doc": "Timestamp in unix time received from Altoida API."}, {"name": "audioHighReactionTimes", "type": "float", "doc": "Distribution of reaction times to high tone(s)."}, {"name": "audioHighAccuracy", "type": "float", "doc": "Distribution of deviation from speaker button center (cm)."}, - {"name": "audioLowReactions", "type": ["null","int"], "doc": "Distributions of number of reactions to low tones."}, + {"name": "audioLowReactions", "type": ["null", "int"], "doc": "Distributions of number of reactions to low tones."}, {"name": "audioIgnoredHighTonePercentage", "type": "float", "doc": "Distribution of ratio of high tones ignored."}, {"name": "audioPrematureToneButtonPresses", "type": "int", "doc": "Distribution of number of premature tone button presses."}, {"name": "randomScreenPressesDuringPlacement", "type": "int", "doc": "Distribution of number of random screen presses during the placement phase."}, From 77cae09f134868347b676afd2cd800c4e9fd04f8 Mon Sep 17 00:00:00 2001 From: mpgxvii Date: Fri, 6 Nov 2020 15:03:37 +0000 Subject: [PATCH 10/12] Update Altoida summary schema --- commons/connector/upload/altoida/altoida_summary.avsc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/commons/connector/upload/altoida/altoida_summary.avsc b/commons/connector/upload/altoida/altoida_summary.avsc index ee3911d7..a1812d1b 100644 --- a/commons/connector/upload/altoida/altoida_summary.avsc +++ b/commons/connector/upload/altoida/altoida_summary.avsc @@ -19,11 +19,6 @@ "type": "enum", "doc": "Classifications provided by Altoida.", "symbols": ["HEALTHY", "AT_RISK", "MCI_DUE_TO_AD"]}], "doc": "Classification based on the analysis 0=healthy, 1=at risk, 2=MCI due to AD.", "default": null}, - {"name": "nmi", "type": "double", "doc": "NMI value of the test,a value in 0-100, where 0-33.3 is class 2, 33.3-66.6 is class 1, 66.6-100 is class 0."}, - {"name": "groundTruth", "type": { - "name": "GroundTruth", - "type": "enum", - "doc": "GroundTruth supported by Altoida.", - "symbols": ["UNKNOWN", "HEALTHY", "AT_RISK", "MCI_OR_AB_PLUS", "MCI_OR_AB_MINUS"]}, "doc": "If the test is based on additional biomarkers -1=unknown, 0=healthy, 1= at risk, 2=MCI/AB+, 3=MCI/AB-.", "default": "UNKNOWN"} + {"name": "nmi", "type": "double", "doc": "NMI value of the test,a value in 0-100, where 0-33.3 is class 2, 33.3-66.6 is class 1, 66.6-100 is class 0."} ] } From c28d7911cd02ab5781b19465c3ad43790775315a Mon Sep 17 00:00:00 2001 From: mpgxvii Date: Fri, 6 Nov 2020 15:20:48 +0000 Subject: [PATCH 11/12] Fix Altoida metrics schema nullable type --- commons/connector/upload/altoida/altoida_summary_metrics.avsc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commons/connector/upload/altoida/altoida_summary_metrics.avsc b/commons/connector/upload/altoida/altoida_summary_metrics.avsc index aff1fa82..76c786df 100644 --- a/commons/connector/upload/altoida/altoida_summary_metrics.avsc +++ b/commons/connector/upload/altoida/altoida_summary_metrics.avsc @@ -8,7 +8,7 @@ {"name": "timeReceived", "type": "double", "doc": "Timestamp in unix time received from Altoida API."}, {"name": "audioHighReactionTimes", "type": "float", "doc": "Distribution of reaction times to high tone(s)."}, {"name": "audioHighAccuracy", "type": "float", "doc": "Distribution of deviation from speaker button center (cm)."}, - {"name": "audioLowReactions", "type": ["null", "int"], "doc": "Distributions of number of reactions to low tones."}, + {"name": "audioLowReactions", "type": ["null", "int"], "doc": "Distributions of number of reactions to low tones.", "default": null}, {"name": "audioIgnoredHighTonePercentage", "type": "float", "doc": "Distribution of ratio of high tones ignored."}, {"name": "audioPrematureToneButtonPresses", "type": "int", "doc": "Distribution of number of premature tone button presses."}, {"name": "randomScreenPressesDuringPlacement", "type": "int", "doc": "Distribution of number of random screen presses during the placement phase."}, From 6c352793009c1416c3f14f22230ed077f03716aa Mon Sep 17 00:00:00 2001 From: Pauline Conde Date: Mon, 9 Nov 2020 12:45:11 +0000 Subject: [PATCH 12/12] Bump version --- java-sdk/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-sdk/build.gradle b/java-sdk/build.gradle index c3f9e16a..844b7992 100644 --- a/java-sdk/build.gradle +++ b/java-sdk/build.gradle @@ -17,7 +17,7 @@ subprojects { apply plugin: 'idea' // Configuration - version = '0.5.15-SNAPSHOT' + version = '0.5.15' group = 'org.radarcns' ext.githubRepoName = 'RADAR-base/RADAR-Schemas'